756 lines
26 KiB
C++
756 lines
26 KiB
C++
#include "Bit.h"
|
||
#include <bitset>
|
||
#include <iomanip>
|
||
#include <regex>
|
||
#include <sstream>
|
||
#include <stdexcept>
|
||
// 2025-01-02 05:01:50 [info] 1a480118 9607f81e f020 3a24 67761dbd 1a9ecbf8 5655c75b 00601307
|
||
#include <algorithm>
|
||
#include <array>
|
||
#include <cstring>
|
||
#include <string>
|
||
#include <string>
|
||
#include <utility>
|
||
#include <vector>
|
||
#include <map>
|
||
#include <iostream>
|
||
#include <set>
|
||
#include <sstream>
|
||
#include <unordered_map>
|
||
#include <bitset>
|
||
#include <cstdint>
|
||
#include <cassert>
|
||
|
||
#ifdef _USE_GTEST
|
||
#include <gtest/gtest.h>
|
||
using namespace Psc;
|
||
#endif
|
||
constexpr std::array<uint8_t, 256> make_hex_to_val() {
|
||
std::array<uint8_t, 256> t{255}; // 初始化为255
|
||
for (uint8_t i = '0'; i <= '9'; ++i) t[i] = i - '0';
|
||
for (uint8_t i = 'A'; i <= 'F'; ++i) t[i] = i - 'A' + 10;
|
||
for (uint8_t i = 'a'; i <= 'f'; ++i) t[i] = i - 'a' + 10;
|
||
return t;
|
||
}
|
||
constexpr std::array<uint8_t, 16> make_val_to_hex(bool uppercase) {
|
||
std::uint8_t s = uppercase ? 'A' : 'a';
|
||
std::array<uint8_t, 16> t{};
|
||
for (uint8_t i = 0; i < 10; ++i) {
|
||
t[i] = '0' + i; // '0' - '9'
|
||
}
|
||
for (uint8_t i = 10; i < 16; ++i) {
|
||
t[i] = s + (i - 10); // 'a' - 'f' 'A - F'
|
||
}
|
||
return t;
|
||
}
|
||
static constexpr std::array<uint8_t, 16> val_to_upper_hex = make_val_to_hex(true);
|
||
static constexpr std::array<uint8_t, 16> val_to_lower_hex = make_val_to_hex(false);
|
||
static constexpr std::array<uint8_t, 256> hex_to_val = make_hex_to_val();
|
||
constexpr const char* hex_lut_lower = "0123456789abcdef";
|
||
constexpr const char* hex_lut_upper = "0123456789ABCDEF";
|
||
constexpr const char* big_dian_hex_to_bin[16] = {
|
||
"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111",
|
||
"1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"
|
||
};
|
||
constexpr const char* small_dian_hex_to_bin[16] = {
|
||
"0000", "1000", "0100", "1100", "0010", "1010", "0110", "1110",
|
||
"0001", "1001", "0101", "1101", "0011", "1011", "0111", "1111"
|
||
};
|
||
constexpr std::array<std::array<std::uint8_t, 256>, 256> make_xor_table() {
|
||
std::array<std::array<std::uint8_t, 256>, 256> t{};
|
||
for (size_t i = 0; i < 256; ++i) {
|
||
for (size_t j = 0; j < 256; ++j) {
|
||
t[i][j] = 255;
|
||
}
|
||
}
|
||
for (size_t i = 0; i < 16; ++i) {
|
||
for (size_t j = 0; j < 16; ++j) {
|
||
t[val_to_lower_hex[i]][val_to_lower_hex[j]] = i ^ j;
|
||
t[val_to_upper_hex[i]][val_to_upper_hex[j]] = i ^ j;
|
||
}
|
||
}
|
||
return t;
|
||
}
|
||
|
||
static constexpr std::array<std::array<std::uint8_t, 256>, 256> xor_table = make_xor_table();
|
||
inline size_t bin4_to_hex(bool big_byte_order, const char* a) {
|
||
static size_t small_base[]{1, 2, 4, 8};
|
||
static size_t big_base[]{8, 4, 2, 1};
|
||
auto cur_dian = big_byte_order ? big_base : small_base;
|
||
size_t ret = 0;
|
||
for (size_t i = 0; i < 4; ++i) {
|
||
auto cur = size_t(a[i] - '0');
|
||
ret += cur_dian[i] * cur;
|
||
}
|
||
return ret;
|
||
}
|
||
|
||
|
||
|
||
namespace Psc {
|
||
const bool is_big_endian = []() {
|
||
uint16_t x = 0x0102; // 设置一个已知的 16-bit 值
|
||
auto* p = reinterpret_cast<uint8_t*>(&x);
|
||
return p[0] == 0x01; // 如果 p[0] 为 0x01,说明是大端字节序
|
||
}();
|
||
std::vector<std::string> split(const std::string& str, const std::string& delimiter) {
|
||
std::vector<std::string> tokens;
|
||
size_t start = 0;
|
||
size_t end = str.find(delimiter);
|
||
if (end == std::string::npos) return {};
|
||
while (end != std::string::npos) {
|
||
tokens.push_back(str.substr(start, end - start));
|
||
start = end + 1;
|
||
end = str.find(delimiter, start);
|
||
}
|
||
tokens.push_back(str.substr(start)); // Add the last token
|
||
return tokens;
|
||
}
|
||
std::string bin2mem(const std::string& bin) {
|
||
const size_t len = bin.size();
|
||
if (len % 8 != 0) {
|
||
throw std::invalid_argument("binary string length must be a multiple of 8");
|
||
}
|
||
std::string result;
|
||
result.reserve(len / 8); // 提前分配
|
||
for (size_t i = 0; i < len; i += 8) {
|
||
uint8_t byte = 0;
|
||
for (size_t j = 0; j < 8; ++j) {
|
||
char bit = bin[i + j];
|
||
if (bit == '1') {
|
||
byte |= (1 << (7 - j));
|
||
} else if (bit != '0') {
|
||
std::ostringstream oss;
|
||
oss << "Invalid bit character '" << bit << "' at position " << (i + j);
|
||
throw std::invalid_argument(oss.str());
|
||
}
|
||
}
|
||
result.push_back(static_cast<char>(byte));
|
||
}
|
||
return result;
|
||
}
|
||
|
||
void bin2mem(void* dest, const char* data, size_t size) {
|
||
if (size % 8 != 0) {
|
||
throw std::invalid_argument("Binary string length must be a multiple of 8");
|
||
}
|
||
uint8_t* byte_dest = static_cast<uint8_t*>(dest); // 将 dest 转换为字节指针
|
||
for (size_t i = 0; i < size; i += 8) {
|
||
uint8_t byte = 0;
|
||
for (size_t j = 0; j < 8; ++j) {
|
||
char bit = data[i + j];
|
||
if (bit == '1') {
|
||
byte |= (1 << (7 - j)); // 设置相应的位
|
||
} else if (bit != '0') {
|
||
std::ostringstream oss;
|
||
oss << "Invalid bit character '" << bit << "' at position " << (i + j);
|
||
throw std::invalid_argument(oss.str());
|
||
}
|
||
}
|
||
byte_dest[i / 8] = byte; // 将转换后的字节写入目标内存
|
||
}
|
||
}
|
||
|
||
void hex2mem_Ex(void* dest, const char* data, size_t size) {
|
||
// 判断输入 hex 数据的长度是否为偶数
|
||
if (size % 2 != 0) {
|
||
throw std::invalid_argument("hex string length must be even");
|
||
}
|
||
// 填充目标数据
|
||
for (size_t i = 0; i < size; i += 2) {
|
||
unsigned char hi = data[i];
|
||
unsigned char lo = data[i + 1];
|
||
auto hi_val = hex_to_val[hi];
|
||
auto lo_val = hex_to_val[lo];
|
||
|
||
if (hi_val == 255 || lo_val == 255) {
|
||
std::ostringstream oss;
|
||
oss << "hex:[" << data << "] Invalid hex: [" << data[i] << data[i + 1] << "] at pos " << i;
|
||
throw std::invalid_argument(oss.str());
|
||
}
|
||
|
||
// 填充目标内存
|
||
unsigned char byte = (hi_val << 4) | lo_val;
|
||
std::memcpy(static_cast<unsigned char*>(dest) + i / 2, &byte, 1);
|
||
}
|
||
}
|
||
|
||
void mem2hex_Ex2(void* dest, void* mem, size_t num, bool uppercase, const char* middle, size_t middle_len) {
|
||
assert(middle != nullptr);
|
||
|
||
const char* lut = uppercase ? hex_lut_upper : hex_lut_lower;
|
||
if (middle_len == std::numeric_limits<size_t>::max()) {
|
||
middle_len = (middle != nullptr) ? std::strlen(middle) : 0;
|
||
}
|
||
char* dest_ptr = static_cast<char*>(dest);
|
||
for (size_t i = 0; i < num; ++i) {
|
||
unsigned char c = static_cast<unsigned char*>(mem)[i];
|
||
*dest_ptr++ = lut[c >> 4];
|
||
*dest_ptr++ = lut[c & 0xF];
|
||
// 添加分隔符
|
||
if (middle_len > 0 && i + 1 < num) {
|
||
std::copy(middle, middle + middle_len, dest_ptr);
|
||
dest_ptr += middle_len;
|
||
}
|
||
}
|
||
}
|
||
|
||
void hex2bin_Ex(void* dest, const char* data, size_t size, bool big_dian) {
|
||
auto& dian = big_dian ? big_dian_hex_to_bin : small_dian_hex_to_bin;
|
||
for (size_t i = 0; i < size; i++) {
|
||
auto str = dian[hex_to_val[(unsigned char)(data[i])]];
|
||
std::memmove(static_cast<uint8_t*>(dest) + i * 4, str, 4);
|
||
}
|
||
}
|
||
|
||
void
|
||
bin2hex_Ex(void* dest, const char* d, size_t size, bool big_dian, bool uppercase) {
|
||
const char* lut = uppercase ? hex_lut_upper : hex_lut_lower;
|
||
auto tt = get_bin2hex_size(size);
|
||
auto n1 = size;
|
||
auto n2 = tt * 4;
|
||
char cur[4] = {'0', '0', '0', '0'};
|
||
auto r = static_cast<std::uint8_t*>(dest);
|
||
if (!big_dian) {
|
||
// 小端 补充后导0
|
||
for (size_t i = 0; i < n2; i++) {
|
||
auto j = i%4;
|
||
cur[j] = i >= n1 ? '0' : d[i];
|
||
if (j == 3) {
|
||
auto val = bin4_to_hex(false, cur);
|
||
r[tt - 1 - i/4] = lut[val];
|
||
}
|
||
}
|
||
} else {
|
||
// 大端模式:补充前导0
|
||
for (size_t i = 0; i < n2; i++) {
|
||
// 对应位置
|
||
auto j = i%4;
|
||
cur[j] = i >= n1 ? '0' : d[n1 - 1 - i];
|
||
if (j == 3) {
|
||
auto val = bin4_to_hex(false, cur);
|
||
r[tt - 1 - i/4] = lut[val];
|
||
}
|
||
}
|
||
}
|
||
}
|
||
#ifdef _USE_GTEST
|
||
TEST(Bit2223, bin2hex_Ex) {
|
||
// EXPECT_EQ(bin2hex("01101110"), "6E");
|
||
//
|
||
{
|
||
// 0110 1110
|
||
// 6 E
|
||
std::string it = "1101110";
|
||
auto size = get_bin2hex_size(it.size());
|
||
std::string res;
|
||
res.resize(size);
|
||
bin2hex_Ex(res.data(), it.c_str(), it.size(), true, true);
|
||
EXPECT_STREQ(res.c_str(), "6E");
|
||
}
|
||
{
|
||
// 1101 1100
|
||
// B 3
|
||
|
||
std::string it = "1101110";
|
||
auto size = get_bin2hex_size(it.size());
|
||
std::string res;
|
||
res.resize(size);
|
||
bin2hex_Ex(res.data(), it.c_str(), it.size(), false, true);
|
||
|
||
// std::cout << res << std::endl;
|
||
EXPECT_STREQ(res.c_str(), "3B");
|
||
}
|
||
|
||
|
||
}
|
||
#endif
|
||
|
||
|
||
void xor_bin_Ex(void* dest, const char* s1, size_t n1, const char* s2, size_t n2, bool big_dian) {
|
||
if (n1 > n2) {
|
||
std::swap(n1, n2);
|
||
std::swap(s1, s2);
|
||
}
|
||
// n1 <= n2
|
||
char* r = static_cast<char*>(dest);
|
||
if (!big_dian) {
|
||
// 小端 补充后导0
|
||
for (size_t i = 0; i < n1; i++) {
|
||
r[i] = s1[i] == s2[i] ? '0' : '1';
|
||
}
|
||
for (size_t i = n1; i < n2; i++) {
|
||
r[i] = '0' == s2[i] ? '0' : '1';
|
||
}
|
||
} else {
|
||
// 大端模式:补充前导0
|
||
for (size_t i = 0; i < n1; i++) {
|
||
// 对应位置
|
||
auto c1 = s1[n1 - 1 - i];
|
||
auto c2 = s2[n2 - 1 - i];
|
||
r[n2 - 1 - i] = c1 == c2 ? '0' : '1'; // 对应位异或
|
||
}
|
||
for (size_t i = n1; i < n2; i++) {
|
||
auto c1 = '0';
|
||
auto c2 = s2[n2 - 1 - i];
|
||
r[n2 - 1 - i] = c1 == c2 ? '0' : '1'; // 对应位异或
|
||
}
|
||
}
|
||
}
|
||
#ifdef _USE_GTEST
|
||
TEST(Bit2223, xor_bin_Ex) {
|
||
const char* s1 = "10";
|
||
const char* s2 = "111";
|
||
std::string res;
|
||
res.resize(3);
|
||
xor_bin_Ex(res.data(), s1, 2, s2, 3, true);
|
||
EXPECT_STREQ(res.c_str(), "101");
|
||
xor_bin_Ex(res.data(), s1, 2, s2, 3, false);
|
||
EXPECT_STREQ(res.c_str(), "011");
|
||
xor_bin_Ex(res.data(), s2, 3, s1, 2, false);
|
||
EXPECT_STREQ(res.c_str(), "011");
|
||
|
||
s2 = "1111";
|
||
res.resize(4);
|
||
// 0010
|
||
// 1111
|
||
// 1101
|
||
xor_bin_Ex(res.data(), s1, 2, s2, 4, true);
|
||
EXPECT_STREQ(res.c_str(), "1101");
|
||
}
|
||
#endif
|
||
|
||
|
||
|
||
void xor_hex_Ex(void* dest, const char* s1, size_t n1, const char* s2, size_t n2, bool big_dian, bool uppercase) {
|
||
if (n1 > n2) {
|
||
std::swap(n1, n2);
|
||
std::swap(s1, s2);
|
||
}
|
||
auto& val_to_hex = uppercase ? val_to_upper_hex : val_to_lower_hex;
|
||
// n1 <= n2
|
||
auto r = static_cast<std::uint8_t*>(dest);
|
||
if (!big_dian) {
|
||
// 小端 补充后导0
|
||
for (size_t i = 0; i < n1; i++) {
|
||
//r[i] = s1[i] == s2[i] ? '0' : '1';
|
||
auto c1 = s1[i];
|
||
auto c2 = s2[i];
|
||
r[i] = val_to_hex[xor_table[c1][c2]];
|
||
}
|
||
for (size_t i = n1; i < n2; i++) {
|
||
//r[i] = '0' == s2[i] ? '0' : '1';
|
||
auto c1 = '0';
|
||
auto c2 = s2[i];
|
||
r[i] = val_to_hex[xor_table[c1][c2]];
|
||
}
|
||
} else {
|
||
// 大端模式:补充前导0
|
||
for (size_t i = 0; i < n1; i++) {
|
||
// 对应位置
|
||
auto c1 = s1[n1 - 1 - i];
|
||
auto c2 = s2[n2 - 1 - i];
|
||
//r[n2 - 1 - i] = c1 == c2 ? '0' : '1'; // 对应位异或
|
||
auto idx = xor_table[c1][c2];
|
||
r[n2 - 1 - i] = val_to_hex[idx]; // 对应位异或
|
||
}
|
||
for (size_t i = n1; i < n2; i++) {
|
||
auto c1 = '0';
|
||
auto c2 = s2[n2 - 1 - i];
|
||
auto idx = xor_table[c1][c2];
|
||
//r[n2 - 1 - i] = c1 == c2 ? '0' : '1'; // 对应位异或
|
||
r[n2 - 1 - i] = val_to_hex[idx]; // 对应位异或
|
||
}
|
||
}
|
||
}
|
||
#ifdef _USE_GTEST
|
||
TEST(Bi222, xor_hex_Ex) {
|
||
{
|
||
const char* s1 = "10";
|
||
const char* s2 = "111";
|
||
std::string res;
|
||
res.resize(3);
|
||
xor_hex_Ex(res.data(), s1, 2, s2, 3, true, true);
|
||
EXPECT_STREQ(res.c_str(), "101");
|
||
xor_hex_Ex(res.data(), s1, 2, s2, 3, false, true);
|
||
EXPECT_STREQ(res.c_str(), "011");
|
||
xor_hex_Ex(res.data(), s2, 3, s1, 2, false, true);
|
||
EXPECT_STREQ(res.c_str(), "011");
|
||
}
|
||
{
|
||
const char* s1 = "ab";
|
||
const char* s2 = "111";
|
||
std::string res;
|
||
res.resize(3);
|
||
// 0ab 0000 0110 0111
|
||
// 111 0001 0001 0001
|
||
// 1ba 0001 0111 0110
|
||
xor_hex_Ex(res.data(), s1, 2, s2, 3, true, true);
|
||
EXPECT_STREQ(res.c_str(), "1BA");
|
||
|
||
|
||
|
||
}
|
||
}
|
||
#endif
|
||
|
||
// 将字节序从大端转换到当前平台字节序,并复制到目标内存中
|
||
void big_endian_2_platform(const std::string& big_endian, char* dest) {
|
||
// 先复制原始数据
|
||
std::string result = big_endian;
|
||
// 如果当前平台是小端,反转数据
|
||
if (!is_big_endian) {
|
||
std::reverse(result.begin(), result.end());
|
||
}
|
||
// 将转换后的数据拷贝到目标内存中
|
||
std::memcpy(dest, result.data(), result.size());
|
||
}
|
||
std::string big_endian_2_platform(const std::string& big_endian) {
|
||
std::string result;
|
||
result.resize(big_endian.size());
|
||
big_endian_2_platform(big_endian, result.data());
|
||
return result;
|
||
}
|
||
// 将字节序从小端转换到当前平台字节序,并复制到目标内存中
|
||
void little_endian_2_platform(const std::string& little_endian, char* dest) {
|
||
// 先复制原始数据
|
||
std::string result = little_endian;
|
||
// 如果当前平台是大端,反转数据
|
||
if (is_big_endian) {
|
||
std::reverse(result.begin(), result.end());
|
||
}
|
||
// 将转换后的数据拷贝到目标内存中
|
||
std::memcpy(dest, result.data(), result.size());
|
||
}
|
||
std::string little_endian_2_platform(const std::string& little_endian) {
|
||
std::string result;
|
||
result.resize(little_endian.size());
|
||
big_endian_2_platform(little_endian, result.data());
|
||
return result;
|
||
}
|
||
// 将平台字节序转换为大端字节序
|
||
std::string platform_2_big_endian(void* t, int size) {
|
||
char* memory = reinterpret_cast<char*>(t);
|
||
// for (int i = 0; i < size; ++i) {
|
||
// std::cout << (int)memory[i] << std::endl;
|
||
// }
|
||
std::string result(memory, memory + size);
|
||
// 如果当前平台是小端,反转字符串,使其成为大端字节序
|
||
//std::cout << "platform_2_big_endian start " << memory2hex(result) << std::endl;
|
||
if (!is_big_endian) {
|
||
std::reverse(result.begin(), result.end());
|
||
}
|
||
//std::cout << "platform_2_big_endian end " << memory2hex(result) << std::endl;
|
||
return result;
|
||
}
|
||
// 将平台字节序转换为小端字节序
|
||
std::string platform_2_little_endian(void* t, int size) {
|
||
char* memory = reinterpret_cast<char*>(t);
|
||
std::string result(memory, memory + size);
|
||
// 如果当前平台是大端,反转字符串,使其成为小端字节序
|
||
if (is_big_endian) {
|
||
std::reverse(result.begin(), result.end());
|
||
}
|
||
return result;
|
||
}
|
||
#define GET_BIT(byte, pos) (((byte) >> (pos)) & 1)
|
||
#define SET_BIT(byte, pos) ((byte) |= (1 << (pos)))
|
||
#define CLR_BIT(byte, pos) ((byte) &= ~(1 << (pos)))
|
||
#define WRITE_BIT(byte, pos, val) \
|
||
((byte) = ((byte) & ~(1 << (pos))) | (((val) & 1) << (pos)))
|
||
template <typename BitOp>
|
||
void bit_op(void* dest, size_t d_offset, const void* src, size_t s_offset, size_t num, BitOp op) {
|
||
auto* d = (uint8_t*)dest;
|
||
const auto* s = (const uint8_t*)src;
|
||
for (size_t i = 0; i < num; ++i) {
|
||
size_t src_pos = s_offset + i;
|
||
size_t dst_pos = d_offset + i;
|
||
uint8_t src_bit = GET_BIT(s[src_pos / 8], src_pos % 8);
|
||
uint8_t dst_bit = GET_BIT(d[dst_pos / 8], dst_pos % 8);
|
||
uint8_t res_bit = op(dst_bit, src_bit);
|
||
WRITE_BIT(d[dst_pos / 8], dst_pos % 8, res_bit);
|
||
}
|
||
}
|
||
void bit_move(void* d, size_t doff, const void* s, size_t soff, size_t n) {
|
||
bit_op(d, doff, s, soff, n, [](uint8_t, uint8_t s) { return s; });
|
||
}
|
||
void bit_xor(void* d, size_t doff, const void* s, size_t soff, size_t n) {
|
||
bit_op(d, doff, s, soff, n, [](uint8_t d, uint8_t s) { return d ^ s; });
|
||
}
|
||
void bit_or(void* d, size_t doff, const void* s, size_t soff, size_t n) {
|
||
bit_op(d, doff, s, soff, n, [](uint8_t d, uint8_t s) { return d | s; });
|
||
}
|
||
void bit_and(void* d, size_t doff, const void* s, size_t soff, size_t n) {
|
||
bit_op(d, doff, s, soff, n, [](uint8_t d, uint8_t s) { return d & s; });
|
||
}
|
||
}
|
||
constexpr uint8_t reverse8(uint8_t b) {
|
||
b = (b & 0xF0) >> 4 | (b & 0x0F) << 4;
|
||
b = (b & 0xCC) >> 2 | (b & 0x33) << 2;
|
||
b = (b & 0xAA) >> 1 | (b & 0x55) << 1;
|
||
return b;
|
||
}
|
||
constexpr std::array<uint8_t, 256> make_reverse8_table() {
|
||
std::array<uint8_t, 256> arr = {};
|
||
for (uint16_t i = 0; i < 256; ++i) arr[i] = reverse8(static_cast<uint8_t>(i));
|
||
return arr;
|
||
}
|
||
constexpr auto reserve8 = make_reverse8_table();
|
||
#define BYTE(b) reserve8[0b##b]
|
||
#ifdef _USE_GTEST
|
||
#include <gtest/gtest.h>
|
||
using namespace Psc;
|
||
// 辅助函数:字节数组转十六进制字符串(方便调试)
|
||
std::string bytes_to_hex(const std::vector<uint8_t>& v) {
|
||
std::ostringstream oss;
|
||
for (auto b : v) {
|
||
oss << std::hex << std::setw(2) << std::setfill('0') << (int)b;
|
||
}
|
||
return oss.str();
|
||
}
|
||
// case 2:dest 偏移,src 对齐
|
||
TEST(BitMoveTest, DestBitOffset) {
|
||
struct Data {
|
||
std::vector<uint8_t> dest;
|
||
size_t dest_offset;
|
||
std::vector<uint8_t> src;
|
||
size_t src_offset;
|
||
size_t num;
|
||
std::vector<uint8_t> expected_move;
|
||
std::vector<uint8_t> expected_xor;
|
||
std::vector<uint8_t> expected_or;
|
||
std::vector<uint8_t> expected_and;
|
||
std::string msg;
|
||
};
|
||
std::vector<Data> list;
|
||
// 1. 目标偏移2位,拷贝6位
|
||
// 00 00000000
|
||
// dest 000000
|
||
// src 111100
|
||
// xor: 111100
|
||
// or: 111100
|
||
// and: 000000
|
||
Data d1{
|
||
{BYTE(00000000), BYTE(00000000)},
|
||
2,
|
||
{BYTE(11110000), BYTE(00001111)},
|
||
0,
|
||
6,
|
||
{BYTE(00111100), BYTE(00000000)},
|
||
// move
|
||
{BYTE(00111100), BYTE(00000000)},
|
||
// xor (0x3C, 0x00)
|
||
{BYTE(00111100), BYTE(00000000)},
|
||
// or (0x3C, 0x00)
|
||
{BYTE(00000000), BYTE(00000000)},
|
||
// and (0x00, 0x00)
|
||
"目标偏移2位,拷贝6位"
|
||
};
|
||
|
||
char arr[100];
|
||
size_t a = get_mem2hex_size(2, 0);
|
||
mem2hex_Ex2(arr, d1.expected_move.data(), 2, false, "");
|
||
|
||
|
||
|
||
EXPECT_STREQ(hex2bin(std::string(arr, a)).c_str(), "0011110000000000");
|
||
|
||
|
||
// 2. 目标偏移1位,拷贝9位,跨越目标字节
|
||
// 1 000001
|
||
// dest 000000000
|
||
// src 011111111
|
||
// xor: 011111111
|
||
// or: 011111111
|
||
// and: 000000000
|
||
list.push_back({
|
||
{BYTE(10000000), BYTE(00000001)},
|
||
1,
|
||
{BYTE(01111111), BYTE(10000000)},
|
||
0,
|
||
9,
|
||
{BYTE(10111111), BYTE(11000001)},
|
||
// move
|
||
{BYTE(10111111), BYTE(11000001)},
|
||
// xor (0xFE, 0x83)
|
||
{BYTE(10111111), BYTE(11000001)},
|
||
// or (0xFE, 0x83)
|
||
{BYTE(10000000), BYTE(00000001)},
|
||
// and (0x01, 0x03)
|
||
"目标偏移1位,拷贝9位,跨字节"
|
||
});
|
||
// 3. 目标偏移4,源偏移3,拷贝8位
|
||
// 1100 1010
|
||
// dest 00111010
|
||
// src 10000000
|
||
// xor 10111010
|
||
// or 10111010
|
||
// and 00000000
|
||
list.push_back({
|
||
{BYTE(11000011), BYTE(10101010)},
|
||
4,
|
||
{BYTE(11110000), BYTE(00001111)},
|
||
3,
|
||
8,
|
||
{BYTE(11001000), BYTE(00001010)},
|
||
// move
|
||
{BYTE(11001011), BYTE(10101010)},
|
||
// xor
|
||
{BYTE(11001011), BYTE(10101010)},
|
||
// or
|
||
{BYTE(11000000), BYTE(00001010)},
|
||
// and
|
||
"目标偏移4,源偏移3,拷贝8位"
|
||
});
|
||
// 4. 全1拷贝部分,全0目标
|
||
// 00000 0000
|
||
// dest 0000000
|
||
// src 1111111
|
||
// xor 1111111
|
||
// or 1111111
|
||
// and 0000000
|
||
list.push_back({
|
||
{BYTE(00000000), BYTE(00000000)},
|
||
5,
|
||
{BYTE(11111111), BYTE(11111111)},
|
||
2,
|
||
7,
|
||
{BYTE(00000111), BYTE(11110000)},
|
||
// move
|
||
{BYTE(00000111), BYTE(11110000)},
|
||
// xor
|
||
{BYTE(00000111), BYTE(11110000)},
|
||
// or
|
||
{BYTE(00000000), BYTE(00000000)},
|
||
// and
|
||
"全1源,拷贝7位到目标末尾"
|
||
});
|
||
// 5. 源目标均有内容(交错)
|
||
// 110 10011
|
||
// dest 01100001
|
||
// src 10100101
|
||
// xor 11000100
|
||
// or 11100101
|
||
// and 00100001
|
||
list.push_back({
|
||
{BYTE(11001100), BYTE(00110011)},
|
||
3,
|
||
{BYTE(10101010), BYTE(01010101)},
|
||
4,
|
||
8,
|
||
{BYTE(11010100), BYTE(10110011)},
|
||
// move
|
||
{BYTE(11011000), BYTE(10010011)},
|
||
// xor
|
||
{BYTE(11011100), BYTE(10110011)},
|
||
// or
|
||
{BYTE(11000100), BYTE(00110011)},
|
||
// and
|
||
"目标有内容,源偏移4,拷贝8位"
|
||
});
|
||
// 6. 源目标完全重叠
|
||
// 1011 01
|
||
// dest 1001110100
|
||
// src 1101111010
|
||
// move 1101111010
|
||
// xor 0100001110
|
||
// or 1101111110
|
||
// and 1001110000
|
||
list.push_back({
|
||
{BYTE(10111001), BYTE(11010001)},
|
||
4,
|
||
{BYTE(10110111), BYTE(10100101)},
|
||
2,
|
||
10,
|
||
{BYTE(10111101), BYTE(11101001)},
|
||
// move
|
||
{BYTE(10110100), BYTE(00111001)},
|
||
// xor
|
||
{BYTE(10111101), BYTE(11111001)},
|
||
// or
|
||
{BYTE(10111001), BYTE(11000001)},
|
||
// and
|
||
"目标/源重叠,偏移不同"
|
||
});
|
||
for (auto& d : list) {
|
||
auto dest_move = d.dest;
|
||
auto dest_xor = d.dest;
|
||
auto dest_or = d.dest;
|
||
auto dest_and = d.dest;
|
||
bit_move(dest_move.data(), d.dest_offset, d.src.data(), d.src_offset, d.num);
|
||
bit_xor(dest_xor.data(), d.dest_offset, d.src.data(), d.src_offset, d.num);
|
||
bit_or(dest_or.data(), d.dest_offset, d.src.data(), d.src_offset, d.num);
|
||
bit_and(dest_and.data(), d.dest_offset, d.src.data(), d.src_offset, d.num);
|
||
EXPECT_EQ(dest_move, d.expected_move) << "move 结果: " << hex2bin(bytes_to_hex(dest_move)) << "\n期望: " <<
|
||
hex2bin(bytes_to_hex(d.expected_move)) << "\n" + d.msg;
|
||
EXPECT_EQ(dest_xor, d.expected_xor) << "xor 结果: " << bytes_to_hex(dest_xor) << "\n期望: " <<
|
||
bytes_to_hex(d.expected_xor) << "\n" + d.msg;
|
||
EXPECT_EQ(dest_or, d.expected_or) << "or 结果: " << bytes_to_hex(dest_or) << "\n期望: " <<
|
||
bytes_to_hex(d.expected_or) << "\n" + d.msg;
|
||
EXPECT_EQ(dest_and, d.expected_and) << "and 结果: " << bytes_to_hex(dest_and) << "\n期望: " <<
|
||
bytes_to_hex(d.expected_and) << "\n" + d.msg;
|
||
}
|
||
|
||
}
|
||
|
||
|
||
// 测试二进制到十六进制转换
|
||
TEST(Bit_Convert, Bin2Hex) {
|
||
std::pmr::string s("11101110");
|
||
std::string s2("11101110");
|
||
|
||
// 检查 bin2hex 的转换结果
|
||
EXPECT_EQ(bin2hex(s), "EE"); // 假设 bin2hex("11101110") 应该是 "EE"
|
||
EXPECT_EQ(bin2hex(s2), "EE"); // 同样检查 std::string 版本
|
||
EXPECT_EQ(bin2hex("11101110"), "EE"); // 直接测试常量字符串
|
||
}
|
||
|
||
TEST(BitOpsLE, WriteAndReadFullByte) {
|
||
uint8_t buf[8] = {0};
|
||
set_bits(buf, 0, 8, 0xAB); // 小端模式:低位在低bit
|
||
EXPECT_EQ(buf[0], 0xAB);
|
||
EXPECT_EQ(get_bits(buf, 0, 8), 0xAB);
|
||
}
|
||
TEST(BitOpsLE, CrossByteWriteAndRead) {
|
||
uint8_t buf[8] = {0};
|
||
set_bits(buf, 4, 12, 0xF0F); // 写12位,偏移4
|
||
EXPECT_EQ(get_bits(buf, 4, 12), 0xF0F);
|
||
}
|
||
TEST(BitOpsLE, UnalignedBitWriteAndRead) {
|
||
uint8_t buf[8] = {0};
|
||
set_bits(buf, 5, 10, 0x2AA); // 偏移5位,写10位
|
||
EXPECT_EQ(get_bits(buf, 5, 10), 0x2AA);
|
||
}
|
||
TEST(BitOpsLE, SingleBitWriteAndRead) {
|
||
uint8_t buf[8] = {0};
|
||
set_bits(buf, 10, 1, 1);
|
||
EXPECT_EQ(get_bits(buf, 10, 1), 1);
|
||
set_bits(buf, 10, 1, 0);
|
||
EXPECT_EQ(get_bits(buf, 10, 1), 0);
|
||
}
|
||
TEST(BitOpsLE, WriteAndReadFullUint64) {
|
||
uint8_t buf[8] = {0};
|
||
set_bits(buf, 0, 64, 0x123456789ABCDEF0ULL);
|
||
EXPECT_EQ(get_bits(buf, 0, 64), 0x123456789ABCDEF0ULL);
|
||
}
|
||
TEST(BitOpsLE, OverwriteZeroBits) {
|
||
uint8_t buf[8];
|
||
std::memset(buf, 0xFF, sizeof(buf));
|
||
set_bits(buf, 16, 16, 0x0000);
|
||
EXPECT_EQ(get_bits(buf, 16, 16), 0x0000);
|
||
// 其它位应保持原值
|
||
for (size_t i = 0; i < 2; ++i)
|
||
EXPECT_EQ(buf[i], 0xFF);
|
||
for (size_t i = 4; i < 8; ++i)
|
||
EXPECT_EQ(buf[i], 0xFF);
|
||
}
|
||
TEST(BitOpsLE, AllZeroAndAllOne) {
|
||
uint8_t buf[8] = {0};
|
||
set_bits(buf, 0, 64, 0xFFFFFFFFFFFFFFFFULL);
|
||
EXPECT_EQ(get_bits(buf, 0, 64), 0xFFFFFFFFFFFFFFFFULL);
|
||
set_bits(buf, 0, 64, 0x0ULL);
|
||
EXPECT_EQ(get_bits(buf, 0, 64), 0x0ULL);
|
||
}
|
||
#else
|
||
#endif
|