当前位置:网站首页>字节序数据读写
字节序数据读写
2022-06-12 13:26:00 【Li.CQ】
字节序判断
iOS中的字节序转换和字节序判断方法详见 NSByteOrder.h 文件中, 具体实现见 CFByteOrder.h
// - 0x01020304在内存中的表现, 小字节序 : 04 03 02 01, 大字节序 01 02 03 04 iOS系统是小字节序;
static uint8_t is_little_endian(){
union {
int a;
uint8_t b;
}c;
// - 此时共用体 c在iOS系统内存中的表现是 01 00 00 00; 则 c.a = 0x00000001, c.b = 0x01, c.a == c.b, 表示了iOS系统是小字节序;
c.a = 1;
return c.b == 1;
/** 地址 低->高 */
c.a = 0x01020304;
0x7ffeefbff388 : 04 03 02 01
c.b = 0x05;
0x7ffeefbff388 : 05 03 02 01
struct {
int a;
int b;
}c;
c.a = 0x01020304;
c.b = 0x05060708;
/** 地址 低->高 */
0x7ffeefbff388 : 04 03 02 01 08 07 06 05
}
数据读写功能的实现
/* 可以用于二进制数据的持续读写 */
#ifndef aw_data_h
#define aw_data_h
#include <stdio.h>
// - 定义数据读写的结构体
//文件数据
typedef struct aw_data{
uint32_t size;//有效数据长度
uint32_t alloc_size;//分配的数据长度
uint32_t curr_pos;//读取或写入的位置
uint8_t *data;//实际数据
}aw_data;
//数据读取,自动处理大小端
typedef struct aw_data_reader{
uint8_t (*read_uint8)(aw_data *); // - 读取1个字节
uint16_t (*read_uint16)(aw_data *); // - 读取2个字节
uint32_t (*read_uint24)(aw_data *); // - 读取3个字节
uint32_t (*read_uint32)(aw_data *); // - 读取4个字节
uint64_t (*read_uint64)(aw_data *); // - 读取8个字节
double (*read_double)(aw_data *); // - 读取double类型
void (*read_string)(aw_data *, char **, int); // - 读取指定长度的字符串
void (*read_bytes)(aw_data *, char **, int); // - 读取指定长度的字节
void (*skip_bytes)(aw_data *, int); // - 跳过指定长度的字节
int (*remain_count)(aw_data *); // - 获取剩余没有读取的字节的长度
//debug,纪录某个程序段,一共读取数据的数量。
void (*start_record_size)();
size_t (*record_size)();
void (*end_record_size)();
void (*start_read)(aw_data *);
}aw_data_reader;
//数据写入,自动处理大小端
typedef struct aw_data_writer{
void (*write_uint8)(aw_data **, uint8_t); // - 写入1个字节
void (*write_uint16)(aw_data **, uint16_t); // - 写入2个字节
void (*write_uint24)(aw_data **, uint32_t); // - 写入3个字节
void (*write_uint32)(aw_data **, uint32_t); // - 写入4个字节
void (*write_uint64)(aw_data **, uint64_t); // - 写入8个字节
void (*write_double)(aw_data **, double); // - 写入double
void (*write_string)(aw_data **, const char *, uint32_t); // - 写入指定长度的字符串,并且将字符长度写在字符串前 uint32_t 字节中;
void (*write_bytes)(aw_data **, const uint8_t *, uint32_t); // - 写入指定长度的字节
void (*write_empty_bytes)(aw_data **, uint32_t); // - 写入空字节
//debug,纪录某个程序段,一共写入数据的数量。
void (*start_record_size)();
size_t (*record_size)();
void (*end_record_size)();
}aw_data_writer;
//全局读写 reader 和 writer
extern aw_data_reader data_reader;
extern aw_data_writer data_writer;
#include "aw_data.h"
#include <string.h>
#include <stdlib.h>
static int8_t aw_is_started_record_size = 0;
static uint32_t aw_recorded_size = 0;
static void aw_start_record_size(){
if (aw_is_started_record_size) {
AWLog("[ERROR] record size is already in use!!");
return;
}
aw_is_started_record_size = 1;
aw_recorded_size = 0;
}
static void aw_increase_record_size(size_t size){
if (aw_is_started_record_size) {
aw_recorded_size += size;
}
}
static size_t aw_get_recorded_size(){
return aw_recorded_size;
}
static void aw_end_record_size(){
aw_is_started_record_size = 0;
aw_recorded_size = 0;
}
#define AW_DATA_ALLOC_BLOCK 10 * 1024
void memcpy_aw_data(aw_data **tdata, const void *fdata, int size){
if (!tdata) {
return;
}
aw_data *tdatap = *tdata;
if (!tdatap) {
tdatap = alloc_aw_data(size);
*tdata = tdatap;
}
int new_size = tdatap->alloc_size;
while (new_size < tdatap->size + size) {
new_size += AW_DATA_ALLOC_BLOCK;
}
if (new_size > tdatap->alloc_size) {
extend_aw_data(tdata, new_size);
tdatap = *tdata;
}
memcpy(tdatap->data + tdatap->curr_pos, fdata, size);
tdatap->curr_pos += size;
tdatap->size = tdatap->curr_pos;
}
aw_data * alloc_aw_data(int size){
int awdatasize = sizeof(aw_data);
aw_data *awdata = (aw_data *)aw_alloc(awdatasize);
memset(awdata, 0, awdatasize);
if (size == 0) {
size = AW_DATA_ALLOC_BLOCK;
}
awdata->data = aw_alloc(size);
awdata->alloc_size = size;
return awdata;
}
extern aw_data * copy_aw_data(aw_data *data){
if (!data) {
return NULL;
}
aw_data *new_data = alloc_aw_data(data->alloc_size);
memcpy_aw_data(&new_data, data->data, data->size);
return new_data;
}
void extend_aw_data(aw_data **old_aw_data, int new_size){
aw_data * new_aw_data = alloc_aw_data(new_size);
memcpy_aw_data(&new_aw_data, (*old_aw_data)->data, (*old_aw_data)->size);
free_aw_data(old_aw_data);
*old_aw_data = new_aw_data;
}
extern void reset_aw_data(aw_data **data){
aw_data *aw_data = *data;
if (aw_data && aw_data->curr_pos > 0 && aw_data->size > 0) {
aw_data->curr_pos = 0;
memset(aw_data->data, 0, aw_data->size);
aw_data->size = 0;
}
}
void free_aw_data(aw_data **data){
aw_data *aw_data = *data;
aw_free(aw_data->data);
aw_data->size = 0;
aw_data->alloc_size = 0;
aw_data->curr_pos = 0;
aw_data->data = 0;
aw_free(aw_data);
*data = NULL;
}
//大小端转换
#define CONVERT_32(i, store, size) \
do{\
store = 0;\
for(int j = 0; j < size; j++){ \
store |= (((i & (0xff << j * 8)) >> j * 8) & 0xff) << (((int)size - 1 - j) * 8); \
} \
}while(0)
//大小端不影响移位操作
#define CONVERT_64(i, store, size) \
do{ \
/*后面*/ \
uint32_t i1 = (uint32_t)i; \
uint32_t store1 = 0; \
CONVERT_32(i1, store1, 4); \
uint32_t *ipre = (uint32_t *)&store + 1; \
memcpy(ipre, &store1, 4); \
/*前面*/\
uint32_t i2 = i >> 32; \
uint32_t store2 = 0; \
CONVERT_32(i2, store2, 4); \
uint32_t *itail = (uint32_t *)&store; \
memcpy(itail, &store2, 4); \
}while(0)
#define CONVERT(i, store, size) \
do{ \
if(size < 8){ \
CONVERT_32(i, store, size); \
} else { \
CONVERT_64(i, store, size); \
} \
}while(0)
//读取数据
//读取单字节
#define READ_BYTE(type, i) \
size_t type_size = sizeof(type); \
memcpy(&i, awdata->data + awdata->curr_pos, type_size); \
awdata->curr_pos += type_size; \
aw_increase_record_size(type_size);
//读取多字节,系统字节序为小端
#define READ_MUTIBYTES_FOR_LITTLE_ENDIAN(i, type, size) \
do{ \
READ_MUTIBYTES_FOR_BIG_ENDIAN(i, type, size); \
type store = 0; \
CONVERT(i, store, size); \
i = store; \
}while(0);
//读取多字节,系统字节序为大端
#define READ_MUTIBYTES_FOR_BIG_ENDIAN(i, type, isize) \
do{\
memcpy(&i, awdata->data + awdata->curr_pos, isize); \
awdata->curr_pos += isize; \
aw_increase_record_size(isize); \
} while(0);
//读取多字节,自动判断大小端
#define READ_MUTIBYTES(i, type, size) \
do{\
if(is_little_endian()) {\
READ_MUTIBYTES_FOR_LITTLE_ENDIAN(i, type, size); \
}else{\
READ_MUTIBYTES_FOR_BIG_ENDIAN(i, type, size); \
}\
}while(0);
//读取多字节带返回值
#define RETURN_FOR_READ_MUTIBYTES(type) \
type i; \
READ_MUTIBYTES(i, type, sizeof(type)); \
return i;
static uint8_t is_little_endian(){
union {
int a;
uint8_t b;
}c;
c.a = 1;
return c.b == 1;
}
static void start_read(aw_data *awdata){
awdata->curr_pos = 0;
}
static uint8_t read_uint8(aw_data *awdata){
uint8_t i;
READ_BYTE(uint8_t, i);
return i;
}
static uint16_t read_uint16(aw_data *awdata){
RETURN_FOR_READ_MUTIBYTES(uint16_t);
}
static uint32_t read_uint24(aw_data *awdata){
uint32_t i;
READ_MUTIBYTES(i, uint32_t, 3);
return i;
}
static uint32_t read_uint32(aw_data *awdata){
RETURN_FOR_READ_MUTIBYTES(uint32_t);
}
static uint64_t read_uint64(aw_data *awdata){
RETURN_FOR_READ_MUTIBYTES(uint64_t);
}
static double read_double(aw_data *awdata){
uint64_t i;
READ_MUTIBYTES(i, uint64_t, sizeof(i));
double d = 0;
memcpy(&d, &i, sizeof(i));
return d;
}
static void read_string(aw_data* awdata, char **string, int len){
*string = aw_alloc(len);
memset(*string, 0, len + 1);
memcpy(*string, awdata->data + awdata->curr_pos, len);
awdata->curr_pos += len;
aw_increase_record_size(len);
}
static void read_bytes(aw_data * awdata, char **bytes, int len){
*bytes = aw_alloc(len);
memset(*bytes, 0, len);
memcpy(*bytes, awdata->data + awdata->curr_pos, len);
awdata->curr_pos += len;
aw_increase_record_size(len);
}
static void skip_bytes(aw_data* awdata, int count){
awdata->curr_pos += count;
aw_increase_record_size(count);
}
static int remain_count(aw_data *awdata){
return awdata->size - awdata->curr_pos;
}
//写入
static void write_uint8(aw_data **awdata, uint8_t v){
memcpy_aw_data(awdata, &v, 1);
aw_increase_record_size(1);
}
static void write_uint16(aw_data **awdata, uint16_t v){
uint16_t big = v;
if (is_little_endian()) {
CONVERT(v, big, sizeof(v));
}
memcpy_aw_data(awdata, &big, sizeof(uint16_t));
aw_increase_record_size(2);
}
static void write_uint24(aw_data **awdata, uint32_t v){
uint32_t big = v;
if (is_little_endian()) {
CONVERT(v, big, 3);
}
memcpy_aw_data(awdata, &big, sizeof(uint8_t) * 3);
aw_increase_record_size(3);
}
static void write_uint32(aw_data **awdata, uint32_t v){
uint32_t big = v;
if (is_little_endian()) {
CONVERT(v, big, sizeof(v));
}
memcpy_aw_data(awdata, &big, sizeof(uint32_t));
aw_increase_record_size(4);
}
static void write_uint64(aw_data **awdata, uint64_t v){
uint64_t big = v;
if (is_little_endian()) {
CONVERT(v, big, sizeof(v));
}
memcpy_aw_data(awdata, &big, sizeof(uint64_t));
aw_increase_record_size(8);
}
static void write_double(aw_data **awdata, double v){
uint64_t newV = 0;
memcpy(&newV, &v, sizeof(uint64_t));
write_uint64(awdata, newV);
}
static void write_bytes(aw_data **awdata, const uint8_t *bytes, uint32_t count){
memcpy_aw_data(awdata, bytes, (int)count);
aw_increase_record_size(count);
}
static void write_string(aw_data **awdata, const char *str, uint32_t len_bytes_count){
size_t str_len = strlen((const char *)str);
switch (len_bytes_count) {
case 1:
write_uint8(awdata, (uint8_t) str_len);
break;
case 2:
write_uint16(awdata, (uint16_t) str_len);
break;
case 4:
write_uint32(awdata, (uint32_t) str_len);
break;
case 8:
write_uint64(awdata, (uint64_t) str_len);
break;
default:
break;
}
write_bytes(awdata, (const uint8_t *)str, (int)str_len);
}
static void write_empty_bytes(aw_data **awdata, uint32_t count){
uint8_t *empty_bytes = (uint8_t *)aw_alloc(count);
memset(empty_bytes, 0, count);
write_bytes(awdata, empty_bytes, count);
}
//初始化 awdata operation
aw_data_reader data_reader = {
.start_read = start_read,
.read_uint8 = read_uint8,
.read_uint16 = read_uint16,
.read_uint24 = read_uint24,
.read_uint32 = read_uint32,
.read_uint64 = read_uint64,
.read_double = read_double,
.read_string = read_string,
.read_bytes = read_bytes,
.skip_bytes = skip_bytes,
.remain_count = remain_count,
//debug
.start_record_size = aw_start_record_size,
.record_size = aw_get_recorded_size,
.end_record_size = aw_end_record_size,
};
aw_data_writer data_writer = {
.write_uint8 = write_uint8,
.write_uint16 = write_uint16,
.write_uint24 = write_uint24,
.write_uint32 = write_uint32,
.write_uint64 = write_uint64,
.write_double = write_double,
.write_string = write_string,
.write_bytes = write_bytes,
.write_empty_bytes = write_empty_bytes,
//debug
.start_record_size = aw_start_record_size,
.record_size = aw_get_recorded_size,
.end_record_size = aw_end_record_size,
};
#define StringMark1(mark) #mark
#define StringMark(mark) StrintMark1(mark)
#define TWO 2
#define PRINT(n) AWLog("%s", StringMark(n))
#define TEST(type, funcname, value, printMark) \
wdata = alloc_aw_data(0); \
type funcname##1 = value; \
data_writer.write_##funcname(&wdata, funcname##1); \
data_reader.start_read(wdata); \
type funcname##2 = data_reader.read_##funcname(wdata); \
AWLog(#type".1 = %"printMark", u"#type".2 = %"printMark, funcname##1, funcname##2); \
free_aw_data(&wdata);
static void aw_data_test_convert(){
uint8_t u8 = 0x12;
uint8_t u81 = 0;
CONVERT(u8, u81, 1);
AWLog("u8=%x, u81=%x", u8, u81);
uint16_t u16 = 0x1234;
uint16_t u161 = 0;
CONVERT_32(u16, u161, 2);
AWLog("u16=%x, u161=%x", u16, u161);
uint32_t u24 = 0x123456;
uint32_t u241 = 0;
CONVERT_32(u24, u241, 3);
AWLog("u24=%x, u241=%x", u24, u241);
uint32_t u32 = 0x12345678;
uint32_t u321 = 0;
CONVERT_32(u32, u321, 4);
AWLog("u32=%x, u321=%x", u32, u321);
uint64_t u64 = 0x12345678aabbccdd;
uint64_t u641 = 0;
CONVERT_64(u64, u641, 8);
AWLog("u64=%llx, u641=%llx", u64, u641);
}
extern void aw_data_test(){
AWLog("小端 = %d", is_little_endian());
aw_data_test_convert();
aw_data *
// 8字节
TEST(uint8_t, uint8, 0xaa, "x");
TEST(uint16_t, uint16, 0xaabb, "x");
TEST(uint32_t, uint24, 0xabcdef, "x");
TEST(uint32_t, uint32, 0x12345678, "x");
TEST(uint64_t, uint64, 0x12345678aabbccdd, "llx");
double d1 = 0.12345678;
uint64_t di1 = 0;
memcpy(&di1, &d1, sizeof(uint64_t));
wdata = alloc_aw_data(0);
data_writer.write_double(&wdata, d1);
data_reader.start_read(wdata);
double d2 = data_reader.read_double(wdata);
uint64_t di2 = 0;
memcpy(&di2, &d2, sizeof(uint64_t));
AWLog("d.1 = %llx, d.2 = %llx \n", di1, di2);
free_aw_data(&wdata);
}
上述代码复制自 AWLive, 这个 aw_data 写法极其值得学习, 包括数据的读取和写入,并且自动字节序判断, 非常好, 而且不依赖iOS系统的库, 可以放在任意支持C语言的平台上使用;
边栏推荐
- Application of bit operation in C language
- A brief introduction to Verilog mode
- 2063: [example 1.4] cattle eat grass
- 442 authors, 100 pages! It took Google 2 years to release the new benchmark big bench | open source
- Script import CDN link prompt net:: err_ FILE_ NOT_ Found problem
- hudi 键的生成(Key Generation)
- Design virtual network to realize communication between virtual machine instance and external network
- Informatics Olympiad all in one 2059: [example 3.11] buy a pen
- Chrome debugging tool
- Title: Yanghui triangle
猜你喜欢

Title: Yanghui triangle
![[wechat applet development] Part 1: development tool installation and program configuration](/img/a8/f4dcbde295ba7cf738d878464b3af0.png)
[wechat applet development] Part 1: development tool installation and program configuration

Hardware composition of embedded system - introduction of embedded development board based on ARM

Script import CDN link prompt net:: err_ FILE_ NOT_ Found problem

Semantic segmentation with pytorch

Getting to know blob objects

Automatic Generation of Visual-Textual Presentation Layout

创新实训(十)高级界面美化

VGA display color bar and picture (FPGA)

Bitmap, bloom filter and hash sharding
随机推荐
Title: Yanghui triangle
[you code, I fix] whitesource was officially renamed mend
C language [23] classic interview questions [2]
leetcode 47. Permutations II 全排列 II(中等)
微信web开发者工具使用教程,web开发问题
VGA display color bar and picture (FPGA)
Application of binary search -- finding the square root sqrt of a number
镜像扫描工具预研
[brush title] probability of winning a draw
Getting to know blob objects
嵌入式系統硬件構成-基於ARM的嵌入式開發板介紹
torch_ geometric message passing network
Newoj week 10 question solution
单向环形链表实现约瑟夫环
One line of code to implement shell if else logic
创新实训(十)高级界面美化
leetcode 47. Permutations II 全排列 II(中等)
创新实训(十二)项目总结
2062: [example 1.3] movie tickets
hudi 键的生成(Key Generation)