add osmo_str_tolower() and _toupper() with test

We already have osmo_str2lower() and osmo_str2upper(), but these lack:
* proper destination buffer bounds checking,
* ability to call directly as printf() argument.

Deprecate osmo_str2upper() and osmo_str2lower() because of missing bounds
checking.

Introduce osmo_str_tolower_buf(), osmo_str_toupper_buf() to provide
bounds-safe conversion, also able to safely convert a buffer in-place.

Introduce osmo_str_tolower(), osmo_str_toupper() that call the above _buf()
equivalents using a static buffer[128] and returning the resulting string
directly, convenient for direct printing. Possibly truncated but always safe.

Add unit tests to utils_test.c.

Replace all libosmocore uses of now deprecated osmo_str2lower().

Naming: the ctype.h API is called tolower() and toupper(), so just prepend
'osmo_str_' and don't separate 'to_lower'.

Change-Id: Ib0ee1206b9f31d7ba25c31f8008119ac55440797
diff --git a/src/utils.c b/src/utils.c
index 3f40f2e..e6adcf8 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -638,4 +638,90 @@
 	return g0;
 }
 
+/*! Convert a string to lowercase, while checking buffer size boundaries.
+ * The result written to \a dest is guaranteed to be nul terminated if \a dest_len > 0.
+ * If dest == src, the string is converted in-place, if necessary truncated at dest_len - 1 characters
+ * length as well as nul terminated.
+ * Note: similar osmo_str2lower(), but safe to use for src strings of arbitrary length.
+ *  \param[out] dest  Target buffer to write lowercase string.
+ *  \param[in] dest_len  Maximum buffer size of dest (e.g. sizeof(dest)).
+ *  \param[in] src  String to convert to lowercase.
+ *  \returns Length of \a src, like osmo_strlcpy(), but if \a dest == \a src at most \a dest_len - 1.
+ */
+size_t osmo_str_tolower_buf(char *dest, size_t dest_len, const char *src)
+{
+	size_t rc;
+	if (dest == src) {
+		if (dest_len < 1)
+			return 0;
+		dest[dest_len - 1] = '\0';
+		rc = strlen(dest);
+	} else {
+		if (dest_len < 1)
+			return strlen(src);
+		rc = osmo_strlcpy(dest, src, dest_len);
+	}
+	for (; *dest; dest++)
+		*dest = tolower(*dest);
+	return rc;
+}
+
+/*! Convert a string to lowercase, using a static buffer.
+ * The resulting string may be truncated if the internally used static buffer is shorter than src.
+ * The internal buffer is at least 128 bytes long, i.e. guaranteed to hold at least 127 characters and a
+ * terminating nul.
+ * See also osmo_str_tolower_buf().
+ * \param[in] src  String to convert to lowercase.
+ * \returns Resulting lowercase string in a static buffer, always nul terminated.
+ */
+const char *osmo_str_tolower(const char *src)
+{
+	static char buf[128];
+	osmo_str_tolower_buf(buf, sizeof(buf), src);
+	return buf;
+}
+
+/*! Convert a string to uppercase, while checking buffer size boundaries.
+ * The result written to \a dest is guaranteed to be nul terminated if \a dest_len > 0.
+ * If dest == src, the string is converted in-place, if necessary truncated at dest_len - 1 characters
+ * length as well as nul terminated.
+ * Note: similar osmo_str2upper(), but safe to use for src strings of arbitrary length.
+ *  \param[out] dest  Target buffer to write uppercase string.
+ *  \param[in] dest_len  Maximum buffer size of dest (e.g. sizeof(dest)).
+ *  \param[in] src  String to convert to uppercase.
+ *  \returns Length of \a src, like osmo_strlcpy(), but if \a dest == \a src at most \a dest_len - 1.
+ */
+size_t osmo_str_toupper_buf(char *dest, size_t dest_len, const char *src)
+{
+	size_t rc;
+	if (dest == src) {
+		if (dest_len < 1)
+			return 0;
+		dest[dest_len - 1] = '\0';
+		rc = strlen(dest);
+	} else {
+		if (dest_len < 1)
+			return strlen(src);
+		rc = osmo_strlcpy(dest, src, dest_len);
+	}
+	for (; *dest; dest++)
+		*dest = toupper(*dest);
+	return rc;
+}
+
+/*! Convert a string to uppercase, using a static buffer.
+ * The resulting string may be truncated if the internally used static buffer is shorter than src.
+ * The internal buffer is at least 128 bytes long, i.e. guaranteed to hold at least 127 characters and a
+ * terminating nul.
+ * See also osmo_str_toupper_buf().
+ * \param[in] src  String to convert to uppercase.
+ * \returns Resulting uppercase string in a static buffer, always nul terminated.
+ */
+const char *osmo_str_toupper(const char *src)
+{
+	static char buf[128];
+	osmo_str_toupper_buf(buf, sizeof(buf), src);
+	return buf;
+}
+
 /*! @} */