| 1 | /* |
| 2 | ** $Id: lstrlib.c,v 1.254 2016/12/22 13:08:50 roberto Exp $ |
| 3 | ** Standard library for string operations and pattern-matching |
| 4 | ** Modified by the Kepler Project and the LOVE Development Team to work with |
| 5 | ** Lua 5.1's API |
| 6 | */ |
| 7 | |
| 8 | /********************************************************************* |
| 9 | * The MIT License (MIT) |
| 10 | * |
| 11 | * Copyright (c) 2015 Kepler Project. |
| 12 | * |
| 13 | * Permission is hereby granted, free of charge, to any person obtaining a copy of |
| 14 | * this software and associated documentation files (the "Software"), to deal in |
| 15 | * the Software without restriction, including without limitation the rights to |
| 16 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of |
| 17 | * the Software, and to permit persons to whom the Software is furnished to do so, |
| 18 | * subject to the following conditions: |
| 19 | |
| 20 | * The above copyright notice and this permission notice shall be included in all |
| 21 | * copies or substantial portions of the Software. |
| 22 | |
| 23 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| 24 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS |
| 25 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR |
| 26 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER |
| 27 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
| 28 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| 29 | *********************************************************************/ |
| 30 | |
| 31 | /********************************************************************* |
| 32 | * This file contains parts of Lua 5.2's and Lua 5.3's source code: |
| 33 | * |
| 34 | * Copyright (C) 1994-2014 Lua.org, PUC-Rio. |
| 35 | * |
| 36 | * Permission is hereby granted, free of charge, to any person obtaining |
| 37 | * a copy of this software and associated documentation files (the |
| 38 | * "Software"), to deal in the Software without restriction, including |
| 39 | * without limitation the rights to use, copy, modify, merge, publish, |
| 40 | * distribute, sublicense, and/or sell copies of the Software, and to |
| 41 | * permit persons to whom the Software is furnished to do so, subject to |
| 42 | * the following conditions: |
| 43 | * |
| 44 | * The above copyright notice and this permission notice shall be |
| 45 | * included in all copies or substantial portions of the Software. |
| 46 | * |
| 47 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
| 48 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
| 49 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. |
| 50 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY |
| 51 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, |
| 52 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE |
| 53 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| 54 | *********************************************************************/ |
| 55 | |
| 56 | #include "lprefix.h" |
| 57 | |
| 58 | |
| 59 | #include <ctype.h> |
| 60 | #include <float.h> |
| 61 | #include <limits.h> |
| 62 | #include <stddef.h> |
| 63 | #include <stdlib.h> |
| 64 | #include <string.h> |
| 65 | |
| 66 | #include "lua.h" |
| 67 | |
| 68 | #include "lauxlib.h" |
| 69 | #include "lualib.h" |
| 70 | #include "lstrlib.h" |
| 71 | |
| 72 | #if LUA_VERSION_NUM == 501 |
| 73 | typedef size_t lua_Unsigned; |
| 74 | #endif |
| 75 | |
| 76 | #if LUA_VERSION_NUM >= 504 |
| 77 | # define LUAL_BUFFER53_BUFFER(B) (B)->b.b |
| 78 | #elif LUA_VERSION_NUM == 501 |
| 79 | # define LUAL_BUFFER53_BUFFER(B) (B)->b.buffer |
| 80 | #else |
| 81 | # define LUAL_BUFFER53_BUFFER(B) (B)->b.initb |
| 82 | #endif |
| 83 | |
| 84 | static void luaL_buffinit_53 (lua_State *L, luaL_Buffer_53 *B) { |
| 85 | #if LUA_VERSION_NUM == 501 |
| 86 | /* make it crash if used via pointer to a 5.1-style luaL_Buffer */ |
| 87 | B->b.p = NULL; |
| 88 | B->b.L = NULL; |
| 89 | B->b.lvl = 0; |
| 90 | /* reuse the buffer from the 5.1-style luaL_Buffer though! */ |
| 91 | B->ptr = B->b.buffer; |
| 92 | B->capacity = LUAL_BUFFERSIZE; |
| 93 | B->nelems = 0; |
| 94 | B->L2 = L; |
| 95 | #else |
| 96 | return luaL_buffinit(L, (luaL_Buffer*) B); |
| 97 | #endif |
| 98 | } |
| 99 | |
| 100 | |
| 101 | static char *luaL_prepbuffsize_53 (luaL_Buffer_53 *B, size_t s) { |
| 102 | #if LUA_VERSION_NUM == 501 |
| 103 | if (B->capacity - B->nelems < s) { /* needs to grow */ |
| 104 | char* newptr = NULL; |
| 105 | size_t newcap = B->capacity * 2; |
| 106 | if (newcap - B->nelems < s) |
| 107 | newcap = B->nelems + s; |
| 108 | if (newcap < B->capacity) /* overflow */ |
| 109 | luaL_error(B->L2, "buffer too large" ); |
| 110 | newptr = (char*)lua_newuserdata(B->L2, newcap); |
| 111 | memcpy(newptr, B->ptr, B->nelems); |
| 112 | if (B->ptr != B->b.buffer) |
| 113 | lua_replace(B->L2, -2); /* remove old buffer */ |
| 114 | B->ptr = newptr; |
| 115 | B->capacity = newcap; |
| 116 | } |
| 117 | return B->ptr+B->nelems; |
| 118 | #else |
| 119 | return luaL_prepbuffsize((luaL_Buffer*) B, s); |
| 120 | #endif |
| 121 | } |
| 122 | |
| 123 | |
| 124 | #define luaL_addsize_53(B, s) \ |
| 125 | ((B)->nelems += (s)) |
| 126 | |
| 127 | #define luaL_addchar_53(B, c) \ |
| 128 | ((void)((B)->nelems < (B)->capacity || luaL_prepbuffsize_53((B), 1)), \ |
| 129 | ((B)->ptr[(B)->nelems++] = (c))) |
| 130 | |
| 131 | |
| 132 | static void luaL_addlstring_53 (luaL_Buffer_53 *B, const char *s, size_t l) { |
| 133 | memcpy(luaL_prepbuffsize_53(B, l), s, l); |
| 134 | luaL_addsize_53(B, l); |
| 135 | } |
| 136 | |
| 137 | |
| 138 | void lua53_pushresult (luaL_Buffer_53 *B) { |
| 139 | lua_pushlstring(B->L2, B->ptr, B->nelems); |
| 140 | if (B->ptr != LUAL_BUFFER53_BUFFER(B)) |
| 141 | lua_replace(B->L2, -2); /* remove userdata buffer */ |
| 142 | } |
| 143 | |
| 144 | void lua53_cleanupbuffer (luaL_Buffer_53 *B) { |
| 145 | if (B->ptr != LUAL_BUFFER53_BUFFER(B)) |
| 146 | lua_replace(B->L2, -1); /* remove userdata buffer */ |
| 147 | } |
| 148 | |
| 149 | /* |
| 150 | ** Some sizes are better limited to fit in 'int', but must also fit in |
| 151 | ** 'size_t'. (We assume that 'lua_Integer' cannot be smaller than 'int'.) |
| 152 | */ |
| 153 | #define MAX_SIZET ((size_t)(~(size_t)0)) |
| 154 | |
| 155 | #define MAXSIZE \ |
| 156 | (sizeof(size_t) < sizeof(int) ? MAX_SIZET : (size_t)(INT_MAX)) |
| 157 | |
| 158 | |
| 159 | /* translate a relative string position: negative means back from end */ |
| 160 | static lua_Integer posrelat (lua_Integer pos, size_t len) { |
| 161 | if (pos >= 0) return pos; |
| 162 | else if (0u - (size_t)pos > len) return 0; |
| 163 | else return (lua_Integer)len + pos + 1; |
| 164 | } |
| 165 | |
| 166 | |
| 167 | /* |
| 168 | ** {====================================================== |
| 169 | ** PACK/UNPACK |
| 170 | ** ======================================================= |
| 171 | */ |
| 172 | |
| 173 | |
| 174 | /* value used for padding */ |
| 175 | #if !defined(LUAL_PACKPADBYTE) |
| 176 | #define LUAL_PACKPADBYTE 0x00 |
| 177 | #endif |
| 178 | |
| 179 | /* maximum size for the binary representation of an integer */ |
| 180 | #define MAXINTSIZE 16 |
| 181 | |
| 182 | /* number of bits in a character */ |
| 183 | #define NB CHAR_BIT |
| 184 | |
| 185 | /* mask for one character (NB 1's) */ |
| 186 | #define MC ((1 << NB) - 1) |
| 187 | |
| 188 | /* size of a lua_Integer */ |
| 189 | #define SZINT ((int)sizeof(lua_Integer)) |
| 190 | |
| 191 | |
| 192 | /* dummy union to get native endianness */ |
| 193 | static const union { |
| 194 | int dummy; |
| 195 | char little; /* true iff machine is little endian */ |
| 196 | } nativeendian = {1}; |
| 197 | |
| 198 | |
| 199 | /* dummy structure to get native alignment requirements */ |
| 200 | struct cD { |
| 201 | char c; |
| 202 | union { double d; void *p; lua_Integer i; lua_Number n; } u; |
| 203 | }; |
| 204 | |
| 205 | #define MAXALIGN (offsetof(struct cD, u)) |
| 206 | |
| 207 | |
| 208 | /* |
| 209 | ** Union for serializing floats |
| 210 | */ |
| 211 | typedef union Ftypes { |
| 212 | float f; |
| 213 | double d; |
| 214 | lua_Number n; |
| 215 | char buff[5 * sizeof(lua_Number)]; /* enough for any float type */ |
| 216 | } Ftypes; |
| 217 | |
| 218 | |
| 219 | /* |
| 220 | ** information to pack/unpack stuff |
| 221 | */ |
| 222 | typedef struct { |
| 223 | lua_State *; |
| 224 | int ; |
| 225 | int ; |
| 226 | } ; |
| 227 | |
| 228 | |
| 229 | /* |
| 230 | ** options for pack/unpack |
| 231 | */ |
| 232 | typedef enum KOption { |
| 233 | Kint, /* signed integers */ |
| 234 | Kuint, /* unsigned integers */ |
| 235 | Kfloat, /* floating-point numbers */ |
| 236 | Kchar, /* fixed-length strings */ |
| 237 | Kstring, /* strings with prefixed length */ |
| 238 | Kzstr, /* zero-terminated strings */ |
| 239 | Kpadding, /* padding */ |
| 240 | Kpaddalign, /* padding for alignment */ |
| 241 | Knop /* no-op (configuration or spaces) */ |
| 242 | } KOption; |
| 243 | |
| 244 | |
| 245 | /* |
| 246 | ** Read an integer numeral from string 'fmt' or return 'df' if |
| 247 | ** there is no numeral |
| 248 | */ |
| 249 | static int digit (int c) { return '0' <= c && c <= '9'; } |
| 250 | |
| 251 | static int getnum (const char **fmt, int df) { |
| 252 | if (!digit(**fmt)) /* no number? */ |
| 253 | return df; /* return default value */ |
| 254 | else { |
| 255 | int a = 0; |
| 256 | do { |
| 257 | a = a*10 + (*((*fmt)++) - '0'); |
| 258 | } while (digit(**fmt) && a <= ((int)MAXSIZE - 9)/10); |
| 259 | return a; |
| 260 | } |
| 261 | } |
| 262 | |
| 263 | |
| 264 | /* |
| 265 | ** Read an integer numeral and raises an error if it is larger |
| 266 | ** than the maximum size for integers. |
| 267 | */ |
| 268 | static int getnumlimit (Header *h, const char **fmt, int df) { |
| 269 | int sz = getnum(fmt, df); |
| 270 | if (sz > MAXINTSIZE || sz <= 0) |
| 271 | luaL_error(h->L, "integral size (%d) out of limits [1,%d]" , |
| 272 | sz, MAXINTSIZE); |
| 273 | return sz; |
| 274 | } |
| 275 | |
| 276 | |
| 277 | /* |
| 278 | ** Initialize Header |
| 279 | */ |
| 280 | static void (lua_State *L, Header *h) { |
| 281 | h->L = L; |
| 282 | h->islittle = nativeendian.little; |
| 283 | h->maxalign = 1; |
| 284 | } |
| 285 | |
| 286 | |
| 287 | /* |
| 288 | ** Read and classify next option. 'size' is filled with option's size. |
| 289 | */ |
| 290 | static KOption getoption (Header *h, const char **fmt, int *size) { |
| 291 | int opt = *((*fmt)++); |
| 292 | *size = 0; /* default */ |
| 293 | switch (opt) { |
| 294 | case 'b': *size = sizeof(char); return Kint; |
| 295 | case 'B': *size = sizeof(char); return Kuint; |
| 296 | case 'h': *size = sizeof(short); return Kint; |
| 297 | case 'H': *size = sizeof(short); return Kuint; |
| 298 | case 'l': *size = sizeof(long); return Kint; |
| 299 | case 'L': *size = sizeof(long); return Kuint; |
| 300 | case 'j': *size = sizeof(lua_Integer); return Kint; |
| 301 | case 'J': *size = sizeof(lua_Integer); return Kuint; |
| 302 | case 'T': *size = sizeof(size_t); return Kuint; |
| 303 | case 'f': *size = sizeof(float); return Kfloat; |
| 304 | case 'd': *size = sizeof(double); return Kfloat; |
| 305 | case 'n': *size = sizeof(lua_Number); return Kfloat; |
| 306 | case 'i': *size = getnumlimit(h, fmt, sizeof(int)); return Kint; |
| 307 | case 'I': *size = getnumlimit(h, fmt, sizeof(int)); return Kuint; |
| 308 | case 's': *size = getnumlimit(h, fmt, sizeof(size_t)); return Kstring; |
| 309 | case 'c': |
| 310 | *size = getnum(fmt, -1); |
| 311 | if (*size == -1) |
| 312 | luaL_error(h->L, "missing size for format option 'c'" ); |
| 313 | return Kchar; |
| 314 | case 'z': return Kzstr; |
| 315 | case 'x': *size = 1; return Kpadding; |
| 316 | case 'X': return Kpaddalign; |
| 317 | case ' ': break; |
| 318 | case '<': h->islittle = 1; break; |
| 319 | case '>': h->islittle = 0; break; |
| 320 | case '=': h->islittle = nativeendian.little; break; |
| 321 | case '!': h->maxalign = getnumlimit(h, fmt, MAXALIGN); break; |
| 322 | default: luaL_error(h->L, "invalid format option '%c'" , opt); |
| 323 | } |
| 324 | return Knop; |
| 325 | } |
| 326 | |
| 327 | |
| 328 | /* |
| 329 | ** Read, classify, and fill other details about the next option. |
| 330 | ** 'psize' is filled with option's size, 'notoalign' with its |
| 331 | ** alignment requirements. |
| 332 | ** Local variable 'size' gets the size to be aligned. (Kpadal option |
| 333 | ** always gets its full alignment, other options are limited by |
| 334 | ** the maximum alignment ('maxalign'). Kchar option needs no alignment |
| 335 | ** despite its size. |
| 336 | */ |
| 337 | static KOption getdetails (Header *h, size_t totalsize, |
| 338 | const char **fmt, int *psize, int *ntoalign) { |
| 339 | KOption opt = getoption(h, fmt, psize); |
| 340 | int align = *psize; /* usually, alignment follows size */ |
| 341 | if (opt == Kpaddalign) { /* 'X' gets alignment from following option */ |
| 342 | if (**fmt == '\0' || getoption(h, fmt, &align) == Kchar || align == 0) |
| 343 | luaL_argerror(h->L, 1, "invalid next option for option 'X'" ); |
| 344 | } |
| 345 | if (align <= 1 || opt == Kchar) /* need no alignment? */ |
| 346 | *ntoalign = 0; |
| 347 | else { |
| 348 | if (align > h->maxalign) /* enforce maximum alignment */ |
| 349 | align = h->maxalign; |
| 350 | if ((align & (align - 1)) != 0) /* is 'align' not a power of 2? */ |
| 351 | luaL_argerror(h->L, 1, "format asks for alignment not power of 2" ); |
| 352 | *ntoalign = (align - (int)(totalsize & (align - 1))) & (align - 1); |
| 353 | } |
| 354 | return opt; |
| 355 | } |
| 356 | |
| 357 | |
| 358 | /* |
| 359 | ** Pack integer 'n' with 'size' bytes and 'islittle' endianness. |
| 360 | ** The final 'if' handles the case when 'size' is larger than |
| 361 | ** the size of a Lua integer, correcting the extra sign-extension |
| 362 | ** bytes if necessary (by default they would be zeros). |
| 363 | */ |
| 364 | static void packint (luaL_Buffer_53 *b, lua_Unsigned n, |
| 365 | int islittle, int size, int neg) { |
| 366 | char *buff = luaL_prepbuffsize_53(b, size); |
| 367 | int i; |
| 368 | buff[islittle ? 0 : size - 1] = (char)(n & MC); /* first byte */ |
| 369 | for (i = 1; i < size; i++) { |
| 370 | n >>= NB; |
| 371 | buff[islittle ? i : size - 1 - i] = (char)(n & MC); |
| 372 | } |
| 373 | if (neg && size > SZINT) { /* negative number need sign extension? */ |
| 374 | for (i = SZINT; i < size; i++) /* correct extra bytes */ |
| 375 | buff[islittle ? i : size - 1 - i] = (char)MC; |
| 376 | } |
| 377 | luaL_addsize_53(b, size); /* add result to buffer */ |
| 378 | } |
| 379 | |
| 380 | |
| 381 | /* |
| 382 | ** Copy 'size' bytes from 'src' to 'dest', correcting endianness if |
| 383 | ** given 'islittle' is different from native endianness. |
| 384 | */ |
| 385 | static void copywithendian (volatile char *dest, volatile const char *src, |
| 386 | int size, int islittle) { |
| 387 | if (islittle == nativeendian.little) { |
| 388 | while (size-- != 0) |
| 389 | *(dest++) = *(src++); |
| 390 | } |
| 391 | else { |
| 392 | dest += size - 1; |
| 393 | while (size-- != 0) |
| 394 | *(dest--) = *(src++); |
| 395 | } |
| 396 | } |
| 397 | |
| 398 | |
| 399 | void lua53_str_pack (lua_State *L, const char *fmt, int startidx, luaL_Buffer_53 *b) { |
| 400 | Header h; |
| 401 | int arg = startidx - 1; /* current argument to pack */ |
| 402 | size_t totalsize = 0; /* accumulate total size of result */ |
| 403 | initheader(L, &h); |
| 404 | lua_pushnil(L); /* mark to separate arguments from string buffer */ |
| 405 | luaL_buffinit_53(L, b); |
| 406 | while (*fmt != '\0') { |
| 407 | int size, ntoalign; |
| 408 | KOption opt = getdetails(&h, totalsize, &fmt, &size, &ntoalign); |
| 409 | totalsize += ntoalign + size; |
| 410 | while (ntoalign-- > 0) |
| 411 | luaL_addchar_53(b, LUAL_PACKPADBYTE); /* fill alignment */ |
| 412 | arg++; |
| 413 | switch (opt) { |
| 414 | case Kint: { /* signed integers */ |
| 415 | lua_Integer n = luaL_checkinteger(L, arg); |
| 416 | if (size < SZINT) { /* need overflow check? */ |
| 417 | lua_Integer lim = (lua_Integer)1 << ((size * NB) - 1); |
| 418 | luaL_argcheck(L, -lim <= n && n < lim, arg, "integer overflow" ); |
| 419 | } |
| 420 | packint(b, (lua_Unsigned)n, h.islittle, size, (n < 0)); |
| 421 | break; |
| 422 | } |
| 423 | case Kuint: { /* unsigned integers */ |
| 424 | lua_Integer n = luaL_checkinteger(L, arg); |
| 425 | if (size < SZINT) /* need overflow check? */ |
| 426 | luaL_argcheck(L, (lua_Unsigned)n < ((lua_Unsigned)1 << (size * NB)), |
| 427 | arg, "unsigned overflow" ); |
| 428 | packint(b, (lua_Unsigned)n, h.islittle, size, 0); |
| 429 | break; |
| 430 | } |
| 431 | case Kfloat: { /* floating-point options */ |
| 432 | volatile Ftypes u; |
| 433 | char *buff = luaL_prepbuffsize_53(b, size); |
| 434 | lua_Number n = luaL_checknumber(L, arg); /* get argument */ |
| 435 | if (size == sizeof(u.f)) u.f = (float)n; /* copy it into 'u' */ |
| 436 | else if (size == sizeof(u.d)) u.d = (double)n; |
| 437 | else u.n = n; |
| 438 | /* move 'u' to final result, correcting endianness if needed */ |
| 439 | copywithendian(buff, u.buff, size, h.islittle); |
| 440 | luaL_addsize_53(b, size); |
| 441 | break; |
| 442 | } |
| 443 | case Kchar: { /* fixed-size string */ |
| 444 | size_t len; |
| 445 | const char *s = luaL_checklstring(L, arg, &len); |
| 446 | luaL_argcheck(L, len <= (size_t)size, arg, |
| 447 | "string longer than given size" ); |
| 448 | luaL_addlstring_53(b, s, len); /* add string */ |
| 449 | while (len++ < (size_t)size) /* pad extra space */ |
| 450 | luaL_addchar_53(b, LUAL_PACKPADBYTE); |
| 451 | break; |
| 452 | } |
| 453 | case Kstring: { /* strings with length count */ |
| 454 | size_t len; |
| 455 | const char *s = luaL_checklstring(L, arg, &len); |
| 456 | luaL_argcheck(L, size >= (int)sizeof(size_t) || |
| 457 | len < ((size_t)1 << (size * NB)), |
| 458 | arg, "string length does not fit in given size" ); |
| 459 | packint(b, (lua_Unsigned)len, h.islittle, size, 0); /* pack length */ |
| 460 | luaL_addlstring_53(b, s, len); |
| 461 | totalsize += len; |
| 462 | break; |
| 463 | } |
| 464 | case Kzstr: { /* zero-terminated string */ |
| 465 | size_t len; |
| 466 | const char *s = luaL_checklstring(L, arg, &len); |
| 467 | luaL_argcheck(L, strlen(s) == len, arg, "string contains zeros" ); |
| 468 | luaL_addlstring_53(b, s, len); |
| 469 | luaL_addchar_53(b, '\0'); /* add zero at the end */ |
| 470 | totalsize += len + 1; |
| 471 | break; |
| 472 | } |
| 473 | case Kpadding: luaL_addchar_53(b, LUAL_PACKPADBYTE); /* FALLTHROUGH */ |
| 474 | case Kpaddalign: case Knop: |
| 475 | arg--; /* undo increment */ |
| 476 | break; |
| 477 | } |
| 478 | } |
| 479 | } |
| 480 | |
| 481 | |
| 482 | int lua53_str_packsize (lua_State *L) { |
| 483 | Header h; |
| 484 | const char *fmt = luaL_checkstring(L, 1); /* format string */ |
| 485 | size_t totalsize = 0; /* accumulate total size of result */ |
| 486 | initheader(L, &h); |
| 487 | while (*fmt != '\0') { |
| 488 | int size, ntoalign; |
| 489 | KOption opt = getdetails(&h, totalsize, &fmt, &size, &ntoalign); |
| 490 | size += ntoalign; /* total space used by option */ |
| 491 | luaL_argcheck(L, totalsize <= MAXSIZE - size, 1, |
| 492 | "format result too large" ); |
| 493 | totalsize += size; |
| 494 | switch (opt) { |
| 495 | case Kstring: /* strings with length count */ |
| 496 | case Kzstr: /* zero-terminated string */ |
| 497 | luaL_argerror(L, 1, "variable-length format" ); |
| 498 | /* call never return, but to avoid warnings: *//* FALLTHROUGH */ |
| 499 | default: break; |
| 500 | } |
| 501 | } |
| 502 | lua_pushinteger(L, (lua_Integer)totalsize); |
| 503 | return 1; |
| 504 | } |
| 505 | |
| 506 | |
| 507 | /* |
| 508 | ** Unpack an integer with 'size' bytes and 'islittle' endianness. |
| 509 | ** If size is smaller than the size of a Lua integer and integer |
| 510 | ** is signed, must do sign extension (propagating the sign to the |
| 511 | ** higher bits); if size is larger than the size of a Lua integer, |
| 512 | ** it must check the unread bytes to see whether they do not cause an |
| 513 | ** overflow. |
| 514 | */ |
| 515 | static lua_Integer unpackint (lua_State *L, const char *str, |
| 516 | int islittle, int size, int issigned) { |
| 517 | lua_Unsigned res = 0; |
| 518 | int i; |
| 519 | int limit = (size <= SZINT) ? size : SZINT; |
| 520 | for (i = limit - 1; i >= 0; i--) { |
| 521 | res <<= NB; |
| 522 | res |= (lua_Unsigned)(unsigned char)str[islittle ? i : size - 1 - i]; |
| 523 | } |
| 524 | if (size < SZINT) { /* real size smaller than lua_Integer? */ |
| 525 | if (issigned) { /* needs sign extension? */ |
| 526 | lua_Unsigned mask = (lua_Unsigned)1 << (size*NB - 1); |
| 527 | res = ((res ^ mask) - mask); /* do sign extension */ |
| 528 | } |
| 529 | } |
| 530 | else if (size > SZINT) { /* must check unread bytes */ |
| 531 | int mask = (!issigned || (lua_Integer)res >= 0) ? 0 : MC; |
| 532 | for (i = limit; i < size; i++) { |
| 533 | if ((unsigned char)str[islittle ? i : size - 1 - i] != mask) |
| 534 | luaL_error(L, "%d-byte integer does not fit into Lua Integer" , size); |
| 535 | } |
| 536 | } |
| 537 | return (lua_Integer)res; |
| 538 | } |
| 539 | |
| 540 | |
| 541 | int lua53_str_unpack (lua_State *L, const char *fmt, const char *data, size_t ld, int dataidx, int posidx) { |
| 542 | Header h; |
| 543 | size_t pos = (size_t)posrelat(luaL_optinteger(L, posidx, 1), ld) - 1; |
| 544 | int n = 0; /* number of results */ |
| 545 | luaL_argcheck(L, pos <= ld, posidx, "initial position out of string" ); |
| 546 | initheader(L, &h); |
| 547 | while (*fmt != '\0') { |
| 548 | int size, ntoalign; |
| 549 | KOption opt = getdetails(&h, pos, &fmt, &size, &ntoalign); |
| 550 | if ((size_t)ntoalign + size > ~pos || pos + ntoalign + size > ld) |
| 551 | luaL_argerror(L, dataidx, "data string too short" ); |
| 552 | pos += ntoalign; /* skip alignment */ |
| 553 | /* stack space for item + next position */ |
| 554 | luaL_checkstack(L, dataidx, "too many results" ); |
| 555 | n++; |
| 556 | switch (opt) { |
| 557 | case Kint: |
| 558 | case Kuint: { |
| 559 | lua_Integer res = unpackint(L, data + pos, h.islittle, size, |
| 560 | (opt == Kint)); |
| 561 | lua_pushinteger(L, res); |
| 562 | break; |
| 563 | } |
| 564 | case Kfloat: { |
| 565 | volatile Ftypes u; |
| 566 | lua_Number num; |
| 567 | copywithendian(u.buff, data + pos, size, h.islittle); |
| 568 | if (size == sizeof(u.f)) num = (lua_Number)u.f; |
| 569 | else if (size == sizeof(u.d)) num = (lua_Number)u.d; |
| 570 | else num = u.n; |
| 571 | lua_pushnumber(L, num); |
| 572 | break; |
| 573 | } |
| 574 | case Kchar: { |
| 575 | lua_pushlstring(L, data + pos, size); |
| 576 | break; |
| 577 | } |
| 578 | case Kstring: { |
| 579 | size_t len = (size_t)unpackint(L, data + pos, h.islittle, size, 0); |
| 580 | luaL_argcheck(L, pos + len + size <= ld, dataidx, "data string too short" ); |
| 581 | lua_pushlstring(L, data + pos + size, len); |
| 582 | pos += len; /* skip string */ |
| 583 | break; |
| 584 | } |
| 585 | case Kzstr: { |
| 586 | size_t len = (int)strlen(data + pos); |
| 587 | lua_pushlstring(L, data + pos, len); |
| 588 | pos += len + 1; /* skip string plus final '\0' */ |
| 589 | break; |
| 590 | } |
| 591 | case Kpaddalign: case Kpadding: case Knop: |
| 592 | n--; /* undo increment */ |
| 593 | break; |
| 594 | } |
| 595 | pos += size; |
| 596 | } |
| 597 | lua_pushinteger(L, pos + 1); /* next position */ |
| 598 | return n + 1; |
| 599 | } |
| 600 | |
| 601 | /* }====================================================== */ |
| 602 | |
| 603 | |