File: | deps/lua/src/lua_struct.c |
Warning: | line 285, column 48 The result of the left shift is undefined because the right operand is negative |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* | |||
2 | ** {====================================================== | |||
3 | ** Library for packing/unpacking structures. | |||
4 | ** $Id: struct.c,v 1.7 2018/05/11 22:04:31 roberto Exp $ | |||
5 | ** See Copyright Notice at the end of this file | |||
6 | ** ======================================================= | |||
7 | */ | |||
8 | /* | |||
9 | ** Valid formats: | |||
10 | ** > - big endian | |||
11 | ** < - little endian | |||
12 | ** ![num] - alignment | |||
13 | ** x - pading | |||
14 | ** b/B - signed/unsigned byte | |||
15 | ** h/H - signed/unsigned short | |||
16 | ** l/L - signed/unsigned long | |||
17 | ** T - size_t | |||
18 | ** i/In - signed/unsigned integer with size 'n' (default is size of int) | |||
19 | ** cn - sequence of 'n' chars (from/to a string); when packing, n==0 means | |||
20 | the whole string; when unpacking, n==0 means use the previous | |||
21 | read number as the string length | |||
22 | ** s - zero-terminated string | |||
23 | ** f - float | |||
24 | ** d - double | |||
25 | ** ' ' - ignored | |||
26 | */ | |||
27 | ||||
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_NUM501 >= 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_INTlong) | |||
49 | #define STRUCT_INTlong long | |||
50 | #endif | |||
51 | ||||
52 | typedef STRUCT_INTlong Inttype; | |||
53 | ||||
54 | /* corresponding unsigned version */ | |||
55 | typedef unsigned STRUCT_INTlong Uinttype; | |||
56 | ||||
57 | ||||
58 | /* maximum size (in bytes) for integral types */ | |||
59 | #define MAXINTSIZE32 32 | |||
60 | ||||
61 | /* is 'x' a power of 2? */ | |||
62 | #define isp2(x)((x) > 0 && ((x) & ((x) - 1)) == 0) ((x) > 0 && ((x) & ((x) - 1)) == 0) | |||
63 | ||||
64 | /* dummy structure to get alignment requirements */ | |||
65 | struct cD { | |||
66 | char c; | |||
67 | double d; | |||
68 | }; | |||
69 | ||||
70 | ||||
71 | #define PADDING(sizeof(struct cD) - sizeof(double)) (sizeof(struct cD) - sizeof(double)) | |||
72 | #define MAXALIGN((sizeof(struct cD) - sizeof(double)) > sizeof(int) ? (sizeof (struct cD) - sizeof(double)) : sizeof(int)) (PADDING(sizeof(struct cD) - sizeof(double)) > sizeof(int) ? PADDING(sizeof(struct cD) - sizeof(double)) : sizeof(int)) | |||
73 | ||||
74 | ||||
75 | /* endian options */ | |||
76 | #define BIG0 0 | |||
77 | #define LITTLE1 1 | |||
78 | ||||
79 | ||||
80 | static union { | |||
81 | int dummy; | |||
82 | char endian; | |||
83 | } const native = {1}; | |||
84 | ||||
85 | ||||
86 | typedef struct Header { | |||
87 | int endian; | |||
88 | int align; | |||
89 | } Header; | |||
90 | ||||
91 | ||||
92 | static int getnum (lua_State *L, const char **fmt, int df) { | |||
93 | if (!isdigit(**fmt)((*__ctype_b_loc ())[(int) ((**fmt))] & (unsigned short int ) _ISdigit)) /* no number? */ | |||
94 | return df; /* return default value */ | |||
95 | else { | |||
96 | int a = 0; | |||
97 | do { | |||
98 | if (a > (INT_MAX2147483647 / 10) || a * 10 > (INT_MAX2147483647 - (**fmt - '0'))) | |||
99 | luaL_error(L, "integral size overflow"); | |||
100 | a = a*10 + *((*fmt)++) - '0'; | |||
101 | } while (isdigit(**fmt)((*__ctype_b_loc ())[(int) ((**fmt))] & (unsigned short int ) _ISdigit)); | |||
102 | return a; | |||
103 | } | |||
104 | } | |||
105 | ||||
106 | ||||
107 | #define defaultoptions(h)((h)->endian = native.endian, (h)->align = 1) ((h)->endian = native.endian, (h)->align = 1) | |||
108 | ||||
109 | ||||
110 | ||||
111 | static size_t optsize (lua_State *L, char opt, const char **fmt) { | |||
112 | switch (opt) { | |||
113 | case 'B': case 'b': return sizeof(char); | |||
114 | case 'H': case 'h': return sizeof(short); | |||
115 | case 'L': case 'l': return sizeof(long); | |||
116 | case 'T': return sizeof(size_t); | |||
117 | case 'f': return sizeof(float); | |||
118 | case 'd': return sizeof(double); | |||
119 | case 'x': return 1; | |||
120 | case 'c': return getnum(L, fmt, 1); | |||
121 | case 'i': case 'I': { | |||
122 | int sz = getnum(L, fmt, sizeof(int)); | |||
123 | if (sz > MAXINTSIZE32) | |||
124 | luaL_error(L, "integral size %d is larger than limit of %d", | |||
125 | sz, MAXINTSIZE32); | |||
126 | return sz; | |||
127 | } | |||
128 | default: return 0; /* other cases do not need alignment */ | |||
129 | } | |||
130 | } | |||
131 | ||||
132 | ||||
133 | /* | |||
134 | ** return number of bytes needed to align an element of size 'size' | |||
135 | ** at current position 'len' | |||
136 | */ | |||
137 | static int gettoalign (size_t len, Header *h, int opt, size_t size) { | |||
138 | if (size == 0 || opt == 'c') return 0; | |||
139 | if (size > (size_t)h->align) | |||
140 | size = h->align; /* respect max. alignment */ | |||
141 | return (size - (len & (size - 1))) & (size - 1); | |||
142 | } | |||
143 | ||||
144 | ||||
145 | /* | |||
146 | ** options to control endianess and alignment | |||
147 | */ | |||
148 | static void controloptions (lua_State *L, int opt, const char **fmt, | |||
149 | Header *h) { | |||
150 | switch (opt) { | |||
151 | case ' ': return; /* ignore white spaces */ | |||
152 | case '>': h->endian = BIG0; return; | |||
153 | case '<': h->endian = LITTLE1; return; | |||
154 | case '!': { | |||
155 | int a = getnum(L, fmt, MAXALIGN((sizeof(struct cD) - sizeof(double)) > sizeof(int) ? (sizeof (struct cD) - sizeof(double)) : sizeof(int))); | |||
156 | if (!isp2(a)((a) > 0 && ((a) & ((a) - 1)) == 0)) | |||
157 | luaL_error(L, "alignment %d is not a power of 2", a); | |||
158 | h->align = a; | |||
159 | return; | |||
160 | } | |||
161 | default: { | |||
162 | const char *msg = lua_pushfstring(L, "invalid format option '%c'", opt); | |||
163 | luaL_argerror(L, 1, msg); | |||
164 | } | |||
165 | } | |||
166 | } | |||
167 | ||||
168 | ||||
169 | static void putinteger (lua_State *L, luaL_Buffer *b, int arg, int endian, | |||
170 | int size) { | |||
171 | lua_Number n = luaL_checknumber(L, arg); | |||
172 | Uinttype value; | |||
173 | char buff[MAXINTSIZE32]; | |||
174 | if (n < 0) | |||
175 | value = (Uinttype)(Inttype)n; | |||
176 | else | |||
177 | value = (Uinttype)n; | |||
178 | if (endian == LITTLE1) { | |||
179 | int i; | |||
180 | for (i = 0; i < size; i++) { | |||
181 | buff[i] = (value & 0xff); | |||
182 | value >>= 8; | |||
183 | } | |||
184 | } | |||
185 | else { | |||
186 | int i; | |||
187 | for (i = size - 1; i >= 0; i--) { | |||
188 | buff[i] = (value & 0xff); | |||
189 | value >>= 8; | |||
190 | } | |||
191 | } | |||
192 | luaL_addlstring(b, buff, size); | |||
193 | } | |||
194 | ||||
195 | ||||
196 | static void correctbytes (char *b, int size, int endian) { | |||
197 | if (endian != native.endian) { | |||
198 | int i = 0; | |||
199 | while (i < --size) { | |||
200 | char temp = b[i]; | |||
201 | b[i++] = b[size]; | |||
202 | b[size] = temp; | |||
203 | } | |||
204 | } | |||
205 | } | |||
206 | ||||
207 | ||||
208 | static int b_pack (lua_State *L) { | |||
209 | luaL_Buffer b; | |||
210 | const char *fmt = luaL_checkstring(L, 1)(luaL_checklstring(L, (1), ((void*)0))); | |||
211 | Header h; | |||
212 | int arg = 2; | |||
213 | size_t totalsize = 0; | |||
214 | defaultoptions(&h)((&h)->endian = native.endian, (&h)->align = 1); | |||
215 | lua_pushnil(L); /* mark to separate arguments from string buffer */ | |||
216 | luaL_buffinit(L, &b); | |||
217 | while (*fmt != '\0') { | |||
218 | int opt = *fmt++; | |||
219 | size_t size = optsize(L, opt, &fmt); | |||
220 | int toalign = gettoalign(totalsize, &h, opt, size); | |||
221 | totalsize += toalign; | |||
222 | while (toalign-- > 0) luaL_addchar(&b, '\0')((void)((&b)->p < ((&b)->buffer+8192) || luaL_prepbuffer (&b)), (*(&b)->p++ = (char)('\0'))); | |||
223 | switch (opt) { | |||
224 | case 'b': case 'B': case 'h': case 'H': | |||
225 | case 'l': case 'L': case 'T': case 'i': case 'I': { /* integer types */ | |||
226 | putinteger(L, &b, arg++, h.endian, size); | |||
227 | break; | |||
228 | } | |||
229 | case 'x': { | |||
230 | luaL_addchar(&b, '\0')((void)((&b)->p < ((&b)->buffer+8192) || luaL_prepbuffer (&b)), (*(&b)->p++ = (char)('\0'))); | |||
231 | break; | |||
232 | } | |||
233 | case 'f': { | |||
234 | float f = (float)luaL_checknumber(L, arg++); | |||
235 | correctbytes((char *)&f, size, h.endian); | |||
236 | luaL_addlstring(&b, (char *)&f, size); | |||
237 | break; | |||
238 | } | |||
239 | case 'd': { | |||
240 | double d = luaL_checknumber(L, arg++); | |||
241 | correctbytes((char *)&d, size, h.endian); | |||
242 | luaL_addlstring(&b, (char *)&d, size); | |||
243 | break; | |||
244 | } | |||
245 | case 'c': case 's': { | |||
246 | size_t l; | |||
247 | const char *s = luaL_checklstring(L, arg++, &l); | |||
248 | if (size == 0) size = l; | |||
249 | luaL_argcheck(L, l >= (size_t)size, arg, "string too short")((void)((l >= (size_t)size) || luaL_argerror(L, (arg), ("string too short" )))); | |||
250 | luaL_addlstring(&b, s, size); | |||
251 | if (opt == 's') { | |||
252 | luaL_addchar(&b, '\0')((void)((&b)->p < ((&b)->buffer+8192) || luaL_prepbuffer (&b)), (*(&b)->p++ = (char)('\0'))); /* add zero at the end */ | |||
253 | size++; | |||
254 | } | |||
255 | break; | |||
256 | } | |||
257 | default: controloptions(L, opt, &fmt, &h); | |||
258 | } | |||
259 | totalsize += size; | |||
260 | } | |||
261 | luaL_pushresult(&b); | |||
262 | return 1; | |||
263 | } | |||
264 | ||||
265 | ||||
266 | static lua_Number getinteger (const char *buff, int endian, | |||
267 | int issigned, int size) { | |||
268 | Uinttype l = 0; | |||
269 | int i; | |||
270 | if (endian
| |||
271 | for (i = 0; i < size; i++) { | |||
272 | l <<= 8; | |||
273 | l |= (Uinttype)(unsigned char)buff[i]; | |||
274 | } | |||
275 | } | |||
276 | else { | |||
277 | for (i = size - 1; i >= 0; i--) { | |||
278 | l <<= 8; | |||
279 | l |= (Uinttype)(unsigned char)buff[i]; | |||
280 | } | |||
281 | } | |||
282 | if (!issigned) | |||
283 | return (lua_Number)l; | |||
284 | else { /* signed format */ | |||
285 | Uinttype mask = (Uinttype)(~((Uinttype)0)) << (size*8 - 1); | |||
| ||||
286 | if (l & mask) /* negative value? */ | |||
287 | l |= mask; /* signal extension */ | |||
288 | return (lua_Number)(Inttype)l; | |||
289 | } | |||
290 | } | |||
291 | ||||
292 | ||||
293 | static int b_unpack (lua_State *L) { | |||
294 | Header h; | |||
295 | const char *fmt = luaL_checkstring(L, 1)(luaL_checklstring(L, (1), ((void*)0))); | |||
296 | size_t ld; | |||
297 | const char *data = luaL_checklstring(L, 2, &ld); | |||
298 | size_t pos = luaL_optinteger(L, 3, 1); | |||
299 | luaL_argcheck(L, pos > 0, 3, "offset must be 1 or greater")((void)((pos > 0) || luaL_argerror(L, (3), ("offset must be 1 or greater" )))); | |||
| ||||
300 | pos--; /* Lua indexes are 1-based, but here we want 0-based for C | |||
301 | * pointer math. */ | |||
302 | int n = 0; /* number of results */ | |||
303 | defaultoptions(&h)((&h)->endian = native.endian, (&h)->align = 1); | |||
304 | while (*fmt) { | |||
305 | int opt = *fmt++; | |||
306 | size_t size = optsize(L, opt, &fmt); | |||
307 | pos += gettoalign(pos, &h, opt, size); | |||
308 | luaL_argcheck(L, size <= ld && pos <= ld - size,((void)((size <= ld && pos <= ld - size) || luaL_argerror (L, (2), ("data string too short")))) | |||
309 | 2, "data string too short")((void)((size <= ld && pos <= ld - size) || luaL_argerror (L, (2), ("data string too short")))); | |||
310 | /* stack space for item + next position */ | |||
311 | luaL_checkstack(L, 2, "too many results"); | |||
312 | switch (opt) { | |||
313 | case 'b': case 'B': case 'h': case 'H': | |||
314 | case 'l': case 'L': case 'T': case 'i': case 'I': { /* integer types */ | |||
315 | int issigned = islower(opt)((*__ctype_b_loc ())[(int) ((opt))] & (unsigned short int ) _ISlower); | |||
316 | lua_Number res = getinteger(data+pos, h.endian, issigned, size); | |||
317 | lua_pushnumber(L, res); n++; | |||
318 | break; | |||
319 | } | |||
320 | case 'x': { | |||
321 | break; | |||
322 | } | |||
323 | case 'f': { | |||
324 | float f; | |||
325 | memcpy(&f, data+pos, size); | |||
326 | correctbytes((char *)&f, sizeof(f), h.endian); | |||
327 | lua_pushnumber(L, f); n++; | |||
328 | break; | |||
329 | } | |||
330 | case 'd': { | |||
331 | double d; | |||
332 | memcpy(&d, data+pos, size); | |||
333 | correctbytes((char *)&d, sizeof(d), h.endian); | |||
334 | lua_pushnumber(L, d); n++; | |||
335 | break; | |||
336 | } | |||
337 | case 'c': { | |||
338 | if (size == 0) { | |||
339 | if (n == 0 || !lua_isnumber(L, -1)) | |||
340 | luaL_error(L, "format 'c0' needs a previous size"); | |||
341 | size = lua_tonumber(L, -1); | |||
342 | lua_pop(L, 1)lua_settop(L, -(1)-1); n--; | |||
343 | luaL_argcheck(L, size <= ld && pos <= ld - size,((void)((size <= ld && pos <= ld - size) || luaL_argerror (L, (2), ("data string too short")))) | |||
344 | 2, "data string too short")((void)((size <= ld && pos <= ld - size) || luaL_argerror (L, (2), ("data string too short")))); | |||
345 | } | |||
346 | lua_pushlstring(L, data+pos, size); n++; | |||
347 | break; | |||
348 | } | |||
349 | case 's': { | |||
350 | const char *e = (const char *)memchr(data+pos, '\0', ld - pos); | |||
351 | if (e == NULL((void*)0)) | |||
352 | luaL_error(L, "unfinished string in data"); | |||
353 | size = (e - (data+pos)) + 1; | |||
354 | lua_pushlstring(L, data+pos, size - 1); n++; | |||
355 | break; | |||
356 | } | |||
357 | default: controloptions(L, opt, &fmt, &h); | |||
358 | } | |||
359 | pos += size; | |||
360 | } | |||
361 | lua_pushinteger(L, pos + 1); /* next position */ | |||
362 | return n + 1; | |||
363 | } | |||
364 | ||||
365 | ||||
366 | static int b_size (lua_State *L) { | |||
367 | Header h; | |||
368 | const char *fmt = luaL_checkstring(L, 1)(luaL_checklstring(L, (1), ((void*)0))); | |||
369 | size_t pos = 0; | |||
370 | defaultoptions(&h)((&h)->endian = native.endian, (&h)->align = 1); | |||
371 | while (*fmt) { | |||
372 | int opt = *fmt++; | |||
373 | size_t size = optsize(L, opt, &fmt); | |||
374 | pos += gettoalign(pos, &h, opt, size); | |||
375 | if (opt == 's') | |||
376 | luaL_argerror(L, 1, "option 's' has no fixed size"); | |||
377 | else if (opt == 'c' && size == 0) | |||
378 | luaL_argerror(L, 1, "option 'c0' has no fixed size"); | |||
379 | if (!isalnum(opt)((*__ctype_b_loc ())[(int) ((opt))] & (unsigned short int ) _ISalnum)) | |||
380 | controloptions(L, opt, &fmt, &h); | |||
381 | pos += size; | |||
382 | } | |||
383 | lua_pushinteger(L, pos); | |||
384 | return 1; | |||
385 | } | |||
386 | ||||
387 | /* }====================================================== */ | |||
388 | ||||
389 | ||||
390 | ||||
391 | static const struct luaL_Reg thislib[] = { | |||
392 | {"pack", b_pack}, | |||
393 | {"unpack", b_unpack}, | |||
394 | {"size", b_size}, | |||
395 | {NULL((void*)0), NULL((void*)0)} | |||
396 | }; | |||
397 | ||||
398 | ||||
399 | LUALIB_APIextern int luaopen_struct (lua_State *L); | |||
400 | ||||
401 | LUALIB_APIextern int luaopen_struct (lua_State *L) { | |||
402 | luaL_register(L, "struct", thislib); | |||
403 | return 1; | |||
404 | } | |||
405 | ||||
406 | ||||
407 | /****************************************************************************** | |||
408 | * Copyright (C) 2010-2018 Lua.org, PUC-Rio. All rights reserved. | |||
409 | * | |||
410 | * Permission is hereby granted, free of charge, to any person obtaining | |||
411 | * a copy of this software and associated documentation files (the | |||
412 | * "Software"), to deal in the Software without restriction, including | |||
413 | * without limitation the rights to use, copy, modify, merge, publish, | |||
414 | * distribute, sublicense, and/or sell copies of the Software, and to | |||
415 | * permit persons to whom the Software is furnished to do so, subject to | |||
416 | * the following conditions: | |||
417 | * | |||
418 | * The above copyright notice and this permission notice shall be | |||
419 | * included in all copies or substantial portions of the Software. | |||
420 | * | |||
421 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||
422 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||
423 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |||
424 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY | |||
425 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | |||
426 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | |||
427 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |||
428 | ******************************************************************************/ | |||
429 |