Merge pull request #462 from jplitza/jsonc-sink

luci-lib-jsonc: Add ltn12-compatible sink factory
pull/582/head
Jo-Philipp Wich 2015-12-17 02:36:45 +01:00
commit e19098d062
3 changed files with 119 additions and 1 deletions

View File

@ -233,6 +233,13 @@ Convert parsed JSON data into Lua table.</td>
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>

View File

@ -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 },

View File

@ -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.