Last active
August 29, 2015 14:14
-
-
Save ianpark/1a385ec48c88e37db3ae to your computer and use it in GitHub Desktop.
BitReader
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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