webmcp

changeset 163:581878c613d6

Always sort keys in JSON objects when exporting
author jbe
date Thu Jul 31 19:27:29 2014 +0200 (2014-07-31)
parents 3b8c1e2aef9c
children 8e969519f7c7
files libraries/json/json.c
line diff
     1.1 --- a/libraries/json/json.c	Thu Jul 31 16:24:39 2014 +0200
     1.2 +++ b/libraries/json/json.c	Thu Jul 31 19:27:29 2014 +0200
     1.3 @@ -678,6 +678,35 @@
     1.4    return 3;
     1.5  }
     1.6  
     1.7 +typedef struct {
     1.8 +  size_t length;
     1.9 +  const char *data;
    1.10 +} json_key_t;
    1.11 +
    1.12 +static int json_key_cmp(json_key_t *key1, json_key_t *key2) {
    1.13 +  size_t pos = 0;
    1.14 +  unsigned char c1, c2;
    1.15 +  while (1) {
    1.16 +    if (key1->length > pos) {
    1.17 +      if (key2->length > pos) {
    1.18 +        c1 = key1->data[pos];
    1.19 +        c2 = key2->data[pos];
    1.20 +        if (c1 < c2) return -1;
    1.21 +        else if (c1 > c2) return 1;
    1.22 +      } else {
    1.23 +        return 1;
    1.24 +      }
    1.25 +    } else {
    1.26 +      if (key2->length > pos) {
    1.27 +        return -1;
    1.28 +      } else {
    1.29 +        return 0;
    1.30 +      }
    1.31 +    }
    1.32 +    pos++;
    1.33 +  }
    1.34 +}
    1.35 +
    1.36  #define JSON_TABLETYPE_UNKNOWN 0
    1.37  #define JSON_TABLETYPE_OBJECT 1
    1.38  #define JSON_TABLETYPE_ARRAY 2
    1.39 @@ -693,6 +722,9 @@
    1.40    int luatype;
    1.41    int tabletype = JSON_TABLETYPE_UNKNOWN;
    1.42    int needsep = 0;
    1.43 +  size_t keycount = 0;
    1.44 +  size_t keypos = 0;
    1.45 +  json_key_t *keybuf;
    1.46    lua_Integer idx;
    1.47    lua_settop(L, 1);
    1.48    if (json_isnullmark(L, 1)) {
    1.49 @@ -768,33 +800,43 @@
    1.50      }
    1.51      switch (tabletype) {
    1.52      case JSON_TABLETYPE_OBJECT:
    1.53 -      lua_settop(L, 3);
    1.54 +      for (lua_pushnil(L); lua_next(L, 1); lua_pop(L, 1)) {
    1.55 +        if (lua_type(L, -2) == LUA_TSTRING) keycount++;
    1.56 +      }
    1.57 +      if (keycount) {
    1.58 +        keybuf = calloc(keycount, sizeof(json_key_t));
    1.59 +        if (!keybuf) return luaL_error(L, "Memory allocation failed in JSON library");
    1.60 +        for (lua_pushnil(L); lua_next(L, 1); lua_pop(L, 1)) {
    1.61 +          if (lua_type(L, -2) == LUA_TSTRING) {
    1.62 +            json_key_t *key = keybuf + (keypos++);
    1.63 +            key->data = lua_tolstring(L, -2, &key->length);
    1.64 +          }
    1.65 +        }
    1.66 +        qsort(keybuf, keycount, sizeof(json_key_t), (void *)json_key_cmp);
    1.67 +      }
    1.68        luaL_buffinit(L, &buf);
    1.69        luaL_addchar(&buf, '{');
    1.70 -      for (lua_pushnil(L); lua_next(L, 1); ) {
    1.71 -        if (lua_type(L, -2) == LUA_TSTRING) {
    1.72 -          lua_replace(L, 3);
    1.73 -          lua_replace(L, 2);
    1.74 -          if (needsep) luaL_addchar(&buf, ',');
    1.75 -          else needsep = 1;
    1.76 -          lua_pushcfunction(L, json_export);
    1.77 -          lua_pushvalue(L, 2);
    1.78 -          lua_call(L, 1, 1);
    1.79 -          luaL_addvalue(&buf);
    1.80 -          luaL_addchar(&buf, ':');
    1.81 -          if (json_isnullmark(L, 3)) {
    1.82 -            luaL_addstring(&buf, "null");
    1.83 -          } else {
    1.84 -            lua_pushcfunction(L, json_export);
    1.85 -            lua_pushvalue(L, 3);
    1.86 -            lua_call(L, 1, 1);
    1.87 -            luaL_addvalue(&buf);
    1.88 -          }
    1.89 -          lua_pushvalue(L, 2);
    1.90 -        } else {
    1.91 -          lua_pop(L, 1);
    1.92 +      for (keypos=0; keypos<keycount; keypos++) {
    1.93 +        json_key_t *key = keybuf + keypos;
    1.94 +        if (keypos) luaL_addchar(&buf, ',');
    1.95 +        lua_pushcfunction(L, json_export);
    1.96 +        lua_pushlstring(L, key->data, key->length);
    1.97 +        if (lua_pcall(L, 1, 1, 0)) {
    1.98 +          if (keybuf) free(keybuf);
    1.99 +          return lua_error(L);
   1.100          }
   1.101 +        luaL_addvalue(&buf);
   1.102 +        luaL_addchar(&buf, ':');
   1.103 +        lua_pushcfunction(L, json_export);
   1.104 +        lua_pushlstring(L, key->data, key->length);
   1.105 +        lua_rawget(L, 1);
   1.106 +        if (lua_pcall(L, 1, 1, 0)) {
   1.107 +          if (keybuf) free(keybuf);
   1.108 +          return lua_error(L);
   1.109 +        }
   1.110 +        luaL_addvalue(&buf);
   1.111        }
   1.112 +      if (keybuf) free(keybuf);
   1.113        luaL_addchar(&buf, '}');
   1.114        luaL_pushresult(&buf);
   1.115        return 1;

Impressum / About Us