1 /* ------------------------------------------------------------------
2 * Copyright (C) 1998-2009 PacketVideo
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
13 * express or implied.
14 * See the License for the specific language governing permissions
15 * and limitations under the License.
16 * -------------------------------------------------------------------
17 */
18 #ifndef BITSTREAMPARSER_H_INCLUDED
19 #include "bitstreamparser.h"
20 #endif
21 #ifndef OSCL_ASSERT_H_INCLUDED
22 #include "oscl_assert.h"
23 #endif
24 #ifndef OSCL_BYTE_ORDER_H_INCLUDED
25 #include "oscl_byte_order.h"
26 #endif
27 #ifndef OSCL_DLL_H_INCLUDED
28 #include "oscl_dll.h"
29 #endif
30 #ifndef OSCL_ERROR_H_INCLUDED
31 #include "oscl_error.h"
32 #endif
33 #ifndef OSCL_ERROR_CODES_H_INCLUDED
34 #include "oscl_error_codes.h"
35 #endif
36 #ifndef OSCL_EXCEPTION_H_INCLUDED
37 #include "oscl_exception.h"
38 #endif
39
40
BitStreamParser(uint8 * stream,uint32 size)41 OSCL_EXPORT_REF BitStreamParser::BitStreamParser(uint8* stream, uint32 size)
42 {
43 ResetBitStreamParser(stream, size);
44 }
45
ResetBitStreamParser(uint8 * stream,uint32 size)46 OSCL_EXPORT_REF void BitStreamParser::ResetBitStreamParser(uint8* stream, uint32 size)
47 {
48 this->size = size;
49 start = OSCL_STATIC_CAST(uint8*, stream);
50 bytepos = OSCL_STATIC_CAST(uint8*, start);
51 bitpos = MOST_SIG_BIT;
52 }
53
ReadBits(uint8 numberOfBits)54 OSCL_EXPORT_REF uint32 BitStreamParser::ReadBits(uint8 numberOfBits)
55 {
56 //Initialize output to zero before shifting out bits.
57 uint32 output = 0;
58
59 OSCL_ASSERT(numberOfBits <= BITS_PER_UINT32);
60 //In case OSCL_ASSERT is defined to do nothing, set the max size.
61 if (numberOfBits > BITS_PER_UINT32) numberOfBits = BITS_PER_UINT32;
62
63 //Note: Using the host's native shift operator will automatically
64 //convert from big endian to host's endianness.
65 while (numberOfBits)
66 {
67 // Make sure bytepos won't exceed the size of the buffer while reading
68 if (bytepos >= (start + size))
69 {
70 OSCL_LEAVE(OsclErrOverflow);
71 }
72
73 //Optimize reads for special cases such as byte-aligned reads and
74 //processing multiple bits at a time.
75 if ((numberOfBits >= BITS_PER_UINT8) && (bitpos == MOST_SIG_BIT))
76 {
77 //This is the special case where a read is a whole byte (aligned).
78 //Shift the output over 8 bits.
79 output <<= BITS_PER_UINT8;
80 //OR the current byte from the stream into the output.
81 output |= *bytepos;
82 //Advance the stream byte pointer.
83 bytepos++;
84 //Decrement the number of bits left to read.
85 numberOfBits -= BITS_PER_UINT8;
86 }
87 else //Read one or more bits at a time.
88 {
89 //Define the bitmask corresponding to the number of bits
90 //to read from the current byte.
91 //This is implemented as a static look-up table for efficiency.
92 static const uint8 bitmask[] =
93 {
94 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff
95 };
96
97 //Process the bits in the current byte...
98
99 //Determine the number of bits remaining in the current byte of the stream.
100 //This is the upper limit on the number of bits we will read
101 //this through the loop.
102 uint8 bitsFromThisByte = bitpos + 1;
103 //If more bits remain then we need, only take what we need.
104 if (bitsFromThisByte > numberOfBits) bitsFromThisByte = numberOfBits;
105
106 //Shift the output value over to make room for the new bits to read.
107 output <<= bitsFromThisByte;
108 //OR in the bits from the stream.
109 //This reads the current byte from the stream,
110 //shifts it over so the bits we want are at the LS end,
111 //and masks off all of the bits except the ones we want.
112 output |= ((*bytepos) >> (bitpos - (bitsFromThisByte - 1))) & bitmask[bitsFromThisByte];
113
114 //Decrement the numberOfBits remaining...
115 numberOfBits -= bitsFromThisByte;
116 //...and advance the bitpos and bytepos pointers.
117 NextBits(bitsFromThisByte);
118 }
119 }
120
121 return output;
122 }
123
124
ReadUInt8(void)125 OSCL_EXPORT_REF uint8 BitStreamParser::ReadUInt8(void)
126 {
127 //If bitpos is not on a byte boundary, have to use ReadBits...
128 if (bitpos != MOST_SIG_BIT) return ReadBits(BITS_PER_UINT8);
129
130 // Make sure the current bytepos doesn't exceed the size of the buffer
131 if (bytepos >= (start + size))
132 {
133 OSCL_LEAVE(OsclErrOverflow);
134 }
135 uint8 read = *bytepos;
136 bytepos++;
137
138 return read;
139 }
140
141
ReadUInt16(void)142 OSCL_EXPORT_REF uint16 BitStreamParser::ReadUInt16(void)
143 {
144 uint16 read;
145 ((uint8*)&read)[0] = ReadUInt8();
146 ((uint8*)&read)[1] = ReadUInt8();
147 big_endian_to_host((char*)&read, sizeof(read));
148 return read;
149 }
150
151
ReadUInt32(void)152 OSCL_EXPORT_REF uint32 BitStreamParser::ReadUInt32(void)
153 {
154 uint32 read;
155 ((uint8*)&read)[0] = ReadUInt8();
156 ((uint8*)&read)[1] = ReadUInt8();
157 ((uint8*)&read)[2] = ReadUInt8();
158 ((uint8*)&read)[3] = ReadUInt8();
159 big_endian_to_host((char*)&read, sizeof(read));
160 return read;
161 }
162
163
WriteBits(uint8 numberOfBits,const uint8 * data)164 OSCL_EXPORT_REF void BitStreamParser::WriteBits(uint8 numberOfBits, const uint8* data)
165 {
166 //This is not the most efficient algorithm, but it is the least complex.
167 //Treat "data" as an input stream.
168 BitStreamParser input(const_cast<uint8*>(data), BITS_TO_BYTES(numberOfBits));
169 //Skip over the unused bits.
170 input.NextBits(input.BitsLeft() - numberOfBits);
171 //Loop through each bit to process...
172 while (numberOfBits)
173 {
174 uint8 bitmask = 1 << bitpos;
175 //READ
176 uint8 byte = *bytepos;
177 //MODIFY
178 byte &= ~(bitmask); //Clear the bit being written.
179 byte |= (input.ReadBits(1) << bitpos); //Write the bit.
180 //WRITE
181 *bytepos = byte;
182 //Advance the bit pointer
183 NextBit();
184 numberOfBits--;
185 }
186 }
187
188
WriteUInt8(uint8 data)189 OSCL_EXPORT_REF void BitStreamParser::WriteUInt8(uint8 data)
190 {
191 if (bitpos != MOST_SIG_BIT)
192 {
193 WriteBits(BITS_PER_BYTE, &data);
194 }
195 else
196 {
197 if (bytepos >= (start + size))
198 {
199 OSCL_LEAVE(OsclErrOverflow);
200 }
201 *bytepos = data;
202 bytepos++;
203 }
204 }
205
206
WriteUInt16(uint16 data)207 OSCL_EXPORT_REF void BitStreamParser::WriteUInt16(uint16 data)
208 {
209 uint16 be = data;
210 host_to_big_endian((char*)&be, sizeof(be));
211 WriteUInt8(((uint8*)&be)[0]);
212 WriteUInt8(((uint8*)&be)[1]);
213 }
214
215
WriteUInt32(uint32 data)216 OSCL_EXPORT_REF void BitStreamParser::WriteUInt32(uint32 data)
217 {
218 uint32 be = data;
219 host_to_big_endian((char*)&be, sizeof(be));
220 WriteUInt8(((uint8*)&be)[0]);
221 WriteUInt8(((uint8*)&be)[1]);
222 WriteUInt8(((uint8*)&be)[2]);
223 WriteUInt8(((uint8*)&be)[3]);
224 }
225
226
NextBits(uint32 numberOfBits)227 OSCL_EXPORT_REF void BitStreamParser::NextBits(uint32 numberOfBits)
228 {
229 //bitpos counts down from 7 to 0, so subtract it from 7 to get the ascending position.
230 uint32 newbitpos = numberOfBits + (MOST_SIG_BIT - bitpos);
231 //Convert the ascending bit position to a descending position using only the least-significant bits.
232 bitpos = MOST_SIG_BIT - (newbitpos & LEAST_SIG_3_BITS_MASK);
233 //Calculate the number of bytes advanced.
234 bytepos += (newbitpos / BITS_PER_BYTE);
235 // Make sure bytepos won't exceed the size of the buffer while reading
236 if (bytepos >= (start + size))
237 {
238 OSCL_LEAVE(OsclErrOverflow);
239 }
240 }
241
242