summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMax <msuraev@sysmocom.de>2016-03-17 11:51:08 +0100
committerHarald Welte <laforge@gnumonks.org>2016-03-17 14:07:19 +0100
commitd4793212b5026fed01d132fa7397cc0ff2f543fe (patch)
tree658148bbf3d49be9e5387516188ad175ea79333b /src
parentbdccc1b1444a8692697bd8a293cc89c90ef2d832 (diff)
Add function to add bits from array to bitvec
Add function which adds specified number of bits from each element of array to the bit vector prefixing each addition with one and finishing entire sequence with adding 0. This is very common patter for various repetitive data structures described with CSN.1 in 3GPP standards. Corresponding test vectors and doxygen headers are added too.
Diffstat (limited to 'src')
-rw-r--r--src/bitvec.c40
1 files changed, 40 insertions, 0 deletions
diff --git a/src/bitvec.c b/src/bitvec.c
index 00ae1505..a92fd716 100644
--- a/src/bitvec.c
+++ b/src/bitvec.c
@@ -570,4 +570,44 @@ void bitvec_shiftl(struct bitvec *bv, unsigned n)
bv->cur_bit -= n;
}
+/*! \brief Add given array to bitvec
+ * \param[in,out] bv bit vector to work with
+ * \param[in] array elements to be added
+ * \param[in] array_len length of array
+ * \param[in] dry_run indicates whether to return number of bits required
+ * instead of adding anything to bv for real
+ * \param[in] num_bits number of bits to consider in each element of array
+ * \returns number of bits necessary to add array elements if dry_run is true,
+ * 0 otherwise (only in this case bv is actually changed)
+ *
+ * N. B: no length checks are performed on bv - it's caller's job to ensure
+ * enough space is available - for example by calling with dry_run = true first.
+ *
+ * Useful for common pattern in CSN.1 spec which looks like:
+ * { 1 < XXX : bit (num_bits) > } ** 0
+ * which means repeat any times (between 0 and infinity),
+ * start each repetition with 1, mark end of repetitions with 0 bit
+ * see app. note in 3GPP TS 24.007 ยง B.2.1 Rule A2
+ */
+unsigned int bitvec_add_array(struct bitvec *bv, const uint32_t *array,
+ unsigned int array_len, bool dry_run,
+ unsigned int num_bits)
+{
+ unsigned i, bits = 1; /* account for stop bit */
+ for (i = 0; i < array_len; i++) {
+ if (dry_run) {
+ bits += (1 + num_bits);
+ } else {
+ bitvec_set_bit(bv, 1);
+ bitvec_set_uint(bv, array[i], num_bits);
+ }
+ }
+
+ if (dry_run)
+ return bits;
+
+ bitvec_set_bit(bv, 0); /* stop bit - end of the sequence */
+ return 0;
+}
+
/*! @} */