Files
pip/libs/main/core/pibitarray.h
2022-08-15 19:35:49 +03:00

230 lines
11 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*! \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