File: bitstr.h

package info (click to toggle)
rtpengine 13.5.1.3-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 13,676 kB
  • sloc: ansic: 86,764; perl: 59,422; python: 3,193; sh: 1,030; makefile: 693; asm: 211
file content (80 lines) | stat: -rw-r--r-- 1,833 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#ifndef _BITSTR_H_
#define _BITSTR_H_

#include "str.h"
#include <assert.h>

struct bitstr_s {
	str s;
	unsigned int bit_offset; // leading consumed bits
};
typedef struct bitstr_s bitstr;

INLINE void bitstr_init(bitstr *b, const str *s) {
	b->s = *s;
	b->bit_offset = 0;
}

INLINE int bitstr_shift_ret(bitstr *b, unsigned int bits, str *ret) {
	if (!bits)
		return 0;
	// check if we have enough
	if (bits > b->s.len * 8 - b->bit_offset)
		return -1;

	unsigned int to_copy = (bits + b->bit_offset + 7) / 8;

	if (ret) {
		assert(ret->len >= to_copy);
		ret->len = to_copy;
		memcpy(ret->s, b->s.s, to_copy);
		unsigned char *ret_s = (unsigned char *) ret->s; // avoid bitshifts on signed chars

		// we have to bit-shift the entire string if there was a leading offset
		if (b->bit_offset) {
			unsigned int left = bits;
			unsigned int c = 0;
			while (b->bit_offset + left > 8) {
				// enough to fill one output byte from two consecutive input bytes
				ret_s[c] <<= b->bit_offset;
				ret_s[c] |= ret_s[c + 1] >> (8 - b->bit_offset);
				if (left <= 8) {
					// final trailing bits overlapping bytes: truncate
					ret_s[c] &= 0xff << (8 - left);
					left = 0;
					ret->len--;
				}
				else
					left -= 8;
				c++;
			}
			if (left) {
				// last byte has the remainder
				ret_s[c] <<= b->bit_offset;
				ret_s[c] &= 0xff << (8 - left);
			}
		}
		else {
			// truncate last byte if needed
			unsigned int bits_left = bits % 8;
			if (bits_left)
				ret_s[to_copy - 1] &= 0xff << (8 - bits_left);
		}
	}

	b->bit_offset += bits;
	unsigned int int_bytes = b->bit_offset / 8;
	int shift_ret = str_shift(&b->s, int_bytes);
	assert(shift_ret == 0);
	(void) shift_ret;
	b->bit_offset -= int_bytes * 8;

	return 0;
}

INLINE int bitstr_shift(bitstr *b, unsigned int bits) {
	return bitstr_shift_ret(b, bits, NULL);
}


#endif