]>
git.zerfleddert.de Git - proxmark3-svn/blob - client/pm3_binlib.c
3 * a Lua library for packing and unpacking binary data
4 * Luiz Henrique de Figueiredo <lhf@tecgraf.puc-rio.br>
6 * This code is hereby placed in the public domain.
7 * with contributions from Ignacio Castao <castanyo@yahoo.es> and
8 * Roberto Ierusalimschy <roberto@inf.puc-rio.br>.
11 #define OP_ZSTRING 'z' /* zero-terminated string */
12 #define OP_BSTRING 'p' /* string preceded by length byte */
13 #define OP_WSTRING 'P' /* string preceded by length word */
14 #define OP_SSTRING 'a' /* string preceded by length size_t */
15 #define OP_STRING 'A' /* string */
16 #define OP_FLOAT 'f' /* float */
17 #define OP_DOUBLE 'd' /* double */
18 #define OP_NUMBER 'n' /* Lua number */
19 #define OP_CHAR 'c' /* char (1-byte int) */
20 #define OP_BYTE 'C' /* byte = unsigned char (1-byte unsigned int) */
21 #define OP_SHORT 's' /* short (2-byte int) */
22 #define OP_USHORT 'S' /* unsigned short (2-byte unsigned int) */
23 #define OP_INT 'i' /* int (4-byte int) */
24 #define OP_UINT 'I' /* unsigned int (4-byte unsigned int) */
25 #define OP_LONG 'l' /* long (8-byte int) */
26 #define OP_ULONG 'L' /* unsigned long (8-byte unsigned int) */
27 #define OP_LITTLEENDIAN '<' /* little endian */
28 #define OP_BIGENDIAN '>' /* big endian */
29 #define OP_NATIVE '=' /* native endian */
39 #include "pm3_binlib.h"
42 static void badcode(lua_State
*L
, int c
)
44 char s
[]="bad code `?'";
49 static int doendian(int c
)
53 if (c
==OP_LITTLEENDIAN
) return !e
;
54 if (c
==OP_BIGENDIAN
) return e
;
55 if (c
==OP_NATIVE
) return 0;
59 static void doswap(int swap
, void *p
, size_t n
)
65 for (i
=0, j
=n
-1, n
=n
/2; n
--; i
++, j
--)
67 char t
=a
[i
]; a
[i
]=a
[j
]; a
[j
]=t
;
72 #define UNPACKNUMBER(OP,T) \
77 if (i+m>len) { done = 1; break;} \
81 lua_pushnumber(L,(lua_Number)a); \
86 #define UNPACKSTRING(OP,T) \
91 if (i+m>len) { done = 1; break; } \
94 if (i+m+l>len) { done = 1; break;} \
96 lua_pushlstring(L,s+i,l); \
102 #define HEXDIGITS(DIG) \
103 "0123456789ABCDEF"[DIG]
105 static int l_unpack(lua_State
*L
) /** unpack(f,s, [init]) */
108 const char *s
=luaL_checklstring(L
,2,&len
); /* switched s and f */
109 const char *f
=luaL_checkstring(L
,1);
110 int i_read
= luaL_optinteger(L
,3,1)-1;
111 // int i_read = luaL_optint(L,3,1)-1;
122 while (*f
&& done
== 0)
126 if (isdigit((int) (unsigned char) *f
))
129 while (isdigit((int) (unsigned char) *f
)) N
=10*N
+(*f
++)-'0';
130 if (N
==0 && c
==OP_STRING
) { lua_pushliteral(L
,""); ++n
; }
132 while (N
-- && done
== 0) switch (c
)
134 case OP_LITTLEENDIAN
:
145 if (i
+N
>len
) {done
= 1; break; }
146 lua_pushlstring(L
,s
+i
,N
);
155 if (i
>=len
) {done
= 1; break; }
157 lua_pushlstring(L
,s
+i
,l
);
163 UNPACKSTRING(OP_BSTRING
, uint8_t)
164 UNPACKSTRING(OP_WSTRING
, uint16_t)
165 UNPACKSTRING(OP_SSTRING
, uint32_t)
166 UNPACKNUMBER(OP_NUMBER
, lua_Number
)
167 UNPACKNUMBER(OP_DOUBLE
, double)
168 UNPACKNUMBER(OP_FLOAT
, float)
169 UNPACKNUMBER(OP_CHAR
, int8_t)
170 UNPACKNUMBER(OP_BYTE
, uint8_t)
171 UNPACKNUMBER(OP_SHORT
, int16_t)
172 UNPACKNUMBER(OP_USHORT
, uint16_t)
173 UNPACKNUMBER(OP_INT
, int32_t)
174 UNPACKNUMBER(OP_UINT
, uint32_t)
175 UNPACKNUMBER(OP_LONG
, int64_t)
176 UNPACKNUMBER(OP_ULONG
, uint64_t)
182 luaL_buffinit(L
,&buf
);
184 if (i
+N
> len
) {done
= 1; break;}
185 for (unsigned int ii
= i
; ii
< i
+N
; ii
++) {
188 hdigit
= HEXDIGITS(val
);
189 luaL_addlstring(&buf
, &hdigit
, 1);
192 hdigit
= HEXDIGITS(val
);
193 luaL_addlstring(&buf
, &hdigit
, 1);
195 luaL_pushresult(&buf
);
209 lua_pushnumber(L
,i
+1);
214 #define PACKNUMBER(OP,T) \
217 T a=(T)luaL_checknumber(L,i++); \
218 doswap(swap,&a,sizeof(a)); \
219 luaL_addlstring(&b,(char*)&a,sizeof(a)); \
223 #define PACKSTRING(OP,T) \
227 const char *a=luaL_checklstring(L,i++,&l); \
229 doswap(swap,&ll,sizeof(ll)); \
230 luaL_addlstring(&b,(char*)&ll,sizeof(ll)); \
231 luaL_addlstring(&b,a,l); \
235 static int l_pack(lua_State
*L
) /** pack(f,...) */
238 const char *f
=luaL_checkstring(L
,1);
246 if (isdigit((int) (unsigned char) *f
))
249 while (isdigit((int) (unsigned char) *f
)) N
=10*N
+(*f
++)-'0';
251 while (N
--) switch (c
)
253 case OP_LITTLEENDIAN
:
265 const char *a
=luaL_checklstring(L
,i
++,&l
);
266 luaL_addlstring(&b
,a
,l
+(c
==OP_ZSTRING
));
269 PACKSTRING(OP_BSTRING
, uint8_t)
270 PACKSTRING(OP_WSTRING
, uint16_t)
271 PACKSTRING(OP_SSTRING
, uint32_t)
272 PACKNUMBER(OP_NUMBER
, lua_Number
)
273 PACKNUMBER(OP_DOUBLE
, double)
274 PACKNUMBER(OP_FLOAT
, float)
275 PACKNUMBER(OP_CHAR
, int8_t)
276 PACKNUMBER(OP_BYTE
, uint8_t)
277 PACKNUMBER(OP_SHORT
, int16_t)
278 PACKNUMBER(OP_USHORT
, uint16_t)
279 PACKNUMBER(OP_INT
, int32_t)
280 PACKNUMBER(OP_UINT
, uint32_t)
281 PACKNUMBER(OP_LONG
, int64_t)
282 PACKNUMBER(OP_ULONG
, uint64_t)
284 { // doing digit parsing the lpack way
285 unsigned char sbyte
= 0;
289 const char *a
= luaL_checklstring(L
, i
++, &l
);
290 for (ii
= 0; ii
< l
; ii
++) {
291 if (isxdigit((int) (unsigned char) a
[ii
])) {
292 if (isdigit((int) (unsigned char) a
[ii
])) {
293 sbyte
+= a
[ii
] - '0';
295 } else if (a
[ii
] >= 'A' && a
[ii
] <= 'F') {
296 sbyte
+= a
[ii
] - 'A' + 10;
298 } else if (a
[ii
] >= 'a' && a
[ii
] <= 'f') {
299 sbyte
+= a
[ii
] - 'a' + 10;
304 } else if (odd
== 2) {
305 luaL_addlstring(&b
, (char *) &sbyte
, 1);
309 } else if (isspace((unsigned char)a
[ii
])) {
312 /* err ... ignore too*/
316 luaL_addlstring(&b
, (char *) &sbyte
, 1);
331 static const luaL_Reg binlib
[] =
334 {"unpack", l_unpack
},
338 LUALIB_API
int luaopen_binlib (lua_State
*L
) {
339 luaL_newlib(L
, binlib
);
345 int set_bin_library (lua_State
*L
) {
347 luaL_requiref(L
, "bin", luaopen_binlib
, 1);