util: add a strv_from_mem() helper function

Generates a strv with the buffer as hex string.
This commit is contained in:
Peter Hutterer 2023-08-23 11:26:31 +10:00
parent 4f2fd16186
commit 8e95c7d8a5
2 changed files with 108 additions and 0 deletions

View file

@ -224,6 +224,46 @@ strreplace(const char *string, const char *separator, const char *replacement)
}
char **
strv_from_mem(const uint8_t *buffer, size_t sz, size_t stride)
{
assert(stride > 0);
assert(stride <= 16);
char **strv = xalloc(((sz / stride) + 2) * sizeof *strv);
#define hex(buffer_, sz, line_, offset_) \
(line_ + offset_ < sz) ? buffer_[line_ + offset_] : 0u
for (size_t i = 0; i < sz; i += stride) {
char *str = xaprintf(
"%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
hex(buffer, sz, i, 0),
hex(buffer, sz, i, 1),
hex(buffer, sz, i, 2),
hex(buffer, sz, i, 3),
hex(buffer, sz, i, 4),
hex(buffer, sz, i, 5),
hex(buffer, sz, i, 6),
hex(buffer, sz, i, 7),
hex(buffer, sz, i, 8),
hex(buffer, sz, i, 9),
hex(buffer, sz, i, 10),
hex(buffer, sz, i, 11),
hex(buffer, sz, i, 12),
hex(buffer, sz, i, 13),
hex(buffer, sz, i, 14),
hex(buffer, sz, i, 15));
/* Chop the string off at the last value or our stride, whichever applies */
if (i + stride >= sz)
str[(sz - i) * 3 - 1] = '\0';
else if (stride < 16)
str[stride * 3 - 1] = '\0';
strv[i / stride] = str;
}
return strv;
}
#if _enable_tests_
#include "util-munit.h"
@ -498,4 +538,64 @@ MUNIT_TEST(test_strlen0)
return MUNIT_OK;
}
MUNIT_TEST(test_strv_from_mem)
{
uint8_t buf[36];
for (size_t i = 0; i < sizeof(buf); i++)
buf[i] = i;
{
_cleanup_(strv_freep) char **strv = strv_from_mem(buf, 16, 16);
munit_assert(strv != NULL);
munit_assert(strv[0] != NULL);
munit_assert_null(strv[1]); /* we expect one line */
munit_assert_string_equal(strv[0], "00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f");
}
{
_cleanup_(strv_freep) char **strv = strv_from_mem(buf, 8, 16);
munit_assert(strv != NULL);
munit_assert(strv[0] != NULL);
munit_assert_null(strv[1]); /* we expect one line */
munit_assert_string_equal(strv[0], "00 01 02 03 04 05 06 07");
}
{
_cleanup_(strv_freep) char **strv = strv_from_mem(buf, 8, 4);
munit_assert(strv != NULL);
munit_assert(strv[0] != NULL);
munit_assert(strv[1] != NULL);
munit_assert_null(strv[2]); /* we expect two lines */
munit_assert_string_equal(strv[0], "00 01 02 03");
munit_assert_string_equal(strv[1], "04 05 06 07");
}
{
_cleanup_(strv_freep) char **strv = strv_from_mem(buf, sizeof(buf), 5);
munit_assert(strv != NULL);
munit_assert_string_equal(strv[0], "00 01 02 03 04");
munit_assert_string_equal(strv[1], "05 06 07 08 09");
munit_assert_string_equal(strv[2], "0a 0b 0c 0d 0e");
munit_assert_string_equal(strv[3], "0f 10 11 12 13");
munit_assert_string_equal(strv[4], "14 15 16 17 18");
munit_assert_string_equal(strv[5], "19 1a 1b 1c 1d");
munit_assert_string_equal(strv[6], "1e 1f 20 21 22");
munit_assert_string_equal(strv[7], "23");
munit_assert_null(strv[8]);
}
{
uint8_t buffer[14];
memset(buffer, -1, sizeof(buffer));
_cleanup_(strv_freep) char **strv = strv_from_mem(buffer, sizeof(buffer), 8);
munit_assert(strv != NULL);
munit_assert_string_equal(strv[0], "ff ff ff ff ff ff ff ff");
munit_assert_string_equal(strv[1], "ff ff ff ff ff ff");
munit_assert_null(strv[2]);
}
return MUNIT_OK;
}
#endif

View file

@ -34,6 +34,7 @@
#include <limits.h>
#include <math.h>
#include <string.h>
#include <stdint.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
@ -276,6 +277,13 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(char **, strv_free);
char * strreplace(const char *string, const char *separator, const char *replacement);
/**
* Creates a list of strings representing the buffer similar to hexdump, i.e.
* a buffer of [0, 1, 2, 3, ...] with a stride of 4 is split into
* the strv of ["00 01 02 03", "04 05 06 07", ...].
*/
char **strv_from_mem(const uint8_t *buffer, size_t sz, size_t stride);
struct key_value_str{
char *key;
char *value;