/* * 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 #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