diff options
author | Jo-Philipp Wich <jow@openwrt.org> | 2015-12-17 02:36:45 +0100 |
---|---|---|
committer | Jo-Philipp Wich <jow@openwrt.org> | 2015-12-17 02:36:45 +0100 |
commit | e19098d0623e96690e65539b36c59965ae1373d5 (patch) | |
tree | d119b6321ece019fbedc711c13bf0b28e85a1055 | |
parent | 31816e92f109e0c534f176ca1e79b032917c876c (diff) | |
parent | 5335f225374c7ed993348d15b5018411dc776bab (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.html | 35 | ||||
-rw-r--r-- | libs/luci-lib-jsonc/src/jsonc.c | 71 | ||||
-rw-r--r-- | libs/luci-lib-jsonc/src/jsonc.luadoc | 14 |
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> ()</td> + <td class="summary"> + +Generate an ltn12-compatible sink.</td> + </tr> + + <tr> <td class="name" nowrap><a href="#parser.stringify">parser:stringify</a> (pretty)</td> <td class="summary"> @@ -406,6 +413,34 @@ Nothing is returned. +<dt><a name="parser.sink"></a><strong>parser:sink</strong> ()</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> (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. |