| 1360 | |
| 1361 | |
| 1362 | static int str_pack(lua_State *L) { |
| 1363 | luaL_Buffer b; |
| 1364 | Header h; |
| 1365 | const char *fmt = luaL_checkstring(L, 1); /* format string */ |
| 1366 | int arg = 1; /* current argument to pack */ |
| 1367 | size_t totalsize = 0; /* accumulate total size of result */ |
| 1368 | initheader(L, &h); |
| 1369 | lua_pushnil(L); /* mark to separate arguments from string buffer */ |
| 1370 | luaL_buffinit(L, &b); |
| 1371 | while (*fmt != '\0') { |
| 1372 | int size, ntoalign; |
| 1373 | KOption opt = getdetails(&h, totalsize, &fmt, &size, &ntoalign); |
| 1374 | totalsize += ntoalign + size; |
| 1375 | while (ntoalign-- > 0) |
| 1376 | luaL_addchar(&b, LUA_PACKPADBYTE); /* fill alignment */ |
| 1377 | arg++; |
| 1378 | switch (opt) { |
| 1379 | case Kint: { /* signed integers */ |
| 1380 | lua_Integer n = luaL_checkinteger(L, arg); |
| 1381 | if (size < SZINT) { /* need overflow check? */ |
| 1382 | lua_Integer lim = (lua_Integer)1 << ((size * NB) - 1); |
| 1383 | luaL_argcheck(L, -lim <= n && n < lim, arg, "integer overflow"); |
| 1384 | } |
| 1385 | packint(&b, (lua_Unsigned)n, h.islittle, size, (n < 0)); |
| 1386 | break; |
| 1387 | } |
| 1388 | case Kuint: { /* unsigned integers */ |
| 1389 | lua_Integer n = luaL_checkinteger(L, arg); |
| 1390 | if (size < SZINT) /* need overflow check? */ |
| 1391 | luaL_argcheck(L, (lua_Unsigned)n < ((lua_Unsigned)1 << (size * NB)), |
| 1392 | arg, "unsigned overflow"); |
| 1393 | packint(&b, (lua_Unsigned)n, h.islittle, size, 0); |
| 1394 | break; |
| 1395 | } |
| 1396 | case Kfloat: { /* floating-point options */ |
| 1397 | volatile Ftypes u; |
| 1398 | char *buff = luaL_prepbuffsize(&b, size); |
| 1399 | lua_Number n = luaL_checknumber(L, arg); /* get argument */ |
| 1400 | if (size == sizeof(u.f)) u.f = (float)n; /* copy it into 'u' */ |
| 1401 | else if (size == sizeof(u.d)) u.d = (double)n; |
| 1402 | else u.n = n; |
| 1403 | /* move 'u' to final result, correcting endianness if needed */ |
| 1404 | copywithendian(buff, u.buff, size, h.islittle); |
| 1405 | luaL_addsize(&b, size); |
| 1406 | break; |
| 1407 | } |
| 1408 | case Kchar: { /* fixed-size string */ |
| 1409 | size_t len; |
| 1410 | const char *s = luaL_checklstring(L, arg, &len); |
| 1411 | if ((size_t)size <= len) /* string larger than (or equal to) needed? */ |
| 1412 | luaL_addlstring(&b, s, size); /* truncate string to asked size */ |
| 1413 | else { /* string smaller than needed */ |
| 1414 | luaL_addlstring(&b, s, len); /* add it all */ |
| 1415 | while (len++ < (size_t)size) /* pad extra space */ |
| 1416 | luaL_addchar(&b, LUA_PACKPADBYTE); |
| 1417 | } |
| 1418 | break; |
| 1419 | } |
nothing calls this directly
no test coverage detected