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