summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJo-Philipp Wich <jow@openwrt.org>2015-12-17 02:36:45 +0100
committerJo-Philipp Wich <jow@openwrt.org>2015-12-17 02:36:45 +0100
commite19098d0623e96690e65539b36c59965ae1373d5 (patch)
treed119b6321ece019fbedc711c13bf0b28e85a1055
parent31816e92f109e0c534f176ca1e79b032917c876c (diff)
parent5335f225374c7ed993348d15b5018411dc776bab (diff)
Merge pull request #462 from jplitza/jsonc-sink
luci-lib-jsonc: Add ltn12-compatible sink factory
-rw-r--r--documentation/api/modules/luci.jsonc.parser.html35
-rw-r--r--libs/luci-lib-jsonc/src/jsonc.c71
-rw-r--r--libs/luci-lib-jsonc/src/jsonc.luadoc14
3 files changed, 119 insertions, 1 deletions
diff --git a/documentation/api/modules/luci.jsonc.parser.html b/documentation/api/modules/luci.jsonc.parser.html
index 4c19cf0e5..e8e145f43 100644
--- a/documentation/api/modules/luci.jsonc.parser.html
+++ b/documentation/api/modules/luci.jsonc.parser.html
@@ -234,6 +234,13 @@ Put Lua data into the parser.</td>
</tr>
<tr>
+ <td class="name" nowrap><a href="#parser.sink">parser:sink</a>&nbsp;()</td>
+ <td class="summary">
+
+Generate an ltn12-compatible sink.</td>
+ </tr>
+
+ <tr>
<td class="name" nowrap><a href="#parser.stringify">parser:stringify</a>&nbsp;(pretty)</td>
<td class="summary">
@@ -406,6 +413,34 @@ Nothing is returned.
+<dt><a name="parser.sink"></a><strong>parser:sink</strong>&nbsp;()</dt>
+<dd>
+
+
+Generate an ltn12-compatible sink.
+
+
+
+
+
+
+<h3>Usage:</h3>
+<pre>parser = luci.jsonc.new()
+ltn12.pump.all(ltn12.source.file(io.input()), parser:sink())
+print(parser:get())</pre>
+
+
+
+<h3>Return value:</h3>
+Returns a function that can be used as an ltn12 sink.
+
+
+
+</dd>
+
+
+
+
<dt><a name="parser.stringify"></a><strong>parser:stringify</strong>&nbsp;(pretty)</dt>
<dd>
diff --git a/libs/luci-lib-jsonc/src/jsonc.c b/libs/luci-lib-jsonc/src/jsonc.c
index b857c979e..ef1110166 100644
--- a/libs/luci-lib-jsonc/src/jsonc.c
+++ b/libs/luci-lib-jsonc/src/jsonc.c
@@ -328,6 +328,76 @@ static int json_parse_set(lua_State *L)
return 0;
}
+static int json_parse_sink_closure(lua_State *L)
+{
+ bool finished = lua_toboolean(L, lua_upvalueindex(2));
+ if (lua_isnil(L, 1))
+ {
+ // no more data available
+ if (finished)
+ {
+ // we were finished parsing
+ lua_pushboolean(L, true);
+ return 1;
+ }
+ else
+ {
+ lua_pushnil(L);
+ lua_pushstring(L, "Incomplete JSON data");
+ return 2;
+ }
+ }
+ else
+ {
+ if (finished)
+ {
+ lua_pushnil(L);
+ lua_pushstring(L, "Unexpected data after complete JSON object");
+ return 2;
+ }
+ else
+ {
+ // luci.jsonc.parser.chunk()
+ lua_pushcfunction(L, json_parse_chunk);
+ // parser object from closure
+ lua_pushvalue(L, lua_upvalueindex(1));
+ // chunk
+ lua_pushvalue(L, 1);
+ lua_call(L, 2, 2);
+
+ if (lua_isnil(L, -2))
+ {
+ // an error occurred, leave (nil, errmsg) on the stack and return it
+ return 2;
+ }
+ else if (lua_toboolean(L, -2))
+ {
+ // finished reading, set finished=true and return nil to prevent further input
+ lua_pop(L, 2);
+ lua_pushboolean(L, true);
+ lua_replace(L, lua_upvalueindex(2));
+ lua_pushnil(L);
+ return 1;
+ }
+ else
+ {
+ // not finished reading, return true
+ lua_pop(L, 2);
+ lua_pushboolean(L, true);
+ return 1;
+ }
+ }
+ }
+}
+
+static int json_parse_sink(lua_State *L)
+{
+ luaL_checkudata(L, 1, LUCI_JSONC_PARSER);
+ lua_pushboolean(L, false);
+ lua_pushcclosure(L, json_parse_sink_closure, 2);
+ return 1;
+}
+
static int json_tostring(lua_State *L)
{
struct json_state *s = luaL_checkudata(L, 1, LUCI_JSONC_PARSER);
@@ -367,6 +437,7 @@ static const luaL_reg jsonc_parser_methods[] = {
{ "parse", json_parse_chunk },
{ "get", json_parse_get },
{ "set", json_parse_set },
+ { "sink", json_parse_sink },
{ "stringify", json_tostring },
{ "__gc", json_gc },
diff --git a/libs/luci-lib-jsonc/src/jsonc.luadoc b/libs/luci-lib-jsonc/src/jsonc.luadoc
index 2ee9cebdc..720b17d1e 100644
--- a/libs/luci-lib-jsonc/src/jsonc.luadoc
+++ b/libs/luci-lib-jsonc/src/jsonc.luadoc
@@ -121,10 +121,22 @@ parser:set({ "some", "data" })`
]]
---[[
-Serialize current parser state as JSON.
+Generate an ltn12-compatible sink.
@class function
@sort 4
+@name parser.sink
+@return Returns a function that can be used as an ltn12 sink.
+@usage `parser = luci.jsonc.new()
+ltn12.pump.all(ltn12.source.file(io.input()), parser:sink())
+print(parser:get())`
+]]
+
+---[[
+Serialize current parser state as JSON.
+
+@class function
+@sort 5
@name parser.stringify
@param pretty A boolean value indicating whether the resulting JSON should be pretty printed.
@return Returns the serialized JSON data of this parser instance.