Skip to content

Instantly share code, notes, and snippets.

@ianpark
Last active August 29, 2015 14:14
Show Gist options
  • Save ianpark/1a385ec48c88e37db3ae to your computer and use it in GitHub Desktop.
Save ianpark/1a385ec48c88e37db3ae to your computer and use it in GitHub Desktop.
BitReader
#ifndef __BIT_READER__H_
#define __BIT_READER__H_
#include <iostream>
#include <stdexcept>
#include <algorithm>
#include <cmath>
class BitReader {
const static unsigned char inbyte_mask[];
public:
BitReader(unsigned const char* buffer, std::size_t size)
: _buffer(buffer), _size(size), _pos(0) {
}
BitReader() {
}
template<typename NewType> NewType read(std::size_t size) {
// Read and move the position
return readBits<NewType>(_pos, size);
}
template<typename NewType> NewType peek(std::size_t size) {
// Read and stay in the same position
std::size_t dummyPos = _pos;
return readBits<NewType>(dummyPos, size);
}
std::size_t pos() {
return _pos;
}
private:
template<typename NewType> NewType readBits(std::size_t& pos, std::size_t size) {
if(pos + size > _size*8) {
throw std::runtime_error("out of range");
}
if(size > sizeof(NewType)*8) {
throw std::runtime_error("Data is too big");
}
NewType value = 0;
std::size_t bitToCopy = size;
while(bitToCopy > 0) {
std::size_t byteOffset = (pos<8)?0:(pos/8);
std::size_t remainedBit = 8 - pos%8; // 1~8
std::size_t availableBit = std::min(remainedBit, bitToCopy);
// Get remained bit
unsigned char tmpData = _buffer[byteOffset]&inbyte_mask[remainedBit-1];
// Clear unnecessary bit
if(remainedBit > availableBit) {
tmpData >>= (remainedBit-availableBit);
}
// Copy the bits
if(value !=0) {
value <<= availableBit;
}
value |= tmpData;
// Adjust the size and position
bitToCopy -= availableBit;
pos += availableBit;
}
return value;
}
unsigned const char * _buffer;
std::size_t _size;
std::size_t _pos;
};
const unsigned char BitReader::inbyte_mask[] = {0x01,0x03,0x07,0x0f,0x1f,0x3f,0x7f,0xff};
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment