gprs: Move TLV parser functions to gprs_utils.c and rename them

Currently the parser functions for single information elements are
defined within gprs_gb_parse.c and not exported explicitely. In
addition they are named like libosmocore's TLV parser functions and
do not have a proper name prefix. Since it is planned to use them for
other protocols, they need to be globally accessible.

This patch moves them to gprs_utils.c and renames them.

The new names are:
    lv_shift             -> gprs_shift_lv
    v_fixed_shift        -> gprs_shift_v_fixed
    lv_shift             -> gprs_shift_lv
    v_fixed_shift        -> gprs_shift_v_fixed

In the long term, these functions should be moved to libosmocore (and
renamed again).

Sponsored-by: On-Waves ehf
diff --git a/openbsc/src/gprs/gprs_utils.c b/openbsc/src/gprs/gprs_utils.c
index 0cf8e4f..cec07d7 100644
--- a/openbsc/src/gprs/gprs_utils.c
+++ b/openbsc/src/gprs/gprs_utils.c
@@ -217,3 +217,120 @@
 
 	*tmsi = ntohl(tmsi_be);
 }
+
+/* TODO: Move shift functions to libosmocore */
+
+int gprs_shift_v_fixed(uint8_t **data, size_t *data_len,
+		  size_t len, uint8_t **value)
+{
+	if (len > *data_len)
+		goto fail;
+
+	if (value)
+		*value = *data;
+
+	*data += len;
+	*data_len -= len;
+
+	return len;
+
+fail:
+	*data += *data_len;
+	*data_len = 0;
+	return -1;
+}
+
+int gprs_match_tv_fixed(uint8_t **data, size_t *data_len,
+		   uint8_t tag, size_t len,
+		   uint8_t **value)
+{
+	size_t ie_len;
+
+	if (*data_len == 0)
+		goto fail;
+
+	if ((*data)[0] != tag)
+		return 0;
+
+	if (len > *data_len - 1)
+		goto fail;
+
+	if (value)
+		*value = *data + 1;
+
+	ie_len = len + 1;
+	*data += ie_len;
+	*data_len -= ie_len;
+
+	return ie_len;
+
+fail:
+	*data += *data_len;
+	*data_len = 0;
+	return -1;
+}
+
+int gprs_match_tlv(uint8_t **data, size_t *data_len,
+	      uint8_t tag, uint8_t **value, size_t *value_len)
+{
+	size_t len;
+	size_t ie_len;
+
+	if (*data_len < 2)
+		goto fail;
+
+	if ((*data)[0] != tag)
+		return 0;
+
+	len = (*data)[1];
+	if (len > *data_len - 2)
+		goto fail;
+
+	if (value)
+		*value = *data + 2;
+	if (value_len)
+		*value_len = len;
+
+	ie_len = len + 2;
+
+	*data += ie_len;
+	*data_len -= ie_len;
+
+	return ie_len;
+
+fail:
+	*data += *data_len;
+	*data_len = 0;
+	return -1;
+}
+
+int gprs_shift_lv(uint8_t **data, size_t *data_len,
+	     uint8_t **value, size_t *value_len)
+{
+	size_t len;
+	size_t ie_len;
+
+	if (*data_len < 1)
+		goto fail;
+
+	len = (*data)[0];
+	if (len > *data_len - 1)
+		goto fail;
+
+	if (value)
+		*value = *data + 1;
+	if (value_len)
+		*value_len = len;
+
+	ie_len = len + 1;
+	*data += ie_len;
+	*data_len -= ie_len;
+
+	return ie_len;
+
+fail:
+	*data += *data_len;
+	*data_len = 0;
+	return -1;
+}
+