add get_value_string_or_null() to handle unknown items

Add get_value_string_or_null() to return NULL in case the given value is not
found in the list of strings, to be able to cleanly fall back to another list
of strings. Absorb the lookup loop from get_value_string().

Context: in osmo-bts, I want to look up an RSL message name in rsl_msgt_names
and fall back to rsl_ipac_msgt_names if not found, because the IPAC PDCH ACT
and DEACT messages are sent in a standard ABIS_RSL_MDISC_DED_CHAN.
In a subsequent commit, get_value_string_or_null() will be used by new
rsl_or_ipac_msg_name().

Change-Id: I1fa3907e28d528d2758bc3eae9d19e6c1168f5e5
Reviewed-on: https://gerrit.osmocom.org/230
Reviewed-by: Harald Welte <laforge@gnumonks.org>
Tested-by: Jenkins Builder
diff --git a/src/utils.c b/src/utils.c
index e76297f..4a54802 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -50,6 +50,23 @@
  */
 const char *get_value_string(const struct value_string *vs, uint32_t val)
 {
+	const char *str = get_value_string_or_null(vs, val);
+	if (str)
+		return str;
+
+	snprintf(namebuf, sizeof(namebuf), "unknown 0x%x", val);
+	namebuf[sizeof(namebuf) - 1] = '\0';
+	return namebuf;
+}
+
+/*! \brief get human-readable string or NULL for given value
+ *  \param[in] vs Array of value_string tuples
+ *  \param[in] val Value to be converted
+ *  \returns pointer to human-readable string or NULL if val is not found
+ */
+const char *get_value_string_or_null(const struct value_string *vs,
+				     uint32_t val)
+{
 	int i;
 
 	for (i = 0;; i++) {
@@ -59,9 +76,7 @@
 			return vs[i].str;
 	}
 
-	snprintf(namebuf, sizeof(namebuf), "unknown 0x%x", val);
-	namebuf[sizeof(namebuf) - 1] = '\0';
-	return namebuf;
+	return NULL;
 }
 
 /*! \brief get numeric value for given human-readable string