scantools 1.0.8
Graphics manipulation with a view towards scanned documents
bitVector.h
1/*
2 * Copyright © 2017 - 2020 Stefan Kebekus <stefan.kebekus@math.uni-freiburg.de>
3 *
4 * This program is free software: you can redistribute it and/or modify it under
5 * the terms of the GNU General Public License as published by the Free Software
6 * Foundation, either version 3 of the License, or (at your option) any later
7 * version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12 * details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18
19#ifndef bitVECTOR
20#define bitVECTOR 1
21
22
23#include <QByteArray>
24#include <QString>
25
41
43{
44 public:
47
54 explicit bitVector(int numBits);
55
67 explicit bitVector(QByteArray data);
68
77 inline quint8 getBit(int index) const {
78 return (content[index/8] >> (7-index%8)) & 0x01;
79 }
80
89 inline void setBit(int index, quint8 bit) {
90 quint32 byteIndex = index/8;
91 if (bit)
92 content[byteIndex] = content[byteIndex] | (0b00000001 << (7-index%8));
93 else
94 content[byteIndex] = content[byteIndex] & ~(0b00000001 << (7-index%8));
95 }
96
101 inline int size() const {
102 return _size;
103 }
104
113 void resize(int newSize);
114
129 public:
131 quint8 numBits;
132
134 quint32 value;
135
144 inline quint8 getBit(int index) const {
145 return (value >> (numBits-1-index)) & 0x01;
146 }
147 };
148
160 bool startsWith(const miniBitVector mbv, int index=0) const;
161
168 inline void append(const miniBitVector mbv) {
169 // If contents array is too small, expand its size
170 if (_size+32 > content.size()*8)
171 content.resize(2*content.size()+1000);
172
173 quint32 value = mbv.value;
174 for(int i=0; i<mbv.numBits; i++) {
175 bool bit = value & 0x01;
176 value = value >> 1;
177 setBit(_size+mbv.numBits-1-i, bit);
178 }
179
180 _size += mbv.numBits;
181 }
182
193 operator QByteArray();
194
199 operator QString() const;
200
212 static inline quint8 getBit(const quint8 *ptr, int index) {
213 return (ptr[index/8] >> (7-index%8)) & 0x01;
214 }
215
227 static inline void setBit(quint8 *ptr, int index, quint8 bit) {
228 quint32 byteIndex = index/8;
229 if (bit)
230 ptr[byteIndex] = ptr[byteIndex] | (0b00000001 << (7-index%8));
231 else
232 ptr[byteIndex] = ptr[byteIndex] & ~(0b00000001 << (7-index%8));
233 }
234
251 static inline void fill(quint8 *ptr, int startIndex, int numBits, quint8 bit) {
252 quint32 endIndex = startIndex+numBits;
253 quint32 index=startIndex;
254 while(index < endIndex) {
255
256 if (index%8 == 0) {
257 uintptr_t currentBytePtr = (uintptr_t)(ptr+index/8);
258
259 if ((currentBytePtr%8 == 0) && (index+64<endIndex)) {
260 *((quint64 *)currentBytePtr) = (bit == 0) ? 0x0000000000000000 : 0xFFFFFFFFFFFFFFFF;
261 index += 64;
262 continue;
263 }
264
265 if ((currentBytePtr%4 == 0) && (index+32<endIndex)) {
266 *((quint32 *)currentBytePtr) = (bit == 0) ? 0x00000000 : 0xFFFFFFFF;
267 index += 32;
268 continue;
269 }
270
271 if ((currentBytePtr%2 == 0) && (index+16<endIndex)) {
272 // cppcheck-suppress unreadVariable
273 *((quint16 *)currentBytePtr) = (bit == 0) ? 0x0000 : 0xFFFF;
274 index += 16;
275 continue;
276 }
277
278 if (index+8<endIndex) {
279 ptr[index/8] = (bit == 0) ? 0x00 : 0xFF;
280 index += 8;
281 continue;
282 }
283 } // endif: index is on byte boundary
284
285 bitVector::setBit(ptr, index, bit);
286 index++;
287 }
288 }
289
304 static inline int findEndOfRun(const quint8 *ptr, int startIndex, int endIndex, quint8 runValue) {
305 int index=startIndex;
306
307 while(index < endIndex) {
308
309 if (index%8 == 0) {
310 uintptr_t currentBytePtr = (uintptr_t)(ptr+index/8);
311
312 // Handle 8-byte words efficiently
313 if ((currentBytePtr%8 == 0) && (endIndex-index >= 64)) {
314 if (runValue == 0) {
315 if ( *((quint64 *)currentBytePtr) == 0) {
316 index += 64;
317 continue;
318 }
319 } else {
320 if ( *((quint64 *)currentBytePtr) == 0xFFFFFFFFFFFFFFFF) {
321 index += 64;
322 continue;
323 }
324 }
325 }
326
327 // Handle 4-byte words efficiently
328 if ((currentBytePtr%4 == 0) && (endIndex-index >= 32)) {
329 if (runValue == 0) {
330 if ( *((quint32 *)currentBytePtr) == 0) {
331 index += 32;
332 continue;
333 }
334 } else {
335 if ( *((quint32 *)currentBytePtr) == 0xFFFFFFFF) {
336 index += 32;
337 continue;
338 }
339 }
340 }
341
342 // Handle 2-byte words efficiently
343 if ((currentBytePtr%2 == 0) && (endIndex-index >= 16)) {
344 if (runValue == 0) {
345 if ( *((quint16 *)currentBytePtr) == 0) {
346 index += 16;
347 continue;
348 }
349 } else {
350 if ( *((quint16 *)currentBytePtr) == 0xFFFF) {
351 index += 16;
352 continue;
353 }
354 }
355 }
356
357 // Handle 1-byte words efficiently
358 if (endIndex-index >= 8) {
359 if (runValue == 0) {
360 if (ptr[index/8] == 0) {
361 index += 8;
362 continue;
363 }
364 } else {
365 if (ptr[index/8] == 0xFF) {
366 index += 8;
367 continue;
368 }
369 }
370 }
371 } // endif: index is on byte boundary
372
373 if (bitVector::getBit(ptr, index) != runValue)
374 return index;
375 index++;
376 }
377
378 return endIndex;
379 }
380
381 private:
382 int _size;
383
384 QByteArray content;
385};
386
387#endif
Simple array of bits, useful for static data.
Definition bitVector.h:128
quint8 numBits
Number of bits stored, must be smaller than or equal to 32.
Definition bitVector.h:131
quint32 value
Array of bits, there the least significant bit is the last of the bits stored.
Definition bitVector.h:134
quint8 getBit(int index) const
Returns the bit at position index.
Definition bitVector.h:144
void resize(int newSize)
Sets the size of the bitVector array to newSize bits.
bitVector(int numBits)
Constructs an array of size bits.
void append(const miniBitVector mbv)
Appends a miniBitVector to the end of the bitVector.
Definition bitVector.h:168
static quint8 getBit(const quint8 *ptr, int index)
Convenience method for read access to a bit in a C-array of bytes.
Definition bitVector.h:212
int size() const
Size of the bitVector in bits.
Definition bitVector.h:101
static void setBit(quint8 *ptr, int index, quint8 bit)
Convenience method for write access to a bit in a C-array of bytes.
Definition bitVector.h:227
static int findEndOfRun(const quint8 *ptr, int startIndex, int endIndex, quint8 runValue)
Searches for end of a run of consecutive bits with same value.
Definition bitVector.h:304
quint8 getBit(int index) const
Returns the bit at position index.
Definition bitVector.h:77
bitVector(QByteArray data)
Constructs a bitVector from a QByteArray.
bitVector()
Constructs an empty bit array.
static void fill(quint8 *ptr, int startIndex, int numBits, quint8 bit)
Convenience method for write access to a continuous block of bits in a C-array of bytes.
Definition bitVector.h:251
void setBit(int index, quint8 bit)
Sets the bit at position index.
Definition bitVector.h:89
bool startsWith(const miniBitVector mbv, int index=0) const
Check if the content of the given miniBitVector is found at a given position.