diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2020-12-16 11:23:51 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2020-12-16 11:23:51 -0300 |
commit | b17178b27a55bd5eeb51538bec935972fd58f1ea (patch) | |
tree | bd3179b1e211cd1217e87c10cb8ea688fa8559b6 | |
parent | e1ceea56740ea119e4ead68c4389407024da523d (diff) | |
download | lua-b17178b27a55bd5eeb51538bec935972fd58f1ea.tar.gz lua-b17178b27a55bd5eeb51538bec935972fd58f1ea.tar.bz2 lua-b17178b27a55bd5eeb51538bec935972fd58f1ea.zip |
Cleaner handling of floats in pack/unpack
-rw-r--r-- | lstrlib.c | 70 |
1 files changed, 41 insertions, 29 deletions
@@ -1359,16 +1359,6 @@ struct cD { | |||
1359 | 1359 | ||
1360 | 1360 | ||
1361 | /* | 1361 | /* |
1362 | ** Union for serializing floats | ||
1363 | */ | ||
1364 | typedef union Ftypes { | ||
1365 | float f; | ||
1366 | double d; | ||
1367 | lua_Number n; | ||
1368 | } Ftypes; | ||
1369 | |||
1370 | |||
1371 | /* | ||
1372 | ** information to pack/unpack stuff | 1362 | ** information to pack/unpack stuff |
1373 | */ | 1363 | */ |
1374 | typedef struct Header { | 1364 | typedef struct Header { |
@@ -1384,7 +1374,9 @@ typedef struct Header { | |||
1384 | typedef enum KOption { | 1374 | typedef enum KOption { |
1385 | Kint, /* signed integers */ | 1375 | Kint, /* signed integers */ |
1386 | Kuint, /* unsigned integers */ | 1376 | Kuint, /* unsigned integers */ |
1387 | Kfloat, /* floating-point numbers */ | 1377 | Kfloat, /* single-precision floating-point numbers */ |
1378 | Knumber, /* Lua "native" floating-point numbers */ | ||
1379 | Kdouble, /* double-precision floating-point numbers */ | ||
1388 | Kchar, /* fixed-length strings */ | 1380 | Kchar, /* fixed-length strings */ |
1389 | Kstring, /* strings with prefixed length */ | 1381 | Kstring, /* strings with prefixed length */ |
1390 | Kzstr, /* zero-terminated strings */ | 1382 | Kzstr, /* zero-terminated strings */ |
@@ -1453,8 +1445,8 @@ static KOption getoption (Header *h, const char **fmt, int *size) { | |||
1453 | case 'J': *size = sizeof(lua_Integer); return Kuint; | 1445 | case 'J': *size = sizeof(lua_Integer); return Kuint; |
1454 | case 'T': *size = sizeof(size_t); return Kuint; | 1446 | case 'T': *size = sizeof(size_t); return Kuint; |
1455 | case 'f': *size = sizeof(float); return Kfloat; | 1447 | case 'f': *size = sizeof(float); return Kfloat; |
1456 | case 'd': *size = sizeof(double); return Kfloat; | 1448 | case 'n': *size = sizeof(lua_Number); return Knumber; |
1457 | case 'n': *size = sizeof(lua_Number); return Kfloat; | 1449 | case 'd': *size = sizeof(double); return Kdouble; |
1458 | case 'i': *size = getnumlimit(h, fmt, sizeof(int)); return Kint; | 1450 | case 'i': *size = getnumlimit(h, fmt, sizeof(int)); return Kint; |
1459 | case 'I': *size = getnumlimit(h, fmt, sizeof(int)); return Kuint; | 1451 | case 'I': *size = getnumlimit(h, fmt, sizeof(int)); return Kuint; |
1460 | case 's': *size = getnumlimit(h, fmt, sizeof(size_t)); return Kstring; | 1452 | case 's': *size = getnumlimit(h, fmt, sizeof(size_t)); return Kstring; |
@@ -1580,15 +1572,27 @@ static int str_pack (lua_State *L) { | |||
1580 | packint(&b, (lua_Unsigned)n, h.islittle, size, 0); | 1572 | packint(&b, (lua_Unsigned)n, h.islittle, size, 0); |
1581 | break; | 1573 | break; |
1582 | } | 1574 | } |
1583 | case Kfloat: { /* floating-point options */ | 1575 | case Kfloat: { /* C float */ |
1584 | Ftypes u; | 1576 | float f = (float)luaL_checknumber(L, arg); /* get argument */ |
1585 | char *buff = luaL_prepbuffsize(&b, size); | 1577 | char *buff = luaL_prepbuffsize(&b, sizeof(f)); |
1586 | lua_Number n = luaL_checknumber(L, arg); /* get argument */ | 1578 | /* move 'f' to final result, correcting endianness if needed */ |
1587 | if (size == sizeof(u.f)) u.f = (float)n; /* copy it into 'u' */ | 1579 | copywithendian(buff, (char *)&f, sizeof(f), h.islittle); |
1588 | else if (size == sizeof(u.d)) u.d = (double)n; | 1580 | luaL_addsize(&b, size); |
1589 | else u.n = n; | 1581 | break; |
1590 | /* move 'u' to final result, correcting endianness if needed */ | 1582 | } |
1591 | copywithendian(buff, (char *)&u, size, h.islittle); | 1583 | case Knumber: { /* Lua float */ |
1584 | lua_Number f = luaL_checknumber(L, arg); /* get argument */ | ||
1585 | char *buff = luaL_prepbuffsize(&b, sizeof(f)); | ||
1586 | /* move 'f' to final result, correcting endianness if needed */ | ||
1587 | copywithendian(buff, (char *)&f, sizeof(f), h.islittle); | ||
1588 | luaL_addsize(&b, size); | ||
1589 | break; | ||
1590 | } | ||
1591 | case Kdouble: { /* C double */ | ||
1592 | double f = (double)luaL_checknumber(L, arg); /* get argument */ | ||
1593 | char *buff = luaL_prepbuffsize(&b, sizeof(f)); | ||
1594 | /* move 'f' to final result, correcting endianness if needed */ | ||
1595 | copywithendian(buff, (char *)&f, sizeof(f), h.islittle); | ||
1592 | luaL_addsize(&b, size); | 1596 | luaL_addsize(&b, size); |
1593 | break; | 1597 | break; |
1594 | } | 1598 | } |
@@ -1714,13 +1718,21 @@ static int str_unpack (lua_State *L) { | |||
1714 | break; | 1718 | break; |
1715 | } | 1719 | } |
1716 | case Kfloat: { | 1720 | case Kfloat: { |
1717 | Ftypes u; | 1721 | float f; |
1718 | lua_Number num; | 1722 | copywithendian((char *)&f, data + pos, sizeof(f), h.islittle); |
1719 | copywithendian((char *)&u, data + pos, size, h.islittle); | 1723 | lua_pushnumber(L, (lua_Number)f); |
1720 | if (size == sizeof(u.f)) num = (lua_Number)u.f; | 1724 | break; |
1721 | else if (size == sizeof(u.d)) num = (lua_Number)u.d; | 1725 | } |
1722 | else num = u.n; | 1726 | case Knumber: { |
1723 | lua_pushnumber(L, num); | 1727 | lua_Number f; |
1728 | copywithendian((char *)&f, data + pos, sizeof(f), h.islittle); | ||
1729 | lua_pushnumber(L, f); | ||
1730 | break; | ||
1731 | } | ||
1732 | case Kdouble: { | ||
1733 | double f; | ||
1734 | copywithendian((char *)&f, data + pos, sizeof(f), h.islittle); | ||
1735 | lua_pushnumber(L, (lua_Number)f); | ||
1724 | break; | 1736 | break; |
1725 | } | 1737 | } |
1726 | case Kchar: { | 1738 | case Kchar: { |