mirror of https://gerrit.osmocom.org/libosmocore
add osmo_bcd2str()
Add a standalone bcd-to-string conversion function with generic parameters. Add a regression test in utils_test.c. So far there is no single universal implementation that converts a BCD to a string. I could only find gsm48_mi_to_string(), which also interprets surrounding bytes, MI type and TMSI as non-BCD value. The idea is to use this function from gsm48_mi_to_string() and similar implementations in subsequent commits. Root cause: in osmo-msc, I want to have an alternative MI-to-string function for composing an FSM name, which needs the BCD part of gsm48_mi_to_string() but not the TMSI part. Change-Id: I86b09d37ceef33331c1a56046a5443127d6c6be0
This commit is contained in:
parent
c01cff1a50
commit
7079e69848
|
@ -49,6 +49,8 @@ char osmo_bcd2char(uint8_t bcd);
|
|||
/* only works for numbers in ascci */
|
||||
uint8_t osmo_char2bcd(char c);
|
||||
|
||||
int osmo_bcd2str(char *dst, size_t dst_size, const uint8_t *bcd, int start_nibble, int end_nibble, bool allow_hex);
|
||||
|
||||
int osmo_hexparse(const char *str, uint8_t *b, int max_len);
|
||||
|
||||
char *osmo_ubit_dump(const uint8_t *bits, unsigned int len);
|
||||
|
|
41
src/utils.c
41
src/utils.c
|
@ -129,6 +129,47 @@ uint8_t osmo_char2bcd(char c)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*! Convert BCD to string.
|
||||
* The given nibble offsets are interpreted in BCD order, i.e. nibble 0 is bcd[0] & 0xf, nibble 1 is bcd[0] >> 4, nibble
|
||||
* 3 is bcd[1] & 0xf, etc..
|
||||
* \param[out] dst Output string buffer, is always nul terminated when dst_size > 0.
|
||||
* \param[in] dst_size sizeof() the output string buffer.
|
||||
* \param[in] bcd Binary coded data buffer.
|
||||
* \param[in] start_nibble Offset to start from, in nibbles, typically 1 to skip the first nibble.
|
||||
* \param[in] end_nibble Offset to stop before, in nibbles, e.g. sizeof(bcd) - (bcd[0] & GSM_MI_ODD? 0:1).
|
||||
* \param[in] allow_hex If false, return error if there are digits other than 0-9. If true, return those as [A-F].
|
||||
* \returns The strlen that would be written if the output buffer is large enough, excluding nul byte (like
|
||||
* snprintf()), or -EINVAL if allow_hex is false and a digit > 9 is encountered. On -EINVAL, the conversion is
|
||||
* still completed as if allow_hex were passed as true. Return -ENOMEM if dst is NULL or dst_size is zero.
|
||||
* If end_nibble <= start_nibble, write an empty string to dst and return 0.
|
||||
*/
|
||||
int osmo_bcd2str(char *dst, size_t dst_size, const uint8_t *bcd, int start_nibble, int end_nibble, bool allow_hex)
|
||||
{
|
||||
char *dst_end = dst + dst_size - 1;
|
||||
int nibble_i;
|
||||
int rc = 0;
|
||||
|
||||
if (!dst || dst_size < 1)
|
||||
return -ENOMEM;
|
||||
|
||||
for (nibble_i = start_nibble; nibble_i < end_nibble && dst < dst_end; nibble_i++, dst++) {
|
||||
uint8_t nibble = bcd[nibble_i >> 1];
|
||||
if ((nibble_i & 1))
|
||||
nibble >>= 4;
|
||||
nibble &= 0xf;
|
||||
|
||||
if (!allow_hex && nibble > 9)
|
||||
rc = -EINVAL;
|
||||
|
||||
*dst = osmo_bcd2char(nibble);
|
||||
}
|
||||
*dst = '\0';
|
||||
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
return OSMO_MAX(0, end_nibble - start_nibble);
|
||||
}
|
||||
|
||||
/*! Parse a string containing hexadecimal digits
|
||||
* \param[in] str string containing ASCII encoded hexadecimal digits
|
||||
* \param[out] b output buffer
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include <time.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <errno.h>
|
||||
|
||||
static void hexdump_test(void)
|
||||
{
|
||||
|
@ -383,6 +384,118 @@ static void bcd_test(void)
|
|||
}
|
||||
}
|
||||
|
||||
struct bcd2str_test {
|
||||
const char *bcd_hex;
|
||||
int start_nibble;
|
||||
int end_nibble;
|
||||
bool allow_hex;
|
||||
size_t str_size;
|
||||
const char *expect_str;
|
||||
int expect_rc;
|
||||
};
|
||||
|
||||
static const struct bcd2str_test bcd2str_tests[] = {
|
||||
{
|
||||
.bcd_hex = "1a 32 54 76 98 f0",
|
||||
.start_nibble = 1,
|
||||
.end_nibble = 11,
|
||||
.expect_str = "1234567890",
|
||||
.expect_rc = 10,
|
||||
},
|
||||
{
|
||||
.bcd_hex = "1a 32 a4 cb 9d f0",
|
||||
.start_nibble = 1,
|
||||
.end_nibble = 11,
|
||||
.expect_str = "1234ABCD90",
|
||||
.expect_rc = -EINVAL,
|
||||
},
|
||||
{
|
||||
.bcd_hex = "1a 32 a4 cb 9d f0",
|
||||
.start_nibble = 1,
|
||||
.end_nibble = 11,
|
||||
.allow_hex = true,
|
||||
.expect_str = "1234ABCD90",
|
||||
.expect_rc = 10,
|
||||
},
|
||||
{
|
||||
.bcd_hex = "1a 32 54 76 98 f0",
|
||||
.start_nibble = 1,
|
||||
.end_nibble = 12,
|
||||
.expect_str = "1234567890F",
|
||||
.expect_rc = -EINVAL,
|
||||
},
|
||||
{
|
||||
.bcd_hex = "1a 32 54 76 98 f0",
|
||||
.start_nibble = 1,
|
||||
.end_nibble = 12,
|
||||
.allow_hex = true,
|
||||
.expect_str = "1234567890F",
|
||||
.expect_rc = 11,
|
||||
},
|
||||
{
|
||||
.bcd_hex = "1a 32 54 76 98 f0",
|
||||
.start_nibble = 0,
|
||||
.end_nibble = 12,
|
||||
.allow_hex = true,
|
||||
.expect_str = "A1234567890F",
|
||||
.expect_rc = 12,
|
||||
},
|
||||
{
|
||||
.bcd_hex = "1a 32 54 76 98 f0",
|
||||
.start_nibble = 1,
|
||||
.end_nibble = 12,
|
||||
.str_size = 5,
|
||||
.expect_str = "1234",
|
||||
.expect_rc = 11,
|
||||
},
|
||||
{
|
||||
.bcd_hex = "",
|
||||
.start_nibble = 1,
|
||||
.end_nibble = 1,
|
||||
.expect_str = "",
|
||||
.expect_rc = 0,
|
||||
},
|
||||
};
|
||||
|
||||
static void bcd2str_test(void)
|
||||
{
|
||||
int i;
|
||||
uint8_t bcd[64];
|
||||
int rc;
|
||||
|
||||
printf("\nTesting bcd to string conversion\n");
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(bcd2str_tests); i++) {
|
||||
const struct bcd2str_test *t = &bcd2str_tests[i];
|
||||
char str[64] = {};
|
||||
size_t str_size = t->str_size ? : sizeof(str);
|
||||
|
||||
osmo_hexparse(t->bcd_hex, bcd, sizeof(bcd));
|
||||
|
||||
printf("- BCD-input='%s' nibbles=[%d..%d[ str_size=%zu\n", t->bcd_hex,
|
||||
t->start_nibble, t->end_nibble, str_size);
|
||||
rc = osmo_bcd2str(str, str_size, bcd, t->start_nibble, t->end_nibble, t->allow_hex);
|
||||
|
||||
printf(" rc=%d\n", rc);
|
||||
|
||||
OSMO_ASSERT(str[str_size-1] == '\0');
|
||||
printf(" -> %s\n", osmo_quote_str(str, -1));
|
||||
|
||||
if (rc != t->expect_rc)
|
||||
printf(" ERROR: expected rc=%d\n", t->expect_rc);
|
||||
if (strcmp(str, t->expect_str))
|
||||
printf(" ERROR: expected result %s\n", osmo_quote_str(t->expect_str, -1));
|
||||
}
|
||||
|
||||
printf("- zero output buffer\n");
|
||||
rc = osmo_bcd2str(NULL, 100, bcd, 1, 2, false);
|
||||
printf(" bcd2str(NULL, ...) -> %d\n", rc);
|
||||
OSMO_ASSERT(rc < 0);
|
||||
rc = osmo_bcd2str((char*)23, 0, bcd, 1, 2, false);
|
||||
printf(" bcd2str(dst, 0, ...) -> %d\n", rc);
|
||||
OSMO_ASSERT(rc < 0);
|
||||
}
|
||||
|
||||
static void str_escape_test(void)
|
||||
{
|
||||
int i;
|
||||
|
@ -810,6 +923,7 @@ int main(int argc, char **argv)
|
|||
test_ipa_ccm_id_resp_parsing();
|
||||
test_is_hexstr();
|
||||
bcd_test();
|
||||
bcd2str_test();
|
||||
str_escape_test();
|
||||
str_quote_test();
|
||||
isqrt_test();
|
||||
|
|
|
@ -80,6 +80,35 @@ Testing BCD conversion
|
|||
val=0xe, expected=E, found=E
|
||||
val=0xf, expected=F, found=F
|
||||
|
||||
Testing bcd to string conversion
|
||||
- BCD-input='1a 32 54 76 98 f0' nibbles=[1..11[ str_size=64
|
||||
rc=10
|
||||
-> "1234567890"
|
||||
- BCD-input='1a 32 a4 cb 9d f0' nibbles=[1..11[ str_size=64
|
||||
rc=-22
|
||||
-> "1234ABCD90"
|
||||
- BCD-input='1a 32 a4 cb 9d f0' nibbles=[1..11[ str_size=64
|
||||
rc=10
|
||||
-> "1234ABCD90"
|
||||
- BCD-input='1a 32 54 76 98 f0' nibbles=[1..12[ str_size=64
|
||||
rc=-22
|
||||
-> "1234567890F"
|
||||
- BCD-input='1a 32 54 76 98 f0' nibbles=[1..12[ str_size=64
|
||||
rc=11
|
||||
-> "1234567890F"
|
||||
- BCD-input='1a 32 54 76 98 f0' nibbles=[0..12[ str_size=64
|
||||
rc=12
|
||||
-> "A1234567890F"
|
||||
- BCD-input='1a 32 54 76 98 f0' nibbles=[1..12[ str_size=5
|
||||
rc=11
|
||||
-> "1234"
|
||||
- BCD-input='' nibbles=[1..1[ str_size=64
|
||||
rc=0
|
||||
-> ""
|
||||
- zero output buffer
|
||||
bcd2str(NULL, ...) -> -12
|
||||
bcd2str(dst, 0, ...) -> -12
|
||||
|
||||
Testing string escaping
|
||||
- all chars from 0 to 255 in batches of 16:
|
||||
"\0\1\2\3\4\5\6\a\b\t\n\v\f\r\14\15"
|
||||
|
|
Loading…
Reference in New Issue