luci-lib-jsonc: Add ltn12-compatible sink factory
To use the luci-lib-jsonc parser as sink for an ltn12 pump (for example from stdin), the following code will now do: require 'luci.ltn12' require 'luci.jsonc' local parser = luci.jsonc.new() luci.ltn12.pump.all(luci.ltn12.source.file(io.input()), parser:sink()) print(parser:get()) Signed-off-by: Jan-Philipp Litza <janphilipp@litza.de>
This commit is contained in:
parent
f0083abed1
commit
5335f22537
3 changed files with 119 additions and 1 deletions
|
@ -233,6 +233,13 @@ Convert parsed JSON data into Lua table.</td>
|
||||||
Put Lua data into the parser.</td>
|
Put Lua data into the parser.</td>
|
||||||
</tr>
|
</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>
|
<tr>
|
||||||
<td class="name" nowrap><a href="#parser.stringify">parser:stringify</a> (pretty)</td>
|
<td class="name" nowrap><a href="#parser.stringify">parser:stringify</a> (pretty)</td>
|
||||||
<td class="summary">
|
<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>
|
<dt><a name="parser.stringify"></a><strong>parser:stringify</strong> (pretty)</dt>
|
||||||
<dd>
|
<dd>
|
||||||
|
|
||||||
|
|
|
@ -328,6 +328,76 @@ static int json_parse_set(lua_State *L)
|
||||||
return 0;
|
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)
|
static int json_tostring(lua_State *L)
|
||||||
{
|
{
|
||||||
struct json_state *s = luaL_checkudata(L, 1, LUCI_JSONC_PARSER);
|
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 },
|
{ "parse", json_parse_chunk },
|
||||||
{ "get", json_parse_get },
|
{ "get", json_parse_get },
|
||||||
{ "set", json_parse_set },
|
{ "set", json_parse_set },
|
||||||
|
{ "sink", json_parse_sink },
|
||||||
{ "stringify", json_tostring },
|
{ "stringify", json_tostring },
|
||||||
|
|
||||||
{ "__gc", json_gc },
|
{ "__gc", json_gc },
|
||||||
|
|
|
@ -121,10 +121,22 @@ parser:set({ "some", "data" })`
|
||||||
]]
|
]]
|
||||||
|
|
||||||
---[[
|
---[[
|
||||||
Serialize current parser state as JSON.
|
Generate an ltn12-compatible sink.
|
||||||
|
|
||||||
@class function
|
@class function
|
||||||
@sort 4
|
@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
|
@name parser.stringify
|
||||||
@param pretty A boolean value indicating whether the resulting JSON should be pretty printed.
|
@param pretty A boolean value indicating whether the resulting JSON should be pretty printed.
|
||||||
@return Returns the serialized JSON data of this parser instance.
|
@return Returns the serialized JSON data of this parser instance.
|
||||||
|
|
Loading…
Reference in a new issue