sms: Added result buffer size parameter to 7bit conv funs

The 7bit<->8bit encoding/decoding functions didn't check whether
there is still enough space in the destination buffer. Therefore a
buffer size parameter has been added to each of the functions which
is used to truncate the output if the buffer is too small.

In addition, the return value of the decoding functions has been
changed to number of characters written (excluding \0), so this
value is always equal to strlen(decoded).

The old functions are still available as wrapper functions.
diff --git a/include/osmocom/gsm/gsm_utils.h b/include/osmocom/gsm/gsm_utils.h
index 6cd46e4..c111f94 100644
--- a/include/osmocom/gsm/gsm_utils.h
+++ b/include/osmocom/gsm/gsm_utils.h
@@ -25,6 +25,7 @@
 #ifndef GSM_UTILS_H
 #define GSM_UTILS_H
 
+#include <stddef.h>
 #include <stdint.h>
 
 #define ADD_MODULO(sum, delta, modulo) do {	\
@@ -56,17 +57,54 @@
 const char *gsm_band_name(enum gsm_band band);
 enum gsm_band gsm_band_parse(const char *mhz);
 
-int gsm_7bit_decode(char *decoded, const uint8_t *user_data, uint8_t length);
-int gsm_7bit_decode_ussd(char *decoded, const uint8_t *user_data, uint8_t length);
-int gsm_7bit_decode_hdr(char *decoded, const uint8_t *user_data, uint8_t length, uint8_t ud_hdr_ind);
-int gsm_7bit_encode(uint8_t *result, const char *data);
-int gsm_7bit_encode_ussd(uint8_t *result, const char *data, int *octets_written);
-int gsm_7bit_encode_oct(uint8_t *result, const char *data, int *octets_written);
+/*!
+ * \brief Decode a sequence of GSM 03.38 encoded 7 bit characters.
+ *
+ * \param decoded	The destination buffer for the decoded characters.
+ * \param n		A maximum of n chars is written (incl. terminating \0).
+ * 			Requires n >= 1.
+ * \param user_data	A pointer to the start of the packed 7bit character
+ *			sequence.
+ * \param length	The length of the input sequence (in octets).
+ *
+ * \returns the number of (8 bit) chars written excluding the terminating \0.
+ * 	    This is the same like strlen(decoded).
+ */
+int gsm_7bit_decode_n(char *decoded, size_t n, const uint8_t *user_data, uint8_t length);
 
-/* the three functions below are helper functions and here for the unit test */
+/*!
+ * \brief Decode a sequence of 7 bit characters (USSD encoding).
+ *
+ * \see gsm_7bit_encode_n()
+ */
+int gsm_7bit_decode_n_ussd(char *decoded, size_t n, const uint8_t *user_data, uint8_t length);
+
+/**
+ * \brief Encode a text string into GSM 03.38 encoded 7 bit characters.
+ *
+ * \param result	The destination buffer for the packed 7 bit sequence.
+ * \param n		A maximum of n octets is written.
+ * \param data		A pointer to the start of the \0 terminated 8 bit character
+ *			string.
+ * \param octets_written  Iff not NULL, *octets_written will be set to the
+ *			number of octets written to the result buffer.
+ *
+ * \returns the number of septets that have been created.
+ */
+int gsm_7bit_encode_n(uint8_t *result, size_t n, const char *data, int *octets_written);
+
+/*!
+ * \brief Encode a text string into GSM 03.38 encoded 7 bit characters (USSD encoding).
+ *
+ * \see gsm_7bit_decode_n()
+ */
+int gsm_7bit_encode_n_ussd(uint8_t *result, size_t n, const char *data, int *octets_written);
+
+/* the four functions below are helper functions and here for the unit test */
 int gsm_septets2octets(uint8_t *result, const uint8_t *rdata, uint8_t septet_len, uint8_t padding);
 int gsm_septet_encode(uint8_t *result, const char *data);
 uint8_t gsm_get_octet_len(const uint8_t sept_len);
+int gsm_7bit_decode_n_hdr(char *decoded, size_t n, const uint8_t *user_data, uint8_t length, uint8_t ud_hdr_ind);
 
 unsigned int ms_class_gmsk_dbm(enum gsm_band band, int ms_class);
 
@@ -154,5 +192,12 @@
 	_GSM_LCHAN_MAX
 };
 
+/* Deprectated functions */
+int gsm_7bit_decode(char *decoded, const uint8_t *user_data, uint8_t length) __attribute__((deprecated ("Use gsm_7bit_decode_n() instead")));
+int gsm_7bit_decode_ussd(char *decoded, const uint8_t *user_data, uint8_t length) __attribute__((deprecated ("Use gsm_7bit_decode_n_ussd() instead")));
+int gsm_7bit_encode(uint8_t *result, const char *data) __attribute__((deprecated ("Use gsm_7bit_encode_n() instead")));
+int gsm_7bit_encode_ussd(uint8_t *result, const char *data, int *octets_written) __attribute__((deprecated ("Use gsm_7bit_encode_n_ussd() instead")));
+int gsm_7bit_encode_oct(uint8_t *result, const char *data, int *octets_written) __attribute__((deprecated ("Use gsm_7bit_encode_n() instead")));
+
 
 #endif