/*- * Copyright (c) 2008-2014 WiredTiger, Inc. * All rights reserved. * * See the file LICENSE for redistribution information. */ #include "wt_internal.h" static const u_char hex[] = "0123456789abcdef"; /* * __fill_hex -- * In-memory conversion of raw bytes to a hexadecimal representation. */ static inline void __fill_hex(const uint8_t *src, size_t src_max, uint8_t *dest, size_t dest_max, size_t *lenp) { uint8_t *dest_orig; dest_orig = dest; if (dest_max > 0) /* save a byte for nul-termination */ --dest_max; for (; src_max > 0 && dest_max > 1; src_max -= 1, dest_max -= 2, ++src) { *dest++ = hex[(*src & 0xf0) >> 4]; *dest++ = hex[*src & 0x0f]; } *dest++ = '\0'; if (lenp != NULL) *lenp = WT_PTRDIFF(dest, dest_orig); } /* * __wt_raw_to_hex -- * Convert a chunk of data to a nul-terminated printable hex string. */ int __wt_raw_to_hex( WT_SESSION_IMPL *session, const uint8_t *from, size_t size, WT_ITEM *to) { size_t len; /* * Every byte takes up 2 spaces, plus a trailing nul byte. */ len = size * 2 + 1; WT_RET(__wt_buf_init(session, to, len)); __fill_hex(from, size, to->mem, len, &to->size); return (0); } /* * __wt_raw_to_esc_hex -- * Convert a chunk of data to a nul-terminated printable string using * escaped hex, as necessary. */ int __wt_raw_to_esc_hex( WT_SESSION_IMPL *session, const uint8_t *from, size_t size, WT_ITEM *to) { size_t i; const uint8_t *p; u_char *t; /* * In the worst case, every character takes up 3 spaces, plus a * trailing nul byte. */ WT_RET(__wt_buf_init(session, to, size * 3 + 1)); /* * In the worst case, every character takes up 3 spaces, plus a * trailing nul byte. */ for (p = from, t = to->mem, i = size; i > 0; --i, ++p) if (isprint((int)*p)) { if (*p == '\\') *t++ = '\\'; *t++ = *p; } else { *t++ = '\\'; *t++ = hex[(*p & 0xf0) >> 4]; *t++ = hex[*p & 0x0f]; } *t++ = '\0'; to->size = WT_PTRDIFF(t, to->mem); return (0); } /* * __wt_hex2byte -- * Convert a pair of hex characters into a byte. */ int __wt_hex2byte(const u_char *from, u_char *to) { uint8_t byte; switch (from[0]) { case '0': byte = 0; break; case '1': byte = 1 << 4; break; case '2': byte = 2 << 4; break; case '3': byte = 3 << 4; break; case '4': byte = 4 << 4; break; case '5': byte = 5 << 4; break; case '6': byte = 6 << 4; break; case '7': byte = 7 << 4; break; case '8': byte = 8 << 4; break; case '9': byte = 9 << 4; break; case 'a': byte = 10 << 4; break; case 'b': byte = 11 << 4; break; case 'c': byte = 12 << 4; break; case 'd': byte = 13 << 4; break; case 'e': byte = 14 << 4; break; case 'f': byte = 15 << 4; break; default: return (1); } switch (from[1]) { case '0': break; case '1': byte |= 1; break; case '2': byte |= 2; break; case '3': byte |= 3; break; case '4': byte |= 4; break; case '5': byte |= 5; break; case '6': byte |= 6; break; case '7': byte |= 7; break; case '8': byte |= 8; break; case '9': byte |= 9; break; case 'a': byte |= 10; break; case 'b': byte |= 11; break; case 'c': byte |= 12; break; case 'd': byte |= 13; break; case 'e': byte |= 14; break; case 'f': byte |= 15; break; default: return (1); } *to = byte; return (0); } /* * __hex_fmterr -- * Hex format error message. */ static int __hex_fmterr(WT_SESSION_IMPL *session) { WT_RET_MSG(session, EINVAL, "Invalid format in hexadecimal string"); } /* * __wt_hex_to_raw -- * Convert a nul-terminated printable hex string to a chunk of data. */ int __wt_hex_to_raw(WT_SESSION_IMPL *session, const char *from, WT_ITEM *to) { return (__wt_nhex_to_raw(session, from, strlen(from), to)); } /* * __wt_nhex_to_raw -- * Convert a printable hex string to a chunk of data. */ int __wt_nhex_to_raw( WT_SESSION_IMPL *session, const char *from, size_t size, WT_ITEM *to) { const u_char *p; u_char *t; if (size % 2 != 0) return (__hex_fmterr(session)); WT_RET(__wt_buf_init(session, to, size / 2)); for (p = (u_char *)from, t = to->mem; size > 0; p += 2, size -= 2, ++t) if (__wt_hex2byte(p, t)) return (__hex_fmterr(session)); to->size = WT_PTRDIFF(t, to->mem); return (0); } /* * __wt_esc_hex_to_raw -- * Convert a printable string, encoded in escaped hex, to a chunk of data. */ int __wt_esc_hex_to_raw(WT_SESSION_IMPL *session, const char *from, WT_ITEM *to) { const u_char *p; u_char *t; WT_RET(__wt_buf_init(session, to, strlen(from))); for (p = (u_char *)from, t = to->mem; *p != '\0'; ++p, ++t) { if ((*t = *p) != '\\') continue; ++p; if (p[0] != '\\') { if (p[0] == '\0' || p[1] == '\0' || __wt_hex2byte(p, t)) return (__hex_fmterr(session)); ++p; } } to->size = WT_PTRDIFF(t, to->mem); return (0); }