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