You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
208 lines
6.6 KiB
208 lines
6.6 KiB
/**
|
|
* Base64 encoder/decoder for arduino repo
|
|
* Uses common web conventions - '+' for 62, '/' for 63, '=' for padding.
|
|
* Note that invalid base64 characters are interpreted as padding.
|
|
* Author: Densaugeo
|
|
* Maintainer: Densaugeo
|
|
* Version: 1.2.1.1
|
|
* Changed unsigned int to uint16_t for use in the professional Ender 3V2/S1 firmware
|
|
* Url: https://www.arduino.cc/reference/en/libraries/base64/
|
|
*/
|
|
|
|
#ifndef BASE64_H_INCLUDED
|
|
#define BASE64_H_INCLUDED
|
|
|
|
/* binary_to_base64:
|
|
* Description:
|
|
* Converts a single byte from a binary value to the corresponding base64 character
|
|
* Parameters:
|
|
* v - Byte to convert
|
|
* Returns:
|
|
* ascii code of base64 character. If byte is >= 64, then there is not corresponding base64 character
|
|
* and 255 is returned
|
|
*/
|
|
unsigned char binary_to_base64(unsigned char v);
|
|
|
|
/* base64_to_binary:
|
|
* Description:
|
|
* Converts a single byte from a base64 character to the corresponding binary value
|
|
* Parameters:
|
|
* c - Base64 character (as ascii code)
|
|
* Returns:
|
|
* 6-bit binary value
|
|
*/
|
|
unsigned char base64_to_binary(unsigned char c);
|
|
|
|
/* encode_base64_length:
|
|
* Description:
|
|
* Calculates length of base64 string needed for a given number of binary bytes
|
|
* Parameters:
|
|
* input_length - Amount of binary data in bytes
|
|
* Returns:
|
|
* Number of base64 characters needed to encode input_length bytes of binary data
|
|
*/
|
|
uint16_t encode_base64_length(uint16_t input_length);
|
|
|
|
/* decode_base64_length:
|
|
* Description:
|
|
* Calculates number of bytes of binary data in a base64 string
|
|
* Variant that does not use input_length no longer used within library, retained for API compatibility
|
|
* Parameters:
|
|
* input - Base64-encoded null-terminated string
|
|
* input_length (optional) - Number of bytes to read from input pointer
|
|
* Returns:
|
|
* Number of bytes of binary data in input
|
|
*/
|
|
uint16_t decode_base64_length(unsigned char input[]);
|
|
uint16_t decode_base64_length(unsigned char input[], uint16_t input_length);
|
|
|
|
/* encode_base64:
|
|
* Description:
|
|
* Converts an array of bytes to a base64 null-terminated string
|
|
* Parameters:
|
|
* input - Pointer to input data
|
|
* input_length - Number of bytes to read from input pointer
|
|
* output - Pointer to output string. Null terminator will be added automatically
|
|
* Returns:
|
|
* Length of encoded string in bytes (not including null terminator)
|
|
*/
|
|
uint16_t encode_base64(unsigned char input[], uint16_t input_length, unsigned char output[]);
|
|
|
|
/* decode_base64:
|
|
* Description:
|
|
* Converts a base64 null-terminated string to an array of bytes
|
|
* Parameters:
|
|
* input - Pointer to input string
|
|
* input_length (optional) - Number of bytes to read from input pointer
|
|
* output - Pointer to output array
|
|
* Returns:
|
|
* Number of bytes in the decoded binary
|
|
*/
|
|
uint16_t decode_base64(unsigned char input[], unsigned char output[]);
|
|
uint16_t decode_base64(unsigned char input[], uint16_t input_length, unsigned char output[]);
|
|
|
|
unsigned char binary_to_base64(unsigned char v) {
|
|
// Capital letters - 'A' is ascii 65 and base64 0
|
|
if (v < 26) return v + 'A';
|
|
|
|
// Lowercase letters - 'a' is ascii 97 and base64 26
|
|
if (v < 52) return v + 71;
|
|
|
|
// Digits - '0' is ascii 48 and base64 52
|
|
if (v < 62) return v - 4;
|
|
|
|
// '+' is ascii 43 and base64 62
|
|
if (v == 62) return '+';
|
|
|
|
// '/' is ascii 47 and base64 63
|
|
if (v == 63) return '/';
|
|
|
|
return 64;
|
|
}
|
|
|
|
unsigned char base64_to_binary(unsigned char c) {
|
|
// Capital letters - 'A' is ascii 65 and base64 0
|
|
if ('A' <= c && c <= 'Z') return c - 'A';
|
|
|
|
// Lowercase letters - 'a' is ascii 97 and base64 26
|
|
if ('a' <= c && c <= 'z') return c - 71;
|
|
|
|
// Digits - '0' is ascii 48 and base64 52
|
|
if ('0' <= c && c <= '9') return c + 4;
|
|
|
|
// '+' is ascii 43 and base64 62
|
|
if (c == '+') return 62;
|
|
|
|
// '/' is ascii 47 and base64 63
|
|
if (c == '/') return 63;
|
|
|
|
return 255;
|
|
}
|
|
|
|
uint16_t encode_base64_length(uint16_t input_length) {
|
|
return (input_length + 2)/3*4;
|
|
}
|
|
|
|
uint16_t decode_base64_length(unsigned char input[]) {
|
|
return decode_base64_length(input, -1);
|
|
}
|
|
|
|
uint16_t decode_base64_length(unsigned char input[], uint16_t input_length) {
|
|
unsigned char *start = input;
|
|
|
|
while (base64_to_binary(input[0]) < 64 && (unsigned char)(input - start) < input_length) {
|
|
++input;
|
|
}
|
|
|
|
input_length = input - start;
|
|
return input_length/4*3 + (input_length % 4 ? input_length % 4 - 1 : 0);
|
|
}
|
|
|
|
uint16_t encode_base64(unsigned char input[], uint16_t input_length, unsigned char output[]) {
|
|
uint16_t full_sets = input_length/3;
|
|
|
|
// While there are still full sets of 24 bits...
|
|
for (uint16_t i = 0; i < full_sets; ++i) {
|
|
output[0] = binary_to_base64( input[0] >> 2);
|
|
output[1] = binary_to_base64((input[0] & 0x03) << 4 | input[1] >> 4);
|
|
output[2] = binary_to_base64((input[1] & 0x0F) << 2 | input[2] >> 6);
|
|
output[3] = binary_to_base64( input[2] & 0x3F);
|
|
|
|
input += 3;
|
|
output += 4;
|
|
}
|
|
|
|
switch (input_length % 3) {
|
|
case 0:
|
|
output[0] = '\0';
|
|
break;
|
|
case 1:
|
|
output[0] = binary_to_base64( input[0] >> 2);
|
|
output[1] = binary_to_base64((input[0] & 0x03) << 4);
|
|
output[2] = '=';
|
|
output[3] = '=';
|
|
output[4] = '\0';
|
|
break;
|
|
case 2:
|
|
output[0] = binary_to_base64( input[0] >> 2);
|
|
output[1] = binary_to_base64((input[0] & 0x03) << 4 | input[1] >> 4);
|
|
output[2] = binary_to_base64((input[1] & 0x0F) << 2);
|
|
output[3] = '=';
|
|
output[4] = '\0';
|
|
break;
|
|
}
|
|
|
|
return encode_base64_length(input_length);
|
|
}
|
|
|
|
uint16_t decode_base64(unsigned char input[], unsigned char output[]) {
|
|
return decode_base64(input, -1, output);
|
|
}
|
|
|
|
uint16_t decode_base64(unsigned char input[], uint16_t input_length, unsigned char output[]) {
|
|
uint16_t output_length = decode_base64_length(input, input_length);
|
|
|
|
// While there are still full sets of 24 bits...
|
|
for (uint16_t i = 2; i < output_length; i += 3) {
|
|
output[0] = base64_to_binary(input[0]) << 2 | base64_to_binary(input[1]) >> 4;
|
|
output[1] = base64_to_binary(input[1]) << 4 | base64_to_binary(input[2]) >> 2;
|
|
output[2] = base64_to_binary(input[2]) << 6 | base64_to_binary(input[3]);
|
|
|
|
input += 4;
|
|
output += 3;
|
|
}
|
|
|
|
switch (output_length % 3) {
|
|
case 1:
|
|
output[0] = base64_to_binary(input[0]) << 2 | base64_to_binary(input[1]) >> 4;
|
|
break;
|
|
case 2:
|
|
output[0] = base64_to_binary(input[0]) << 2 | base64_to_binary(input[1]) >> 4;
|
|
output[1] = base64_to_binary(input[1]) << 4 | base64_to_binary(input[2]) >> 2;
|
|
break;
|
|
}
|
|
|
|
return output_length;
|
|
}
|
|
|
|
#endif // BASE64_H_INCLUDED
|
|
|