1 /* 2 * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 #include "BitBuffer.h" 8 9 10 // #pragma mark - BitReader 11 12 13 struct BitBuffer::BitReader { 14 const uint8* data; 15 uint64 bitSize; 16 uint32 bitOffset; 17 18 BitReader(const uint8* data, uint64 bitSize, uint32 bitOffset) 19 : 20 data(data), 21 bitSize(bitSize), 22 bitOffset(bitOffset) 23 { 24 } 25 26 uint8 ReadByte() 27 { 28 uint8 byte = *data; 29 data++; 30 bitSize -= 8; 31 32 if (bitOffset == 0) 33 return byte; 34 35 return (byte << bitOffset) | (*data >> (8 - bitOffset)); 36 } 37 38 uint8 ReadBits(uint32 count) 39 { 40 uint8 byte = *data; 41 bitSize -= count; 42 bitOffset += count; 43 44 if (bitOffset <= 8) { 45 if (bitOffset == 8) { 46 bitOffset = 0; 47 data++; 48 return byte & ((1 << count) - 1); 49 } 50 51 return (byte >> (8 - bitOffset)) & ((1 << count) - 1); 52 } 53 54 data++; 55 bitOffset -= 8; 56 return ((byte << bitOffset) | (*data >> (8 - bitOffset))) 57 & ((1 << count) - 1); 58 } 59 }; 60 61 62 // #pragma mark - BitBuffer 63 64 65 BitBuffer::BitBuffer() 66 : 67 fMissingBits(0) 68 { 69 } 70 71 72 BitBuffer::~BitBuffer() 73 { 74 } 75 76 77 bool 78 BitBuffer::AddBytes(const void* data, size_t size) 79 { 80 if (size == 0) 81 return true; 82 83 if (fMissingBits == 0) { 84 size_t oldSize = fBytes.Size(); 85 if (!fBytes.AddUninitialized(size)) 86 return false; 87 88 memcpy(fBytes.Elements() + oldSize, data, size); 89 return true; 90 } 91 92 return AddBits(data, (uint64)size * 8, 0); 93 } 94 95 96 bool 97 BitBuffer::AddBits(const void* _data, uint64 bitSize, uint32 bitOffset) 98 { 99 if (bitSize == 0) 100 return true; 101 102 const uint8* data = (const uint8*)_data + bitOffset / 8; 103 bitOffset %= 8; 104 105 BitReader reader(data, bitSize, bitOffset); 106 107 // handle special case first: no more bits than missing 108 size_t oldSize = fBytes.Size(); 109 if (fMissingBits > 0 && bitSize <= fMissingBits) { 110 fMissingBits -= bitSize; 111 uint8 bits = reader.ReadBits(bitSize) << fMissingBits; 112 fBytes[oldSize - 1] |= bits; 113 return true; 114 } 115 116 // resize the buffer 117 if (!fBytes.AddUninitialized((reader.bitSize - fMissingBits + 7) / 8)) 118 return false; 119 120 // fill in missing bits 121 if (fMissingBits > 0) { 122 fBytes[oldSize - 1] |= reader.ReadBits(fMissingBits); 123 fMissingBits = 0; 124 } 125 126 // read full bytes as long as we can 127 uint8* buffer = fBytes.Elements() + oldSize; 128 while (reader.bitSize >= 8) { 129 *buffer = reader.ReadByte(); 130 buffer++; 131 } 132 133 // If we have left-over bits, write a partial byte. 134 if (reader.bitSize > 0) { 135 fMissingBits = 8 - reader.bitSize; 136 *buffer = reader.ReadBits(reader.bitSize) << fMissingBits; 137 } 138 139 return true; 140 } 141 142 143 bool 144 BitBuffer::AddZeroBits(uint64 bitSize) 145 { 146 if (bitSize == 0) 147 return true; 148 149 // handle special case first: no more bits than missing 150 size_t oldSize = fBytes.Size(); 151 if (fMissingBits > 0 && bitSize <= fMissingBits) { 152 fMissingBits -= bitSize; 153 return true; 154 } 155 156 // resize the buffer 157 if (!fBytes.AddUninitialized((bitSize - fMissingBits + 7) / 8)) 158 return false; 159 160 // fill in missing bits 161 if (fMissingBits > 0) { 162 bitSize -= fMissingBits; 163 fMissingBits = 0; 164 } 165 166 // zero the remaining bytes, including a potentially partial last byte 167 uint8* buffer = fBytes.Elements() + oldSize; 168 memset(buffer, 0, (bitSize + 7) / 8); 169 bitSize %= 8; 170 171 if (bitSize > 0) 172 fMissingBits = 8 - bitSize; 173 174 return true; 175 } 176