开发过程中,对于自定义协议的打包,可以借助stream完成。
stream.h
#pragma once
#include <stdio.h>
#include <string.h>
typedef struct stream
{
char d[256];
size_t size;
size_t len;
size_t pos;
} stream, *pstream;
void stem_init(pstream s);
void stem_push(pstream s, void *value, size_t vsize, int flip);
void stem_dump(pstream s, FILE *f);
#define stem_push_func(type) \
inline void stem_push_##type(pstream s, type v, int flip) \
{ stem_push(s, &v, sizeof(v), flip); }
#define stem_push_func_i(type) \
stem_push_func(type) \
inline void stem_push_u##type(pstream s, unsigned type v, int flip) \
{ stem_push(s, &v, sizeof(v), flip); }
stem_push_func_i(char)
stem_push_func_i(short)
stem_push_func_i(int)
stem_push_func(float)
stem_push_func(double)
inline void stem_push_string(pstream s, const char *str)
{
stem_push(s, (void*)str, strlen(str), 0);
}
stream.c
#include <assert.h>
#include <memory.h>
#include "stream.h"
void stem_init(pstream s)
{
s->size = 256;
s->len = s->pos = 0;
memset(s->d, 0, s->size);
}
void stem_push(pstream s, void *value, size_t vsize, int flip)
{
assert(s);
assert(vsize <= s->size - s->pos);
if (!flip)
{
memcpy(s->d + s->pos, value, vsize);
}
else
{
char *pe = (char*)value + vsize;
switch (vsize)
{
case 1:
*(s->d + s->pos + 0) = *--pe;
break;
case 2:
*(s->d + s->pos + 0) = *--pe;
*(s->d + s->pos + 1) = *--pe;
break;
case 4:
*(s->d + s->pos + 0) = *--pe;
*(s->d + s->pos + 1) = *--pe;
*(s->d + s->pos + 2) = *--pe;
*(s->d + s->pos + 3) = *--pe;
break;
case 8:
*(s->d + s->pos + 0) = *--pe;
*(s->d + s->pos + 1) = *--pe;
*(s->d + s->pos + 2) = *--pe;
*(s->d + s->pos + 3) = *--pe;
*(s->d + s->pos + 4) = *--pe;
*(s->d + s->pos + 5) = *--pe;
*(s->d + s->pos + 6) = *--pe;
*(s->d + s->pos + 7) = *--pe;
break;
default:
for (size_t i = 0; i < vsize; i++)
{
memcpy(s->d + s->pos + i, --pe, 1);
}
break;
}
}
s->len += vsize;
s->pos += vsize;
}
void stem_dump(pstream s, FILE *f)
{
if (s->len)
{
for (size_t i = 0; i < s->len; i++)
fprintf(f, "%02x ", (unsigned char)s->d[i]);
fprintf(f, "\n");
}
else
{
fputs("stream:[]", f);
}
}
main.c
#include "stream.h"
int main()
{
stream s;
stem_init(&s);
stem_push_char(&s, 'a', 0);
stem_push_uchar(&s, 'b', 0);
stem_push_short(&s, -1234, 0);
stem_push_ushort(&s, 4455, 0);
stem_push_int(&s, 0xAABBCCDD, 1);
stem_push_uint(&s, 0xAABBCCDD, 0);
stem_push_float(&s, 3.14f, 0);
stem_push_double(&s, 6.155, 0);
stem_push_string(&s, "hello, world!");
stem_dump(&s, stdout);
int x = 0xDDCCBBAA;
unsigned int ux = 0xAABBCCDD;
printf("\n");
printf("x: %d\n", x);
printf("ux: %u\n", ux);
printf("\n");
printf("char: %c\n", *(s.d + 0));
printf("uchar: %c\n", *(s.d + 1));
printf("short: %d\n", *(short*)(s.d + 2));
printf("ushort: %d\n", *(unsigned short*)(s.d + 4));
printf("int: %i\n", *(int*)(s.d + 6));
printf("uint: %u\n", *(unsigned int*)(s.d + 10));
printf("float: %f\n", *(float*)(s.d + 14));
printf("doulbe: %f\n", *(double*)(s.d + 18));
printf("string: %s\n", (s.d + 26));
}