#pragma once #include #include #include #include #include #include #include #include #include #include #undef min #undef max namespace Psc { template typename std::enable_if, 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 std::enable_if_t, T> create_string(size_t size, std::pmr::memory_resource *resource = nullptr) { std::string ret; ret.resize(size); return ret; // 返回 std::string } template struct cacl_type { using type = T; static size_t size(T &a) { return a.size(); } static void *data(T &a) { return static_cast(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 { using type = std::string; static size_t size(std::string_view a) { return a.size(); } static void *data(std::string_view a) { return (void *) a.data(); } }; template<> struct cacl_type { using type = std::string; static size_t size(const char *a) { return std::strlen(a); } static void *data(const char *a) { return (void *) a; } }; template struct cacl_type { 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 struct cacl_type { 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; } }; } #define Base template , \ typename STR_Type = std::basic_string, allocator_type>, \ typename ret_type = typename cacl_type::type \ > // #define Base template <\ // typename STR_Type, \ // typename ret_type = typename cacl_type::type \ // > namespace Psc { // 检查当前机器是否是大端字节序 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(const std::string &big_endian, char *dest); void little_endian_2_platform(const std::string &little_endian, char *dest); std::string big_endian_2_platform(const std::string &big_endian); std::string little_endian_2_platform(const std::string &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 n1 > n2 ? 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::size(s1); auto n2 = cacl_type::size(s2); auto size = get_xor_hex_size(n1, n2); auto ret = create_string(size, resource); xor_hex_Ex((void *) ret.data(), (const char *) cacl_type::data(s1), n1, (const char *) cacl_type::data(s2), n2, true, true); return ret; } inline size_t get_xor_bin_size(size_t n1, size_t n2) { return n1 > n2 ? 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::size(s1); auto n2 = cacl_type::size(s2); auto size = get_xor_bin_size(n1, n2); auto ret = create_string(size, resource); xor_bin_Ex((void *) ret.data(), (const char *) cacl_type::data(s1), n1, (const char *) cacl_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::size(mem); auto ret = create_string(get_bin2hex_size(size), resource); bin2hex_Ex((void *) ret.data(), (const char *) cacl_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::size(mem); auto ret = create_string(get_hex2bin_size(size), resource); hex2bin_Ex((void *) ret.data(), (const char *) cacl_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 ret_type bin2mem(const STR_Type &mem, std::pmr::memory_resource *resource = nullptr) { auto size = cacl_type::size(mem); auto ret = create_string(get_bin2mem_size(size), resource); bin2mem((void *) ret.data(), (const char *) cacl_type::data(mem), 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 ret_type hex2mem(const STR_Type &mem, std::pmr::memory_resource *resource = nullptr) { auto size = cacl_type::size(mem); auto ret = create_string(get_hex2mem_size(size), resource); hex2mem_Ex((void *) ret.data(), (const char *) cacl_type::data(mem), 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 = true, const char *middle = "", size_t middle_len = std::numeric_limits::max()); Base ret_type mem2hex(const STR_Type &mem, bool uppercase = true, const std::string &middle = "", std::pmr::memory_resource *resource = nullptr) { auto size = cacl_type::size(mem); auto ret = create_string(get_mem2hex_size(size, middle.size()), resource); mem2hex_Ex2(ret.data(), cacl_type::data(mem), size, uppercase, middle.data(), middle.size()); return ret; } template void get_bin(std::string &msg, int &n) { n = std::bitset(msg.substr(start, len)).to_ullong(); } template void get_bin(std::string &msg, Enum &n) { n = static_cast(std::bitset(msg.substr(start, len)).to_ullong()); } template Enum get_bin(std::string &msg) { return static_cast(std::bitset(msg.substr(start, len)).to_ullong()); } template int get_bin(const std::string &msg) { return std::bitset(msg.substr(start, len)).to_ullong(); } template void set_bin(std::string &msg, unsigned long long n) { msg.replace(start, len, std::bitset(n).to_string()); } template void set_bin(std::string &msg, const std::string &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 std::string to_bin(unsigned long long n) { return std::bitset(n).to_string(); } template std::string to_bin(double n) { return std::bitset(static_cast(n)).to_string(); } template T bin2(std::string_view binstr) { auto text = std::string(binstr); return std::stoull(text, nullptr, 2); } template unsigned long long hex2(std::string_view hexstr) { auto text = std::string(hexstr); return std::stoull(text, nullptr, 16); } template<> inline int bin2(std::string_view binstr) { int bit_limit = sizeof(int) * 8; if (binstr.size() > bit_limit) { std::cout << "Bitset.h inline int bin2 error! Binary string exceeds int bit limit" << std::endl; } auto text = std::string(binstr); return std::stoi(text, nullptr, 2); } // 设置dest的从off位起n位,写入value的低n位 template void set_bits(void *dest, size_t off, size_t n, T value) { auto d = static_cast(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 T get_bits(void *src, size_t off, size_t n) { auto s = static_cast(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; } } #undef Base