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