* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include <errno.h>
+
#include <lualib.h>
#include <lauxlib.h>
#include <murphy/core/lua-bindings/murphy.h>
+static int stringify_table(lua_State *L, int index,
+ char **bufp, int *sizep, int *offsp);
+
static int plugin_exists(lua_State *L)
{
mrp_context_t *ctx;
}
+static int ensure_buffer(char **bufp, int *sizep, int *offsp, int len)
+{
+ int spc, size, diff;
+
+ spc = *sizep - *offsp;
+ if (spc < len) {
+ diff = len - spc;
+
+ if (diff > *sizep)
+ size = *sizep + diff;
+ else
+ size = *sizep * 2;
+
+ if (!mrp_realloc(*bufp, size))
+ return -1;
+ else
+ *sizep = size;
+ }
+
+ return 0;
+}
+
+
+static int push_buffer(char **bufp, int *sizep, int *offsp,
+ const char *str, int len)
+{
+ if (len <= 0)
+ len = strlen(str);
+
+ if (ensure_buffer(bufp, sizep, offsp, len + 1) == 0) {
+ strcpy(*bufp + *offsp, str);
+ *offsp += len;
+
+ return 0;
+ }
+ else
+ return -1;
+}
+
+
+static int stringify_string(lua_State *L, int index,
+ char **bufp, int *sizep, int *offsp)
+{
+ const char *str;
+ size_t size;
+ int len;
+
+ str = lua_tolstring(L, index, &size);
+ len = (int)size;
+
+ if (ensure_buffer(bufp, sizep, offsp, len + 3) < 0)
+ return -1;
+
+ snprintf(*bufp + *offsp, len + 3, "'%s'", str);
+ *offsp += len + 2;
+
+ return 0;
+}
+
+
+static int stringify_number(lua_State *L, int index,
+ char **bufp, int *sizep, int *offsp)
+{
+ char num[64];
+ double d;
+ int i, len;
+
+ if ((d = lua_tonumber(L, index)) == 1.0 * (i = lua_tointeger(L, index)))
+ len = snprintf(num, sizeof(num), "%d", i);
+ else
+ len = snprintf(num, sizeof(num), "%f", d);
+
+ return push_buffer(bufp, sizep, offsp, num, len);
+}
+
+
+static int stringify_boolean(lua_State *L, int index,
+ char **bufp, int *sizep, int *offsp)
+{
+ const char *bln;
+ int len;
+
+ if (lua_toboolean(L, index)) {
+ bln = "true";
+ len = 4;
+ }
+ else {
+ bln = "false";
+ len = 5;
+ }
+
+ return push_buffer(bufp, sizep, offsp, bln, len);
+}
+
+
+static int stringify_object(lua_State *L, int index,
+ char **bufp, int *sizep, int *offsp)
+{
+ switch (lua_type(L, index)) {
+ case LUA_TSTRING: return stringify_string(L, index, bufp, sizep, offsp);
+ case LUA_TNUMBER: return stringify_number(L, index, bufp, sizep, offsp);
+ case LUA_TBOOLEAN: return stringify_boolean(L, index, bufp, sizep, offsp);
+ case LUA_TTABLE: return stringify_table(L, index, bufp, sizep, offsp);
+ default:
+ errno = EINVAL;
+ }
+
+ return -1;
+}
+
+
+static int stringify_table(lua_State *L, int index,
+ char **bufp, int *sizep, int *offsp)
+{
+ const char *sep, *p;
+ char key[256];
+ int arr;
+ int i, d, idx, len;
+
+ arr = TRUE;
+
+ lua_pushnil(L);
+
+ /*
+ * check what the table should be converted to (array or dictionary)
+ */
+ idx = -1;
+ while (arr && lua_next(L, index - 1)) {
+ switch (lua_type(L, -2)) {
+ case LUA_TBOOLEAN:
+ case LUA_TTABLE:
+ default:
+ invalid:
+ lua_pop(L, 3);
+ return -1;
+
+ case LUA_TNUMBER:
+ d = lua_tonumber(L, -2);
+ i = lua_tointeger(L, -2);
+
+ if (d != 1.0 * i || (idx >= 0 && i != idx + 1))
+ goto invalid;
+ else
+ idx = i;
+ break;
+
+ case LUA_TSTRING:
+ lua_pop(L, 1);
+ arr = FALSE;
+ break;
+ }
+
+ lua_pop(L, 1);
+ }
+
+
+ /*
+ * convert either to an array or a dictionary
+ */
+
+ if (push_buffer(bufp, sizep, offsp, arr ? "[" : "{", 1))
+ return -1;
+
+ sep = "";
+ lua_pushnil(L);
+ while (lua_next(L, index - 1)) {
+ if (!arr) {
+ len = snprintf(key, sizeof(key), "%s'%s':", sep,
+ lua_tostring(L, -2));
+ p = key;
+ }
+ else {
+ p = (char *)sep;
+ len = strlen(sep);
+ }
+
+ if (push_buffer(bufp, sizep, offsp, p, len) < 0)
+ return -1;
+
+ if (stringify_object(L, -1, bufp, sizep, offsp) < 0) {
+ lua_pop(L, 3);
+ return -1;
+ }
+
+ lua_pop(L, 1);
+ sep = ",";
+ }
+
+ if (push_buffer(bufp, sizep, offsp, arr ? "]" : "}", 1) < 0)
+ return -1;
+ else
+ return 0;
+}
+
+
static int load(lua_State *L, int may_fail)
{
mrp_context_t *ctx;
const char *instance, *argerr;
mrp_plugin_arg_t args[256];
int narg, n, type, t, success;
+ char *json;
+ int size, offs;
ctx = mrp_lua_check_murphy_context(L, 1);
n = lua_gettop(L);
args[narg].str = mrp_strdup(lua_toboolean(L, -1) ?
"true" : "false");
break;
+ case LUA_TTABLE:
+ json = NULL;
+ size = 0;
+ offs = 0;
+ if (stringify_table(L, -1, &json, &size, &offs) == 0)
+ args[narg].str = json;
+ else {
+ argerr = "failed to json-stringify Lua table";
+ goto arg_error;
+ }
+ break;
default:
argerr = "invalid argument table value";
goto arg_error;