6 @video https://www.bilibili.com/video/BV1Sr4y1n7bP
14 'a' size_t字符串,前4字节表达长度,然后接着是N字节的数据
15 'A' 指定长度字符串, 例如A8, 代表8字节的数据
18 'n' Lua number , 32bit固件4字节, 64bit固件8字节
20 'b' byte = unsigned char , 1字节
22 'H' unsigned short , 2字节
24 'I' unsigned int , 4字节
25 'l' long , 8字节, 仅64bit固件能正确获取
26 'L' unsigned long , 8字节, 仅64bit固件能正确获取
32 #define OP_ZSTRING 'z' /* zero-terminated string */
33 #define OP_BSTRING 'p' /* string preceded by length byte */
34 #define OP_WSTRING 'P' /* string preceded by length word */
35 #define OP_SSTRING 'a' /* string preceded by length size_t */
36 #define OP_STRING 'A' /* string */
37 #define OP_FLOAT 'f' /* float */
38 #define OP_DOUBLE 'd' /* double */
39 #define OP_NUMBER 'n' /* Lua number */
40 #define OP_CHAR 'c' /* char */
41 #define OP_BYTE 'b' /* byte = unsigned char */
42 #define OP_SHORT 'h' /* short */
43 #define OP_USHORT 'H' /* unsigned short */
44 #define OP_INT 'i' /* int */
45 #define OP_UINT 'I' /* unsigned int */
46 #define OP_LONG 'l' /* long */
47 #define OP_ULONG 'L' /* unsigned long */
48 #define OP_LITTLEENDIAN '<' /* little endian */
49 #define OP_BIGENDIAN '>' /* big endian */
50 #define OP_NATIVE '=' /* native endian */
59 #define LUAT_LOG_TAG "pack"
62 static void badcode(lua_State
*L
, int c
)
64 char s
[]="bad code `?'";
69 static int doendian(int c
)
73 if (c
==OP_LITTLEENDIAN
) return !e
;
74 if (c
==OP_BIGENDIAN
) return e
;
75 if (c
==OP_NATIVE
) return 0;
79 static void doswap(int swap
, void *p
, size_t n
)
85 for (i
=0, j
=n
-1, n
=n
/2; n
--; i
++, j
--)
87 char t
=a
[i
]; a
[i
]=a
[j
]; a
[j
]=t
;
92 #define UNPACKNUMBER(OP,T) \
97 if (i+m>len) goto done; \
101 lua_pushnumber(L,(lua_Number)a); \
106 #define UNPACKINT(OP,T) \
111 if (i+m>len) goto done; \
115 lua_pushinteger(L,(lua_Integer)a); \
120 #define UNPACKINT8(OP,T) \
125 if (i+m>len) goto done; \
129 int t = (a & 0x80)?(0xffffff00+a):a;\
130 lua_pushinteger(L,(lua_Integer)t); \
135 #define UNPACKSTRING(OP,T) \
140 if (i+m>len) goto done; \
143 if (i+m+l>len) goto done; \
145 lua_pushlstring(L,s+i,l); \
153 @api pack.unpack( string, format, init)
158 @return any 第一个解包的值, 根据format值,可能有N个返回值
160 local _,a = pack.unpack(x,">h") --解包成short (2字节)
162 static int l_unpack(lua_State
*L
)
165 const char *s
=luaL_checklstring(L
,1,&len
);
166 const unsigned char *f
= (const unsigned char*)luaL_checkstring(L
,2);
167 int i
=luaL_optnumber(L
,3,1)-1;
178 while (isdigit(*f
)) N
=10*N
+(*f
++)-'0';
179 if (N
==0 && c
==OP_STRING
) { lua_pushliteral(L
,""); ++n
; }
182 if (!lua_checkstack(L
, n
))
183 return luaL_error(L
, "too many results to unpack");
187 case OP_LITTLEENDIAN
:
198 if (i
+N
>len
) goto done
;
199 lua_pushlstring(L
,s
+i
,N
);
208 if (i
>=len
) goto done
;
210 lua_pushlstring(L
,s
+i
,l
);
215 UNPACKSTRING(OP_BSTRING
, unsigned char)
216 UNPACKSTRING(OP_WSTRING
, unsigned short)
217 UNPACKSTRING(OP_SSTRING
, size_t)
218 UNPACKNUMBER(OP_NUMBER
, lua_Number
)
219 #ifndef LUA_NUMBER_INTEGRAL
220 UNPACKNUMBER(OP_DOUBLE
, double)
221 UNPACKNUMBER(OP_FLOAT
, float)
223 UNPACKINT8(OP_CHAR
, char)
224 UNPACKINT(OP_BYTE
, unsigned char)
225 UNPACKINT(OP_SHORT
, short)
226 UNPACKINT(OP_USHORT
, unsigned short)
227 UNPACKINT(OP_INT
, int)
228 UNPACKINT(OP_UINT
, unsigned int)
229 UNPACKINT(OP_LONG
, long)
230 UNPACKINT(OP_ULONG
, unsigned long)
240 lua_pushnumber(L
,i
+1);
245 #define PACKNUMBER(OP,T) \
248 T a=(T)luaL_checknumber(L,i++); \
249 doswap(swap,&a,sizeof(a)); \
250 luaL_addlstring(&b,(void*)&a,sizeof(a)); \
254 #define PACKINT(OP,T) \
257 T a=(T)luaL_checkinteger(L,i++); \
258 doswap(swap,&a,sizeof(a)); \
259 luaL_addlstring(&b,(void*)&a,sizeof(a)); \
263 #define PACKSTRING(OP,T) \
267 const char *a=luaL_checklstring(L,i++,&l); \
269 doswap(swap,&ll,sizeof(ll)); \
270 luaL_addlstring(&b,(void*)&ll,sizeof(ll)); \
271 luaL_addlstring(&b,a,l); \
277 @api pack.pack( format, val1, val2, val3, valn )
283 @return string 一个包含所有格式化变量的字符串
285 local data = pack.pack('<h', crypto.crc16("MODBUS", val))
286 log.info("data", data, data:toHex())
288 static int l_pack(lua_State
*L
)
291 const unsigned char *f
=(const unsigned char*)luaL_checkstring(L
,1);
302 while (isdigit(*f
)) N
=10*N
+(*f
++)-'0';
304 while (N
--) switch (c
)
306 case OP_LITTLEENDIAN
:
318 const char *a
=luaL_checklstring(L
,i
++,&l
);
319 luaL_addlstring(&b
,a
,l
+(c
==OP_ZSTRING
));
322 PACKSTRING(OP_BSTRING
, unsigned char)
323 PACKSTRING(OP_WSTRING
, unsigned short)
324 PACKSTRING(OP_SSTRING
, size_t)
325 PACKNUMBER(OP_NUMBER
, lua_Number
)
326 #ifndef LUA_NUMBER_INTEGRAL
327 PACKNUMBER(OP_DOUBLE
, double)
328 PACKNUMBER(OP_FLOAT
, float)
330 PACKINT(OP_CHAR
, char)
331 PACKINT(OP_BYTE
, unsigned char)
332 PACKINT(OP_SHORT
, short)
333 PACKINT(OP_USHORT
, unsigned short)
335 PACKINT(OP_UINT
, unsigned int)
336 PACKINT(OP_LONG
, long)
337 PACKINT(OP_ULONG
, unsigned long)
349 int luat_pack(lua_State
*L
) {
353 int luat_unpack(lua_State
*L
) {
357 #include "rotable2.h"
358 static const rotable_Reg_t reg_pack
[] =
360 {"pack", ROREG_FUNC(l_pack
)},
361 {"unpack", ROREG_FUNC(l_unpack
)},
362 {NULL
, ROREG_INT(0) }
365 LUAMOD_API
int luaopen_pack( lua_State
*L
) {
366 luat_newlib2(L
, reg_pack
);