Files
ECAP_Server/module/dll_source_lzy/ecap/lib/hulc/Bit.h
T
2026-07-06 09:30:04 +08:00

300 lines
11 KiB
C++

#ifndef BitSet_H
#define BitSet_H
#include <bitset>
#include <string_view>
#ifdef __linux__
#include <cstring>
#endif
#include <iostream>
#include <memory_resource>
#include <string>
#include <type_traits>
namespace yC {
template <typename T = std::pmr::string>
typename std::enable_if<std::is_same<T, std::pmr::string>::value, T>::type
create_string(size_t size, std::pmr::memory_resource *resource = nullptr) {
std::pmr::memory_resource *r =
resource ? resource : std::pmr::get_default_resource();
std::pmr::string ret(r);
ret.resize(size);
return ret; // 返回 std::pmr::string
}
template <typename T = std::string>
typename std::enable_if<std::is_same<T, std::string>::value, T>::type
create_string(size_t size, std::pmr::memory_resource *resource = nullptr) {
std::string ret;
ret.resize(size);
return ret; // 返回 std::string
}
template <typename T> struct cacl_type {
using type = T;
size_t size(T &a) { return a.size(); }
static void *data(T &a) { return (void *)a.data(); }
static size_t size(const T &a) { return a.size(); }
static void *data(const T &a) { return (void *)a.data(); }
};
template <> struct cacl_type<const char *> {
using type = std::string;
static size_t size(const char *a) { return strlen(a); }
static void *data(const char *a) { return (void *)a; }
};
template <size_t N> struct cacl_type<char[N]> {
using type = std::string;
static size_t size(const char (&a)[N]) { return N - 1; }
static void *data(const char (&a)[N]) { return (void *)a; }
};
template <size_t N> struct cacl_type<const char[N]> {
using type = std::string;
static size_t size(const char (&a)[N]) { return N - 1; }
static void *data(const char (&a)[N]) { return (void *)a; }
};
} // namespace yC
#define Base \
template <typename allocator_type = std::allocator<char>, \
typename STR_Type = std::basic_string< \
char, std::char_traits<char>, allocator_type>, \
typename ret_type = typename cacl_type<STR_Type>::type>
// #define Base template <\
// typename STR_Type, \
// typename ret_type = typename cacl_type<STR_Type>::type \
// >
namespace yC {
// 检查当前机器是否是大端字节序
extern const bool is_big_endian;
void big_endian_2_platform(void *dest, const char *d, size_t size);
void little_endian_2_platform(void *dest, const char *d, size_t size);
void big_endian_2_platform(std::string_view big_endian, char *dest);
void little_endian_2_platform(std::string_view little_endian, char *dest);
std::string big_endian_2_platform(std::string_view big_endian);
std::string little_endian_2_platform(std::string_view little_endian);
std::string platform_2_big_endian(void *memory, int size);
std::string platform_2_little_endian(void *memory, int size);
inline size_t get_xor_hex_size(size_t n1, size_t n2) {
return std::max(n1, n2);
}
void xor_hex_Ex(void *dest, const char *s1, size_t n1, const char *s2,
size_t n2, bool big_dian, bool is_upper);
Base ret_type xorHex(const STR_Type &s1, const STR_Type &s2,
std::pmr::memory_resource *resource = nullptr) {
auto n1 = cacl_type<STR_Type>::size(s1);
auto n2 = cacl_type<STR_Type>::size(s2);
auto size = get_xor_hex_size(n1, n2);
auto ret = create_string<ret_type>(size, resource);
xor_hex_Ex((void *)ret.data(), (const char *)cacl_type<STR_Type>::data(s1),
n1, (const char *)cacl_type<STR_Type>::data(s2), n2, true, true);
return ret;
}
inline size_t get_xor_bin_size(size_t n1, size_t n2) {
return std::max(n1, n2);
}
void xor_bin_Ex(void *dest, const char *s1, size_t n1, const char *s2,
size_t n2, bool big_dian);
Base ret_type xorBin(const STR_Type &s1, const STR_Type &s2,
std::pmr::memory_resource *resource = nullptr) {
auto n1 = cacl_type<STR_Type>::size(s1);
auto n2 = cacl_type<STR_Type>::size(s2);
auto size = get_xor_bin_size(n1, n2);
auto ret = create_string<ret_type>(size, resource);
xor_bin_Ex((void *)ret.data(), (const char *)cacl_type<STR_Type>::data(s1),
n1, (const char *)cacl_type<STR_Type>::data(s2), n2, true);
return ret;
}
inline size_t get_bin2hex_size(size_t num) { return (num + 3) / 4; }
void bin2hex_Ex(void *dest, const char *data, size_t size, bool big_dian,
bool isupper);
Base ret_type bin2hex(const STR_Type &mem,
std::pmr::memory_resource *resource = nullptr) {
auto size = cacl_type<STR_Type>::size(mem);
auto ret = create_string<ret_type>(get_bin2hex_size(size), resource);
bin2hex_Ex((void *)ret.data(), (const char *)cacl_type<STR_Type>::data(mem),
size, true, true);
return ret;
}
inline size_t get_hex2bin_size(size_t num) { return num * 4; }
void hex2bin_Ex(void *dest, const char *data, size_t size, bool big_dian);
Base ret_type hex2bin(const STR_Type &mem,
std::pmr::memory_resource *resource = nullptr) {
auto size = cacl_type<STR_Type>::size(mem);
auto ret = create_string<ret_type>(get_hex2bin_size(size), resource);
hex2bin_Ex((void *)ret.data(), (const char *)cacl_type<STR_Type>::data(mem),
size, true);
return ret;
}
inline size_t get_bin2mem_size(size_t num) { return num / 8; };
void bin2mem(void *dest, const char *data, size_t size);
Base STR_Type bin2mem(const STR_Type &mem,
std::pmr::memory_resource *resource = nullptr) {
auto size = cacl_type<STR_Type>::size(mem);
auto ret = create_string<STR_Type>(get_bin2mem_size(size), resource);
bin2mem((void *)ret.data(), (const char *)cacl_type<STR_Type>::data(mem),
size);
return ret;
}
// inline ret_str bin2mem(param_str mem, std::pmr::memory_resource* resource =
// nullptr) {
// auto size = mem.size();
// auto ret = ret_str();
// ret.resize(get_bin2mem_size(size));
// bin2mem((void*)ret.data(), (const char*)mem.data(), size);
// return ret;
// }
inline size_t get_hex2mem_size(size_t hex_hum) { return hex_hum / 2; };
void hex2mem_Ex(void *dest, const char *data, size_t size);
Base STR_Type hex2mem(const STR_Type &mem,
std::pmr::memory_resource *resource = nullptr) {
auto size = cacl_type<STR_Type>::size(mem);
auto ret = create_string<STR_Type>(get_hex2mem_size(size), resource);
hex2mem_Ex((void *)ret.data(), (const char *)cacl_type<STR_Type>::data(mem),
size);
return ret;
}
// inline ret_str hex2mem(param_str hex, std::pmr::memory_resource* resource =
// nullptr) {
// auto size = hex.size();
// auto ret = ret_str();
// ret.resize(get_hex2mem_size(size));
// hex2mem_Ex((void*)ret.data(), (const char*)hex.data(), size);
// return ret;
// }
inline size_t get_mem2hex_size(size_t num, size_t middle_len) {
return num * 2 + (num - 1) * middle_len;
}
void mem2hex_Ex2(void *dest, void *mem, size_t num, bool uppercase,
const char *middle,
size_t middle_len = std::numeric_limits<size_t>::max());
Base STR_Type mem2hex(const STR_Type &mem, bool uppercase = true,
std::string_view middle = "",
std::pmr::memory_resource *resource = nullptr) {
auto size = cacl_type<STR_Type>::size(mem);
auto ret =
create_string<STR_Type>(get_mem2hex_size(size, middle.size()), resource);
mem2hex_Ex2(ret.data(), cacl_type<STR_Type>::data(mem), size, uppercase,
middle.data(), middle.size());
return ret;
}
// inline ret_str mem2hex(param_str& mem, bool uppercase = true, const
// std::string& middle = "", std::pmr::memory_resource* resource = nullptr) {
// auto size = get_mem2hex_size(mem.size(), middle.size());
// auto ret = ret_str();
// mem2hex_Ex2(ret.data(), (void*)mem.data(), size, uppercase,
// middle.data(), middle.size()); return ret;
// }
template <int start, int len> void get_bin(std::string &msg, int &n) {
n = std::bitset<len>(msg.substr(start, len)).to_ullong();
}
template <int start, int len, typename Enum>
void get_bin(std::string &msg, Enum &n) {
n = static_cast<Enum>(std::bitset<len>(msg.substr(start, len)).to_ullong());
}
template <int start, int len, typename Enum> Enum get_bin(std::string &msg) {
return static_cast<Enum>(
std::bitset<len>(msg.substr(start, len)).to_ullong());
}
template <int start, int len> int get_bin(std::string_view msg) {
return std::bitset<len>(msg.substr(start, len)).to_ullong();
}
template <int start, int len>
void set_bin(std::string &msg, unsigned long long n) {
msg.replace(start, len, std::bitset<len>(n).to_string());
}
template <int start, int len>
void set_bin(std::string &msg, std::string_view value) {
if (value.size() != len) {
std::cout << "len == " << len << " bits.size() == " << value.size()
<< std::endl;
throw std::out_of_range("Start position and length exceed bit string size");
}
msg.replace(start, len, value);
}
template <int len> std::string to_bin(unsigned long long n) {
return std::bitset<len>(n).to_string();
}
template <int num> std::string to_bin(double n) {
return std::bitset<num>(static_cast<unsigned long long>(n)).to_string();
}
template <typename T> T bin2(std::string_view binstr) {
return std::stoull(binstr, nullptr, 2);
}
template <typename T> unsigned long long hex2(std::string_view hexstr) {
return std::stoull(hexstr, nullptr, 16);
}
template <> inline int bin2<int>(std::string_view binstr) {
int bit_limit = sizeof(int) * 8;
if (binstr.size() > bit_limit) {
std::cout << "Bitset.h inline int bin2<int> error! Binary string exceeds "
"int bit limit"
<< std::endl;
}
return std::stoi(binstr, nullptr, 2);
}
// 设置dest的从off位起n位,写入value的低n位
template <typename T = std::uint64_t>
void set_bits(void *dest, size_t off, size_t n, T value) {
auto d = static_cast<uint8_t *>(dest);
size_t bit_pos = off;
size_t val_pos = 0;
while (n > 0) {
size_t byte_idx = bit_pos / 8;
size_t bit_in_byte = bit_pos % 8;
size_t bits_in_this_byte = std::min(n, 8 - bit_in_byte);
// 为当前字节构建掩码
uint8_t mask = ((1u << bits_in_this_byte) - 1) << bit_in_byte;
// 取value对应的低bits_in_this_byte位
uint8_t v = (value >> val_pos) & ((1u << bits_in_this_byte) - 1);
// 清除目标字节对应位置后设置
d[byte_idx] = (d[byte_idx] & ~mask) | ((v << bit_in_byte) & mask);
bit_pos += bits_in_this_byte;
val_pos += bits_in_this_byte;
n -= bits_in_this_byte;
}
}
// 大批量位处理性能不好 但是通常也没有这样的场景
void bit_move(void *d, size_t doff, const void *s, size_t soff, size_t n);
void bit_xor(void *d, size_t doff, const void *s, size_t soff, size_t n);
void bit_or(void *d, size_t doff, const void *s, size_t soff, size_t n);
void bit_and(void *d, size_t doff, const void *s, size_t soff, size_t n);
template <typename T = std::uint64_t>
T get_bits(void *src, size_t off, size_t n) {
auto s = static_cast<const uint8_t *>(src);
size_t bit_pos = off;
size_t val_pos = 0;
T result = 0;
while (n > 0) {
size_t byte_idx = bit_pos / 8;
size_t bit_in_byte = bit_pos % 8;
size_t bits_in_this_byte = std::min(n, 8 - bit_in_byte);
uint8_t mask = ((1u << bits_in_this_byte) - 1) << bit_in_byte;
uint8_t bits = (s[byte_idx] & mask) >> bit_in_byte;
result |= (T(bits) << val_pos);
bit_pos += bits_in_this_byte;
val_pos += bits_in_this_byte;
n -= bits_in_this_byte;
}
return result;
}
} // namespace yC
#undef Base
#endif