1 /*
2 * Bit stream reader
3 * Copyright (C) 2007 Andreas Öman
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include <stdio.h>
20 #include <inttypes.h>
21 #include "bitstream.h"
22
23
24 int
init_rbits(bitstream_t * bs,const uint8_t * data,uint32_t bits)25 init_rbits(bitstream_t *bs, const uint8_t *data, uint32_t bits)
26 {
27 bs->wdata = NULL;
28 bs->rdata = data;
29 bs->offset = 0;
30 bs->len = bits;
31 return 0;
32 }
33
34
35 int
init_wbits(bitstream_t * bs,uint8_t * data,uint32_t bits)36 init_wbits(bitstream_t *bs, uint8_t *data, uint32_t bits)
37 {
38 bs->wdata = data;
39 bs->rdata = NULL;
40 bs->offset = 0;
41 bs->len = bits;
42 return 0;
43 }
44
45 uint32_t
read_bits(bitstream_t * bs,uint32_t num)46 read_bits(bitstream_t *bs, uint32_t num)
47 {
48 uint32_t r = 0;
49
50 while(num > 0) {
51 if(bs->offset >= bs->len)
52 return 0;
53
54 num--;
55
56 if(bs->rdata[bs->offset / 8] & (1 << (7 - (bs->offset & 7))))
57 r |= 1 << num;
58
59 bs->offset++;
60 }
61 return r;
62 }
63
64 uint64_t
read_bits64(bitstream_t * bs,uint32_t num)65 read_bits64(bitstream_t *bs, uint32_t num)
66 {
67 uint64_t r = 0;
68
69 while(num > 0) {
70 if(bs->offset >= bs->len)
71 return 0;
72
73 num--;
74
75 if(bs->rdata[bs->offset / 8] & (1 << (7 - (bs->offset & 7))))
76 r |= (int64_t)1 << num;
77
78 bs->offset++;
79 }
80 return r;
81 }
82
83 uint32_t
show_bits(bitstream_t * bs,uint32_t num)84 show_bits(bitstream_t *bs, uint32_t num)
85 {
86 uint32_t r = 0, offset = bs->offset;
87
88 while(num > 0) {
89 if(offset >= bs->len)
90 return 0;
91
92 num--;
93
94 if(bs->rdata[offset / 8] & (1 << (7 - (offset & 7))))
95 r |= 1 << num;
96
97 offset++;
98 }
99 return r;
100 }
101
102 uint32_t
read_golomb_ue(bitstream_t * bs)103 read_golomb_ue(bitstream_t *bs)
104 {
105 uint32_t b;
106 int lzb = -1;
107
108 for(b = 0; !b && !bs_eof(bs) && lzb < 32; lzb++)
109 b = read_bits1(bs);
110
111 if (lzb < 0 || lzb > 31)
112 return 0;
113 return (1 << lzb) - 1 + read_bits(bs, lzb);
114 }
115
116
117 int32_t
read_golomb_se(bitstream_t * bs)118 read_golomb_se(bitstream_t *bs)
119 {
120 uint32_t v;
121 v = read_golomb_ue(bs);
122 if(v == 0)
123 return 0;
124
125 return (v & 1) ? ((v + 1) >> 1) : -(v >> 1);
126 }
127
128
129 void
put_bits(bitstream_t * bs,uint32_t val,uint32_t num)130 put_bits(bitstream_t *bs, uint32_t val, uint32_t num)
131 {
132 while(num > 0) {
133 if(bs->offset >= bs->len)
134 return;
135
136 num--;
137
138 if(val & (1 << num))
139 bs->wdata[bs->offset / 8] |= 1 << (7 - (bs->offset & 7));
140 else
141 bs->wdata[bs->offset / 8] &= ~(1 << (7 - (bs->offset & 7)));
142
143 bs->offset++;
144 }
145 }
146