14bf54857SBaptiste Daroussin /* Copyright (c) 2014, Vsevolod Stakhov
24bf54857SBaptiste Daroussin * All rights reserved.
34bf54857SBaptiste Daroussin *
44bf54857SBaptiste Daroussin * Redistribution and use in source and binary forms, with or without
54bf54857SBaptiste Daroussin * modification, are permitted provided that the following conditions are met:
64bf54857SBaptiste Daroussin * * Redistributions of source code must retain the above copyright
74bf54857SBaptiste Daroussin * notice, this list of conditions and the following disclaimer.
84bf54857SBaptiste Daroussin * * Redistributions in binary form must reproduce the above copyright
94bf54857SBaptiste Daroussin * notice, this list of conditions and the following disclaimer in the
104bf54857SBaptiste Daroussin * documentation and/or other materials provided with the distribution.
114bf54857SBaptiste Daroussin *
124bf54857SBaptiste Daroussin * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY
134bf54857SBaptiste Daroussin * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
144bf54857SBaptiste Daroussin * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
154bf54857SBaptiste Daroussin * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY
164bf54857SBaptiste Daroussin * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
174bf54857SBaptiste Daroussin * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
184bf54857SBaptiste Daroussin * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
194bf54857SBaptiste Daroussin * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
204bf54857SBaptiste Daroussin * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
214bf54857SBaptiste Daroussin * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
224bf54857SBaptiste Daroussin */
234bf54857SBaptiste Daroussin
244bf54857SBaptiste Daroussin /**
254bf54857SBaptiste Daroussin * @file lua ucl bindings
264bf54857SBaptiste Daroussin */
274bf54857SBaptiste Daroussin
284bf54857SBaptiste Daroussin #include "ucl.h"
294bf54857SBaptiste Daroussin #include "ucl_internal.h"
304bf54857SBaptiste Daroussin #include "lua_ucl.h"
314bf54857SBaptiste Daroussin #include <strings.h>
324bf54857SBaptiste Daroussin
334bf54857SBaptiste Daroussin /***
344bf54857SBaptiste Daroussin * @module ucl
354bf54857SBaptiste Daroussin * This lua module allows to parse objects from strings and to store data into
364bf54857SBaptiste Daroussin * ucl objects. It uses `libucl` C library to parse and manipulate with ucl objects.
374bf54857SBaptiste Daroussin * @example
384bf54857SBaptiste Daroussin local ucl = require("ucl")
394bf54857SBaptiste Daroussin
404bf54857SBaptiste Daroussin local parser = ucl.parser()
414bf54857SBaptiste Daroussin local res,err = parser:parse_string('{key=value}')
424bf54857SBaptiste Daroussin
434bf54857SBaptiste Daroussin if not res then
444bf54857SBaptiste Daroussin print('parser error: ' .. err)
454bf54857SBaptiste Daroussin else
464bf54857SBaptiste Daroussin local obj = parser:get_object()
474bf54857SBaptiste Daroussin local got = ucl.to_format(obj, 'json')
484bf54857SBaptiste Daroussin endif
494bf54857SBaptiste Daroussin
504bf54857SBaptiste Daroussin local table = {
514bf54857SBaptiste Daroussin str = 'value',
524bf54857SBaptiste Daroussin num = 100500,
534bf54857SBaptiste Daroussin null = ucl.null,
544bf54857SBaptiste Daroussin func = function ()
554bf54857SBaptiste Daroussin return 'huh'
564bf54857SBaptiste Daroussin end
574bf54857SBaptiste Daroussin }
584bf54857SBaptiste Daroussin
594bf54857SBaptiste Daroussin print(ucl.to_format(table, 'ucl'))
604bf54857SBaptiste Daroussin -- Output:
614bf54857SBaptiste Daroussin --[[
624bf54857SBaptiste Daroussin num = 100500;
634bf54857SBaptiste Daroussin str = "value";
644bf54857SBaptiste Daroussin null = null;
654bf54857SBaptiste Daroussin func = "huh";
664bf54857SBaptiste Daroussin --]]
674bf54857SBaptiste Daroussin */
684bf54857SBaptiste Daroussin
694bf54857SBaptiste Daroussin #define PARSER_META "ucl.parser.meta"
704bf54857SBaptiste Daroussin #define EMITTER_META "ucl.emitter.meta"
71*a0409676SBaptiste Daroussin #define NULL_META "ucl.null.meta"
7239ee7a7aSBaptiste Daroussin #define OBJECT_META "ucl.object.meta"
73*a0409676SBaptiste Daroussin #define UCL_OBJECT_TYPE_META "ucl.type.object"
74*a0409676SBaptiste Daroussin #define UCL_ARRAY_TYPE_META "ucl.type.array"
75*a0409676SBaptiste Daroussin #define UCL_IMPL_ARRAY_TYPE_META "ucl.type.impl_array"
764bf54857SBaptiste Daroussin
77*a0409676SBaptiste Daroussin static int ucl_object_lua_push_array (lua_State *L, const ucl_object_t *obj, int flags);
78*a0409676SBaptiste Daroussin static int ucl_object_lua_push_scalar (lua_State *L, const ucl_object_t *obj, int flags);
79*a0409676SBaptiste Daroussin static int ucl_object_push_lua_common (lua_State *L, const ucl_object_t *obj, int flags);
80*a0409676SBaptiste Daroussin static ucl_object_t* ucl_object_lua_fromtable (lua_State *L, int idx, ucl_string_flags_t flags);
81*a0409676SBaptiste Daroussin static ucl_object_t* ucl_object_lua_fromelt (lua_State *L, int idx, ucl_string_flags_t flags);
824bf54857SBaptiste Daroussin
834bf54857SBaptiste Daroussin static void *ucl_null;
844bf54857SBaptiste Daroussin
85*a0409676SBaptiste Daroussin
86*a0409676SBaptiste Daroussin enum lua_ucl_push_flags {
87*a0409676SBaptiste Daroussin LUA_UCL_DEFAULT_FLAGS = 0,
88*a0409676SBaptiste Daroussin LUA_UCL_ALLOW_ARRAY = (1u << 0u),
89*a0409676SBaptiste Daroussin LUA_UCL_CONVERT_NIL = (1u << 1u),
90*a0409676SBaptiste Daroussin };
91*a0409676SBaptiste Daroussin
924bf54857SBaptiste Daroussin /**
934bf54857SBaptiste Daroussin * Push a single element of an object to lua
944bf54857SBaptiste Daroussin * @param L
954bf54857SBaptiste Daroussin * @param key
964bf54857SBaptiste Daroussin * @param obj
974bf54857SBaptiste Daroussin */
984bf54857SBaptiste Daroussin static void
ucl_object_lua_push_element(lua_State * L,const char * key,const ucl_object_t * obj,int flags)994bf54857SBaptiste Daroussin ucl_object_lua_push_element (lua_State *L, const char *key,
100*a0409676SBaptiste Daroussin const ucl_object_t *obj, int flags)
1014bf54857SBaptiste Daroussin {
1024bf54857SBaptiste Daroussin lua_pushstring (L, key);
103*a0409676SBaptiste Daroussin ucl_object_push_lua_common (L, obj, flags|LUA_UCL_ALLOW_ARRAY);
1044bf54857SBaptiste Daroussin lua_settable (L, -3);
1054bf54857SBaptiste Daroussin }
1064bf54857SBaptiste Daroussin
1074bf54857SBaptiste Daroussin static void
lua_ucl_userdata_dtor(void * ud)1084bf54857SBaptiste Daroussin lua_ucl_userdata_dtor (void *ud)
1094bf54857SBaptiste Daroussin {
1104bf54857SBaptiste Daroussin struct ucl_lua_funcdata *fd = (struct ucl_lua_funcdata *)ud;
1114bf54857SBaptiste Daroussin
1124bf54857SBaptiste Daroussin luaL_unref (fd->L, LUA_REGISTRYINDEX, fd->idx);
1134bf54857SBaptiste Daroussin if (fd->ret != NULL) {
1144bf54857SBaptiste Daroussin free (fd->ret);
1154bf54857SBaptiste Daroussin }
1164bf54857SBaptiste Daroussin free (fd);
1174bf54857SBaptiste Daroussin }
1184bf54857SBaptiste Daroussin
1194bf54857SBaptiste Daroussin static const char *
lua_ucl_userdata_emitter(void * ud)1204bf54857SBaptiste Daroussin lua_ucl_userdata_emitter (void *ud)
1214bf54857SBaptiste Daroussin {
1224bf54857SBaptiste Daroussin struct ucl_lua_funcdata *fd = (struct ucl_lua_funcdata *)ud;
1234bf54857SBaptiste Daroussin const char *out = "";
1244bf54857SBaptiste Daroussin
1254bf54857SBaptiste Daroussin lua_rawgeti (fd->L, LUA_REGISTRYINDEX, fd->idx);
1264bf54857SBaptiste Daroussin
1274bf54857SBaptiste Daroussin lua_pcall (fd->L, 0, 1, 0);
1284bf54857SBaptiste Daroussin out = lua_tostring (fd->L, -1);
1294bf54857SBaptiste Daroussin
1304bf54857SBaptiste Daroussin if (out != NULL) {
1314bf54857SBaptiste Daroussin /* We need to store temporary string in a more appropriate place */
1324bf54857SBaptiste Daroussin if (fd->ret) {
1334bf54857SBaptiste Daroussin free (fd->ret);
1344bf54857SBaptiste Daroussin }
1354bf54857SBaptiste Daroussin fd->ret = strdup (out);
1364bf54857SBaptiste Daroussin }
1374bf54857SBaptiste Daroussin
1384bf54857SBaptiste Daroussin lua_settop (fd->L, 0);
1394bf54857SBaptiste Daroussin
1404bf54857SBaptiste Daroussin return fd->ret;
1414bf54857SBaptiste Daroussin }
1424bf54857SBaptiste Daroussin
1434bf54857SBaptiste Daroussin /**
1444bf54857SBaptiste Daroussin * Push a single object to lua
1454bf54857SBaptiste Daroussin * @param L
1464bf54857SBaptiste Daroussin * @param obj
1474bf54857SBaptiste Daroussin * @return
1484bf54857SBaptiste Daroussin */
1494bf54857SBaptiste Daroussin static int
ucl_object_lua_push_object(lua_State * L,const ucl_object_t * obj,int flags)1504bf54857SBaptiste Daroussin ucl_object_lua_push_object (lua_State *L, const ucl_object_t *obj,
151*a0409676SBaptiste Daroussin int flags)
1524bf54857SBaptiste Daroussin {
1534bf54857SBaptiste Daroussin const ucl_object_t *cur;
1544bf54857SBaptiste Daroussin ucl_object_iter_t it = NULL;
1554bf54857SBaptiste Daroussin
156*a0409676SBaptiste Daroussin if ((flags & LUA_UCL_ALLOW_ARRAY) && obj->next != NULL) {
1574bf54857SBaptiste Daroussin /* Actually we need to push this as an array */
158*a0409676SBaptiste Daroussin return ucl_object_lua_push_array (L, obj, flags);
1594bf54857SBaptiste Daroussin }
1604bf54857SBaptiste Daroussin
161*a0409676SBaptiste Daroussin lua_createtable (L, 0, obj->len);
1624bf54857SBaptiste Daroussin it = NULL;
1634bf54857SBaptiste Daroussin
164d9f0ce31SBaptiste Daroussin while ((cur = ucl_object_iterate (obj, &it, true)) != NULL) {
165*a0409676SBaptiste Daroussin ucl_object_lua_push_element (L, ucl_object_key (cur), cur, flags);
1664bf54857SBaptiste Daroussin }
1674bf54857SBaptiste Daroussin
168*a0409676SBaptiste Daroussin luaL_getmetatable (L, UCL_OBJECT_TYPE_META);
169*a0409676SBaptiste Daroussin lua_setmetatable (L, -2);
170*a0409676SBaptiste Daroussin
1714bf54857SBaptiste Daroussin return 1;
1724bf54857SBaptiste Daroussin }
1734bf54857SBaptiste Daroussin
1744bf54857SBaptiste Daroussin /**
1754bf54857SBaptiste Daroussin * Push an array to lua as table indexed by integers
1764bf54857SBaptiste Daroussin * @param L
1774bf54857SBaptiste Daroussin * @param obj
1784bf54857SBaptiste Daroussin * @return
1794bf54857SBaptiste Daroussin */
1804bf54857SBaptiste Daroussin static int
ucl_object_lua_push_array(lua_State * L,const ucl_object_t * obj,int flags)181*a0409676SBaptiste Daroussin ucl_object_lua_push_array (lua_State *L, const ucl_object_t *obj, int flags)
1824bf54857SBaptiste Daroussin {
1834bf54857SBaptiste Daroussin const ucl_object_t *cur;
18439ee7a7aSBaptiste Daroussin ucl_object_iter_t it;
1854bf54857SBaptiste Daroussin int i = 1, nelt = 0;
1864bf54857SBaptiste Daroussin
18739ee7a7aSBaptiste Daroussin if (obj->type == UCL_ARRAY) {
18839ee7a7aSBaptiste Daroussin nelt = obj->len;
18939ee7a7aSBaptiste Daroussin it = ucl_object_iterate_new (obj);
19039ee7a7aSBaptiste Daroussin lua_createtable (L, nelt, 0);
19139ee7a7aSBaptiste Daroussin
19239ee7a7aSBaptiste Daroussin while ((cur = ucl_object_iterate_safe (it, true))) {
193*a0409676SBaptiste Daroussin ucl_object_push_lua (L, cur, (flags & ~LUA_UCL_ALLOW_ARRAY));
19439ee7a7aSBaptiste Daroussin lua_rawseti (L, -2, i);
19539ee7a7aSBaptiste Daroussin i ++;
19639ee7a7aSBaptiste Daroussin }
19711dd9ed6SBaptiste Daroussin
198*a0409676SBaptiste Daroussin luaL_getmetatable (L, UCL_ARRAY_TYPE_META);
199*a0409676SBaptiste Daroussin lua_setmetatable (L, -2);
200*a0409676SBaptiste Daroussin
20111dd9ed6SBaptiste Daroussin ucl_object_iterate_free (it);
20239ee7a7aSBaptiste Daroussin }
20339ee7a7aSBaptiste Daroussin else {
2044bf54857SBaptiste Daroussin /* Optimize allocation by preallocation of table */
2054bf54857SBaptiste Daroussin LL_FOREACH (obj, cur) {
2064bf54857SBaptiste Daroussin nelt ++;
2074bf54857SBaptiste Daroussin }
2084bf54857SBaptiste Daroussin
2094bf54857SBaptiste Daroussin lua_createtable (L, nelt, 0);
2104bf54857SBaptiste Daroussin
2114bf54857SBaptiste Daroussin LL_FOREACH (obj, cur) {
212*a0409676SBaptiste Daroussin ucl_object_push_lua (L, cur, (flags & ~LUA_UCL_ALLOW_ARRAY));
2134bf54857SBaptiste Daroussin lua_rawseti (L, -2, i);
2144bf54857SBaptiste Daroussin i ++;
2154bf54857SBaptiste Daroussin }
216*a0409676SBaptiste Daroussin
217*a0409676SBaptiste Daroussin luaL_getmetatable (L, UCL_IMPL_ARRAY_TYPE_META);
218*a0409676SBaptiste Daroussin lua_setmetatable (L, -2);
21939ee7a7aSBaptiste Daroussin }
2204bf54857SBaptiste Daroussin
2214bf54857SBaptiste Daroussin return 1;
2224bf54857SBaptiste Daroussin }
2234bf54857SBaptiste Daroussin
2244bf54857SBaptiste Daroussin /**
2254bf54857SBaptiste Daroussin * Push a simple object to lua depending on its actual type
2264bf54857SBaptiste Daroussin */
2274bf54857SBaptiste Daroussin static int
ucl_object_lua_push_scalar(lua_State * L,const ucl_object_t * obj,int flags)2284bf54857SBaptiste Daroussin ucl_object_lua_push_scalar (lua_State *L, const ucl_object_t *obj,
229*a0409676SBaptiste Daroussin int flags)
2304bf54857SBaptiste Daroussin {
2314bf54857SBaptiste Daroussin struct ucl_lua_funcdata *fd;
2324bf54857SBaptiste Daroussin
233*a0409676SBaptiste Daroussin if ((flags & LUA_UCL_ALLOW_ARRAY) && obj->next != NULL) {
2344bf54857SBaptiste Daroussin /* Actually we need to push this as an array */
235*a0409676SBaptiste Daroussin return ucl_object_lua_push_array (L, obj, flags);
2364bf54857SBaptiste Daroussin }
2374bf54857SBaptiste Daroussin
2384bf54857SBaptiste Daroussin switch (obj->type) {
2394bf54857SBaptiste Daroussin case UCL_BOOLEAN:
2404bf54857SBaptiste Daroussin lua_pushboolean (L, ucl_obj_toboolean (obj));
2414bf54857SBaptiste Daroussin break;
2424bf54857SBaptiste Daroussin case UCL_STRING:
2434bf54857SBaptiste Daroussin lua_pushstring (L, ucl_obj_tostring (obj));
2444bf54857SBaptiste Daroussin break;
2454bf54857SBaptiste Daroussin case UCL_INT:
2464bf54857SBaptiste Daroussin #if LUA_VERSION_NUM >= 501
2474bf54857SBaptiste Daroussin lua_pushinteger (L, ucl_obj_toint (obj));
2484bf54857SBaptiste Daroussin #else
2494bf54857SBaptiste Daroussin lua_pushnumber (L, ucl_obj_toint (obj));
2504bf54857SBaptiste Daroussin #endif
2514bf54857SBaptiste Daroussin break;
2524bf54857SBaptiste Daroussin case UCL_FLOAT:
2534bf54857SBaptiste Daroussin case UCL_TIME:
2544bf54857SBaptiste Daroussin lua_pushnumber (L, ucl_obj_todouble (obj));
2554bf54857SBaptiste Daroussin break;
2564bf54857SBaptiste Daroussin case UCL_NULL:
257*a0409676SBaptiste Daroussin if (flags & LUA_UCL_CONVERT_NIL) {
258*a0409676SBaptiste Daroussin lua_pushboolean (L, false);
259*a0409676SBaptiste Daroussin }
260*a0409676SBaptiste Daroussin else {
2614bf54857SBaptiste Daroussin lua_getfield (L, LUA_REGISTRYINDEX, "ucl.null");
262*a0409676SBaptiste Daroussin }
2634bf54857SBaptiste Daroussin break;
2644bf54857SBaptiste Daroussin case UCL_USERDATA:
2654bf54857SBaptiste Daroussin fd = (struct ucl_lua_funcdata *)obj->value.ud;
2664bf54857SBaptiste Daroussin lua_rawgeti (L, LUA_REGISTRYINDEX, fd->idx);
2674bf54857SBaptiste Daroussin break;
2684bf54857SBaptiste Daroussin default:
2694bf54857SBaptiste Daroussin lua_pushnil (L);
2704bf54857SBaptiste Daroussin break;
2714bf54857SBaptiste Daroussin }
2724bf54857SBaptiste Daroussin
2734bf54857SBaptiste Daroussin return 1;
2744bf54857SBaptiste Daroussin }
2754bf54857SBaptiste Daroussin
276*a0409676SBaptiste Daroussin static int
ucl_object_push_lua_common(lua_State * L,const ucl_object_t * obj,int flags)277*a0409676SBaptiste Daroussin ucl_object_push_lua_common (lua_State *L, const ucl_object_t *obj, int flags)
278*a0409676SBaptiste Daroussin {
279*a0409676SBaptiste Daroussin switch (obj->type) {
280*a0409676SBaptiste Daroussin case UCL_OBJECT:
281*a0409676SBaptiste Daroussin return ucl_object_lua_push_object (L, obj, flags);
282*a0409676SBaptiste Daroussin case UCL_ARRAY:
283*a0409676SBaptiste Daroussin return ucl_object_lua_push_array (L, obj, flags);
284*a0409676SBaptiste Daroussin default:
285*a0409676SBaptiste Daroussin return ucl_object_lua_push_scalar (L, obj, flags);
286*a0409676SBaptiste Daroussin }
287*a0409676SBaptiste Daroussin }
288*a0409676SBaptiste Daroussin
2894bf54857SBaptiste Daroussin /***
2904bf54857SBaptiste Daroussin * @function ucl_object_push_lua(L, obj, allow_array)
2914bf54857SBaptiste Daroussin * This is a `C` function to push `UCL` object as lua variable. This function
2924bf54857SBaptiste Daroussin * converts `obj` to lua representation using the following conversions:
2934bf54857SBaptiste Daroussin *
2944bf54857SBaptiste Daroussin * - *scalar* values are directly presented by lua objects
2954bf54857SBaptiste Daroussin * - *userdata* values are converted to lua function objects using `LUA_REGISTRYINDEX`,
2964bf54857SBaptiste Daroussin * this can be used to pass functions from lua to c and vice-versa
2974bf54857SBaptiste Daroussin * - *arrays* are converted to lua tables with numeric indicies suitable for `ipairs` iterations
2984bf54857SBaptiste Daroussin * - *objects* are converted to lua tables with string indicies
2994bf54857SBaptiste Daroussin * @param {lua_State} L lua state pointer
3004bf54857SBaptiste Daroussin * @param {ucl_object_t} obj object to push
3014bf54857SBaptiste Daroussin * @param {bool} allow_array expand implicit arrays (should be true for all but partial arrays)
3024bf54857SBaptiste Daroussin * @return {int} `1` if an object is pushed to lua
3034bf54857SBaptiste Daroussin */
3044bf54857SBaptiste Daroussin int
ucl_object_push_lua(lua_State * L,const ucl_object_t * obj,bool allow_array)3054bf54857SBaptiste Daroussin ucl_object_push_lua (lua_State *L, const ucl_object_t *obj, bool allow_array)
3064bf54857SBaptiste Daroussin {
307*a0409676SBaptiste Daroussin return ucl_object_push_lua_common (L, obj,
308*a0409676SBaptiste Daroussin allow_array ? LUA_UCL_ALLOW_ARRAY : LUA_UCL_DEFAULT_FLAGS);
3094bf54857SBaptiste Daroussin }
310*a0409676SBaptiste Daroussin
311*a0409676SBaptiste Daroussin int
ucl_object_push_lua_filter_nil(lua_State * L,const ucl_object_t * obj,bool allow_array)312*a0409676SBaptiste Daroussin ucl_object_push_lua_filter_nil (lua_State *L, const ucl_object_t *obj, bool allow_array)
313*a0409676SBaptiste Daroussin {
314*a0409676SBaptiste Daroussin return ucl_object_push_lua_common (L, obj,
315*a0409676SBaptiste Daroussin allow_array ? (LUA_UCL_ALLOW_ARRAY|LUA_UCL_CONVERT_NIL) :
316*a0409676SBaptiste Daroussin (LUA_UCL_DEFAULT_FLAGS|LUA_UCL_CONVERT_NIL));
3174bf54857SBaptiste Daroussin }
3184bf54857SBaptiste Daroussin
3194bf54857SBaptiste Daroussin /**
3204bf54857SBaptiste Daroussin * Parse lua table into object top
3214bf54857SBaptiste Daroussin * @param L
3224bf54857SBaptiste Daroussin * @param top
3234bf54857SBaptiste Daroussin * @param idx
3244bf54857SBaptiste Daroussin */
3254bf54857SBaptiste Daroussin static ucl_object_t *
ucl_object_lua_fromtable(lua_State * L,int idx,ucl_string_flags_t flags)326*a0409676SBaptiste Daroussin ucl_object_lua_fromtable (lua_State *L, int idx, ucl_string_flags_t flags)
3274bf54857SBaptiste Daroussin {
328*a0409676SBaptiste Daroussin ucl_object_t *obj, *top = NULL, *cur;
3294bf54857SBaptiste Daroussin size_t keylen;
3304bf54857SBaptiste Daroussin const char *k;
331*a0409676SBaptiste Daroussin bool is_array = true, is_implicit = false, found_mt = false;
332*a0409676SBaptiste Daroussin size_t max = 0, nelts = 0;
3334bf54857SBaptiste Daroussin
3344bf54857SBaptiste Daroussin if (idx < 0) {
3354bf54857SBaptiste Daroussin /* For negative indicies we want to invert them */
3364bf54857SBaptiste Daroussin idx = lua_gettop (L) + idx + 1;
3374bf54857SBaptiste Daroussin }
338*a0409676SBaptiste Daroussin
339*a0409676SBaptiste Daroussin /* First, we check from metatable */
340*a0409676SBaptiste Daroussin if (luaL_getmetafield (L, idx, "class") != 0) {
341*a0409676SBaptiste Daroussin
342*a0409676SBaptiste Daroussin if (lua_type (L, -1) == LUA_TSTRING) {
343*a0409676SBaptiste Daroussin const char *classname = lua_tostring (L, -1);
344*a0409676SBaptiste Daroussin
345*a0409676SBaptiste Daroussin if (strcmp (classname, UCL_OBJECT_TYPE_META) == 0) {
346*a0409676SBaptiste Daroussin is_array = false;
347*a0409676SBaptiste Daroussin found_mt = true;
348*a0409676SBaptiste Daroussin } else if (strcmp (classname, UCL_ARRAY_TYPE_META) == 0) {
349*a0409676SBaptiste Daroussin is_array = true;
350*a0409676SBaptiste Daroussin found_mt = true;
351*a0409676SBaptiste Daroussin #if LUA_VERSION_NUM >= 502
352*a0409676SBaptiste Daroussin max = lua_rawlen (L, idx);
353*a0409676SBaptiste Daroussin #else
354*a0409676SBaptiste Daroussin max = lua_objlen (L, idx);
355*a0409676SBaptiste Daroussin #endif
356*a0409676SBaptiste Daroussin nelts = max;
357*a0409676SBaptiste Daroussin } else if (strcmp (classname, UCL_IMPL_ARRAY_TYPE_META) == 0) {
358*a0409676SBaptiste Daroussin is_array = true;
359*a0409676SBaptiste Daroussin is_implicit = true;
360*a0409676SBaptiste Daroussin found_mt = true;
361*a0409676SBaptiste Daroussin #if LUA_VERSION_NUM >= 502
362*a0409676SBaptiste Daroussin max = lua_rawlen (L, idx);
363*a0409676SBaptiste Daroussin #else
364*a0409676SBaptiste Daroussin max = lua_objlen (L, idx);
365*a0409676SBaptiste Daroussin #endif
366*a0409676SBaptiste Daroussin nelts = max;
367*a0409676SBaptiste Daroussin }
368*a0409676SBaptiste Daroussin }
369*a0409676SBaptiste Daroussin
370*a0409676SBaptiste Daroussin lua_pop (L, 1);
371*a0409676SBaptiste Daroussin }
372*a0409676SBaptiste Daroussin
373*a0409676SBaptiste Daroussin if (!found_mt) {
374*a0409676SBaptiste Daroussin /* Check for array (it is all inefficient) */
3754bf54857SBaptiste Daroussin lua_pushnil (L);
376*a0409676SBaptiste Daroussin
3774bf54857SBaptiste Daroussin while (lua_next (L, idx) != 0) {
378*a0409676SBaptiste Daroussin lua_pushvalue (L, -2);
379*a0409676SBaptiste Daroussin
380*a0409676SBaptiste Daroussin if (lua_type (L, -1) == LUA_TNUMBER) {
381*a0409676SBaptiste Daroussin double num = lua_tonumber (L, -1);
3824bf54857SBaptiste Daroussin if (num == (int) num) {
3834bf54857SBaptiste Daroussin if (num > max) {
3844bf54857SBaptiste Daroussin max = num;
3854bf54857SBaptiste Daroussin }
3864bf54857SBaptiste Daroussin }
3874bf54857SBaptiste Daroussin else {
3884bf54857SBaptiste Daroussin /* Keys are not integer */
3894bf54857SBaptiste Daroussin is_array = false;
3904bf54857SBaptiste Daroussin }
3914bf54857SBaptiste Daroussin }
3924bf54857SBaptiste Daroussin else {
3934bf54857SBaptiste Daroussin /* Keys are not numeric */
3944bf54857SBaptiste Daroussin is_array = false;
3954bf54857SBaptiste Daroussin }
396*a0409676SBaptiste Daroussin
397*a0409676SBaptiste Daroussin lua_pop (L, 2);
398*a0409676SBaptiste Daroussin nelts ++;
399*a0409676SBaptiste Daroussin }
4004bf54857SBaptiste Daroussin }
4014bf54857SBaptiste Daroussin
4024bf54857SBaptiste Daroussin /* Table iterate */
4034bf54857SBaptiste Daroussin if (is_array) {
4044bf54857SBaptiste Daroussin int i;
4054bf54857SBaptiste Daroussin
406*a0409676SBaptiste Daroussin if (!is_implicit) {
4074bf54857SBaptiste Daroussin top = ucl_object_typed_new (UCL_ARRAY);
408*a0409676SBaptiste Daroussin ucl_object_reserve (top, nelts);
409*a0409676SBaptiste Daroussin }
410*a0409676SBaptiste Daroussin else {
411*a0409676SBaptiste Daroussin top = NULL;
412*a0409676SBaptiste Daroussin }
413*a0409676SBaptiste Daroussin
4144bf54857SBaptiste Daroussin for (i = 1; i <= max; i ++) {
4154bf54857SBaptiste Daroussin lua_pushinteger (L, i);
4164bf54857SBaptiste Daroussin lua_gettable (L, idx);
417*a0409676SBaptiste Daroussin
418*a0409676SBaptiste Daroussin obj = ucl_object_lua_fromelt (L, lua_gettop (L), flags);
419*a0409676SBaptiste Daroussin
4204bf54857SBaptiste Daroussin if (obj != NULL) {
421*a0409676SBaptiste Daroussin if (is_implicit) {
422*a0409676SBaptiste Daroussin DL_APPEND (top, obj);
423*a0409676SBaptiste Daroussin }
424*a0409676SBaptiste Daroussin else {
4254bf54857SBaptiste Daroussin ucl_array_append (top, obj);
4264bf54857SBaptiste Daroussin }
427*a0409676SBaptiste Daroussin }
42839ee7a7aSBaptiste Daroussin lua_pop (L, 1);
4294bf54857SBaptiste Daroussin }
4304bf54857SBaptiste Daroussin }
4314bf54857SBaptiste Daroussin else {
4324bf54857SBaptiste Daroussin lua_pushnil (L);
4334bf54857SBaptiste Daroussin top = ucl_object_typed_new (UCL_OBJECT);
434*a0409676SBaptiste Daroussin ucl_object_reserve (top, nelts);
435*a0409676SBaptiste Daroussin
4364bf54857SBaptiste Daroussin while (lua_next (L, idx) != 0) {
4374bf54857SBaptiste Daroussin /* copy key to avoid modifications */
438*a0409676SBaptiste Daroussin lua_pushvalue (L, -2);
439*a0409676SBaptiste Daroussin k = lua_tolstring (L, -1, &keylen);
440*a0409676SBaptiste Daroussin obj = ucl_object_lua_fromelt (L, lua_gettop (L) - 1, flags);
4414bf54857SBaptiste Daroussin
4424bf54857SBaptiste Daroussin if (obj != NULL) {
4434bf54857SBaptiste Daroussin ucl_object_insert_key (top, obj, k, keylen, true);
444*a0409676SBaptiste Daroussin
445*a0409676SBaptiste Daroussin DL_FOREACH (obj, cur) {
446*a0409676SBaptiste Daroussin if (cur->keylen == 0) {
447*a0409676SBaptiste Daroussin cur->keylen = obj->keylen;
448*a0409676SBaptiste Daroussin cur->key = obj->key;
4494bf54857SBaptiste Daroussin }
450*a0409676SBaptiste Daroussin }
451*a0409676SBaptiste Daroussin }
452*a0409676SBaptiste Daroussin lua_pop (L, 2);
4534bf54857SBaptiste Daroussin }
4544bf54857SBaptiste Daroussin }
4554bf54857SBaptiste Daroussin
4564bf54857SBaptiste Daroussin return top;
4574bf54857SBaptiste Daroussin }
4584bf54857SBaptiste Daroussin
4594bf54857SBaptiste Daroussin /**
4604bf54857SBaptiste Daroussin * Get a single element from lua to object obj
4614bf54857SBaptiste Daroussin * @param L
4624bf54857SBaptiste Daroussin * @param obj
4634bf54857SBaptiste Daroussin * @param idx
4644bf54857SBaptiste Daroussin */
4654bf54857SBaptiste Daroussin static ucl_object_t *
ucl_object_lua_fromelt(lua_State * L,int idx,ucl_string_flags_t flags)466*a0409676SBaptiste Daroussin ucl_object_lua_fromelt (lua_State *L, int idx, ucl_string_flags_t flags)
4674bf54857SBaptiste Daroussin {
4684bf54857SBaptiste Daroussin int type;
4694bf54857SBaptiste Daroussin double num;
4704bf54857SBaptiste Daroussin ucl_object_t *obj = NULL;
4714bf54857SBaptiste Daroussin struct ucl_lua_funcdata *fd;
472*a0409676SBaptiste Daroussin const char *str;
473*a0409676SBaptiste Daroussin size_t sz;
4744bf54857SBaptiste Daroussin
4754bf54857SBaptiste Daroussin type = lua_type (L, idx);
4764bf54857SBaptiste Daroussin
4774bf54857SBaptiste Daroussin switch (type) {
4784bf54857SBaptiste Daroussin case LUA_TSTRING:
479*a0409676SBaptiste Daroussin str = lua_tolstring (L, idx, &sz);
480*a0409676SBaptiste Daroussin
481*a0409676SBaptiste Daroussin if (str) {
482*a0409676SBaptiste Daroussin obj = ucl_object_fromstring_common (str, sz, flags);
483*a0409676SBaptiste Daroussin }
484*a0409676SBaptiste Daroussin else {
485*a0409676SBaptiste Daroussin obj = ucl_object_typed_new (UCL_NULL);
486*a0409676SBaptiste Daroussin }
4874bf54857SBaptiste Daroussin break;
4884bf54857SBaptiste Daroussin case LUA_TNUMBER:
4894bf54857SBaptiste Daroussin num = lua_tonumber (L, idx);
4904bf54857SBaptiste Daroussin if (num == (int64_t)num) {
4914bf54857SBaptiste Daroussin obj = ucl_object_fromint (num);
4924bf54857SBaptiste Daroussin }
4934bf54857SBaptiste Daroussin else {
4944bf54857SBaptiste Daroussin obj = ucl_object_fromdouble (num);
4954bf54857SBaptiste Daroussin }
4964bf54857SBaptiste Daroussin break;
4974bf54857SBaptiste Daroussin case LUA_TBOOLEAN:
4984bf54857SBaptiste Daroussin obj = ucl_object_frombool (lua_toboolean (L, idx));
4994bf54857SBaptiste Daroussin break;
5004bf54857SBaptiste Daroussin case LUA_TUSERDATA:
5014bf54857SBaptiste Daroussin if (lua_topointer (L, idx) == ucl_null) {
5024bf54857SBaptiste Daroussin obj = ucl_object_typed_new (UCL_NULL);
5034bf54857SBaptiste Daroussin }
5044bf54857SBaptiste Daroussin break;
5054bf54857SBaptiste Daroussin case LUA_TTABLE:
5064bf54857SBaptiste Daroussin case LUA_TFUNCTION:
5074bf54857SBaptiste Daroussin case LUA_TTHREAD:
5084bf54857SBaptiste Daroussin if (luaL_getmetafield (L, idx, "__gen_ucl")) {
5094bf54857SBaptiste Daroussin if (lua_isfunction (L, -1)) {
5104bf54857SBaptiste Daroussin lua_settop (L, 3); /* gen, obj, func */
5114bf54857SBaptiste Daroussin lua_insert (L, 1); /* func, gen, obj */
5124bf54857SBaptiste Daroussin lua_insert (L, 2); /* func, obj, gen */
5134bf54857SBaptiste Daroussin lua_call(L, 2, 1);
514*a0409676SBaptiste Daroussin obj = ucl_object_lua_fromelt (L, 1, flags);
5154bf54857SBaptiste Daroussin }
5164bf54857SBaptiste Daroussin lua_pop (L, 2);
5174bf54857SBaptiste Daroussin }
5184bf54857SBaptiste Daroussin else {
5194bf54857SBaptiste Daroussin if (type == LUA_TTABLE) {
520*a0409676SBaptiste Daroussin obj = ucl_object_lua_fromtable (L, idx, flags);
5214bf54857SBaptiste Daroussin }
5224bf54857SBaptiste Daroussin else if (type == LUA_TFUNCTION) {
5234bf54857SBaptiste Daroussin fd = malloc (sizeof (*fd));
5244bf54857SBaptiste Daroussin if (fd != NULL) {
5254bf54857SBaptiste Daroussin lua_pushvalue (L, idx);
5264bf54857SBaptiste Daroussin fd->L = L;
5274bf54857SBaptiste Daroussin fd->ret = NULL;
5284bf54857SBaptiste Daroussin fd->idx = luaL_ref (L, LUA_REGISTRYINDEX);
5294bf54857SBaptiste Daroussin
5304bf54857SBaptiste Daroussin obj = ucl_object_new_userdata (lua_ucl_userdata_dtor,
531d9f0ce31SBaptiste Daroussin lua_ucl_userdata_emitter, (void *)fd);
5324bf54857SBaptiste Daroussin }
5334bf54857SBaptiste Daroussin }
5344bf54857SBaptiste Daroussin }
5354bf54857SBaptiste Daroussin break;
5364bf54857SBaptiste Daroussin }
5374bf54857SBaptiste Daroussin
5384bf54857SBaptiste Daroussin return obj;
5394bf54857SBaptiste Daroussin }
5404bf54857SBaptiste Daroussin
5414bf54857SBaptiste Daroussin /**
5424bf54857SBaptiste Daroussin * @function ucl_object_lua_import(L, idx)
5434bf54857SBaptiste Daroussin * Extracts ucl object from lua variable at `idx` position,
5444bf54857SBaptiste Daroussin * @see ucl_object_push_lua for conversion definitions
5454bf54857SBaptiste Daroussin * @param {lua_state} L lua state machine pointer
5464bf54857SBaptiste Daroussin * @param {int} idx index where the source variable is placed
5474bf54857SBaptiste Daroussin * @return {ucl_object_t} new ucl object extracted from lua variable. Reference count of this object is 1,
5484bf54857SBaptiste Daroussin * this object thus needs to be unref'ed after usage.
5494bf54857SBaptiste Daroussin */
5504bf54857SBaptiste Daroussin ucl_object_t *
ucl_object_lua_import(lua_State * L,int idx)5514bf54857SBaptiste Daroussin ucl_object_lua_import (lua_State *L, int idx)
5524bf54857SBaptiste Daroussin {
5534bf54857SBaptiste Daroussin ucl_object_t *obj;
5544bf54857SBaptiste Daroussin int t;
5554bf54857SBaptiste Daroussin
5564bf54857SBaptiste Daroussin t = lua_type (L, idx);
5574bf54857SBaptiste Daroussin switch (t) {
5584bf54857SBaptiste Daroussin case LUA_TTABLE:
559*a0409676SBaptiste Daroussin obj = ucl_object_lua_fromtable (L, idx, 0);
5604bf54857SBaptiste Daroussin break;
5614bf54857SBaptiste Daroussin default:
562*a0409676SBaptiste Daroussin obj = ucl_object_lua_fromelt (L, idx, 0);
563*a0409676SBaptiste Daroussin break;
564*a0409676SBaptiste Daroussin }
565*a0409676SBaptiste Daroussin
566*a0409676SBaptiste Daroussin return obj;
567*a0409676SBaptiste Daroussin }
568*a0409676SBaptiste Daroussin
569*a0409676SBaptiste Daroussin /**
570*a0409676SBaptiste Daroussin * @function ucl_object_lua_import_escape(L, idx)
571*a0409676SBaptiste Daroussin * Extracts ucl object from lua variable at `idx` position escaping JSON strings
572*a0409676SBaptiste Daroussin * @see ucl_object_push_lua for conversion definitions
573*a0409676SBaptiste Daroussin * @param {lua_state} L lua state machine pointer
574*a0409676SBaptiste Daroussin * @param {int} idx index where the source variable is placed
575*a0409676SBaptiste Daroussin * @return {ucl_object_t} new ucl object extracted from lua variable. Reference count of this object is 1,
576*a0409676SBaptiste Daroussin * this object thus needs to be unref'ed after usage.
577*a0409676SBaptiste Daroussin */
578*a0409676SBaptiste Daroussin ucl_object_t *
ucl_object_lua_import_escape(lua_State * L,int idx)579*a0409676SBaptiste Daroussin ucl_object_lua_import_escape (lua_State *L, int idx)
580*a0409676SBaptiste Daroussin {
581*a0409676SBaptiste Daroussin ucl_object_t *obj;
582*a0409676SBaptiste Daroussin int t;
583*a0409676SBaptiste Daroussin
584*a0409676SBaptiste Daroussin t = lua_type (L, idx);
585*a0409676SBaptiste Daroussin switch (t) {
586*a0409676SBaptiste Daroussin case LUA_TTABLE:
587*a0409676SBaptiste Daroussin obj = ucl_object_lua_fromtable (L, idx, UCL_STRING_RAW);
588*a0409676SBaptiste Daroussin break;
589*a0409676SBaptiste Daroussin default:
590*a0409676SBaptiste Daroussin obj = ucl_object_lua_fromelt (L, idx, UCL_STRING_RAW);
5914bf54857SBaptiste Daroussin break;
5924bf54857SBaptiste Daroussin }
5934bf54857SBaptiste Daroussin
5944bf54857SBaptiste Daroussin return obj;
5954bf54857SBaptiste Daroussin }
5964bf54857SBaptiste Daroussin
5974bf54857SBaptiste Daroussin static int
lua_ucl_to_string(lua_State * L,const ucl_object_t * obj,enum ucl_emitter type)59839ee7a7aSBaptiste Daroussin lua_ucl_to_string (lua_State *L, const ucl_object_t *obj, enum ucl_emitter type)
59939ee7a7aSBaptiste Daroussin {
60039ee7a7aSBaptiste Daroussin unsigned char *result;
60139ee7a7aSBaptiste Daroussin
60239ee7a7aSBaptiste Daroussin result = ucl_object_emit (obj, type);
60339ee7a7aSBaptiste Daroussin
60439ee7a7aSBaptiste Daroussin if (result != NULL) {
60539ee7a7aSBaptiste Daroussin lua_pushstring (L, (const char *)result);
60639ee7a7aSBaptiste Daroussin free (result);
60739ee7a7aSBaptiste Daroussin }
60839ee7a7aSBaptiste Daroussin else {
60939ee7a7aSBaptiste Daroussin lua_pushnil (L);
61039ee7a7aSBaptiste Daroussin }
61139ee7a7aSBaptiste Daroussin
61239ee7a7aSBaptiste Daroussin return 1;
61339ee7a7aSBaptiste Daroussin }
61439ee7a7aSBaptiste Daroussin
61539ee7a7aSBaptiste Daroussin static int
lua_ucl_parser_init(lua_State * L)6164bf54857SBaptiste Daroussin lua_ucl_parser_init (lua_State *L)
6174bf54857SBaptiste Daroussin {
6184bf54857SBaptiste Daroussin struct ucl_parser *parser, **pparser;
61911dd9ed6SBaptiste Daroussin int flags = UCL_PARSER_NO_FILEVARS;
6204bf54857SBaptiste Daroussin
6214bf54857SBaptiste Daroussin if (lua_gettop (L) >= 1) {
6224bf54857SBaptiste Daroussin flags = lua_tonumber (L, 1);
6234bf54857SBaptiste Daroussin }
6244bf54857SBaptiste Daroussin
6254bf54857SBaptiste Daroussin parser = ucl_parser_new (flags);
6264bf54857SBaptiste Daroussin if (parser == NULL) {
6274bf54857SBaptiste Daroussin lua_pushnil (L);
628*a0409676SBaptiste Daroussin return 1;
6294bf54857SBaptiste Daroussin }
6304bf54857SBaptiste Daroussin
6314bf54857SBaptiste Daroussin pparser = lua_newuserdata (L, sizeof (parser));
6324bf54857SBaptiste Daroussin *pparser = parser;
6334bf54857SBaptiste Daroussin luaL_getmetatable (L, PARSER_META);
6344bf54857SBaptiste Daroussin lua_setmetatable (L, -2);
6354bf54857SBaptiste Daroussin
6364bf54857SBaptiste Daroussin return 1;
6374bf54857SBaptiste Daroussin }
6384bf54857SBaptiste Daroussin
6394bf54857SBaptiste Daroussin static struct ucl_parser *
lua_ucl_parser_get(lua_State * L,int index)6404bf54857SBaptiste Daroussin lua_ucl_parser_get (lua_State *L, int index)
6414bf54857SBaptiste Daroussin {
6424bf54857SBaptiste Daroussin return *((struct ucl_parser **) luaL_checkudata(L, index, PARSER_META));
6434bf54857SBaptiste Daroussin }
6444bf54857SBaptiste Daroussin
64539ee7a7aSBaptiste Daroussin static ucl_object_t *
lua_ucl_object_get(lua_State * L,int index)64639ee7a7aSBaptiste Daroussin lua_ucl_object_get (lua_State *L, int index)
64739ee7a7aSBaptiste Daroussin {
64839ee7a7aSBaptiste Daroussin return *((ucl_object_t **) luaL_checkudata(L, index, OBJECT_META));
64939ee7a7aSBaptiste Daroussin }
65039ee7a7aSBaptiste Daroussin
651d9f0ce31SBaptiste Daroussin static void
lua_ucl_push_opaque(lua_State * L,ucl_object_t * obj)652d9f0ce31SBaptiste Daroussin lua_ucl_push_opaque (lua_State *L, ucl_object_t *obj)
653d9f0ce31SBaptiste Daroussin {
654d9f0ce31SBaptiste Daroussin ucl_object_t **pobj;
655d9f0ce31SBaptiste Daroussin
656d9f0ce31SBaptiste Daroussin pobj = lua_newuserdata (L, sizeof (*pobj));
657d9f0ce31SBaptiste Daroussin *pobj = obj;
658d9f0ce31SBaptiste Daroussin luaL_getmetatable (L, OBJECT_META);
659d9f0ce31SBaptiste Daroussin lua_setmetatable (L, -2);
660d9f0ce31SBaptiste Daroussin }
661d9f0ce31SBaptiste Daroussin
66211dd9ed6SBaptiste Daroussin static inline enum ucl_parse_type
lua_ucl_str_to_parse_type(const char * str)66311dd9ed6SBaptiste Daroussin lua_ucl_str_to_parse_type (const char *str)
66411dd9ed6SBaptiste Daroussin {
66511dd9ed6SBaptiste Daroussin enum ucl_parse_type type = UCL_PARSE_UCL;
66611dd9ed6SBaptiste Daroussin
66711dd9ed6SBaptiste Daroussin if (str != NULL) {
66811dd9ed6SBaptiste Daroussin if (strcasecmp (str, "msgpack") == 0) {
66911dd9ed6SBaptiste Daroussin type = UCL_PARSE_MSGPACK;
67011dd9ed6SBaptiste Daroussin }
67111dd9ed6SBaptiste Daroussin else if (strcasecmp (str, "sexp") == 0 ||
67211dd9ed6SBaptiste Daroussin strcasecmp (str, "csexp") == 0) {
67311dd9ed6SBaptiste Daroussin type = UCL_PARSE_CSEXP;
67411dd9ed6SBaptiste Daroussin }
67511dd9ed6SBaptiste Daroussin else if (strcasecmp (str, "auto") == 0) {
67611dd9ed6SBaptiste Daroussin type = UCL_PARSE_AUTO;
67711dd9ed6SBaptiste Daroussin }
67811dd9ed6SBaptiste Daroussin }
67911dd9ed6SBaptiste Daroussin
68011dd9ed6SBaptiste Daroussin return type;
68111dd9ed6SBaptiste Daroussin }
68211dd9ed6SBaptiste Daroussin
6834bf54857SBaptiste Daroussin /***
6844bf54857SBaptiste Daroussin * @method parser:parse_file(name)
6854bf54857SBaptiste Daroussin * Parse UCL object from file.
6864bf54857SBaptiste Daroussin * @param {string} name filename to parse
6874bf54857SBaptiste Daroussin * @return {bool[, string]} if res is `true` then file has been parsed successfully, otherwise an error string is also returned
6884bf54857SBaptiste Daroussin @example
6894bf54857SBaptiste Daroussin local parser = ucl.parser()
6904bf54857SBaptiste Daroussin local res,err = parser:parse_file('/some/file.conf')
6914bf54857SBaptiste Daroussin
6924bf54857SBaptiste Daroussin if not res then
6934bf54857SBaptiste Daroussin print('parser error: ' .. err)
6944bf54857SBaptiste Daroussin else
6954bf54857SBaptiste Daroussin -- Do something with object
6964bf54857SBaptiste Daroussin end
6974bf54857SBaptiste Daroussin */
6984bf54857SBaptiste Daroussin static int
lua_ucl_parser_parse_file(lua_State * L)6994bf54857SBaptiste Daroussin lua_ucl_parser_parse_file (lua_State *L)
7004bf54857SBaptiste Daroussin {
7014bf54857SBaptiste Daroussin struct ucl_parser *parser;
7024bf54857SBaptiste Daroussin const char *file;
7034bf54857SBaptiste Daroussin int ret = 2;
7044bf54857SBaptiste Daroussin
7054bf54857SBaptiste Daroussin parser = lua_ucl_parser_get (L, 1);
7064bf54857SBaptiste Daroussin file = luaL_checkstring (L, 2);
7074bf54857SBaptiste Daroussin
7084bf54857SBaptiste Daroussin if (parser != NULL && file != NULL) {
7094bf54857SBaptiste Daroussin if (ucl_parser_add_file (parser, file)) {
7104bf54857SBaptiste Daroussin lua_pushboolean (L, true);
7114bf54857SBaptiste Daroussin ret = 1;
7124bf54857SBaptiste Daroussin }
7134bf54857SBaptiste Daroussin else {
7144bf54857SBaptiste Daroussin lua_pushboolean (L, false);
7154bf54857SBaptiste Daroussin lua_pushstring (L, ucl_parser_get_error (parser));
7164bf54857SBaptiste Daroussin }
7174bf54857SBaptiste Daroussin }
7184bf54857SBaptiste Daroussin else {
7194bf54857SBaptiste Daroussin lua_pushboolean (L, false);
7204bf54857SBaptiste Daroussin lua_pushstring (L, "invalid arguments");
7214bf54857SBaptiste Daroussin }
7224bf54857SBaptiste Daroussin
7234bf54857SBaptiste Daroussin return ret;
7244bf54857SBaptiste Daroussin }
7254bf54857SBaptiste Daroussin
7264bf54857SBaptiste Daroussin /***
727*a0409676SBaptiste Daroussin * @method parser:register_variable(name, value)
728*a0409676SBaptiste Daroussin * Register parser variable
729*a0409676SBaptiste Daroussin * @param {string} name name of variable
730*a0409676SBaptiste Daroussin * @param {string} value value of variable
731*a0409676SBaptiste Daroussin * @return {bool} success
732*a0409676SBaptiste Daroussin @example
733*a0409676SBaptiste Daroussin local parser = ucl.parser()
734*a0409676SBaptiste Daroussin local res = parser:register_variable('CONFDIR', '/etc/foo')
735*a0409676SBaptiste Daroussin */
736*a0409676SBaptiste Daroussin static int
lua_ucl_parser_register_variable(lua_State * L)737*a0409676SBaptiste Daroussin lua_ucl_parser_register_variable (lua_State *L)
738*a0409676SBaptiste Daroussin {
739*a0409676SBaptiste Daroussin struct ucl_parser *parser;
740*a0409676SBaptiste Daroussin const char *name, *value;
741*a0409676SBaptiste Daroussin int ret = 2;
742*a0409676SBaptiste Daroussin
743*a0409676SBaptiste Daroussin parser = lua_ucl_parser_get (L, 1);
744*a0409676SBaptiste Daroussin name = luaL_checkstring (L, 2);
745*a0409676SBaptiste Daroussin value = luaL_checkstring (L, 3);
746*a0409676SBaptiste Daroussin
747*a0409676SBaptiste Daroussin if (parser != NULL && name != NULL && value != NULL) {
748*a0409676SBaptiste Daroussin ucl_parser_register_variable (parser, name, value);
749*a0409676SBaptiste Daroussin lua_pushboolean (L, true);
750*a0409676SBaptiste Daroussin ret = 1;
751*a0409676SBaptiste Daroussin }
752*a0409676SBaptiste Daroussin else {
753*a0409676SBaptiste Daroussin return luaL_error (L, "invalid arguments");
754*a0409676SBaptiste Daroussin }
755*a0409676SBaptiste Daroussin
756*a0409676SBaptiste Daroussin return ret;
757*a0409676SBaptiste Daroussin }
758*a0409676SBaptiste Daroussin
759*a0409676SBaptiste Daroussin /***
760*a0409676SBaptiste Daroussin * @method parser:register_variables(vars)
761*a0409676SBaptiste Daroussin * Register parser variables
762*a0409676SBaptiste Daroussin * @param {table} vars names/values of variables
763*a0409676SBaptiste Daroussin * @return {bool} success
764*a0409676SBaptiste Daroussin @example
765*a0409676SBaptiste Daroussin local parser = ucl.parser()
766*a0409676SBaptiste Daroussin local res = parser:register_variables({CONFDIR = '/etc/foo', VARDIR = '/var'})
767*a0409676SBaptiste Daroussin */
768*a0409676SBaptiste Daroussin static int
lua_ucl_parser_register_variables(lua_State * L)769*a0409676SBaptiste Daroussin lua_ucl_parser_register_variables (lua_State *L)
770*a0409676SBaptiste Daroussin {
771*a0409676SBaptiste Daroussin struct ucl_parser *parser;
772*a0409676SBaptiste Daroussin const char *name, *value;
773*a0409676SBaptiste Daroussin int ret = 2;
774*a0409676SBaptiste Daroussin
775*a0409676SBaptiste Daroussin parser = lua_ucl_parser_get (L, 1);
776*a0409676SBaptiste Daroussin
777*a0409676SBaptiste Daroussin if (parser != NULL && lua_type (L, 2) == LUA_TTABLE) {
778*a0409676SBaptiste Daroussin for (lua_pushnil (L); lua_next (L, 2); lua_pop (L, 1)) {
779*a0409676SBaptiste Daroussin lua_pushvalue (L, -2);
780*a0409676SBaptiste Daroussin name = luaL_checkstring (L, -1);
781*a0409676SBaptiste Daroussin value = luaL_checkstring (L, -2);
782*a0409676SBaptiste Daroussin ucl_parser_register_variable (parser, name, value);
783*a0409676SBaptiste Daroussin lua_pop (L, 1);
784*a0409676SBaptiste Daroussin }
785*a0409676SBaptiste Daroussin
786*a0409676SBaptiste Daroussin lua_pushboolean (L, true);
787*a0409676SBaptiste Daroussin ret = 1;
788*a0409676SBaptiste Daroussin }
789*a0409676SBaptiste Daroussin else {
790*a0409676SBaptiste Daroussin return luaL_error (L, "invalid arguments");
791*a0409676SBaptiste Daroussin }
792*a0409676SBaptiste Daroussin
793*a0409676SBaptiste Daroussin return ret;
794*a0409676SBaptiste Daroussin }
795*a0409676SBaptiste Daroussin
796*a0409676SBaptiste Daroussin /***
7974bf54857SBaptiste Daroussin * @method parser:parse_string(input)
7984bf54857SBaptiste Daroussin * Parse UCL object from file.
7994bf54857SBaptiste Daroussin * @param {string} input string to parse
8004bf54857SBaptiste Daroussin * @return {bool[, string]} if res is `true` then file has been parsed successfully, otherwise an error string is also returned
8014bf54857SBaptiste Daroussin */
8024bf54857SBaptiste Daroussin static int
lua_ucl_parser_parse_string(lua_State * L)8034bf54857SBaptiste Daroussin lua_ucl_parser_parse_string (lua_State *L)
8044bf54857SBaptiste Daroussin {
8054bf54857SBaptiste Daroussin struct ucl_parser *parser;
8064bf54857SBaptiste Daroussin const char *string;
8074bf54857SBaptiste Daroussin size_t llen;
80811dd9ed6SBaptiste Daroussin enum ucl_parse_type type = UCL_PARSE_UCL;
8094bf54857SBaptiste Daroussin int ret = 2;
8104bf54857SBaptiste Daroussin
8114bf54857SBaptiste Daroussin parser = lua_ucl_parser_get (L, 1);
8124bf54857SBaptiste Daroussin string = luaL_checklstring (L, 2, &llen);
8134bf54857SBaptiste Daroussin
81411dd9ed6SBaptiste Daroussin if (lua_type (L, 3) == LUA_TSTRING) {
81511dd9ed6SBaptiste Daroussin type = lua_ucl_str_to_parse_type (lua_tostring (L, 3));
81611dd9ed6SBaptiste Daroussin }
81711dd9ed6SBaptiste Daroussin
8184bf54857SBaptiste Daroussin if (parser != NULL && string != NULL) {
81911dd9ed6SBaptiste Daroussin if (ucl_parser_add_chunk_full (parser, (const unsigned char *)string,
82011dd9ed6SBaptiste Daroussin llen, 0, UCL_DUPLICATE_APPEND, type)) {
8214bf54857SBaptiste Daroussin lua_pushboolean (L, true);
8224bf54857SBaptiste Daroussin ret = 1;
8234bf54857SBaptiste Daroussin }
8244bf54857SBaptiste Daroussin else {
8254bf54857SBaptiste Daroussin lua_pushboolean (L, false);
8264bf54857SBaptiste Daroussin lua_pushstring (L, ucl_parser_get_error (parser));
8274bf54857SBaptiste Daroussin }
8284bf54857SBaptiste Daroussin }
8294bf54857SBaptiste Daroussin else {
8304bf54857SBaptiste Daroussin lua_pushboolean (L, false);
8314bf54857SBaptiste Daroussin lua_pushstring (L, "invalid arguments");
8324bf54857SBaptiste Daroussin }
8334bf54857SBaptiste Daroussin
8344bf54857SBaptiste Daroussin return ret;
8354bf54857SBaptiste Daroussin }
8364bf54857SBaptiste Daroussin
837*a0409676SBaptiste Daroussin struct _rspamd_lua_text {
838*a0409676SBaptiste Daroussin const char *start;
839*a0409676SBaptiste Daroussin unsigned int len;
840*a0409676SBaptiste Daroussin unsigned int flags;
841*a0409676SBaptiste Daroussin };
842*a0409676SBaptiste Daroussin
843*a0409676SBaptiste Daroussin /***
844*a0409676SBaptiste Daroussin * @method parser:parse_text(input)
845*a0409676SBaptiste Daroussin * Parse UCL object from text object (Rspamd specific).
846*a0409676SBaptiste Daroussin * @param {rspamd_text} input text to parse
847*a0409676SBaptiste Daroussin * @return {bool[, string]} if res is `true` then file has been parsed successfully, otherwise an error string is also returned
848*a0409676SBaptiste Daroussin */
849*a0409676SBaptiste Daroussin static int
lua_ucl_parser_parse_text(lua_State * L)850*a0409676SBaptiste Daroussin lua_ucl_parser_parse_text (lua_State *L)
851*a0409676SBaptiste Daroussin {
852*a0409676SBaptiste Daroussin struct ucl_parser *parser;
853*a0409676SBaptiste Daroussin struct _rspamd_lua_text *t;
854*a0409676SBaptiste Daroussin enum ucl_parse_type type = UCL_PARSE_UCL;
855*a0409676SBaptiste Daroussin int ret = 2;
856*a0409676SBaptiste Daroussin
857*a0409676SBaptiste Daroussin parser = lua_ucl_parser_get (L, 1);
858*a0409676SBaptiste Daroussin t = lua_touserdata (L, 2);
859*a0409676SBaptiste Daroussin
860*a0409676SBaptiste Daroussin if (lua_type (L, 3) == LUA_TSTRING) {
861*a0409676SBaptiste Daroussin type = lua_ucl_str_to_parse_type (lua_tostring (L, 3));
862*a0409676SBaptiste Daroussin }
863*a0409676SBaptiste Daroussin
864*a0409676SBaptiste Daroussin if (parser != NULL && t != NULL) {
865*a0409676SBaptiste Daroussin if (ucl_parser_add_chunk_full (parser, (const unsigned char *)t->start,
866*a0409676SBaptiste Daroussin t->len, 0, UCL_DUPLICATE_APPEND, type)) {
867*a0409676SBaptiste Daroussin lua_pushboolean (L, true);
868*a0409676SBaptiste Daroussin ret = 1;
869*a0409676SBaptiste Daroussin }
870*a0409676SBaptiste Daroussin else {
871*a0409676SBaptiste Daroussin lua_pushboolean (L, false);
872*a0409676SBaptiste Daroussin lua_pushstring (L, ucl_parser_get_error (parser));
873*a0409676SBaptiste Daroussin }
874*a0409676SBaptiste Daroussin }
875*a0409676SBaptiste Daroussin else {
876*a0409676SBaptiste Daroussin lua_pushboolean (L, false);
877*a0409676SBaptiste Daroussin lua_pushstring (L, "invalid arguments");
878*a0409676SBaptiste Daroussin }
879*a0409676SBaptiste Daroussin
880*a0409676SBaptiste Daroussin return ret;
881*a0409676SBaptiste Daroussin }
882*a0409676SBaptiste Daroussin
8834bf54857SBaptiste Daroussin /***
8844bf54857SBaptiste Daroussin * @method parser:get_object()
8854bf54857SBaptiste Daroussin * Get top object from parser and export it to lua representation.
8864bf54857SBaptiste Daroussin * @return {variant or nil} ucl object as lua native variable
8874bf54857SBaptiste Daroussin */
8884bf54857SBaptiste Daroussin static int
lua_ucl_parser_get_object(lua_State * L)8894bf54857SBaptiste Daroussin lua_ucl_parser_get_object (lua_State *L)
8904bf54857SBaptiste Daroussin {
8914bf54857SBaptiste Daroussin struct ucl_parser *parser;
8924bf54857SBaptiste Daroussin ucl_object_t *obj;
8934bf54857SBaptiste Daroussin int ret = 1;
8944bf54857SBaptiste Daroussin
8954bf54857SBaptiste Daroussin parser = lua_ucl_parser_get (L, 1);
8964bf54857SBaptiste Daroussin obj = ucl_parser_get_object (parser);
8974bf54857SBaptiste Daroussin
8984bf54857SBaptiste Daroussin if (obj != NULL) {
8994bf54857SBaptiste Daroussin ret = ucl_object_push_lua (L, obj, false);
9004bf54857SBaptiste Daroussin /* no need to keep reference */
9014bf54857SBaptiste Daroussin ucl_object_unref (obj);
9024bf54857SBaptiste Daroussin }
9034bf54857SBaptiste Daroussin else {
9044bf54857SBaptiste Daroussin lua_pushnil (L);
9054bf54857SBaptiste Daroussin }
9064bf54857SBaptiste Daroussin
9074bf54857SBaptiste Daroussin return ret;
9084bf54857SBaptiste Daroussin }
9094bf54857SBaptiste Daroussin
91039ee7a7aSBaptiste Daroussin /***
91139ee7a7aSBaptiste Daroussin * @method parser:get_object_wrapped()
91239ee7a7aSBaptiste Daroussin * Get top object from parser and export it to userdata object without
91339ee7a7aSBaptiste Daroussin * unwrapping to lua.
91439ee7a7aSBaptiste Daroussin * @return {ucl.object or nil} ucl object wrapped variable
91539ee7a7aSBaptiste Daroussin */
91639ee7a7aSBaptiste Daroussin static int
lua_ucl_parser_get_object_wrapped(lua_State * L)91739ee7a7aSBaptiste Daroussin lua_ucl_parser_get_object_wrapped (lua_State *L)
91839ee7a7aSBaptiste Daroussin {
91939ee7a7aSBaptiste Daroussin struct ucl_parser *parser;
920d9f0ce31SBaptiste Daroussin ucl_object_t *obj;
92139ee7a7aSBaptiste Daroussin int ret = 1;
92239ee7a7aSBaptiste Daroussin
92339ee7a7aSBaptiste Daroussin parser = lua_ucl_parser_get (L, 1);
92439ee7a7aSBaptiste Daroussin obj = ucl_parser_get_object (parser);
92539ee7a7aSBaptiste Daroussin
92639ee7a7aSBaptiste Daroussin if (obj != NULL) {
927d9f0ce31SBaptiste Daroussin lua_ucl_push_opaque (L, obj);
92839ee7a7aSBaptiste Daroussin }
92939ee7a7aSBaptiste Daroussin else {
93039ee7a7aSBaptiste Daroussin lua_pushnil (L);
93139ee7a7aSBaptiste Daroussin }
93239ee7a7aSBaptiste Daroussin
93339ee7a7aSBaptiste Daroussin return ret;
93439ee7a7aSBaptiste Daroussin }
93539ee7a7aSBaptiste Daroussin
93639ee7a7aSBaptiste Daroussin /***
93739ee7a7aSBaptiste Daroussin * @method parser:validate(schema)
93839ee7a7aSBaptiste Daroussin * Validates the top object in the parser against schema. Schema might be
93939ee7a7aSBaptiste Daroussin * another object or a string that represents file to load schema from.
94039ee7a7aSBaptiste Daroussin *
94139ee7a7aSBaptiste Daroussin * @param {string/table} schema input schema
94239ee7a7aSBaptiste Daroussin * @return {result,err} two values: boolean result and the corresponding error
94339ee7a7aSBaptiste Daroussin *
94439ee7a7aSBaptiste Daroussin */
94539ee7a7aSBaptiste Daroussin static int
lua_ucl_parser_validate(lua_State * L)94639ee7a7aSBaptiste Daroussin lua_ucl_parser_validate (lua_State *L)
94739ee7a7aSBaptiste Daroussin {
94839ee7a7aSBaptiste Daroussin struct ucl_parser *parser, *schema_parser;
94939ee7a7aSBaptiste Daroussin ucl_object_t *schema;
95039ee7a7aSBaptiste Daroussin const char *schema_file;
95139ee7a7aSBaptiste Daroussin struct ucl_schema_error err;
95239ee7a7aSBaptiste Daroussin
95339ee7a7aSBaptiste Daroussin parser = lua_ucl_parser_get (L, 1);
95439ee7a7aSBaptiste Daroussin
95539ee7a7aSBaptiste Daroussin if (parser && parser->top_obj) {
95639ee7a7aSBaptiste Daroussin if (lua_type (L, 2) == LUA_TTABLE) {
95739ee7a7aSBaptiste Daroussin schema = ucl_object_lua_import (L, 2);
95839ee7a7aSBaptiste Daroussin
95939ee7a7aSBaptiste Daroussin if (schema == NULL) {
96039ee7a7aSBaptiste Daroussin lua_pushboolean (L, false);
96139ee7a7aSBaptiste Daroussin lua_pushstring (L, "cannot load schema from lua table");
96239ee7a7aSBaptiste Daroussin
96339ee7a7aSBaptiste Daroussin return 2;
96439ee7a7aSBaptiste Daroussin }
96539ee7a7aSBaptiste Daroussin }
96639ee7a7aSBaptiste Daroussin else if (lua_type (L, 2) == LUA_TSTRING) {
96739ee7a7aSBaptiste Daroussin schema_parser = ucl_parser_new (0);
96839ee7a7aSBaptiste Daroussin schema_file = luaL_checkstring (L, 2);
96939ee7a7aSBaptiste Daroussin
97039ee7a7aSBaptiste Daroussin if (!ucl_parser_add_file (schema_parser, schema_file)) {
97139ee7a7aSBaptiste Daroussin lua_pushboolean (L, false);
97239ee7a7aSBaptiste Daroussin lua_pushfstring (L, "cannot parse schema file \"%s\": "
97339ee7a7aSBaptiste Daroussin "%s", schema_file, ucl_parser_get_error (parser));
97439ee7a7aSBaptiste Daroussin ucl_parser_free (schema_parser);
97539ee7a7aSBaptiste Daroussin
97639ee7a7aSBaptiste Daroussin return 2;
97739ee7a7aSBaptiste Daroussin }
97839ee7a7aSBaptiste Daroussin
97939ee7a7aSBaptiste Daroussin schema = ucl_parser_get_object (schema_parser);
98039ee7a7aSBaptiste Daroussin ucl_parser_free (schema_parser);
98139ee7a7aSBaptiste Daroussin }
98239ee7a7aSBaptiste Daroussin else {
98339ee7a7aSBaptiste Daroussin lua_pushboolean (L, false);
98439ee7a7aSBaptiste Daroussin lua_pushstring (L, "invalid schema argument");
98539ee7a7aSBaptiste Daroussin
98639ee7a7aSBaptiste Daroussin return 2;
98739ee7a7aSBaptiste Daroussin }
98839ee7a7aSBaptiste Daroussin
98939ee7a7aSBaptiste Daroussin if (!ucl_object_validate (schema, parser->top_obj, &err)) {
99039ee7a7aSBaptiste Daroussin lua_pushboolean (L, false);
99139ee7a7aSBaptiste Daroussin lua_pushfstring (L, "validation error: "
99239ee7a7aSBaptiste Daroussin "%s", err.msg);
99339ee7a7aSBaptiste Daroussin }
99439ee7a7aSBaptiste Daroussin else {
99539ee7a7aSBaptiste Daroussin lua_pushboolean (L, true);
99639ee7a7aSBaptiste Daroussin lua_pushnil (L);
99739ee7a7aSBaptiste Daroussin }
99839ee7a7aSBaptiste Daroussin
99939ee7a7aSBaptiste Daroussin ucl_object_unref (schema);
100039ee7a7aSBaptiste Daroussin }
100139ee7a7aSBaptiste Daroussin else {
100239ee7a7aSBaptiste Daroussin lua_pushboolean (L, false);
100339ee7a7aSBaptiste Daroussin lua_pushstring (L, "invalid parser or empty top object");
100439ee7a7aSBaptiste Daroussin }
100539ee7a7aSBaptiste Daroussin
100639ee7a7aSBaptiste Daroussin return 2;
100739ee7a7aSBaptiste Daroussin }
100839ee7a7aSBaptiste Daroussin
10094bf54857SBaptiste Daroussin static int
lua_ucl_parser_gc(lua_State * L)10104bf54857SBaptiste Daroussin lua_ucl_parser_gc (lua_State *L)
10114bf54857SBaptiste Daroussin {
10124bf54857SBaptiste Daroussin struct ucl_parser *parser;
10134bf54857SBaptiste Daroussin
10144bf54857SBaptiste Daroussin parser = lua_ucl_parser_get (L, 1);
10154bf54857SBaptiste Daroussin ucl_parser_free (parser);
10164bf54857SBaptiste Daroussin
10174bf54857SBaptiste Daroussin return 0;
10184bf54857SBaptiste Daroussin }
10194bf54857SBaptiste Daroussin
102039ee7a7aSBaptiste Daroussin /***
102139ee7a7aSBaptiste Daroussin * @method object:unwrap()
102239ee7a7aSBaptiste Daroussin * Unwraps opaque ucl object to the native lua object (performing copying)
102339ee7a7aSBaptiste Daroussin * @return {variant} any lua object
102439ee7a7aSBaptiste Daroussin */
102539ee7a7aSBaptiste Daroussin static int
lua_ucl_object_unwrap(lua_State * L)102639ee7a7aSBaptiste Daroussin lua_ucl_object_unwrap (lua_State *L)
102739ee7a7aSBaptiste Daroussin {
102839ee7a7aSBaptiste Daroussin ucl_object_t *obj;
102939ee7a7aSBaptiste Daroussin
103039ee7a7aSBaptiste Daroussin obj = lua_ucl_object_get (L, 1);
103139ee7a7aSBaptiste Daroussin
103239ee7a7aSBaptiste Daroussin if (obj) {
103339ee7a7aSBaptiste Daroussin ucl_object_push_lua (L, obj, true);
103439ee7a7aSBaptiste Daroussin }
103539ee7a7aSBaptiste Daroussin else {
103639ee7a7aSBaptiste Daroussin lua_pushnil (L);
103739ee7a7aSBaptiste Daroussin }
103839ee7a7aSBaptiste Daroussin
103939ee7a7aSBaptiste Daroussin return 1;
104039ee7a7aSBaptiste Daroussin }
104139ee7a7aSBaptiste Daroussin
104211dd9ed6SBaptiste Daroussin static inline enum ucl_emitter
lua_ucl_str_to_emit_type(const char * strtype)104311dd9ed6SBaptiste Daroussin lua_ucl_str_to_emit_type (const char *strtype)
104411dd9ed6SBaptiste Daroussin {
104511dd9ed6SBaptiste Daroussin enum ucl_emitter format = UCL_EMIT_JSON_COMPACT;
104611dd9ed6SBaptiste Daroussin
104711dd9ed6SBaptiste Daroussin if (strcasecmp (strtype, "json") == 0) {
104811dd9ed6SBaptiste Daroussin format = UCL_EMIT_JSON;
104911dd9ed6SBaptiste Daroussin }
105011dd9ed6SBaptiste Daroussin else if (strcasecmp (strtype, "json-compact") == 0) {
105111dd9ed6SBaptiste Daroussin format = UCL_EMIT_JSON_COMPACT;
105211dd9ed6SBaptiste Daroussin }
105311dd9ed6SBaptiste Daroussin else if (strcasecmp (strtype, "yaml") == 0) {
105411dd9ed6SBaptiste Daroussin format = UCL_EMIT_YAML;
105511dd9ed6SBaptiste Daroussin }
105611dd9ed6SBaptiste Daroussin else if (strcasecmp (strtype, "config") == 0 ||
105711dd9ed6SBaptiste Daroussin strcasecmp (strtype, "ucl") == 0) {
105811dd9ed6SBaptiste Daroussin format = UCL_EMIT_CONFIG;
105911dd9ed6SBaptiste Daroussin }
106011dd9ed6SBaptiste Daroussin
106111dd9ed6SBaptiste Daroussin return format;
106211dd9ed6SBaptiste Daroussin }
106311dd9ed6SBaptiste Daroussin
106439ee7a7aSBaptiste Daroussin /***
106539ee7a7aSBaptiste Daroussin * @method object:tostring(type)
106639ee7a7aSBaptiste Daroussin * Unwraps opaque ucl object to string (json by default). Optionally you can
106739ee7a7aSBaptiste Daroussin * specify output format:
106839ee7a7aSBaptiste Daroussin *
106939ee7a7aSBaptiste Daroussin * - `json` - fine printed json
107039ee7a7aSBaptiste Daroussin * - `json-compact` - compacted json
107139ee7a7aSBaptiste Daroussin * - `config` - fine printed configuration
107239ee7a7aSBaptiste Daroussin * - `ucl` - same as `config`
107339ee7a7aSBaptiste Daroussin * - `yaml` - embedded yaml
107439ee7a7aSBaptiste Daroussin * @param {string} type optional
107539ee7a7aSBaptiste Daroussin * @return {string} string representation of the opaque ucl object
107639ee7a7aSBaptiste Daroussin */
107739ee7a7aSBaptiste Daroussin static int
lua_ucl_object_tostring(lua_State * L)107839ee7a7aSBaptiste Daroussin lua_ucl_object_tostring (lua_State *L)
107939ee7a7aSBaptiste Daroussin {
108039ee7a7aSBaptiste Daroussin ucl_object_t *obj;
108139ee7a7aSBaptiste Daroussin enum ucl_emitter format = UCL_EMIT_JSON_COMPACT;
108239ee7a7aSBaptiste Daroussin
108339ee7a7aSBaptiste Daroussin obj = lua_ucl_object_get (L, 1);
108439ee7a7aSBaptiste Daroussin
108539ee7a7aSBaptiste Daroussin if (obj) {
108639ee7a7aSBaptiste Daroussin if (lua_gettop (L) > 1) {
108739ee7a7aSBaptiste Daroussin if (lua_type (L, 2) == LUA_TSTRING) {
108839ee7a7aSBaptiste Daroussin const char *strtype = lua_tostring (L, 2);
108939ee7a7aSBaptiste Daroussin
109011dd9ed6SBaptiste Daroussin format = lua_ucl_str_to_emit_type (strtype);
109139ee7a7aSBaptiste Daroussin }
109239ee7a7aSBaptiste Daroussin }
109339ee7a7aSBaptiste Daroussin
109439ee7a7aSBaptiste Daroussin return lua_ucl_to_string (L, obj, format);
109539ee7a7aSBaptiste Daroussin }
109639ee7a7aSBaptiste Daroussin else {
109739ee7a7aSBaptiste Daroussin lua_pushnil (L);
109839ee7a7aSBaptiste Daroussin }
109939ee7a7aSBaptiste Daroussin
110039ee7a7aSBaptiste Daroussin return 1;
110139ee7a7aSBaptiste Daroussin }
110239ee7a7aSBaptiste Daroussin
110339ee7a7aSBaptiste Daroussin /***
1104d9f0ce31SBaptiste Daroussin * @method object:validate(schema[, path[, ext_refs]])
110539ee7a7aSBaptiste Daroussin * Validates the given ucl object using schema object represented as another
110639ee7a7aSBaptiste Daroussin * opaque ucl object. You can also specify path in the form `#/path/def` to
110739ee7a7aSBaptiste Daroussin * specify the specific schema element to perform validation.
110839ee7a7aSBaptiste Daroussin *
110939ee7a7aSBaptiste Daroussin * @param {ucl.object} schema schema object
111039ee7a7aSBaptiste Daroussin * @param {string} path optional path for validation procedure
1111d9f0ce31SBaptiste Daroussin * @return {result,err} two values: boolean result and the corresponding
1112d9f0ce31SBaptiste Daroussin * error, if `ext_refs` are also specified, then they are returned as opaque
1113d9f0ce31SBaptiste Daroussin * ucl object as {result,err,ext_refs}
111439ee7a7aSBaptiste Daroussin */
111539ee7a7aSBaptiste Daroussin static int
lua_ucl_object_validate(lua_State * L)111639ee7a7aSBaptiste Daroussin lua_ucl_object_validate (lua_State *L)
111739ee7a7aSBaptiste Daroussin {
1118d9f0ce31SBaptiste Daroussin ucl_object_t *obj, *schema, *ext_refs = NULL;
111939ee7a7aSBaptiste Daroussin const ucl_object_t *schema_elt;
112039ee7a7aSBaptiste Daroussin bool res = false;
112139ee7a7aSBaptiste Daroussin struct ucl_schema_error err;
112239ee7a7aSBaptiste Daroussin const char *path = NULL;
112339ee7a7aSBaptiste Daroussin
112439ee7a7aSBaptiste Daroussin obj = lua_ucl_object_get (L, 1);
112539ee7a7aSBaptiste Daroussin schema = lua_ucl_object_get (L, 2);
112639ee7a7aSBaptiste Daroussin
112739ee7a7aSBaptiste Daroussin if (schema && obj && ucl_object_type (schema) == UCL_OBJECT) {
1128d9f0ce31SBaptiste Daroussin if (lua_gettop (L) > 2) {
1129d9f0ce31SBaptiste Daroussin if (lua_type (L, 3) == LUA_TSTRING) {
113039ee7a7aSBaptiste Daroussin path = lua_tostring (L, 3);
113139ee7a7aSBaptiste Daroussin if (path[0] == '#') {
113239ee7a7aSBaptiste Daroussin path++;
113339ee7a7aSBaptiste Daroussin }
113439ee7a7aSBaptiste Daroussin }
1135d9f0ce31SBaptiste Daroussin else if (lua_type (L, 3) == LUA_TUSERDATA || lua_type (L, 3) ==
1136d9f0ce31SBaptiste Daroussin LUA_TTABLE) {
1137d9f0ce31SBaptiste Daroussin /* External refs */
1138d9f0ce31SBaptiste Daroussin ext_refs = lua_ucl_object_get (L, 3);
1139d9f0ce31SBaptiste Daroussin }
1140d9f0ce31SBaptiste Daroussin
1141d9f0ce31SBaptiste Daroussin if (lua_gettop (L) > 3) {
1142d9f0ce31SBaptiste Daroussin if (lua_type (L, 4) == LUA_TUSERDATA || lua_type (L, 4) ==
1143d9f0ce31SBaptiste Daroussin LUA_TTABLE) {
1144d9f0ce31SBaptiste Daroussin /* External refs */
1145d9f0ce31SBaptiste Daroussin ext_refs = lua_ucl_object_get (L, 4);
1146d9f0ce31SBaptiste Daroussin }
1147d9f0ce31SBaptiste Daroussin }
1148d9f0ce31SBaptiste Daroussin }
114939ee7a7aSBaptiste Daroussin
115039ee7a7aSBaptiste Daroussin if (path) {
1151d9f0ce31SBaptiste Daroussin schema_elt = ucl_object_lookup_path_char (schema, path, '/');
115239ee7a7aSBaptiste Daroussin }
115339ee7a7aSBaptiste Daroussin else {
115439ee7a7aSBaptiste Daroussin /* Use the top object */
115539ee7a7aSBaptiste Daroussin schema_elt = schema;
115639ee7a7aSBaptiste Daroussin }
115739ee7a7aSBaptiste Daroussin
115839ee7a7aSBaptiste Daroussin if (schema_elt) {
1159d9f0ce31SBaptiste Daroussin res = ucl_object_validate_root_ext (schema_elt, obj, schema,
1160d9f0ce31SBaptiste Daroussin ext_refs, &err);
116139ee7a7aSBaptiste Daroussin
116239ee7a7aSBaptiste Daroussin if (res) {
116339ee7a7aSBaptiste Daroussin lua_pushboolean (L, res);
116439ee7a7aSBaptiste Daroussin lua_pushnil (L);
1165d9f0ce31SBaptiste Daroussin
1166d9f0ce31SBaptiste Daroussin if (ext_refs) {
1167d9f0ce31SBaptiste Daroussin lua_ucl_push_opaque (L, ext_refs);
1168d9f0ce31SBaptiste Daroussin }
116939ee7a7aSBaptiste Daroussin }
117039ee7a7aSBaptiste Daroussin else {
117139ee7a7aSBaptiste Daroussin lua_pushboolean (L, res);
117239ee7a7aSBaptiste Daroussin lua_pushfstring (L, "validation error: %s", err.msg);
1173d9f0ce31SBaptiste Daroussin
1174d9f0ce31SBaptiste Daroussin if (ext_refs) {
1175d9f0ce31SBaptiste Daroussin lua_ucl_push_opaque (L, ext_refs);
1176d9f0ce31SBaptiste Daroussin }
117739ee7a7aSBaptiste Daroussin }
117839ee7a7aSBaptiste Daroussin }
117939ee7a7aSBaptiste Daroussin else {
118039ee7a7aSBaptiste Daroussin lua_pushboolean (L, res);
118139ee7a7aSBaptiste Daroussin
118239ee7a7aSBaptiste Daroussin lua_pushfstring (L, "cannot find the requested path: %s", path);
1183d9f0ce31SBaptiste Daroussin
1184d9f0ce31SBaptiste Daroussin if (ext_refs) {
1185d9f0ce31SBaptiste Daroussin lua_ucl_push_opaque (L, ext_refs);
118639ee7a7aSBaptiste Daroussin }
118739ee7a7aSBaptiste Daroussin }
118839ee7a7aSBaptiste Daroussin }
118939ee7a7aSBaptiste Daroussin else {
119039ee7a7aSBaptiste Daroussin lua_pushboolean (L, res);
119139ee7a7aSBaptiste Daroussin lua_pushstring (L, "invalid object or schema");
119239ee7a7aSBaptiste Daroussin }
119339ee7a7aSBaptiste Daroussin
1194d9f0ce31SBaptiste Daroussin if (ext_refs) {
1195d9f0ce31SBaptiste Daroussin return 3;
1196d9f0ce31SBaptiste Daroussin }
1197d9f0ce31SBaptiste Daroussin
119839ee7a7aSBaptiste Daroussin return 2;
119939ee7a7aSBaptiste Daroussin }
120039ee7a7aSBaptiste Daroussin
120139ee7a7aSBaptiste Daroussin static int
lua_ucl_object_gc(lua_State * L)120239ee7a7aSBaptiste Daroussin lua_ucl_object_gc (lua_State *L)
120339ee7a7aSBaptiste Daroussin {
120439ee7a7aSBaptiste Daroussin ucl_object_t *obj;
120539ee7a7aSBaptiste Daroussin
120639ee7a7aSBaptiste Daroussin obj = lua_ucl_object_get (L, 1);
120739ee7a7aSBaptiste Daroussin
120839ee7a7aSBaptiste Daroussin ucl_object_unref (obj);
120939ee7a7aSBaptiste Daroussin
121039ee7a7aSBaptiste Daroussin return 0;
121139ee7a7aSBaptiste Daroussin }
121239ee7a7aSBaptiste Daroussin
12134bf54857SBaptiste Daroussin static void
lua_ucl_parser_mt(lua_State * L)12144bf54857SBaptiste Daroussin lua_ucl_parser_mt (lua_State *L)
12154bf54857SBaptiste Daroussin {
12164bf54857SBaptiste Daroussin luaL_newmetatable (L, PARSER_META);
12174bf54857SBaptiste Daroussin
12184bf54857SBaptiste Daroussin lua_pushvalue(L, -1);
12194bf54857SBaptiste Daroussin lua_setfield(L, -2, "__index");
12204bf54857SBaptiste Daroussin
12214bf54857SBaptiste Daroussin lua_pushcfunction (L, lua_ucl_parser_gc);
12224bf54857SBaptiste Daroussin lua_setfield (L, -2, "__gc");
12234bf54857SBaptiste Daroussin
12244bf54857SBaptiste Daroussin lua_pushcfunction (L, lua_ucl_parser_parse_file);
12254bf54857SBaptiste Daroussin lua_setfield (L, -2, "parse_file");
12264bf54857SBaptiste Daroussin
12274bf54857SBaptiste Daroussin lua_pushcfunction (L, lua_ucl_parser_parse_string);
12284bf54857SBaptiste Daroussin lua_setfield (L, -2, "parse_string");
12294bf54857SBaptiste Daroussin
1230*a0409676SBaptiste Daroussin lua_pushcfunction (L, lua_ucl_parser_parse_text);
1231*a0409676SBaptiste Daroussin lua_setfield (L, -2, "parse_text");
1232*a0409676SBaptiste Daroussin
1233*a0409676SBaptiste Daroussin lua_pushcfunction (L, lua_ucl_parser_register_variable);
1234*a0409676SBaptiste Daroussin lua_setfield (L, -2, "register_variable");
1235*a0409676SBaptiste Daroussin
1236*a0409676SBaptiste Daroussin lua_pushcfunction (L, lua_ucl_parser_register_variables);
1237*a0409676SBaptiste Daroussin lua_setfield (L, -2, "register_variables");
1238*a0409676SBaptiste Daroussin
12394bf54857SBaptiste Daroussin lua_pushcfunction (L, lua_ucl_parser_get_object);
12404bf54857SBaptiste Daroussin lua_setfield (L, -2, "get_object");
12414bf54857SBaptiste Daroussin
124239ee7a7aSBaptiste Daroussin lua_pushcfunction (L, lua_ucl_parser_get_object_wrapped);
124339ee7a7aSBaptiste Daroussin lua_setfield (L, -2, "get_object_wrapped");
124439ee7a7aSBaptiste Daroussin
124539ee7a7aSBaptiste Daroussin lua_pushcfunction (L, lua_ucl_parser_validate);
124639ee7a7aSBaptiste Daroussin lua_setfield (L, -2, "validate");
124739ee7a7aSBaptiste Daroussin
12484bf54857SBaptiste Daroussin lua_pop (L, 1);
12494bf54857SBaptiste Daroussin }
12504bf54857SBaptiste Daroussin
125139ee7a7aSBaptiste Daroussin static void
lua_ucl_object_mt(lua_State * L)125239ee7a7aSBaptiste Daroussin lua_ucl_object_mt (lua_State *L)
12534bf54857SBaptiste Daroussin {
125439ee7a7aSBaptiste Daroussin luaL_newmetatable (L, OBJECT_META);
12554bf54857SBaptiste Daroussin
125639ee7a7aSBaptiste Daroussin lua_pushvalue(L, -1);
125739ee7a7aSBaptiste Daroussin lua_setfield(L, -2, "__index");
12584bf54857SBaptiste Daroussin
125939ee7a7aSBaptiste Daroussin lua_pushcfunction (L, lua_ucl_object_gc);
126039ee7a7aSBaptiste Daroussin lua_setfield (L, -2, "__gc");
12614bf54857SBaptiste Daroussin
126239ee7a7aSBaptiste Daroussin lua_pushcfunction (L, lua_ucl_object_tostring);
126339ee7a7aSBaptiste Daroussin lua_setfield (L, -2, "__tostring");
126439ee7a7aSBaptiste Daroussin
126539ee7a7aSBaptiste Daroussin lua_pushcfunction (L, lua_ucl_object_tostring);
126639ee7a7aSBaptiste Daroussin lua_setfield (L, -2, "tostring");
126739ee7a7aSBaptiste Daroussin
126839ee7a7aSBaptiste Daroussin lua_pushcfunction (L, lua_ucl_object_unwrap);
126939ee7a7aSBaptiste Daroussin lua_setfield (L, -2, "unwrap");
127039ee7a7aSBaptiste Daroussin
127139ee7a7aSBaptiste Daroussin lua_pushcfunction (L, lua_ucl_object_unwrap);
127239ee7a7aSBaptiste Daroussin lua_setfield (L, -2, "tolua");
127339ee7a7aSBaptiste Daroussin
127439ee7a7aSBaptiste Daroussin lua_pushcfunction (L, lua_ucl_object_validate);
127539ee7a7aSBaptiste Daroussin lua_setfield (L, -2, "validate");
127639ee7a7aSBaptiste Daroussin
127739ee7a7aSBaptiste Daroussin lua_pushstring (L, OBJECT_META);
127839ee7a7aSBaptiste Daroussin lua_setfield (L, -2, "class");
127939ee7a7aSBaptiste Daroussin
128039ee7a7aSBaptiste Daroussin lua_pop (L, 1);
12814bf54857SBaptiste Daroussin }
12824bf54857SBaptiste Daroussin
1283*a0409676SBaptiste Daroussin static void
lua_ucl_types_mt(lua_State * L)1284*a0409676SBaptiste Daroussin lua_ucl_types_mt (lua_State *L)
1285*a0409676SBaptiste Daroussin {
1286*a0409676SBaptiste Daroussin luaL_newmetatable (L, UCL_OBJECT_TYPE_META);
1287*a0409676SBaptiste Daroussin
1288*a0409676SBaptiste Daroussin lua_pushcfunction (L, lua_ucl_object_tostring);
1289*a0409676SBaptiste Daroussin lua_setfield (L, -2, "__tostring");
1290*a0409676SBaptiste Daroussin
1291*a0409676SBaptiste Daroussin lua_pushcfunction (L, lua_ucl_object_tostring);
1292*a0409676SBaptiste Daroussin lua_setfield (L, -2, "tostring");
1293*a0409676SBaptiste Daroussin
1294*a0409676SBaptiste Daroussin lua_pushstring (L, UCL_OBJECT_TYPE_META);
1295*a0409676SBaptiste Daroussin lua_setfield (L, -2, "class");
1296*a0409676SBaptiste Daroussin
1297*a0409676SBaptiste Daroussin lua_pop (L, 1);
1298*a0409676SBaptiste Daroussin
1299*a0409676SBaptiste Daroussin luaL_newmetatable (L, UCL_ARRAY_TYPE_META);
1300*a0409676SBaptiste Daroussin
1301*a0409676SBaptiste Daroussin lua_pushcfunction (L, lua_ucl_object_tostring);
1302*a0409676SBaptiste Daroussin lua_setfield (L, -2, "__tostring");
1303*a0409676SBaptiste Daroussin
1304*a0409676SBaptiste Daroussin lua_pushcfunction (L, lua_ucl_object_tostring);
1305*a0409676SBaptiste Daroussin lua_setfield (L, -2, "tostring");
1306*a0409676SBaptiste Daroussin
1307*a0409676SBaptiste Daroussin lua_pushstring (L, UCL_ARRAY_TYPE_META);
1308*a0409676SBaptiste Daroussin lua_setfield (L, -2, "class");
1309*a0409676SBaptiste Daroussin
1310*a0409676SBaptiste Daroussin lua_pop (L, 1);
1311*a0409676SBaptiste Daroussin
1312*a0409676SBaptiste Daroussin luaL_newmetatable (L, UCL_IMPL_ARRAY_TYPE_META);
1313*a0409676SBaptiste Daroussin
1314*a0409676SBaptiste Daroussin lua_pushcfunction (L, lua_ucl_object_tostring);
1315*a0409676SBaptiste Daroussin lua_setfield (L, -2, "__tostring");
1316*a0409676SBaptiste Daroussin
1317*a0409676SBaptiste Daroussin lua_pushcfunction (L, lua_ucl_object_tostring);
1318*a0409676SBaptiste Daroussin lua_setfield (L, -2, "tostring");
1319*a0409676SBaptiste Daroussin
1320*a0409676SBaptiste Daroussin lua_pushstring (L, UCL_IMPL_ARRAY_TYPE_META);
1321*a0409676SBaptiste Daroussin lua_setfield (L, -2, "class");
1322*a0409676SBaptiste Daroussin
1323*a0409676SBaptiste Daroussin lua_pop (L, 1);
1324*a0409676SBaptiste Daroussin }
1325*a0409676SBaptiste Daroussin
13264bf54857SBaptiste Daroussin static int
lua_ucl_to_json(lua_State * L)13274bf54857SBaptiste Daroussin lua_ucl_to_json (lua_State *L)
13284bf54857SBaptiste Daroussin {
13294bf54857SBaptiste Daroussin ucl_object_t *obj;
13304bf54857SBaptiste Daroussin int format = UCL_EMIT_JSON;
13314bf54857SBaptiste Daroussin
13324bf54857SBaptiste Daroussin if (lua_gettop (L) > 1) {
13334bf54857SBaptiste Daroussin if (lua_toboolean (L, 2)) {
13344bf54857SBaptiste Daroussin format = UCL_EMIT_JSON_COMPACT;
13354bf54857SBaptiste Daroussin }
13364bf54857SBaptiste Daroussin }
13374bf54857SBaptiste Daroussin
13384bf54857SBaptiste Daroussin obj = ucl_object_lua_import (L, 1);
13394bf54857SBaptiste Daroussin if (obj != NULL) {
13404bf54857SBaptiste Daroussin lua_ucl_to_string (L, obj, format);
13414bf54857SBaptiste Daroussin ucl_object_unref (obj);
13424bf54857SBaptiste Daroussin }
13434bf54857SBaptiste Daroussin else {
13444bf54857SBaptiste Daroussin lua_pushnil (L);
13454bf54857SBaptiste Daroussin }
13464bf54857SBaptiste Daroussin
13474bf54857SBaptiste Daroussin return 1;
13484bf54857SBaptiste Daroussin }
13494bf54857SBaptiste Daroussin
13504bf54857SBaptiste Daroussin static int
lua_ucl_to_config(lua_State * L)13514bf54857SBaptiste Daroussin lua_ucl_to_config (lua_State *L)
13524bf54857SBaptiste Daroussin {
13534bf54857SBaptiste Daroussin ucl_object_t *obj;
13544bf54857SBaptiste Daroussin
13554bf54857SBaptiste Daroussin obj = ucl_object_lua_import (L, 1);
13564bf54857SBaptiste Daroussin if (obj != NULL) {
13574bf54857SBaptiste Daroussin lua_ucl_to_string (L, obj, UCL_EMIT_CONFIG);
13584bf54857SBaptiste Daroussin ucl_object_unref (obj);
13594bf54857SBaptiste Daroussin }
13604bf54857SBaptiste Daroussin else {
13614bf54857SBaptiste Daroussin lua_pushnil (L);
13624bf54857SBaptiste Daroussin }
13634bf54857SBaptiste Daroussin
13644bf54857SBaptiste Daroussin return 1;
13654bf54857SBaptiste Daroussin }
13664bf54857SBaptiste Daroussin
13674bf54857SBaptiste Daroussin /***
13684bf54857SBaptiste Daroussin * @function ucl.to_format(var, format)
13694bf54857SBaptiste Daroussin * Converts lua variable `var` to the specified `format`. Formats supported are:
13704bf54857SBaptiste Daroussin *
13714bf54857SBaptiste Daroussin * - `json` - fine printed json
13724bf54857SBaptiste Daroussin * - `json-compact` - compacted json
13734bf54857SBaptiste Daroussin * - `config` - fine printed configuration
13744bf54857SBaptiste Daroussin * - `ucl` - same as `config`
13754bf54857SBaptiste Daroussin * - `yaml` - embedded yaml
13764bf54857SBaptiste Daroussin *
13774bf54857SBaptiste Daroussin * If `var` contains function, they are called during output formatting and if
1378*a0409676SBaptiste Daroussin * they return string value, then this value is used for output.
13794bf54857SBaptiste Daroussin * @param {variant} var any sort of lua variable (if userdata then metafield `__to_ucl` is searched for output)
13804bf54857SBaptiste Daroussin * @param {string} format any available format
13814bf54857SBaptiste Daroussin * @return {string} string representation of `var` in the specific `format`.
13824bf54857SBaptiste Daroussin * @example
13834bf54857SBaptiste Daroussin local table = {
13844bf54857SBaptiste Daroussin str = 'value',
13854bf54857SBaptiste Daroussin num = 100500,
13864bf54857SBaptiste Daroussin null = ucl.null,
13874bf54857SBaptiste Daroussin func = function ()
13884bf54857SBaptiste Daroussin return 'huh'
13894bf54857SBaptiste Daroussin end
13904bf54857SBaptiste Daroussin }
13914bf54857SBaptiste Daroussin
13924bf54857SBaptiste Daroussin print(ucl.to_format(table, 'ucl'))
13934bf54857SBaptiste Daroussin -- Output:
13944bf54857SBaptiste Daroussin --[[
13954bf54857SBaptiste Daroussin num = 100500;
13964bf54857SBaptiste Daroussin str = "value";
13974bf54857SBaptiste Daroussin null = null;
13984bf54857SBaptiste Daroussin func = "huh";
13994bf54857SBaptiste Daroussin --]]
14004bf54857SBaptiste Daroussin */
14014bf54857SBaptiste Daroussin static int
lua_ucl_to_format(lua_State * L)14024bf54857SBaptiste Daroussin lua_ucl_to_format (lua_State *L)
14034bf54857SBaptiste Daroussin {
14044bf54857SBaptiste Daroussin ucl_object_t *obj;
14054bf54857SBaptiste Daroussin int format = UCL_EMIT_JSON;
1406*a0409676SBaptiste Daroussin bool sort = false;
14074bf54857SBaptiste Daroussin
14084bf54857SBaptiste Daroussin if (lua_gettop (L) > 1) {
14094bf54857SBaptiste Daroussin if (lua_type (L, 2) == LUA_TNUMBER) {
14104bf54857SBaptiste Daroussin format = lua_tonumber (L, 2);
14114bf54857SBaptiste Daroussin if (format < 0 || format >= UCL_EMIT_YAML) {
14124bf54857SBaptiste Daroussin lua_pushnil (L);
14134bf54857SBaptiste Daroussin return 1;
14144bf54857SBaptiste Daroussin }
14154bf54857SBaptiste Daroussin }
14164bf54857SBaptiste Daroussin else if (lua_type (L, 2) == LUA_TSTRING) {
14174bf54857SBaptiste Daroussin const char *strtype = lua_tostring (L, 2);
14184bf54857SBaptiste Daroussin
14194bf54857SBaptiste Daroussin if (strcasecmp (strtype, "json") == 0) {
14204bf54857SBaptiste Daroussin format = UCL_EMIT_JSON;
14214bf54857SBaptiste Daroussin }
14224bf54857SBaptiste Daroussin else if (strcasecmp (strtype, "json-compact") == 0) {
14234bf54857SBaptiste Daroussin format = UCL_EMIT_JSON_COMPACT;
14244bf54857SBaptiste Daroussin }
14254bf54857SBaptiste Daroussin else if (strcasecmp (strtype, "yaml") == 0) {
14264bf54857SBaptiste Daroussin format = UCL_EMIT_YAML;
14274bf54857SBaptiste Daroussin }
14284bf54857SBaptiste Daroussin else if (strcasecmp (strtype, "config") == 0 ||
14294bf54857SBaptiste Daroussin strcasecmp (strtype, "ucl") == 0) {
14304bf54857SBaptiste Daroussin format = UCL_EMIT_CONFIG;
14314bf54857SBaptiste Daroussin }
143211dd9ed6SBaptiste Daroussin else if (strcasecmp (strtype, "msgpack") == 0) {
143311dd9ed6SBaptiste Daroussin format = UCL_EMIT_MSGPACK;
143411dd9ed6SBaptiste Daroussin }
14354bf54857SBaptiste Daroussin }
1436*a0409676SBaptiste Daroussin
1437*a0409676SBaptiste Daroussin if (lua_isboolean (L, 3)) {
1438*a0409676SBaptiste Daroussin sort = lua_toboolean (L, 3);
1439*a0409676SBaptiste Daroussin }
14404bf54857SBaptiste Daroussin }
14414bf54857SBaptiste Daroussin
14424bf54857SBaptiste Daroussin obj = ucl_object_lua_import (L, 1);
1443*a0409676SBaptiste Daroussin
14444bf54857SBaptiste Daroussin if (obj != NULL) {
1445*a0409676SBaptiste Daroussin
1446*a0409676SBaptiste Daroussin if (sort) {
1447*a0409676SBaptiste Daroussin if (ucl_object_type (obj) == UCL_OBJECT) {
1448*a0409676SBaptiste Daroussin ucl_object_sort_keys (obj, UCL_SORT_KEYS_RECURSIVE);
1449*a0409676SBaptiste Daroussin }
1450*a0409676SBaptiste Daroussin }
1451*a0409676SBaptiste Daroussin
14524bf54857SBaptiste Daroussin lua_ucl_to_string (L, obj, format);
14534bf54857SBaptiste Daroussin ucl_object_unref (obj);
14544bf54857SBaptiste Daroussin }
14554bf54857SBaptiste Daroussin else {
14564bf54857SBaptiste Daroussin lua_pushnil (L);
14574bf54857SBaptiste Daroussin }
14584bf54857SBaptiste Daroussin
14594bf54857SBaptiste Daroussin return 1;
14604bf54857SBaptiste Daroussin }
14614bf54857SBaptiste Daroussin
14624bf54857SBaptiste Daroussin static int
lua_ucl_null_tostring(lua_State * L)14634bf54857SBaptiste Daroussin lua_ucl_null_tostring (lua_State* L)
14644bf54857SBaptiste Daroussin {
14654bf54857SBaptiste Daroussin lua_pushstring (L, "null");
14664bf54857SBaptiste Daroussin return 1;
14674bf54857SBaptiste Daroussin }
14684bf54857SBaptiste Daroussin
14694bf54857SBaptiste Daroussin static void
lua_ucl_null_mt(lua_State * L)14704bf54857SBaptiste Daroussin lua_ucl_null_mt (lua_State *L)
14714bf54857SBaptiste Daroussin {
14724bf54857SBaptiste Daroussin luaL_newmetatable (L, NULL_META);
14734bf54857SBaptiste Daroussin
14744bf54857SBaptiste Daroussin lua_pushcfunction (L, lua_ucl_null_tostring);
14754bf54857SBaptiste Daroussin lua_setfield (L, -2, "__tostring");
14764bf54857SBaptiste Daroussin
14774bf54857SBaptiste Daroussin lua_pop (L, 1);
14784bf54857SBaptiste Daroussin }
14794bf54857SBaptiste Daroussin
14804bf54857SBaptiste Daroussin int
luaopen_ucl(lua_State * L)14814bf54857SBaptiste Daroussin luaopen_ucl (lua_State *L)
14824bf54857SBaptiste Daroussin {
14834bf54857SBaptiste Daroussin lua_ucl_parser_mt (L);
14844bf54857SBaptiste Daroussin lua_ucl_null_mt (L);
148539ee7a7aSBaptiste Daroussin lua_ucl_object_mt (L);
1486*a0409676SBaptiste Daroussin lua_ucl_types_mt (L);
14874bf54857SBaptiste Daroussin
14884bf54857SBaptiste Daroussin /* Create the refs weak table: */
14894bf54857SBaptiste Daroussin lua_createtable (L, 0, 2);
14904bf54857SBaptiste Daroussin lua_pushliteral (L, "v"); /* tbl, "v" */
14914bf54857SBaptiste Daroussin lua_setfield (L, -2, "__mode");
14924bf54857SBaptiste Daroussin lua_pushvalue (L, -1); /* tbl, tbl */
14934bf54857SBaptiste Daroussin lua_setmetatable (L, -2); /* tbl */
14944bf54857SBaptiste Daroussin lua_setfield (L, LUA_REGISTRYINDEX, "ucl.refs");
14954bf54857SBaptiste Daroussin
14964bf54857SBaptiste Daroussin lua_newtable (L);
14974bf54857SBaptiste Daroussin
14984bf54857SBaptiste Daroussin lua_pushcfunction (L, lua_ucl_parser_init);
14994bf54857SBaptiste Daroussin lua_setfield (L, -2, "parser");
15004bf54857SBaptiste Daroussin
15014bf54857SBaptiste Daroussin lua_pushcfunction (L, lua_ucl_to_json);
15024bf54857SBaptiste Daroussin lua_setfield (L, -2, "to_json");
15034bf54857SBaptiste Daroussin
15044bf54857SBaptiste Daroussin lua_pushcfunction (L, lua_ucl_to_config);
15054bf54857SBaptiste Daroussin lua_setfield (L, -2, "to_config");
15064bf54857SBaptiste Daroussin
15074bf54857SBaptiste Daroussin lua_pushcfunction (L, lua_ucl_to_format);
15084bf54857SBaptiste Daroussin lua_setfield (L, -2, "to_format");
15094bf54857SBaptiste Daroussin
15104bf54857SBaptiste Daroussin ucl_null = lua_newuserdata (L, 0);
15114bf54857SBaptiste Daroussin luaL_getmetatable (L, NULL_META);
15124bf54857SBaptiste Daroussin lua_setmetatable (L, -2);
15134bf54857SBaptiste Daroussin
15144bf54857SBaptiste Daroussin lua_pushvalue (L, -1);
15154bf54857SBaptiste Daroussin lua_setfield (L, LUA_REGISTRYINDEX, "ucl.null");
15164bf54857SBaptiste Daroussin
15174bf54857SBaptiste Daroussin lua_setfield (L, -2, "null");
15184bf54857SBaptiste Daroussin
15194bf54857SBaptiste Daroussin return 1;
15204bf54857SBaptiste Daroussin }
15214bf54857SBaptiste Daroussin
15224bf54857SBaptiste Daroussin struct ucl_lua_funcdata*
ucl_object_toclosure(const ucl_object_t * obj)15234bf54857SBaptiste Daroussin ucl_object_toclosure (const ucl_object_t *obj)
15244bf54857SBaptiste Daroussin {
15254bf54857SBaptiste Daroussin if (obj == NULL || obj->type != UCL_USERDATA) {
15264bf54857SBaptiste Daroussin return NULL;
15274bf54857SBaptiste Daroussin }
15284bf54857SBaptiste Daroussin
15294bf54857SBaptiste Daroussin return (struct ucl_lua_funcdata*)obj->value.ud;
15304bf54857SBaptiste Daroussin }
1531