261 lines
5.4 KiB
C
261 lines
5.4 KiB
C
|
/*
|
||
|
* Copyright (c) 2011 Apple Inc. All rights reserved.
|
||
|
*
|
||
|
* @APPLE_APACHE_LICENSE_HEADER_START@
|
||
|
*
|
||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
* you may not use this file except in compliance with the License.
|
||
|
* You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* limitations under the License.
|
||
|
*
|
||
|
* @APPLE_APACHE_LICENSE_HEADER_END@
|
||
|
*/
|
||
|
|
||
|
/*=============================================================================
|
||
|
File: ALACBitUtilities.c
|
||
|
|
||
|
$NoKeywords: $
|
||
|
=============================================================================*/
|
||
|
|
||
|
#include <stdio.h>
|
||
|
#include "ALACBitUtilities.h"
|
||
|
|
||
|
// BitBufferInit
|
||
|
//
|
||
|
void BitBufferInit( BitBuffer * bits, uint8_t * buffer, uint32_t byteSize )
|
||
|
{
|
||
|
bits->cur = buffer;
|
||
|
bits->end = bits->cur + byteSize;
|
||
|
bits->bitIndex = 0;
|
||
|
bits->byteSize = byteSize;
|
||
|
}
|
||
|
|
||
|
// BitBufferRead
|
||
|
//
|
||
|
uint32_t BitBufferRead( BitBuffer * bits, uint8_t numBits )
|
||
|
{
|
||
|
uint32_t returnBits;
|
||
|
|
||
|
//Assert( numBits <= 16 );
|
||
|
|
||
|
returnBits = ((uint32_t)bits->cur[0] << 16) | ((uint32_t)bits->cur[1] << 8) | ((uint32_t)bits->cur[2]);
|
||
|
returnBits = returnBits << bits->bitIndex;
|
||
|
returnBits &= 0x00FFFFFF;
|
||
|
|
||
|
bits->bitIndex += numBits;
|
||
|
|
||
|
returnBits = returnBits >> (24 - numBits);
|
||
|
|
||
|
bits->cur += (bits->bitIndex >> 3);
|
||
|
bits->bitIndex &= 7;
|
||
|
|
||
|
//Assert( bits->cur <= bits->end );
|
||
|
|
||
|
return returnBits;
|
||
|
}
|
||
|
|
||
|
// BitBufferReadSmall
|
||
|
//
|
||
|
// Reads up to 8 bits
|
||
|
uint8_t BitBufferReadSmall( BitBuffer * bits, uint8_t numBits )
|
||
|
{
|
||
|
uint16_t returnBits;
|
||
|
|
||
|
//Assert( numBits <= 8 );
|
||
|
|
||
|
returnBits = (bits->cur[0] << 8) | bits->cur[1];
|
||
|
returnBits = returnBits << bits->bitIndex;
|
||
|
|
||
|
bits->bitIndex += numBits;
|
||
|
|
||
|
returnBits = returnBits >> (16 - numBits);
|
||
|
|
||
|
bits->cur += (bits->bitIndex >> 3);
|
||
|
bits->bitIndex &= 7;
|
||
|
|
||
|
//Assert( bits->cur <= bits->end );
|
||
|
|
||
|
return (uint8_t)returnBits;
|
||
|
}
|
||
|
|
||
|
// BitBufferReadOne
|
||
|
//
|
||
|
// Reads one byte
|
||
|
uint8_t BitBufferReadOne( BitBuffer * bits )
|
||
|
{
|
||
|
uint8_t returnBits;
|
||
|
|
||
|
returnBits = (bits->cur[0] >> (7 - bits->bitIndex)) & 1;
|
||
|
|
||
|
bits->bitIndex++;
|
||
|
|
||
|
bits->cur += (bits->bitIndex >> 3);
|
||
|
bits->bitIndex &= 7;
|
||
|
|
||
|
//Assert( bits->cur <= bits->end );
|
||
|
|
||
|
return returnBits;
|
||
|
}
|
||
|
|
||
|
// BitBufferPeek
|
||
|
//
|
||
|
uint32_t BitBufferPeek( BitBuffer * bits, uint8_t numBits )
|
||
|
{
|
||
|
return ((((((uint32_t) bits->cur[0] << 16) | ((uint32_t) bits->cur[1] << 8) |
|
||
|
((uint32_t) bits->cur[2])) << bits->bitIndex) & 0x00FFFFFF) >> (24 - numBits));
|
||
|
}
|
||
|
|
||
|
// BitBufferPeekOne
|
||
|
//
|
||
|
uint32_t BitBufferPeekOne( BitBuffer * bits )
|
||
|
{
|
||
|
return ((bits->cur[0] >> (7 - bits->bitIndex)) & 1);
|
||
|
}
|
||
|
|
||
|
// BitBufferUnpackBERSize
|
||
|
//
|
||
|
uint32_t BitBufferUnpackBERSize( BitBuffer * bits )
|
||
|
{
|
||
|
uint32_t size;
|
||
|
uint8_t tmp;
|
||
|
|
||
|
for ( size = 0, tmp = 0x80u; tmp &= 0x80u; size = (size << 7u) | (tmp & 0x7fu) )
|
||
|
tmp = (uint8_t) BitBufferReadSmall( bits, 8 );
|
||
|
|
||
|
return size;
|
||
|
}
|
||
|
|
||
|
// BitBufferGetPosition
|
||
|
//
|
||
|
uint32_t BitBufferGetPosition( BitBuffer * bits )
|
||
|
{
|
||
|
uint8_t * begin;
|
||
|
|
||
|
begin = bits->end - bits->byteSize;
|
||
|
|
||
|
return ((uint32_t)(bits->cur - begin) * 8) + bits->bitIndex;
|
||
|
}
|
||
|
|
||
|
// BitBufferByteAlign
|
||
|
//
|
||
|
void BitBufferByteAlign( BitBuffer * bits, int32_t addZeros )
|
||
|
{
|
||
|
// align bit buffer to next byte boundary, writing zeros if requested
|
||
|
if ( bits->bitIndex == 0 )
|
||
|
return;
|
||
|
|
||
|
if ( addZeros )
|
||
|
BitBufferWrite( bits, 0, 8 - bits->bitIndex );
|
||
|
else
|
||
|
BitBufferAdvance( bits, 8 - bits->bitIndex );
|
||
|
}
|
||
|
|
||
|
// BitBufferAdvance
|
||
|
//
|
||
|
void BitBufferAdvance( BitBuffer * bits, uint32_t numBits )
|
||
|
{
|
||
|
if ( numBits )
|
||
|
{
|
||
|
bits->bitIndex += numBits;
|
||
|
bits->cur += (bits->bitIndex >> 3);
|
||
|
bits->bitIndex &= 7;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// BitBufferRewind
|
||
|
//
|
||
|
void BitBufferRewind( BitBuffer * bits, uint32_t numBits )
|
||
|
{
|
||
|
uint32_t numBytes;
|
||
|
|
||
|
if ( numBits == 0 )
|
||
|
return;
|
||
|
|
||
|
if ( bits->bitIndex >= numBits )
|
||
|
{
|
||
|
bits->bitIndex -= numBits;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
numBits -= bits->bitIndex;
|
||
|
bits->bitIndex = 0;
|
||
|
|
||
|
numBytes = numBits / 8;
|
||
|
numBits = numBits % 8;
|
||
|
|
||
|
bits->cur -= numBytes;
|
||
|
|
||
|
if ( numBits > 0 )
|
||
|
{
|
||
|
bits->bitIndex = 8 - numBits;
|
||
|
bits->cur--;
|
||
|
}
|
||
|
|
||
|
if ( bits->cur < (bits->end - bits->byteSize) )
|
||
|
{
|
||
|
//DebugCMsg("BitBufferRewind: Rewound too far.");
|
||
|
|
||
|
bits->cur = (bits->end - bits->byteSize);
|
||
|
bits->bitIndex = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// BitBufferWrite
|
||
|
//
|
||
|
void BitBufferWrite( BitBuffer * bits, uint32_t bitValues, uint32_t numBits )
|
||
|
{
|
||
|
uint32_t invBitIndex;
|
||
|
|
||
|
RequireAction( bits != nil, return; );
|
||
|
RequireActionSilent( numBits > 0, return; );
|
||
|
|
||
|
invBitIndex = 8 - bits->bitIndex;
|
||
|
|
||
|
while ( numBits > 0 )
|
||
|
{
|
||
|
uint32_t tmp;
|
||
|
uint8_t shift;
|
||
|
uint8_t mask;
|
||
|
uint32_t curNum;
|
||
|
|
||
|
curNum = MIN( invBitIndex, numBits );
|
||
|
|
||
|
tmp = bitValues >> (numBits - curNum);
|
||
|
|
||
|
shift = (uint8_t)(invBitIndex - curNum);
|
||
|
mask = 0xffu >> (8 - curNum); // must be done in two steps to avoid compiler sequencing ambiguity
|
||
|
mask <<= shift;
|
||
|
|
||
|
bits->cur[0] = (bits->cur[0] & ~mask) | (((uint8_t) tmp << shift) & mask);
|
||
|
numBits -= curNum;
|
||
|
|
||
|
// increment to next byte if need be
|
||
|
invBitIndex -= curNum;
|
||
|
if ( invBitIndex == 0 )
|
||
|
{
|
||
|
invBitIndex = 8;
|
||
|
bits->cur++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bits->bitIndex = 8 - invBitIndex;
|
||
|
}
|
||
|
|
||
|
void BitBufferReset( BitBuffer * bits )
|
||
|
//void BitBufferInit( BitBuffer * bits, uint8_t * buffer, uint32_t byteSize )
|
||
|
{
|
||
|
bits->cur = bits->end - bits->byteSize;
|
||
|
bits->bitIndex = 0;
|
||
|
}
|
||
|
|
||
|
#if PRAGMA_MARK
|
||
|
#pragma mark -
|
||
|
#endif
|