10 #include "../misc/definitions.h"
20 ReadBuffer(std::ifstream& file, usint words) :
26 usint* buffer = new usint[this->size];
27 memset(buffer, 0, this->size * sizeof(usint));
28 file.read((char*)buffer, this->size * sizeof(usint));
33 ReadBuffer(std::ifstream& file, usint _items, usint item_size) :
38 this->size = bitsToWords(this->items * this->item_bits);
39 usint* buffer = new usint[this->size];
40 memset(buffer, 0, this->size * sizeof(usint));
41 file.read((char*)buffer, this->size * sizeof(usint));
46 ReadBuffer(std::FILE* file, usint _items, usint item_size) :
51 this->size = bitsToWords(this->items * this->item_bits);
52 usint* buffer = new usint[this->size];
53 memset(buffer, 0, this->size * sizeof(usint));
54 if (fread(buffer, sizeof(usint), this->size, file) != this->size)
56 std::cerr << "ReadBuffer constructor: Unable to read file" << std::endl;
63 // This version does not delete the data when deleted.
64 ReadBuffer(const usint* buffer, usint words) :
74 // This version does not delete the data when deleted.
75 ReadBuffer(const usint* buffer, usint _items, usint item_size) :
80 this->size = bitsToWords(this->items * this->item_bits);
85 // This version does not delete the data when deleted.
86 ReadBuffer(const ReadBuffer& original) :
89 item_bits(original.item_bits),
90 items(original.items),
104 //--------------------------------------------------------------------------
108 this->free_buffer = true;
111 void writeBuffer(std::ofstream& file) const
113 file.write((const char*)this->data, this->size * sizeof(usint));
115 void writeBuffer(std::FILE* file) const
117 fwrite(this->data, sizeof(usint), this->size, file);
120 // The buffer will no longer own the data.
121 void moveBuffer(const usint* buffer)
123 if(this->free_buffer)
127 this->free_buffer = false;
133 usint reportSize() const
135 usint bytes = sizeof(*this);
136 if(this->free_buffer) { bytes += this->size * sizeof(usint); }
140 //--------------------------------------------------------------------------
145 this->bits = WORD_BITS;
149 inline void skipBits(usint count)
151 if(count < this->bits)
158 this->pos += 1 + count / WORD_BITS;
159 this->bits = WORD_BITS - count % WORD_BITS;
162 //--------------------------------------------------------------------------
164 inline usint bitsLeft() const
166 return this->bits + WORD_BITS * (this->size - this->pos - 1);
169 // Returns nonzero if bit is 1
170 inline usint readBit()
173 usint bit = this->data[this->pos] & ((usint)1 << this->bits);
175 if(this->bits == 0) { this->pos++; this->bits = WORD_BITS; }
180 inline usint readBits(usint count)
184 if(count >= this->bits)
187 value |= HIGHER(GET(this->data[this->pos], this->bits), count);
188 this->pos++; this->bits = WORD_BITS;
193 value |= GET(LOWER(this->data[this->pos], this->bits), count);
199 //--------------------------------------------------------------------------
202 These operations work on 4-bit nibbles.
203 Do not use these with the bit-level operations.
206 inline usint readNibble()
209 usint value = GET(LOWER(this->data[this->pos], this->bits), 4);
211 if(this->bits == 0) { this->pos++; this->bits = WORD_BITS; }
216 // Nibble code for positive integers.
217 inline usint readNibbleCode()
219 usint temp, value = 0, shift = 0;
222 temp = this->readNibble();
223 value |= (temp & 0x7) << shift;
226 while((temp & 0x8) == 0);
231 //--------------------------------------------------------------------------
234 These operations work on fixed-size items. No sanity checks are made
235 for parameter values.
238 inline usint getItemSize() const
240 return this->item_bits;
243 inline void goToItem(usint item)
245 usint b = item * this->item_bits;
246 this->pos = b / WORD_BITS;
247 this->bits = WORD_BITS - b % WORD_BITS;
248 this->current = item;
251 inline usint readItem()
254 return this->readBits(this->item_bits);
257 inline usint readItem(usint item)
259 this->goToItem(item);
260 return this->readItem();
263 inline usint readFirstItem()
265 return this->readItem(0);
268 inline usint readItemConst(usint item) const
270 usint b = item * this->item_bits;
271 usint p = b / WORD_BITS;
272 b = WORD_BITS - b % WORD_BITS;
274 usint c = this->item_bits;
280 value |= HIGHER(GET(this->data[p], b), c);
286 value |= GET(LOWER(this->data[p], b), c);
292 inline bool hasNextItem() const
294 return (this->current < this->items);
297 inline void skipItem()
299 this->skipBits(this->item_bits);
303 //--------------------------------------------------------------------------
306 Delta coding for positive integers
309 inline usint readDeltaCode()
312 while(this->readBit() == 0) { len++; }
314 usint temp = (((usint)1 << len) | this->readBits(len)) - 1;
315 temp = ((usint)1 << temp) | this->readBits(temp);
319 //--------------------------------------------------------------------------
323 usint size, item_bits, items;
327 usint pos, bits, current;
329 inline static usint bitsToWords(usint _bits) { return (_bits + WORD_BITS - 1) / WORD_BITS; }
331 // These are not allowed.
333 ReadBuffer& operator = (const ReadBuffer&);
337 //--------------------------------------------------------------------------
343 WriteBuffer(usint words) :
349 this->data = new usint[words];
350 memset(this->data, 0, this->size * sizeof(usint));
354 WriteBuffer(usint _items, usint item_size) :
355 item_bits(item_size),
359 this->size = bitsToWords(this->items * this->item_bits);
360 this->data = new usint[this->size];
361 memset(this->data, 0, this->size * sizeof(usint));
365 // This version does not delete the data when deleted.
366 WriteBuffer(usint* buffer, usint words) :
376 // This version does not delete the data when deleted.
377 WriteBuffer(usint* buffer, usint _items, usint item_size) :
378 item_bits(item_size),
382 this->size = bitsToWords(this->items * this->item_bits);
389 if(this->free_buffer)
395 //--------------------------------------------------------------------------
397 // This transfers the ownership of the data to the read buffer.
398 ReadBuffer* getReadBuffer()
403 buffer = new ReadBuffer(this->data, this->items, this->item_bits);
407 buffer = new ReadBuffer(this->data, this->size);
410 if(this->free_buffer)
413 this->free_buffer = false;
419 void writeBuffer(std::ofstream& file) const
421 file.write((char*)this->data, this->size * sizeof(usint));
423 void writeBuffer(std::FILE *file) const
425 fwrite(this->data, sizeof(usint), this->size, file);
428 // The buffer will no longer own the data.
429 void moveBuffer(usint* buffer)
431 if(this->free_buffer)
435 this->free_buffer = false;
441 usint reportSize() const
443 usint bytes = sizeof(*this);
444 if(this->free_buffer) { bytes += this->size * sizeof(usint); }
448 //--------------------------------------------------------------------------
453 this->bits = WORD_BITS;
457 inline void skipBits(usint count)
459 if(count < this->bits)
466 this->pos += 1 + count / WORD_BITS;
467 this->bits = WORD_BITS - count % WORD_BITS;
470 //--------------------------------------------------------------------------
472 inline usint bitsLeft() const
474 return this->bits + WORD_BITS * (this->size - this->pos - 1);
477 inline void writeBits(usint value, usint count)
479 if(count >= this->bits)
482 this->data[this->pos] |= GET(LOWER(value, count), this->bits);
483 this->pos++; this->bits = WORD_BITS;
488 this->data[this->pos] |= HIGHER(GET(value, count), this->bits);
492 //--------------------------------------------------------------------------
495 These operations work on fixed-size items.
498 inline usint getItemSize() const
500 return this->item_bits;
503 inline void goToItem(usint item)
505 usint b = item * this->item_bits;
506 this->pos = b / WORD_BITS;
507 this->bits = WORD_BITS - b % WORD_BITS;
508 this->current = item;
511 inline bool hasNextItem() const
513 return (this->current < this->items);
516 inline void writeItem(usint item)
518 this->writeBits(item, this->item_bits);
522 inline void skipItem()
524 this->skipBits(this->item_bits);
528 //--------------------------------------------------------------------------
531 Nibble coding for positive integers.
534 inline usint nibbleCodeLength(usint value) const
549 // Something breaks very badly if value > 15.
550 inline void writeNibble(usint value)
553 this->data[this->pos] |= HIGHER(value, this->bits);
554 if(this->bits == 0) { this->pos++; this->bits = WORD_BITS; }
557 // It is assumed that there is enough space for the code.
558 inline void writeNibbleCode(usint value)
563 this->writeNibble(value & 0x7);
566 this->writeNibble(value | 0x8);
569 //--------------------------------------------------------------------------
572 Delta coding for positive integers
575 inline bool canDeltaCode(usint value) const
577 return this->deltaCodeLength(value) <= this->bitsLeft();
580 inline usint deltaCodeLength(usint value) const
582 usint len = length(value);
583 usint llen = length(len);
584 return (len + llen + llen - 2);
587 // This version returns false if there is no space left for the encoding.
588 inline bool writeDeltaCode(usint value)
590 usint len = length(value);
591 usint llen = length(len);
593 if(len + llen + llen - 2 > this->bitsLeft()) { return false; }
595 // this->writeBits(0, llen - 1); // Now included in the next writeBits()
596 this->writeBits(len, llen + llen - 1);
597 this->writeBits(value, len - 1);
601 // This version assumes the code fits into the buffer.
602 inline void writeDeltaCodeDirect(usint value)
604 usint len = length(value);
605 usint llen = length(len);
607 // this->writeBits(0, llen - 1); // Now included in the next writeBits()
608 this->writeBits(len, llen + llen - 1);
609 this->writeBits(value, len - 1);
612 // We assume the code fits into usint:
613 // 32-bit: value < 2^24
614 // 64-bit: value < 2^54
615 inline void writeDeltaCodeFast(usint value)
617 usint len = length(value);
619 value ^= ((usint)1 << (len - 1));
620 this->writeBits((len << (len - 1)) | value, len + 2 * length(len) - 2);
623 //--------------------------------------------------------------------------
627 usint size, item_bits, items;
631 usint pos, bits, current;
633 inline static usint bitsToWords(usint _bits) { return (_bits + WORD_BITS - 1) / WORD_BITS; }
635 // These are not allowed.
637 WriteBuffer(const WriteBuffer&);
638 WriteBuffer& operator = (const WriteBuffer&);
642 //--------------------------------------------------------------------------
648 #endif // BITBUFFER_H