1*fce4895dSRene Gollent /*
2*fce4895dSRene Gollent * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
3*fce4895dSRene Gollent * Distributed under the terms of the MIT License.
4*fce4895dSRene Gollent */
5*fce4895dSRene Gollent
6*fce4895dSRene Gollent
7*fce4895dSRene Gollent #include "BitBuffer.h"
8*fce4895dSRene Gollent
9*fce4895dSRene Gollent
10*fce4895dSRene Gollent // #pragma mark - BitReader
11*fce4895dSRene Gollent
12*fce4895dSRene Gollent
13*fce4895dSRene Gollent struct BitBuffer::BitReader {
14*fce4895dSRene Gollent const uint8* data;
15*fce4895dSRene Gollent uint64 bitSize;
16*fce4895dSRene Gollent uint32 bitOffset;
17*fce4895dSRene Gollent
BitReaderBitBuffer::BitReader18*fce4895dSRene Gollent BitReader(const uint8* data, uint64 bitSize, uint32 bitOffset)
19*fce4895dSRene Gollent :
20*fce4895dSRene Gollent data(data),
21*fce4895dSRene Gollent bitSize(bitSize),
22*fce4895dSRene Gollent bitOffset(bitOffset)
23*fce4895dSRene Gollent {
24*fce4895dSRene Gollent }
25*fce4895dSRene Gollent
ReadByteBitBuffer::BitReader26*fce4895dSRene Gollent uint8 ReadByte()
27*fce4895dSRene Gollent {
28*fce4895dSRene Gollent uint8 byte = *data;
29*fce4895dSRene Gollent data++;
30*fce4895dSRene Gollent bitSize -= 8;
31*fce4895dSRene Gollent
32*fce4895dSRene Gollent if (bitOffset == 0)
33*fce4895dSRene Gollent return byte;
34*fce4895dSRene Gollent
35*fce4895dSRene Gollent return (byte << bitOffset) | (*data >> (8 - bitOffset));
36*fce4895dSRene Gollent }
37*fce4895dSRene Gollent
ReadBitsBitBuffer::BitReader38*fce4895dSRene Gollent uint8 ReadBits(uint32 count)
39*fce4895dSRene Gollent {
40*fce4895dSRene Gollent uint8 byte = *data;
41*fce4895dSRene Gollent bitSize -= count;
42*fce4895dSRene Gollent bitOffset += count;
43*fce4895dSRene Gollent
44*fce4895dSRene Gollent if (bitOffset <= 8) {
45*fce4895dSRene Gollent if (bitOffset == 8) {
46*fce4895dSRene Gollent bitOffset = 0;
47*fce4895dSRene Gollent data++;
48*fce4895dSRene Gollent return byte & ((1 << count) - 1);
49*fce4895dSRene Gollent }
50*fce4895dSRene Gollent
51*fce4895dSRene Gollent return (byte >> (8 - bitOffset)) & ((1 << count) - 1);
52*fce4895dSRene Gollent }
53*fce4895dSRene Gollent
54*fce4895dSRene Gollent data++;
55*fce4895dSRene Gollent bitOffset -= 8;
56*fce4895dSRene Gollent return ((byte << bitOffset) | (*data >> (8 - bitOffset)))
57*fce4895dSRene Gollent & ((1 << count) - 1);
58*fce4895dSRene Gollent }
59*fce4895dSRene Gollent };
60*fce4895dSRene Gollent
61*fce4895dSRene Gollent
62*fce4895dSRene Gollent // #pragma mark - BitBuffer
63*fce4895dSRene Gollent
64*fce4895dSRene Gollent
BitBuffer()65*fce4895dSRene Gollent BitBuffer::BitBuffer()
66*fce4895dSRene Gollent :
67*fce4895dSRene Gollent fMissingBits(0)
68*fce4895dSRene Gollent {
69*fce4895dSRene Gollent }
70*fce4895dSRene Gollent
71*fce4895dSRene Gollent
~BitBuffer()72*fce4895dSRene Gollent BitBuffer::~BitBuffer()
73*fce4895dSRene Gollent {
74*fce4895dSRene Gollent }
75*fce4895dSRene Gollent
76*fce4895dSRene Gollent
77*fce4895dSRene Gollent bool
AddBytes(const void * data,size_t size)78*fce4895dSRene Gollent BitBuffer::AddBytes(const void* data, size_t size)
79*fce4895dSRene Gollent {
80*fce4895dSRene Gollent if (size == 0)
81*fce4895dSRene Gollent return true;
82*fce4895dSRene Gollent
83*fce4895dSRene Gollent if (fMissingBits == 0) {
84*fce4895dSRene Gollent size_t oldSize = fBytes.Size();
85*fce4895dSRene Gollent if (!fBytes.AddUninitialized(size))
86*fce4895dSRene Gollent return false;
87*fce4895dSRene Gollent
88*fce4895dSRene Gollent memcpy(fBytes.Elements() + oldSize, data, size);
89*fce4895dSRene Gollent return true;
90*fce4895dSRene Gollent }
91*fce4895dSRene Gollent
92*fce4895dSRene Gollent return AddBits(data, (uint64)size * 8, 0);
93*fce4895dSRene Gollent }
94*fce4895dSRene Gollent
95*fce4895dSRene Gollent
96*fce4895dSRene Gollent bool
AddBits(const void * _data,uint64 bitSize,uint32 bitOffset)97*fce4895dSRene Gollent BitBuffer::AddBits(const void* _data, uint64 bitSize, uint32 bitOffset)
98*fce4895dSRene Gollent {
99*fce4895dSRene Gollent if (bitSize == 0)
100*fce4895dSRene Gollent return true;
101*fce4895dSRene Gollent
102*fce4895dSRene Gollent const uint8* data = (const uint8*)_data + bitOffset / 8;
103*fce4895dSRene Gollent bitOffset %= 8;
104*fce4895dSRene Gollent
105*fce4895dSRene Gollent BitReader reader(data, bitSize, bitOffset);
106*fce4895dSRene Gollent
107*fce4895dSRene Gollent // handle special case first: no more bits than missing
108*fce4895dSRene Gollent size_t oldSize = fBytes.Size();
109*fce4895dSRene Gollent if (fMissingBits > 0 && bitSize <= fMissingBits) {
110*fce4895dSRene Gollent fMissingBits -= bitSize;
111*fce4895dSRene Gollent uint8 bits = reader.ReadBits(bitSize) << fMissingBits;
112*fce4895dSRene Gollent fBytes[oldSize - 1] |= bits;
113*fce4895dSRene Gollent return true;
114*fce4895dSRene Gollent }
115*fce4895dSRene Gollent
116*fce4895dSRene Gollent // resize the buffer
117*fce4895dSRene Gollent if (!fBytes.AddUninitialized((reader.bitSize - fMissingBits + 7) / 8))
118*fce4895dSRene Gollent return false;
119*fce4895dSRene Gollent
120*fce4895dSRene Gollent // fill in missing bits
121*fce4895dSRene Gollent if (fMissingBits > 0) {
122*fce4895dSRene Gollent fBytes[oldSize - 1] |= reader.ReadBits(fMissingBits);
123*fce4895dSRene Gollent fMissingBits = 0;
124*fce4895dSRene Gollent }
125*fce4895dSRene Gollent
126*fce4895dSRene Gollent // read full bytes as long as we can
127*fce4895dSRene Gollent uint8* buffer = fBytes.Elements() + oldSize;
128*fce4895dSRene Gollent while (reader.bitSize >= 8) {
129*fce4895dSRene Gollent *buffer = reader.ReadByte();
130*fce4895dSRene Gollent buffer++;
131*fce4895dSRene Gollent }
132*fce4895dSRene Gollent
133*fce4895dSRene Gollent // If we have left-over bits, write a partial byte.
134*fce4895dSRene Gollent if (reader.bitSize > 0) {
135*fce4895dSRene Gollent fMissingBits = 8 - reader.bitSize;
136*fce4895dSRene Gollent *buffer = reader.ReadBits(reader.bitSize) << fMissingBits;
137*fce4895dSRene Gollent }
138*fce4895dSRene Gollent
139*fce4895dSRene Gollent return true;
140*fce4895dSRene Gollent }
141*fce4895dSRene Gollent
142*fce4895dSRene Gollent
143*fce4895dSRene Gollent bool
AddZeroBits(uint64 bitSize)144*fce4895dSRene Gollent BitBuffer::AddZeroBits(uint64 bitSize)
145*fce4895dSRene Gollent {
146*fce4895dSRene Gollent if (bitSize == 0)
147*fce4895dSRene Gollent return true;
148*fce4895dSRene Gollent
149*fce4895dSRene Gollent // handle special case first: no more bits than missing
150*fce4895dSRene Gollent size_t oldSize = fBytes.Size();
151*fce4895dSRene Gollent if (fMissingBits > 0 && bitSize <= fMissingBits) {
152*fce4895dSRene Gollent fMissingBits -= bitSize;
153*fce4895dSRene Gollent return true;
154*fce4895dSRene Gollent }
155*fce4895dSRene Gollent
156*fce4895dSRene Gollent // resize the buffer
157*fce4895dSRene Gollent if (!fBytes.AddUninitialized((bitSize - fMissingBits + 7) / 8))
158*fce4895dSRene Gollent return false;
159*fce4895dSRene Gollent
160*fce4895dSRene Gollent // fill in missing bits
161*fce4895dSRene Gollent if (fMissingBits > 0) {
162*fce4895dSRene Gollent bitSize -= fMissingBits;
163*fce4895dSRene Gollent fMissingBits = 0;
164*fce4895dSRene Gollent }
165*fce4895dSRene Gollent
166*fce4895dSRene Gollent // zero the remaining bytes, including a potentially partial last byte
167*fce4895dSRene Gollent uint8* buffer = fBytes.Elements() + oldSize;
168*fce4895dSRene Gollent memset(buffer, 0, (bitSize + 7) / 8);
169*fce4895dSRene Gollent bitSize %= 8;
170*fce4895dSRene Gollent
171*fce4895dSRene Gollent if (bitSize > 0)
172*fce4895dSRene Gollent fMissingBits = 8 - bitSize;
173*fce4895dSRene Gollent
174*fce4895dSRene Gollent return true;
175*fce4895dSRene Gollent }
176