Skip to content

Commit

Permalink
Add b64 libs
Browse files Browse the repository at this point in the history
  • Loading branch information
xperiments committed Jun 11, 2024
1 parent 6b206ba commit 16cc08d
Show file tree
Hide file tree
Showing 2 changed files with 204 additions and 0 deletions.
59 changes: 59 additions & 0 deletions src/xtouch/b64/arduino_base64.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#pragma once

#include "stdint.h"
#include "string.h"

/**
* Convert between binary and base64 encoded string.
* @see https://github.com/dojyorin/arduino_base64
*/
namespace base64
{
/**
* Convert binary to base64 encoded string.
* If input is string, cast to `uint8_t*`.
* @example
* ```c++
* const uint8_t input[] = {0x17, 0x77, 0x3B, 0x11, 0x82, 0xA4, 0xC4, 0xC8};
* auto inputLength = sizeof(input);
* char output[base64::encodeLength(inputLength)];
* base64::encode(input, inputLength, output);
* ```
*/
void encode(const uint8_t *input, size_t inputLength, char *output);

/**
* Calculate number of output characters.
* @example
* ```c++
* const uint8_t input[] = {0x17, 0x77, 0x3B, 0x11, 0x82, 0xA4, 0xC4, 0xC8};
* auto inputLength = sizeof(input);
* char output[base64::encodeLength(inputLength)];
* base64::encode(input, inputLength, output);
* ```
*/
size_t encodeLength(size_t inputLength);

/**
* Convert base64 encoded string to binary.
* If output is string, cast to `char*`.
* @example
* ```c++
* const char input[] = "F3c7EYKkxMgnvO0nB8FWVw==";
* uint8_t output[base64::decodeLength(input)];
* base64::decode(input, output);
* ```
*/
void decode(const char *input, uint8_t *output);

/**
* Calculate number of output bytes.
* @example
* ```c++
* const char input[] = "F3c7EYKkxMgnvO0nB8FWVw==";
* uint8_t output[base64::decodeLength(input)];
* base64::decode(input, output);
* ```
*/
size_t decodeLength(const char *input);
}
145 changes: 145 additions & 0 deletions src/xtouch/b64/base64.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
#include "./arduino_base64.hpp"

namespace
{
constexpr char CODE[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

uint8_t indexOf(char search)
{
for (uint8_t i = 0; i < 64; i++)
{
if (::CODE[i] == search)
{
return i;
}
}

return 0xFF;
}

void to6x4(uint8_t *input, uint8_t *output)
{
output[0] = (input[0] & 0xFC) >> 2;
output[1] = ((input[0] & 0x03) << 4) + ((input[1] & 0xF0) >> 4);
output[2] = ((input[1] & 0x0F) << 2) + ((input[2] & 0xC0) >> 6);
output[3] = input[2] & 0x3F;
}

void to8x3(uint8_t *input, uint8_t *output)
{
output[0] = (input[0] << 2) + ((input[1] & 0x30) >> 4);
output[1] = ((input[1] & 0x0F) << 4) + ((input[2] & 0x3C) >> 2);
output[2] = ((input[2] & 0x03) << 6) + input[3];
}
}

void base64::encode(const uint8_t *input, size_t inputLength, char *output)
{
uint8_t position = 0;
uint8_t bit8x3[3] = {};
uint8_t bit6x4[4] = {};

while (inputLength--)
{
bit8x3[position++] = *input++;

if (position == 3)
{
::to6x4(bit8x3, bit6x4);

for (const auto &v : bit6x4)
{
*output++ = ::CODE[v];
}

position = 0;
}
}

if (position)
{
for (uint8_t i = position; i < 3; i++)
{
bit8x3[i] = 0x00;
}

::to6x4(bit8x3, bit6x4);

for (uint8_t i = 0; i < position + 1; i++)
{
*output++ = ::CODE[bit6x4[i]];
}

while (position++ < 3)
{
*output++ = '=';
}
}

*output = '\0';
}

size_t base64::encodeLength(size_t inputLength)
{
return (inputLength + 2 - ((inputLength + 2) % 3)) / 3 * 4 + 1;
}

void base64::decode(const char *input, uint8_t *output)
{
auto inputLength = strlen(input);
uint8_t position = 0;
uint8_t bit8x3[3] = {};
uint8_t bit6x4[4] = {};

while (inputLength--)
{
if (*input == '=')
{
break;
}

bit6x4[position++] = ::indexOf(*input++);

if (position == 4)
{
::to8x3(bit6x4, bit8x3);

for (const auto &v : bit8x3)
{
*output++ = v;
}

position = 0;
}
}

if (position)
{
for (uint8_t i = position; i < 4; i++)
{
bit6x4[i] = 0x00;
}

::to8x3(bit6x4, bit8x3);

for (uint8_t i = 0; i < position - 1; i++)
{
*output++ = bit8x3[i];
}
}
}

size_t base64::decodeLength(const char *input)
{
auto inputLength = strlen(input);
uint8_t equal = 0;

input += inputLength - 1;

while (*input-- == '=')
{
equal++;
}

return 6 * inputLength / 8 - equal;
}

0 comments on commit 16cc08d

Please sign in to comment.