| 291 | |
| 292 | |
| 293 | static int b_unpack (lua_State *L) { |
| 294 | Header h; |
| 295 | const char *fmt = luaL_checkstring(L, 1); |
| 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"); |
| 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); |
| 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, |
| 309 | 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); |
| 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); n--; |
| 343 | luaL_argcheck(L, size <= ld && pos <= ld - size, |
| 344 | 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); |
nothing calls this directly
no test coverage detected