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 fread(buffer, sizeof(usint), this->size, file);
59 // This version does not delete the data when deleted.
60 ReadBuffer(const usint* buffer, usint words) :
70 // This version does not delete the data when deleted.
71 ReadBuffer(const usint* buffer, usint _items, usint item_size) :
76 this->size = bitsToWords(this->items * this->item_bits);
81 // This version does not delete the data when deleted.
82 ReadBuffer(const ReadBuffer& original) :
85 item_bits(original.item_bits),
86 items(original.items),
100 //--------------------------------------------------------------------------
104 this->free_buffer = true;
107 void writeBuffer(std::ofstream& file) const
109 file.write((const char*)this->data, this->size * sizeof(usint));
111 void writeBuffer(std::FILE* file) const
113 fwrite(this->data, sizeof(usint), this->size, file);
116 // The buffer will no longer own the data.
117 void moveBuffer(const usint* buffer)
119 if(this->free_buffer)
123 this->free_buffer = false;
129 usint reportSize() const
131 usint bytes = sizeof(*this);
132 if(this->free_buffer) { bytes += this->size * sizeof(usint); }
136 //--------------------------------------------------------------------------
141 this->bits = WORD_BITS;
145 inline void skipBits(usint count)
147 if(count < this->bits)
154 this->pos += 1 + count / WORD_BITS;
155 this->bits = WORD_BITS - count % WORD_BITS;
158 //--------------------------------------------------------------------------
160 inline usint bitsLeft() const
162 return this->bits + WORD_BITS * (this->size - this->pos - 1);
165 // Returns nonzero if bit is 1
166 inline usint readBit()
169 usint bit = this->data[this->pos] & ((usint)1 << this->bits);
171 if(this->bits == 0) { this->pos++; this->bits = WORD_BITS; }
176 inline usint readBits(usint count)
180 if(count >= this->bits)
183 value |= HIGHER(GET(this->data[this->pos], this->bits), count);
184 this->pos++; this->bits = WORD_BITS;
189 value |= GET(LOWER(this->data[this->pos], this->bits), count);
195 //--------------------------------------------------------------------------
198 These operations work on 4-bit nibbles.
199 Do not use these with the bit-level operations.
202 inline usint readNibble()
205 usint value = GET(LOWER(this->data[this->pos], this->bits), 4);
207 if(this->bits == 0) { this->pos++; this->bits = WORD_BITS; }
212 // Nibble code for positive integers.
213 inline usint readNibbleCode()
215 usint temp, value = 0, shift = 0;
218 temp = this->readNibble();
219 value |= (temp & 0x7) << shift;
222 while((temp & 0x8) == 0);
227 //--------------------------------------------------------------------------
230 These operations work on fixed-size items. No sanity checks are made
231 for parameter values.
234 inline usint getItemSize() const
236 return this->item_bits;
239 inline void goToItem(usint item)
241 usint b = item * this->item_bits;
242 this->pos = b / WORD_BITS;
243 this->bits = WORD_BITS - b % WORD_BITS;
244 this->current = item;
247 inline usint readItem()
250 return this->readBits(this->item_bits);
253 inline usint readItem(usint item)
255 this->goToItem(item);
256 return this->readItem();
259 inline usint readFirstItem()
261 return this->readItem(0);
264 inline usint readItemConst(usint item) const
266 usint b = item * this->item_bits;
267 usint p = b / WORD_BITS;
268 b = WORD_BITS - b % WORD_BITS;
270 usint c = this->item_bits;
276 value |= HIGHER(GET(this->data[p], b), c);
282 value |= GET(LOWER(this->data[p], b), c);
288 inline bool hasNextItem() const
290 return (this->current < this->items);
293 inline void skipItem()
295 this->skipBits(this->item_bits);
299 //--------------------------------------------------------------------------
302 Delta coding for positive integers
305 inline usint readDeltaCode()
308 while(this->readBit() == 0) { len++; }
310 usint temp = (((usint)1 << len) | this->readBits(len)) - 1;
311 temp = ((usint)1 << temp) | this->readBits(temp);
315 //--------------------------------------------------------------------------
319 usint size, item_bits, items;
323 usint pos, bits, current;
325 inline static usint bitsToWords(usint _bits) { return (_bits + WORD_BITS - 1) / WORD_BITS; }
327 // These are not allowed.
329 ReadBuffer& operator = (const ReadBuffer&);
333 //--------------------------------------------------------------------------
339 WriteBuffer(usint words) :
345 this->data = new usint[words];
346 memset(this->data, 0, this->size * sizeof(usint));
350 WriteBuffer(usint _items, usint item_size) :
351 item_bits(item_size),
355 this->size = bitsToWords(this->items * this->item_bits);
356 this->data = new usint[this->size];
357 memset(this->data, 0, this->size * sizeof(usint));
361 // This version does not delete the data when deleted.
362 WriteBuffer(usint* buffer, usint words) :
372 // This version does not delete the data when deleted.
373 WriteBuffer(usint* buffer, usint _items, usint item_size) :
374 item_bits(item_size),
378 this->size = bitsToWords(this->items * this->item_bits);
385 if(this->free_buffer)
391 //--------------------------------------------------------------------------
393 // This transfers the ownership of the data to the read buffer.
394 ReadBuffer* getReadBuffer()
399 buffer = new ReadBuffer(this->data, this->items, this->item_bits);
403 buffer = new ReadBuffer(this->data, this->size);
406 if(this->free_buffer)
409 this->free_buffer = false;
415 void writeBuffer(std::ofstream& file) const
417 file.write((char*)this->data, this->size * sizeof(usint));
419 void writeBuffer(std::FILE *file) const
421 fwrite(this->data, sizeof(usint), this->size, file);
424 // The buffer will no longer own the data.
425 void moveBuffer(usint* buffer)
427 if(this->free_buffer)
431 this->free_buffer = false;
437 usint reportSize() const
439 usint bytes = sizeof(*this);
440 if(this->free_buffer) { bytes += this->size * sizeof(usint); }
444 //--------------------------------------------------------------------------
449 this->bits = WORD_BITS;
453 inline void skipBits(usint count)
455 if(count < this->bits)
462 this->pos += 1 + count / WORD_BITS;
463 this->bits = WORD_BITS - count % WORD_BITS;
466 //--------------------------------------------------------------------------
468 inline usint bitsLeft() const
470 return this->bits + WORD_BITS * (this->size - this->pos - 1);
473 inline void writeBits(usint value, usint count)
475 if(count >= this->bits)
478 this->data[this->pos] |= GET(LOWER(value, count), this->bits);
479 this->pos++; this->bits = WORD_BITS;
484 this->data[this->pos] |= HIGHER(GET(value, count), this->bits);
488 //--------------------------------------------------------------------------
491 These operations work on fixed-size items.
494 inline usint getItemSize() const
496 return this->item_bits;
499 inline void goToItem(usint item)
501 usint b = item * this->item_bits;
502 this->pos = b / WORD_BITS;
503 this->bits = WORD_BITS - b % WORD_BITS;
504 this->current = item;
507 inline bool hasNextItem() const
509 return (this->current < this->items);
512 inline void writeItem(usint item)
514 this->writeBits(item, this->item_bits);
518 inline void skipItem()
520 this->skipBits(this->item_bits);
524 //--------------------------------------------------------------------------
527 Nibble coding for positive integers.
530 inline usint nibbleCodeLength(usint value) const
545 // Something breaks very badly if value > 15.
546 inline void writeNibble(usint value)
549 this->data[this->pos] |= HIGHER(value, this->bits);
550 if(this->bits == 0) { this->pos++; this->bits = WORD_BITS; }
553 // It is assumed that there is enough space for the code.
554 inline void writeNibbleCode(usint value)
559 this->writeNibble(value & 0x7);
562 this->writeNibble(value | 0x8);
565 //--------------------------------------------------------------------------
568 Delta coding for positive integers
571 inline bool canDeltaCode(usint value) const
573 return this->deltaCodeLength(value) <= this->bitsLeft();
576 inline usint deltaCodeLength(usint value) const
578 usint len = length(value);
579 usint llen = length(len);
580 return (len + llen + llen - 2);
583 // This version returns false if there is no space left for the encoding.
584 inline bool writeDeltaCode(usint value)
586 usint len = length(value);
587 usint llen = length(len);
589 if(len + llen + llen - 2 > this->bitsLeft()) { return false; }
591 // this->writeBits(0, llen - 1); // Now included in the next writeBits()
592 this->writeBits(len, llen + llen - 1);
593 this->writeBits(value, len - 1);
597 // This version assumes the code fits into the buffer.
598 inline void writeDeltaCodeDirect(usint value)
600 usint len = length(value);
601 usint llen = length(len);
603 // this->writeBits(0, llen - 1); // Now included in the next writeBits()
604 this->writeBits(len, llen + llen - 1);
605 this->writeBits(value, len - 1);
608 // We assume the code fits into usint:
609 // 32-bit: value < 2^24
610 // 64-bit: value < 2^54
611 inline void writeDeltaCodeFast(usint value)
613 usint len = length(value);
615 value ^= ((usint)1 << (len - 1));
616 this->writeBits((len << (len - 1)) | value, len + 2 * length(len) - 2);
619 //--------------------------------------------------------------------------
623 usint size, item_bits, items;
627 usint pos, bits, current;
629 inline static usint bitsToWords(usint _bits) { return (_bits + WORD_BITS - 1) / WORD_BITS; }
631 // These are not allowed.
633 WriteBuffer(const WriteBuffer&);
634 WriteBuffer& operator = (const WriteBuffer&);
638 //--------------------------------------------------------------------------
644 #endif // BITBUFFER_H