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" 714bf54857SBaptiste Daroussin #define NULL_META "null.emitter.meta" 72*39ee7a7aSBaptiste Daroussin #define OBJECT_META "ucl.object.meta" 734bf54857SBaptiste Daroussin 744bf54857SBaptiste Daroussin static int ucl_object_lua_push_array (lua_State *L, const ucl_object_t *obj); 754bf54857SBaptiste Daroussin static int ucl_object_lua_push_scalar (lua_State *L, const ucl_object_t *obj, bool allow_array); 764bf54857SBaptiste Daroussin static ucl_object_t* ucl_object_lua_fromtable (lua_State *L, int idx); 774bf54857SBaptiste Daroussin static ucl_object_t* ucl_object_lua_fromelt (lua_State *L, int idx); 784bf54857SBaptiste Daroussin 794bf54857SBaptiste Daroussin static void *ucl_null; 804bf54857SBaptiste Daroussin 814bf54857SBaptiste Daroussin /** 824bf54857SBaptiste Daroussin * Push a single element of an object to lua 834bf54857SBaptiste Daroussin * @param L 844bf54857SBaptiste Daroussin * @param key 854bf54857SBaptiste Daroussin * @param obj 864bf54857SBaptiste Daroussin */ 874bf54857SBaptiste Daroussin static void 884bf54857SBaptiste Daroussin ucl_object_lua_push_element (lua_State *L, const char *key, 894bf54857SBaptiste Daroussin const ucl_object_t *obj) 904bf54857SBaptiste Daroussin { 914bf54857SBaptiste Daroussin lua_pushstring (L, key); 924bf54857SBaptiste Daroussin ucl_object_push_lua (L, obj, true); 934bf54857SBaptiste Daroussin lua_settable (L, -3); 944bf54857SBaptiste Daroussin } 954bf54857SBaptiste Daroussin 964bf54857SBaptiste Daroussin static void 974bf54857SBaptiste Daroussin lua_ucl_userdata_dtor (void *ud) 984bf54857SBaptiste Daroussin { 994bf54857SBaptiste Daroussin struct ucl_lua_funcdata *fd = (struct ucl_lua_funcdata *)ud; 1004bf54857SBaptiste Daroussin 1014bf54857SBaptiste Daroussin luaL_unref (fd->L, LUA_REGISTRYINDEX, fd->idx); 1024bf54857SBaptiste Daroussin if (fd->ret != NULL) { 1034bf54857SBaptiste Daroussin free (fd->ret); 1044bf54857SBaptiste Daroussin } 1054bf54857SBaptiste Daroussin free (fd); 1064bf54857SBaptiste Daroussin } 1074bf54857SBaptiste Daroussin 1084bf54857SBaptiste Daroussin static const char * 1094bf54857SBaptiste Daroussin lua_ucl_userdata_emitter (void *ud) 1104bf54857SBaptiste Daroussin { 1114bf54857SBaptiste Daroussin struct ucl_lua_funcdata *fd = (struct ucl_lua_funcdata *)ud; 1124bf54857SBaptiste Daroussin const char *out = ""; 1134bf54857SBaptiste Daroussin 1144bf54857SBaptiste Daroussin lua_rawgeti (fd->L, LUA_REGISTRYINDEX, fd->idx); 1154bf54857SBaptiste Daroussin 1164bf54857SBaptiste Daroussin lua_pcall (fd->L, 0, 1, 0); 1174bf54857SBaptiste Daroussin out = lua_tostring (fd->L, -1); 1184bf54857SBaptiste Daroussin 1194bf54857SBaptiste Daroussin if (out != NULL) { 1204bf54857SBaptiste Daroussin /* We need to store temporary string in a more appropriate place */ 1214bf54857SBaptiste Daroussin if (fd->ret) { 1224bf54857SBaptiste Daroussin free (fd->ret); 1234bf54857SBaptiste Daroussin } 1244bf54857SBaptiste Daroussin fd->ret = strdup (out); 1254bf54857SBaptiste Daroussin } 1264bf54857SBaptiste Daroussin 1274bf54857SBaptiste Daroussin lua_settop (fd->L, 0); 1284bf54857SBaptiste Daroussin 1294bf54857SBaptiste Daroussin return fd->ret; 1304bf54857SBaptiste Daroussin } 1314bf54857SBaptiste Daroussin 1324bf54857SBaptiste Daroussin /** 1334bf54857SBaptiste Daroussin * Push a single object to lua 1344bf54857SBaptiste Daroussin * @param L 1354bf54857SBaptiste Daroussin * @param obj 1364bf54857SBaptiste Daroussin * @return 1374bf54857SBaptiste Daroussin */ 1384bf54857SBaptiste Daroussin static int 1394bf54857SBaptiste Daroussin ucl_object_lua_push_object (lua_State *L, const ucl_object_t *obj, 1404bf54857SBaptiste Daroussin bool allow_array) 1414bf54857SBaptiste Daroussin { 1424bf54857SBaptiste Daroussin const ucl_object_t *cur; 1434bf54857SBaptiste Daroussin ucl_object_iter_t it = NULL; 1444bf54857SBaptiste Daroussin int nelt = 0; 1454bf54857SBaptiste Daroussin 1464bf54857SBaptiste Daroussin if (allow_array && obj->next != NULL) { 1474bf54857SBaptiste Daroussin /* Actually we need to push this as an array */ 1484bf54857SBaptiste Daroussin return ucl_object_lua_push_array (L, obj); 1494bf54857SBaptiste Daroussin } 1504bf54857SBaptiste Daroussin 1514bf54857SBaptiste Daroussin /* Optimize allocation by preallocation of table */ 1524bf54857SBaptiste Daroussin while (ucl_iterate_object (obj, &it, true) != NULL) { 1534bf54857SBaptiste Daroussin nelt ++; 1544bf54857SBaptiste Daroussin } 1554bf54857SBaptiste Daroussin 1564bf54857SBaptiste Daroussin lua_createtable (L, 0, nelt); 1574bf54857SBaptiste Daroussin it = NULL; 1584bf54857SBaptiste Daroussin 1594bf54857SBaptiste Daroussin while ((cur = ucl_iterate_object (obj, &it, true)) != NULL) { 1604bf54857SBaptiste Daroussin ucl_object_lua_push_element (L, ucl_object_key (cur), cur); 1614bf54857SBaptiste Daroussin } 1624bf54857SBaptiste Daroussin 1634bf54857SBaptiste Daroussin return 1; 1644bf54857SBaptiste Daroussin } 1654bf54857SBaptiste Daroussin 1664bf54857SBaptiste Daroussin /** 1674bf54857SBaptiste Daroussin * Push an array to lua as table indexed by integers 1684bf54857SBaptiste Daroussin * @param L 1694bf54857SBaptiste Daroussin * @param obj 1704bf54857SBaptiste Daroussin * @return 1714bf54857SBaptiste Daroussin */ 1724bf54857SBaptiste Daroussin static int 1734bf54857SBaptiste Daroussin ucl_object_lua_push_array (lua_State *L, const ucl_object_t *obj) 1744bf54857SBaptiste Daroussin { 1754bf54857SBaptiste Daroussin const ucl_object_t *cur; 176*39ee7a7aSBaptiste Daroussin ucl_object_iter_t it; 1774bf54857SBaptiste Daroussin int i = 1, nelt = 0; 1784bf54857SBaptiste Daroussin 179*39ee7a7aSBaptiste Daroussin if (obj->type == UCL_ARRAY) { 180*39ee7a7aSBaptiste Daroussin nelt = obj->len; 181*39ee7a7aSBaptiste Daroussin it = ucl_object_iterate_new (obj); 182*39ee7a7aSBaptiste Daroussin lua_createtable (L, nelt, 0); 183*39ee7a7aSBaptiste Daroussin 184*39ee7a7aSBaptiste Daroussin while ((cur = ucl_object_iterate_safe (it, true))) { 185*39ee7a7aSBaptiste Daroussin ucl_object_push_lua (L, cur, false); 186*39ee7a7aSBaptiste Daroussin lua_rawseti (L, -2, i); 187*39ee7a7aSBaptiste Daroussin i ++; 188*39ee7a7aSBaptiste Daroussin } 189*39ee7a7aSBaptiste Daroussin } 190*39ee7a7aSBaptiste Daroussin else { 1914bf54857SBaptiste Daroussin /* Optimize allocation by preallocation of table */ 1924bf54857SBaptiste Daroussin LL_FOREACH (obj, cur) { 1934bf54857SBaptiste Daroussin nelt ++; 1944bf54857SBaptiste Daroussin } 1954bf54857SBaptiste Daroussin 1964bf54857SBaptiste Daroussin lua_createtable (L, nelt, 0); 1974bf54857SBaptiste Daroussin 1984bf54857SBaptiste Daroussin LL_FOREACH (obj, cur) { 1994bf54857SBaptiste Daroussin ucl_object_push_lua (L, cur, false); 2004bf54857SBaptiste Daroussin lua_rawseti (L, -2, i); 2014bf54857SBaptiste Daroussin i ++; 2024bf54857SBaptiste Daroussin } 203*39ee7a7aSBaptiste Daroussin } 2044bf54857SBaptiste Daroussin 2054bf54857SBaptiste Daroussin return 1; 2064bf54857SBaptiste Daroussin } 2074bf54857SBaptiste Daroussin 2084bf54857SBaptiste Daroussin /** 2094bf54857SBaptiste Daroussin * Push a simple object to lua depending on its actual type 2104bf54857SBaptiste Daroussin */ 2114bf54857SBaptiste Daroussin static int 2124bf54857SBaptiste Daroussin ucl_object_lua_push_scalar (lua_State *L, const ucl_object_t *obj, 2134bf54857SBaptiste Daroussin bool allow_array) 2144bf54857SBaptiste Daroussin { 2154bf54857SBaptiste Daroussin struct ucl_lua_funcdata *fd; 2164bf54857SBaptiste Daroussin 2174bf54857SBaptiste Daroussin if (allow_array && obj->next != NULL) { 2184bf54857SBaptiste Daroussin /* Actually we need to push this as an array */ 2194bf54857SBaptiste Daroussin return ucl_object_lua_push_array (L, obj); 2204bf54857SBaptiste Daroussin } 2214bf54857SBaptiste Daroussin 2224bf54857SBaptiste Daroussin switch (obj->type) { 2234bf54857SBaptiste Daroussin case UCL_BOOLEAN: 2244bf54857SBaptiste Daroussin lua_pushboolean (L, ucl_obj_toboolean (obj)); 2254bf54857SBaptiste Daroussin break; 2264bf54857SBaptiste Daroussin case UCL_STRING: 2274bf54857SBaptiste Daroussin lua_pushstring (L, ucl_obj_tostring (obj)); 2284bf54857SBaptiste Daroussin break; 2294bf54857SBaptiste Daroussin case UCL_INT: 2304bf54857SBaptiste Daroussin #if LUA_VERSION_NUM >= 501 2314bf54857SBaptiste Daroussin lua_pushinteger (L, ucl_obj_toint (obj)); 2324bf54857SBaptiste Daroussin #else 2334bf54857SBaptiste Daroussin lua_pushnumber (L, ucl_obj_toint (obj)); 2344bf54857SBaptiste Daroussin #endif 2354bf54857SBaptiste Daroussin break; 2364bf54857SBaptiste Daroussin case UCL_FLOAT: 2374bf54857SBaptiste Daroussin case UCL_TIME: 2384bf54857SBaptiste Daroussin lua_pushnumber (L, ucl_obj_todouble (obj)); 2394bf54857SBaptiste Daroussin break; 2404bf54857SBaptiste Daroussin case UCL_NULL: 2414bf54857SBaptiste Daroussin lua_getfield (L, LUA_REGISTRYINDEX, "ucl.null"); 2424bf54857SBaptiste Daroussin break; 2434bf54857SBaptiste Daroussin case UCL_USERDATA: 2444bf54857SBaptiste Daroussin fd = (struct ucl_lua_funcdata *)obj->value.ud; 2454bf54857SBaptiste Daroussin lua_rawgeti (L, LUA_REGISTRYINDEX, fd->idx); 2464bf54857SBaptiste Daroussin break; 2474bf54857SBaptiste Daroussin default: 2484bf54857SBaptiste Daroussin lua_pushnil (L); 2494bf54857SBaptiste Daroussin break; 2504bf54857SBaptiste Daroussin } 2514bf54857SBaptiste Daroussin 2524bf54857SBaptiste Daroussin return 1; 2534bf54857SBaptiste Daroussin } 2544bf54857SBaptiste Daroussin 2554bf54857SBaptiste Daroussin /*** 2564bf54857SBaptiste Daroussin * @function ucl_object_push_lua(L, obj, allow_array) 2574bf54857SBaptiste Daroussin * This is a `C` function to push `UCL` object as lua variable. This function 2584bf54857SBaptiste Daroussin * converts `obj` to lua representation using the following conversions: 2594bf54857SBaptiste Daroussin * 2604bf54857SBaptiste Daroussin * - *scalar* values are directly presented by lua objects 2614bf54857SBaptiste Daroussin * - *userdata* values are converted to lua function objects using `LUA_REGISTRYINDEX`, 2624bf54857SBaptiste Daroussin * this can be used to pass functions from lua to c and vice-versa 2634bf54857SBaptiste Daroussin * - *arrays* are converted to lua tables with numeric indicies suitable for `ipairs` iterations 2644bf54857SBaptiste Daroussin * - *objects* are converted to lua tables with string indicies 2654bf54857SBaptiste Daroussin * @param {lua_State} L lua state pointer 2664bf54857SBaptiste Daroussin * @param {ucl_object_t} obj object to push 2674bf54857SBaptiste Daroussin * @param {bool} allow_array expand implicit arrays (should be true for all but partial arrays) 2684bf54857SBaptiste Daroussin * @return {int} `1` if an object is pushed to lua 2694bf54857SBaptiste Daroussin */ 2704bf54857SBaptiste Daroussin int 2714bf54857SBaptiste Daroussin ucl_object_push_lua (lua_State *L, const ucl_object_t *obj, bool allow_array) 2724bf54857SBaptiste Daroussin { 2734bf54857SBaptiste Daroussin switch (obj->type) { 2744bf54857SBaptiste Daroussin case UCL_OBJECT: 2754bf54857SBaptiste Daroussin return ucl_object_lua_push_object (L, obj, allow_array); 2764bf54857SBaptiste Daroussin case UCL_ARRAY: 277*39ee7a7aSBaptiste Daroussin return ucl_object_lua_push_array (L, obj); 2784bf54857SBaptiste Daroussin default: 2794bf54857SBaptiste Daroussin return ucl_object_lua_push_scalar (L, obj, allow_array); 2804bf54857SBaptiste Daroussin } 2814bf54857SBaptiste Daroussin } 2824bf54857SBaptiste Daroussin 2834bf54857SBaptiste Daroussin /** 2844bf54857SBaptiste Daroussin * Parse lua table into object top 2854bf54857SBaptiste Daroussin * @param L 2864bf54857SBaptiste Daroussin * @param top 2874bf54857SBaptiste Daroussin * @param idx 2884bf54857SBaptiste Daroussin */ 2894bf54857SBaptiste Daroussin static ucl_object_t * 2904bf54857SBaptiste Daroussin ucl_object_lua_fromtable (lua_State *L, int idx) 2914bf54857SBaptiste Daroussin { 2924bf54857SBaptiste Daroussin ucl_object_t *obj, *top = NULL; 2934bf54857SBaptiste Daroussin size_t keylen; 2944bf54857SBaptiste Daroussin const char *k; 2954bf54857SBaptiste Daroussin bool is_array = true; 2964bf54857SBaptiste Daroussin int max = INT_MIN; 2974bf54857SBaptiste Daroussin 2984bf54857SBaptiste Daroussin if (idx < 0) { 2994bf54857SBaptiste Daroussin /* For negative indicies we want to invert them */ 3004bf54857SBaptiste Daroussin idx = lua_gettop (L) + idx + 1; 3014bf54857SBaptiste Daroussin } 3024bf54857SBaptiste Daroussin /* Check for array */ 3034bf54857SBaptiste Daroussin lua_pushnil (L); 3044bf54857SBaptiste Daroussin while (lua_next (L, idx) != 0) { 3054bf54857SBaptiste Daroussin if (lua_type (L, -2) == LUA_TNUMBER) { 3064bf54857SBaptiste Daroussin double num = lua_tonumber (L, -2); 3074bf54857SBaptiste Daroussin if (num == (int)num) { 3084bf54857SBaptiste Daroussin if (num > max) { 3094bf54857SBaptiste Daroussin max = num; 3104bf54857SBaptiste Daroussin } 3114bf54857SBaptiste Daroussin } 3124bf54857SBaptiste Daroussin else { 3134bf54857SBaptiste Daroussin /* Keys are not integer */ 3144bf54857SBaptiste Daroussin lua_pop (L, 2); 3154bf54857SBaptiste Daroussin is_array = false; 3164bf54857SBaptiste Daroussin break; 3174bf54857SBaptiste Daroussin } 3184bf54857SBaptiste Daroussin } 3194bf54857SBaptiste Daroussin else { 3204bf54857SBaptiste Daroussin /* Keys are not numeric */ 3214bf54857SBaptiste Daroussin lua_pop (L, 2); 3224bf54857SBaptiste Daroussin is_array = false; 3234bf54857SBaptiste Daroussin break; 3244bf54857SBaptiste Daroussin } 3254bf54857SBaptiste Daroussin lua_pop (L, 1); 3264bf54857SBaptiste Daroussin } 3274bf54857SBaptiste Daroussin 3284bf54857SBaptiste Daroussin /* Table iterate */ 3294bf54857SBaptiste Daroussin if (is_array) { 3304bf54857SBaptiste Daroussin int i; 3314bf54857SBaptiste Daroussin 3324bf54857SBaptiste Daroussin top = ucl_object_typed_new (UCL_ARRAY); 3334bf54857SBaptiste Daroussin for (i = 1; i <= max; i ++) { 3344bf54857SBaptiste Daroussin lua_pushinteger (L, i); 3354bf54857SBaptiste Daroussin lua_gettable (L, idx); 3364bf54857SBaptiste Daroussin obj = ucl_object_lua_fromelt (L, lua_gettop (L)); 3374bf54857SBaptiste Daroussin if (obj != NULL) { 3384bf54857SBaptiste Daroussin ucl_array_append (top, obj); 3394bf54857SBaptiste Daroussin } 340*39ee7a7aSBaptiste Daroussin lua_pop (L, 1); 3414bf54857SBaptiste Daroussin } 3424bf54857SBaptiste Daroussin } 3434bf54857SBaptiste Daroussin else { 3444bf54857SBaptiste Daroussin lua_pushnil (L); 3454bf54857SBaptiste Daroussin top = ucl_object_typed_new (UCL_OBJECT); 3464bf54857SBaptiste Daroussin while (lua_next (L, idx) != 0) { 3474bf54857SBaptiste Daroussin /* copy key to avoid modifications */ 3484bf54857SBaptiste Daroussin k = lua_tolstring (L, -2, &keylen); 3494bf54857SBaptiste Daroussin obj = ucl_object_lua_fromelt (L, lua_gettop (L)); 3504bf54857SBaptiste Daroussin 3514bf54857SBaptiste Daroussin if (obj != NULL) { 3524bf54857SBaptiste Daroussin ucl_object_insert_key (top, obj, k, keylen, true); 3534bf54857SBaptiste Daroussin } 3544bf54857SBaptiste Daroussin lua_pop (L, 1); 3554bf54857SBaptiste Daroussin } 3564bf54857SBaptiste Daroussin } 3574bf54857SBaptiste Daroussin 3584bf54857SBaptiste Daroussin return top; 3594bf54857SBaptiste Daroussin } 3604bf54857SBaptiste Daroussin 3614bf54857SBaptiste Daroussin /** 3624bf54857SBaptiste Daroussin * Get a single element from lua to object obj 3634bf54857SBaptiste Daroussin * @param L 3644bf54857SBaptiste Daroussin * @param obj 3654bf54857SBaptiste Daroussin * @param idx 3664bf54857SBaptiste Daroussin */ 3674bf54857SBaptiste Daroussin static ucl_object_t * 3684bf54857SBaptiste Daroussin ucl_object_lua_fromelt (lua_State *L, int idx) 3694bf54857SBaptiste Daroussin { 3704bf54857SBaptiste Daroussin int type; 3714bf54857SBaptiste Daroussin double num; 3724bf54857SBaptiste Daroussin ucl_object_t *obj = NULL; 3734bf54857SBaptiste Daroussin struct ucl_lua_funcdata *fd; 3744bf54857SBaptiste Daroussin 3754bf54857SBaptiste Daroussin type = lua_type (L, idx); 3764bf54857SBaptiste Daroussin 3774bf54857SBaptiste Daroussin switch (type) { 3784bf54857SBaptiste Daroussin case LUA_TSTRING: 3794bf54857SBaptiste Daroussin obj = ucl_object_fromstring_common (lua_tostring (L, idx), 0, 0); 3804bf54857SBaptiste Daroussin break; 3814bf54857SBaptiste Daroussin case LUA_TNUMBER: 3824bf54857SBaptiste Daroussin num = lua_tonumber (L, idx); 3834bf54857SBaptiste Daroussin if (num == (int64_t)num) { 3844bf54857SBaptiste Daroussin obj = ucl_object_fromint (num); 3854bf54857SBaptiste Daroussin } 3864bf54857SBaptiste Daroussin else { 3874bf54857SBaptiste Daroussin obj = ucl_object_fromdouble (num); 3884bf54857SBaptiste Daroussin } 3894bf54857SBaptiste Daroussin break; 3904bf54857SBaptiste Daroussin case LUA_TBOOLEAN: 3914bf54857SBaptiste Daroussin obj = ucl_object_frombool (lua_toboolean (L, idx)); 3924bf54857SBaptiste Daroussin break; 3934bf54857SBaptiste Daroussin case LUA_TUSERDATA: 3944bf54857SBaptiste Daroussin if (lua_topointer (L, idx) == ucl_null) { 3954bf54857SBaptiste Daroussin obj = ucl_object_typed_new (UCL_NULL); 3964bf54857SBaptiste Daroussin } 3974bf54857SBaptiste Daroussin break; 3984bf54857SBaptiste Daroussin case LUA_TTABLE: 3994bf54857SBaptiste Daroussin case LUA_TFUNCTION: 4004bf54857SBaptiste Daroussin case LUA_TTHREAD: 4014bf54857SBaptiste Daroussin if (luaL_getmetafield (L, idx, "__gen_ucl")) { 4024bf54857SBaptiste Daroussin if (lua_isfunction (L, -1)) { 4034bf54857SBaptiste Daroussin lua_settop (L, 3); /* gen, obj, func */ 4044bf54857SBaptiste Daroussin lua_insert (L, 1); /* func, gen, obj */ 4054bf54857SBaptiste Daroussin lua_insert (L, 2); /* func, obj, gen */ 4064bf54857SBaptiste Daroussin lua_call(L, 2, 1); 4074bf54857SBaptiste Daroussin obj = ucl_object_lua_fromelt (L, 1); 4084bf54857SBaptiste Daroussin } 4094bf54857SBaptiste Daroussin lua_pop (L, 2); 4104bf54857SBaptiste Daroussin } 4114bf54857SBaptiste Daroussin else { 4124bf54857SBaptiste Daroussin if (type == LUA_TTABLE) { 4134bf54857SBaptiste Daroussin obj = ucl_object_lua_fromtable (L, idx); 4144bf54857SBaptiste Daroussin } 4154bf54857SBaptiste Daroussin else if (type == LUA_TFUNCTION) { 4164bf54857SBaptiste Daroussin fd = malloc (sizeof (*fd)); 4174bf54857SBaptiste Daroussin if (fd != NULL) { 4184bf54857SBaptiste Daroussin lua_pushvalue (L, idx); 4194bf54857SBaptiste Daroussin fd->L = L; 4204bf54857SBaptiste Daroussin fd->ret = NULL; 4214bf54857SBaptiste Daroussin fd->idx = luaL_ref (L, LUA_REGISTRYINDEX); 4224bf54857SBaptiste Daroussin 4234bf54857SBaptiste Daroussin obj = ucl_object_new_userdata (lua_ucl_userdata_dtor, 4244bf54857SBaptiste Daroussin lua_ucl_userdata_emitter); 4254bf54857SBaptiste Daroussin obj->type = UCL_USERDATA; 4264bf54857SBaptiste Daroussin obj->value.ud = (void *)fd; 4274bf54857SBaptiste Daroussin } 4284bf54857SBaptiste Daroussin } 4294bf54857SBaptiste Daroussin } 4304bf54857SBaptiste Daroussin break; 4314bf54857SBaptiste Daroussin } 4324bf54857SBaptiste Daroussin 4334bf54857SBaptiste Daroussin return obj; 4344bf54857SBaptiste Daroussin } 4354bf54857SBaptiste Daroussin 4364bf54857SBaptiste Daroussin /** 4374bf54857SBaptiste Daroussin * @function ucl_object_lua_import(L, idx) 4384bf54857SBaptiste Daroussin * Extracts ucl object from lua variable at `idx` position, 4394bf54857SBaptiste Daroussin * @see ucl_object_push_lua for conversion definitions 4404bf54857SBaptiste Daroussin * @param {lua_state} L lua state machine pointer 4414bf54857SBaptiste Daroussin * @param {int} idx index where the source variable is placed 4424bf54857SBaptiste Daroussin * @return {ucl_object_t} new ucl object extracted from lua variable. Reference count of this object is 1, 4434bf54857SBaptiste Daroussin * this object thus needs to be unref'ed after usage. 4444bf54857SBaptiste Daroussin */ 4454bf54857SBaptiste Daroussin ucl_object_t * 4464bf54857SBaptiste Daroussin ucl_object_lua_import (lua_State *L, int idx) 4474bf54857SBaptiste Daroussin { 4484bf54857SBaptiste Daroussin ucl_object_t *obj; 4494bf54857SBaptiste Daroussin int t; 4504bf54857SBaptiste Daroussin 4514bf54857SBaptiste Daroussin t = lua_type (L, idx); 4524bf54857SBaptiste Daroussin switch (t) { 4534bf54857SBaptiste Daroussin case LUA_TTABLE: 4544bf54857SBaptiste Daroussin obj = ucl_object_lua_fromtable (L, idx); 4554bf54857SBaptiste Daroussin break; 4564bf54857SBaptiste Daroussin default: 4574bf54857SBaptiste Daroussin obj = ucl_object_lua_fromelt (L, idx); 4584bf54857SBaptiste Daroussin break; 4594bf54857SBaptiste Daroussin } 4604bf54857SBaptiste Daroussin 4614bf54857SBaptiste Daroussin return obj; 4624bf54857SBaptiste Daroussin } 4634bf54857SBaptiste Daroussin 4644bf54857SBaptiste Daroussin static int 465*39ee7a7aSBaptiste Daroussin lua_ucl_to_string (lua_State *L, const ucl_object_t *obj, enum ucl_emitter type) 466*39ee7a7aSBaptiste Daroussin { 467*39ee7a7aSBaptiste Daroussin unsigned char *result; 468*39ee7a7aSBaptiste Daroussin 469*39ee7a7aSBaptiste Daroussin result = ucl_object_emit (obj, type); 470*39ee7a7aSBaptiste Daroussin 471*39ee7a7aSBaptiste Daroussin if (result != NULL) { 472*39ee7a7aSBaptiste Daroussin lua_pushstring (L, (const char *)result); 473*39ee7a7aSBaptiste Daroussin free (result); 474*39ee7a7aSBaptiste Daroussin } 475*39ee7a7aSBaptiste Daroussin else { 476*39ee7a7aSBaptiste Daroussin lua_pushnil (L); 477*39ee7a7aSBaptiste Daroussin } 478*39ee7a7aSBaptiste Daroussin 479*39ee7a7aSBaptiste Daroussin return 1; 480*39ee7a7aSBaptiste Daroussin } 481*39ee7a7aSBaptiste Daroussin 482*39ee7a7aSBaptiste Daroussin static int 4834bf54857SBaptiste Daroussin lua_ucl_parser_init (lua_State *L) 4844bf54857SBaptiste Daroussin { 4854bf54857SBaptiste Daroussin struct ucl_parser *parser, **pparser; 4864bf54857SBaptiste Daroussin int flags = 0; 4874bf54857SBaptiste Daroussin 4884bf54857SBaptiste Daroussin if (lua_gettop (L) >= 1) { 4894bf54857SBaptiste Daroussin flags = lua_tonumber (L, 1); 4904bf54857SBaptiste Daroussin } 4914bf54857SBaptiste Daroussin 4924bf54857SBaptiste Daroussin parser = ucl_parser_new (flags); 4934bf54857SBaptiste Daroussin if (parser == NULL) { 4944bf54857SBaptiste Daroussin lua_pushnil (L); 4954bf54857SBaptiste Daroussin } 4964bf54857SBaptiste Daroussin 4974bf54857SBaptiste Daroussin pparser = lua_newuserdata (L, sizeof (parser)); 4984bf54857SBaptiste Daroussin *pparser = parser; 4994bf54857SBaptiste Daroussin luaL_getmetatable (L, PARSER_META); 5004bf54857SBaptiste Daroussin lua_setmetatable (L, -2); 5014bf54857SBaptiste Daroussin 5024bf54857SBaptiste Daroussin return 1; 5034bf54857SBaptiste Daroussin } 5044bf54857SBaptiste Daroussin 5054bf54857SBaptiste Daroussin static struct ucl_parser * 5064bf54857SBaptiste Daroussin lua_ucl_parser_get (lua_State *L, int index) 5074bf54857SBaptiste Daroussin { 5084bf54857SBaptiste Daroussin return *((struct ucl_parser **) luaL_checkudata(L, index, PARSER_META)); 5094bf54857SBaptiste Daroussin } 5104bf54857SBaptiste Daroussin 511*39ee7a7aSBaptiste Daroussin static ucl_object_t * 512*39ee7a7aSBaptiste Daroussin lua_ucl_object_get (lua_State *L, int index) 513*39ee7a7aSBaptiste Daroussin { 514*39ee7a7aSBaptiste Daroussin return *((ucl_object_t **) luaL_checkudata(L, index, OBJECT_META)); 515*39ee7a7aSBaptiste Daroussin } 516*39ee7a7aSBaptiste Daroussin 5174bf54857SBaptiste Daroussin /*** 5184bf54857SBaptiste Daroussin * @method parser:parse_file(name) 5194bf54857SBaptiste Daroussin * Parse UCL object from file. 5204bf54857SBaptiste Daroussin * @param {string} name filename to parse 5214bf54857SBaptiste Daroussin * @return {bool[, string]} if res is `true` then file has been parsed successfully, otherwise an error string is also returned 5224bf54857SBaptiste Daroussin @example 5234bf54857SBaptiste Daroussin local parser = ucl.parser() 5244bf54857SBaptiste Daroussin local res,err = parser:parse_file('/some/file.conf') 5254bf54857SBaptiste Daroussin 5264bf54857SBaptiste Daroussin if not res then 5274bf54857SBaptiste Daroussin print('parser error: ' .. err) 5284bf54857SBaptiste Daroussin else 5294bf54857SBaptiste Daroussin -- Do something with object 5304bf54857SBaptiste Daroussin end 5314bf54857SBaptiste Daroussin */ 5324bf54857SBaptiste Daroussin static int 5334bf54857SBaptiste Daroussin lua_ucl_parser_parse_file (lua_State *L) 5344bf54857SBaptiste Daroussin { 5354bf54857SBaptiste Daroussin struct ucl_parser *parser; 5364bf54857SBaptiste Daroussin const char *file; 5374bf54857SBaptiste Daroussin int ret = 2; 5384bf54857SBaptiste Daroussin 5394bf54857SBaptiste Daroussin parser = lua_ucl_parser_get (L, 1); 5404bf54857SBaptiste Daroussin file = luaL_checkstring (L, 2); 5414bf54857SBaptiste Daroussin 5424bf54857SBaptiste Daroussin if (parser != NULL && file != NULL) { 5434bf54857SBaptiste Daroussin if (ucl_parser_add_file (parser, file)) { 5444bf54857SBaptiste Daroussin lua_pushboolean (L, true); 5454bf54857SBaptiste Daroussin ret = 1; 5464bf54857SBaptiste Daroussin } 5474bf54857SBaptiste Daroussin else { 5484bf54857SBaptiste Daroussin lua_pushboolean (L, false); 5494bf54857SBaptiste Daroussin lua_pushstring (L, ucl_parser_get_error (parser)); 5504bf54857SBaptiste Daroussin } 5514bf54857SBaptiste Daroussin } 5524bf54857SBaptiste Daroussin else { 5534bf54857SBaptiste Daroussin lua_pushboolean (L, false); 5544bf54857SBaptiste Daroussin lua_pushstring (L, "invalid arguments"); 5554bf54857SBaptiste Daroussin } 5564bf54857SBaptiste Daroussin 5574bf54857SBaptiste Daroussin return ret; 5584bf54857SBaptiste Daroussin } 5594bf54857SBaptiste Daroussin 5604bf54857SBaptiste Daroussin /*** 5614bf54857SBaptiste Daroussin * @method parser:parse_string(input) 5624bf54857SBaptiste Daroussin * Parse UCL object from file. 5634bf54857SBaptiste Daroussin * @param {string} input string to parse 5644bf54857SBaptiste Daroussin * @return {bool[, string]} if res is `true` then file has been parsed successfully, otherwise an error string is also returned 5654bf54857SBaptiste Daroussin */ 5664bf54857SBaptiste Daroussin static int 5674bf54857SBaptiste Daroussin lua_ucl_parser_parse_string (lua_State *L) 5684bf54857SBaptiste Daroussin { 5694bf54857SBaptiste Daroussin struct ucl_parser *parser; 5704bf54857SBaptiste Daroussin const char *string; 5714bf54857SBaptiste Daroussin size_t llen; 5724bf54857SBaptiste Daroussin int ret = 2; 5734bf54857SBaptiste Daroussin 5744bf54857SBaptiste Daroussin parser = lua_ucl_parser_get (L, 1); 5754bf54857SBaptiste Daroussin string = luaL_checklstring (L, 2, &llen); 5764bf54857SBaptiste Daroussin 5774bf54857SBaptiste Daroussin if (parser != NULL && string != NULL) { 5784bf54857SBaptiste Daroussin if (ucl_parser_add_chunk (parser, (const unsigned char *)string, llen)) { 5794bf54857SBaptiste Daroussin lua_pushboolean (L, true); 5804bf54857SBaptiste Daroussin ret = 1; 5814bf54857SBaptiste Daroussin } 5824bf54857SBaptiste Daroussin else { 5834bf54857SBaptiste Daroussin lua_pushboolean (L, false); 5844bf54857SBaptiste Daroussin lua_pushstring (L, ucl_parser_get_error (parser)); 5854bf54857SBaptiste Daroussin } 5864bf54857SBaptiste Daroussin } 5874bf54857SBaptiste Daroussin else { 5884bf54857SBaptiste Daroussin lua_pushboolean (L, false); 5894bf54857SBaptiste Daroussin lua_pushstring (L, "invalid arguments"); 5904bf54857SBaptiste Daroussin } 5914bf54857SBaptiste Daroussin 5924bf54857SBaptiste Daroussin return ret; 5934bf54857SBaptiste Daroussin } 5944bf54857SBaptiste Daroussin 5954bf54857SBaptiste Daroussin /*** 5964bf54857SBaptiste Daroussin * @method parser:get_object() 5974bf54857SBaptiste Daroussin * Get top object from parser and export it to lua representation. 5984bf54857SBaptiste Daroussin * @return {variant or nil} ucl object as lua native variable 5994bf54857SBaptiste Daroussin */ 6004bf54857SBaptiste Daroussin static int 6014bf54857SBaptiste Daroussin lua_ucl_parser_get_object (lua_State *L) 6024bf54857SBaptiste Daroussin { 6034bf54857SBaptiste Daroussin struct ucl_parser *parser; 6044bf54857SBaptiste Daroussin ucl_object_t *obj; 6054bf54857SBaptiste Daroussin int ret = 1; 6064bf54857SBaptiste Daroussin 6074bf54857SBaptiste Daroussin parser = lua_ucl_parser_get (L, 1); 6084bf54857SBaptiste Daroussin obj = ucl_parser_get_object (parser); 6094bf54857SBaptiste Daroussin 6104bf54857SBaptiste Daroussin if (obj != NULL) { 6114bf54857SBaptiste Daroussin ret = ucl_object_push_lua (L, obj, false); 6124bf54857SBaptiste Daroussin /* no need to keep reference */ 6134bf54857SBaptiste Daroussin ucl_object_unref (obj); 6144bf54857SBaptiste Daroussin } 6154bf54857SBaptiste Daroussin else { 6164bf54857SBaptiste Daroussin lua_pushnil (L); 6174bf54857SBaptiste Daroussin } 6184bf54857SBaptiste Daroussin 6194bf54857SBaptiste Daroussin return ret; 6204bf54857SBaptiste Daroussin } 6214bf54857SBaptiste Daroussin 622*39ee7a7aSBaptiste Daroussin /*** 623*39ee7a7aSBaptiste Daroussin * @method parser:get_object_wrapped() 624*39ee7a7aSBaptiste Daroussin * Get top object from parser and export it to userdata object without 625*39ee7a7aSBaptiste Daroussin * unwrapping to lua. 626*39ee7a7aSBaptiste Daroussin * @return {ucl.object or nil} ucl object wrapped variable 627*39ee7a7aSBaptiste Daroussin */ 628*39ee7a7aSBaptiste Daroussin static int 629*39ee7a7aSBaptiste Daroussin lua_ucl_parser_get_object_wrapped (lua_State *L) 630*39ee7a7aSBaptiste Daroussin { 631*39ee7a7aSBaptiste Daroussin struct ucl_parser *parser; 632*39ee7a7aSBaptiste Daroussin ucl_object_t *obj, **pobj; 633*39ee7a7aSBaptiste Daroussin int ret = 1; 634*39ee7a7aSBaptiste Daroussin 635*39ee7a7aSBaptiste Daroussin parser = lua_ucl_parser_get (L, 1); 636*39ee7a7aSBaptiste Daroussin obj = ucl_parser_get_object (parser); 637*39ee7a7aSBaptiste Daroussin 638*39ee7a7aSBaptiste Daroussin if (obj != NULL) { 639*39ee7a7aSBaptiste Daroussin pobj = lua_newuserdata (L, sizeof (*pobj)); 640*39ee7a7aSBaptiste Daroussin *pobj = obj; 641*39ee7a7aSBaptiste Daroussin luaL_getmetatable (L, OBJECT_META); 642*39ee7a7aSBaptiste Daroussin lua_setmetatable (L, -2); 643*39ee7a7aSBaptiste Daroussin } 644*39ee7a7aSBaptiste Daroussin else { 645*39ee7a7aSBaptiste Daroussin lua_pushnil (L); 646*39ee7a7aSBaptiste Daroussin } 647*39ee7a7aSBaptiste Daroussin 648*39ee7a7aSBaptiste Daroussin return ret; 649*39ee7a7aSBaptiste Daroussin } 650*39ee7a7aSBaptiste Daroussin 651*39ee7a7aSBaptiste Daroussin /*** 652*39ee7a7aSBaptiste Daroussin * @method parser:validate(schema) 653*39ee7a7aSBaptiste Daroussin * Validates the top object in the parser against schema. Schema might be 654*39ee7a7aSBaptiste Daroussin * another object or a string that represents file to load schema from. 655*39ee7a7aSBaptiste Daroussin * 656*39ee7a7aSBaptiste Daroussin * @param {string/table} schema input schema 657*39ee7a7aSBaptiste Daroussin * @return {result,err} two values: boolean result and the corresponding error 658*39ee7a7aSBaptiste Daroussin * 659*39ee7a7aSBaptiste Daroussin */ 660*39ee7a7aSBaptiste Daroussin static int 661*39ee7a7aSBaptiste Daroussin lua_ucl_parser_validate (lua_State *L) 662*39ee7a7aSBaptiste Daroussin { 663*39ee7a7aSBaptiste Daroussin struct ucl_parser *parser, *schema_parser; 664*39ee7a7aSBaptiste Daroussin ucl_object_t *schema; 665*39ee7a7aSBaptiste Daroussin const char *schema_file; 666*39ee7a7aSBaptiste Daroussin struct ucl_schema_error err; 667*39ee7a7aSBaptiste Daroussin 668*39ee7a7aSBaptiste Daroussin parser = lua_ucl_parser_get (L, 1); 669*39ee7a7aSBaptiste Daroussin 670*39ee7a7aSBaptiste Daroussin if (parser && parser->top_obj) { 671*39ee7a7aSBaptiste Daroussin if (lua_type (L, 2) == LUA_TTABLE) { 672*39ee7a7aSBaptiste Daroussin schema = ucl_object_lua_import (L, 2); 673*39ee7a7aSBaptiste Daroussin 674*39ee7a7aSBaptiste Daroussin if (schema == NULL) { 675*39ee7a7aSBaptiste Daroussin lua_pushboolean (L, false); 676*39ee7a7aSBaptiste Daroussin lua_pushstring (L, "cannot load schema from lua table"); 677*39ee7a7aSBaptiste Daroussin 678*39ee7a7aSBaptiste Daroussin return 2; 679*39ee7a7aSBaptiste Daroussin } 680*39ee7a7aSBaptiste Daroussin } 681*39ee7a7aSBaptiste Daroussin else if (lua_type (L, 2) == LUA_TSTRING) { 682*39ee7a7aSBaptiste Daroussin schema_parser = ucl_parser_new (0); 683*39ee7a7aSBaptiste Daroussin schema_file = luaL_checkstring (L, 2); 684*39ee7a7aSBaptiste Daroussin 685*39ee7a7aSBaptiste Daroussin if (!ucl_parser_add_file (schema_parser, schema_file)) { 686*39ee7a7aSBaptiste Daroussin lua_pushboolean (L, false); 687*39ee7a7aSBaptiste Daroussin lua_pushfstring (L, "cannot parse schema file \"%s\": " 688*39ee7a7aSBaptiste Daroussin "%s", schema_file, ucl_parser_get_error (parser)); 689*39ee7a7aSBaptiste Daroussin ucl_parser_free (schema_parser); 690*39ee7a7aSBaptiste Daroussin 691*39ee7a7aSBaptiste Daroussin return 2; 692*39ee7a7aSBaptiste Daroussin } 693*39ee7a7aSBaptiste Daroussin 694*39ee7a7aSBaptiste Daroussin schema = ucl_parser_get_object (schema_parser); 695*39ee7a7aSBaptiste Daroussin ucl_parser_free (schema_parser); 696*39ee7a7aSBaptiste Daroussin } 697*39ee7a7aSBaptiste Daroussin else { 698*39ee7a7aSBaptiste Daroussin lua_pushboolean (L, false); 699*39ee7a7aSBaptiste Daroussin lua_pushstring (L, "invalid schema argument"); 700*39ee7a7aSBaptiste Daroussin 701*39ee7a7aSBaptiste Daroussin return 2; 702*39ee7a7aSBaptiste Daroussin } 703*39ee7a7aSBaptiste Daroussin 704*39ee7a7aSBaptiste Daroussin if (!ucl_object_validate (schema, parser->top_obj, &err)) { 705*39ee7a7aSBaptiste Daroussin lua_pushboolean (L, false); 706*39ee7a7aSBaptiste Daroussin lua_pushfstring (L, "validation error: " 707*39ee7a7aSBaptiste Daroussin "%s", err.msg); 708*39ee7a7aSBaptiste Daroussin } 709*39ee7a7aSBaptiste Daroussin else { 710*39ee7a7aSBaptiste Daroussin lua_pushboolean (L, true); 711*39ee7a7aSBaptiste Daroussin lua_pushnil (L); 712*39ee7a7aSBaptiste Daroussin } 713*39ee7a7aSBaptiste Daroussin 714*39ee7a7aSBaptiste Daroussin ucl_object_unref (schema); 715*39ee7a7aSBaptiste Daroussin } 716*39ee7a7aSBaptiste Daroussin else { 717*39ee7a7aSBaptiste Daroussin lua_pushboolean (L, false); 718*39ee7a7aSBaptiste Daroussin lua_pushstring (L, "invalid parser or empty top object"); 719*39ee7a7aSBaptiste Daroussin } 720*39ee7a7aSBaptiste Daroussin 721*39ee7a7aSBaptiste Daroussin return 2; 722*39ee7a7aSBaptiste Daroussin } 723*39ee7a7aSBaptiste Daroussin 7244bf54857SBaptiste Daroussin static int 7254bf54857SBaptiste Daroussin lua_ucl_parser_gc (lua_State *L) 7264bf54857SBaptiste Daroussin { 7274bf54857SBaptiste Daroussin struct ucl_parser *parser; 7284bf54857SBaptiste Daroussin 7294bf54857SBaptiste Daroussin parser = lua_ucl_parser_get (L, 1); 7304bf54857SBaptiste Daroussin ucl_parser_free (parser); 7314bf54857SBaptiste Daroussin 7324bf54857SBaptiste Daroussin return 0; 7334bf54857SBaptiste Daroussin } 7344bf54857SBaptiste Daroussin 735*39ee7a7aSBaptiste Daroussin /*** 736*39ee7a7aSBaptiste Daroussin * @method object:unwrap() 737*39ee7a7aSBaptiste Daroussin * Unwraps opaque ucl object to the native lua object (performing copying) 738*39ee7a7aSBaptiste Daroussin * @return {variant} any lua object 739*39ee7a7aSBaptiste Daroussin */ 740*39ee7a7aSBaptiste Daroussin static int 741*39ee7a7aSBaptiste Daroussin lua_ucl_object_unwrap (lua_State *L) 742*39ee7a7aSBaptiste Daroussin { 743*39ee7a7aSBaptiste Daroussin ucl_object_t *obj; 744*39ee7a7aSBaptiste Daroussin 745*39ee7a7aSBaptiste Daroussin obj = lua_ucl_object_get (L, 1); 746*39ee7a7aSBaptiste Daroussin 747*39ee7a7aSBaptiste Daroussin if (obj) { 748*39ee7a7aSBaptiste Daroussin ucl_object_push_lua (L, obj, true); 749*39ee7a7aSBaptiste Daroussin } 750*39ee7a7aSBaptiste Daroussin else { 751*39ee7a7aSBaptiste Daroussin lua_pushnil (L); 752*39ee7a7aSBaptiste Daroussin } 753*39ee7a7aSBaptiste Daroussin 754*39ee7a7aSBaptiste Daroussin return 1; 755*39ee7a7aSBaptiste Daroussin } 756*39ee7a7aSBaptiste Daroussin 757*39ee7a7aSBaptiste Daroussin /*** 758*39ee7a7aSBaptiste Daroussin * @method object:tostring(type) 759*39ee7a7aSBaptiste Daroussin * Unwraps opaque ucl object to string (json by default). Optionally you can 760*39ee7a7aSBaptiste Daroussin * specify output format: 761*39ee7a7aSBaptiste Daroussin * 762*39ee7a7aSBaptiste Daroussin * - `json` - fine printed json 763*39ee7a7aSBaptiste Daroussin * - `json-compact` - compacted json 764*39ee7a7aSBaptiste Daroussin * - `config` - fine printed configuration 765*39ee7a7aSBaptiste Daroussin * - `ucl` - same as `config` 766*39ee7a7aSBaptiste Daroussin * - `yaml` - embedded yaml 767*39ee7a7aSBaptiste Daroussin * @param {string} type optional 768*39ee7a7aSBaptiste Daroussin * @return {string} string representation of the opaque ucl object 769*39ee7a7aSBaptiste Daroussin */ 770*39ee7a7aSBaptiste Daroussin static int 771*39ee7a7aSBaptiste Daroussin lua_ucl_object_tostring (lua_State *L) 772*39ee7a7aSBaptiste Daroussin { 773*39ee7a7aSBaptiste Daroussin ucl_object_t *obj; 774*39ee7a7aSBaptiste Daroussin enum ucl_emitter format = UCL_EMIT_JSON_COMPACT; 775*39ee7a7aSBaptiste Daroussin 776*39ee7a7aSBaptiste Daroussin obj = lua_ucl_object_get (L, 1); 777*39ee7a7aSBaptiste Daroussin 778*39ee7a7aSBaptiste Daroussin if (obj) { 779*39ee7a7aSBaptiste Daroussin if (lua_gettop (L) > 1) { 780*39ee7a7aSBaptiste Daroussin if (lua_type (L, 2) == LUA_TSTRING) { 781*39ee7a7aSBaptiste Daroussin const char *strtype = lua_tostring (L, 2); 782*39ee7a7aSBaptiste Daroussin 783*39ee7a7aSBaptiste Daroussin if (strcasecmp (strtype, "json") == 0) { 784*39ee7a7aSBaptiste Daroussin format = UCL_EMIT_JSON; 785*39ee7a7aSBaptiste Daroussin } 786*39ee7a7aSBaptiste Daroussin else if (strcasecmp (strtype, "json-compact") == 0) { 787*39ee7a7aSBaptiste Daroussin format = UCL_EMIT_JSON_COMPACT; 788*39ee7a7aSBaptiste Daroussin } 789*39ee7a7aSBaptiste Daroussin else if (strcasecmp (strtype, "yaml") == 0) { 790*39ee7a7aSBaptiste Daroussin format = UCL_EMIT_YAML; 791*39ee7a7aSBaptiste Daroussin } 792*39ee7a7aSBaptiste Daroussin else if (strcasecmp (strtype, "config") == 0 || 793*39ee7a7aSBaptiste Daroussin strcasecmp (strtype, "ucl") == 0) { 794*39ee7a7aSBaptiste Daroussin format = UCL_EMIT_CONFIG; 795*39ee7a7aSBaptiste Daroussin } 796*39ee7a7aSBaptiste Daroussin } 797*39ee7a7aSBaptiste Daroussin } 798*39ee7a7aSBaptiste Daroussin 799*39ee7a7aSBaptiste Daroussin return lua_ucl_to_string (L, obj, format); 800*39ee7a7aSBaptiste Daroussin } 801*39ee7a7aSBaptiste Daroussin else { 802*39ee7a7aSBaptiste Daroussin lua_pushnil (L); 803*39ee7a7aSBaptiste Daroussin } 804*39ee7a7aSBaptiste Daroussin 805*39ee7a7aSBaptiste Daroussin return 1; 806*39ee7a7aSBaptiste Daroussin } 807*39ee7a7aSBaptiste Daroussin 808*39ee7a7aSBaptiste Daroussin /*** 809*39ee7a7aSBaptiste Daroussin * @method object:validate(schema, path) 810*39ee7a7aSBaptiste Daroussin * Validates the given ucl object using schema object represented as another 811*39ee7a7aSBaptiste Daroussin * opaque ucl object. You can also specify path in the form `#/path/def` to 812*39ee7a7aSBaptiste Daroussin * specify the specific schema element to perform validation. 813*39ee7a7aSBaptiste Daroussin * 814*39ee7a7aSBaptiste Daroussin * @param {ucl.object} schema schema object 815*39ee7a7aSBaptiste Daroussin * @param {string} path optional path for validation procedure 816*39ee7a7aSBaptiste Daroussin * @return {result,err} two values: boolean result and the corresponding error 817*39ee7a7aSBaptiste Daroussin */ 818*39ee7a7aSBaptiste Daroussin static int 819*39ee7a7aSBaptiste Daroussin lua_ucl_object_validate (lua_State *L) 820*39ee7a7aSBaptiste Daroussin { 821*39ee7a7aSBaptiste Daroussin ucl_object_t *obj, *schema; 822*39ee7a7aSBaptiste Daroussin const ucl_object_t *schema_elt; 823*39ee7a7aSBaptiste Daroussin bool res = false; 824*39ee7a7aSBaptiste Daroussin struct ucl_schema_error err; 825*39ee7a7aSBaptiste Daroussin const char *path = NULL; 826*39ee7a7aSBaptiste Daroussin 827*39ee7a7aSBaptiste Daroussin obj = lua_ucl_object_get (L, 1); 828*39ee7a7aSBaptiste Daroussin schema = lua_ucl_object_get (L, 2); 829*39ee7a7aSBaptiste Daroussin 830*39ee7a7aSBaptiste Daroussin if (schema && obj && ucl_object_type (schema) == UCL_OBJECT) { 831*39ee7a7aSBaptiste Daroussin if (lua_gettop (L) > 2 && lua_type (L, 3) == LUA_TSTRING) { 832*39ee7a7aSBaptiste Daroussin path = lua_tostring (L, 3); 833*39ee7a7aSBaptiste Daroussin if (path[0] == '#') { 834*39ee7a7aSBaptiste Daroussin path ++; 835*39ee7a7aSBaptiste Daroussin } 836*39ee7a7aSBaptiste Daroussin } 837*39ee7a7aSBaptiste Daroussin 838*39ee7a7aSBaptiste Daroussin if (path) { 839*39ee7a7aSBaptiste Daroussin schema_elt = ucl_lookup_path_char (schema, path, '/'); 840*39ee7a7aSBaptiste Daroussin } 841*39ee7a7aSBaptiste Daroussin else { 842*39ee7a7aSBaptiste Daroussin /* Use the top object */ 843*39ee7a7aSBaptiste Daroussin schema_elt = schema; 844*39ee7a7aSBaptiste Daroussin } 845*39ee7a7aSBaptiste Daroussin 846*39ee7a7aSBaptiste Daroussin if (schema_elt) { 847*39ee7a7aSBaptiste Daroussin res = ucl_object_validate (schema_elt, obj, &err); 848*39ee7a7aSBaptiste Daroussin 849*39ee7a7aSBaptiste Daroussin if (res) { 850*39ee7a7aSBaptiste Daroussin lua_pushboolean (L, res); 851*39ee7a7aSBaptiste Daroussin lua_pushnil (L); 852*39ee7a7aSBaptiste Daroussin } 853*39ee7a7aSBaptiste Daroussin else { 854*39ee7a7aSBaptiste Daroussin lua_pushboolean (L, res); 855*39ee7a7aSBaptiste Daroussin lua_pushfstring (L, "validation error: %s", err.msg); 856*39ee7a7aSBaptiste Daroussin } 857*39ee7a7aSBaptiste Daroussin } 858*39ee7a7aSBaptiste Daroussin else { 859*39ee7a7aSBaptiste Daroussin lua_pushboolean (L, res); 860*39ee7a7aSBaptiste Daroussin 861*39ee7a7aSBaptiste Daroussin if (path) { 862*39ee7a7aSBaptiste Daroussin lua_pushfstring (L, "cannot find the requested path: %s", path); 863*39ee7a7aSBaptiste Daroussin } 864*39ee7a7aSBaptiste Daroussin else { 865*39ee7a7aSBaptiste Daroussin /* Should not be reached */ 866*39ee7a7aSBaptiste Daroussin lua_pushstring (L, "unknown error"); 867*39ee7a7aSBaptiste Daroussin } 868*39ee7a7aSBaptiste Daroussin } 869*39ee7a7aSBaptiste Daroussin } 870*39ee7a7aSBaptiste Daroussin else { 871*39ee7a7aSBaptiste Daroussin lua_pushboolean (L, res); 872*39ee7a7aSBaptiste Daroussin lua_pushstring (L, "invalid object or schema"); 873*39ee7a7aSBaptiste Daroussin } 874*39ee7a7aSBaptiste Daroussin 875*39ee7a7aSBaptiste Daroussin return 2; 876*39ee7a7aSBaptiste Daroussin } 877*39ee7a7aSBaptiste Daroussin 878*39ee7a7aSBaptiste Daroussin static int 879*39ee7a7aSBaptiste Daroussin lua_ucl_object_gc (lua_State *L) 880*39ee7a7aSBaptiste Daroussin { 881*39ee7a7aSBaptiste Daroussin ucl_object_t *obj; 882*39ee7a7aSBaptiste Daroussin 883*39ee7a7aSBaptiste Daroussin obj = lua_ucl_object_get (L, 1); 884*39ee7a7aSBaptiste Daroussin 885*39ee7a7aSBaptiste Daroussin ucl_object_unref (obj); 886*39ee7a7aSBaptiste Daroussin 887*39ee7a7aSBaptiste Daroussin return 0; 888*39ee7a7aSBaptiste Daroussin } 889*39ee7a7aSBaptiste Daroussin 8904bf54857SBaptiste Daroussin static void 8914bf54857SBaptiste Daroussin lua_ucl_parser_mt (lua_State *L) 8924bf54857SBaptiste Daroussin { 8934bf54857SBaptiste Daroussin luaL_newmetatable (L, PARSER_META); 8944bf54857SBaptiste Daroussin 8954bf54857SBaptiste Daroussin lua_pushvalue(L, -1); 8964bf54857SBaptiste Daroussin lua_setfield(L, -2, "__index"); 8974bf54857SBaptiste Daroussin 8984bf54857SBaptiste Daroussin lua_pushcfunction (L, lua_ucl_parser_gc); 8994bf54857SBaptiste Daroussin lua_setfield (L, -2, "__gc"); 9004bf54857SBaptiste Daroussin 9014bf54857SBaptiste Daroussin lua_pushcfunction (L, lua_ucl_parser_parse_file); 9024bf54857SBaptiste Daroussin lua_setfield (L, -2, "parse_file"); 9034bf54857SBaptiste Daroussin 9044bf54857SBaptiste Daroussin lua_pushcfunction (L, lua_ucl_parser_parse_string); 9054bf54857SBaptiste Daroussin lua_setfield (L, -2, "parse_string"); 9064bf54857SBaptiste Daroussin 9074bf54857SBaptiste Daroussin lua_pushcfunction (L, lua_ucl_parser_get_object); 9084bf54857SBaptiste Daroussin lua_setfield (L, -2, "get_object"); 9094bf54857SBaptiste Daroussin 910*39ee7a7aSBaptiste Daroussin lua_pushcfunction (L, lua_ucl_parser_get_object_wrapped); 911*39ee7a7aSBaptiste Daroussin lua_setfield (L, -2, "get_object_wrapped"); 912*39ee7a7aSBaptiste Daroussin 913*39ee7a7aSBaptiste Daroussin lua_pushcfunction (L, lua_ucl_parser_validate); 914*39ee7a7aSBaptiste Daroussin lua_setfield (L, -2, "validate"); 915*39ee7a7aSBaptiste Daroussin 9164bf54857SBaptiste Daroussin lua_pop (L, 1); 9174bf54857SBaptiste Daroussin } 9184bf54857SBaptiste Daroussin 919*39ee7a7aSBaptiste Daroussin static void 920*39ee7a7aSBaptiste Daroussin lua_ucl_object_mt (lua_State *L) 9214bf54857SBaptiste Daroussin { 922*39ee7a7aSBaptiste Daroussin luaL_newmetatable (L, OBJECT_META); 9234bf54857SBaptiste Daroussin 924*39ee7a7aSBaptiste Daroussin lua_pushvalue(L, -1); 925*39ee7a7aSBaptiste Daroussin lua_setfield(L, -2, "__index"); 9264bf54857SBaptiste Daroussin 927*39ee7a7aSBaptiste Daroussin lua_pushcfunction (L, lua_ucl_object_gc); 928*39ee7a7aSBaptiste Daroussin lua_setfield (L, -2, "__gc"); 9294bf54857SBaptiste Daroussin 930*39ee7a7aSBaptiste Daroussin lua_pushcfunction (L, lua_ucl_object_tostring); 931*39ee7a7aSBaptiste Daroussin lua_setfield (L, -2, "__tostring"); 932*39ee7a7aSBaptiste Daroussin 933*39ee7a7aSBaptiste Daroussin lua_pushcfunction (L, lua_ucl_object_tostring); 934*39ee7a7aSBaptiste Daroussin lua_setfield (L, -2, "tostring"); 935*39ee7a7aSBaptiste Daroussin 936*39ee7a7aSBaptiste Daroussin lua_pushcfunction (L, lua_ucl_object_unwrap); 937*39ee7a7aSBaptiste Daroussin lua_setfield (L, -2, "unwrap"); 938*39ee7a7aSBaptiste Daroussin 939*39ee7a7aSBaptiste Daroussin lua_pushcfunction (L, lua_ucl_object_unwrap); 940*39ee7a7aSBaptiste Daroussin lua_setfield (L, -2, "tolua"); 941*39ee7a7aSBaptiste Daroussin 942*39ee7a7aSBaptiste Daroussin lua_pushcfunction (L, lua_ucl_object_validate); 943*39ee7a7aSBaptiste Daroussin lua_setfield (L, -2, "validate"); 944*39ee7a7aSBaptiste Daroussin 945*39ee7a7aSBaptiste Daroussin lua_pushstring (L, OBJECT_META); 946*39ee7a7aSBaptiste Daroussin lua_setfield (L, -2, "class"); 947*39ee7a7aSBaptiste Daroussin 948*39ee7a7aSBaptiste Daroussin lua_pop (L, 1); 9494bf54857SBaptiste Daroussin } 9504bf54857SBaptiste Daroussin 9514bf54857SBaptiste Daroussin static int 9524bf54857SBaptiste Daroussin lua_ucl_to_json (lua_State *L) 9534bf54857SBaptiste Daroussin { 9544bf54857SBaptiste Daroussin ucl_object_t *obj; 9554bf54857SBaptiste Daroussin int format = UCL_EMIT_JSON; 9564bf54857SBaptiste Daroussin 9574bf54857SBaptiste Daroussin if (lua_gettop (L) > 1) { 9584bf54857SBaptiste Daroussin if (lua_toboolean (L, 2)) { 9594bf54857SBaptiste Daroussin format = UCL_EMIT_JSON_COMPACT; 9604bf54857SBaptiste Daroussin } 9614bf54857SBaptiste Daroussin } 9624bf54857SBaptiste Daroussin 9634bf54857SBaptiste Daroussin obj = ucl_object_lua_import (L, 1); 9644bf54857SBaptiste Daroussin if (obj != NULL) { 9654bf54857SBaptiste Daroussin lua_ucl_to_string (L, obj, format); 9664bf54857SBaptiste Daroussin ucl_object_unref (obj); 9674bf54857SBaptiste Daroussin } 9684bf54857SBaptiste Daroussin else { 9694bf54857SBaptiste Daroussin lua_pushnil (L); 9704bf54857SBaptiste Daroussin } 9714bf54857SBaptiste Daroussin 9724bf54857SBaptiste Daroussin return 1; 9734bf54857SBaptiste Daroussin } 9744bf54857SBaptiste Daroussin 9754bf54857SBaptiste Daroussin static int 9764bf54857SBaptiste Daroussin lua_ucl_to_config (lua_State *L) 9774bf54857SBaptiste Daroussin { 9784bf54857SBaptiste Daroussin ucl_object_t *obj; 9794bf54857SBaptiste Daroussin 9804bf54857SBaptiste Daroussin obj = ucl_object_lua_import (L, 1); 9814bf54857SBaptiste Daroussin if (obj != NULL) { 9824bf54857SBaptiste Daroussin lua_ucl_to_string (L, obj, UCL_EMIT_CONFIG); 9834bf54857SBaptiste Daroussin ucl_object_unref (obj); 9844bf54857SBaptiste Daroussin } 9854bf54857SBaptiste Daroussin else { 9864bf54857SBaptiste Daroussin lua_pushnil (L); 9874bf54857SBaptiste Daroussin } 9884bf54857SBaptiste Daroussin 9894bf54857SBaptiste Daroussin return 1; 9904bf54857SBaptiste Daroussin } 9914bf54857SBaptiste Daroussin 9924bf54857SBaptiste Daroussin /*** 9934bf54857SBaptiste Daroussin * @function ucl.to_format(var, format) 9944bf54857SBaptiste Daroussin * Converts lua variable `var` to the specified `format`. Formats supported are: 9954bf54857SBaptiste Daroussin * 9964bf54857SBaptiste Daroussin * - `json` - fine printed json 9974bf54857SBaptiste Daroussin * - `json-compact` - compacted json 9984bf54857SBaptiste Daroussin * - `config` - fine printed configuration 9994bf54857SBaptiste Daroussin * - `ucl` - same as `config` 10004bf54857SBaptiste Daroussin * - `yaml` - embedded yaml 10014bf54857SBaptiste Daroussin * 10024bf54857SBaptiste Daroussin * If `var` contains function, they are called during output formatting and if 10034bf54857SBaptiste Daroussin * they return string value, then this value is used for ouptut. 10044bf54857SBaptiste Daroussin * @param {variant} var any sort of lua variable (if userdata then metafield `__to_ucl` is searched for output) 10054bf54857SBaptiste Daroussin * @param {string} format any available format 10064bf54857SBaptiste Daroussin * @return {string} string representation of `var` in the specific `format`. 10074bf54857SBaptiste Daroussin * @example 10084bf54857SBaptiste Daroussin local table = { 10094bf54857SBaptiste Daroussin str = 'value', 10104bf54857SBaptiste Daroussin num = 100500, 10114bf54857SBaptiste Daroussin null = ucl.null, 10124bf54857SBaptiste Daroussin func = function () 10134bf54857SBaptiste Daroussin return 'huh' 10144bf54857SBaptiste Daroussin end 10154bf54857SBaptiste Daroussin } 10164bf54857SBaptiste Daroussin 10174bf54857SBaptiste Daroussin print(ucl.to_format(table, 'ucl')) 10184bf54857SBaptiste Daroussin -- Output: 10194bf54857SBaptiste Daroussin --[[ 10204bf54857SBaptiste Daroussin num = 100500; 10214bf54857SBaptiste Daroussin str = "value"; 10224bf54857SBaptiste Daroussin null = null; 10234bf54857SBaptiste Daroussin func = "huh"; 10244bf54857SBaptiste Daroussin --]] 10254bf54857SBaptiste Daroussin */ 10264bf54857SBaptiste Daroussin static int 10274bf54857SBaptiste Daroussin lua_ucl_to_format (lua_State *L) 10284bf54857SBaptiste Daroussin { 10294bf54857SBaptiste Daroussin ucl_object_t *obj; 10304bf54857SBaptiste Daroussin int format = UCL_EMIT_JSON; 10314bf54857SBaptiste Daroussin 10324bf54857SBaptiste Daroussin if (lua_gettop (L) > 1) { 10334bf54857SBaptiste Daroussin if (lua_type (L, 2) == LUA_TNUMBER) { 10344bf54857SBaptiste Daroussin format = lua_tonumber (L, 2); 10354bf54857SBaptiste Daroussin if (format < 0 || format >= UCL_EMIT_YAML) { 10364bf54857SBaptiste Daroussin lua_pushnil (L); 10374bf54857SBaptiste Daroussin return 1; 10384bf54857SBaptiste Daroussin } 10394bf54857SBaptiste Daroussin } 10404bf54857SBaptiste Daroussin else if (lua_type (L, 2) == LUA_TSTRING) { 10414bf54857SBaptiste Daroussin const char *strtype = lua_tostring (L, 2); 10424bf54857SBaptiste Daroussin 10434bf54857SBaptiste Daroussin if (strcasecmp (strtype, "json") == 0) { 10444bf54857SBaptiste Daroussin format = UCL_EMIT_JSON; 10454bf54857SBaptiste Daroussin } 10464bf54857SBaptiste Daroussin else if (strcasecmp (strtype, "json-compact") == 0) { 10474bf54857SBaptiste Daroussin format = UCL_EMIT_JSON_COMPACT; 10484bf54857SBaptiste Daroussin } 10494bf54857SBaptiste Daroussin else if (strcasecmp (strtype, "yaml") == 0) { 10504bf54857SBaptiste Daroussin format = UCL_EMIT_YAML; 10514bf54857SBaptiste Daroussin } 10524bf54857SBaptiste Daroussin else if (strcasecmp (strtype, "config") == 0 || 10534bf54857SBaptiste Daroussin strcasecmp (strtype, "ucl") == 0) { 10544bf54857SBaptiste Daroussin format = UCL_EMIT_CONFIG; 10554bf54857SBaptiste Daroussin } 10564bf54857SBaptiste Daroussin } 10574bf54857SBaptiste Daroussin } 10584bf54857SBaptiste Daroussin 10594bf54857SBaptiste Daroussin obj = ucl_object_lua_import (L, 1); 10604bf54857SBaptiste Daroussin if (obj != NULL) { 10614bf54857SBaptiste Daroussin lua_ucl_to_string (L, obj, format); 10624bf54857SBaptiste Daroussin ucl_object_unref (obj); 10634bf54857SBaptiste Daroussin } 10644bf54857SBaptiste Daroussin else { 10654bf54857SBaptiste Daroussin lua_pushnil (L); 10664bf54857SBaptiste Daroussin } 10674bf54857SBaptiste Daroussin 10684bf54857SBaptiste Daroussin return 1; 10694bf54857SBaptiste Daroussin } 10704bf54857SBaptiste Daroussin 10714bf54857SBaptiste Daroussin static int 10724bf54857SBaptiste Daroussin lua_ucl_null_tostring (lua_State* L) 10734bf54857SBaptiste Daroussin { 10744bf54857SBaptiste Daroussin lua_pushstring (L, "null"); 10754bf54857SBaptiste Daroussin return 1; 10764bf54857SBaptiste Daroussin } 10774bf54857SBaptiste Daroussin 10784bf54857SBaptiste Daroussin static void 10794bf54857SBaptiste Daroussin lua_ucl_null_mt (lua_State *L) 10804bf54857SBaptiste Daroussin { 10814bf54857SBaptiste Daroussin luaL_newmetatable (L, NULL_META); 10824bf54857SBaptiste Daroussin 10834bf54857SBaptiste Daroussin lua_pushcfunction (L, lua_ucl_null_tostring); 10844bf54857SBaptiste Daroussin lua_setfield (L, -2, "__tostring"); 10854bf54857SBaptiste Daroussin 10864bf54857SBaptiste Daroussin lua_pop (L, 1); 10874bf54857SBaptiste Daroussin } 10884bf54857SBaptiste Daroussin 10894bf54857SBaptiste Daroussin int 10904bf54857SBaptiste Daroussin luaopen_ucl (lua_State *L) 10914bf54857SBaptiste Daroussin { 10924bf54857SBaptiste Daroussin lua_ucl_parser_mt (L); 10934bf54857SBaptiste Daroussin lua_ucl_null_mt (L); 1094*39ee7a7aSBaptiste Daroussin lua_ucl_object_mt (L); 10954bf54857SBaptiste Daroussin 10964bf54857SBaptiste Daroussin /* Create the refs weak table: */ 10974bf54857SBaptiste Daroussin lua_createtable (L, 0, 2); 10984bf54857SBaptiste Daroussin lua_pushliteral (L, "v"); /* tbl, "v" */ 10994bf54857SBaptiste Daroussin lua_setfield (L, -2, "__mode"); 11004bf54857SBaptiste Daroussin lua_pushvalue (L, -1); /* tbl, tbl */ 11014bf54857SBaptiste Daroussin lua_setmetatable (L, -2); /* tbl */ 11024bf54857SBaptiste Daroussin lua_setfield (L, LUA_REGISTRYINDEX, "ucl.refs"); 11034bf54857SBaptiste Daroussin 11044bf54857SBaptiste Daroussin lua_newtable (L); 11054bf54857SBaptiste Daroussin 11064bf54857SBaptiste Daroussin lua_pushcfunction (L, lua_ucl_parser_init); 11074bf54857SBaptiste Daroussin lua_setfield (L, -2, "parser"); 11084bf54857SBaptiste Daroussin 11094bf54857SBaptiste Daroussin lua_pushcfunction (L, lua_ucl_to_json); 11104bf54857SBaptiste Daroussin lua_setfield (L, -2, "to_json"); 11114bf54857SBaptiste Daroussin 11124bf54857SBaptiste Daroussin lua_pushcfunction (L, lua_ucl_to_config); 11134bf54857SBaptiste Daroussin lua_setfield (L, -2, "to_config"); 11144bf54857SBaptiste Daroussin 11154bf54857SBaptiste Daroussin lua_pushcfunction (L, lua_ucl_to_format); 11164bf54857SBaptiste Daroussin lua_setfield (L, -2, "to_format"); 11174bf54857SBaptiste Daroussin 11184bf54857SBaptiste Daroussin ucl_null = lua_newuserdata (L, 0); 11194bf54857SBaptiste Daroussin luaL_getmetatable (L, NULL_META); 11204bf54857SBaptiste Daroussin lua_setmetatable (L, -2); 11214bf54857SBaptiste Daroussin 11224bf54857SBaptiste Daroussin lua_pushvalue (L, -1); 11234bf54857SBaptiste Daroussin lua_setfield (L, LUA_REGISTRYINDEX, "ucl.null"); 11244bf54857SBaptiste Daroussin 11254bf54857SBaptiste Daroussin lua_setfield (L, -2, "null"); 11264bf54857SBaptiste Daroussin 11274bf54857SBaptiste Daroussin return 1; 11284bf54857SBaptiste Daroussin } 11294bf54857SBaptiste Daroussin 11304bf54857SBaptiste Daroussin struct ucl_lua_funcdata* 11314bf54857SBaptiste Daroussin ucl_object_toclosure (const ucl_object_t *obj) 11324bf54857SBaptiste Daroussin { 11334bf54857SBaptiste Daroussin if (obj == NULL || obj->type != UCL_USERDATA) { 11344bf54857SBaptiste Daroussin return NULL; 11354bf54857SBaptiste Daroussin } 11364bf54857SBaptiste Daroussin 11374bf54857SBaptiste Daroussin return (struct ucl_lua_funcdata*)obj->value.ud; 11384bf54857SBaptiste Daroussin } 1139