Branch data Line data Source code
1 : : // Copyright 2011-2026 David Robillard <d@drobilla.net> 2 : : // SPDX-License-Identifier: ISC 3 : : 4 : : #include "char_utils.h" 5 : : #include "read_utils.h" 6 : : #include "result.h" 7 : : #include "write_utils.h" 8 : : 9 : : #include <exess/exess.h> 10 : : 11 : : #include <stdint.h> 12 : : #include <string.h> 13 : : 14 : : /// Hex encoding table 15 : : static const char hex_map[] = "0123456789ABCDEF"; 16 : : 17 : : static uint8_t 18 : 65547 : decode_nibble(const char c) 19 : : { 20 [ + + ]: 65547 : if (is_digit(c)) { 21 : 41022 : return (uint8_t)(c - '0'); 22 : : } 23 : : 24 [ + + + + ]: 24525 : if (c >= 'A' && c <= 'F') { 25 : 24505 : return (uint8_t)(10 + c - 'A'); 26 : : } 27 : : 28 [ + + + + ]: 20 : if (c >= 'a' && c <= 'f') { 29 : 6 : return (uint8_t)(10 + c - 'a'); 30 : : } 31 : : 32 : 14 : return UINT8_MAX; 33 : : } 34 : : 35 : : EXESS_NONBLOCKING size_t 36 : 6 : exess_decoded_hex_size(const size_t length) 37 : : { 38 : 6 : return length / 2; 39 : : } 40 : : 41 : : EXESS_NONBLOCKING ExessVariableResult 42 : 316 : exess_read_hex(const char* const str, const size_t out_size, void* const out) 43 : : { 44 : 316 : uint8_t* const uout = (uint8_t*)out; 45 : 316 : const size_t first = skip_whitespace(str); 46 : 316 : size_t i = first; 47 : 316 : size_t o = 0U; 48 : : 49 [ + + ]: 33079 : while (str[i]) { 50 : 32778 : const char hi_char = str[i]; 51 : 32778 : const uint8_t hi = decode_nibble(hi_char); 52 [ + + ]: 32778 : if (hi == UINT8_MAX) { 53 [ + + ]: 8 : return VRESULT(i == first ? EXESS_EXPECTED_HEX : EXESS_SUCCESS, i, o); 54 : : } 55 : : 56 : 32770 : ++i; 57 : : 58 : 32770 : const char lo_char = str[i]; 59 [ + + ]: 32770 : if (!lo_char) { 60 : 1 : return VRESULT(EXESS_EXPECTED_HEX, i, o); 61 : : } 62 : : 63 : 32769 : const uint8_t lo = decode_nibble(lo_char); 64 [ + + ]: 32769 : if (lo == UINT8_MAX) { 65 : 6 : return VRESULT(EXESS_EXPECTED_HEX, i, o); 66 : : } 67 : : 68 : 32763 : ++i; 69 : : 70 [ + + ]: 32763 : if (o < out_size) { 71 : 32757 : uout[o] = (uint8_t)(((unsigned)hi << 4U) | lo); 72 : : } 73 : : 74 : 32763 : ++o; 75 : : } 76 : : 77 [ + + ]: 301 : return VRESULT(o <= out_size ? EXESS_SUCCESS : EXESS_NO_SPACE, i, o); 78 : : } 79 : : 80 : : EXESS_NONBLOCKING ExessResult 81 : 519 : exess_write_hex(const size_t data_size, 82 : : const void* const data, 83 : : const size_t buf_size, 84 : : char* const buf) 85 : : { 86 : 519 : const size_t length = 2 * data_size; 87 [ + + + + ]: 519 : if (!buf || length >= buf_size) { 88 : 261 : return end_write(EXESS_NO_SPACE, buf_size, buf, length); 89 : : } 90 : : 91 : 258 : const uint8_t* const in = (const uint8_t*)data; 92 : 258 : size_t o = 0U; 93 : : 94 [ + + ]: 32907 : for (size_t i = 0; i < data_size; ++i) { 95 : 32649 : const uint8_t hi = (in[i] & 0xF0U) >> 4U; 96 : 32649 : const uint8_t lo = (in[i] & 0x0FU); 97 : : 98 : 32649 : buf[o++] = hex_map[hi]; 99 : 32649 : buf[o++] = hex_map[lo]; 100 : : } 101 : : 102 : 258 : return end_write(EXESS_SUCCESS, buf_size, buf, o); 103 : : }