gsm: add gsm48_mnc_from_str() and gsm48_mnc_cmp(), for 3-digit MNC gsm48_mnc_from_str() preserves leading zeros in the string and is useful for VTY config parsing.
gsm48_mnc_cmp() will be used by osmo-sgsn.git Change-Id: Ib7176b1d65a03b76f41f94bc9d3293a8a07d24c6 --- M include/osmocom/gsm/gsm48.h M src/gsm/gsm48.c M src/gsm/libosmogsm.map 3 files changed, 63 insertions(+), 0 deletions(-) git pull ssh://gerrit.osmocom.org:29418/libosmocore refs/changes/63/6663/2 diff --git a/include/osmocom/gsm/gsm48.h b/include/osmocom/gsm/gsm48.h index 9d312c2..37c421d 100644 --- a/include/osmocom/gsm/gsm48.h +++ b/include/osmocom/gsm/gsm48.h @@ -63,3 +63,7 @@ void gsm48_mcc_mnc_to_bcd2(uint8_t *bcd_dst, uint16_t mcc, uint16_t mnc, bool mnc_3_digits); void gsm48_mcc_mnc_from_bcd(uint8_t *bcd_src, uint16_t *mcc, uint16_t *mnc); void gsm48_mcc_mnc_from_bcd2(uint8_t *bcd_src, uint16_t *mcc, uint16_t *mnc, bool *mnc_3_digits); + +int gsm48_mnc_from_str(const char *mnc_str, uint16_t *mnc, bool *mnc_3_digits); + +int gsm48_mnc_cmp(uint16_t a_mnc, bool a_mnc_3_digits, uint16_t b_mnc, bool b_mnc_3_digits); diff --git a/src/gsm/gsm48.c b/src/gsm/gsm48.c index 122f7ea..be2a976 100644 --- a/src/gsm/gsm48.c +++ b/src/gsm/gsm48.c @@ -530,6 +530,63 @@ } } +/* Convert string to MNC, detecting 3-digit MNC with leading zeros. + * Return mnc_3_digits as false if the MNC's most significant digit is encoded as 0xF, true + * otherwise; i.e. true if MNC > 99 or if it is represented with leading zeros instead of 0xF. + * \param mnc_str[in] String representation of an MNC, with or without leading zeros. + * \param mnc[out] MNC result buffer, or NULL. + * \param[out] mnc_3_digits Result buffer for 3-digit flag, or NULL. + * \returns zero on success, -EINVAL in case of surplus characters, negative errno in case of conversion + * errors. + */ +int gsm48_mnc_from_str(const char *mnc_str, uint16_t *mnc, bool *mnc_3_digits) +{ + uint16_t _mnc = 0; + bool _mnc_3_digits = false; + char *endptr; + int rc = 0; + + if (!mnc_str || !isdigit(mnc_str[0])) { + /* return invalid, but give strtol a shot anyway, for callers that don't want to be + * strict */ + rc = -EINVAL; + } + errno = 0; + _mnc = strtol(mnc_str, &endptr, 10); + if (errno) + rc = -errno; + else if (*endptr) + rc = -EINVAL; + _mnc_3_digits = strlen(mnc_str) > 2; + + if (mnc) + *mnc = _mnc; + if (mnc_3_digits) + *mnc_3_digits = _mnc_3_digits; + return rc; +} + +/* Compare two MNC with three-digit flag. + * The mnc_3_digits flags passed in only have an effect if the MNC are < 100, i.e. if they would amount + * to a change in leading zeros in a BCD representation. An MNC >= 100 implies three digits, and the flag + * is actually ignored. + * \param a_mnc[in] "Left" side MNC. + * \param a_mnc_3_digits[in] "Left" side three-digits flag. + * \param b_mnc[in] "Right" side MNC. + * \param b_mnc_3_digits[in] "Right" side three-digits flag. + * \returns 0 if the MNC are equal, -1 if a < b or a shorter, 1 if a > b or a longer. */ +int gsm48_mnc_cmp(uint16_t a_mnc, bool a_mnc_3_digits, uint16_t b_mnc, bool b_mnc_3_digits) +{ + if (a_mnc < b_mnc) + return -1; + if (a_mnc > b_mnc) + return 1; + /* a_mnc == b_mnc, but same amount of leading zeros? */ + if (a_mnc < 100 && a_mnc_3_digits != b_mnc_3_digits) + return a_mnc_3_digits ? 1 : -1; + return 0; +} + /*! Encode TS 04.08 Location Area Identifier, legacy implementation. * Instead use gsm48_generate_lai2(), which is capable of three-digit MNC with leading zeros. * \param[out] caller-provided memory for output diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map index 917eab2..9e3de75 100644 --- a/src/gsm/libosmogsm.map +++ b/src/gsm/libosmogsm.map @@ -272,6 +272,8 @@ osmo_mcc_mnc_name; osmo_mcc_mnc_name2; osmo_rai_name; +gsm48_mnc_from_str; +gsm48_mnc_cmp; gsm48_chan_mode_names; gsm_chan_t_names; gsm48_pdisc_names; -- To view, visit https://gerrit.osmocom.org/6663 To unsubscribe, visit https://gerrit.osmocom.org/settings Gerrit-MessageType: newpatchset Gerrit-Change-Id: Ib7176b1d65a03b76f41f94bc9d3293a8a07d24c6 Gerrit-PatchSet: 2 Gerrit-Project: libosmocore Gerrit-Branch: master Gerrit-Owner: Neels Hofmeyr <nhofm...@sysmocom.de>