| 1328 | |
| 1329 | |
| 1330 | static int str_pack (lua_State *L) { |
| 1331 | luaL_Buffer b; |
| 1332 | Header h; |
| 1333 | const char *fmt = luaL_checkstring(L, 1); /* format string */ |
| 1334 | int arg = 1; /* current argument to pack */ |
| 1335 | size_t totalsize = 0; /* accumulate total size of result */ |
| 1336 | initheader(L, &h); |
| 1337 | lua_pushnil(L); /* mark to separate arguments from string buffer */ |
| 1338 | luaL_buffinit(L, &b); |
| 1339 | while (*fmt != '\0') { |
| 1340 | int size, ntoalign; |
| 1341 | KOption opt = getdetails(&h, totalsize, &fmt, &size, &ntoalign); |
| 1342 | totalsize += ntoalign + size; |
| 1343 | while (ntoalign-- > 0) |
| 1344 | luaL_addchar(&b, LUAL_PACKPADBYTE); /* fill alignment */ |
| 1345 | arg++; |
| 1346 | switch (opt) { |
| 1347 | case Kint: { /* signed integers */ |
| 1348 | lua_Integer n = luaL_checkinteger(L, arg); |
| 1349 | if (size < SZINT) { /* need overflow check? */ |
| 1350 | lua_Integer lim = (lua_Integer)1 << ((size * NB) - 1); |
| 1351 | luaL_argcheck(L, -lim <= n && n < lim, arg, "integer overflow"); |
| 1352 | } |
| 1353 | packint(&b, (lua_Unsigned)n, h.islittle, size, (n < 0)); |
| 1354 | break; |
| 1355 | } |
| 1356 | case Kuint: { /* unsigned integers */ |
| 1357 | lua_Integer n = luaL_checkinteger(L, arg); |
| 1358 | if (size < SZINT) /* need overflow check? */ |
| 1359 | luaL_argcheck(L, (lua_Unsigned)n < ((lua_Unsigned)1 << (size * NB)), |
| 1360 | arg, "unsigned overflow"); |
| 1361 | packint(&b, (lua_Unsigned)n, h.islittle, size, 0); |
| 1362 | break; |
| 1363 | } |
| 1364 | case Kfloat: { /* floating-point options */ |
| 1365 | volatile Ftypes u; |
| 1366 | char *buff = luaL_prepbuffsize(&b, size); |
| 1367 | lua_Number n = luaL_checknumber(L, arg); /* get argument */ |
| 1368 | if (size == sizeof(u.f)) u.f = (float)n; /* copy it into 'u' */ |
| 1369 | else if (size == sizeof(u.d)) u.d = (double)n; |
| 1370 | else u.n = n; |
| 1371 | /* move 'u' to final result, correcting endianness if needed */ |
| 1372 | copywithendian(buff, u.buff, size, h.islittle); |
| 1373 | luaL_addsize(&b, size); |
| 1374 | break; |
| 1375 | } |
| 1376 | case Kchar: { /* fixed-size string */ |
| 1377 | size_t len; |
| 1378 | const char *s = luaL_checklstring(L, arg, &len); |
| 1379 | luaL_argcheck(L, len <= (size_t)size, arg, |
| 1380 | "string longer than given size"); |
| 1381 | luaL_addlstring(&b, s, len); /* add string */ |
| 1382 | while (len++ < (size_t)size) /* pad extra space */ |
| 1383 | luaL_addchar(&b, LUAL_PACKPADBYTE); |
| 1384 | break; |
| 1385 | } |
| 1386 | case Kstring: { /* strings with length count */ |
| 1387 | size_t len; |
nothing calls this directly
no test coverage detected