mirror of
https://github.com/esphome/esphome.git
synced 2026-02-08 00:31:58 +00:00
[helpers] Add base85 support (#13254)
Co-authored-by: J. Nick Koston <nick@koston.org>
This commit is contained in:
@@ -617,6 +617,55 @@ std::vector<uint8_t> base64_decode(const std::string &encoded_string) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Encode int32 to 5 base85 characters + null terminator
|
||||||
|
/// Standard ASCII85 alphabet: '!' (33) = 0 through 'u' (117) = 84
|
||||||
|
inline void base85_encode_int32(int32_t value, std::span<char, BASE85_INT32_ENCODED_SIZE> output) {
|
||||||
|
uint32_t v = static_cast<uint32_t>(value);
|
||||||
|
// Encode least significant digit first, then reverse
|
||||||
|
for (int i = 4; i >= 0; i--) {
|
||||||
|
output[i] = static_cast<char>('!' + (v % 85));
|
||||||
|
v /= 85;
|
||||||
|
}
|
||||||
|
output[5] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Decode 5 base85 characters to int32
|
||||||
|
inline bool base85_decode_int32(const char *input, int32_t &out) {
|
||||||
|
uint8_t c0 = static_cast<uint8_t>(input[0] - '!');
|
||||||
|
uint8_t c1 = static_cast<uint8_t>(input[1] - '!');
|
||||||
|
uint8_t c2 = static_cast<uint8_t>(input[2] - '!');
|
||||||
|
uint8_t c3 = static_cast<uint8_t>(input[3] - '!');
|
||||||
|
uint8_t c4 = static_cast<uint8_t>(input[4] - '!');
|
||||||
|
|
||||||
|
// Each digit must be 0-84. Since uint8_t wraps, chars below '!' become > 84
|
||||||
|
if (c0 > 84 || c1 > 84 || c2 > 84 || c3 > 84 || c4 > 84)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// 85^4 = 52200625, 85^3 = 614125, 85^2 = 7225, 85^1 = 85
|
||||||
|
out = static_cast<int32_t>(c0 * 52200625u + c1 * 614125u + c2 * 7225u + c3 * 85u + c4);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Decode base85 string directly into vector (no intermediate buffer)
|
||||||
|
bool base85_decode_int32_vector(const std::string &base85, std::vector<int32_t> &out) {
|
||||||
|
size_t len = base85.size();
|
||||||
|
if (len % 5 != 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
out.clear();
|
||||||
|
const char *ptr = base85.data();
|
||||||
|
const char *end = ptr + len;
|
||||||
|
|
||||||
|
while (ptr < end) {
|
||||||
|
int32_t value;
|
||||||
|
if (!base85_decode_int32(ptr, value))
|
||||||
|
return false;
|
||||||
|
out.push_back(value);
|
||||||
|
ptr += 5;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// Colors
|
// Colors
|
||||||
|
|
||||||
float gamma_correct(float value, float gamma) {
|
float gamma_correct(float value, float gamma) {
|
||||||
|
|||||||
@@ -1086,6 +1086,14 @@ std::vector<uint8_t> base64_decode(const std::string &encoded_string);
|
|||||||
size_t base64_decode(std::string const &encoded_string, uint8_t *buf, size_t buf_len);
|
size_t base64_decode(std::string const &encoded_string, uint8_t *buf, size_t buf_len);
|
||||||
size_t base64_decode(const uint8_t *encoded_data, size_t encoded_len, uint8_t *buf, size_t buf_len);
|
size_t base64_decode(const uint8_t *encoded_data, size_t encoded_len, uint8_t *buf, size_t buf_len);
|
||||||
|
|
||||||
|
/// Size of buffer needed for base85 encoded int32 (5 chars + null terminator)
|
||||||
|
static constexpr size_t BASE85_INT32_ENCODED_SIZE = 6;
|
||||||
|
|
||||||
|
void base85_encode_int32(int32_t value, std::span<char, BASE85_INT32_ENCODED_SIZE> output);
|
||||||
|
|
||||||
|
bool base85_decode_int32(const char *input, int32_t &out);
|
||||||
|
bool base85_decode_int32_vector(const std::string &base85, std::vector<int32_t> &out);
|
||||||
|
|
||||||
///@}
|
///@}
|
||||||
|
|
||||||
/// @name Colors
|
/// @name Colors
|
||||||
|
|||||||
Reference in New Issue
Block a user