diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2014-04-16 15:48:31 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2014-04-16 15:48:31 -0300 |
commit | 3d4913f7030e3b805de880aa1059d16fc92a8350 (patch) | |
tree | d45bb3234cc8079085893feb51198017f2649093 /lstrlib.c | |
parent | c27ef1b79c5063e87efe81ef5915b23e59a47aa4 (diff) | |
download | lua-3d4913f7030e3b805de880aa1059d16fc92a8350.tar.gz lua-3d4913f7030e3b805de880aa1059d16fc92a8350.tar.bz2 lua-3d4913f7030e3b805de880aa1059d16fc92a8350.zip |
back to larger sizes for 'dumpint/undumpint' (small Lua should
be able to dump/undump long-long integers)
Diffstat (limited to 'lstrlib.c')
-rw-r--r-- | lstrlib.c | 52 |
1 files changed, 39 insertions, 13 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lstrlib.c,v 1.195 2014/04/12 14:45:10 roberto Exp roberto $ | 2 | ** $Id: lstrlib.c,v 1.196 2014/04/14 16:59:46 roberto Exp roberto $ |
3 | ** Standard library for string operations and pattern-matching | 3 | ** Standard library for string operations and pattern-matching |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -950,17 +950,17 @@ static int str_format (lua_State *L) { | |||
950 | /* number of bits in a character */ | 950 | /* number of bits in a character */ |
951 | #define NB CHAR_BIT | 951 | #define NB CHAR_BIT |
952 | 952 | ||
953 | /* mask for one character (NB ones) */ | 953 | /* mask for one character (NB 1's) */ |
954 | #define MC ((1 << NB) - 1) | 954 | #define MC ((1 << NB) - 1) |
955 | 955 | ||
956 | /* mask for one character without sign ((NB - 1) ones) */ | 956 | /* mask for one character without sign bit ((NB - 1) 1's) */ |
957 | #define SM ((1 << (NB - 1)) - 1) | 957 | #define SM (MC >> 1) |
958 | 958 | ||
959 | /* size of a lua_Integer */ | 959 | /* size of a lua_Integer */ |
960 | #define SZINT ((int)sizeof(lua_Integer)) | 960 | #define SZINT ((int)sizeof(lua_Integer)) |
961 | 961 | ||
962 | /* maximum size for the binary representation of an integer */ | 962 | /* maximum size for the binary representation of an integer */ |
963 | #define MAXINTSIZE SZINT | 963 | #define MAXINTSIZE 12 |
964 | 964 | ||
965 | 965 | ||
966 | static union { | 966 | static union { |
@@ -989,18 +989,24 @@ static int getintsize (lua_State *L, int arg) { | |||
989 | } | 989 | } |
990 | 990 | ||
991 | 991 | ||
992 | static int dumpint (char *buff, lua_Unsigned n, int littleendian, int size) { | 992 | /* mask for all ones in last byte in a lua Integer */ |
993 | #define HIGHERBYTE ((lua_Unsigned)MC << (NB * (SZINT - 1))) | ||
994 | |||
995 | |||
996 | static int dumpint (char *buff, lua_Integer m, int littleendian, int size) { | ||
993 | int i; | 997 | int i; |
998 | lua_Unsigned n = (lua_Unsigned)m; | ||
999 | lua_Unsigned mask = (m >= 0) ? 0 : HIGHERBYTE; /* sign extension */ | ||
994 | if (littleendian) { | 1000 | if (littleendian) { |
995 | for (i = 0; i < size - 1; i++) { | 1001 | for (i = 0; i < size - 1; i++) { |
996 | buff[i] = (n & MC); | 1002 | buff[i] = (n & MC); |
997 | n >>= NB; | 1003 | n = (n >> NB) | mask; |
998 | } | 1004 | } |
999 | } | 1005 | } |
1000 | else { | 1006 | else { |
1001 | for (i = size - 1; i > 0; i--) { | 1007 | for (i = size - 1; i > 0; i--) { |
1002 | buff[i] = (n & MC); | 1008 | buff[i] = (n & MC); |
1003 | n >>= NB; | 1009 | n = (n >> NB) | mask; |
1004 | } | 1010 | } |
1005 | } | 1011 | } |
1006 | buff[i] = (n & MC); /* last byte */ | 1012 | buff[i] = (n & MC); /* last byte */ |
@@ -1008,7 +1014,7 @@ static int dumpint (char *buff, lua_Unsigned n, int littleendian, int size) { | |||
1008 | /* OK if there are only zeros left in higher bytes, | 1014 | /* OK if there are only zeros left in higher bytes, |
1009 | or only ones left (excluding non-signal bits in last byte) */ | 1015 | or only ones left (excluding non-signal bits in last byte) */ |
1010 | return ((n & ~(lua_Integer)MC) == 0 || | 1016 | return ((n & ~(lua_Integer)MC) == 0 || |
1011 | (n | SM) == (LUA_MAXUNSIGNED >> ((size - 1) * NB))); | 1017 | (n | SM) == ~(lua_Integer)0); |
1012 | } | 1018 | } |
1013 | else return 1; /* no overflow can occur with full size */ | 1019 | else return 1; /* no overflow can occur with full size */ |
1014 | } | 1020 | } |
@@ -1019,7 +1025,7 @@ static int dumpint_l (lua_State *L) { | |||
1019 | lua_Integer n = luaL_checkinteger(L, 1); | 1025 | lua_Integer n = luaL_checkinteger(L, 1); |
1020 | int size = getintsize(L, 2); | 1026 | int size = getintsize(L, 2); |
1021 | int endian = getendian(L, 3); | 1027 | int endian = getendian(L, 3); |
1022 | if (dumpint(buff, (lua_Unsigned)n, endian, size)) | 1028 | if (dumpint(buff, n, endian, size)) |
1023 | lua_pushlstring(L, buff, size); | 1029 | lua_pushlstring(L, buff, size); |
1024 | else | 1030 | else |
1025 | luaL_error(L, "integer does not fit into given size (%d)", size); | 1031 | luaL_error(L, "integer does not fit into given size (%d)", size); |
@@ -1027,10 +1033,25 @@ static int dumpint_l (lua_State *L) { | |||
1027 | } | 1033 | } |
1028 | 1034 | ||
1029 | 1035 | ||
1030 | static lua_Integer undumpint (const char *buff, int littleendian, int size) { | 1036 | /* mask to check higher-order byte + signal bit of next (lower) byte */ |
1037 | #define HIGHERBYTE1 (HIGHERBYTE | (HIGHERBYTE >> 1)) | ||
1038 | |||
1039 | |||
1040 | static int undumpint (const char *buff, lua_Integer *res, | ||
1041 | int littleendian, int size) { | ||
1031 | lua_Integer n = 0; | 1042 | lua_Integer n = 0; |
1032 | int i; | 1043 | int i; |
1033 | for (i = 0; i < size; i++) { | 1044 | for (i = 0; i < size; i++) { |
1045 | if (i >= SZINT) { /* will throw away a byte? */ | ||
1046 | /* check for overflow: it is OK to throw away leading zeros for a | ||
1047 | positive number, leading ones for a negative number, and a | ||
1048 | leading zero byte to allow unsigned integers with a 1 in | ||
1049 | its "signal bit" */ | ||
1050 | if (!((n & HIGHERBYTE1) == 0 || /* zeros for positive number */ | ||
1051 | (n & HIGHERBYTE1) == HIGHERBYTE1 || /* ones for negative number */ | ||
1052 | (i == size - 1 && (n & HIGHERBYTE) == 0))) /* leading zero */ | ||
1053 | return 0; /* overflow */ | ||
1054 | } | ||
1034 | n <<= NB; | 1055 | n <<= NB; |
1035 | n |= (lua_Integer)(unsigned char)buff[littleendian ? size - 1 - i : i]; | 1056 | n |= (lua_Integer)(unsigned char)buff[littleendian ? size - 1 - i : i]; |
1036 | } | 1057 | } |
@@ -1038,11 +1059,13 @@ static lua_Integer undumpint (const char *buff, int littleendian, int size) { | |||
1038 | lua_Unsigned mask = (lua_Unsigned)1 << (size*NB - 1); | 1059 | lua_Unsigned mask = (lua_Unsigned)1 << (size*NB - 1); |
1039 | n = (lua_Integer)((n ^ mask) - mask); /* do sign extension */ | 1060 | n = (lua_Integer)((n ^ mask) - mask); /* do sign extension */ |
1040 | } | 1061 | } |
1041 | return n; | 1062 | *res = n; |
1063 | return 1; | ||
1042 | } | 1064 | } |
1043 | 1065 | ||
1044 | 1066 | ||
1045 | static int undumpint_l (lua_State *L) { | 1067 | static int undumpint_l (lua_State *L) { |
1068 | lua_Integer res; | ||
1046 | size_t len; | 1069 | size_t len; |
1047 | const char *s = luaL_checklstring(L, 1, &len); | 1070 | const char *s = luaL_checklstring(L, 1, &len); |
1048 | lua_Integer pos = posrelat(luaL_optinteger(L, 2, 1), len); | 1071 | lua_Integer pos = posrelat(luaL_optinteger(L, 2, 1), len); |
@@ -1050,7 +1073,10 @@ static int undumpint_l (lua_State *L) { | |||
1050 | int endian = getendian(L, 4); | 1073 | int endian = getendian(L, 4); |
1051 | luaL_argcheck(L, 1 <= pos && (size_t)pos + size - 1 <= len, 1, | 1074 | luaL_argcheck(L, 1 <= pos && (size_t)pos + size - 1 <= len, 1, |
1052 | "string too short"); | 1075 | "string too short"); |
1053 | lua_pushinteger(L, undumpint(s + pos - 1, endian, size)); | 1076 | if(undumpint(s + pos - 1, &res, endian, size)) |
1077 | lua_pushinteger(L, res); | ||
1078 | else | ||
1079 | luaL_error(L, "result does not fit into a Lua integer"); | ||
1054 | return 1; | 1080 | return 1; |
1055 | } | 1081 | } |
1056 | 1082 | ||