-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathbin_pack.h
152 lines (122 loc) · 5.54 KB
/
bin_pack.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
/*
+----------------------------------------------------------------------+
| BinPack for PHP |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| [email protected] so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Author: Huqiu Liao <[email protected]> |
+----------------------------------------------------------------------+
*/
#ifndef BIN_PACK_H_
#define BIN_PACK_H_ 1
#include <stddef.h>
#include <stdlib.h>
#include <stdint.h>
#include "bin_pack_def.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
BIN_TYPE_CLOSURE = 0x01,
BIN_TYPE_LIST = 0x02,
BIN_TYPE_DICT = 0x03,
BIN_TYPE_BOOL = 0x04, /* 0000 0100 T */
BIN_TYPE_BOOL_FALSE = 0x05, /* 0000 0101 F */
BIN_TYPE_FLOAT_DOUBLE = 0x06, /* 0010 0110 */
BIN_TYPE_FLOAT_SINGLE = 0x07, /* 0000 0111 */
BIN_TYPE_NULL = 0x0f,
BIN_TYPE_BLOB = 0x10, /* 0001 xxxx */
BIN_TYPE_STRING = 0x20, /* 0010 xxxx */
BIN_TYPE_INTEGER = 0x40, /* 010x xxxx + */
BIN_TYPE_INTEGER_NEGATIVE = 0x60 /* 011x xxxx - */
} bin_type_t;
#define BIN_MASK_INTEGER_SIGN 0x20 /* check if integer is negative */
#define BIN_MASK_TYPE_INTEGER 0x60 /* 0110 0000: integer or negative integer */
#define BIN_MASK_TYPE_STRING_OR_BLOB 0x30 /* 00xx 0000: string or blob */
#define BIN_MASK_LAST_INTEGER 0x1f /* 000x xxxx the last 5 bits */
#define BIN_MASK_LAST_UINT_LEN 0x0f /* 0000 xxxx the last 4 bits will be uesd to pack unit len */
#define BIN_TAG_PACK_INTERGER 0x20 /* 000x xxxx */
#define BIN_TAG_PACK_UINT_LEN 0x10 /* 0000 xxxx */
#define bin_bool_byte(value) ((unsigned char)((value) ? BIN_TYPE_BOOL : BIN_TYPE_BOOL_FALSE))
#define bin_null_byte() ((unsigned char)BIN_TYPE_NULL)
#define bin_closure_byte() ((unsigned char)BIN_TYPE_CLOSURE)
#define bin_list_byte() ((unsigned char)BIN_TYPE_LIST)
#define bin_dict_byte() ((unsigned char)BIN_TYPE_DICT)
#define bin_pack_bool(packer, value) do { \
char byte = bin_bool_byte(value); \
(packer)->write((packer)->buf, (&byte), 1); \
}while(0)
#define bin_pack_null(packer) do { \
char byte = bin_null_byte(); \
(packer)->write((packer)->buf, (&byte), 1); \
}while(0)
#define bin_pack_open_list(packer) do { \
char byte = bin_list_byte(); \
(packer)->write((packer)->buf, (&byte), 1); \
}while(0)
#define bin_pack_open_dict(packer) do { \
char byte = bin_dict_byte(); \
(packer)->write((packer)->buf, (&byte), 1); \
}while(0)
#define bin_pack_closure(packer) do { \
char byte = bin_closure_byte(); \
(packer)->write((packer)->buf, (&byte), 1); \
}while(0)
#define bin_packer_init(PACKER, WRITE, BUF) do { \
(PACKER)->write = (WRITE); \
(PACKER)->buf = (BUF); \
} while(0)
#define bin_unpacker_init(UK, BUF, SIZE) do { \
(UK)->buf = (BUF); \
(UK)->size = (SIZE); \
(UK)->pos = 0; \
(UK)->error = 0; \
} while(0)
size_t bin_int_buffer(char *buf, intmax_t value);
size_t bin_uint_buffer(char *buf, uintmax_t value);
size_t bin_real_buffer(char *buf, double value);
size_t bin_strhead_buffer(char *buf, size_t strlen);
size_t bin_blobhead_buffer(char *buf, size_t bloblen);
typedef struct bin_packer_t {
int (*write)(void *buf, const void *data, size_t size);
void *buf;
int error;
} bin_packer_t;
typedef struct bin_unpacker_t {
char *buf;
size_t size;
size_t pos;
int error;
} bin_unpacker_t;
/*
* Return 0 if success.
* Return -1 if error.
*/
int bin_pack_integer(bin_packer_t *packer, intmax_t value);
int bin_pack_uinteger(bin_packer_t *packer, uintmax_t value);
int bin_pack_lstring(bin_packer_t *packer, const char *str, size_t len);
int bin_pack_string(bin_packer_t *packer, const char *str);
int bin_pack_blob(bin_packer_t *packer, const void *data, size_t len);
int bin_pack_float_double(bin_packer_t *packer, double value);
int bin_pack_float_single(bin_packer_t *packer, float value);
int bin_unpack_type(bin_unpacker_t *job, uintmax_t *p_value);
int bin_unpack_integer(bin_unpacker_t *job, intmax_t *p_value);
int bin_unpack_uinteger(bin_unpacker_t *job, uintmax_t *p_value);
int bin_unpack_lstring(bin_unpacker_t *job, char **p_str, size_t *p_len);
int bin_unpack_blob(bin_unpacker_t *job, void **p_data, size_t *p_len);
int bin_unpack_float_double(bin_unpacker_t *job, double *p_value);
int bin_unpack_float_single(bin_unpacker_t *job, float *p_value);
int bin_unpack_bool(bin_unpacker_t *job, bool *p_value);
int bin_unpack_null(bin_unpacker_t *job);
double bin_make_double(bin_unpacker_t *packer);
float bin_make_float(bin_unpacker_t *packer);
#ifdef __cplusplus
}
#endif
#endif