Add bitvec-related functions from Osmo-PCU

Allocation, pack/unpack, field access and helper routines used
extensively by Osmo-PCU. Whenever memory allocation happens, alocator
context is passed explicitly by caller.
diff --git a/src/bitvec.c b/src/bitvec.c
index 8596d51..f9341b7 100644
--- a/src/bitvec.c
+++ b/src/bitvec.c
@@ -1,6 +1,7 @@
 /* bit vector utility routines */
 
 /* (C) 2009 by Harald Welte <laforge@gnumonks.org>
+ * (C) 2012 Ivan Klyuchnikov
  * (C) 2015 by Sysmocom s.f.m.c. GmbH
  *
  * All Rights Reserved
@@ -32,6 +33,7 @@
 #include <errno.h>
 #include <stdint.h>
 #include <string.h>
+#include <stdio.h>
 
 #include <osmocom/core/bitvec.h>
 
@@ -336,4 +338,97 @@
 	bv->cur_bit += count * 8;
 	return 0;
 }
+
+struct bitvec *bitvec_alloc(unsigned int size, TALLOC_CTX *ctx)
+{
+	struct bitvec *bv = talloc_zero(ctx, struct bitvec);
+	if (!bv)
+		return NULL;
+
+	bv->data = talloc_zero_array(bv, uint8_t, size);
+	if (!(bv->data)) {
+		talloc_free(bv);
+		return NULL;
+	}
+
+	bv->data_len = size;
+	bv->cur_bit = 0;
+	return bv;
+}
+
+void bitvec_free(struct bitvec *bv)
+{
+	talloc_free(bv->data);
+	talloc_free(bv);
+}
+
+unsigned int bitvec_pack(const struct bitvec *bv, uint8_t *buffer)
+{
+	unsigned int i = 0;
+	for (i = 0; i < bv->data_len; i++)
+		buffer[i] = bv->data[i];
+
+	return i;
+}
+
+unsigned int bitvec_unpack(struct bitvec *bv, const uint8_t *buffer)
+{
+	unsigned int i = 0;
+	for (i = 0; i < bv->data_len; i++)
+		bv->data[i] = buffer[i];
+
+	return i;
+}
+
+
+int bitvec_unhex(struct bitvec *bv, const char *src)
+{
+	unsigned val;
+	unsigned write_index = 0;
+	unsigned digits = bv->data_len * 2;
+	for (unsigned i = 0; i < digits; i++) {
+		if (sscanf(src + i, "%1x", &val) < 1) {
+			return 1;
+		}
+		bitvec_write_field(bv, write_index,val, 4);
+	}
+	return 0;
+}
+
+uint64_t bitvec_read_field(struct bitvec *bv, unsigned int read_index, unsigned int len)
+{
+	unsigned int i;
+	uint64_t ui = 0;
+	bv->cur_bit = read_index;
+
+	for (i = 0; i < len; i++) {
+		int bit = bitvec_get_bit_pos((const struct bitvec *)bv, bv->cur_bit);
+		if (bit < 0)
+			return bit;
+		if (bit)
+			ui |= ((uint64_t)1 << (len - i - 1));
+		bv->cur_bit++;
+	}
+	read_index += len;
+	return ui;
+}
+
+
+int bitvec_write_field(struct bitvec *bv, unsigned int write_index, uint64_t val, unsigned int len)
+{
+	unsigned int i;
+	int rc;
+	bv->cur_bit = write_index;
+	for (i = 0; i < len; i++) {
+		int bit = 0;
+		if (val & ((uint64_t)1 << (len - i - 1)))
+			bit = 1;
+		rc = bitvec_set_bit(bv, bit);
+		if (rc)
+			return rc;
+	}
+	write_index += len;
+	return 0;
+}
+
 /*! @} */