From 5548c75e5507da6a0f9fb6a45a07a5cc6edd9393 Mon Sep 17 00:00:00 2001 From: wm4 Date: Sun, 19 Oct 2014 05:27:35 +0200 Subject: lua: expose JSON parser The JSON parser was introduced for the IPC protocol, but I guess it's useful here too. The motivation for this commit is the same as with 8e4fa5fc (again). --- DOCS/man/lua.rst | 14 ++++++++++++++ misc/json.c | 5 +++++ misc/json.h | 1 + player/lua.c | 26 ++++++++++++++++++++++++++ 4 files changed, 46 insertions(+) diff --git a/DOCS/man/lua.rst b/DOCS/man/lua.rst index c49d2c388c..2eddbb8f2f 100644 --- a/DOCS/man/lua.rst +++ b/DOCS/man/lua.rst @@ -593,6 +593,20 @@ strictly part of the guaranteed API. In all cases, ``mp.resume_all()`` is implicitly called. +``utils.parse_json(str [, trail])`` + Parses the given string argument as JSON, and returns it as a Lua table. On + error, returns ``nil, error``. (Currently, ``error`` is just a string + reading ``error``, because there is no fine-grained error reporting of any + kind.) + + The returned value uses similar conventions as ``mp.get_property_native()`` + to distinguish empty objects and arrays. + + If the ``trail`` parameter is ``true`` (or any value equal to ``true``), + then trailing non-whitespace text is tolerated by the function, and the + trailing text is returned as 3rd return value. (The 3rd return value is + always there, but with ``trail`` set, no error is raised.) + Events ------ diff --git a/misc/json.c b/misc/json.c index 489f087987..b301296ebe 100644 --- a/misc/json.c +++ b/misc/json.c @@ -70,6 +70,11 @@ static void eat_ws(char **src) } } +void json_skip_whitespace(char **src) +{ + eat_ws(src); +} + static int read_str(void *ta_parent, struct mpv_node *dst, char **src) { if (!eat_c(src, '"')) diff --git a/misc/json.h b/misc/json.h index e8551fe2a7..f5ad4cf258 100644 --- a/misc/json.h +++ b/misc/json.h @@ -22,6 +22,7 @@ #include "libmpv/client.h" int json_parse(void *ta_parent, struct mpv_node *dst, char **src, int max_depth); +void json_skip_whitespace(char **src); int json_write(char **s, struct mpv_node *src); #endif diff --git a/player/lua.c b/player/lua.c index b565dedfe2..306f3a66f5 100644 --- a/player/lua.c +++ b/player/lua.c @@ -40,6 +40,7 @@ #include "input/input.h" #include "options/path.h" #include "misc/bstr.h" +#include "misc/json.h" #include "osdep/timer.h" #include "osdep/threads.h" #include "stream/stream.h" @@ -1290,6 +1291,30 @@ done: } #endif +static int script_parse_json(lua_State *L) +{ + void *tmp = mp_lua_PITA(L); + char *text = talloc_strdup(tmp, luaL_checkstring(L, 1)); + bool trail = lua_toboolean(L, 2); + bool ok = false; + struct mpv_node node; + if (json_parse(tmp, &node, &text, 32) >= 0) { + json_skip_whitespace(&text); + ok = !text[0] || !trail; + } + if (ok) { + if (!pushnode(L, &node, 64)) + luaL_error(L, "stack overflow"); + lua_pushnil(L); + } else { + lua_pushnil(L); + lua_pushstring(L, "error"); + } + lua_pushstring(L, text); + talloc_free_children(tmp); + return 3; +} + #define FN_ENTRY(name) {#name, script_ ## name} struct fn_entry { const char *name; @@ -1339,6 +1364,7 @@ static const struct fn_entry utils_fns[] = { #if HAVE_POSIX_SPAWN FN_ENTRY(subprocess), #endif + FN_ENTRY(parse_json), {0} }; -- cgit v1.2.3