| 1550 | |
| 1551 | |
| 1552 | static int str_pack (lua_State *L) { |
| 1553 | luaL_Buffer b; |
| 1554 | Header h; |
| 1555 | const char *fmt = luaL_checkstring(L, 1); /* format string */ |
| 1556 | int arg = 1; /* current argument to pack */ |
| 1557 | size_t totalsize = 0; /* accumulate total size of result */ |
| 1558 | initheader(L, &h); |
| 1559 | lua_pushnil(L); /* mark to separate arguments from string buffer */ |
| 1560 | luaL_buffinit(L, &b); |
| 1561 | while (*fmt != '\0') { |
| 1562 | int size, ntoalign; |
| 1563 | KOption opt = getdetails(&h, totalsize, &fmt, &size, &ntoalign); |
| 1564 | totalsize += ntoalign + size; |
| 1565 | while (ntoalign-- > 0) |
| 1566 | luaL_addchar(&b, LUAL_PACKPADBYTE); /* fill alignment */ |
| 1567 | arg++; |
| 1568 | switch (opt) { |
| 1569 | case Kint: { /* signed integers */ |
| 1570 | lua_Integer n = luaL_checkinteger(L, arg); |
| 1571 | if (size < SZINT) { /* need overflow check? */ |
| 1572 | lua_Integer lim = (lua_Integer)1 << ((size * NB) - 1); |
| 1573 | luaL_argcheck(L, -lim <= n && n < lim, arg, "integer overflow"); |
| 1574 | } |
| 1575 | packint(&b, (lua_Unsigned)n, h.islittle, size, (n < 0)); |
| 1576 | break; |
| 1577 | } |
| 1578 | case Kuint: { /* unsigned integers */ |
| 1579 | lua_Integer n = luaL_checkinteger(L, arg); |
| 1580 | if (size < SZINT) /* need overflow check? */ |
| 1581 | luaL_argcheck(L, (lua_Unsigned)n < ((lua_Unsigned)1 << (size * NB)), |
| 1582 | arg, "unsigned overflow"); |
| 1583 | packint(&b, (lua_Unsigned)n, h.islittle, size, 0); |
| 1584 | break; |
| 1585 | } |
| 1586 | case Kfloat: { /* floating-point options */ |
| 1587 | volatile Ftypes u; |
| 1588 | char *buff = luaL_prepbuffsize(&b, size); |
| 1589 | lua_Number n = luaL_checknumber(L, arg); /* get argument */ |
| 1590 | if (size == sizeof(u.f)) u.f = (float)n; /* copy it into 'u' */ |
| 1591 | else if (size == sizeof(u.d)) u.d = (double)n; |
| 1592 | else u.n = n; |
| 1593 | /* move 'u' to final result, correcting endianness if needed */ |
| 1594 | copywithendian(buff, u.buff, size, h.islittle); |
| 1595 | luaL_addsize(&b, size); |
| 1596 | break; |
| 1597 | } |
| 1598 | case Kchar: { /* fixed-size string */ |
| 1599 | size_t len; |
| 1600 | const char *s = luaL_checklstring(L, arg, &len); |
| 1601 | luaL_argcheck(L, len <= (size_t)size, arg, |
| 1602 | "string longer than given size"); |
| 1603 | luaL_addlstring(&b, s, len); /* add string */ |
| 1604 | while (len++ < (size_t)size) /* pad extra space */ |
| 1605 | luaL_addchar(&b, LUAL_PACKPADBYTE); |
| 1606 | break; |
| 1607 | } |
| 1608 | case Kstring: { /* strings with length count */ |
| 1609 | size_t len; |
nothing calls this directly
no test coverage detected