230 lines
11 KiB
C++
230 lines
11 KiB
C++
/*! \file pibitarray.h
|
||
* \~\brief
|
||
* \~english Bit array
|
||
* \~russian Битовый массив
|
||
*/
|
||
/*
|
||
PIP - Platform Independent Primitives
|
||
Bit array
|
||
Ivan Pelipenko peri4ko@yandex.ru
|
||
|
||
This program is free software: you can redistribute it and/or modify
|
||
it under the terms of the GNU Lesser General Public License as published by
|
||
the Free Software Foundation, either version 3 of the License, or
|
||
(at your option) any later version.
|
||
|
||
This program is distributed in the hope that it will be useful,
|
||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
GNU Lesser General Public License for more details.
|
||
|
||
You should have received a copy of the GNU Lesser General Public License
|
||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
*/
|
||
|
||
#ifndef PIBITARRAY_H
|
||
#define PIBITARRAY_H
|
||
|
||
#include "pivector.h"
|
||
|
||
|
||
//! \ingroup Core
|
||
//! \~\brief
|
||
//! \~english The %PIBitArray class provides an space-efficient array of bits.
|
||
//! \~russian Класс %PIBitArray представляет собой компактный массив битов.
|
||
class PIP_EXPORT PIBitArray {
|
||
template <typename P>
|
||
friend PIBinaryStream<P> & operator >>(PIBinaryStream<P> & s, PIBitArray & v);
|
||
template <typename P>
|
||
friend PIBinaryStream<P> & operator <<(PIBinaryStream<P> & s, const PIBitArray & v);
|
||
public:
|
||
|
||
//! \~english Constructs bit array with "size" size.
|
||
//! \~russian Создает битовый массив с размером "size".
|
||
PIBitArray(const int & size = 0) {resize(size);}
|
||
|
||
//! \~english Constructs bit array with size 8 and values from "val".
|
||
//! \~russian Создает битовый массив с размером 8 и значениями из "val".
|
||
PIBitArray(uchar val) {resize(sizeof(val) * 8); data_[0] = val;}
|
||
|
||
//! \~english Constructs bit array with size 16 and values from "val".
|
||
//! \~russian Создает битовый массив с размером 16 и значениями из "val".
|
||
PIBitArray(ushort val) {resize(sizeof(val) * 8); memcpy(data(), &val, sizeof(val));}
|
||
|
||
//! \~english Constructs bit array with size 32 and values from "val".
|
||
//! \~russian Создает битовый массив с размером 32 и значениями из "val".
|
||
PIBitArray(uint val) {resize(sizeof(val) * 8); memcpy(data(), &val, sizeof(val));}
|
||
|
||
//! \~english Constructs bit array with size 64 and values from "val".
|
||
//! \~russian Создает битовый массив с размером 64 и значениями из "val".
|
||
PIBitArray(ullong val) {resize(sizeof(val) * 8); memcpy(data(), &val, sizeof(val));}
|
||
|
||
//! \~english Constructs bit array with size "bytes * 8" and values from "data".
|
||
//! \~russian Создает битовый массив с размером "bytes * 8" и значениями из "data".
|
||
PIBitArray(const uchar * data, uint bytes) {resize(bytes * 8); memcpy(this->data(), data, bytes);}
|
||
|
||
|
||
//! \~english Returns a size in bits.
|
||
//! \~russian Возвращает размер в битах.
|
||
uint bitSize() const {return size_;}
|
||
|
||
//! \~english Returns a size in bytes.
|
||
//! \~russian Возвращает размер в байтах.
|
||
uint byteSize() const {return bytesInBits(size_);}
|
||
|
||
//! \~english Resize this array to "size" bits.
|
||
//! \~russian Изменяет размер массива до "size" битов.
|
||
PIBitArray & resize(const uint & size) {size_ = size; data_.resize(bytesInBits(size_)); return *this;}
|
||
|
||
|
||
//! \~english Set bit with index "index" to 0.
|
||
//! \~russian Устанавливает бит с индексом "index" в 0.
|
||
PIBitArray & clearBit(const uint & index) {data_[index / 8] &= ~(1 << (index % 8)); return *this;}
|
||
|
||
//! \~english Set bit with index "index" to 1.
|
||
//! \~russian Устанавливает бит с индексом "index" в 1.
|
||
PIBitArray & setBit(const uint & index) {data_[index / 8] |= (1 << (index % 8)); return *this;}
|
||
|
||
//! \~english Set bit with index "index" to "value".
|
||
//! \~russian Устанавливает бит с индексом "index" в "value".
|
||
PIBitArray & writeBit(const uint & index, const bool & value) {if (value) setBit(index); else clearBit(index); return *this;}
|
||
|
||
//! \~english Set bit with index "index" to "value".
|
||
//! \~russian Устанавливает бит с индексом "index" в "value".
|
||
PIBitArray & writeBit(const uint & index, const uchar & value) {return writeBit(index, value > 0);}
|
||
|
||
|
||
//! \~english Add bit with value "value" to the end of array.
|
||
//! \~russian Добавляет бит со значением "value" в конец массива.
|
||
PIBitArray & push_back(const bool & value) {resize(size_ + 1); writeBit(size_ - 1, value); return *this;}
|
||
|
||
//! \~english Add bit with value "value" to the end of array.
|
||
//! \~russian Добавляет бит со значением "value" в конец массива.
|
||
PIBitArray & push_back(const uchar & value) {return push_back(value > 0);}
|
||
|
||
//! \~english Insert bit with value "value" after "index" position.
|
||
//! \~russian Вставляет бит со значением "value" после положения "index".
|
||
PIBitArray & insert(const uint & index, const bool & value) {
|
||
resize(size_ + 1);
|
||
uint fi = byteSize() - 1, si = index / 8, ti = index % 8;
|
||
uchar c = data_[si];
|
||
for (uint i = fi; i > si; --i) {
|
||
data_[i] <<= 1;
|
||
if ((0x80 & data_[i - 1]) == 0x80) data_[i] |= 1;
|
||
else data_[i] &= 0xFE;}
|
||
data_[si] &= (0xFF >> (7 - ti));
|
||
data_[si] |= ((c << 1) & (0xFF << (ti)));
|
||
if (value) data_[si] |= (1 << ti);
|
||
else data_[si] &= ~(1 << ti);
|
||
return *this;}
|
||
|
||
//! \~english Insert bit with value "value" after "index" position.
|
||
//! \~russian Вставляет бит со значением "value" после положения "index".
|
||
PIBitArray & insert(const uint & index, const uchar & value) {return insert(index, value > 0);}
|
||
|
||
//! \~english Add bit with value "value" to the beginning of array.
|
||
//! \~russian Добавляет бит со значением "value" в начало массива.
|
||
PIBitArray & push_front(const bool & value) {return insert(0, value);}
|
||
|
||
//! \~english Add bit with value "value" to the beginning of array.
|
||
//! \~russian Добавляет бит со значением "value" в начало массива.
|
||
PIBitArray & push_front(const uchar & value) {return push_front(value > 0);}
|
||
|
||
//! \~english Remove one bit from the end of array.
|
||
//! \~russian Удаляет один бит с конца массива.
|
||
PIBitArray & pop_back() {return resize(size_ - 1);}
|
||
|
||
//! \~english Remove one bit from the beginning of array.
|
||
//! \~russian Удаляет один бит с начала массива.
|
||
PIBitArray & pop_front() {
|
||
if (size_ == 0) return *this;
|
||
uint fi = byteSize() - 1;
|
||
for (uint i = 0; i < fi; ++i) {
|
||
data_[i] >>= 1;
|
||
if ((1 & data_[i + 1]) == 1) data_[i] |= 0x80;
|
||
else data_[i] &= 0x7F;}
|
||
data_[fi] >>= 1;
|
||
resize(size_ - 1);
|
||
return *this;}
|
||
|
||
//! \~english Add bits "ba" to the end of array.
|
||
//! \~russian Добавляет биты "ba" в конец массива.
|
||
PIBitArray & append(const PIBitArray & ba) {for (uint i = 0; i < ba.bitSize(); ++i) push_back(ba[i]); return *this;}
|
||
|
||
|
||
//! \~english Returns pointer to bytes data of array.
|
||
//! \~russian Возвращает указатель на байтовое содержимое массива.
|
||
uchar * data() {return data_.data();}
|
||
|
||
//! \~english Returns data of array as \b uchar.
|
||
//! \~russian Возвращает байтовое содержимое массива как \b uchar.
|
||
uchar toUChar() {if (size_ == 0) return 0; return data_[0];}
|
||
|
||
//! \~english Returns data of array as \b ushort.
|
||
//! \~russian Возвращает байтовое содержимое массива как \b ushort.
|
||
ushort toUShort() {ushort t = 0; memcpy(&t, data(), piMin<uint>(byteSize(), sizeof(t))); return t;}
|
||
|
||
//! \~english Returns data of array as \b uint.
|
||
//! \~russian Возвращает байтовое содержимое массива как \b uint.
|
||
uint toUInt() {uint t = 0; memcpy(&t, data(), piMin<uint>(byteSize(), sizeof(t))); return t;}
|
||
|
||
//! \~english Returns data of array as \b ullong.
|
||
//! \~russian Возвращает байтовое содержимое массива как \b ullong.
|
||
ullong toULLong() {ullong t = 0; memcpy(&t, data(), piMin<uint>(byteSize(), sizeof(t))); return t;}
|
||
|
||
|
||
//! \~english Returns bit value at index "index".
|
||
//! \~russian Возвращает значение бита с индексом "index".
|
||
bool at(const uint & index) const {return (1 & (data_[index / 8] >> (index % 8))) == 1 ? true : false;}
|
||
|
||
//! \~english Returns bit value at index "index".
|
||
//! \~russian Возвращает значение бита с индексом "index".
|
||
bool operator [](const uint & index) const {return at(index);}
|
||
|
||
//! \~english Similar to \a append().
|
||
//! \~russian Аналог \a append().
|
||
void operator +=(const PIBitArray & ba) {append(ba);}
|
||
|
||
//! \~english Returns if two bit arrays are similar.
|
||
//! \~russian Возвращает равны ли для битовых массива.
|
||
bool operator ==(const PIBitArray & ba) const {if (bitSize() != ba.bitSize()) return false; for (uint i = 0; i < bitSize(); ++i) if (at(i) != ba[i]) return false; return true;}
|
||
|
||
//! \~english Returns if two bit arrays are not similar.
|
||
//! \~russian Возвращает не равны ли для битовых массива.
|
||
bool operator !=(const PIBitArray & ba) const {return !(*this == ba);}
|
||
|
||
//! \~english Resize and set values from "val".
|
||
//! \~russian Изменяет размер и устанавливает значения из "val".
|
||
void operator =(const uchar & val) {resize(sizeof(val) * 8); data_[0] = val;}
|
||
|
||
//! \~english Resize and set values from "val".
|
||
//! \~russian Изменяет размер и устанавливает значения из "val".
|
||
void operator =(const ushort & val) {resize(sizeof(val) * 8); memcpy(data(), &val, sizeof(val));}
|
||
|
||
//! \~english Resize and set values from "val".
|
||
//! \~russian Изменяет размер и устанавливает значения из "val".
|
||
void operator =(const uint & val) {resize(sizeof(val) * 8); memcpy(data(), &val, sizeof(val));}
|
||
|
||
//! \~english Resize and set values from "val".
|
||
//! \~russian Изменяет размер и устанавливает значения из "val".
|
||
void operator =(const ullong & val) {resize(sizeof(val) * 8); memcpy(data(), &val, sizeof(val));}
|
||
|
||
private:
|
||
static uint bytesInBits(const uint & bits) {return (bits + 7) / 8;}
|
||
|
||
PIVector<uchar> data_;
|
||
uint size_;
|
||
|
||
};
|
||
|
||
#ifdef PIP_STD_IOSTREAM
|
||
//std::ostream & operator <<(std::ostream & s, const PIBitArray & ba);
|
||
#endif
|
||
|
||
//! \relatesalso PIByteArray
|
||
//! \~english Output operator to \a PICout
|
||
//! \~russian Оператор вывода в \a PICout
|
||
PICout operator <<(PICout s, const PIBitArray & ba);
|
||
|
||
#endif // PIBITARRAY_H
|