/* wsutil/to_str.c * Routines for utilities to convert various other types to strings. * * Wireshark - Network traffic analyzer * By Gerald Combs * Copyright 1998 Gerald Combs * * SPDX-License-Identifier: GPL-2.0-or-later */ #include "config.h" #include #include #include #include #include "to_str.h" #include #include static inline char low_nibble_of_octet_to_hex(guint8 oct) { /* At least one version of Apple's C compiler/linker is buggy, causing a complaint from the linker about the "literal C string section" not ending with '\0' if we initialize a 16-element "char" array with a 16-character string, the fact that initializing such an array with such a string is perfectly legitimate ANSI C nonwithstanding, the 17th '\0' byte in the string nonwithstanding. */ static const gchar hex_digits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; return hex_digits[oct & 0xF]; } static inline char * byte_to_hex(char *out, guint32 dword) { *out++ = low_nibble_of_octet_to_hex(dword >> 4); *out++ = low_nibble_of_octet_to_hex(dword); return out; } /* * This does *not* null-terminate the string. It returns a pointer * to the position in the string following the last character it * puts there, so that the caller can either put the null terminator * in or can append more stuff to the buffer. * * There needs to be at least len * 2 bytes left in the buffer. */ char * bytes_to_hexstr(char *out, const guint8 *ad, size_t len) { size_t i; if (!ad) { ws_warning("Null pointer passed to bytes_to_hexstr()"); return NULL; } for (i = 0; i < len; i++) out = byte_to_hex(out, ad[i]); return out; } /* * This does *not* null-terminate the string. It returns a pointer * to the position in the string following the last character it * puts there, so that the caller can either put the null terminator * in or can append more stuff to the buffer. * * There needs to be at least len * 3 - 1 bytes left in the buffer. */ char * bytes_to_hexstr_punct(char *out, const guint8 *ad, size_t len, char punct) { size_t i; if (!ad) { ws_warning("Null pointer passed to bytes_to_hexstr_punct()"); return NULL; } out = byte_to_hex(out, ad[0]); for (i = 1; i < len; i++) { *out++ = punct; out = byte_to_hex(out, ad[i]); } return out; } /* Routine to convert a sequence of bytes to a hex string, one byte/two hex * digits at at a time, with a specified punctuation character between * the bytes. * * If punct is '\0', no punctuation is applied (and thus * the resulting string is (len-1) bytes shorter) */ gchar * bytes_to_str_punct_max(wmem_allocator_t *scope, const guint8 *ad, size_t len, const char punct, size_t max) { gchar *buf; size_t buflen = len; gchar *buf_ptr; int truncated = 0; if (len == 0) { ws_warning("Zero length passed to bytes_to_str_punct()"); return wmem_strdup(scope, "(zero length)"); } if (!ad) { ws_warning("Null pointer passed to bytes_to_str_punct()"); return wmem_strdup(scope, "(null pointer)"); } if (!punct) return bytes_to_str_max(scope, ad, len, max); if (max > len * 3) max = len * 3; buf=(gchar *)wmem_alloc(scope, max+3+1); if (buflen > max/3) { truncated = 1; buflen = max/3; } buf_ptr = bytes_to_hexstr_punct(buf, ad, buflen, punct); /* maximum max-1 bytes */ if (truncated) { *buf_ptr++ = punct; /* 1 byte */ buf_ptr = g_stpcpy(buf_ptr, UTF8_HORIZONTAL_ELLIPSIS); /* 3 bytes */ } *buf_ptr = '\0'; return buf; } char * bytes_to_str_max(wmem_allocator_t *scope, const guint8 *bd, size_t bd_len, size_t max) { gchar *cur; gchar *cur_ptr; int truncated = 0; if (bd_len == 0) { ws_warning("Zero length passed to bytes_to_str()"); return wmem_strdup(scope, "(zero length)"); } if (!bd) { ws_warning("Null pointer passed to bytes_to_str()"); return wmem_strdup(scope, "(null pointer)"); } if (max > bd_len * 2) max = bd_len * 2; cur=(gchar *)wmem_alloc(scope, max+3+1); if (bd_len > max/2) { truncated = 1; bd_len = max/2; } cur_ptr = bytes_to_hexstr(cur, bd, bd_len); /* max MAX_BYTE_STR_LEN bytes */ if (truncated) cur_ptr = g_stpcpy(cur_ptr, UTF8_HORIZONTAL_ELLIPSIS); /* 3 bytes */ *cur_ptr = '\0'; /* 1 byte */ return cur; } /* * Editor modelines - https://www.wireshark.org/tools/modelines.html * * Local variables: * c-basic-offset: 8 * tab-width: 8 * indent-tabs-mode: t * End: * * vi: set shiftwidth=8 tabstop=8 noexpandtab: * :indentSize=8:tabSize=8:noTabs=false: */