scantools  1.0.4
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 
42 class bitVector
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
The bitVector class provides an array of bits, similar to QBitArray.
Definition: bitVector.h:43
void resize(int newSize)
Sets the size of the bitVector array to newSize bits.
bitVector(int numBits)
Constructs an array of size bits.
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
bool startsWith(const miniBitVector &mbv, int index=0) const
Check if the content of the given miniBitVector is found at a given position.
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.
void append(const miniBitVector &mbv)
Appends a miniBitVector to the end of the bitVector.
Definition: bitVector.h:168
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