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" 7239ee7a7aSBaptiste 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 */ 152d9f0ce31SBaptiste Daroussin while (ucl_object_iterate (obj, &it, true) != NULL) { 1534bf54857SBaptiste Daroussin nelt ++; 1544bf54857SBaptiste Daroussin } 1554bf54857SBaptiste Daroussin 1564bf54857SBaptiste Daroussin lua_createtable (L, 0, nelt); 1574bf54857SBaptiste Daroussin it = NULL; 1584bf54857SBaptiste Daroussin 159d9f0ce31SBaptiste Daroussin while ((cur = ucl_object_iterate (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; 17639ee7a7aSBaptiste Daroussin ucl_object_iter_t it; 1774bf54857SBaptiste Daroussin int i = 1, nelt = 0; 1784bf54857SBaptiste Daroussin 17939ee7a7aSBaptiste Daroussin if (obj->type == UCL_ARRAY) { 18039ee7a7aSBaptiste Daroussin nelt = obj->len; 18139ee7a7aSBaptiste Daroussin it = ucl_object_iterate_new (obj); 18239ee7a7aSBaptiste Daroussin lua_createtable (L, nelt, 0); 18339ee7a7aSBaptiste Daroussin 18439ee7a7aSBaptiste Daroussin while ((cur = ucl_object_iterate_safe (it, true))) { 18539ee7a7aSBaptiste Daroussin ucl_object_push_lua (L, cur, false); 18639ee7a7aSBaptiste Daroussin lua_rawseti (L, -2, i); 18739ee7a7aSBaptiste Daroussin i ++; 18839ee7a7aSBaptiste Daroussin } 189*11dd9ed6SBaptiste Daroussin 190*11dd9ed6SBaptiste Daroussin ucl_object_iterate_free (it); 19139ee7a7aSBaptiste Daroussin } 19239ee7a7aSBaptiste Daroussin else { 1934bf54857SBaptiste Daroussin /* Optimize allocation by preallocation of table */ 1944bf54857SBaptiste Daroussin LL_FOREACH (obj, cur) { 1954bf54857SBaptiste Daroussin nelt ++; 1964bf54857SBaptiste Daroussin } 1974bf54857SBaptiste Daroussin 1984bf54857SBaptiste Daroussin lua_createtable (L, nelt, 0); 1994bf54857SBaptiste Daroussin 2004bf54857SBaptiste Daroussin LL_FOREACH (obj, cur) { 2014bf54857SBaptiste Daroussin ucl_object_push_lua (L, cur, false); 2024bf54857SBaptiste Daroussin lua_rawseti (L, -2, i); 2034bf54857SBaptiste Daroussin i ++; 2044bf54857SBaptiste Daroussin } 20539ee7a7aSBaptiste Daroussin } 2064bf54857SBaptiste Daroussin 2074bf54857SBaptiste Daroussin return 1; 2084bf54857SBaptiste Daroussin } 2094bf54857SBaptiste Daroussin 2104bf54857SBaptiste Daroussin /** 2114bf54857SBaptiste Daroussin * Push a simple object to lua depending on its actual type 2124bf54857SBaptiste Daroussin */ 2134bf54857SBaptiste Daroussin static int 2144bf54857SBaptiste Daroussin ucl_object_lua_push_scalar (lua_State *L, const ucl_object_t *obj, 2154bf54857SBaptiste Daroussin bool allow_array) 2164bf54857SBaptiste Daroussin { 2174bf54857SBaptiste Daroussin struct ucl_lua_funcdata *fd; 2184bf54857SBaptiste Daroussin 2194bf54857SBaptiste Daroussin if (allow_array && obj->next != NULL) { 2204bf54857SBaptiste Daroussin /* Actually we need to push this as an array */ 2214bf54857SBaptiste Daroussin return ucl_object_lua_push_array (L, obj); 2224bf54857SBaptiste Daroussin } 2234bf54857SBaptiste Daroussin 2244bf54857SBaptiste Daroussin switch (obj->type) { 2254bf54857SBaptiste Daroussin case UCL_BOOLEAN: 2264bf54857SBaptiste Daroussin lua_pushboolean (L, ucl_obj_toboolean (obj)); 2274bf54857SBaptiste Daroussin break; 2284bf54857SBaptiste Daroussin case UCL_STRING: 2294bf54857SBaptiste Daroussin lua_pushstring (L, ucl_obj_tostring (obj)); 2304bf54857SBaptiste Daroussin break; 2314bf54857SBaptiste Daroussin case UCL_INT: 2324bf54857SBaptiste Daroussin #if LUA_VERSION_NUM >= 501 2334bf54857SBaptiste Daroussin lua_pushinteger (L, ucl_obj_toint (obj)); 2344bf54857SBaptiste Daroussin #else 2354bf54857SBaptiste Daroussin lua_pushnumber (L, ucl_obj_toint (obj)); 2364bf54857SBaptiste Daroussin #endif 2374bf54857SBaptiste Daroussin break; 2384bf54857SBaptiste Daroussin case UCL_FLOAT: 2394bf54857SBaptiste Daroussin case UCL_TIME: 2404bf54857SBaptiste Daroussin lua_pushnumber (L, ucl_obj_todouble (obj)); 2414bf54857SBaptiste Daroussin break; 2424bf54857SBaptiste Daroussin case UCL_NULL: 2434bf54857SBaptiste Daroussin lua_getfield (L, LUA_REGISTRYINDEX, "ucl.null"); 2444bf54857SBaptiste Daroussin break; 2454bf54857SBaptiste Daroussin case UCL_USERDATA: 2464bf54857SBaptiste Daroussin fd = (struct ucl_lua_funcdata *)obj->value.ud; 2474bf54857SBaptiste Daroussin lua_rawgeti (L, LUA_REGISTRYINDEX, fd->idx); 2484bf54857SBaptiste Daroussin break; 2494bf54857SBaptiste Daroussin default: 2504bf54857SBaptiste Daroussin lua_pushnil (L); 2514bf54857SBaptiste Daroussin break; 2524bf54857SBaptiste Daroussin } 2534bf54857SBaptiste Daroussin 2544bf54857SBaptiste Daroussin return 1; 2554bf54857SBaptiste Daroussin } 2564bf54857SBaptiste Daroussin 2574bf54857SBaptiste Daroussin /*** 2584bf54857SBaptiste Daroussin * @function ucl_object_push_lua(L, obj, allow_array) 2594bf54857SBaptiste Daroussin * This is a `C` function to push `UCL` object as lua variable. This function 2604bf54857SBaptiste Daroussin * converts `obj` to lua representation using the following conversions: 2614bf54857SBaptiste Daroussin * 2624bf54857SBaptiste Daroussin * - *scalar* values are directly presented by lua objects 2634bf54857SBaptiste Daroussin * - *userdata* values are converted to lua function objects using `LUA_REGISTRYINDEX`, 2644bf54857SBaptiste Daroussin * this can be used to pass functions from lua to c and vice-versa 2654bf54857SBaptiste Daroussin * - *arrays* are converted to lua tables with numeric indicies suitable for `ipairs` iterations 2664bf54857SBaptiste Daroussin * - *objects* are converted to lua tables with string indicies 2674bf54857SBaptiste Daroussin * @param {lua_State} L lua state pointer 2684bf54857SBaptiste Daroussin * @param {ucl_object_t} obj object to push 2694bf54857SBaptiste Daroussin * @param {bool} allow_array expand implicit arrays (should be true for all but partial arrays) 2704bf54857SBaptiste Daroussin * @return {int} `1` if an object is pushed to lua 2714bf54857SBaptiste Daroussin */ 2724bf54857SBaptiste Daroussin int 2734bf54857SBaptiste Daroussin ucl_object_push_lua (lua_State *L, const ucl_object_t *obj, bool allow_array) 2744bf54857SBaptiste Daroussin { 2754bf54857SBaptiste Daroussin switch (obj->type) { 2764bf54857SBaptiste Daroussin case UCL_OBJECT: 2774bf54857SBaptiste Daroussin return ucl_object_lua_push_object (L, obj, allow_array); 2784bf54857SBaptiste Daroussin case UCL_ARRAY: 27939ee7a7aSBaptiste Daroussin return ucl_object_lua_push_array (L, obj); 2804bf54857SBaptiste Daroussin default: 2814bf54857SBaptiste Daroussin return ucl_object_lua_push_scalar (L, obj, allow_array); 2824bf54857SBaptiste Daroussin } 2834bf54857SBaptiste Daroussin } 2844bf54857SBaptiste Daroussin 2854bf54857SBaptiste Daroussin /** 2864bf54857SBaptiste Daroussin * Parse lua table into object top 2874bf54857SBaptiste Daroussin * @param L 2884bf54857SBaptiste Daroussin * @param top 2894bf54857SBaptiste Daroussin * @param idx 2904bf54857SBaptiste Daroussin */ 2914bf54857SBaptiste Daroussin static ucl_object_t * 2924bf54857SBaptiste Daroussin ucl_object_lua_fromtable (lua_State *L, int idx) 2934bf54857SBaptiste Daroussin { 2944bf54857SBaptiste Daroussin ucl_object_t *obj, *top = NULL; 2954bf54857SBaptiste Daroussin size_t keylen; 2964bf54857SBaptiste Daroussin const char *k; 2974bf54857SBaptiste Daroussin bool is_array = true; 2984bf54857SBaptiste Daroussin int max = INT_MIN; 2994bf54857SBaptiste Daroussin 3004bf54857SBaptiste Daroussin if (idx < 0) { 3014bf54857SBaptiste Daroussin /* For negative indicies we want to invert them */ 3024bf54857SBaptiste Daroussin idx = lua_gettop (L) + idx + 1; 3034bf54857SBaptiste Daroussin } 3044bf54857SBaptiste Daroussin /* Check for array */ 3054bf54857SBaptiste Daroussin lua_pushnil (L); 3064bf54857SBaptiste Daroussin while (lua_next (L, idx) != 0) { 3074bf54857SBaptiste Daroussin if (lua_type (L, -2) == LUA_TNUMBER) { 3084bf54857SBaptiste Daroussin double num = lua_tonumber (L, -2); 3094bf54857SBaptiste Daroussin if (num == (int)num) { 3104bf54857SBaptiste Daroussin if (num > max) { 3114bf54857SBaptiste Daroussin max = num; 3124bf54857SBaptiste Daroussin } 3134bf54857SBaptiste Daroussin } 3144bf54857SBaptiste Daroussin else { 3154bf54857SBaptiste Daroussin /* Keys are not integer */ 3164bf54857SBaptiste Daroussin lua_pop (L, 2); 3174bf54857SBaptiste Daroussin is_array = false; 3184bf54857SBaptiste Daroussin break; 3194bf54857SBaptiste Daroussin } 3204bf54857SBaptiste Daroussin } 3214bf54857SBaptiste Daroussin else { 3224bf54857SBaptiste Daroussin /* Keys are not numeric */ 3234bf54857SBaptiste Daroussin lua_pop (L, 2); 3244bf54857SBaptiste Daroussin is_array = false; 3254bf54857SBaptiste Daroussin break; 3264bf54857SBaptiste Daroussin } 3274bf54857SBaptiste Daroussin lua_pop (L, 1); 3284bf54857SBaptiste Daroussin } 3294bf54857SBaptiste Daroussin 3304bf54857SBaptiste Daroussin /* Table iterate */ 3314bf54857SBaptiste Daroussin if (is_array) { 3324bf54857SBaptiste Daroussin int i; 3334bf54857SBaptiste Daroussin 3344bf54857SBaptiste Daroussin top = ucl_object_typed_new (UCL_ARRAY); 3354bf54857SBaptiste Daroussin for (i = 1; i <= max; i ++) { 3364bf54857SBaptiste Daroussin lua_pushinteger (L, i); 3374bf54857SBaptiste Daroussin lua_gettable (L, idx); 3384bf54857SBaptiste Daroussin obj = ucl_object_lua_fromelt (L, lua_gettop (L)); 3394bf54857SBaptiste Daroussin if (obj != NULL) { 3404bf54857SBaptiste Daroussin ucl_array_append (top, obj); 3414bf54857SBaptiste Daroussin } 34239ee7a7aSBaptiste Daroussin lua_pop (L, 1); 3434bf54857SBaptiste Daroussin } 3444bf54857SBaptiste Daroussin } 3454bf54857SBaptiste Daroussin else { 3464bf54857SBaptiste Daroussin lua_pushnil (L); 3474bf54857SBaptiste Daroussin top = ucl_object_typed_new (UCL_OBJECT); 3484bf54857SBaptiste Daroussin while (lua_next (L, idx) != 0) { 3494bf54857SBaptiste Daroussin /* copy key to avoid modifications */ 3504bf54857SBaptiste Daroussin k = lua_tolstring (L, -2, &keylen); 3514bf54857SBaptiste Daroussin obj = ucl_object_lua_fromelt (L, lua_gettop (L)); 3524bf54857SBaptiste Daroussin 3534bf54857SBaptiste Daroussin if (obj != NULL) { 3544bf54857SBaptiste Daroussin ucl_object_insert_key (top, obj, k, keylen, true); 3554bf54857SBaptiste Daroussin } 3564bf54857SBaptiste Daroussin lua_pop (L, 1); 3574bf54857SBaptiste Daroussin } 3584bf54857SBaptiste Daroussin } 3594bf54857SBaptiste Daroussin 3604bf54857SBaptiste Daroussin return top; 3614bf54857SBaptiste Daroussin } 3624bf54857SBaptiste Daroussin 3634bf54857SBaptiste Daroussin /** 3644bf54857SBaptiste Daroussin * Get a single element from lua to object obj 3654bf54857SBaptiste Daroussin * @param L 3664bf54857SBaptiste Daroussin * @param obj 3674bf54857SBaptiste Daroussin * @param idx 3684bf54857SBaptiste Daroussin */ 3694bf54857SBaptiste Daroussin static ucl_object_t * 3704bf54857SBaptiste Daroussin ucl_object_lua_fromelt (lua_State *L, int idx) 3714bf54857SBaptiste Daroussin { 3724bf54857SBaptiste Daroussin int type; 3734bf54857SBaptiste Daroussin double num; 3744bf54857SBaptiste Daroussin ucl_object_t *obj = NULL; 3754bf54857SBaptiste Daroussin struct ucl_lua_funcdata *fd; 3764bf54857SBaptiste Daroussin 3774bf54857SBaptiste Daroussin type = lua_type (L, idx); 3784bf54857SBaptiste Daroussin 3794bf54857SBaptiste Daroussin switch (type) { 3804bf54857SBaptiste Daroussin case LUA_TSTRING: 3814bf54857SBaptiste Daroussin obj = ucl_object_fromstring_common (lua_tostring (L, idx), 0, 0); 3824bf54857SBaptiste Daroussin break; 3834bf54857SBaptiste Daroussin case LUA_TNUMBER: 3844bf54857SBaptiste Daroussin num = lua_tonumber (L, idx); 3854bf54857SBaptiste Daroussin if (num == (int64_t)num) { 3864bf54857SBaptiste Daroussin obj = ucl_object_fromint (num); 3874bf54857SBaptiste Daroussin } 3884bf54857SBaptiste Daroussin else { 3894bf54857SBaptiste Daroussin obj = ucl_object_fromdouble (num); 3904bf54857SBaptiste Daroussin } 3914bf54857SBaptiste Daroussin break; 3924bf54857SBaptiste Daroussin case LUA_TBOOLEAN: 3934bf54857SBaptiste Daroussin obj = ucl_object_frombool (lua_toboolean (L, idx)); 3944bf54857SBaptiste Daroussin break; 3954bf54857SBaptiste Daroussin case LUA_TUSERDATA: 3964bf54857SBaptiste Daroussin if (lua_topointer (L, idx) == ucl_null) { 3974bf54857SBaptiste Daroussin obj = ucl_object_typed_new (UCL_NULL); 3984bf54857SBaptiste Daroussin } 3994bf54857SBaptiste Daroussin break; 4004bf54857SBaptiste Daroussin case LUA_TTABLE: 4014bf54857SBaptiste Daroussin case LUA_TFUNCTION: 4024bf54857SBaptiste Daroussin case LUA_TTHREAD: 4034bf54857SBaptiste Daroussin if (luaL_getmetafield (L, idx, "__gen_ucl")) { 4044bf54857SBaptiste Daroussin if (lua_isfunction (L, -1)) { 4054bf54857SBaptiste Daroussin lua_settop (L, 3); /* gen, obj, func */ 4064bf54857SBaptiste Daroussin lua_insert (L, 1); /* func, gen, obj */ 4074bf54857SBaptiste Daroussin lua_insert (L, 2); /* func, obj, gen */ 4084bf54857SBaptiste Daroussin lua_call(L, 2, 1); 4094bf54857SBaptiste Daroussin obj = ucl_object_lua_fromelt (L, 1); 4104bf54857SBaptiste Daroussin } 4114bf54857SBaptiste Daroussin lua_pop (L, 2); 4124bf54857SBaptiste Daroussin } 4134bf54857SBaptiste Daroussin else { 4144bf54857SBaptiste Daroussin if (type == LUA_TTABLE) { 4154bf54857SBaptiste Daroussin obj = ucl_object_lua_fromtable (L, idx); 4164bf54857SBaptiste Daroussin } 4174bf54857SBaptiste Daroussin else if (type == LUA_TFUNCTION) { 4184bf54857SBaptiste Daroussin fd = malloc (sizeof (*fd)); 4194bf54857SBaptiste Daroussin if (fd != NULL) { 4204bf54857SBaptiste Daroussin lua_pushvalue (L, idx); 4214bf54857SBaptiste Daroussin fd->L = L; 4224bf54857SBaptiste Daroussin fd->ret = NULL; 4234bf54857SBaptiste Daroussin fd->idx = luaL_ref (L, LUA_REGISTRYINDEX); 4244bf54857SBaptiste Daroussin 4254bf54857SBaptiste Daroussin obj = ucl_object_new_userdata (lua_ucl_userdata_dtor, 426d9f0ce31SBaptiste Daroussin lua_ucl_userdata_emitter, (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 46539ee7a7aSBaptiste Daroussin lua_ucl_to_string (lua_State *L, const ucl_object_t *obj, enum ucl_emitter type) 46639ee7a7aSBaptiste Daroussin { 46739ee7a7aSBaptiste Daroussin unsigned char *result; 46839ee7a7aSBaptiste Daroussin 46939ee7a7aSBaptiste Daroussin result = ucl_object_emit (obj, type); 47039ee7a7aSBaptiste Daroussin 47139ee7a7aSBaptiste Daroussin if (result != NULL) { 47239ee7a7aSBaptiste Daroussin lua_pushstring (L, (const char *)result); 47339ee7a7aSBaptiste Daroussin free (result); 47439ee7a7aSBaptiste Daroussin } 47539ee7a7aSBaptiste Daroussin else { 47639ee7a7aSBaptiste Daroussin lua_pushnil (L); 47739ee7a7aSBaptiste Daroussin } 47839ee7a7aSBaptiste Daroussin 47939ee7a7aSBaptiste Daroussin return 1; 48039ee7a7aSBaptiste Daroussin } 48139ee7a7aSBaptiste Daroussin 48239ee7a7aSBaptiste Daroussin static int 4834bf54857SBaptiste Daroussin lua_ucl_parser_init (lua_State *L) 4844bf54857SBaptiste Daroussin { 4854bf54857SBaptiste Daroussin struct ucl_parser *parser, **pparser; 486*11dd9ed6SBaptiste Daroussin int flags = UCL_PARSER_NO_FILEVARS; 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 51139ee7a7aSBaptiste Daroussin static ucl_object_t * 51239ee7a7aSBaptiste Daroussin lua_ucl_object_get (lua_State *L, int index) 51339ee7a7aSBaptiste Daroussin { 51439ee7a7aSBaptiste Daroussin return *((ucl_object_t **) luaL_checkudata(L, index, OBJECT_META)); 51539ee7a7aSBaptiste Daroussin } 51639ee7a7aSBaptiste Daroussin 517d9f0ce31SBaptiste Daroussin static void 518d9f0ce31SBaptiste Daroussin lua_ucl_push_opaque (lua_State *L, ucl_object_t *obj) 519d9f0ce31SBaptiste Daroussin { 520d9f0ce31SBaptiste Daroussin ucl_object_t **pobj; 521d9f0ce31SBaptiste Daroussin 522d9f0ce31SBaptiste Daroussin pobj = lua_newuserdata (L, sizeof (*pobj)); 523d9f0ce31SBaptiste Daroussin *pobj = obj; 524d9f0ce31SBaptiste Daroussin luaL_getmetatable (L, OBJECT_META); 525d9f0ce31SBaptiste Daroussin lua_setmetatable (L, -2); 526d9f0ce31SBaptiste Daroussin } 527d9f0ce31SBaptiste Daroussin 528*11dd9ed6SBaptiste Daroussin static inline enum ucl_parse_type 529*11dd9ed6SBaptiste Daroussin lua_ucl_str_to_parse_type (const char *str) 530*11dd9ed6SBaptiste Daroussin { 531*11dd9ed6SBaptiste Daroussin enum ucl_parse_type type = UCL_PARSE_UCL; 532*11dd9ed6SBaptiste Daroussin 533*11dd9ed6SBaptiste Daroussin if (str != NULL) { 534*11dd9ed6SBaptiste Daroussin if (strcasecmp (str, "msgpack") == 0) { 535*11dd9ed6SBaptiste Daroussin type = UCL_PARSE_MSGPACK; 536*11dd9ed6SBaptiste Daroussin } 537*11dd9ed6SBaptiste Daroussin else if (strcasecmp (str, "sexp") == 0 || 538*11dd9ed6SBaptiste Daroussin strcasecmp (str, "csexp") == 0) { 539*11dd9ed6SBaptiste Daroussin type = UCL_PARSE_CSEXP; 540*11dd9ed6SBaptiste Daroussin } 541*11dd9ed6SBaptiste Daroussin else if (strcasecmp (str, "auto") == 0) { 542*11dd9ed6SBaptiste Daroussin type = UCL_PARSE_AUTO; 543*11dd9ed6SBaptiste Daroussin } 544*11dd9ed6SBaptiste Daroussin } 545*11dd9ed6SBaptiste Daroussin 546*11dd9ed6SBaptiste Daroussin return type; 547*11dd9ed6SBaptiste Daroussin } 548*11dd9ed6SBaptiste Daroussin 5494bf54857SBaptiste Daroussin /*** 5504bf54857SBaptiste Daroussin * @method parser:parse_file(name) 5514bf54857SBaptiste Daroussin * Parse UCL object from file. 5524bf54857SBaptiste Daroussin * @param {string} name filename to parse 5534bf54857SBaptiste Daroussin * @return {bool[, string]} if res is `true` then file has been parsed successfully, otherwise an error string is also returned 5544bf54857SBaptiste Daroussin @example 5554bf54857SBaptiste Daroussin local parser = ucl.parser() 5564bf54857SBaptiste Daroussin local res,err = parser:parse_file('/some/file.conf') 5574bf54857SBaptiste Daroussin 5584bf54857SBaptiste Daroussin if not res then 5594bf54857SBaptiste Daroussin print('parser error: ' .. err) 5604bf54857SBaptiste Daroussin else 5614bf54857SBaptiste Daroussin -- Do something with object 5624bf54857SBaptiste Daroussin end 5634bf54857SBaptiste Daroussin */ 5644bf54857SBaptiste Daroussin static int 5654bf54857SBaptiste Daroussin lua_ucl_parser_parse_file (lua_State *L) 5664bf54857SBaptiste Daroussin { 5674bf54857SBaptiste Daroussin struct ucl_parser *parser; 5684bf54857SBaptiste Daroussin const char *file; 5694bf54857SBaptiste Daroussin int ret = 2; 5704bf54857SBaptiste Daroussin 5714bf54857SBaptiste Daroussin parser = lua_ucl_parser_get (L, 1); 5724bf54857SBaptiste Daroussin file = luaL_checkstring (L, 2); 5734bf54857SBaptiste Daroussin 5744bf54857SBaptiste Daroussin if (parser != NULL && file != NULL) { 5754bf54857SBaptiste Daroussin if (ucl_parser_add_file (parser, file)) { 5764bf54857SBaptiste Daroussin lua_pushboolean (L, true); 5774bf54857SBaptiste Daroussin ret = 1; 5784bf54857SBaptiste Daroussin } 5794bf54857SBaptiste Daroussin else { 5804bf54857SBaptiste Daroussin lua_pushboolean (L, false); 5814bf54857SBaptiste Daroussin lua_pushstring (L, ucl_parser_get_error (parser)); 5824bf54857SBaptiste Daroussin } 5834bf54857SBaptiste Daroussin } 5844bf54857SBaptiste Daroussin else { 5854bf54857SBaptiste Daroussin lua_pushboolean (L, false); 5864bf54857SBaptiste Daroussin lua_pushstring (L, "invalid arguments"); 5874bf54857SBaptiste Daroussin } 5884bf54857SBaptiste Daroussin 5894bf54857SBaptiste Daroussin return ret; 5904bf54857SBaptiste Daroussin } 5914bf54857SBaptiste Daroussin 5924bf54857SBaptiste Daroussin /*** 5934bf54857SBaptiste Daroussin * @method parser:parse_string(input) 5944bf54857SBaptiste Daroussin * Parse UCL object from file. 5954bf54857SBaptiste Daroussin * @param {string} input string to parse 5964bf54857SBaptiste Daroussin * @return {bool[, string]} if res is `true` then file has been parsed successfully, otherwise an error string is also returned 5974bf54857SBaptiste Daroussin */ 5984bf54857SBaptiste Daroussin static int 5994bf54857SBaptiste Daroussin lua_ucl_parser_parse_string (lua_State *L) 6004bf54857SBaptiste Daroussin { 6014bf54857SBaptiste Daroussin struct ucl_parser *parser; 6024bf54857SBaptiste Daroussin const char *string; 6034bf54857SBaptiste Daroussin size_t llen; 604*11dd9ed6SBaptiste Daroussin enum ucl_parse_type type = UCL_PARSE_UCL; 6054bf54857SBaptiste Daroussin int ret = 2; 6064bf54857SBaptiste Daroussin 6074bf54857SBaptiste Daroussin parser = lua_ucl_parser_get (L, 1); 6084bf54857SBaptiste Daroussin string = luaL_checklstring (L, 2, &llen); 6094bf54857SBaptiste Daroussin 610*11dd9ed6SBaptiste Daroussin if (lua_type (L, 3) == LUA_TSTRING) { 611*11dd9ed6SBaptiste Daroussin type = lua_ucl_str_to_parse_type (lua_tostring (L, 3)); 612*11dd9ed6SBaptiste Daroussin } 613*11dd9ed6SBaptiste Daroussin 6144bf54857SBaptiste Daroussin if (parser != NULL && string != NULL) { 615*11dd9ed6SBaptiste Daroussin if (ucl_parser_add_chunk_full (parser, (const unsigned char *)string, 616*11dd9ed6SBaptiste Daroussin llen, 0, UCL_DUPLICATE_APPEND, type)) { 6174bf54857SBaptiste Daroussin lua_pushboolean (L, true); 6184bf54857SBaptiste Daroussin ret = 1; 6194bf54857SBaptiste Daroussin } 6204bf54857SBaptiste Daroussin else { 6214bf54857SBaptiste Daroussin lua_pushboolean (L, false); 6224bf54857SBaptiste Daroussin lua_pushstring (L, ucl_parser_get_error (parser)); 6234bf54857SBaptiste Daroussin } 6244bf54857SBaptiste Daroussin } 6254bf54857SBaptiste Daroussin else { 6264bf54857SBaptiste Daroussin lua_pushboolean (L, false); 6274bf54857SBaptiste Daroussin lua_pushstring (L, "invalid arguments"); 6284bf54857SBaptiste Daroussin } 6294bf54857SBaptiste Daroussin 6304bf54857SBaptiste Daroussin return ret; 6314bf54857SBaptiste Daroussin } 6324bf54857SBaptiste Daroussin 6334bf54857SBaptiste Daroussin /*** 6344bf54857SBaptiste Daroussin * @method parser:get_object() 6354bf54857SBaptiste Daroussin * Get top object from parser and export it to lua representation. 6364bf54857SBaptiste Daroussin * @return {variant or nil} ucl object as lua native variable 6374bf54857SBaptiste Daroussin */ 6384bf54857SBaptiste Daroussin static int 6394bf54857SBaptiste Daroussin lua_ucl_parser_get_object (lua_State *L) 6404bf54857SBaptiste Daroussin { 6414bf54857SBaptiste Daroussin struct ucl_parser *parser; 6424bf54857SBaptiste Daroussin ucl_object_t *obj; 6434bf54857SBaptiste Daroussin int ret = 1; 6444bf54857SBaptiste Daroussin 6454bf54857SBaptiste Daroussin parser = lua_ucl_parser_get (L, 1); 6464bf54857SBaptiste Daroussin obj = ucl_parser_get_object (parser); 6474bf54857SBaptiste Daroussin 6484bf54857SBaptiste Daroussin if (obj != NULL) { 6494bf54857SBaptiste Daroussin ret = ucl_object_push_lua (L, obj, false); 6504bf54857SBaptiste Daroussin /* no need to keep reference */ 6514bf54857SBaptiste Daroussin ucl_object_unref (obj); 6524bf54857SBaptiste Daroussin } 6534bf54857SBaptiste Daroussin else { 6544bf54857SBaptiste Daroussin lua_pushnil (L); 6554bf54857SBaptiste Daroussin } 6564bf54857SBaptiste Daroussin 6574bf54857SBaptiste Daroussin return ret; 6584bf54857SBaptiste Daroussin } 6594bf54857SBaptiste Daroussin 66039ee7a7aSBaptiste Daroussin /*** 66139ee7a7aSBaptiste Daroussin * @method parser:get_object_wrapped() 66239ee7a7aSBaptiste Daroussin * Get top object from parser and export it to userdata object without 66339ee7a7aSBaptiste Daroussin * unwrapping to lua. 66439ee7a7aSBaptiste Daroussin * @return {ucl.object or nil} ucl object wrapped variable 66539ee7a7aSBaptiste Daroussin */ 66639ee7a7aSBaptiste Daroussin static int 66739ee7a7aSBaptiste Daroussin lua_ucl_parser_get_object_wrapped (lua_State *L) 66839ee7a7aSBaptiste Daroussin { 66939ee7a7aSBaptiste Daroussin struct ucl_parser *parser; 670d9f0ce31SBaptiste Daroussin ucl_object_t *obj; 67139ee7a7aSBaptiste Daroussin int ret = 1; 67239ee7a7aSBaptiste Daroussin 67339ee7a7aSBaptiste Daroussin parser = lua_ucl_parser_get (L, 1); 67439ee7a7aSBaptiste Daroussin obj = ucl_parser_get_object (parser); 67539ee7a7aSBaptiste Daroussin 67639ee7a7aSBaptiste Daroussin if (obj != NULL) { 677d9f0ce31SBaptiste Daroussin lua_ucl_push_opaque (L, obj); 67839ee7a7aSBaptiste Daroussin } 67939ee7a7aSBaptiste Daroussin else { 68039ee7a7aSBaptiste Daroussin lua_pushnil (L); 68139ee7a7aSBaptiste Daroussin } 68239ee7a7aSBaptiste Daroussin 68339ee7a7aSBaptiste Daroussin return ret; 68439ee7a7aSBaptiste Daroussin } 68539ee7a7aSBaptiste Daroussin 68639ee7a7aSBaptiste Daroussin /*** 68739ee7a7aSBaptiste Daroussin * @method parser:validate(schema) 68839ee7a7aSBaptiste Daroussin * Validates the top object in the parser against schema. Schema might be 68939ee7a7aSBaptiste Daroussin * another object or a string that represents file to load schema from. 69039ee7a7aSBaptiste Daroussin * 69139ee7a7aSBaptiste Daroussin * @param {string/table} schema input schema 69239ee7a7aSBaptiste Daroussin * @return {result,err} two values: boolean result and the corresponding error 69339ee7a7aSBaptiste Daroussin * 69439ee7a7aSBaptiste Daroussin */ 69539ee7a7aSBaptiste Daroussin static int 69639ee7a7aSBaptiste Daroussin lua_ucl_parser_validate (lua_State *L) 69739ee7a7aSBaptiste Daroussin { 69839ee7a7aSBaptiste Daroussin struct ucl_parser *parser, *schema_parser; 69939ee7a7aSBaptiste Daroussin ucl_object_t *schema; 70039ee7a7aSBaptiste Daroussin const char *schema_file; 70139ee7a7aSBaptiste Daroussin struct ucl_schema_error err; 70239ee7a7aSBaptiste Daroussin 70339ee7a7aSBaptiste Daroussin parser = lua_ucl_parser_get (L, 1); 70439ee7a7aSBaptiste Daroussin 70539ee7a7aSBaptiste Daroussin if (parser && parser->top_obj) { 70639ee7a7aSBaptiste Daroussin if (lua_type (L, 2) == LUA_TTABLE) { 70739ee7a7aSBaptiste Daroussin schema = ucl_object_lua_import (L, 2); 70839ee7a7aSBaptiste Daroussin 70939ee7a7aSBaptiste Daroussin if (schema == NULL) { 71039ee7a7aSBaptiste Daroussin lua_pushboolean (L, false); 71139ee7a7aSBaptiste Daroussin lua_pushstring (L, "cannot load schema from lua table"); 71239ee7a7aSBaptiste Daroussin 71339ee7a7aSBaptiste Daroussin return 2; 71439ee7a7aSBaptiste Daroussin } 71539ee7a7aSBaptiste Daroussin } 71639ee7a7aSBaptiste Daroussin else if (lua_type (L, 2) == LUA_TSTRING) { 71739ee7a7aSBaptiste Daroussin schema_parser = ucl_parser_new (0); 71839ee7a7aSBaptiste Daroussin schema_file = luaL_checkstring (L, 2); 71939ee7a7aSBaptiste Daroussin 72039ee7a7aSBaptiste Daroussin if (!ucl_parser_add_file (schema_parser, schema_file)) { 72139ee7a7aSBaptiste Daroussin lua_pushboolean (L, false); 72239ee7a7aSBaptiste Daroussin lua_pushfstring (L, "cannot parse schema file \"%s\": " 72339ee7a7aSBaptiste Daroussin "%s", schema_file, ucl_parser_get_error (parser)); 72439ee7a7aSBaptiste Daroussin ucl_parser_free (schema_parser); 72539ee7a7aSBaptiste Daroussin 72639ee7a7aSBaptiste Daroussin return 2; 72739ee7a7aSBaptiste Daroussin } 72839ee7a7aSBaptiste Daroussin 72939ee7a7aSBaptiste Daroussin schema = ucl_parser_get_object (schema_parser); 73039ee7a7aSBaptiste Daroussin ucl_parser_free (schema_parser); 73139ee7a7aSBaptiste Daroussin } 73239ee7a7aSBaptiste Daroussin else { 73339ee7a7aSBaptiste Daroussin lua_pushboolean (L, false); 73439ee7a7aSBaptiste Daroussin lua_pushstring (L, "invalid schema argument"); 73539ee7a7aSBaptiste Daroussin 73639ee7a7aSBaptiste Daroussin return 2; 73739ee7a7aSBaptiste Daroussin } 73839ee7a7aSBaptiste Daroussin 73939ee7a7aSBaptiste Daroussin if (!ucl_object_validate (schema, parser->top_obj, &err)) { 74039ee7a7aSBaptiste Daroussin lua_pushboolean (L, false); 74139ee7a7aSBaptiste Daroussin lua_pushfstring (L, "validation error: " 74239ee7a7aSBaptiste Daroussin "%s", err.msg); 74339ee7a7aSBaptiste Daroussin } 74439ee7a7aSBaptiste Daroussin else { 74539ee7a7aSBaptiste Daroussin lua_pushboolean (L, true); 74639ee7a7aSBaptiste Daroussin lua_pushnil (L); 74739ee7a7aSBaptiste Daroussin } 74839ee7a7aSBaptiste Daroussin 74939ee7a7aSBaptiste Daroussin ucl_object_unref (schema); 75039ee7a7aSBaptiste Daroussin } 75139ee7a7aSBaptiste Daroussin else { 75239ee7a7aSBaptiste Daroussin lua_pushboolean (L, false); 75339ee7a7aSBaptiste Daroussin lua_pushstring (L, "invalid parser or empty top object"); 75439ee7a7aSBaptiste Daroussin } 75539ee7a7aSBaptiste Daroussin 75639ee7a7aSBaptiste Daroussin return 2; 75739ee7a7aSBaptiste Daroussin } 75839ee7a7aSBaptiste Daroussin 7594bf54857SBaptiste Daroussin static int 7604bf54857SBaptiste Daroussin lua_ucl_parser_gc (lua_State *L) 7614bf54857SBaptiste Daroussin { 7624bf54857SBaptiste Daroussin struct ucl_parser *parser; 7634bf54857SBaptiste Daroussin 7644bf54857SBaptiste Daroussin parser = lua_ucl_parser_get (L, 1); 7654bf54857SBaptiste Daroussin ucl_parser_free (parser); 7664bf54857SBaptiste Daroussin 7674bf54857SBaptiste Daroussin return 0; 7684bf54857SBaptiste Daroussin } 7694bf54857SBaptiste Daroussin 77039ee7a7aSBaptiste Daroussin /*** 77139ee7a7aSBaptiste Daroussin * @method object:unwrap() 77239ee7a7aSBaptiste Daroussin * Unwraps opaque ucl object to the native lua object (performing copying) 77339ee7a7aSBaptiste Daroussin * @return {variant} any lua object 77439ee7a7aSBaptiste Daroussin */ 77539ee7a7aSBaptiste Daroussin static int 77639ee7a7aSBaptiste Daroussin lua_ucl_object_unwrap (lua_State *L) 77739ee7a7aSBaptiste Daroussin { 77839ee7a7aSBaptiste Daroussin ucl_object_t *obj; 77939ee7a7aSBaptiste Daroussin 78039ee7a7aSBaptiste Daroussin obj = lua_ucl_object_get (L, 1); 78139ee7a7aSBaptiste Daroussin 78239ee7a7aSBaptiste Daroussin if (obj) { 78339ee7a7aSBaptiste Daroussin ucl_object_push_lua (L, obj, true); 78439ee7a7aSBaptiste Daroussin } 78539ee7a7aSBaptiste Daroussin else { 78639ee7a7aSBaptiste Daroussin lua_pushnil (L); 78739ee7a7aSBaptiste Daroussin } 78839ee7a7aSBaptiste Daroussin 78939ee7a7aSBaptiste Daroussin return 1; 79039ee7a7aSBaptiste Daroussin } 79139ee7a7aSBaptiste Daroussin 792*11dd9ed6SBaptiste Daroussin static inline enum ucl_emitter 793*11dd9ed6SBaptiste Daroussin lua_ucl_str_to_emit_type (const char *strtype) 794*11dd9ed6SBaptiste Daroussin { 795*11dd9ed6SBaptiste Daroussin enum ucl_emitter format = UCL_EMIT_JSON_COMPACT; 796*11dd9ed6SBaptiste Daroussin 797*11dd9ed6SBaptiste Daroussin if (strcasecmp (strtype, "json") == 0) { 798*11dd9ed6SBaptiste Daroussin format = UCL_EMIT_JSON; 799*11dd9ed6SBaptiste Daroussin } 800*11dd9ed6SBaptiste Daroussin else if (strcasecmp (strtype, "json-compact") == 0) { 801*11dd9ed6SBaptiste Daroussin format = UCL_EMIT_JSON_COMPACT; 802*11dd9ed6SBaptiste Daroussin } 803*11dd9ed6SBaptiste Daroussin else if (strcasecmp (strtype, "yaml") == 0) { 804*11dd9ed6SBaptiste Daroussin format = UCL_EMIT_YAML; 805*11dd9ed6SBaptiste Daroussin } 806*11dd9ed6SBaptiste Daroussin else if (strcasecmp (strtype, "config") == 0 || 807*11dd9ed6SBaptiste Daroussin strcasecmp (strtype, "ucl") == 0) { 808*11dd9ed6SBaptiste Daroussin format = UCL_EMIT_CONFIG; 809*11dd9ed6SBaptiste Daroussin } 810*11dd9ed6SBaptiste Daroussin 811*11dd9ed6SBaptiste Daroussin return format; 812*11dd9ed6SBaptiste Daroussin } 813*11dd9ed6SBaptiste Daroussin 81439ee7a7aSBaptiste Daroussin /*** 81539ee7a7aSBaptiste Daroussin * @method object:tostring(type) 81639ee7a7aSBaptiste Daroussin * Unwraps opaque ucl object to string (json by default). Optionally you can 81739ee7a7aSBaptiste Daroussin * specify output format: 81839ee7a7aSBaptiste Daroussin * 81939ee7a7aSBaptiste Daroussin * - `json` - fine printed json 82039ee7a7aSBaptiste Daroussin * - `json-compact` - compacted json 82139ee7a7aSBaptiste Daroussin * - `config` - fine printed configuration 82239ee7a7aSBaptiste Daroussin * - `ucl` - same as `config` 82339ee7a7aSBaptiste Daroussin * - `yaml` - embedded yaml 82439ee7a7aSBaptiste Daroussin * @param {string} type optional 82539ee7a7aSBaptiste Daroussin * @return {string} string representation of the opaque ucl object 82639ee7a7aSBaptiste Daroussin */ 82739ee7a7aSBaptiste Daroussin static int 82839ee7a7aSBaptiste Daroussin lua_ucl_object_tostring (lua_State *L) 82939ee7a7aSBaptiste Daroussin { 83039ee7a7aSBaptiste Daroussin ucl_object_t *obj; 83139ee7a7aSBaptiste Daroussin enum ucl_emitter format = UCL_EMIT_JSON_COMPACT; 83239ee7a7aSBaptiste Daroussin 83339ee7a7aSBaptiste Daroussin obj = lua_ucl_object_get (L, 1); 83439ee7a7aSBaptiste Daroussin 83539ee7a7aSBaptiste Daroussin if (obj) { 83639ee7a7aSBaptiste Daroussin if (lua_gettop (L) > 1) { 83739ee7a7aSBaptiste Daroussin if (lua_type (L, 2) == LUA_TSTRING) { 83839ee7a7aSBaptiste Daroussin const char *strtype = lua_tostring (L, 2); 83939ee7a7aSBaptiste Daroussin 840*11dd9ed6SBaptiste Daroussin format = lua_ucl_str_to_emit_type (strtype); 84139ee7a7aSBaptiste Daroussin } 84239ee7a7aSBaptiste Daroussin } 84339ee7a7aSBaptiste Daroussin 84439ee7a7aSBaptiste Daroussin return lua_ucl_to_string (L, obj, format); 84539ee7a7aSBaptiste Daroussin } 84639ee7a7aSBaptiste Daroussin else { 84739ee7a7aSBaptiste Daroussin lua_pushnil (L); 84839ee7a7aSBaptiste Daroussin } 84939ee7a7aSBaptiste Daroussin 85039ee7a7aSBaptiste Daroussin return 1; 85139ee7a7aSBaptiste Daroussin } 85239ee7a7aSBaptiste Daroussin 85339ee7a7aSBaptiste Daroussin /*** 854d9f0ce31SBaptiste Daroussin * @method object:validate(schema[, path[, ext_refs]]) 85539ee7a7aSBaptiste Daroussin * Validates the given ucl object using schema object represented as another 85639ee7a7aSBaptiste Daroussin * opaque ucl object. You can also specify path in the form `#/path/def` to 85739ee7a7aSBaptiste Daroussin * specify the specific schema element to perform validation. 85839ee7a7aSBaptiste Daroussin * 85939ee7a7aSBaptiste Daroussin * @param {ucl.object} schema schema object 86039ee7a7aSBaptiste Daroussin * @param {string} path optional path for validation procedure 861d9f0ce31SBaptiste Daroussin * @return {result,err} two values: boolean result and the corresponding 862d9f0ce31SBaptiste Daroussin * error, if `ext_refs` are also specified, then they are returned as opaque 863d9f0ce31SBaptiste Daroussin * ucl object as {result,err,ext_refs} 86439ee7a7aSBaptiste Daroussin */ 86539ee7a7aSBaptiste Daroussin static int 86639ee7a7aSBaptiste Daroussin lua_ucl_object_validate (lua_State *L) 86739ee7a7aSBaptiste Daroussin { 868d9f0ce31SBaptiste Daroussin ucl_object_t *obj, *schema, *ext_refs = NULL; 86939ee7a7aSBaptiste Daroussin const ucl_object_t *schema_elt; 87039ee7a7aSBaptiste Daroussin bool res = false; 87139ee7a7aSBaptiste Daroussin struct ucl_schema_error err; 87239ee7a7aSBaptiste Daroussin const char *path = NULL; 87339ee7a7aSBaptiste Daroussin 87439ee7a7aSBaptiste Daroussin obj = lua_ucl_object_get (L, 1); 87539ee7a7aSBaptiste Daroussin schema = lua_ucl_object_get (L, 2); 87639ee7a7aSBaptiste Daroussin 87739ee7a7aSBaptiste Daroussin if (schema && obj && ucl_object_type (schema) == UCL_OBJECT) { 878d9f0ce31SBaptiste Daroussin if (lua_gettop (L) > 2) { 879d9f0ce31SBaptiste Daroussin if (lua_type (L, 3) == LUA_TSTRING) { 88039ee7a7aSBaptiste Daroussin path = lua_tostring (L, 3); 88139ee7a7aSBaptiste Daroussin if (path[0] == '#') { 88239ee7a7aSBaptiste Daroussin path++; 88339ee7a7aSBaptiste Daroussin } 88439ee7a7aSBaptiste Daroussin } 885d9f0ce31SBaptiste Daroussin else if (lua_type (L, 3) == LUA_TUSERDATA || lua_type (L, 3) == 886d9f0ce31SBaptiste Daroussin LUA_TTABLE) { 887d9f0ce31SBaptiste Daroussin /* External refs */ 888d9f0ce31SBaptiste Daroussin ext_refs = lua_ucl_object_get (L, 3); 889d9f0ce31SBaptiste Daroussin } 890d9f0ce31SBaptiste Daroussin 891d9f0ce31SBaptiste Daroussin if (lua_gettop (L) > 3) { 892d9f0ce31SBaptiste Daroussin if (lua_type (L, 4) == LUA_TUSERDATA || lua_type (L, 4) == 893d9f0ce31SBaptiste Daroussin LUA_TTABLE) { 894d9f0ce31SBaptiste Daroussin /* External refs */ 895d9f0ce31SBaptiste Daroussin ext_refs = lua_ucl_object_get (L, 4); 896d9f0ce31SBaptiste Daroussin } 897d9f0ce31SBaptiste Daroussin } 898d9f0ce31SBaptiste Daroussin } 89939ee7a7aSBaptiste Daroussin 90039ee7a7aSBaptiste Daroussin if (path) { 901d9f0ce31SBaptiste Daroussin schema_elt = ucl_object_lookup_path_char (schema, path, '/'); 90239ee7a7aSBaptiste Daroussin } 90339ee7a7aSBaptiste Daroussin else { 90439ee7a7aSBaptiste Daroussin /* Use the top object */ 90539ee7a7aSBaptiste Daroussin schema_elt = schema; 90639ee7a7aSBaptiste Daroussin } 90739ee7a7aSBaptiste Daroussin 90839ee7a7aSBaptiste Daroussin if (schema_elt) { 909d9f0ce31SBaptiste Daroussin res = ucl_object_validate_root_ext (schema_elt, obj, schema, 910d9f0ce31SBaptiste Daroussin ext_refs, &err); 91139ee7a7aSBaptiste Daroussin 91239ee7a7aSBaptiste Daroussin if (res) { 91339ee7a7aSBaptiste Daroussin lua_pushboolean (L, res); 91439ee7a7aSBaptiste Daroussin lua_pushnil (L); 915d9f0ce31SBaptiste Daroussin 916d9f0ce31SBaptiste Daroussin if (ext_refs) { 917d9f0ce31SBaptiste Daroussin lua_ucl_push_opaque (L, ext_refs); 918d9f0ce31SBaptiste Daroussin } 91939ee7a7aSBaptiste Daroussin } 92039ee7a7aSBaptiste Daroussin else { 92139ee7a7aSBaptiste Daroussin lua_pushboolean (L, res); 92239ee7a7aSBaptiste Daroussin lua_pushfstring (L, "validation error: %s", err.msg); 923d9f0ce31SBaptiste Daroussin 924d9f0ce31SBaptiste Daroussin if (ext_refs) { 925d9f0ce31SBaptiste Daroussin lua_ucl_push_opaque (L, ext_refs); 926d9f0ce31SBaptiste Daroussin } 92739ee7a7aSBaptiste Daroussin } 92839ee7a7aSBaptiste Daroussin } 92939ee7a7aSBaptiste Daroussin else { 93039ee7a7aSBaptiste Daroussin lua_pushboolean (L, res); 93139ee7a7aSBaptiste Daroussin 93239ee7a7aSBaptiste Daroussin lua_pushfstring (L, "cannot find the requested path: %s", path); 933d9f0ce31SBaptiste Daroussin 934d9f0ce31SBaptiste Daroussin if (ext_refs) { 935d9f0ce31SBaptiste Daroussin lua_ucl_push_opaque (L, ext_refs); 93639ee7a7aSBaptiste Daroussin } 93739ee7a7aSBaptiste Daroussin } 93839ee7a7aSBaptiste Daroussin } 93939ee7a7aSBaptiste Daroussin else { 94039ee7a7aSBaptiste Daroussin lua_pushboolean (L, res); 94139ee7a7aSBaptiste Daroussin lua_pushstring (L, "invalid object or schema"); 94239ee7a7aSBaptiste Daroussin } 94339ee7a7aSBaptiste Daroussin 944d9f0ce31SBaptiste Daroussin if (ext_refs) { 945d9f0ce31SBaptiste Daroussin return 3; 946d9f0ce31SBaptiste Daroussin } 947d9f0ce31SBaptiste Daroussin 94839ee7a7aSBaptiste Daroussin return 2; 94939ee7a7aSBaptiste Daroussin } 95039ee7a7aSBaptiste Daroussin 95139ee7a7aSBaptiste Daroussin static int 95239ee7a7aSBaptiste Daroussin lua_ucl_object_gc (lua_State *L) 95339ee7a7aSBaptiste Daroussin { 95439ee7a7aSBaptiste Daroussin ucl_object_t *obj; 95539ee7a7aSBaptiste Daroussin 95639ee7a7aSBaptiste Daroussin obj = lua_ucl_object_get (L, 1); 95739ee7a7aSBaptiste Daroussin 95839ee7a7aSBaptiste Daroussin ucl_object_unref (obj); 95939ee7a7aSBaptiste Daroussin 96039ee7a7aSBaptiste Daroussin return 0; 96139ee7a7aSBaptiste Daroussin } 96239ee7a7aSBaptiste Daroussin 9634bf54857SBaptiste Daroussin static void 9644bf54857SBaptiste Daroussin lua_ucl_parser_mt (lua_State *L) 9654bf54857SBaptiste Daroussin { 9664bf54857SBaptiste Daroussin luaL_newmetatable (L, PARSER_META); 9674bf54857SBaptiste Daroussin 9684bf54857SBaptiste Daroussin lua_pushvalue(L, -1); 9694bf54857SBaptiste Daroussin lua_setfield(L, -2, "__index"); 9704bf54857SBaptiste Daroussin 9714bf54857SBaptiste Daroussin lua_pushcfunction (L, lua_ucl_parser_gc); 9724bf54857SBaptiste Daroussin lua_setfield (L, -2, "__gc"); 9734bf54857SBaptiste Daroussin 9744bf54857SBaptiste Daroussin lua_pushcfunction (L, lua_ucl_parser_parse_file); 9754bf54857SBaptiste Daroussin lua_setfield (L, -2, "parse_file"); 9764bf54857SBaptiste Daroussin 9774bf54857SBaptiste Daroussin lua_pushcfunction (L, lua_ucl_parser_parse_string); 9784bf54857SBaptiste Daroussin lua_setfield (L, -2, "parse_string"); 9794bf54857SBaptiste Daroussin 9804bf54857SBaptiste Daroussin lua_pushcfunction (L, lua_ucl_parser_get_object); 9814bf54857SBaptiste Daroussin lua_setfield (L, -2, "get_object"); 9824bf54857SBaptiste Daroussin 98339ee7a7aSBaptiste Daroussin lua_pushcfunction (L, lua_ucl_parser_get_object_wrapped); 98439ee7a7aSBaptiste Daroussin lua_setfield (L, -2, "get_object_wrapped"); 98539ee7a7aSBaptiste Daroussin 98639ee7a7aSBaptiste Daroussin lua_pushcfunction (L, lua_ucl_parser_validate); 98739ee7a7aSBaptiste Daroussin lua_setfield (L, -2, "validate"); 98839ee7a7aSBaptiste Daroussin 9894bf54857SBaptiste Daroussin lua_pop (L, 1); 9904bf54857SBaptiste Daroussin } 9914bf54857SBaptiste Daroussin 99239ee7a7aSBaptiste Daroussin static void 99339ee7a7aSBaptiste Daroussin lua_ucl_object_mt (lua_State *L) 9944bf54857SBaptiste Daroussin { 99539ee7a7aSBaptiste Daroussin luaL_newmetatable (L, OBJECT_META); 9964bf54857SBaptiste Daroussin 99739ee7a7aSBaptiste Daroussin lua_pushvalue(L, -1); 99839ee7a7aSBaptiste Daroussin lua_setfield(L, -2, "__index"); 9994bf54857SBaptiste Daroussin 100039ee7a7aSBaptiste Daroussin lua_pushcfunction (L, lua_ucl_object_gc); 100139ee7a7aSBaptiste Daroussin lua_setfield (L, -2, "__gc"); 10024bf54857SBaptiste Daroussin 100339ee7a7aSBaptiste Daroussin lua_pushcfunction (L, lua_ucl_object_tostring); 100439ee7a7aSBaptiste Daroussin lua_setfield (L, -2, "__tostring"); 100539ee7a7aSBaptiste Daroussin 100639ee7a7aSBaptiste Daroussin lua_pushcfunction (L, lua_ucl_object_tostring); 100739ee7a7aSBaptiste Daroussin lua_setfield (L, -2, "tostring"); 100839ee7a7aSBaptiste Daroussin 100939ee7a7aSBaptiste Daroussin lua_pushcfunction (L, lua_ucl_object_unwrap); 101039ee7a7aSBaptiste Daroussin lua_setfield (L, -2, "unwrap"); 101139ee7a7aSBaptiste Daroussin 101239ee7a7aSBaptiste Daroussin lua_pushcfunction (L, lua_ucl_object_unwrap); 101339ee7a7aSBaptiste Daroussin lua_setfield (L, -2, "tolua"); 101439ee7a7aSBaptiste Daroussin 101539ee7a7aSBaptiste Daroussin lua_pushcfunction (L, lua_ucl_object_validate); 101639ee7a7aSBaptiste Daroussin lua_setfield (L, -2, "validate"); 101739ee7a7aSBaptiste Daroussin 101839ee7a7aSBaptiste Daroussin lua_pushstring (L, OBJECT_META); 101939ee7a7aSBaptiste Daroussin lua_setfield (L, -2, "class"); 102039ee7a7aSBaptiste Daroussin 102139ee7a7aSBaptiste Daroussin lua_pop (L, 1); 10224bf54857SBaptiste Daroussin } 10234bf54857SBaptiste Daroussin 10244bf54857SBaptiste Daroussin static int 10254bf54857SBaptiste Daroussin lua_ucl_to_json (lua_State *L) 10264bf54857SBaptiste Daroussin { 10274bf54857SBaptiste Daroussin ucl_object_t *obj; 10284bf54857SBaptiste Daroussin int format = UCL_EMIT_JSON; 10294bf54857SBaptiste Daroussin 10304bf54857SBaptiste Daroussin if (lua_gettop (L) > 1) { 10314bf54857SBaptiste Daroussin if (lua_toboolean (L, 2)) { 10324bf54857SBaptiste Daroussin format = UCL_EMIT_JSON_COMPACT; 10334bf54857SBaptiste Daroussin } 10344bf54857SBaptiste Daroussin } 10354bf54857SBaptiste Daroussin 10364bf54857SBaptiste Daroussin obj = ucl_object_lua_import (L, 1); 10374bf54857SBaptiste Daroussin if (obj != NULL) { 10384bf54857SBaptiste Daroussin lua_ucl_to_string (L, obj, format); 10394bf54857SBaptiste Daroussin ucl_object_unref (obj); 10404bf54857SBaptiste Daroussin } 10414bf54857SBaptiste Daroussin else { 10424bf54857SBaptiste Daroussin lua_pushnil (L); 10434bf54857SBaptiste Daroussin } 10444bf54857SBaptiste Daroussin 10454bf54857SBaptiste Daroussin return 1; 10464bf54857SBaptiste Daroussin } 10474bf54857SBaptiste Daroussin 10484bf54857SBaptiste Daroussin static int 10494bf54857SBaptiste Daroussin lua_ucl_to_config (lua_State *L) 10504bf54857SBaptiste Daroussin { 10514bf54857SBaptiste Daroussin ucl_object_t *obj; 10524bf54857SBaptiste Daroussin 10534bf54857SBaptiste Daroussin obj = ucl_object_lua_import (L, 1); 10544bf54857SBaptiste Daroussin if (obj != NULL) { 10554bf54857SBaptiste Daroussin lua_ucl_to_string (L, obj, UCL_EMIT_CONFIG); 10564bf54857SBaptiste Daroussin ucl_object_unref (obj); 10574bf54857SBaptiste Daroussin } 10584bf54857SBaptiste Daroussin else { 10594bf54857SBaptiste Daroussin lua_pushnil (L); 10604bf54857SBaptiste Daroussin } 10614bf54857SBaptiste Daroussin 10624bf54857SBaptiste Daroussin return 1; 10634bf54857SBaptiste Daroussin } 10644bf54857SBaptiste Daroussin 10654bf54857SBaptiste Daroussin /*** 10664bf54857SBaptiste Daroussin * @function ucl.to_format(var, format) 10674bf54857SBaptiste Daroussin * Converts lua variable `var` to the specified `format`. Formats supported are: 10684bf54857SBaptiste Daroussin * 10694bf54857SBaptiste Daroussin * - `json` - fine printed json 10704bf54857SBaptiste Daroussin * - `json-compact` - compacted json 10714bf54857SBaptiste Daroussin * - `config` - fine printed configuration 10724bf54857SBaptiste Daroussin * - `ucl` - same as `config` 10734bf54857SBaptiste Daroussin * - `yaml` - embedded yaml 10744bf54857SBaptiste Daroussin * 10754bf54857SBaptiste Daroussin * If `var` contains function, they are called during output formatting and if 10764bf54857SBaptiste Daroussin * they return string value, then this value is used for ouptut. 10774bf54857SBaptiste Daroussin * @param {variant} var any sort of lua variable (if userdata then metafield `__to_ucl` is searched for output) 10784bf54857SBaptiste Daroussin * @param {string} format any available format 10794bf54857SBaptiste Daroussin * @return {string} string representation of `var` in the specific `format`. 10804bf54857SBaptiste Daroussin * @example 10814bf54857SBaptiste Daroussin local table = { 10824bf54857SBaptiste Daroussin str = 'value', 10834bf54857SBaptiste Daroussin num = 100500, 10844bf54857SBaptiste Daroussin null = ucl.null, 10854bf54857SBaptiste Daroussin func = function () 10864bf54857SBaptiste Daroussin return 'huh' 10874bf54857SBaptiste Daroussin end 10884bf54857SBaptiste Daroussin } 10894bf54857SBaptiste Daroussin 10904bf54857SBaptiste Daroussin print(ucl.to_format(table, 'ucl')) 10914bf54857SBaptiste Daroussin -- Output: 10924bf54857SBaptiste Daroussin --[[ 10934bf54857SBaptiste Daroussin num = 100500; 10944bf54857SBaptiste Daroussin str = "value"; 10954bf54857SBaptiste Daroussin null = null; 10964bf54857SBaptiste Daroussin func = "huh"; 10974bf54857SBaptiste Daroussin --]] 10984bf54857SBaptiste Daroussin */ 10994bf54857SBaptiste Daroussin static int 11004bf54857SBaptiste Daroussin lua_ucl_to_format (lua_State *L) 11014bf54857SBaptiste Daroussin { 11024bf54857SBaptiste Daroussin ucl_object_t *obj; 11034bf54857SBaptiste Daroussin int format = UCL_EMIT_JSON; 11044bf54857SBaptiste Daroussin 11054bf54857SBaptiste Daroussin if (lua_gettop (L) > 1) { 11064bf54857SBaptiste Daroussin if (lua_type (L, 2) == LUA_TNUMBER) { 11074bf54857SBaptiste Daroussin format = lua_tonumber (L, 2); 11084bf54857SBaptiste Daroussin if (format < 0 || format >= UCL_EMIT_YAML) { 11094bf54857SBaptiste Daroussin lua_pushnil (L); 11104bf54857SBaptiste Daroussin return 1; 11114bf54857SBaptiste Daroussin } 11124bf54857SBaptiste Daroussin } 11134bf54857SBaptiste Daroussin else if (lua_type (L, 2) == LUA_TSTRING) { 11144bf54857SBaptiste Daroussin const char *strtype = lua_tostring (L, 2); 11154bf54857SBaptiste Daroussin 11164bf54857SBaptiste Daroussin if (strcasecmp (strtype, "json") == 0) { 11174bf54857SBaptiste Daroussin format = UCL_EMIT_JSON; 11184bf54857SBaptiste Daroussin } 11194bf54857SBaptiste Daroussin else if (strcasecmp (strtype, "json-compact") == 0) { 11204bf54857SBaptiste Daroussin format = UCL_EMIT_JSON_COMPACT; 11214bf54857SBaptiste Daroussin } 11224bf54857SBaptiste Daroussin else if (strcasecmp (strtype, "yaml") == 0) { 11234bf54857SBaptiste Daroussin format = UCL_EMIT_YAML; 11244bf54857SBaptiste Daroussin } 11254bf54857SBaptiste Daroussin else if (strcasecmp (strtype, "config") == 0 || 11264bf54857SBaptiste Daroussin strcasecmp (strtype, "ucl") == 0) { 11274bf54857SBaptiste Daroussin format = UCL_EMIT_CONFIG; 11284bf54857SBaptiste Daroussin } 1129*11dd9ed6SBaptiste Daroussin else if (strcasecmp (strtype, "msgpack") == 0) { 1130*11dd9ed6SBaptiste Daroussin format = UCL_EMIT_MSGPACK; 1131*11dd9ed6SBaptiste Daroussin } 11324bf54857SBaptiste Daroussin } 11334bf54857SBaptiste Daroussin } 11344bf54857SBaptiste Daroussin 11354bf54857SBaptiste Daroussin obj = ucl_object_lua_import (L, 1); 11364bf54857SBaptiste Daroussin if (obj != NULL) { 11374bf54857SBaptiste Daroussin lua_ucl_to_string (L, obj, format); 11384bf54857SBaptiste Daroussin ucl_object_unref (obj); 11394bf54857SBaptiste Daroussin } 11404bf54857SBaptiste Daroussin else { 11414bf54857SBaptiste Daroussin lua_pushnil (L); 11424bf54857SBaptiste Daroussin } 11434bf54857SBaptiste Daroussin 11444bf54857SBaptiste Daroussin return 1; 11454bf54857SBaptiste Daroussin } 11464bf54857SBaptiste Daroussin 11474bf54857SBaptiste Daroussin static int 11484bf54857SBaptiste Daroussin lua_ucl_null_tostring (lua_State* L) 11494bf54857SBaptiste Daroussin { 11504bf54857SBaptiste Daroussin lua_pushstring (L, "null"); 11514bf54857SBaptiste Daroussin return 1; 11524bf54857SBaptiste Daroussin } 11534bf54857SBaptiste Daroussin 11544bf54857SBaptiste Daroussin static void 11554bf54857SBaptiste Daroussin lua_ucl_null_mt (lua_State *L) 11564bf54857SBaptiste Daroussin { 11574bf54857SBaptiste Daroussin luaL_newmetatable (L, NULL_META); 11584bf54857SBaptiste Daroussin 11594bf54857SBaptiste Daroussin lua_pushcfunction (L, lua_ucl_null_tostring); 11604bf54857SBaptiste Daroussin lua_setfield (L, -2, "__tostring"); 11614bf54857SBaptiste Daroussin 11624bf54857SBaptiste Daroussin lua_pop (L, 1); 11634bf54857SBaptiste Daroussin } 11644bf54857SBaptiste Daroussin 11654bf54857SBaptiste Daroussin int 11664bf54857SBaptiste Daroussin luaopen_ucl (lua_State *L) 11674bf54857SBaptiste Daroussin { 11684bf54857SBaptiste Daroussin lua_ucl_parser_mt (L); 11694bf54857SBaptiste Daroussin lua_ucl_null_mt (L); 117039ee7a7aSBaptiste Daroussin lua_ucl_object_mt (L); 11714bf54857SBaptiste Daroussin 11724bf54857SBaptiste Daroussin /* Create the refs weak table: */ 11734bf54857SBaptiste Daroussin lua_createtable (L, 0, 2); 11744bf54857SBaptiste Daroussin lua_pushliteral (L, "v"); /* tbl, "v" */ 11754bf54857SBaptiste Daroussin lua_setfield (L, -2, "__mode"); 11764bf54857SBaptiste Daroussin lua_pushvalue (L, -1); /* tbl, tbl */ 11774bf54857SBaptiste Daroussin lua_setmetatable (L, -2); /* tbl */ 11784bf54857SBaptiste Daroussin lua_setfield (L, LUA_REGISTRYINDEX, "ucl.refs"); 11794bf54857SBaptiste Daroussin 11804bf54857SBaptiste Daroussin lua_newtable (L); 11814bf54857SBaptiste Daroussin 11824bf54857SBaptiste Daroussin lua_pushcfunction (L, lua_ucl_parser_init); 11834bf54857SBaptiste Daroussin lua_setfield (L, -2, "parser"); 11844bf54857SBaptiste Daroussin 11854bf54857SBaptiste Daroussin lua_pushcfunction (L, lua_ucl_to_json); 11864bf54857SBaptiste Daroussin lua_setfield (L, -2, "to_json"); 11874bf54857SBaptiste Daroussin 11884bf54857SBaptiste Daroussin lua_pushcfunction (L, lua_ucl_to_config); 11894bf54857SBaptiste Daroussin lua_setfield (L, -2, "to_config"); 11904bf54857SBaptiste Daroussin 11914bf54857SBaptiste Daroussin lua_pushcfunction (L, lua_ucl_to_format); 11924bf54857SBaptiste Daroussin lua_setfield (L, -2, "to_format"); 11934bf54857SBaptiste Daroussin 11944bf54857SBaptiste Daroussin ucl_null = lua_newuserdata (L, 0); 11954bf54857SBaptiste Daroussin luaL_getmetatable (L, NULL_META); 11964bf54857SBaptiste Daroussin lua_setmetatable (L, -2); 11974bf54857SBaptiste Daroussin 11984bf54857SBaptiste Daroussin lua_pushvalue (L, -1); 11994bf54857SBaptiste Daroussin lua_setfield (L, LUA_REGISTRYINDEX, "ucl.null"); 12004bf54857SBaptiste Daroussin 12014bf54857SBaptiste Daroussin lua_setfield (L, -2, "null"); 12024bf54857SBaptiste Daroussin 12034bf54857SBaptiste Daroussin return 1; 12044bf54857SBaptiste Daroussin } 12054bf54857SBaptiste Daroussin 12064bf54857SBaptiste Daroussin struct ucl_lua_funcdata* 12074bf54857SBaptiste Daroussin ucl_object_toclosure (const ucl_object_t *obj) 12084bf54857SBaptiste Daroussin { 12094bf54857SBaptiste Daroussin if (obj == NULL || obj->type != UCL_USERDATA) { 12104bf54857SBaptiste Daroussin return NULL; 12114bf54857SBaptiste Daroussin } 12124bf54857SBaptiste Daroussin 12134bf54857SBaptiste Daroussin return (struct ucl_lua_funcdata*)obj->value.ud; 12144bf54857SBaptiste Daroussin } 1215