aboutsummaryrefslogtreecommitdiffstats
path: root/src/utils.c
diff options
context:
space:
mode:
authorNeels Hofmeyr <neels@hofmeyr.de>2018-12-05 21:02:36 +0100
committerHarald Welte <laforge@gnumonks.org>2018-12-10 17:06:30 +0000
commit7079e698481705c82c7aff58ea9c63469626af80 (patch)
tree4e9ba1b40828af8cbfe97a6ce7872bfc8cbc0c66 /src/utils.c
parentc01cff1a502b95ef6d5348e4b8bbfcf746b5d2e4 (diff)
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
Diffstat (limited to 'src/utils.c')
-rw-r--r--src/utils.c41
1 files changed, 41 insertions, 0 deletions
diff --git a/src/utils.c b/src/utils.c
index e6adcf86..4b4e6d25 100644
--- a/src/utils.c
+++ b/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