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