diff options
| author | Neels Hofmeyr <neels@hofmeyr.de> | 2018-12-05 21:02:36 +0100 | 
|---|---|---|
| committer | Harald Welte <laforge@gnumonks.org> | 2018-12-10 17:06:30 +0000 | 
| commit | 7079e698481705c82c7aff58ea9c63469626af80 (patch) | |
| tree | 4e9ba1b40828af8cbfe97a6ce7872bfc8cbc0c66 /src | |
| parent | c01cff1a502b95ef6d5348e4b8bbfcf746b5d2e4 (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')
| -rw-r--r-- | src/utils.c | 41 | 
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  | 
