xref: /haiku/src/kits/debugger/util/BitBuffer.cpp (revision fce4895d1884da5ae6fb299d23c735c598e690b1)
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 
BitReaderBitBuffer::BitReader18 	BitReader(const uint8* data, uint64 bitSize, uint32 bitOffset)
19 		:
20 		data(data),
21 		bitSize(bitSize),
22 		bitOffset(bitOffset)
23 	{
24 	}
25 
ReadByteBitBuffer::BitReader26 	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 
ReadBitsBitBuffer::BitReader38 	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 
BitBuffer()65 BitBuffer::BitBuffer()
66 	:
67 	fMissingBits(0)
68 {
69 }
70 
71 
~BitBuffer()72 BitBuffer::~BitBuffer()
73 {
74 }
75 
76 
77 bool
AddBytes(const void * data,size_t size)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
AddBits(const void * _data,uint64 bitSize,uint32 bitOffset)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
AddZeroBits(uint64 bitSize)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