forked from xperiments-in/xtouch
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
6b206ba
commit 16cc08d
Showing
2 changed files
with
204 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} |