lua: allow uci.set() to create/update a list value
[project/uci.git] / lua / uci.c
index c209cae..1c67742 100644 (file)
--- a/lua/uci.c
+++ b/lua/uci.c
@@ -88,17 +88,42 @@ done:
        lua_pop(L, 2);
 }
 
+static void uci_push_option(lua_State *L, struct uci_option *o)
+{
+       struct uci_element *e;
+       int i = 0;
+
+       switch(o->type) {
+       case UCI_TYPE_STRING:
+               lua_pushstring(L, o->v.string);
+               break;
+       case UCI_TYPE_LIST:
+               lua_newtable(L);
+               uci_foreach_element(&o->v.list, e) {
+                       i++;
+                       lua_pushstring(L, e->name);
+                       lua_rawseti(L, -2, i);
+               }
+               break;
+       default:
+               lua_pushnil(L);
+               break;
+       }
+}
+
 static void uci_push_section(lua_State *L, struct uci_section *s)
 {
        struct uci_element *e;
 
        lua_newtable(L);
        lua_pushstring(L, s->type);
-       lua_setfield(L, -2, ".TYPE");
+       lua_setfield(L, -2, ".type");
+       lua_pushstring(L, s->e.name);
+       lua_setfield(L, -2, ".name");
 
        uci_foreach_element(&s->options, e) {
                struct uci_option *o = uci_to_option(e);
-               lua_pushstring(L, o->value);
+               uci_push_option(L, o);
                lua_setfield(L, -2, o->e.name);
        }
 }
@@ -199,6 +224,7 @@ uci_lua_get_any(lua_State *L, bool all)
 {
        struct uci_element *e = NULL;
        struct uci_package *p = NULL;
+       struct uci_option *o = NULL;
        const char *package = NULL;
        const char *section = NULL;
        const char *option = NULL;
@@ -252,7 +278,8 @@ uci_lua_get_any(lua_State *L, bool all)
                                lua_pushstring(L, uci_to_section(e)->type);
                        break;
                case UCI_TYPE_OPTION:
-                       lua_pushstring(L, uci_to_option(e)->value);
+                       o = uci_to_option(e);
+                       uci_push_option(L, o);
                        break;
                default:
                        err = UCI_ERR_INVAL;
@@ -374,7 +401,8 @@ uci_lua_set(lua_State *L)
        const char *value = NULL;
        const char *s;
        int err = UCI_ERR_MEM;
-       int nargs;
+       int i, nargs;
+       bool istable = false;
 
        nargs = lua_gettop(L);
 
@@ -397,7 +425,16 @@ uci_lua_set(lua_State *L)
                /* Format: uci.set("p", "s", "v") */
                package = s;
                section = luaL_checkstring(L, 2);
-               value = luaL_checkstring(L, nargs);
+               if (lua_istable(L, nargs)) {
+                       if (lua_objlen(L, nargs) < 1)
+                               luaL_error(L, "Cannot set an uci option to an empty table value");
+                       lua_rawgeti(L, nargs, 1);
+                       value = luaL_checkstring(L, -1);
+                       lua_pop(L, 1);
+                       istable = true;
+               } else {
+                       value = luaL_checkstring(L, nargs);
+               }
                break;
        default:
                err = UCI_ERR_INVAL;
@@ -415,6 +452,16 @@ uci_lua_set(lua_State *L)
                goto error;
        }
        err = uci_set(ctx, p, section, option, value, NULL);
+       if (istable) {
+               for (i = 2; i <= lua_objlen(L, nargs); i++) {
+                       lua_rawgeti(L, nargs, i);
+                       value = luaL_checkstring(L, -1);
+                       err = uci_add_list(ctx, p, section, option, value, NULL);
+                       lua_pop(L, 1);
+                       if (err)
+                               goto error;
+               }
+       }
 
 error:
        if (err)
@@ -526,12 +573,12 @@ uci_lua_add_change(lua_State *L, struct uci_element *e)
        lua_getfield(L, -1, h->section);
        if (lua_isnil(L, -1)) {
                lua_pop(L, 1);
-               lua_createtable(L, 0, 0);
+               lua_newtable(L);
                lua_pushvalue(L, -1); /* copy for setfield */
                lua_setfield(L, -3, h->section);
        }
 
-       name = (h->e.name ? h->e.name : ".TYPE");
+       name = (h->e.name ? h->e.name : ".type");
        if (h->value)
                lua_pushstring(L, h->value);
        else
@@ -558,7 +605,7 @@ uci_lua_changes_pkg(lua_State *L, const char *package)
        if (uci_list_empty(&p->history) && uci_list_empty(&p->saved_history))
                goto done;
 
-       lua_createtable(L, 0, 0);
+       lua_newtable(L);
        uci_foreach_element(&p->saved_history, e) {
                uci_lua_add_change(L, e);
        }
@@ -590,7 +637,7 @@ uci_lua_changes(lua_State *L)
                luaL_error(L, "invalid argument count");
        }
 
-       lua_createtable(L, 0, 0);
+       lua_newtable(L);
        if (package) {
                uci_lua_changes_pkg(L, package);
        } else {