Skip to content

Commit

Permalink
[glibutil] Added range utilities
Browse files Browse the repository at this point in the history
New functions are useful for parsing binary data:

  gutil_range_init_with_bytes()
  gutil_range_has_prefix()
  gutil_range_skip_prefix()
  • Loading branch information
monich committed May 22, 2021
1 parent b5359fb commit b6d240c
Show file tree
Hide file tree
Showing 3 changed files with 139 additions and 0 deletions.
15 changes: 15 additions & 0 deletions include/gutil_misc.h
Expand Up @@ -136,6 +136,21 @@ gutil_memdup(
const void* ptr,
gsize size); /* Since 1.0.52 */

gsize
gutil_range_init_with_bytes(
GUtilRange* range,
GBytes* bytes); /* Since 1.0.55 */

gboolean
gutil_range_has_prefix(
const GUtilRange* range,
const GUtilData* prefix); /* Since 1.0.55 */

gboolean
gutil_range_skip_prefix(
GUtilRange* range,
const GUtilData* prefix); /* Since 1.0.55 */

G_END_DECLS

#endif /* GUTIL_MISC_H */
Expand Down
46 changes: 46 additions & 0 deletions src/gutil_misc.c
Expand Up @@ -502,6 +502,52 @@ gutil_memdup(
}
}

gsize
gutil_range_init_with_bytes(
GUtilRange* range,
GBytes* bytes) /* Since 1.0.55 */
{
gsize size = 0;

if (G_LIKELY(range)) {
if (G_LIKELY(bytes)) {
range->ptr = (const guint8*) g_bytes_get_data(bytes, &size);
range->end = range->ptr + size;
} else {
memset(range, 0, sizeof(*range));
}
}
return size;
}

gboolean
gutil_range_has_prefix(
const GUtilRange* range,
const GUtilData* prefix) /* Since 1.0.55 */
{
if (G_LIKELY(range) && G_LIKELY(range->ptr) && G_LIKELY(prefix)) {
if (range->end > range->ptr) {
return (gsize)(range->end - range->ptr) >= prefix->size &&
!memcmp(range->ptr, prefix->bytes, prefix->size);
} else {
return !prefix->size;
}
}
return FALSE;
}

gboolean
gutil_range_skip_prefix(
GUtilRange* range,
const GUtilData* prefix) /* Since 1.0.55 */
{
if (gutil_range_has_prefix(range, prefix)) {
range->ptr += prefix->size;
return TRUE;
}
return FALSE;
}

/*
* Local Variables:
* mode: C
Expand Down
78 changes: 78 additions & 0 deletions test/test_misc/test_misc.c
Expand Up @@ -581,6 +581,82 @@ test_memdup(
g_assert(!gutil_memdup(NULL, 1));
}

/*==========================================================================*
* range_init
*==========================================================================*/

static
void
test_range_init(
void)
{
static const guint8 data[] = { 0x01, 0x02, 0x03 };
GBytes* bytes = g_bytes_new_static(data, sizeof(data));
GUtilRange range;

g_assert(!gutil_range_init_with_bytes(NULL, NULL));
g_assert(!gutil_range_init_with_bytes(&range, NULL));
g_assert(!range.ptr);
g_assert(!range.end);

g_assert(gutil_range_init_with_bytes(&range, bytes) == sizeof(data));
g_assert(range.ptr == data);
g_assert(range.end == (data + sizeof(data)));
g_bytes_unref(bytes);
}

/*==========================================================================*
* range_prefix
*==========================================================================*/

static
void
test_range_prefix(
void)
{
static const guint8 data[] = { 0x01, 0x02, 0x03, 0x04 };
static const guint8 prefix[] = { 0x01, 0x02 };
static const guint8 not_prefix[] = { 0x03, 0x04 };
static const guint8 too_long[] = { 0x01, 0x02, 0x03, 0x04, 0x05 };
GUtilData prefix_data, not_prefix_data, too_long_data;
GUtilRange range;

memset(&range, 0, sizeof(range));
g_assert(!gutil_range_has_prefix(NULL, NULL));
g_assert(!gutil_range_has_prefix(&range, NULL));

not_prefix_data.bytes = not_prefix;
not_prefix_data.size = sizeof(not_prefix);
too_long_data.bytes = too_long;
too_long_data.size = sizeof(too_long);

range.end = range.ptr = data; /* Empty range */
memset(&prefix_data, 0, sizeof(prefix_data)); /* Empty prefix */
/* Empty range doesn't have NULL prefix */
g_assert(!gutil_range_has_prefix(&range, NULL));
/* But does have empty prefix */
g_assert(gutil_range_has_prefix(&range, &prefix_data));

/* And doesn't have non-empty prefix */
g_assert(!gutil_range_has_prefix(&range, &not_prefix_data));
prefix_data.bytes = prefix;
prefix_data.size = sizeof(prefix);
g_assert(!gutil_range_has_prefix(&range, &prefix_data));

range.end = range.ptr + sizeof(data);

g_assert(gutil_range_has_prefix(&range, &prefix_data));
g_assert(!gutil_range_has_prefix(&range, &not_prefix_data));
g_assert(!gutil_range_has_prefix(&range, &too_long_data));

/* Test skipping */
g_assert(!gutil_range_skip_prefix(&range, &not_prefix_data));
g_assert(range.ptr == data);

g_assert(gutil_range_skip_prefix(&range, &prefix_data));
g_assert(range.ptr == (data + prefix_data.size));
}

/*==========================================================================*
* Common
*==========================================================================*/
Expand Down Expand Up @@ -614,6 +690,8 @@ int main(int argc, char* argv[])
g_test_add_func(TEST_("ptrv_lenght"), test_ptrv_length);
g_test_add_func(TEST_("ptrv_free"), test_ptrv_free);
g_test_add_func(TEST_("memdup"), test_memdup);
g_test_add_func(TEST_("range_init"), test_range_init);
g_test_add_func(TEST_("range_prefix"), test_range_prefix);
test_init(&test_opt, argc, argv);
return g_test_run();
}
Expand Down

0 comments on commit b6d240c

Please sign in to comment.