| /* |
| * Copyright 2020, Data61, CSIRO (ABN 41 687 119 230) |
| * |
| * SPDX-License-Identifier: BSD-2-Clause |
| */ |
| |
| #pragma once |
| |
| #include <stdio.h> |
| #include <stdint.h> |
| #include <stddef.h> |
| #include <utils/arith.h> |
| |
| /* A streaming base64 encoder */ |
| |
| typedef struct { |
| FILE *output; |
| uint16_t buffer; |
| size_t bits; |
| } base64_t; |
| |
| #define BASE64_LOOKUP (\ |
| "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \ |
| "abcdefghijklmnopqrstuvwxyz" \ |
| "0123456789+/" \ |
| ) |
| |
| /* Create a new base64 streamer that streams to the given output */ |
| static inline base64_t base64_new(FILE *output) |
| { |
| return (base64_t) { |
| .output = output, |
| .buffer = 0, |
| .bits = 0, |
| }; |
| } |
| |
| /* Lookup the character for a given bit pattern */ |
| static inline uint8_t base64_lookup(uint8_t bit) |
| { |
| return BASE64_LOOKUP[bit & MASK(6)]; |
| } |
| |
| /* Write a byte to a base64 stream */ |
| static inline int base64_putbyte(base64_t *streamer, uint8_t byte) |
| { |
| /* Buffer the byte */ |
| streamer->buffer <<= 8; |
| streamer->buffer |= byte; |
| streamer->bits += 8; |
| |
| /* Write any bits to the output */ |
| while (streamer->bits >= 6) { |
| streamer->bits -= 6; |
| uint8_t part = streamer->buffer >> streamer->bits; |
| fputc(base64_lookup(part), streamer->output); |
| } |
| |
| return 0; |
| } |
| |
| /* Write any remaining data to the output */ |
| static inline int base64_terminate(base64_t *streamer) |
| { |
| if (streamer->bits > 0) { |
| size_t padding = 6 - streamer->bits; |
| streamer->buffer <<= padding; |
| fputc(base64_lookup(streamer->buffer), streamer->output); |
| while (padding > 0) { |
| fputc('=', streamer->output); |
| padding -= 2; |
| } |
| } |
| |
| /* Reset the streamer */ |
| streamer->bits = 0; |
| |
| return 0; |
| } |