1 /*
2  * Copyright (c) 2011 Apple Inc. All rights reserved.
3  *
4  * @APPLE_APACHE_LICENSE_HEADER_START@
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  * @APPLE_APACHE_LICENSE_HEADER_END@
19  */
20 
21 /*=============================================================================
22     File:		ALACBitUtilities.c
23 
24 	$NoKeywords: $
25 =============================================================================*/
26 
27 #include <stdio.h>
28 #include "ALACBitUtilities.h"
29 
30 // BitBufferInit
31 //
BitBufferInit(BitBuffer * bits,uint8_t * buffer,uint32_t byteSize)32 void BitBufferInit( BitBuffer * bits, uint8_t * buffer, uint32_t byteSize )
33 {
34 	bits->cur		= buffer;
35 	bits->end		= bits->cur + byteSize;
36 	bits->bitIndex	= 0;
37 	bits->byteSize	= byteSize;
38 }
39 
40 // BitBufferRead
41 //
BitBufferRead(BitBuffer * bits,uint8_t numBits)42 uint32_t BitBufferRead( BitBuffer * bits, uint8_t numBits )
43 {
44 	uint32_t		returnBits;
45 
46 	//Assert( numBits <= 16 );
47 
48 	returnBits = ((uint32_t)bits->cur[0] << 16) | ((uint32_t)bits->cur[1] << 8) | ((uint32_t)bits->cur[2]);
49 	returnBits = returnBits << bits->bitIndex;
50 	returnBits &= 0x00FFFFFF;
51 
52 	bits->bitIndex += numBits;
53 
54 	returnBits = returnBits >> (24 - numBits);
55 
56 	bits->cur		+= (bits->bitIndex >> 3);
57 	bits->bitIndex	&= 7;
58 
59 	//Assert( bits->cur <= bits->end );
60 
61 	return returnBits;
62 }
63 
64 // BitBufferReadSmall
65 //
66 // Reads up to 8 bits
BitBufferReadSmall(BitBuffer * bits,uint8_t numBits)67 uint8_t BitBufferReadSmall( BitBuffer * bits, uint8_t numBits )
68 {
69 	uint16_t		returnBits;
70 
71 	//Assert( numBits <= 8 );
72 
73 	returnBits = (bits->cur[0] << 8) | bits->cur[1];
74 	returnBits = returnBits << bits->bitIndex;
75 
76 	bits->bitIndex += numBits;
77 
78 	returnBits = returnBits >> (16 - numBits);
79 
80 	bits->cur		+= (bits->bitIndex >> 3);
81 	bits->bitIndex	&= 7;
82 
83 	//Assert( bits->cur <= bits->end );
84 
85 	return (uint8_t)returnBits;
86 }
87 
88 // BitBufferReadOne
89 //
90 // Reads one byte
BitBufferReadOne(BitBuffer * bits)91 uint8_t BitBufferReadOne( BitBuffer * bits )
92 {
93 	uint8_t		returnBits;
94 
95 	returnBits = (bits->cur[0] >> (7 - bits->bitIndex)) & 1;
96 
97 	bits->bitIndex++;
98 
99 	bits->cur		+= (bits->bitIndex >> 3);
100 	bits->bitIndex	&= 7;
101 
102 	//Assert( bits->cur <= bits->end );
103 
104 	return returnBits;
105 }
106 
107 // BitBufferPeek
108 //
BitBufferPeek(BitBuffer * bits,uint8_t numBits)109 uint32_t BitBufferPeek( BitBuffer * bits, uint8_t numBits )
110 {
111 	return ((((((uint32_t) bits->cur[0] << 16) | ((uint32_t) bits->cur[1] << 8) |
112 			((uint32_t) bits->cur[2])) << bits->bitIndex) & 0x00FFFFFF) >> (24 - numBits));
113 }
114 
115 // BitBufferPeekOne
116 //
BitBufferPeekOne(BitBuffer * bits)117 uint32_t BitBufferPeekOne( BitBuffer * bits )
118 {
119 	return ((bits->cur[0] >> (7 - bits->bitIndex)) & 1);
120 }
121 
122 // BitBufferUnpackBERSize
123 //
BitBufferUnpackBERSize(BitBuffer * bits)124 uint32_t BitBufferUnpackBERSize( BitBuffer * bits )
125 {
126 	uint32_t		size;
127 	uint8_t		tmp;
128 
129 	for ( size = 0, tmp = 0x80u; tmp &= 0x80u; size = (size << 7u) | (tmp & 0x7fu) )
130 		tmp = (uint8_t) BitBufferReadSmall( bits, 8 );
131 
132 	return size;
133 }
134 
135 // BitBufferGetPosition
136 //
BitBufferGetPosition(BitBuffer * bits)137 uint32_t BitBufferGetPosition( BitBuffer * bits )
138 {
139 	uint8_t *		begin;
140 
141 	begin = bits->end - bits->byteSize;
142 
143 	return ((uint32_t)(bits->cur - begin) * 8) + bits->bitIndex;
144 }
145 
146 // BitBufferByteAlign
147 //
BitBufferByteAlign(BitBuffer * bits,int32_t addZeros)148 void BitBufferByteAlign( BitBuffer * bits, int32_t addZeros )
149 {
150 	// align bit buffer to next byte boundary, writing zeros if requested
151 	if ( bits->bitIndex == 0 )
152 		return;
153 
154 	if ( addZeros )
155 		BitBufferWrite( bits, 0, 8 - bits->bitIndex );
156 	else
157 		BitBufferAdvance( bits, 8 - bits->bitIndex );
158 }
159 
160 // BitBufferAdvance
161 //
BitBufferAdvance(BitBuffer * bits,uint32_t numBits)162 void BitBufferAdvance( BitBuffer * bits, uint32_t numBits )
163 {
164 	if ( numBits )
165 	{
166 		bits->bitIndex += numBits;
167 		bits->cur += (bits->bitIndex >> 3);
168 		bits->bitIndex &= 7;
169 	}
170 }
171 
172 // BitBufferRewind
173 //
BitBufferRewind(BitBuffer * bits,uint32_t numBits)174 void BitBufferRewind( BitBuffer * bits, uint32_t numBits )
175 {
176 	uint32_t	numBytes;
177 
178 	if ( numBits == 0 )
179 		return;
180 
181 	if ( bits->bitIndex >= numBits )
182 	{
183 		bits->bitIndex -= numBits;
184 		return;
185 	}
186 
187 	numBits -= bits->bitIndex;
188 	bits->bitIndex = 0;
189 
190 	numBytes	= numBits / 8;
191 	numBits		= numBits % 8;
192 
193 	bits->cur -= numBytes;
194 
195 	if ( numBits > 0 )
196 	{
197 		bits->bitIndex = 8 - numBits;
198 		bits->cur--;
199 	}
200 
201 	if ( bits->cur < (bits->end - bits->byteSize) )
202 	{
203 		//DebugCMsg("BitBufferRewind: Rewound too far.");
204 
205 		bits->cur		= (bits->end - bits->byteSize);
206 		bits->bitIndex	= 0;
207 	}
208 }
209 
210 // BitBufferWrite
211 //
BitBufferWrite(BitBuffer * bits,uint32_t bitValues,uint32_t numBits)212 void BitBufferWrite( BitBuffer * bits, uint32_t bitValues, uint32_t numBits )
213 {
214 	uint32_t				invBitIndex;
215 
216 	RequireAction( bits != nil, return; );
217 	RequireActionSilent( numBits > 0, return; );
218 
219 	invBitIndex = 8 - bits->bitIndex;
220 
221 	while ( numBits > 0 )
222 	{
223 		uint32_t		tmp;
224 		uint8_t		shift;
225 		uint8_t		mask;
226 		uint32_t		curNum;
227 
228 		curNum = MIN( invBitIndex, numBits );
229 
230 		tmp = bitValues >> (numBits - curNum);
231 
232 		shift  = (uint8_t)(invBitIndex - curNum);
233 		mask   = 0xffu >> (8 - curNum);		// must be done in two steps to avoid compiler sequencing ambiguity
234 		mask <<= shift;
235 
236 		bits->cur[0] = (bits->cur[0] & ~mask) | (((uint8_t) tmp << shift)  & mask);
237 		numBits -= curNum;
238 
239 		// increment to next byte if need be
240 		invBitIndex -= curNum;
241 		if ( invBitIndex == 0 )
242 		{
243 			invBitIndex = 8;
244 			bits->cur++;
245 		}
246 	}
247 
248 	bits->bitIndex = 8 - invBitIndex;
249 }
250 
BitBufferReset(BitBuffer * bits)251 void	BitBufferReset( BitBuffer * bits )
252 //void BitBufferInit( BitBuffer * bits, uint8_t * buffer, uint32_t byteSize )
253 {
254 	bits->cur		= bits->end - bits->byteSize;
255     bits->bitIndex	= 0;
256 }
257 
258 #if PRAGMA_MARK
259 #pragma mark -
260 #endif
261