1
-
2
- #include <assert.h>
3
- #include <ctype.h>
4
- #include <limits.h>
5
- #include <string.h>
6
-
7
-
8
- #include "lua.h"
9
- #include "lauxlib.h"
10
-
11
-
12
1
/*
13
2
** {======================================================
14
3
** Library for packing/unpacking structures.
15
- ** $Id: struct.c,v 1.2 2008/04/18 20:06:01 roberto Exp $
4
+ ** $Id: struct.c,v 1.4 2012/07/04 18:54:29 roberto Exp $
16
5
** See Copyright Notice at the end of this file
17
6
** =======================================================
18
7
*/
25
14
** b/B - signed/unsigned byte
26
15
** h/H - signed/unsigned short
27
16
** l/L - signed/unsigned long
17
+ ** T - size_t
28
18
** i/In - signed/unsigned integer with size `n' (default is size of int)
29
19
** cn - sequence of `n' chars (from/to a string); when packing, n==0 means
30
20
the whole string; when unpacking, n==0 means use the previous
36
26
*/
37
27
38
28
29
+ #include <assert.h>
30
+ #include <ctype.h>
31
+ #include <limits.h>
32
+ #include <stddef.h>
33
+ #include <string.h>
34
+
35
+
36
+ #include "lua.h"
37
+ #include "lauxlib.h"
38
+
39
+
40
+ #if (LUA_VERSION_NUM >= 502 )
41
+
42
+ #define luaL_register (L ,n ,f ) luaL_newlib(L,f)
43
+
44
+ #endif
45
+
46
+
47
+ /* basic integer type */
48
+ #if !defined(STRUCT_INT )
49
+ #define STRUCT_INT long
50
+ #endif
51
+
52
+ typedef STRUCT_INT Inttype ;
53
+
54
+ /* corresponding unsigned version */
55
+ typedef unsigned STRUCT_INT Uinttype ;
56
+
57
+
58
+ /* maximum size (in bytes) for integral types */
59
+ #define MAXINTSIZE 32
60
+
39
61
/* is 'x' a power of 2? */
40
62
#define isp2 (x ) ((x) > 0 && ((x) & ((x) - 1)) == 0)
41
63
@@ -67,11 +89,11 @@ typedef struct Header {
67
89
} Header ;
68
90
69
91
70
- static size_t getnum (const char * * fmt , size_t df ) {
92
+ static int getnum (const char * * fmt , int df ) {
71
93
if (!isdigit (* * fmt )) /* no number? */
72
94
return df ; /* return default value */
73
95
else {
74
- size_t a = 0 ;
96
+ int a = 0 ;
75
97
do {
76
98
a = a * 10 + * ((* fmt )++ ) - '0' ;
77
99
} while (isdigit (* * fmt ));
@@ -89,33 +111,40 @@ static size_t optsize (lua_State *L, char opt, const char **fmt) {
89
111
case 'B' : case 'b' : return sizeof (char );
90
112
case 'H' : case 'h' : return sizeof (short );
91
113
case 'L' : case 'l' : return sizeof (long );
114
+ case 'T' : return sizeof (size_t );
92
115
case 'f' : return sizeof (float );
93
116
case 'd' : return sizeof (double );
94
117
case 'x' : return 1 ;
95
118
case 'c' : return getnum (fmt , 1 );
96
- case 's' : case ' ' : case '<' : case '>' : case '!' : return 0 ;
97
119
case 'i' : case 'I' : {
98
120
int sz = getnum (fmt , sizeof (int ));
99
- if (!isp2 (sz ))
100
- luaL_error (L , "integral size %d is not a power of 2" , sz );
121
+ if (sz > MAXINTSIZE )
122
+ luaL_error (L , "integral size %d is larger than limit of %d" ,
123
+ sz , MAXINTSIZE );
101
124
return sz ;
102
125
}
103
- default : {
104
- const char * msg = lua_pushfstring (L , "invalid format option [%c]" , opt );
105
- return luaL_argerror (L , 1 , msg );
106
- }
126
+ default : return 0 ; /* other cases do not need alignment */
107
127
}
108
128
}
109
129
110
130
131
+ /*
132
+ ** return number of bytes needed to align an element of size 'size'
133
+ ** at current position 'len'
134
+ */
111
135
static int gettoalign (size_t len , Header * h , int opt , size_t size ) {
112
136
if (size == 0 || opt == 'c' ) return 0 ;
113
- if (size > (size_t )h -> align ) size = h -> align ; /* respect max. alignment */
114
- return (size - (len & (size - 1 ))) & (size - 1 );
137
+ if (size > (size_t )h -> align )
138
+ size = h -> align ; /* respect max. alignment */
139
+ return (size - (len & (size - 1 ))) & (size - 1 );
115
140
}
116
141
117
142
118
- static void commoncases (lua_State * L , int opt , const char * * fmt , Header * h ) {
143
+ /*
144
+ ** options to control endianess and alignment
145
+ */
146
+ static void controloptions (lua_State * L , int opt , const char * * fmt ,
147
+ Header * h ) {
119
148
switch (opt ) {
120
149
case ' ' : return ; /* ignore white spaces */
121
150
case '>' : h -> endian = BIG ; return ;
@@ -127,29 +156,38 @@ static void commoncases (lua_State *L, int opt, const char **fmt, Header *h) {
127
156
h -> align = a ;
128
157
return ;
129
158
}
130
- default : assert (0 );
159
+ default : {
160
+ const char * msg = lua_pushfstring (L , "invalid format option '%c'" , opt );
161
+ luaL_argerror (L , 1 , msg );
162
+ }
131
163
}
132
164
}
133
165
134
166
135
167
static void putinteger (lua_State * L , luaL_Buffer * b , int arg , int endian ,
136
168
int size ) {
137
169
lua_Number n = luaL_checknumber (L , arg );
138
- unsigned long value ;
139
- if (n < (lua_Number )LONG_MAX )
140
- value = (long )n ;
170
+ Uinttype value ;
171
+ char buff [MAXINTSIZE ];
172
+ if (n < 0 )
173
+ value = (Uinttype )(Inttype )n ;
141
174
else
142
- value = (unsigned long )n ;
175
+ value = (Uinttype )n ;
143
176
if (endian == LITTLE ) {
144
177
int i ;
145
- for (i = 0 ; i < size ; i ++ )
146
- luaL_addchar (b , (value >> 8 * i ) & 0xff );
178
+ for (i = 0 ; i < size ; i ++ ) {
179
+ buff [i ] = (value & 0xff );
180
+ value >>= 8 ;
181
+ }
147
182
}
148
183
else {
149
184
int i ;
150
- for (i = size - 1 ; i >= 0 ; i -- )
151
- luaL_addchar (b , (value >> 8 * i ) & 0xff );
185
+ for (i = size - 1 ; i >= 0 ; i -- ) {
186
+ buff [i ] = (value & 0xff );
187
+ value >>= 8 ;
188
+ }
152
189
}
190
+ luaL_addlstring (b , buff , size );
153
191
}
154
192
155
193
@@ -179,15 +217,15 @@ static int b_pack (lua_State *L) {
179
217
size_t size = optsize (L , opt , & fmt );
180
218
int toalign = gettoalign (totalsize , & h , opt , size );
181
219
totalsize += toalign ;
182
- while (toalign -- > 0 ) luaL_putchar (& b , '\0' );
220
+ while (toalign -- > 0 ) luaL_addchar (& b , '\0' );
183
221
switch (opt ) {
184
222
case 'b' : case 'B' : case 'h' : case 'H' :
185
- case 'l' : case 'L' : case 'i' : case 'I' : { /* integer types */
223
+ case 'l' : case 'L' : case 'T' : case ' i' : case 'I' : { /* integer types */
186
224
putinteger (L , & b , arg ++ , h .endian , size );
187
225
break ;
188
226
}
189
227
case 'x' : {
190
- luaL_putchar (& b , '\0' );
228
+ luaL_addchar (& b , '\0' );
191
229
break ;
192
230
}
193
231
case 'f' : {
@@ -209,12 +247,12 @@ static int b_pack (lua_State *L) {
209
247
luaL_argcheck (L , l >= (size_t )size , arg , "string too short" );
210
248
luaL_addlstring (& b , s , size );
211
249
if (opt == 's' ) {
212
- luaL_putchar (& b , '\0' ); /* add zero at the end */
250
+ luaL_addchar (& b , '\0' ); /* add zero at the end */
213
251
size ++ ;
214
252
}
215
253
break ;
216
254
}
217
- default : commoncases (L , opt , & fmt , & h );
255
+ default : controloptions (L , opt , & fmt , & h );
218
256
}
219
257
totalsize += size ;
220
258
}
@@ -225,24 +263,27 @@ static int b_pack (lua_State *L) {
225
263
226
264
static lua_Number getinteger (const char * buff , int endian ,
227
265
int issigned , int size ) {
228
- unsigned long l = 0 ;
266
+ Uinttype l = 0 ;
267
+ int i ;
229
268
if (endian == BIG ) {
230
- int i ;
231
- for (i = 0 ; i < size ; i ++ )
232
- l |= (unsigned long )(unsigned char )buff [size - i - 1 ] << (i * 8 );
269
+ for (i = 0 ; i < size ; i ++ ) {
270
+ l <<= 8 ;
271
+ l |= (Uinttype )(unsigned char )buff [i ];
272
+ }
233
273
}
234
274
else {
235
- int i ;
236
- for (i = 0 ; i < size ; i ++ )
237
- l |= (unsigned long )(unsigned char )buff [i ] << (i * 8 );
275
+ for (i = size - 1 ; i >= 0 ; i -- ) {
276
+ l <<= 8 ;
277
+ l |= (Uinttype )(unsigned char )buff [i ];
278
+ }
238
279
}
239
280
if (!issigned )
240
281
return (lua_Number )l ;
241
282
else { /* signed format */
242
- unsigned long mask = ~( 0UL ) << (size * 8 - 1 );
283
+ Uinttype mask = ( Uinttype )(~(( Uinttype ) 0 ) ) << (size * 8 - 1 );
243
284
if (l & mask ) /* negative value? */
244
285
l |= mask ; /* signal extension */
245
- return (lua_Number )(long )l ;
286
+ return (lua_Number )(Inttype )l ;
246
287
}
247
288
}
248
289
@@ -260,9 +301,10 @@ static int b_unpack (lua_State *L) {
260
301
size_t size = optsize (L , opt , & fmt );
261
302
pos += gettoalign (pos , & h , opt , size );
262
303
luaL_argcheck (L , pos + size <= ld , 2 , "data string too short" );
304
+ luaL_checkstack (L , 1 , "too many results" );
263
305
switch (opt ) {
264
306
case 'b' : case 'B' : case 'h' : case 'H' :
265
- case 'l' : case 'L' : case 'i' : case 'I' : { /* integer types */
307
+ case 'l' : case 'L' : case 'T' : case ' i' : case 'I' : { /* integer types */
266
308
int issigned = islower (opt );
267
309
lua_Number res = getinteger (data + pos , h .endian , issigned , size );
268
310
lua_pushnumber (L , res );
@@ -304,34 +346,58 @@ static int b_unpack (lua_State *L) {
304
346
lua_pushlstring (L , data + pos , size - 1 );
305
347
break ;
306
348
}
307
- default : commoncases (L , opt , & fmt , & h );
349
+ default : controloptions (L , opt , & fmt , & h );
308
350
}
309
351
pos += size ;
310
352
}
311
353
lua_pushinteger (L , pos + 1 );
312
354
return lua_gettop (L ) - 2 ;
313
355
}
314
356
357
+
358
+ static int b_size (lua_State * L ) {
359
+ Header h ;
360
+ const char * fmt = luaL_checkstring (L , 1 );
361
+ size_t pos = 0 ;
362
+ defaultoptions (& h );
363
+ while (* fmt ) {
364
+ int opt = * fmt ++ ;
365
+ size_t size = optsize (L , opt , & fmt );
366
+ pos += gettoalign (pos , & h , opt , size );
367
+ if (opt == 's' )
368
+ luaL_argerror (L , 1 , "option 's' has no fixed size" );
369
+ else if (opt == 'c' && size == 0 )
370
+ luaL_argerror (L , 1 , "option 'c0' has no fixed size" );
371
+ if (!isalnum (opt ))
372
+ controloptions (L , opt , & fmt , & h );
373
+ pos += size ;
374
+ }
375
+ lua_pushinteger (L , pos );
376
+ return 1 ;
377
+ }
378
+
315
379
/* }====================================================== */
316
380
317
381
318
382
319
- static const struct luaL_reg thislib [] = {
383
+ static const struct luaL_Reg thislib [] = {
320
384
{"pack" , b_pack },
321
385
{"unpack" , b_unpack },
386
+ {"size" , b_size },
322
387
{NULL , NULL }
323
388
};
324
389
325
390
391
+ LUALIB_API int luaopen_struct (lua_State * L );
392
+
326
393
LUALIB_API int luaopen_struct (lua_State * L ) {
327
394
luaL_register (L , "struct" , thislib );
328
395
return 1 ;
329
396
}
330
397
331
398
332
-
333
399
/******************************************************************************
334
- * Copyright (C) 2010 Lua.org, PUC-Rio. All rights reserved.
400
+ * Copyright (C) 2010-2012 Lua.org, PUC-Rio. All rights reserved.
335
401
*
336
402
* Permission is hereby granted, free of charge, to any person obtaining
337
403
* a copy of this software and associated documentation files (the
@@ -352,3 +418,4 @@ LUALIB_API int luaopen_struct (lua_State *L) {
352
418
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
353
419
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
354
420
******************************************************************************/
421
+
0 commit comments