summaryrefslogtreecommitdiffstats
path: root/src/utils.c
diff options
context:
space:
mode:
authorNeels Hofmeyr <neels@hofmeyr.de>2019-01-14 23:32:53 +0100
committerNeels Hofmeyr <nhofmeyr@sysmocom.de>2019-01-28 23:58:53 +0000
commit0423b61aa8dd75b3141e13cf9276b8fa14ceb473 (patch)
tree8437f60dc6f6f817f96f3118db61bf91383cbd7a /src/utils.c
parentd01ef75ab876d79c9a0a73cdefb4ccfc60bb47f8 (diff)
add osmo_hexdump_buf() and test
Add osmo_hexdump_buf() as an all-purpose hexdump function, which all other osmo_hexdump_*() implementations now call. It absorbs the static _osmo_hexdump(). Add tests for osmo_hexdump_buf(). Rationale: recently during patch review, a situation came up where two hexdumps in a single printf would have been useful. Now I've faced a similar situation again, in ongoing development. So I decided it is time to provide this API. The traditional osmo_hexdump() API returns a non-const char*, which should probably have been a const instead. Particularly this new function may return a string constant "" if the buf is NULL or empty, so return const char*. That is why the older implementations calling osmo_hexdump_buf() separately return the buffer instead of the const return value directly. Change-Id: I590595567b218b24e53c9eb1fd8736c0324d371d
Diffstat (limited to 'src/utils.c')
-rw-r--r--src/utils.c49
1 files changed, 38 insertions, 11 deletions
diff --git a/src/utils.c b/src/utils.c
index d1da4fa8..0b2ed31d 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -219,30 +219,55 @@ int osmo_hexparse(const char *str, uint8_t *b, int max_len)
static char hexd_buff[4096];
static const char hex_chars[] = "0123456789abcdef";
-static char *_osmo_hexdump(const unsigned char *buf, int len, char *delim)
+/*! Convert binary sequence to hexadecimal ASCII string.
+ * \param[out] out_buf Output buffer to write the resulting string to.
+ * \param[in] out_buf_size sizeof(out_buf).
+ * \param[in] buf Input buffer, pointer to sequence of bytes.
+ * \param[in] len Length of input buf in number of bytes.
+ * \param[in] delim String to separate each byte; NULL or "" for no delim.
+ * \param[in] delim_after_last If true, end the string in delim (true: "1a:ef:d9:", false: "1a:ef:d9");
+ * if out_buf has insufficient space, the string will always end in a delim.
+ * \returns out_buf, containing a zero-terminated string, or "" (empty string) if out_buf == NULL or out_buf_size < 1.
+ *
+ * This function will print a sequence of bytes as hexadecimal numbers, adding one delim between each byte (e.g. for
+ * delim passed as ":", return a string like "1a:ef:d9").
+ *
+ * The delim_after_last argument exists to be able to exactly show the original osmo_hexdump() behavior, which always
+ * ends the string with a delimiter.
+ */
+const char *osmo_hexdump_buf(char *out_buf, size_t out_buf_size, const unsigned char *buf, int len, const char *delim,
+ bool delim_after_last)
{
int i;
- char *cur = hexd_buff;
+ char *cur = out_buf;
+ size_t delim_len;
+
+ if (!out_buf || !out_buf_size)
+ return "";
+
+ delim = delim ? : "";
+ delim_len = strlen(delim);
- hexd_buff[0] = 0;
for (i = 0; i < len; i++) {
const char *delimp = delim;
- int len_remain = sizeof(hexd_buff) - (cur - hexd_buff);
- if (len_remain < 3)
+ int len_remain = out_buf_size - (cur - out_buf) - 1;
+ if (len_remain < (2 + delim_len)
+ && !(!delim_after_last && i == (len - 1) && len_remain >= 2))
break;
*cur++ = hex_chars[buf[i] >> 4];
*cur++ = hex_chars[buf[i] & 0xf];
+ if (i == (len - 1) && !delim_after_last)
+ break;
+
while (len_remain > 1 && *delimp) {
*cur++ = *delimp++;
len_remain--;
}
-
- *cur = 0;
}
- hexd_buff[sizeof(hexd_buff)-1] = 0;
- return hexd_buff;
+ *cur = '\0';
+ return out_buf;
}
/*! Convert a sequence of unpacked bits to ASCII string
@@ -292,7 +317,8 @@ char *osmo_ubit_dump(const uint8_t *bits, unsigned int len)
*/
char *osmo_hexdump(const unsigned char *buf, int len)
{
- return _osmo_hexdump(buf, len, " ");
+ osmo_hexdump_buf(hexd_buff, sizeof(hexd_buff), buf, len, " ", true);
+ return hexd_buff;
}
/*! Convert binary sequence to hexadecimal ASCII string
@@ -308,7 +334,8 @@ char *osmo_hexdump(const unsigned char *buf, int len)
*/
char *osmo_hexdump_nospc(const unsigned char *buf, int len)
{
- return _osmo_hexdump(buf, len, "");
+ osmo_hexdump_buf(hexd_buff, sizeof(hexd_buff), buf, len, "", true);
+ return hexd_buff;
}
/* Compat with previous typo to preserve abi */