-
Notifications
You must be signed in to change notification settings - Fork 0
/
decoder.c
171 lines (155 loc) · 4.46 KB
/
decoder.c
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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
#include "xrpack.h"
#define xrio_invalid_check(L, ilen, len) if (ilen > len) return luaL_error(L, "buffer was Invalid.");
/* 读取`Nil` */
static inline int read_nil(lua_State *L) {
lua_pushnil(L);
return 1;
}
/* 读取`Null` */
static inline int read_null(lua_State *L) {
lua_pushlightuserdata(L, NULL);
return 1;
}
/* 读取`Boolean` */
static inline int read_boolean(lua_State *L, const char *buffer, size_t len) {
xrio_invalid_check(L, 1, len);
lua_pushboolean(L, *buffer ? 1 : 0);
return 2;
}
/* 读取`Integer` */
static inline int read_int8(lua_State *L, const char *buffer, size_t len) {
xrio_invalid_check(L, 1, len);
lua_pushinteger(L, (uint8_t)buffer[0]);
return 2;
}
static inline int read_int16(lua_State *L, const char *buffer, size_t len) {
xrio_invalid_check(L, 2, len);
lua_pushinteger(L, (uint16_t)buffer[0] | (uint16_t)buffer[1] << 8);
return 3;
}
static inline int read_int32(lua_State *L, const char *buffer, size_t len) {
xrio_invalid_check(L, 4, len);
union { uint32_t i; char buffer[4]; } v;
memmove(v.buffer, buffer, 4);
lua_pushinteger(L, v.i);
return 5;
}
static inline int read_int64(lua_State *L, const char *buffer, size_t len) {
xrio_invalid_check(L, 8, len);
union { int64_t i; char buffer[8]; } v;
memmove(v.buffer, buffer, 8);
lua_pushinteger(L, v.i);
return 9;
}
/* 读取`Number` */
static inline int read_number(lua_State *L, const char *buffer, size_t len) {
xrio_invalid_check(L, 8, len);
union { lua_Number n; char buffer[8]; } v;
memmove(v.buffer, buffer, 8);
lua_pushnumber(L, v.n);
return 9;
}
/* 读取`CString` */
static inline int read_sstring(lua_State *L, const char *buffer, size_t len){
uint8_t csize = 0;
xrio_invalid_check(L, 1, len);
csize = (uint8_t)buffer[0];
if (csize)
xrio_invalid_check(L, 1 + csize, len);
lua_pushlstring(L, buffer + 1, csize);
return 2 + csize;
}
static inline int read_lstring(lua_State *L, const char *buffer, size_t len){
uint32_t csize = 0;
xrio_invalid_check(L, 4, len);
csize = buffer[3] << 24 | buffer[2] << 16 | buffer[1] << 8 | buffer[0];
if (csize)
xrio_invalid_check(L, csize + 4, len);
lua_pushlstring(L, buffer + 4, csize);
return 5 + csize;
}
static inline int decoder_read(lua_State *L, const char *buffer, size_t *pos, size_t len);
/* 读取`Table` */
static inline int read_table(lua_State *L, const char *buffer, size_t len) {
int offset = 0;
int bsize = len;
size_t position = 0;
lua_newtable(L);
int top = lua_gettop(L);
while (bsize)
{
offset = decoder_read(L, buffer, &position, bsize);
if (offset == -1)
break;
/* 检查堆栈字段 */
if (top + 2 == lua_gettop(L))
lua_rawset(L, top);
/* 计算偏移值 */
bsize -= offset; position += offset;
}
return position;
}
static inline int decoder_read(lua_State *L, const char *buffer, size_t *pos, size_t len) {
size_t offset = 0;
switch (buffer[*pos])
{
case XRTYPE_NIL:
offset = read_nil(L);
break;
case XRTYPE_USERDATA:
offset = read_null(L);
break;
case XRTYPE_BOOLEAN:
offset = read_boolean(L, buffer + *pos + 1, len - 1);
break;
case XRTYPE_INT8:
offset = read_int8(L, buffer + *pos + 1, len - 1);
break;
case XRTYPE_INT16:
offset = read_int16(L, buffer + *pos + 1, len - 1);
break;
case XRTYPE_INT32:
offset = read_int32(L, buffer + *pos + 1, len - 1);
break;
case XRTYPE_INT64:
offset = read_int64(L, buffer + *pos + 1, len - 1);
break;
case XRTYPE_NUMBER:
offset = read_number(L, buffer + *pos + 1, len - 1);
break;
case XRTYPE_SSTRING:
offset = read_sstring(L, buffer + *pos + 1, len - 1);
break;
case XRTYPE_LSTRING:
offset = read_lstring(L, buffer + *pos + 1, len - 1);
break;
case XRTYPE_TABLE:
offset = read_table(L, buffer + *pos + 1, len);
offset += 2;
break;
case 0x00:
offset = -1;
break;
default:
return luaL_error(L, "decode error: Invalid type. (%d, %d)", *pos, len);
}
return offset;
}
int decoder(lua_State *L) {
size_t bsize;
const char * buffer = luaL_checklstring(L, 1, &bsize);
if (!buffer || bsize < 4)
return luaL_error(L, "Invalid decoder buffer.");
size_t nret = 0;
size_t position = 0;
size_t offset = 0;
int blen = bsize - 4;
buffer = buffer + 4;
while (blen)
{
offset = decoder_read(L, buffer, &position, blen);
blen -= offset; position += offset;
nret++;
}
return nret;
}