lua: properly handle corner cases in changes
authorJo-Philipp Wich <jow@openwrt.org>
Tue, 20 Dec 2011 16:06:50 +0000 (17:06 +0100)
committerJo-Philipp Wich <jow@openwrt.org>
Tue, 20 Dec 2011 16:06:50 +0000 (17:06 +0100)
The previous rework of the change serialization caused some deltas to incorrectly
get promoted to list appends. Rework the code to explicitely check for an add list
change type, in all other cases simply overwrite existing fields with the current
string value instead of coercing existing values into a table and append to that.
This hopefully sorts out the remaining issues.

lua/uci.c

index 564948bc67ebd443cb7ad3fd6900af2307f200e2..0667fc24a7b70ee35036d53ac84f1fccfcf7d802 100644 (file)
--- a/lua/uci.c
+++ b/lua/uci.c
@@ -711,35 +711,38 @@ uci_lua_add_change(lua_State *L, struct uci_element *e)
        if (name) {
                lua_getfield(L, -1, name);
 
-               /* there seems to be no value yet */
-               if (lua_isnil(L, -1)) {
-                       /* this delta is a list add operation, initialize table */
-                       if (h->cmd == UCI_CMD_LIST_ADD) {
+               /* this delta is a list add operation */
+               if (h->cmd == UCI_CMD_LIST_ADD) {
+                       /* there seems to be no table yet */
+                       if (!lua_istable(L, -1)) {
                                lua_newtable(L);
-                               lua_pushstring(L, value);
-                               lua_rawseti(L, -2, 1);
-                               lua_setfield(L, -3, name);
-                       } else {
-                               lua_pushstring(L, value);
-                               lua_setfield(L, -3, name);
-                       }
 
-               /* there is a value already, append */
-               } else {
-                       /* a string is on top of the stack, coerce into table */
-                       if (lua_isstring(L, -1)) {
-                               lua_newtable(L);
-                               lua_pushvalue(L, -2);
-                               lua_rawseti(L, -2, 1);
+                               /* if there is a value on the stack already, add */
+                               if (!lua_isnil(L, -2)) {
+                                       lua_pushvalue(L, -2);
+                                       lua_rawseti(L, -2, 1);
+                                       lua_pushstring(L, value);
+                                       lua_rawseti(L, -2, 2);
+
+                               /* this is the first table item */
+                               } else {
+                                       lua_pushstring(L, value);
+                                       lua_rawseti(L, -2, 1);
+                               }
+
                                lua_setfield(L, -3, name);
-                       }
 
-                       /* a table is on the top of the stack so this is a subsequent,
+                       /* a table is on the top of the stack and this is a subsequent,
                         * list_add, append this value to table */
-                       if (lua_istable(L, -1)) {
+                       } else {
                                lua_pushstring(L, value);
                                lua_rawseti(L, -2, lua_objlen(L, -2) + 1);
                        }
+
+               /* non-list change, simply set/replace field */
+               } else {
+                       lua_pushstring(L, value);
+                       lua_setfield(L, -3, name);
                }
 
                lua_pop(L, 1);