feat: hexa parsing util
This commit is contained in:
parent
b26de0f3e3
commit
ad6a542969
5 changed files with 190 additions and 2 deletions
|
|
@ -1,11 +1,14 @@
|
|||
#ifndef CLI_PARSE_UTILS_H
|
||||
#define CLI_PARSE_UTILS_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
int cli_parse_uint64(const char *s, uint64_t *out);
|
||||
int cli_parse_int64(const char *s, int64_t *out);
|
||||
int cli_parse_float(const char *s, float *out);
|
||||
int cli_parse_ufloat(const char *s, float *out);
|
||||
int cli_parse_hex(const char *str, uint8_t *out, size_t max_len, size_t
|
||||
*out_len);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -6,7 +6,8 @@ libcli_la_SOURCES = \
|
|||
parse_utils/parse_uint.c \
|
||||
parse_utils/parse_int.c \
|
||||
parse_utils/parse_float.c \
|
||||
parse_utils/parse_ufloat.c
|
||||
parse_utils/parse_ufloat.c \
|
||||
parse_utils/parse_hex.c
|
||||
|
||||
libcli_la_CPPFLAGS = -I$(top_srcdir)/include
|
||||
libcli_la_CFLAGS = -std=c99 -Wall -Wextra
|
||||
|
|
|
|||
41
src/parse_utils/parse_hex.c
Normal file
41
src/parse_utils/parse_hex.c
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
#include <string.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/* Forward declarations */
|
||||
static int hex_nibble(char c);
|
||||
/* -------------------- */
|
||||
|
||||
int
|
||||
cli_parse_hex(const char *str, uint8_t *out, size_t max_len, size_t *out_len)
|
||||
{
|
||||
size_t str_len;
|
||||
size_t byte_count;
|
||||
|
||||
if (NULL == str || '\0' == str[0])
|
||||
return 1;
|
||||
str_len = strlen(str);
|
||||
byte_count = (str_len + 1) / 2;
|
||||
if (byte_count > max_len)
|
||||
return 1;
|
||||
*out_len = 0;
|
||||
for (size_t i = 0; i < str_len; i += 2)
|
||||
{
|
||||
int hi = hex_nibble(str[i]);
|
||||
int lo = (i + 1 < str_len) ? hex_nibble(str[i + 1]) : 0;
|
||||
|
||||
if (hi < 0 || lo < 0)
|
||||
return 1;
|
||||
out[(*out_len)++] = (uint8_t)(hi << 4 | lo);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
hex_nibble(char c)
|
||||
{
|
||||
if (c >= '0' && c <= '9') return c - '0';
|
||||
if (c >= 'a' && c <= 'f') return c - 'a' + 10;
|
||||
if (c >= 'A' && c <= 'F') return c - 'A' + 10;
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -6,7 +6,8 @@ check_PROGRAMS = test_cli
|
|||
test_cli_SOURCES = \
|
||||
test_main.c \
|
||||
parse_utils/test_parse_int.c \
|
||||
parse_utils/test_parse_float.c
|
||||
parse_utils/test_parse_float.c \
|
||||
parse_utils/test_parse_hex.c
|
||||
|
||||
test_cli_LDADD = \
|
||||
$(top_builddir)/src/libcli.la \
|
||||
|
|
|
|||
142
tests/parse_utils/test_parse_hex.c
Normal file
142
tests/parse_utils/test_parse_hex.c
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
#include <criterion/criterion.h>
|
||||
#include <stdint.h>
|
||||
#include "cli_parse_utils.h"
|
||||
|
||||
/* Test 1: Valid even-length string */
|
||||
Test(parse_hex, even_length)
|
||||
{
|
||||
uint8_t out[4];
|
||||
size_t len;
|
||||
int ret = cli_parse_hex("deadbeef", out, 4, &len);
|
||||
|
||||
cr_assert_eq(ret, 0);
|
||||
cr_assert_eq(len, 4);
|
||||
cr_assert_eq(out[0], 0xde);
|
||||
cr_assert_eq(out[1], 0xad);
|
||||
cr_assert_eq(out[2], 0xbe);
|
||||
cr_assert_eq(out[3], 0xef);
|
||||
}
|
||||
|
||||
/* Test 2: Valid odd-length string — trailing nibble padded with 0 */
|
||||
Test(parse_hex, odd_length)
|
||||
{
|
||||
uint8_t out[2];
|
||||
size_t len;
|
||||
int ret = cli_parse_hex("abc", out, 2, &len);
|
||||
|
||||
cr_assert_eq(ret, 0);
|
||||
cr_assert_eq(len, 2);
|
||||
cr_assert_eq(out[0], 0xab);
|
||||
cr_assert_eq(out[1], 0xc0);
|
||||
}
|
||||
|
||||
/* Test 3: Single char */
|
||||
Test(parse_hex, single_char)
|
||||
{
|
||||
uint8_t out[1];
|
||||
size_t len;
|
||||
int ret = cli_parse_hex("f", out, 1, &len);
|
||||
|
||||
cr_assert_eq(ret, 0);
|
||||
cr_assert_eq(len, 1);
|
||||
cr_assert_eq(out[0], 0xf0);
|
||||
}
|
||||
|
||||
/* Test 4: Single byte */
|
||||
Test(parse_hex, single_byte)
|
||||
{
|
||||
uint8_t out[1];
|
||||
size_t len;
|
||||
int ret = cli_parse_hex("ff", out, 1, &len);
|
||||
|
||||
cr_assert_eq(ret, 0);
|
||||
cr_assert_eq(len, 1);
|
||||
cr_assert_eq(out[0], 0xff);
|
||||
}
|
||||
|
||||
/* Test 5: Mixed case */
|
||||
Test(parse_hex, mixed_case)
|
||||
{
|
||||
uint8_t out[2];
|
||||
size_t len;
|
||||
int ret = cli_parse_hex("DeAd", out, 2, &len);
|
||||
|
||||
cr_assert_eq(ret, 0);
|
||||
cr_assert_eq(len, 2);
|
||||
cr_assert_eq(out[0], 0xde);
|
||||
cr_assert_eq(out[1], 0xad);
|
||||
}
|
||||
|
||||
/* Test 6: All zeros */
|
||||
Test(parse_hex, all_zeros)
|
||||
{
|
||||
uint8_t out[2];
|
||||
size_t len;
|
||||
int ret = cli_parse_hex("0000", out, 2, &len);
|
||||
|
||||
cr_assert_eq(ret, 0);
|
||||
cr_assert_eq(len, 2);
|
||||
cr_assert_eq(out[0], 0x00);
|
||||
cr_assert_eq(out[1], 0x00);
|
||||
}
|
||||
|
||||
/* Test 7: Exactly at max_len */
|
||||
Test(parse_hex, exact_max_len)
|
||||
{
|
||||
uint8_t out[4];
|
||||
size_t len;
|
||||
int ret = cli_parse_hex("deadbeef", out, 4, &len);
|
||||
|
||||
cr_assert_eq(ret, 0);
|
||||
cr_assert_eq(len, 4);
|
||||
}
|
||||
|
||||
/* Test 8: Exceeds max_len */
|
||||
Test(parse_hex, exceeds_max_len)
|
||||
{
|
||||
uint8_t out[2];
|
||||
size_t len;
|
||||
int ret = cli_parse_hex("deadbeef", out, 2, &len);
|
||||
|
||||
cr_assert_eq(ret, 1);
|
||||
}
|
||||
|
||||
/* Test 9: NULL input */
|
||||
Test(parse_hex, null_input)
|
||||
{
|
||||
uint8_t out[4];
|
||||
size_t len;
|
||||
int ret = cli_parse_hex(NULL, out, 4, &len);
|
||||
|
||||
cr_assert_eq(ret, 1);
|
||||
}
|
||||
|
||||
/* Test 10: Empty string */
|
||||
Test(parse_hex, empty_string)
|
||||
{
|
||||
uint8_t out[4];
|
||||
size_t len;
|
||||
int ret = cli_parse_hex("", out, 4, &len);
|
||||
|
||||
cr_assert_eq(ret, 1);
|
||||
}
|
||||
|
||||
/* Test 11: Invalid hex characters */
|
||||
Test(parse_hex, invalid_chars)
|
||||
{
|
||||
uint8_t out[4];
|
||||
size_t len;
|
||||
int ret = cli_parse_hex("xyz", out, 4, &len);
|
||||
|
||||
cr_assert_eq(ret, 1);
|
||||
}
|
||||
|
||||
/* Test 12: Invalid char mid-string */
|
||||
Test(parse_hex, invalid_char_mid)
|
||||
{
|
||||
uint8_t out[4];
|
||||
size_t len;
|
||||
int ret = cli_parse_hex("de_d", out, 4, &len);
|
||||
|
||||
cr_assert_eq(ret, 1);
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue