This is merely a historical archive of years 2008-2021, before the migration to mailman3.
A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.
Harald Welte gerrit-no-reply at lists.osmocom.orgHarald Welte has submitted this change and it was merged. ( https://gerrit.osmocom.org/12153 ) Change subject: add osmo_bcd2str() ...................................................................... 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 --- M include/osmocom/core/utils.h M src/utils.c M tests/utils/utils_test.c M tests/utils/utils_test.ok 4 files changed, 186 insertions(+), 0 deletions(-) Approvals: Harald Welte: Looks good to me, approved Pau Espin Pedrol: Looks good to me, but someone else must approve Jenkins Builder: Verified diff --git a/include/osmocom/core/utils.h b/include/osmocom/core/utils.h index 0b54c88..04f2fb4 100644 --- a/include/osmocom/core/utils.h +++ b/include/osmocom/core/utils.h @@ -49,6 +49,8 @@ /* 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); diff --git a/src/utils.c b/src/utils.c index e6adcf8..4b4e6d2 100644 --- a/src/utils.c +++ b/src/utils.c @@ -129,6 +129,47 @@ 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 diff --git a/tests/utils/utils_test.c b/tests/utils/utils_test.c index 2bb1f9c..a773b3f 100644 --- a/tests/utils/utils_test.c +++ b/tests/utils/utils_test.c @@ -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 @@ } } +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 @@ test_ipa_ccm_id_resp_parsing(); test_is_hexstr(); bcd_test(); + bcd2str_test(); str_escape_test(); str_quote_test(); isqrt_test(); diff --git a/tests/utils/utils_test.ok b/tests/utils/utils_test.ok index 3ea8ec6..65e32ed 100644 --- a/tests/utils/utils_test.ok +++ b/tests/utils/utils_test.ok @@ -80,6 +80,35 @@ 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" -- To view, visit https://gerrit.osmocom.org/12153 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: libosmocore Gerrit-Branch: master Gerrit-MessageType: merged Gerrit-Change-Id: I86b09d37ceef33331c1a56046a5443127d6c6be0 Gerrit-Change-Number: 12153 Gerrit-PatchSet: 7 Gerrit-Owner: Neels Hofmeyr <nhofmeyr at sysmocom.de> Gerrit-Reviewer: Harald Welte <laforge at gnumonks.org> Gerrit-Reviewer: Jenkins Builder (1000002) Gerrit-Reviewer: Neels Hofmeyr <nhofmeyr at sysmocom.de> Gerrit-Reviewer: Pau Espin Pedrol <pespin at sysmocom.de> Gerrit-Reviewer: Stefan Sperling <stsp at stsp.name> -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20181210/94aeb79a/attachment.htm>