/* vim: set expandtab ts=4 sw=4: */ /* * You may redistribute this program and/or modify it under the terms of * the GNU General Public License as published by the Free Software Foundation, * either version 3 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "util/Hex.h" #include #include static const uint8_t numForAscii[] = { 99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99, 99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99, 99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,99,99,99,99,99,99, 99,10,11,12,13,14,15,99,99,99,99,99,99,99,99,99, 99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99, 99,10,11,12,13,14,15,99,99,99,99,99,99,99,99,99, 99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99, }; static const char* hexEntities = "0123456789abcdef"; int Hex_encode(uint8_t* output, const uint32_t outputLength, const uint8_t* in, const uint32_t inputLength) { if (outputLength < inputLength * 2) { return Hex_TOO_BIG; } else if (outputLength > inputLength * 2) { output[inputLength * 2] = '\0'; } for (uint32_t i = 0; i < inputLength; i++) { output[i * 2] = hexEntities[in[i] >> 4]; output[i * 2 + 1] = hexEntities[in[i] & 15]; } return inputLength * 2; } int Hex_decodeByte(const uint8_t highNibble, const uint8_t lowNibble) { if ((highNibble & 0x80) | (lowNibble & 0x80)) { return -1; } int high = numForAscii[highNibble]; int low = numForAscii[lowNibble]; return (high + low < 31) ? (high << 4) | low : -1; } bool Hex_isHexEntity(const uint8_t character) { return !(character & 0x80) && (numForAscii[character] < 99); } int Hex_decode(uint8_t* output, const uint32_t outLength, const uint8_t* hex, const uint32_t length) { if (length % 1) { return Hex_BAD_INPUT; } else if (outLength < (length / 2)) { return Hex_TOO_BIG; } else if (outLength > (length / 2)) { output[length / 2] = '\0'; } for (uint32_t i = 0; i < length; i += 2) { int byte = Hex_decodeByte(hex[i], hex[i + 1]); if (byte == -1) { return Hex_BAD_INPUT; } output[i / 2] = (uint8_t) byte; } return length / 2; } uint8_t Hex_encodeLowNibble(const uint8_t nibble) { return hexEntities[nibble & 15]; } char* Hex_print(void* bytes, uint32_t length, struct Allocator* alloc) { int outLen = length * 2; char* outBuf = Allocator_malloc(alloc, outLen+1); Assert_true(Hex_encode(outBuf, outLen, (uint8_t*) bytes, length) == outLen); outBuf[outLen] = '\0'; return outBuf; }