我不久前写了这个类,当时我需要处理比特。它也可能对您有用。这里是:
#include <deque>
#include <vector>
#include <algorithm>
class bitStream {
public:
bitStream() {}
/// Copies the data from another bitStream into this one upon construction
bitStream(const bitStream& bStream, bool reverse=false) {
this->appendData(bStream, reverse);
}
/// Copies the data from a vector of booleans upon construction
bitStream(const vector<bool>& vec, bool reverse=false) {
this->appendData(vec, reverse);
}
/// Appends data to the stream from a uint64_t type. The lower-n bits will be appended, starting with the highest bit of those by default.
void appendData(uint64_t data, size_t n, bool reverse=false) {
deque<bool> _buffer;
n = (n>64)?64:n;
for (int i=0; i<n; i++) {
_oneBit tmp;
tmp.data = data;
_buffer.push_back(tmp.data);
data >>= 0x1;
}
if (!reverse) std::reverse(_buffer.begin(), _buffer.end());
for (const auto v: _buffer) _data.push_back(v);
}
/// Appends data to the stream from a C-style array of booleans
void appendData(bool* data, size_t n, bool reverse=false) {
if (reverse) {
for (int i=0; i<n; i++) this->appendBit(*(data+(n-i-1)));
} else {
for (int i=0; i<n; i++) this->appendBit(*(data+i));
}
}
/// Appends data to the stream from a vector of booleans
void appendData(const vector<bool>& vec, bool reverse=false) {
if (reverse) {
for (auto i = vec.size()-1; vec.size() > i; --i) this->appendBit(vec.at(i));
} else {
for (const auto& v : vec) this->appendBit(v);
}
}
/// Appends a single bit
void appendBit(bool bit) {
_data.push_back(bit);
}
/// Appends the bits from another bitStream object to this one
void appendData(const bitStream& bStream, bool reverse=false) {
if (!bStream.getSize()) return;
if (reverse) {
for (int i=0; i<bStream.getSize(); i++) this->appendBit(*(bStream.getData()+(bStream.getSize()-i-1)));
} else {
for (int i=0; i<bStream.getSize(); i++) this->appendBit(*(bStream.getData()+i));
}
}
/// Returns a pointer to the begining of the data (read-only!)
const bool* getData() const { return &_data.front(); }
/// Reference to the bit at a specified position (assignable, but at lest n+1 elements must exist before calling!)
bool& operator[] (size_t n) {
if (n>_data.size()-1) throw runtime_error("Out of range!");
return _data.at(n);
}
/// Fills your vector with the data chopped up into "sizeof(T)"-byte pieces.
template <typename T>
void getDataAsVector(vector<T>& vec) {
vec.clear();
size_t oSize = sizeof(T)*8;
T tmp = 0x0;
for (int i=0; i<_data.size(); i++) {
if (!(i%oSize) && i) {
vec.push_back(tmp);
tmp = 0x0;
}
tmp <<= 0x1;
tmp |= _data[i];
}
vec.push_back(tmp);
}
/// Returns the number of bits that are stored
size_t getSize() const { return _data.size(); }
/// Reverses the stored bits
void reverse() { std::reverse(_data.begin(), _data.end()); }
private:
deque<bool> _data;
struct _oneBit {
uint8_t data:1;
};
};
使用起来相当简单,所以我没有费心写一个例子。
首先,我实际上从未在项目中使用过它,因此可能存在一些错误(我记得只对其进行了非常简短的测试),而且它还没有完全完成(有几个可能的构造函数我还没有实现)。此外,尽管名称为“流”,但它与 C++ 中的流无关。
所以基本上它可以让你存储位。您放入其中的位将存储在连续的内存地址(是的,这是每个内存字节一个位,但无论如何),在对象的生命周期内保持不变(这是因为 deque 不重新分配自己不像vector)!您可以通过各种方式(从不同的数据源,以反向或非反向顺序)向其附加位,并以不同的形式将它们读回。在您的情况下,appendData(uint64_t data, size_t n, bool reverse=false) 函数是您可以用来填充它的函数。要取回您的数据,您可以使用 vector<char> 填充数据,并将其切成 1 字节的片段(字符),如果您愿意的话!
再次重申,请不要将此视为 100% 经测试且有效的事情。我只是简单地测试了它,所以你应该尝试一下,看看它是否适合你!我想我会与你分享,以防你觉得它有帮助。