Explorar o código

Change struct & sjson to use integers. This is slightly more complex (#3222)

* Change struct to use integers. This is slightly more complex as we have to deal with Unsigned 32-bit integers (that aren't lua integers)
* Use int64 in struct rather than double.
* Fix sjson to do the right things in LUA5.3 with integers and floats
Philip Gladstone %!s(int64=3) %!d(string=hai) anos
pai
achega
0e02c0e5f3
Modificáronse 2 ficheiros con 47 adicións e 20 borrados
  1. 24 9
      app/modules/sjson.c
  2. 23 11
      app/modules/struct.c

+ 24 - 9
app/modules/sjson.c

@@ -97,7 +97,7 @@ create_new_element(jsonsl_t jsn,
       lua_rawgeti(data->L, LUA_REGISTRYINDEX, get_parent_object_ref());
       if (data->hkey_ref == LUA_NOREF) {
         // list, so append
-        lua_pushnumber(data->L, get_parent_object_used_count_pre_inc());
+        lua_pushinteger(data->L, get_parent_object_used_count_pre_inc());
         DBG_PRINTF("Adding array element\n");
       } else {
         // object, so
@@ -108,7 +108,7 @@ create_new_element(jsonsl_t jsn,
       }
       if (data->pos_ref != LUA_NOREF && state->level > 1) {
         lua_rawgeti(data->L, LUA_REGISTRYINDEX, data->pos_ref);
-        lua_pushnumber(data->L, state->level - 1);
+        lua_pushinteger(data->L, state->level - 1);
         lua_pushvalue(data->L, -3);     // get the key
         lua_settable(data->L, -3);
         lua_pop(data->L, 1);
@@ -152,10 +152,21 @@ create_new_element(jsonsl_t jsn,
 }
 
 static void push_number(JSN_DATA *data, struct jsonsl_state_st *state) {
-  lua_pushlstring(data->L, get_state_buffer(data, state), state->pos_cur - state->pos_begin);
-  LUA_NUMBER r = lua_tonumber(data->L, -1);
+  const char *start = get_state_buffer(data, state);
+  const char *end = start + state->pos_cur - state->pos_begin;
+  lua_pushlstring(data->L, start, end - start);
+#if LUA_VERSION_NUM >= 503
+  int sz = lua_stringtonumber(data->L, lua_tostring(data->L, -1));
+  if (sz) {
+    lua_pop(data->L, 1);
+  } else {
+    luaL_error(data->L, "Invalid number");
+  }
+#else
+  lua_Number result = lua_tonumber(data->L, -1);
   lua_pop(data->L, 1);
-  lua_pushnumber(data->L, r);
+  lua_pushnumber(data->L, result);
+#endif
 }
 
 static int fromhex(char c) {
@@ -241,7 +252,7 @@ cleanup_closing_element(jsonsl_t jsn,
       lua_rawgeti(data->L, LUA_REGISTRYINDEX, get_parent_object_ref());
       if (data->hkey_ref == LUA_NOREF) {
         // list, so append
-        lua_pushnumber(data->L, get_parent_object_used_count_pre_inc());
+        lua_pushinteger(data->L, get_parent_object_used_count_pre_inc());
       } else {
         // object, so
         lua_rawgeti(data->L, LUA_REGISTRYINDEX, data->hkey_ref);
@@ -272,7 +283,7 @@ cleanup_closing_element(jsonsl_t jsn,
         lua_rawgeti(data->L, LUA_REGISTRYINDEX, get_parent_object_ref());
         if (data->hkey_ref == LUA_NOREF) {
           // list, so append
-          lua_pushnumber(data->L, get_parent_object_used_count_pre_inc());
+          lua_pushinteger(data->L, get_parent_object_used_count_pre_inc());
         } else {
           // object, so
           lua_rawgeti(data->L, LUA_REGISTRYINDEX, data->hkey_ref);
@@ -291,7 +302,7 @@ cleanup_closing_element(jsonsl_t jsn,
       state->lua_object_ref = LUA_NOREF;
       if (data->pos_ref != LUA_NOREF) {
         lua_rawgeti(data->L, LUA_REGISTRYINDEX, data->pos_ref);
-        lua_pushnumber(data->L, state->level);
+        lua_pushinteger(data->L, state->level);
         lua_pushnil(data->L);
         lua_settable(data->L, -3);
         lua_pop(data->L, 1);
@@ -719,7 +730,11 @@ static void encode_lua_object(lua_State *L, ENC_DATA *data, int argno, const cha
       char value[len + 1];
       strcpy(value, str);
       lua_pop(L, 1);
-      luaL_addstring(&b, value);
+      if (strcmp(value, "-Infinity") == 0 || strcmp(value, "NaN") == 0 || strcmp(value, "Infinity") == 0) {
+        luaL_addstring(&b, "null");   // According to ECMA-262 section 24.5.2 Note 4
+      } else {
+        luaL_addstring(&b, value);
+      }
       break;
     }
 

+ 23 - 11
app/modules/struct.c

@@ -60,6 +60,14 @@ typedef unsigned STRUCT_INT Uinttype;
 #define MAXINTSIZE	32
 #endif
 
+#ifndef LUA_MININTEGER
+#define LUA_MININTEGER INT_MIN
+#endif
+
+#ifndef LUA_MAXINTEGER
+#define LUA_MAXINTEGER INT_MAX
+#endif
+
 /* is 'x' a power of 2? */
 #define isp2(x)		((x) > 0 && ((x) & ((x) - 1)) == 0)
 
@@ -170,7 +178,7 @@ static void controloptions (lua_State *L, int opt, const char **fmt,
 
 static void putinteger (lua_State *L, luaL_Buffer *b, int arg, int endian,
                         int size) {
-  lua_Number n = luaL_checknumber(L, arg);
+  int32_t n = luaL_checkinteger(L, arg);
   Uinttype value;
   char buff[MAXINTSIZE];
   if (n < 0)
@@ -267,29 +275,29 @@ static int b_pack (lua_State *L) {
 }
 
 
-static lua_Number getinteger (const char *buff, int endian,
+static int64_t getinteger (const char *buff, int endian,
                         int issigned, int size) {
-  Uinttype l = 0;
+  uint64_t l = 0;
   int i;
   if (endian == BIG) {
     for (i = 0; i < size; i++) {
       l <<= 8;
-      l |= (Uinttype)(unsigned char)buff[i];
+      l |= (unsigned char)buff[i];
     }
   }
   else {
     for (i = size - 1; i >= 0; i--) {
       l <<= 8;
-      l |= (Uinttype)(unsigned char)buff[i];
+      l |= (unsigned char)buff[i];
     }
   }
   if (!issigned)
-    return (lua_Number)l;
+    return (int64_t)l;
   else {  /* signed format */
-    Uinttype mask = (Uinttype)(~((Uinttype)0)) << (size*8 - 1);
+    uint64_t mask = (uint64_t)(~((uint64_t)0)) << (size*8 - 1);
     if (l & mask)  /* negative value? */
       l |= mask;  /* signal extension */
-    return (lua_Number)(Inttype)l;
+    return (int64_t)l;
   }
 }
 
@@ -312,8 +320,12 @@ static int b_unpack (lua_State *L) {
       case 'b': case 'B': case 'h': case 'H':
       case 'l': case 'L': case 'T': case 'i':  case 'I': {  /* integer types */
         int issigned = islower(opt);
-        lua_Number res = getinteger(data+pos, h.endian, issigned, size);
-        lua_pushnumber(L, res);
+        int64_t res = getinteger(data+pos, h.endian, issigned, size);
+        if (res >= LUA_MININTEGER && res <= LUA_MAXINTEGER) {
+          lua_pushinteger(L, res);
+        } else {
+          lua_pushnumber(L, res);
+        }
         break;
       }
       case 'x': {
@@ -339,7 +351,7 @@ static int b_unpack (lua_State *L) {
         if (size == 0) {
           if (!lua_isnumber(L, -1))
             luaL_error(L, "format `c0' needs a previous size");
-          size = lua_tonumber(L, -1);
+          size = lua_tointeger(L, -1);
           lua_pop(L, 1);
           luaL_argcheck(L, pos+size <= ld, 2, "data string too short");
         }