Project

General

Profile

Download (8.6 KB) Statistics
| Branch: | Revision:
#ifndef BITOPS_H
#define BITOPS_H

#define RBITS( c, n ) ( c & ( 0xFF >> (8 - n) ) )
#define LBITS( c, n ) ( c >> (8 - n) )
#define MBITS( c, l, r ) ( RBITS( c,l ) >> r )
#define BITN( c, n ) ( (c >> n) & 0x1 )
#define BITLEN( l, v ) for ( l = 0; ( v >> l ) > 0; l++ )
#define FDIV2( v, p ) ( ( v < 0 ) ? -( (-v) >> p ) : ( v >> p ) )

#include <cstdint>
#include <memory>
#include <string>
#include <vector>

/* -----------------------------------------------
class to read arrays bitwise
----------------------------------------------- */
class BitReader {
public:
BitReader( unsigned char* array, int size );
~BitReader();
unsigned int read( int nbits );
unsigned char read_bit();
unsigned char unpad( unsigned char fillbit );
int getpos();
int getbitp();
void setpos( int pbyte, int pbit );
void rewind_bits( int nbits );
bool eof();
int peof();
private:
void update_curr_byte();

unsigned char* data = nullptr;
int lbyte = 0;
int cbyte = 0;
int cbit = 8;
int peof_ = 0;
bool eof_ = false;
};


class BitWriter {
public:
BitWriter(std::uint8_t padbit);
~BitWriter();
/*
* Writes the first (lowest) n bits from val (n is assumed to be less than or equal to 16).
*/
void write_u16(std::uint16_t val, std::size_t num_bits);

/*
* Writes the bit (assumed to be 0 or 1).
*/
void write_bit(std::uint8_t bit);
/**
* Fills in the remainder of the current byte using the padbit.
*/
void pad();
/**
* Returns a copy of the bytes written to the writer, padding the current byte if necessary.
*/
std::vector<std::uint8_t> get_bytes();
/**
* Allocates and returns a copy of the bytes written to the writer, padding the current byte if necessary.
*/
unsigned char* get_c_bytes();
/*
* Returns the number of bytes written. If a byte has not been fully written (e.g., only 5 bits have been written),
* then it is not counted in the number of bytes written.
*/
std::size_t num_bytes_written() const;
private:
void write_curr_byte();

std::vector<std::uint8_t> bytes_;
const std::uint8_t padbit_; // A bit, either 0 or 1, to fill the unwritten bits of the current byte with.
std::uint8_t curr_byte_ = 0; // The current byte being written.
std::size_t curr_bit_ = 8; // The position of the next bit in the current byte.
};

class Reader {
public:
Reader() {}

virtual ~Reader() {}

/*
* Reads the minimum of n and the number of unread bytes to the pointer.
*/
virtual std::size_t read(std::uint8_t* to, std::size_t n) = 0;

/*
* Reads the minimum of n and the number of unread bytes to the vector, starting at the given offset in the
* vector. If the destination vector is too small, it is resized. Returns the number of bytes read.
*/
virtual std::size_t read(std::vector<std::uint8_t>& into, std::size_t n, std::size_t offset = 0) = 0;

/*
* Returns one byte from the reader, throwing a std::runtime_error exception if there are none left to read.
*/
virtual std::uint8_t read_byte() = 0;

/*
* Reads one byte to the pointer, returning whether there was a byte available to writer.
*/
virtual bool read_byte(std::uint8_t* to) = 0;

/*
* Skips the minimum of the n and the number of unread bytes left in the reader.
*/
virtual void skip(std::size_t n) = 0;

/*
* Moves the reader back by the minimum of n and the number of bytes already read in the reader.
*/
virtual void rewind_bytes(std::size_t n) = 0;

/*
* Resets the number of bytes read to zero.
*/
virtual void rewind() = 0;

/*
* Returns the number of bytes read.
*/
virtual std::size_t num_bytes_read() = 0;

/*
* Returns the number of bytes in the reader.
*/
virtual std::size_t get_size() = 0;

/*
* Returns a copy of the data backing the reader.
*/
virtual std::vector<std::uint8_t> get_data() = 0;

unsigned char* get_c_data();

virtual bool error() = 0;
/*
* Returns whether all bytes in the reader have been read.
*/
virtual bool end_of_reader() = 0;
};

class MemoryReader : public Reader {
public:
MemoryReader(const std::vector<std::uint8_t>& bytes);
MemoryReader(const std::uint8_t* bytes, std::size_t size);

~MemoryReader() {}

std::size_t read(std::uint8_t* to, std::size_t num_to_read) override;
std::size_t read(std::vector<std::uint8_t>& into, std::size_t num_to_read, std::size_t offset = 0) override;
std::uint8_t read_byte() override;
bool read_byte(std::uint8_t* to) override;

void skip(std::size_t n) override;
void rewind_bytes(std::size_t n) override;
void rewind() override;

std::size_t num_bytes_read() override;
std::size_t get_size() override;
std::vector<std::uint8_t> get_data() override;
bool error() override;
bool end_of_reader() override;

private:
const std::vector<std::uint8_t> data_;
std::vector<std::uint8_t>::const_iterator cbyte_; // The position in the data of the byte being read.
};

class FileReader : public Reader {
public:
FileReader(const std::string& file_path);
~FileReader();

std::size_t read(std::uint8_t* to, std::size_t num_to_read) override;
std::size_t read(std::vector<std::uint8_t>& into, std::size_t num_to_read, std::size_t offset = 0) override;
std::uint8_t read_byte() override;
bool read_byte(std::uint8_t* to) override;

void skip(std::size_t n) override;
void rewind_bytes(std::size_t n) override;
void rewind() override;

std::size_t num_bytes_read() override;
std::size_t get_size() override;
std::vector<std::uint8_t> get_data() override;
bool error() override;
bool end_of_reader() override;

private:
std::unique_ptr<MemoryReader> reader_;
};

class StreamReader : public Reader {
public:
StreamReader();

~StreamReader() {}

std::size_t read(std::uint8_t* to, std::size_t num_to_read) override;
std::size_t read(std::vector<std::uint8_t>& into, std::size_t num_to_read, std::size_t offset = 0) override;
std::uint8_t read_byte() override;
bool read_byte(std::uint8_t* to) override;

void skip(std::size_t n) override;
void rewind_bytes(std::size_t n) override;
void rewind() override;

std::size_t num_bytes_read() override;
std::size_t get_size() override;
std::vector<std::uint8_t> get_data() override;
bool error() override;
bool end_of_reader() override;

private:
std::unique_ptr<MemoryReader> reader_;
};

class Writer {
public:
Writer() {}

virtual ~Writer() {}

virtual std::size_t write(const std::uint8_t* from, std::size_t n) = 0;
virtual std::size_t write(const std::vector<std::uint8_t>& bytes) = 0;
virtual std::size_t write(const std::array<std::uint8_t, 2>& bytes) = 0;

virtual bool write_byte(std::uint8_t byte) = 0;

virtual std::vector<std::uint8_t> get_data() = 0;
unsigned char* get_c_data();

virtual void reset() = 0;
virtual std::size_t num_bytes_written() = 0;
virtual bool error() = 0;
};

class MemoryWriter : public Writer {
public:
MemoryWriter();

~MemoryWriter() {}

std::size_t write(const std::uint8_t* from, std::size_t n) override;
std::size_t write(const std::vector<std::uint8_t>& bytes) override;
std::size_t write(const std::array<std::uint8_t, 2>& bytes) override;
bool write_byte(std::uint8_t byte) override;

std::vector<std::uint8_t> get_data() override;

void reset() override;
std::size_t num_bytes_written() override;
bool error() override;

private:
std::vector<std::uint8_t> data_;
};

class FileWriter : public Writer {
public:
FileWriter(const std::string& file_path);
~FileWriter();

std::size_t write(const std::uint8_t* from, std::size_t n) override;
std::size_t write(const std::vector<std::uint8_t>& bytes) override;
std::size_t write(const std::array<std::uint8_t, 2>& bytes) override;
bool write_byte(std::uint8_t byte) override;

std::vector<std::uint8_t> get_data() override;

void reset() override;
std::size_t num_bytes_written() override;
bool error() override;

private:
FILE* fptr_ = nullptr;
std::vector<char> file_buffer_; // Used to replace the default file buffer for reads/writes to improve performance.
const std::string file_path_;
};

class StreamWriter : public Writer {
public:
StreamWriter();
~StreamWriter();

std::size_t write(const std::uint8_t* from, std::size_t n) override;
std::size_t write(const std::vector<std::uint8_t>& bytes) override;
std::size_t write(const std::array<std::uint8_t, 2>& bytes) override;
bool write_byte(std::uint8_t byte) override;

std::vector<std::uint8_t> get_data() override;

void reset() override;
std::size_t num_bytes_written() override;
bool error() override;

private:
std::unique_ptr<MemoryWriter> writer_;
};

#endif
(7-7/16)