C++数据bit比特位编辑类CLBit
目前数据的最小编辑单位大多为Byte(比特),而缺少对bit(比特位)的编辑方式。因此CLBit类就是为了编辑数据比特位构造的包装类。通过比特位级别的数据编辑(增删改查等)功能,可更有效的使用内存空间资源。
#ifndef __CL_BITBASE_H__
#define __CL_BITBASE_H__
#include "../_cl_common/CLCommon.h"
#include <vector>
#include <iostream>
#include <type_traits>
class CLBit :std::vector<unsigned char> {
typedef std::vector<unsigned char> base;
typedef unsigned char Byte;
typedef unsigned long long Var64;
typedef CLBit& ref;
bool _checkBuf(size_t bitCounts, size_t startPos){
if (bitCounts) {
auto si = (((startPos + bitCounts - 1) >> 3) + 1);
if (base::size() < si)base::resize(si, 0);
return true;
}
else return false;
}
static bool _getBit(const void* const src, size_t bitPos) {
return (*(((Byte*)src) + (bitPos >> 3))) & (Byte(0x1) << (bitPos & 0x7));
}
static void _setBit(void* const src, size_t bitPos,bool val) {
if (val)
(*(((Byte*)src) + (bitPos >> 3))) |= (Byte(0x1) << (bitPos & 0x7));
else
(*(((Byte*)src) + (bitPos >> 3))) &= (~(Byte(0x1) << (bitPos & 0x7)));
}
struct Bit {
void* const _data;
const size_t _pos;
operator bool() const {
return CLBit::_getBit(_data, _pos);
}
const Bit& operator=(bool val) const {
CLBit::_setBit(_data, _pos, val);
return *this;
}
const Bit& operator=(const Bit& val) const {
CLBit::_setBit(_data, _pos, CLBit::_getBit(val._data,val._pos));
return *this;
}
const Bit& operator|=(bool val) const {
CLBit::_setBit(_data, _pos, CLBit::_getBit(_data, _pos) || val);
return *this;
}
const Bit& operator&=(bool val) const {
CLBit::_setBit(_data, _pos, CLBit::_getBit(_data, _pos) && val);
return *this;
}
const Bit& operator^=(bool val) const {
CLBit::_setBit(_data, _pos, CLBit::_getBit(_data, _pos) ^ val);
return *this;
}
const Bit& operator~() const {
CLBit::_setBit(_data, _pos, !CLBit::_getBit(_data, _pos));
return *this;
}
};
public:
CLBit() {}
template<class T>
explicit CLBit(T* src, size_t srcbitCounts, size_t insertPos) {
setValue(src, srcbitCounts, 0, insertPos);
}
CLBit(PCStr charString, size_t pos = 0, bool isbitCharStringBigEnd = false) {
setValueByChar2(charString, pos, isbitCharStringBigEnd);
}
template<class T>
CLBit(T src, size_t insertPos = 0) {
static_assert(std::is_integral_v<T> || std::is_floating_point_v<T> ,
"template<class T>CLBit(T src, size_t insertPos): class T must be integral or floating point!");
setValue((const void*)&src, sizeof(T) * 8, insertPos);
}
explicit CLBit(const Bit& bt, size_t insertPos = 0) {
bool v = bt;
setValue((const void*)&v, 1, insertPos);
}
bool operator[](size_t pos) const {
return _getBit(data(),pos);
}
Bit operator[](size_t pos) {
_checkBuf(1, pos);
return Bit{data(),pos};
}
ref clear() {
base::clear();
return *this;
}
size_t size() const {
return base::size() * 8;
}
ref reserve(size_t reserveBitCounts) {
return _checkBuf(reserveBitCounts,0), * this;
}
void print(size_t st = 0, size_t ed = 0, size_t eclapse = 8) const {
auto _st = min(st, size());
auto _ed = ed <= 0 ? size() :
ed < _st ? _st : ed > size() ? size() : ed;
size_t time = eclapse;
for (size_t i = _st; i < _ed; i++) {
cout << (*this)[i];
if (time)
if (--time == 0) {
cout << " "; time = eclapse;
}
}
}
template<class T>
ref setValue(T* src, size_t srcBitCount, size_t srcBitStartPos, size_t insertPos) {
if (_checkBuf(srcBitCount, insertPos)) {
for (size_t i = 0; i < srcBitCount; i++)
_setBit(data(), insertPos + i, _getBit(src, srcBitStartPos + i));
}
else throw std::invalid_argument("CLBit::setValue: para \'srcBitCount\' con not be 0!");
return *this;
}
template<class T>
ref setValue(T* src,size_t srcBitCount, size_t insertPos) {
return setValue(src, srcBitCount, 0, insertPos);
}
template<class T>
ref setValue(T src, size_t srcBitCount = 0, size_t insertPos = 0) {
static_assert(std::is_integral_v<T> || std::is_floating_point_v<T>,
"template<class T>setValue(T src, size_t srcBitCount, size_t insertPos): class T must be integral or floating point!");
return setValue((const void*)&src, srcBitCount ? min(sizeof(T) * 8, srcBitCount) : sizeof(T) * 8, insertPos);
}
ref setValue(const CLBit& bit, size_t srcBitCount, size_t srcBitStartPos, size_t insertPos) {
if (_checkBuf(srcBitCount, insertPos)) {
for (size_t i = 0; i < srcBitCount; i++)
_setBit(data(), insertPos + i, bit[srcBitStartPos + i]);
}
else throw std::invalid_argument("CLBit::setValue: para \'srcBitCount\' con not be 0!");
return *this;
}
Var64 getValue(size_t getBitCount, size_t pos) const {
Var64 _var = 0;
getValue(&_var, min(sizeof(Var64) * 8, getBitCount), pos);
return _var;
}
Var64 operator()(size_t getBitCount, size_t pos) const {
return getValue(getBitCount, pos);
}
void* getValue(void* const buf,size_t getBitCount, size_t pos) const {
for (size_t i = 0; i < getBitCount; i++)
_setBit(buf, i, _getBit(data(), pos + i));
return buf;
}
void* operator()(void* const buf, size_t getBitCount, size_t pos) const {
getValue(buf, getBitCount, pos);
}
ref setValueByChar2(PCStr bitCharString, size_t pos,bool isbitCharStringBigEnd = false) {
if (bitCharString) {
if (isbitCharStringBigEnd) {
PCStr pend = bitCharString;
while (*pend)pend++; pend--;
for (; pend >= bitCharString; pend--)
{
if (*pend == _T('0'))
(*this)[pos++] = 0;
else if (*pend == _T('1'))
(*this)[pos++] = 1;
}
}
else {
for (; *bitCharString; bitCharString++)
{
if (*bitCharString == _T('0'))
(*this)[pos++] = 0;
else if (*bitCharString == _T('1'))
(*this)[pos++] = 1;
}
}
}return *this;
}
ref setValueByChar4(PCStr bitCharString, size_t pos, bool isbitCharStringBigEnd = false) {
if (bitCharString) {
if (isbitCharStringBigEnd) {
PCStr pend = bitCharString;
while (*pend)pend++; pend--;
for (; pend >= bitCharString; pend--)
{
Char ch = *pend;
if (ch >= _T('0') && ch <= _T('3')) {
ch -= 48;
setValue(ch, 2, pos);
pos += 2;
}
}
}
else {
for (; *bitCharString; bitCharString++)
{
Char ch = *bitCharString;
if (ch >= _T('0') && ch <= _T('3')) {
ch -= 48;
setValue(ch, 2, pos);
pos += 2;
}
}
}
}
return *this;
}
ref setValueByChar8(PCStr bitCharString, size_t pos, bool isbitCharStringBigEnd = false) {
if (bitCharString) {
if (isbitCharStringBigEnd) {
PCStr pend = bitCharString;
while (*pend)pend++; pend--;
for (; pend >= bitCharString; pend--)
{
Char ch = *pend;
if (ch >= _T('0') && ch <= _T('7')) {
ch -= 48;
setValue(ch, 3, pos);
pos += 3;
}
}
}
else {
for (; *bitCharString; bitCharString++)
{
Char ch = *bitCharString;
if (ch >= _T('0') && ch <= _T('7')) {
ch -= 48;
setValue(ch, 3, pos);
pos += 3;
}
}
}
}
return *this;
}
ref setValueByChar16(PCStr bitCharString, size_t pos, bool isbitCharStringBigEnd = false) {
if (bitCharString) {
if (isbitCharStringBigEnd) {
PCStr pend = bitCharString;
while (*pend)pend++; pend--;
for (; pend >= bitCharString; pend--)
{
Char ch = *pend;
if (ch >= _T('0') && ch <= _T('9')) {
ch -= 48;
setValue(ch, 4, pos);
pos += 4;
}
else if (ch >= _T('a') && ch <= _T('f')) {
ch -= 87;
setValue(ch, 4, pos);
pos += 4;
}
else if (ch >= _T('A') && ch <= _T('F')) {
ch -= 55;
setValue(ch, 4, pos);
pos += 4;
}
}
}
else {
for (; *bitCharString; bitCharString++)
{
Char ch = *bitCharString;
if (ch >= _T('0') && ch <= _T('9')) {
ch -= 48;
setValue(ch, 4, pos);
pos += 4;
}
else if (ch >= _T('a') && ch <= _T('f')) {
ch -= 87;
setValue(ch, 4, pos);
pos += 4;
}
else if (ch >= _T('A') && ch <= _T('F')) {
ch -= 55;
setValue(ch, 4, pos);
pos += 4;
}
}
}
}
return *this;
}
ref insertBit(const CLBit& src, size_t srcBitCounts, size_t srcBitStartPos, size_t insertPos) {
if (_checkBuf(srcBitCounts, insertPos)) {
size_t i = size();
for (; i > insertPos;)
{
i--;
if (_getBit(data(), i))
break;
}
for (; i >= insertPos; i--)
_setBit(data(), i + srcBitCounts, _getBit(data(), i));
for ( i = 0; i < srcBitCounts; i++)
_setBit(data(), insertPos + i, src[srcBitStartPos + i]);
}
return *this;
}
ref deleteBit(size_t bitCountsToDelete, size_t deleteStartPos) {
for (size_t i = deleteStartPos; i < size(); i++)
_setBit(data(), i, i + bitCountsToDelete < size() ? _getBit(data(), i + bitCountsToDelete) : false);
return *this;
}
ref erase(size_t bitCountsToErase, size_t eraseStartPos) {
for (size_t i = eraseStartPos, si = min(size(), eraseStartPos + bitCountsToErase); i < si; i++)
_setBit(data(), i, false);
return *this;
}
ref fill(size_t bitCountsToErase, size_t fillStartPos) {
if (_checkBuf(bitCountsToErase, fillStartPos)) {
for (size_t i = fillStartPos, si = fillStartPos + bitCountsToErase; i < si; i++)
_setBit(data(), i, true);
}
return *this;
}
template<class _iofstream = std::ifstream>
size_t loadFile(_iofstream& file,size_t loadBitCounts = 0, size_t loadStartBitPos = 0,
size_t insertBitPos = 0,bool chearBeforeLoad = true) {
static_assert(std::is_same_v<_iofstream, std::fstream> || std::is_same_v<_iofstream, std::ifstream>,
"template <class _iofstream> loadFile:_iofstream is not std::fstream or std::ifstream!");
if (chearBeforeLoad)
clear();
if (!file.is_open())
return 0;
size_t fileSize = file.seekg(0, file.end).tellg();
auto fileBits = loadBitCounts == 0 ? fileSize * 8 : min(loadBitCounts, fileSize * 8);
auto maxBits = min(fileSize * 8, loadStartBitPos + fileBits) - min(fileSize * 8, loadStartBitPos);
char ch = 0; size_t total = 0;
if (maxBits) {
auto startBytePos = min(fileSize, (loadStartBitPos >> 3));
auto endBytePos = min(fileSize, ((loadStartBitPos + maxBits) >> 3) + 1);
auto si = (((loadStartBitPos + maxBits - 1) >> 3) + 1);
if (base::size() < si)base::resize(si, 0);
file.seekg(ios::beg, startBytePos);
for (size_t i = startBytePos; i < endBytePos; i++)
{
file.read(&ch, 1);
for (size_t j = (loadStartBitPos & 0x7); j < 8; j++, loadStartBitPos++, insertBitPos++)
{
_setBit(data(), insertBitPos, _getBit(&ch, j));
if (++total >= maxBits)
goto end;
}
}
}
end:
return total;
}
template<class _iofstream = std::ofstream>
size_t writeToFile(_iofstream& file, size_t srcBitCountsToWrite = 0, size_t srcStartBitPosToWrite = 0) {
static_assert(std::is_same_v<_iofstream, std::fstream> || std::is_same_v<_iofstream, std::ofstream>,
"template <class _iofstream> writeToFile:_iofstream is not std::fstream or std::ofstream!");
if (!file.is_open())
return 0;
auto fileBits = srcBitCountsToWrite == 0 ? size() : min(srcBitCountsToWrite, size());
auto maxBits = min(size(), srcStartBitPosToWrite + fileBits) - min(size(),srcStartBitPosToWrite);
char ch = 0; size_t total = 0;
while (1)
{
ch = 0;
for (size_t j = (srcStartBitPosToWrite & 0x7); j < 8; j++, srcStartBitPosToWrite++)
{
_setBit(&ch, j, _getBit(data(), srcStartBitPosToWrite));
if (++total >= maxBits) {
file.write(&ch, 1);
goto end;
}
}
file.write(&ch, 1);
}
end:
return total;
}
};
#endif
测试代码
void test_class_CLBit() {
cout << "\n\ntest_class_CLBit:\n\n";
srand(time(0));
CLBit bt;
bt = 1123;
bt[8] = 1;
bt[123] = 1;
bt[0] = 1;
bt[1] = 1;
bt[2] = 1;
bt.clear();
((bt[5] = 1, bt)[3] = 2, bt)[13] = 2;
cout << endl;;
for (size_t i = 0; i < 10000000; i++)
{
int v = (rand()%20) > 10 ? 1 : 0;
bt[i] = v;
if(i < 200)
cout << v;;
}
cout << endl;; cout << endl;; cout << endl;;
for (size_t i = 0; i < 10000000; i++)
{
if (i < 200)
cout << bt[i];;
}
cout << endl;; cout << endl;; cout << endl;;
struct _A {
_A(const CLBit& bt) {
for (size_t i = 0; i < 10000000; i++)
{
if (i < 200)
cout << bt[i];
}
}
};
_A a(bt);
cout << "\n\n";
bt.print(0,200,8);
cout << "\n\n";
const auto v = bt.getValue(20, 30);
CLBit btv; btv.setValue(&v,64,0); btv.print(0, 200);
cout << "\n\n";
byte d[20] = { 0 };
bt.getValue(d, 20 * 8, 20);
CLBit btd; btd.setValue(d, 20 * 8,0); btd.print(0, 200);
char v1 = 34; int v2 = 3456; long long v3 = 2135; double v4 = 65659.362;
CLBit btv1 (v1); cout << "\n\n"; btv1.print(0, 200);
CLBit btv11(v1, 3);
btv11.setValue(v3, 0, 0);
cout << "\n\n"; btv11.print(0, 200);
CLBit btv13(&v1,16,8); cout << "\n\n"; btv13.print(0, 200);
CLBit btv2(v2); cout << "\n\n"; btv2.print(0, 200);
CLBit btv3(v3); cout << "\n\n"; btv3.print(0, 200);
CLBit btv4(v4); cout << "\n\n"; btv4.print(0, 200);
CLBit btv7 = btv4;
cout << "\n\n"; btv7.print(0, 200);
CLBit btv8 (btv7.getValue(11, 11));
cout << "\n\n"; btv8.print(0, 200);
CLBit btv9((short)btv7(11, 11));
cout << "\n\n"; btv9.print(0, 200);
CLBit btv19(btv7[1],3);
cout << "\n\n"; btv19.print(0, 200);
btv19[20] = btv7[1];
btv19[21] = 2;
btv19[28] &= 1;
btv19[29] ^= 1;
~btv19[33] ^= 0;
cout << "\n\n"; btv19.print(0, 200);
CLBit btv112; btv112.setValueByChar2("1111111111111111", 5);
cout << "\n\n"; btv112.print(0, 200);
CLBit btv111; btv111.setValueByChar16("A0a0", 8);
cout << "\n\n"; btv111.print(0, 200);
CLBit btv14; btv14.setValueByChar16("FaaCBA7654321000000A765432107654aaff", 8);
cout << "\n\n"; btv14.print(0, 0, 8);
CLBit btv15; btv15.setValueByChar16("aaaa", 8,true);
cout << "\n\n"; btv15.print(0, 0, 8);
btv112.insertBit(CLBit("010010"), 6, 0, 11); cout << "\n\n"; btv112.print(0, 0, 8);
btv112.deleteBit(5,7); cout << "\n\n"; btv112.print(0, 0, 8);
CLBit bt1 = 5625; cout << "\n\n\n"; bt1.print(0, 0, 8);
CLBit bt2 = 5625123.123; cout << "\n\n\n"; bt2.print(0, 0, 8);
CLBit bt3 = "001000101111101111110000111001001101011101010100111110011110111101111111111100111000001111111111111100011111111111110101100"; cout << "\n\n\n"; bt3.print(0, 0, 8);
ofstream f1(CLString().getSpecialFolderPath() << CLSla << "bttem.txt");
bt3.writeToFile(f1);
f1.close();
ifstream f2(CLString().getSpecialFolderPath() << CLSla << "bttem.txt");
CLBit bt4;
bt4.loadFile(f2); cout << "\n\n\n"; bt4.print(0, 0, 8);
}
|