| 1177 | |
| 1178 | |
| 1179 | static int str_pack (lua_State *L) { |
| 1180 | luaL_Buffer b; |
| 1181 | Header h; |
| 1182 | const char *fmt = luaL_checkstring(L, 1); /* format string */ |
| 1183 | int arg = 1; /* current argument to pack */ |
| 1184 | size_t totalsize = 0; /* accumulate total size of result */ |
| 1185 | initheader(L, &h); |
| 1186 | lua_pushnil(L); /* mark to separate arguments from string buffer */ |
| 1187 | luaL_buffinit(L, &b); |
| 1188 | while (*fmt != '\0') { |
| 1189 | int size, ntoalign; |
| 1190 | KOption opt = getdetails(&h, totalsize, &fmt, &size, &ntoalign); |
| 1191 | totalsize += ntoalign + size; |
| 1192 | while (ntoalign-- > 0) |
| 1193 | luaL_addchar(&b, LUA_PACKPADBYTE); /* fill alignment */ |
| 1194 | arg++; |
| 1195 | switch (opt) { |
| 1196 | case Kint: { /* signed integers */ |
| 1197 | lua_Integer n = luaL_checkinteger(L, arg); |
| 1198 | if (size < SZINT) { /* need overflow check? */ |
| 1199 | lua_Integer lim = (lua_Integer)1 << ((size * NB) - 1); |
| 1200 | luaL_argcheck(L, -lim <= n && n < lim, arg, "integer overflow"); |
| 1201 | } |
| 1202 | packint(&b, (lua_Unsigned)n, h.islittle, size, (n < 0)); |
| 1203 | break; |
| 1204 | } |
| 1205 | case Kuint: { /* unsigned integers */ |
| 1206 | lua_Integer n = luaL_checkinteger(L, arg); |
| 1207 | if (size < SZINT) /* need overflow check? */ |
| 1208 | luaL_argcheck(L, (lua_Unsigned)n < ((lua_Unsigned)1 << (size * NB)), |
| 1209 | arg, "unsigned overflow"); |
| 1210 | packint(&b, (lua_Unsigned)n, h.islittle, size, 0); |
| 1211 | break; |
| 1212 | } |
| 1213 | case Kfloat: { /* floating-point options */ |
| 1214 | volatile Ftypes u; |
| 1215 | char *buff = luaL_prepbuffsize(&b, size); |
| 1216 | lua_Number n = luaL_checknumber(L, arg); /* get argument */ |
| 1217 | if (size == sizeof(u.f)) u.f = (float)n; /* copy it into 'u' */ |
| 1218 | else if (size == sizeof(u.d)) u.d = (double)n; |
| 1219 | else u.n = n; |
| 1220 | /* move 'u' to final result, correcting endianness if needed */ |
| 1221 | copywithendian(buff, u.buff, size, h.islittle); |
| 1222 | luaL_addsize(&b, size); |
| 1223 | break; |
| 1224 | } |
| 1225 | case Kchar: { /* fixed-size string */ |
| 1226 | size_t len; |
| 1227 | const char *s = luaL_checklstring(L, arg, &len); |
| 1228 | luaL_argcheck(L, len == (size_t)size, arg, "wrong length"); |
| 1229 | luaL_addlstring(&b, s, size); |
| 1230 | break; |
| 1231 | } |
| 1232 | case Kstring: { /* strings with length count */ |
| 1233 | size_t len; |
| 1234 | const char *s = luaL_checklstring(L, arg, &len); |
| 1235 | luaL_argcheck(L, size >= (int)sizeof(size_t) || |
| 1236 | len < ((size_t)1 << (size * NB)), |
nothing calls this directly
no test coverage detected