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#define PRAGMA_MARK 0
31
32// BitBufferInit
33//
34void BitBufferInit (BitBuffer * bits, uint8_t * buffer, uint32_t byteSize)
35{
36	bits->cur		= buffer ;
37	bits->end		= bits->cur + byteSize ;
38	bits->bitIndex	= 0 ;
39	bits->byteSize	= byteSize ;
40}
41
42// BitBufferRead
43//
44uint32_t BitBufferRead (BitBuffer * bits, uint8_t numBits)
45{
46	uint32_t		returnBits ;
47
48	//Assert (numBits <= 16) ;
49
50	returnBits = ((uint32_t) bits->cur [0] << 16) | ((uint32_t) bits->cur [1] << 8) | ((uint32_t) bits->cur [2]) ;
51	returnBits = returnBits << bits->bitIndex ;
52	returnBits &= 0x00FFFFFF ;
53
54	bits->bitIndex += numBits ;
55
56	returnBits = returnBits >> (24 - numBits) ;
57
58	bits->cur		+= (bits->bitIndex >> 3) ;
59	bits->bitIndex	&= 7 ;
60
61	//Assert (bits->cur <= bits->end) ;
62
63	return returnBits ;
64}
65
66// BitBufferReadSmall
67//
68// Reads up to 8 bits
69uint8_t BitBufferReadSmall (BitBuffer * bits, uint8_t numBits)
70{
71	uint16_t		returnBits ;
72
73	//Assert (numBits <= 8) ;
74
75	returnBits = (bits->cur [0] << 8) | bits->cur [1] ;
76	returnBits = returnBits << bits->bitIndex ;
77
78	bits->bitIndex += numBits ;
79
80	returnBits = returnBits >> (16 - numBits) ;
81
82	bits->cur		+= (bits->bitIndex >> 3) ;
83	bits->bitIndex	&= 7 ;
84
85	//Assert (bits->cur <= bits->end) ;
86
87	return (uint8_t) returnBits ;
88}
89
90// BitBufferReadOne
91//
92// Reads one byte
93uint8_t BitBufferReadOne (BitBuffer * bits)
94{
95	uint8_t		returnBits ;
96
97	returnBits = (bits->cur [0] >> (7 - bits->bitIndex)) & 1 ;
98
99	bits->bitIndex++ ;
100
101	bits->cur		+= (bits->bitIndex >> 3) ;
102	bits->bitIndex	&= 7 ;
103
104	//Assert (bits->cur <= bits->end) ;
105
106	return returnBits ;
107}
108
109// BitBufferPeek
110//
111uint32_t BitBufferPeek (BitBuffer * bits, uint8_t numBits)
112{
113	return ((((((uint32_t) bits->cur [0] << 16) | ((uint32_t) bits->cur [1] << 8) |
114			((uint32_t) bits->cur [2])) << bits->bitIndex) & 0x00FFFFFF) >> (24 - numBits)) ;
115}
116
117// BitBufferPeekOne
118//
119uint32_t BitBufferPeekOne (BitBuffer * bits)
120{
121	return ((bits->cur [0] >> (7 - bits->bitIndex)) & 1) ;
122}
123
124// BitBufferUnpackBERSize
125//
126uint32_t BitBufferUnpackBERSize (BitBuffer * bits)
127{
128	uint32_t		size ;
129	uint8_t		tmp ;
130
131	for (size = 0, tmp = 0x80u ; tmp &= 0x80u ; size = (size << 7u) | (tmp & 0x7fu))
132		tmp = (uint8_t) BitBufferReadSmall (bits, 8) ;
133
134	return size ;
135}
136
137// BitBufferGetPosition
138//
139uint32_t BitBufferGetPosition (BitBuffer * bits)
140{
141	uint8_t *		begin ;
142
143	begin = bits->end - bits->byteSize ;
144
145	return ((uint32_t) (bits->cur - begin) * 8) + bits->bitIndex ;
146}
147
148// BitBufferByteAlign
149//
150void BitBufferByteAlign (BitBuffer * bits, int32_t addZeros)
151{
152	// align bit buffer to next byte boundary, writing zeros if requested
153	if (bits->bitIndex == 0)
154		return ;
155
156	if (addZeros)
157		BitBufferWrite (bits, 0, 8 - bits->bitIndex) ;
158	else
159		BitBufferAdvance (bits, 8 - bits->bitIndex) ;
160}
161
162// BitBufferAdvance
163//
164void BitBufferAdvance (BitBuffer * bits, uint32_t numBits)
165{
166	if (numBits)
167	{
168		bits->bitIndex += numBits ;
169		bits->cur += (bits->bitIndex >> 3) ;
170		bits->bitIndex &= 7 ;
171	}
172}
173
174// BitBufferRewind
175//
176void BitBufferRewind (BitBuffer * bits, uint32_t numBits)
177{
178	uint32_t	numBytes ;
179
180	if (numBits == 0)
181		return ;
182
183	if (bits->bitIndex >= numBits)
184	{
185		bits->bitIndex -= numBits ;
186		return ;
187	}
188
189	numBits -= bits->bitIndex ;
190	bits->bitIndex = 0 ;
191
192	numBytes	= numBits / 8 ;
193	numBits		= numBits % 8 ;
194
195	bits->cur -= numBytes ;
196
197	if (numBits > 0)
198	{
199		bits->bitIndex = 8 - numBits ;
200		bits->cur-- ;
201	}
202
203	if (bits->cur < (bits->end - bits->byteSize))
204	{
205		//DebugCMsg ("BitBufferRewind: Rewound too far.") ;
206
207		bits->cur		= (bits->end - bits->byteSize) ;
208		bits->bitIndex	= 0 ;
209	}
210}
211
212// BitBufferWrite
213//
214void BitBufferWrite (BitBuffer * bits, uint32_t bitValues, uint32_t numBits)
215{
216	uint32_t				invBitIndex ;
217
218	RequireAction (bits != NULL, return ;) ;
219	RequireActionSilent (numBits > 0, return ;) ;
220
221	invBitIndex = 8 - bits->bitIndex ;
222
223	while (numBits > 0)
224	{
225		uint32_t		tmp ;
226		uint8_t		shift ;
227		uint8_t		mask ;
228		uint32_t		curNum ;
229
230		curNum = MIN (invBitIndex, numBits) ;
231
232		tmp = bitValues >> (numBits - curNum) ;
233
234		shift = (uint8_t) (invBitIndex - curNum) ;
235		mask = 0xffu >> (8 - curNum) ;		// must be done in two steps to avoid compiler sequencing ambiguity
236		mask <<= shift ;
237
238		bits->cur [0] = (bits->cur [0] & ~mask) | (((uint8_t) tmp << shift) & mask) ;
239		numBits -= curNum ;
240
241		// increment to next byte if need be
242		invBitIndex -= curNum ;
243		if (invBitIndex == 0)
244		{
245			invBitIndex = 8 ;
246			bits->cur++ ;
247		}
248	}
249
250	bits->bitIndex = 8 - invBitIndex ;
251}
252
253void	BitBufferReset (BitBuffer * bits)
254//void BitBufferInit (BitBuffer * bits, uint8_t * buffer, uint32_t byteSize)
255{
256	bits->cur = bits->end - bits->byteSize ;
257	bits->bitIndex = 0 ;
258}
259
260#if PRAGMA_MARK
261#pragma mark -
262#endif
263