blob: f07b42c391ea05e284124f8f461be7a2aa5e9b84 [file] [log] [blame]
Harald Welteec8b4502010-02-20 20:34:29 +01001/* (C) 2009 by Harald Welte <laforge@gnumonks.org>
Maxa15f05f2016-01-26 10:43:15 +01002 * (C) 2012 Ivan Klyuchnikov
Jacob Erlbeck5f349be2015-12-21 16:04:03 +01003 * (C) 2015 by Sysmocom s.f.m.c. GmbH
Harald Welteec8b4502010-02-20 20:34:29 +01004 *
5 * All Rights Reserved
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 */
22
Harald Welteba6988b2011-08-17 12:46:48 +020023/*! \addtogroup bitvec
24 * @{
Neels Hofmeyr17518fe2017-06-20 04:35:06 +020025 * Osmocom bit vector abstraction utility routines.
26 *
27 * These functions assume a MSB (most significant bit) first layout of the
28 * bits, so that for instance the 5 bit number abcde (a is MSB) can be
29 * embedded into a byte sequence like in xxxxxxab cdexxxxx. The bit count
30 * starts with the MSB, so the bits in a byte are numbered (MSB) 01234567 (LSB).
31 * Note that there are other incompatible encodings, like it is used
32 * for the EGPRS RLC data block headers (there the bits are numbered from LSB
33 * to MSB).
34 *
35 * \file bitvec.c */
Harald Welte96e2a002017-06-12 21:44:18 +020036
Harald Welteec8b4502010-02-20 20:34:29 +010037#include <errno.h>
38#include <stdint.h>
Jacob Erlbeck5f349be2015-12-21 16:04:03 +010039#include <string.h>
Maxa15f05f2016-01-26 10:43:15 +010040#include <stdio.h>
Max0a59e982016-02-05 13:55:37 +010041#include <stdbool.h>
Harald Welteec8b4502010-02-20 20:34:29 +010042
Max0a59e982016-02-05 13:55:37 +010043#include <osmocom/core/bits.h>
Pablo Neira Ayuso83419342011-03-22 16:36:13 +010044#include <osmocom/core/bitvec.h>
Harald Welteec8b4502010-02-20 20:34:29 +010045
46#define BITNUM_FROM_COMP(byte, bit) ((byte*8)+bit)
47
48static inline unsigned int bytenum_from_bitnum(unsigned int bitnum)
49{
50 unsigned int bytenum = bitnum / 8;
51
52 return bytenum;
53}
54
55/* convert ZERO/ONE/L/H to a bitmask at given pos in a byte */
56static uint8_t bitval2mask(enum bit_value bit, uint8_t bitnum)
57{
58 int bitval;
59
60 switch (bit) {
61 case ZERO:
62 bitval = (0 << bitnum);
63 break;
64 case ONE:
65 bitval = (1 << bitnum);
66 break;
67 case L:
68 bitval = ((0x2b ^ (0 << bitnum)) & (1 << bitnum));
69 break;
70 case H:
71 bitval = ((0x2b ^ (1 << bitnum)) & (1 << bitnum));
72 break;
73 default:
74 return 0;
75 }
76 return bitval;
77}
78
Neels Hofmeyr87e45502017-06-20 00:17:59 +020079/*! check if the bit is 0 or 1 for a given position inside a bitvec
Harald Welteba6988b2011-08-17 12:46:48 +020080 * \param[in] bv the bit vector on which to check
81 * \param[in] bitnr the bit number inside the bit vector to check
Harald Welte2d2e2cc2016-04-25 12:11:20 +020082 * \return value of the requested bit
Harald Welteba6988b2011-08-17 12:46:48 +020083 */
Harald Welted9abf012010-03-06 11:28:49 +010084enum bit_value bitvec_get_bit_pos(const struct bitvec *bv, unsigned int bitnr)
Harald Welteec8b4502010-02-20 20:34:29 +010085{
86 unsigned int bytenum = bytenum_from_bitnum(bitnr);
87 unsigned int bitnum = 7 - (bitnr % 8);
88 uint8_t bitval;
89
90 if (bytenum >= bv->data_len)
91 return -EINVAL;
92
93 bitval = bitval2mask(ONE, bitnum);
94
95 if (bv->data[bytenum] & bitval)
96 return ONE;
97
98 return ZERO;
99}
100
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200101/*! check if the bit is L or H for a given position inside a bitvec
Harald Welteba6988b2011-08-17 12:46:48 +0200102 * \param[in] bv the bit vector on which to check
103 * \param[in] bitnr the bit number inside the bit vector to check
Harald Welte2d2e2cc2016-04-25 12:11:20 +0200104 * \return value of the requested bit
Harald Welteba6988b2011-08-17 12:46:48 +0200105 */
Andreas.Eversberg0ebd6882010-05-09 09:36:54 +0000106enum bit_value bitvec_get_bit_pos_high(const struct bitvec *bv,
107 unsigned int bitnr)
108{
109 unsigned int bytenum = bytenum_from_bitnum(bitnr);
110 unsigned int bitnum = 7 - (bitnr % 8);
111 uint8_t bitval;
112
113 if (bytenum >= bv->data_len)
114 return -EINVAL;
115
116 bitval = bitval2mask(H, bitnum);
117
Andreas.Eversbergdc0ebdf2010-10-24 11:59:33 +0200118 if ((bv->data[bytenum] & (1 << bitnum)) == bitval)
Andreas.Eversberg0ebd6882010-05-09 09:36:54 +0000119 return H;
120
121 return L;
122}
123
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200124/*! get the Nth set bit inside the bit vector
Harald Welteba6988b2011-08-17 12:46:48 +0200125 * \param[in] bv the bit vector to use
126 * \param[in] n the bit number to get
127 * \returns the bit number (offset) of the Nth set bit in \a bv
128 */
Harald Welted9abf012010-03-06 11:28:49 +0100129unsigned int bitvec_get_nth_set_bit(const struct bitvec *bv, unsigned int n)
Harald Welteec8b4502010-02-20 20:34:29 +0100130{
131 unsigned int i, k = 0;
132
133 for (i = 0; i < bv->data_len*8; i++) {
134 if (bitvec_get_bit_pos(bv, i) == ONE) {
135 k++;
136 if (k == n)
137 return i;
138 }
139 }
140
141 return 0;
142}
143
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200144/*! set a bit at given position in a bit vector
Harald Welteba6988b2011-08-17 12:46:48 +0200145 * \param[in] bv bit vector on which to operate
Katerina Barone-Adesic28c6a02013-02-15 13:27:59 +0100146 * \param[in] bitnr number of bit to be set
Harald Welteba6988b2011-08-17 12:46:48 +0200147 * \param[in] bit value to which the bit is to be set
Max912bc6f2016-01-28 12:07:12 +0100148 * \returns 0 on success, negative value on error
Harald Welteba6988b2011-08-17 12:46:48 +0200149 */
Holger Hans Peter Freyther511b4482016-07-13 12:26:10 +0200150inline int bitvec_set_bit_pos(struct bitvec *bv, unsigned int bitnr,
Harald Welteec8b4502010-02-20 20:34:29 +0100151 enum bit_value bit)
152{
153 unsigned int bytenum = bytenum_from_bitnum(bitnr);
154 unsigned int bitnum = 7 - (bitnr % 8);
155 uint8_t bitval;
156
157 if (bytenum >= bv->data_len)
158 return -EINVAL;
159
160 /* first clear the bit */
161 bitval = bitval2mask(ONE, bitnum);
162 bv->data[bytenum] &= ~bitval;
163
164 /* then set it to desired value */
165 bitval = bitval2mask(bit, bitnum);
166 bv->data[bytenum] |= bitval;
167
168 return 0;
169}
170
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200171/*! set the next bit inside a bitvec
Harald Welteba6988b2011-08-17 12:46:48 +0200172 * \param[in] bv bit vector to be used
173 * \param[in] bit value of the bit to be set
Max912bc6f2016-01-28 12:07:12 +0100174 * \returns 0 on success, negative value on error
Harald Welteba6988b2011-08-17 12:46:48 +0200175 */
Holger Hans Peter Freyther511b4482016-07-13 12:26:10 +0200176inline int bitvec_set_bit(struct bitvec *bv, enum bit_value bit)
Harald Welteec8b4502010-02-20 20:34:29 +0100177{
178 int rc;
179
180 rc = bitvec_set_bit_pos(bv, bv->cur_bit, bit);
181 if (!rc)
182 bv->cur_bit++;
183
184 return rc;
185}
186
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200187/*! get the next bit (low/high) inside a bitvec
Harald Welte2d2e2cc2016-04-25 12:11:20 +0200188 * \return value of th next bit in the vector */
Andreas.Eversberg0ebd6882010-05-09 09:36:54 +0000189int bitvec_get_bit_high(struct bitvec *bv)
190{
191 int rc;
192
193 rc = bitvec_get_bit_pos_high(bv, bv->cur_bit);
194 if (rc >= 0)
195 bv->cur_bit++;
196
197 return rc;
198}
199
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200200/*! set multiple bits (based on array of bitvals) at current pos
Harald Welteba6988b2011-08-17 12:46:48 +0200201 * \param[in] bv bit vector
202 * \param[in] bits array of \ref bit_value
203 * \param[in] count number of bits to set
Harald Welte2d2e2cc2016-04-25 12:11:20 +0200204 * \return 0 on success; negative in case of error */
Harald Welte14bf28a2016-06-27 15:19:10 +0200205int bitvec_set_bits(struct bitvec *bv, const enum bit_value *bits, unsigned int count)
Harald Welteec8b4502010-02-20 20:34:29 +0100206{
207 int i, rc;
208
209 for (i = 0; i < count; i++) {
210 rc = bitvec_set_bit(bv, bits[i]);
211 if (rc)
212 return rc;
213 }
214
215 return 0;
216}
217
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200218/*! set multiple bits (based on numeric value) at current pos
Harald Welte2d2e2cc2016-04-25 12:11:20 +0200219 * \return 0 in case of success; negative in case of error */
Maxe49af082016-01-22 16:46:56 +0100220int bitvec_set_uint(struct bitvec *bv, unsigned int ui, unsigned int num_bits)
Harald Welteec8b4502010-02-20 20:34:29 +0100221{
Maxe49af082016-01-22 16:46:56 +0100222 int rc;
223 unsigned i;
Harald Welteec8b4502010-02-20 20:34:29 +0100224 for (i = 0; i < num_bits; i++) {
225 int bit = 0;
Holger Hans Peter Freytherab0eb962016-02-18 20:28:25 +0100226 if (ui & (1u << (num_bits - i - 1)))
Harald Welteec8b4502010-02-20 20:34:29 +0100227 bit = 1;
228 rc = bitvec_set_bit(bv, bit);
229 if (rc)
230 return rc;
231 }
232
233 return 0;
234}
235
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200236/*! get multiple bits (num_bits) from beginning of vector (MSB side)
Harald Welte2d2e2cc2016-04-25 12:11:20 +0200237 * \return 16bit signed integer retrieved from bit vector */
Max0a59e982016-02-05 13:55:37 +0100238int16_t bitvec_get_int16_msb(const struct bitvec *bv, unsigned int num_bits)
239{
240 if (num_bits > 15 || bv->cur_bit < num_bits)
241 return -EINVAL;
242
243 if (num_bits < 9)
244 return bv->data[0] >> (8 - num_bits);
245
246 return osmo_load16be(bv->data) >> (16 - num_bits);
247}
248
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200249/*! get multiple bits (based on numeric value) from current pos
Harald Welte2d2e2cc2016-04-25 12:11:20 +0200250 * \return integer value retrieved from bit vector */
Maxe49af082016-01-22 16:46:56 +0100251int bitvec_get_uint(struct bitvec *bv, unsigned int num_bits)
Andreas.Eversberg0ebd6882010-05-09 09:36:54 +0000252{
253 int i;
254 unsigned int ui = 0;
255
256 for (i = 0; i < num_bits; i++) {
257 int bit = bitvec_get_bit_pos(bv, bv->cur_bit);
258 if (bit < 0)
259 return bit;
260 if (bit)
261 ui |= (1 << (num_bits - i - 1));
262 bv->cur_bit++;
263 }
264
265 return ui;
266}
267
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200268/*! fill num_bits with \fill starting from the current position
Harald Welte2d2e2cc2016-04-25 12:11:20 +0200269 * \return 0 on success; negative otherwise (out of vector boundary)
Max0a59e982016-02-05 13:55:37 +0100270 */
271int bitvec_fill(struct bitvec *bv, unsigned int num_bits, enum bit_value fill)
272{
273 unsigned i, stop = bv->cur_bit + num_bits;
274 for (i = bv->cur_bit; i < stop; i++)
275 if (bitvec_set_bit(bv, fill) < 0)
276 return -EINVAL;
277
278 return 0;
279}
280
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200281/*! pad all remaining bits up to num_bits
Harald Welte2d2e2cc2016-04-25 12:11:20 +0200282 * \return 0 on success; negative otherwise */
Harald Welteec8b4502010-02-20 20:34:29 +0100283int bitvec_spare_padding(struct bitvec *bv, unsigned int up_to_bit)
284{
Max0a59e982016-02-05 13:55:37 +0100285 int n = up_to_bit - bv->cur_bit + 1;
286 if (n < 1)
287 return 0;
Harald Welteec8b4502010-02-20 20:34:29 +0100288
Max0a59e982016-02-05 13:55:37 +0100289 return bitvec_fill(bv, n, L);
Harald Welteec8b4502010-02-20 20:34:29 +0100290}
Pablo Neira Ayuso36bdf2c2011-03-28 19:24:19 +0200291
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200292/*! find first bit set in bit vector
Harald Welte2d2e2cc2016-04-25 12:11:20 +0200293 * \return 0 on success; negative otherwise */
Pablo Neira Ayuso36bdf2c2011-03-28 19:24:19 +0200294int bitvec_find_bit_pos(const struct bitvec *bv, unsigned int n,
295 enum bit_value val)
296{
297 unsigned int i;
298
299 for (i = n; i < bv->data_len*8; i++) {
300 if (bitvec_get_bit_pos(bv, i) == val)
301 return i;
302 }
303
304 return -1;
305}
Harald Welteba6988b2011-08-17 12:46:48 +0200306
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200307/*! get multiple bytes from current pos
Jacob Erlbeck5f349be2015-12-21 16:04:03 +0100308 * Assumes MSB first encoding.
309 * \param[in] bv bit vector
310 * \param[in] bytes array
311 * \param[in] count number of bytes to copy
Harald Welte2d2e2cc2016-04-25 12:11:20 +0200312 * \return 0 on success; negative otherwise
Jacob Erlbeck5f349be2015-12-21 16:04:03 +0100313 */
Maxe49af082016-01-22 16:46:56 +0100314int bitvec_get_bytes(struct bitvec *bv, uint8_t *bytes, unsigned int count)
Jacob Erlbeck5f349be2015-12-21 16:04:03 +0100315{
316 int byte_offs = bytenum_from_bitnum(bv->cur_bit);
317 int bit_offs = bv->cur_bit % 8;
318 uint8_t c, last_c;
319 int i;
320 uint8_t *src;
321
322 if (byte_offs + count + (bit_offs ? 1 : 0) > bv->data_len)
323 return -EINVAL;
324
325 if (bit_offs == 0) {
326 memcpy(bytes, bv->data + byte_offs, count);
327 } else {
328 src = bv->data + byte_offs;
329 last_c = *(src++);
330 for (i = count; i > 0; i--) {
331 c = *(src++);
332 *(bytes++) =
333 (last_c << bit_offs) |
334 (c >> (8 - bit_offs));
335 last_c = c;
336 }
337 }
338
339 bv->cur_bit += count * 8;
340 return 0;
341}
342
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200343/*! set multiple bytes at current pos
Jacob Erlbeck5f349be2015-12-21 16:04:03 +0100344 * Assumes MSB first encoding.
345 * \param[in] bv bit vector
346 * \param[in] bytes array
347 * \param[in] count number of bytes to copy
Harald Welte2d2e2cc2016-04-25 12:11:20 +0200348 * \return 0 on success; negative otherwise
Jacob Erlbeck5f349be2015-12-21 16:04:03 +0100349 */
Maxe49af082016-01-22 16:46:56 +0100350int bitvec_set_bytes(struct bitvec *bv, const uint8_t *bytes, unsigned int count)
Jacob Erlbeck5f349be2015-12-21 16:04:03 +0100351{
352 int byte_offs = bytenum_from_bitnum(bv->cur_bit);
353 int bit_offs = bv->cur_bit % 8;
354 uint8_t c, last_c;
355 int i;
356 uint8_t *dst;
357
358 if (byte_offs + count + (bit_offs ? 1 : 0) > bv->data_len)
359 return -EINVAL;
360
361 if (bit_offs == 0) {
362 memcpy(bv->data + byte_offs, bytes, count);
363 } else if (count > 0) {
364 dst = bv->data + byte_offs;
365 /* Get lower bits of first dst byte */
366 last_c = *dst >> (8 - bit_offs);
367 for (i = count; i > 0; i--) {
368 c = *(bytes++);
369 *(dst++) =
370 (last_c << (8 - bit_offs)) |
371 (c >> bit_offs);
372 last_c = c;
373 }
374 /* Overwrite lower bits of N+1 dst byte */
375 *dst = (*dst & ((1 << (8 - bit_offs)) - 1)) |
376 (last_c << (8 - bit_offs));
377 }
378
379 bv->cur_bit += count * 8;
380 return 0;
381}
Maxa15f05f2016-01-26 10:43:15 +0100382
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200383/*! Allocate a bit vector
Harald Welte2d2e2cc2016-04-25 12:11:20 +0200384 * \param[in] size Number of bits in the vector
385 * \param[in] ctx Context from which to allocate
386 * \return pointer to allocated vector; NULL in case of error */
Maxa15f05f2016-01-26 10:43:15 +0100387struct bitvec *bitvec_alloc(unsigned int size, TALLOC_CTX *ctx)
388{
389 struct bitvec *bv = talloc_zero(ctx, struct bitvec);
390 if (!bv)
391 return NULL;
392
393 bv->data = talloc_zero_array(bv, uint8_t, size);
394 if (!(bv->data)) {
395 talloc_free(bv);
396 return NULL;
397 }
398
399 bv->data_len = size;
400 bv->cur_bit = 0;
401 return bv;
402}
403
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200404/*! Free a bit vector (release its memory)
Harald Welte2d2e2cc2016-04-25 12:11:20 +0200405 * \param[in] bit vector to free */
Maxa15f05f2016-01-26 10:43:15 +0100406void bitvec_free(struct bitvec *bv)
407{
408 talloc_free(bv->data);
409 talloc_free(bv);
410}
411
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200412/*! Export a bit vector to a buffer
Harald Welte2d2e2cc2016-04-25 12:11:20 +0200413 * \param[in] bitvec (unpacked bits)
414 * \param[out] buffer for the unpacked bits
415 * \return number of bytes (= bits) copied */
Maxa15f05f2016-01-26 10:43:15 +0100416unsigned int bitvec_pack(const struct bitvec *bv, uint8_t *buffer)
417{
418 unsigned int i = 0;
419 for (i = 0; i < bv->data_len; i++)
420 buffer[i] = bv->data[i];
421
422 return i;
423}
424
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200425/*! Copy buffer of unpacked bits into bit vector
Harald Welte2d2e2cc2016-04-25 12:11:20 +0200426 * \param[in] buffer unpacked input bits
427 * \param[out] bv unpacked bit vector
428 * \return number of bytes (= bits) copied */
Maxa15f05f2016-01-26 10:43:15 +0100429unsigned int bitvec_unpack(struct bitvec *bv, const uint8_t *buffer)
430{
431 unsigned int i = 0;
432 for (i = 0; i < bv->data_len; i++)
433 bv->data[i] = buffer[i];
434
435 return i;
436}
437
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200438/*! read hexadecimap string into a bit vector
Harald Welte2d2e2cc2016-04-25 12:11:20 +0200439 * \param[in] src string containing hex digits
440 * \param[out] bv unpacked bit vector
441 * \return 0 in case of success; 1 in case of error
442 */
Maxa15f05f2016-01-26 10:43:15 +0100443int bitvec_unhex(struct bitvec *bv, const char *src)
444{
Holger Hans Peter Freyther2745b482016-01-27 17:08:02 +0100445 unsigned i;
Maxa15f05f2016-01-26 10:43:15 +0100446 unsigned val;
447 unsigned write_index = 0;
448 unsigned digits = bv->data_len * 2;
Holger Hans Peter Freyther2745b482016-01-27 17:08:02 +0100449
450 for (i = 0; i < digits; i++) {
Maxa15f05f2016-01-26 10:43:15 +0100451 if (sscanf(src + i, "%1x", &val) < 1) {
452 return 1;
453 }
Holger Hans Peter Freythera9301a12016-01-30 10:54:43 +0100454 bitvec_write_field(bv, &write_index, val, 4);
Maxa15f05f2016-01-26 10:43:15 +0100455 }
456 return 0;
457}
458
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200459/*! read part of the vector
Max912bc6f2016-01-28 12:07:12 +0100460 * \param[in] bv The boolean vector to work on
Holger Hans Peter Freythera9301a12016-01-30 10:54:43 +0100461 * \param[in,out] read_index Where reading supposed to start in the vector
Max912bc6f2016-01-28 12:07:12 +0100462 * \param[in] len How many bits to read from vector
463 * \returns read bits or negative value on error
464 */
Holger Hans Peter Freythera9301a12016-01-30 10:54:43 +0100465uint64_t bitvec_read_field(struct bitvec *bv, unsigned int *read_index, unsigned int len)
Maxa15f05f2016-01-26 10:43:15 +0100466{
467 unsigned int i;
468 uint64_t ui = 0;
Holger Hans Peter Freythera9301a12016-01-30 10:54:43 +0100469 bv->cur_bit = *read_index;
Maxa15f05f2016-01-26 10:43:15 +0100470
471 for (i = 0; i < len; i++) {
472 int bit = bitvec_get_bit_pos((const struct bitvec *)bv, bv->cur_bit);
473 if (bit < 0)
474 return bit;
475 if (bit)
476 ui |= ((uint64_t)1 << (len - i - 1));
477 bv->cur_bit++;
478 }
Holger Hans Peter Freythera9301a12016-01-30 10:54:43 +0100479 *read_index += len;
Maxa15f05f2016-01-26 10:43:15 +0100480 return ui;
481}
482
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200483/*! write into the vector
Max912bc6f2016-01-28 12:07:12 +0100484 * \param[in] bv The boolean vector to work on
Holger Hans Peter Freythera9301a12016-01-30 10:54:43 +0100485 * \param[in,out] write_index Where writing supposed to start in the vector
Max912bc6f2016-01-28 12:07:12 +0100486 * \param[in] len How many bits to write
487 * \returns next write index or negative value on error
488 */
Holger Hans Peter Freythera9301a12016-01-30 10:54:43 +0100489int bitvec_write_field(struct bitvec *bv, unsigned int *write_index, uint64_t val, unsigned int len)
Maxa15f05f2016-01-26 10:43:15 +0100490{
491 unsigned int i;
492 int rc;
Holger Hans Peter Freythera9301a12016-01-30 10:54:43 +0100493 bv->cur_bit = *write_index;
Maxa15f05f2016-01-26 10:43:15 +0100494 for (i = 0; i < len; i++) {
495 int bit = 0;
496 if (val & ((uint64_t)1 << (len - i - 1)))
497 bit = 1;
498 rc = bitvec_set_bit(bv, bit);
499 if (rc)
500 return rc;
501 }
Holger Hans Peter Freythera9301a12016-01-30 10:54:43 +0100502 *write_index += len;
Maxa15f05f2016-01-26 10:43:15 +0100503 return 0;
504}
505
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200506/*! convert enum to corresponding character
Harald Welte2d2e2cc2016-04-25 12:11:20 +0200507 * \param v input value (bit)
508 * \return single character, either 0, 1, L or H */
Max0a59e982016-02-05 13:55:37 +0100509char bit_value_to_char(enum bit_value v)
510{
511 switch (v) {
512 case ZERO: return '0';
513 case ONE: return '1';
514 case L: return 'L';
515 case H: return 'H';
516 default: abort();
517 }
518}
519
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200520/*! prints bit vector to provided string
Max0a59e982016-02-05 13:55:37 +0100521 * It's caller's responsibility to ensure that we won't shoot him in the foot:
522 * the provided buffer should be at lest cur_bit + 1 bytes long
523 */
524void bitvec_to_string_r(const struct bitvec *bv, char *str)
525{
526 unsigned i, pos = 0;
527 char *cur = str;
528 for (i = 0; i < bv->cur_bit; i++) {
529 if (0 == i % 8)
530 *cur++ = ' ';
531 *cur++ = bit_value_to_char(bitvec_get_bit_pos(bv, i));
532 pos++;
533 }
534 *cur = 0;
535}
536
537/* we assume that x have at least 1 non-b bit */
538static inline unsigned leading_bits(uint8_t x, bool b)
539{
540 if (b) {
541 if (x < 0x80) return 0;
542 if (x < 0xC0) return 1;
543 if (x < 0xE0) return 2;
544 if (x < 0xF0) return 3;
545 if (x < 0xF8) return 4;
546 if (x < 0xFC) return 5;
547 if (x < 0xFE) return 6;
548 } else {
549 if (x > 0x7F) return 0;
550 if (x > 0x3F) return 1;
551 if (x > 0x1F) return 2;
552 if (x > 0xF) return 3;
553 if (x > 7) return 4;
554 if (x > 3) return 5;
555 if (x > 1) return 6;
556 }
557 return 7;
558}
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200559/*! force bit vector to all 0 and current bit to the beginnig of the vector */
Max0a59e982016-02-05 13:55:37 +0100560void bitvec_zero(struct bitvec *bv)
561{
562 bv->cur_bit = 0;
563 memset(bv->data, 0, bv->data_len);
564}
565
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200566/*! Return number (bits) of uninterrupted bit run in vector starting from the MSB
Max0a59e982016-02-05 13:55:37 +0100567 * \param[in] bv The boolean vector to work on
568 * \param[in] b The boolean, sequence of which is looked at from the vector start
569 * \returns Number of consecutive bits of \p b in \p bv
570 */
571unsigned bitvec_rl(const struct bitvec *bv, bool b)
572{
573 unsigned i;
574 for (i = 0; i < (bv->cur_bit % 8 ? bv->cur_bit / 8 + 1 : bv->cur_bit / 8); i++) {
575 if ( (b ? 0xFF : 0) != bv->data[i])
576 return i * 8 + leading_bits(bv->data[i], b);
577 }
578
579 return bv->cur_bit;
580}
581
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200582/*! Return number (bits) of uninterrupted bit run in vector
Pravin Kumarvel848de8f2016-12-02 15:13:03 +0530583 * starting from the current bit
584 * \param[in] bv The boolean vector to work on
585 * \param[in] b The boolean, sequence of 1's or 0's to be checked
586 * \param[in] max_bits Total Number of Uncmopresed bits
587 * \returns Number of consecutive bits of \p b in \p bv and cur_bit will
588 * \go to cur_bit + number of consecutive bit
589 */
590unsigned bitvec_rl_curbit(struct bitvec *bv, bool b, int max_bits)
591{
592 unsigned i = 0;
593 unsigned j = 8;
594 int temp_res = 0;
595 int count = 0;
596 unsigned readIndex = bv->cur_bit;
597 unsigned remaining_bits = max_bits % 8;
598 unsigned remaining_bytes = max_bits / 8;
599 unsigned byte_mask = 0xFF;
600
601 if (readIndex % 8) {
602 for (j -= (readIndex % 8) ; j > 0 ; j--) {
603 if (readIndex < max_bits && bitvec_read_field(bv, &readIndex, 1) == b)
604 temp_res++;
605 else {
606 bv->cur_bit--;
607 return temp_res;
608 }
609 }
610 }
611 for (i = (readIndex / 8);
612 i < (remaining_bits ? remaining_bytes + 1 : remaining_bytes);
613 i++, count++) {
614 if ((b ? byte_mask : 0) != bv->data[i]) {
615 bv->cur_bit = (count * 8 +
616 leading_bits(bv->data[i], b) + readIndex);
617 return count * 8 +
618 leading_bits(bv->data[i], b) + temp_res;
619 }
620 }
621 bv->cur_bit = (temp_res + (count * 8)) + readIndex;
622 if (bv->cur_bit > max_bits)
623 bv->cur_bit = max_bits;
624 return (bv->cur_bit - readIndex + temp_res);
625}
626
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200627/*! Shifts bitvec to the left, n MSB bits lost */
Max0a59e982016-02-05 13:55:37 +0100628void bitvec_shiftl(struct bitvec *bv, unsigned n)
629{
630 if (0 == n)
631 return;
632 if (n >= bv->cur_bit) {
633 bitvec_zero(bv);
634 return;
635 }
636
637 memmove(bv->data, bv->data + n / 8, bv->data_len - n / 8);
638
639 uint8_t tmp[2];
640 unsigned i;
641 for (i = 0; i < bv->data_len - 2; i++) {
642 uint16_t t = osmo_load16be(bv->data + i);
643 osmo_store16be(t << (n % 8), &tmp);
644 bv->data[i] = tmp[0];
645 }
646
647 bv->data[bv->data_len - 1] <<= (n % 8);
648 bv->cur_bit -= n;
649}
650
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200651/*! Add given array to bitvec
Maxd4793212016-03-17 11:51:08 +0100652 * \param[in,out] bv bit vector to work with
653 * \param[in] array elements to be added
654 * \param[in] array_len length of array
655 * \param[in] dry_run indicates whether to return number of bits required
656 * instead of adding anything to bv for real
657 * \param[in] num_bits number of bits to consider in each element of array
658 * \returns number of bits necessary to add array elements if dry_run is true,
659 * 0 otherwise (only in this case bv is actually changed)
660 *
661 * N. B: no length checks are performed on bv - it's caller's job to ensure
662 * enough space is available - for example by calling with dry_run = true first.
663 *
664 * Useful for common pattern in CSN.1 spec which looks like:
665 * { 1 < XXX : bit (num_bits) > } ** 0
666 * which means repeat any times (between 0 and infinity),
667 * start each repetition with 1, mark end of repetitions with 0 bit
668 * see app. note in 3GPP TS 24.007 ยง B.2.1 Rule A2
669 */
670unsigned int bitvec_add_array(struct bitvec *bv, const uint32_t *array,
671 unsigned int array_len, bool dry_run,
672 unsigned int num_bits)
673{
674 unsigned i, bits = 1; /* account for stop bit */
675 for (i = 0; i < array_len; i++) {
676 if (dry_run) {
677 bits += (1 + num_bits);
678 } else {
679 bitvec_set_bit(bv, 1);
680 bitvec_set_uint(bv, array[i], num_bits);
681 }
682 }
683
684 if (dry_run)
685 return bits;
686
687 bitvec_set_bit(bv, 0); /* stop bit - end of the sequence */
688 return 0;
689}
690
Sylvain Munautdca7d2c2012-04-18 21:53:23 +0200691/*! @} */