aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2020-12-16 11:23:51 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2020-12-16 11:23:51 -0300
commitb17178b27a55bd5eeb51538bec935972fd58f1ea (patch)
treebd3179b1e211cd1217e87c10cb8ea688fa8559b6
parente1ceea56740ea119e4ead68c4389407024da523d (diff)
downloadlua-b17178b27a55bd5eeb51538bec935972fd58f1ea.tar.gz
lua-b17178b27a55bd5eeb51538bec935972fd58f1ea.tar.bz2
lua-b17178b27a55bd5eeb51538bec935972fd58f1ea.zip
Cleaner handling of floats in pack/unpack
-rw-r--r--lstrlib.c70
1 files changed, 41 insertions, 29 deletions
diff --git a/lstrlib.c b/lstrlib.c
index 940a14ca..c7242ea4 100644
--- a/lstrlib.c
+++ b/lstrlib.c
@@ -1359,16 +1359,6 @@ struct cD {
1359 1359
1360 1360
1361/* 1361/*
1362** Union for serializing floats
1363*/
1364typedef 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*/
1374typedef struct Header { 1364typedef struct Header {
@@ -1384,7 +1374,9 @@ typedef struct Header {
1384typedef enum KOption { 1374typedef 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: {