| /* | |
| * 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" | |
| #define PRAGMA_MARK 0 | |
| // 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 != NULL, 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 |