1*4bf54857SBaptiste Daroussin /* Copyright (c) 2014, Vsevolod Stakhov 2*4bf54857SBaptiste Daroussin * All rights reserved. 3*4bf54857SBaptiste Daroussin * 4*4bf54857SBaptiste Daroussin * Redistribution and use in source and binary forms, with or without 5*4bf54857SBaptiste Daroussin * modification, are permitted provided that the following conditions are met: 6*4bf54857SBaptiste Daroussin * * Redistributions of source code must retain the above copyright 7*4bf54857SBaptiste Daroussin * notice, this list of conditions and the following disclaimer. 8*4bf54857SBaptiste Daroussin * * Redistributions in binary form must reproduce the above copyright 9*4bf54857SBaptiste Daroussin * notice, this list of conditions and the following disclaimer in the 10*4bf54857SBaptiste Daroussin * documentation and/or other materials provided with the distribution. 11*4bf54857SBaptiste Daroussin * 12*4bf54857SBaptiste Daroussin * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY 13*4bf54857SBaptiste Daroussin * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 14*4bf54857SBaptiste Daroussin * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 15*4bf54857SBaptiste Daroussin * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY 16*4bf54857SBaptiste Daroussin * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 17*4bf54857SBaptiste Daroussin * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 18*4bf54857SBaptiste Daroussin * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 19*4bf54857SBaptiste Daroussin * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 20*4bf54857SBaptiste Daroussin * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 21*4bf54857SBaptiste Daroussin * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22*4bf54857SBaptiste Daroussin */ 23*4bf54857SBaptiste Daroussin 24*4bf54857SBaptiste Daroussin /** 25*4bf54857SBaptiste Daroussin * @file lua ucl bindings 26*4bf54857SBaptiste Daroussin */ 27*4bf54857SBaptiste Daroussin 28*4bf54857SBaptiste Daroussin #include "ucl.h" 29*4bf54857SBaptiste Daroussin #include "ucl_internal.h" 30*4bf54857SBaptiste Daroussin #include "lua_ucl.h" 31*4bf54857SBaptiste Daroussin #include <strings.h> 32*4bf54857SBaptiste Daroussin 33*4bf54857SBaptiste Daroussin /*** 34*4bf54857SBaptiste Daroussin * @module ucl 35*4bf54857SBaptiste Daroussin * This lua module allows to parse objects from strings and to store data into 36*4bf54857SBaptiste Daroussin * ucl objects. It uses `libucl` C library to parse and manipulate with ucl objects. 37*4bf54857SBaptiste Daroussin * @example 38*4bf54857SBaptiste Daroussin local ucl = require("ucl") 39*4bf54857SBaptiste Daroussin 40*4bf54857SBaptiste Daroussin local parser = ucl.parser() 41*4bf54857SBaptiste Daroussin local res,err = parser:parse_string('{key=value}') 42*4bf54857SBaptiste Daroussin 43*4bf54857SBaptiste Daroussin if not res then 44*4bf54857SBaptiste Daroussin print('parser error: ' .. err) 45*4bf54857SBaptiste Daroussin else 46*4bf54857SBaptiste Daroussin local obj = parser:get_object() 47*4bf54857SBaptiste Daroussin local got = ucl.to_format(obj, 'json') 48*4bf54857SBaptiste Daroussin endif 49*4bf54857SBaptiste Daroussin 50*4bf54857SBaptiste Daroussin local table = { 51*4bf54857SBaptiste Daroussin str = 'value', 52*4bf54857SBaptiste Daroussin num = 100500, 53*4bf54857SBaptiste Daroussin null = ucl.null, 54*4bf54857SBaptiste Daroussin func = function () 55*4bf54857SBaptiste Daroussin return 'huh' 56*4bf54857SBaptiste Daroussin end 57*4bf54857SBaptiste Daroussin } 58*4bf54857SBaptiste Daroussin 59*4bf54857SBaptiste Daroussin print(ucl.to_format(table, 'ucl')) 60*4bf54857SBaptiste Daroussin -- Output: 61*4bf54857SBaptiste Daroussin --[[ 62*4bf54857SBaptiste Daroussin num = 100500; 63*4bf54857SBaptiste Daroussin str = "value"; 64*4bf54857SBaptiste Daroussin null = null; 65*4bf54857SBaptiste Daroussin func = "huh"; 66*4bf54857SBaptiste Daroussin --]] 67*4bf54857SBaptiste Daroussin */ 68*4bf54857SBaptiste Daroussin 69*4bf54857SBaptiste Daroussin #define PARSER_META "ucl.parser.meta" 70*4bf54857SBaptiste Daroussin #define EMITTER_META "ucl.emitter.meta" 71*4bf54857SBaptiste Daroussin #define NULL_META "null.emitter.meta" 72*4bf54857SBaptiste Daroussin 73*4bf54857SBaptiste Daroussin static int ucl_object_lua_push_array (lua_State *L, const ucl_object_t *obj); 74*4bf54857SBaptiste Daroussin static int ucl_object_lua_push_scalar (lua_State *L, const ucl_object_t *obj, bool allow_array); 75*4bf54857SBaptiste Daroussin static ucl_object_t* ucl_object_lua_fromtable (lua_State *L, int idx); 76*4bf54857SBaptiste Daroussin static ucl_object_t* ucl_object_lua_fromelt (lua_State *L, int idx); 77*4bf54857SBaptiste Daroussin 78*4bf54857SBaptiste Daroussin static void *ucl_null; 79*4bf54857SBaptiste Daroussin 80*4bf54857SBaptiste Daroussin /** 81*4bf54857SBaptiste Daroussin * Push a single element of an object to lua 82*4bf54857SBaptiste Daroussin * @param L 83*4bf54857SBaptiste Daroussin * @param key 84*4bf54857SBaptiste Daroussin * @param obj 85*4bf54857SBaptiste Daroussin */ 86*4bf54857SBaptiste Daroussin static void 87*4bf54857SBaptiste Daroussin ucl_object_lua_push_element (lua_State *L, const char *key, 88*4bf54857SBaptiste Daroussin const ucl_object_t *obj) 89*4bf54857SBaptiste Daroussin { 90*4bf54857SBaptiste Daroussin lua_pushstring (L, key); 91*4bf54857SBaptiste Daroussin ucl_object_push_lua (L, obj, true); 92*4bf54857SBaptiste Daroussin lua_settable (L, -3); 93*4bf54857SBaptiste Daroussin } 94*4bf54857SBaptiste Daroussin 95*4bf54857SBaptiste Daroussin static void 96*4bf54857SBaptiste Daroussin lua_ucl_userdata_dtor (void *ud) 97*4bf54857SBaptiste Daroussin { 98*4bf54857SBaptiste Daroussin struct ucl_lua_funcdata *fd = (struct ucl_lua_funcdata *)ud; 99*4bf54857SBaptiste Daroussin 100*4bf54857SBaptiste Daroussin luaL_unref (fd->L, LUA_REGISTRYINDEX, fd->idx); 101*4bf54857SBaptiste Daroussin if (fd->ret != NULL) { 102*4bf54857SBaptiste Daroussin free (fd->ret); 103*4bf54857SBaptiste Daroussin } 104*4bf54857SBaptiste Daroussin free (fd); 105*4bf54857SBaptiste Daroussin } 106*4bf54857SBaptiste Daroussin 107*4bf54857SBaptiste Daroussin static const char * 108*4bf54857SBaptiste Daroussin lua_ucl_userdata_emitter (void *ud) 109*4bf54857SBaptiste Daroussin { 110*4bf54857SBaptiste Daroussin struct ucl_lua_funcdata *fd = (struct ucl_lua_funcdata *)ud; 111*4bf54857SBaptiste Daroussin const char *out = ""; 112*4bf54857SBaptiste Daroussin 113*4bf54857SBaptiste Daroussin lua_rawgeti (fd->L, LUA_REGISTRYINDEX, fd->idx); 114*4bf54857SBaptiste Daroussin 115*4bf54857SBaptiste Daroussin lua_pcall (fd->L, 0, 1, 0); 116*4bf54857SBaptiste Daroussin out = lua_tostring (fd->L, -1); 117*4bf54857SBaptiste Daroussin 118*4bf54857SBaptiste Daroussin if (out != NULL) { 119*4bf54857SBaptiste Daroussin /* We need to store temporary string in a more appropriate place */ 120*4bf54857SBaptiste Daroussin if (fd->ret) { 121*4bf54857SBaptiste Daroussin free (fd->ret); 122*4bf54857SBaptiste Daroussin } 123*4bf54857SBaptiste Daroussin fd->ret = strdup (out); 124*4bf54857SBaptiste Daroussin } 125*4bf54857SBaptiste Daroussin 126*4bf54857SBaptiste Daroussin lua_settop (fd->L, 0); 127*4bf54857SBaptiste Daroussin 128*4bf54857SBaptiste Daroussin return fd->ret; 129*4bf54857SBaptiste Daroussin } 130*4bf54857SBaptiste Daroussin 131*4bf54857SBaptiste Daroussin /** 132*4bf54857SBaptiste Daroussin * Push a single object to lua 133*4bf54857SBaptiste Daroussin * @param L 134*4bf54857SBaptiste Daroussin * @param obj 135*4bf54857SBaptiste Daroussin * @return 136*4bf54857SBaptiste Daroussin */ 137*4bf54857SBaptiste Daroussin static int 138*4bf54857SBaptiste Daroussin ucl_object_lua_push_object (lua_State *L, const ucl_object_t *obj, 139*4bf54857SBaptiste Daroussin bool allow_array) 140*4bf54857SBaptiste Daroussin { 141*4bf54857SBaptiste Daroussin const ucl_object_t *cur; 142*4bf54857SBaptiste Daroussin ucl_object_iter_t it = NULL; 143*4bf54857SBaptiste Daroussin int nelt = 0; 144*4bf54857SBaptiste Daroussin 145*4bf54857SBaptiste Daroussin if (allow_array && obj->next != NULL) { 146*4bf54857SBaptiste Daroussin /* Actually we need to push this as an array */ 147*4bf54857SBaptiste Daroussin return ucl_object_lua_push_array (L, obj); 148*4bf54857SBaptiste Daroussin } 149*4bf54857SBaptiste Daroussin 150*4bf54857SBaptiste Daroussin /* Optimize allocation by preallocation of table */ 151*4bf54857SBaptiste Daroussin while (ucl_iterate_object (obj, &it, true) != NULL) { 152*4bf54857SBaptiste Daroussin nelt ++; 153*4bf54857SBaptiste Daroussin } 154*4bf54857SBaptiste Daroussin 155*4bf54857SBaptiste Daroussin lua_createtable (L, 0, nelt); 156*4bf54857SBaptiste Daroussin it = NULL; 157*4bf54857SBaptiste Daroussin 158*4bf54857SBaptiste Daroussin while ((cur = ucl_iterate_object (obj, &it, true)) != NULL) { 159*4bf54857SBaptiste Daroussin ucl_object_lua_push_element (L, ucl_object_key (cur), cur); 160*4bf54857SBaptiste Daroussin } 161*4bf54857SBaptiste Daroussin 162*4bf54857SBaptiste Daroussin return 1; 163*4bf54857SBaptiste Daroussin } 164*4bf54857SBaptiste Daroussin 165*4bf54857SBaptiste Daroussin /** 166*4bf54857SBaptiste Daroussin * Push an array to lua as table indexed by integers 167*4bf54857SBaptiste Daroussin * @param L 168*4bf54857SBaptiste Daroussin * @param obj 169*4bf54857SBaptiste Daroussin * @return 170*4bf54857SBaptiste Daroussin */ 171*4bf54857SBaptiste Daroussin static int 172*4bf54857SBaptiste Daroussin ucl_object_lua_push_array (lua_State *L, const ucl_object_t *obj) 173*4bf54857SBaptiste Daroussin { 174*4bf54857SBaptiste Daroussin const ucl_object_t *cur; 175*4bf54857SBaptiste Daroussin int i = 1, nelt = 0; 176*4bf54857SBaptiste Daroussin 177*4bf54857SBaptiste Daroussin /* Optimize allocation by preallocation of table */ 178*4bf54857SBaptiste Daroussin LL_FOREACH (obj, cur) { 179*4bf54857SBaptiste Daroussin nelt ++; 180*4bf54857SBaptiste Daroussin } 181*4bf54857SBaptiste Daroussin 182*4bf54857SBaptiste Daroussin lua_createtable (L, nelt, 0); 183*4bf54857SBaptiste Daroussin 184*4bf54857SBaptiste Daroussin LL_FOREACH (obj, cur) { 185*4bf54857SBaptiste Daroussin ucl_object_push_lua (L, cur, false); 186*4bf54857SBaptiste Daroussin lua_rawseti (L, -2, i); 187*4bf54857SBaptiste Daroussin i ++; 188*4bf54857SBaptiste Daroussin } 189*4bf54857SBaptiste Daroussin 190*4bf54857SBaptiste Daroussin return 1; 191*4bf54857SBaptiste Daroussin } 192*4bf54857SBaptiste Daroussin 193*4bf54857SBaptiste Daroussin /** 194*4bf54857SBaptiste Daroussin * Push a simple object to lua depending on its actual type 195*4bf54857SBaptiste Daroussin */ 196*4bf54857SBaptiste Daroussin static int 197*4bf54857SBaptiste Daroussin ucl_object_lua_push_scalar (lua_State *L, const ucl_object_t *obj, 198*4bf54857SBaptiste Daroussin bool allow_array) 199*4bf54857SBaptiste Daroussin { 200*4bf54857SBaptiste Daroussin struct ucl_lua_funcdata *fd; 201*4bf54857SBaptiste Daroussin 202*4bf54857SBaptiste Daroussin if (allow_array && obj->next != NULL) { 203*4bf54857SBaptiste Daroussin /* Actually we need to push this as an array */ 204*4bf54857SBaptiste Daroussin return ucl_object_lua_push_array (L, obj); 205*4bf54857SBaptiste Daroussin } 206*4bf54857SBaptiste Daroussin 207*4bf54857SBaptiste Daroussin switch (obj->type) { 208*4bf54857SBaptiste Daroussin case UCL_BOOLEAN: 209*4bf54857SBaptiste Daroussin lua_pushboolean (L, ucl_obj_toboolean (obj)); 210*4bf54857SBaptiste Daroussin break; 211*4bf54857SBaptiste Daroussin case UCL_STRING: 212*4bf54857SBaptiste Daroussin lua_pushstring (L, ucl_obj_tostring (obj)); 213*4bf54857SBaptiste Daroussin break; 214*4bf54857SBaptiste Daroussin case UCL_INT: 215*4bf54857SBaptiste Daroussin #if LUA_VERSION_NUM >= 501 216*4bf54857SBaptiste Daroussin lua_pushinteger (L, ucl_obj_toint (obj)); 217*4bf54857SBaptiste Daroussin #else 218*4bf54857SBaptiste Daroussin lua_pushnumber (L, ucl_obj_toint (obj)); 219*4bf54857SBaptiste Daroussin #endif 220*4bf54857SBaptiste Daroussin break; 221*4bf54857SBaptiste Daroussin case UCL_FLOAT: 222*4bf54857SBaptiste Daroussin case UCL_TIME: 223*4bf54857SBaptiste Daroussin lua_pushnumber (L, ucl_obj_todouble (obj)); 224*4bf54857SBaptiste Daroussin break; 225*4bf54857SBaptiste Daroussin case UCL_NULL: 226*4bf54857SBaptiste Daroussin lua_getfield (L, LUA_REGISTRYINDEX, "ucl.null"); 227*4bf54857SBaptiste Daroussin break; 228*4bf54857SBaptiste Daroussin case UCL_USERDATA: 229*4bf54857SBaptiste Daroussin fd = (struct ucl_lua_funcdata *)obj->value.ud; 230*4bf54857SBaptiste Daroussin lua_rawgeti (L, LUA_REGISTRYINDEX, fd->idx); 231*4bf54857SBaptiste Daroussin break; 232*4bf54857SBaptiste Daroussin default: 233*4bf54857SBaptiste Daroussin lua_pushnil (L); 234*4bf54857SBaptiste Daroussin break; 235*4bf54857SBaptiste Daroussin } 236*4bf54857SBaptiste Daroussin 237*4bf54857SBaptiste Daroussin return 1; 238*4bf54857SBaptiste Daroussin } 239*4bf54857SBaptiste Daroussin 240*4bf54857SBaptiste Daroussin /*** 241*4bf54857SBaptiste Daroussin * @function ucl_object_push_lua(L, obj, allow_array) 242*4bf54857SBaptiste Daroussin * This is a `C` function to push `UCL` object as lua variable. This function 243*4bf54857SBaptiste Daroussin * converts `obj` to lua representation using the following conversions: 244*4bf54857SBaptiste Daroussin * 245*4bf54857SBaptiste Daroussin * - *scalar* values are directly presented by lua objects 246*4bf54857SBaptiste Daroussin * - *userdata* values are converted to lua function objects using `LUA_REGISTRYINDEX`, 247*4bf54857SBaptiste Daroussin * this can be used to pass functions from lua to c and vice-versa 248*4bf54857SBaptiste Daroussin * - *arrays* are converted to lua tables with numeric indicies suitable for `ipairs` iterations 249*4bf54857SBaptiste Daroussin * - *objects* are converted to lua tables with string indicies 250*4bf54857SBaptiste Daroussin * @param {lua_State} L lua state pointer 251*4bf54857SBaptiste Daroussin * @param {ucl_object_t} obj object to push 252*4bf54857SBaptiste Daroussin * @param {bool} allow_array expand implicit arrays (should be true for all but partial arrays) 253*4bf54857SBaptiste Daroussin * @return {int} `1` if an object is pushed to lua 254*4bf54857SBaptiste Daroussin */ 255*4bf54857SBaptiste Daroussin int 256*4bf54857SBaptiste Daroussin ucl_object_push_lua (lua_State *L, const ucl_object_t *obj, bool allow_array) 257*4bf54857SBaptiste Daroussin { 258*4bf54857SBaptiste Daroussin switch (obj->type) { 259*4bf54857SBaptiste Daroussin case UCL_OBJECT: 260*4bf54857SBaptiste Daroussin return ucl_object_lua_push_object (L, obj, allow_array); 261*4bf54857SBaptiste Daroussin case UCL_ARRAY: 262*4bf54857SBaptiste Daroussin return ucl_object_lua_push_array (L, obj->value.av); 263*4bf54857SBaptiste Daroussin default: 264*4bf54857SBaptiste Daroussin return ucl_object_lua_push_scalar (L, obj, allow_array); 265*4bf54857SBaptiste Daroussin } 266*4bf54857SBaptiste Daroussin } 267*4bf54857SBaptiste Daroussin 268*4bf54857SBaptiste Daroussin /** 269*4bf54857SBaptiste Daroussin * Parse lua table into object top 270*4bf54857SBaptiste Daroussin * @param L 271*4bf54857SBaptiste Daroussin * @param top 272*4bf54857SBaptiste Daroussin * @param idx 273*4bf54857SBaptiste Daroussin */ 274*4bf54857SBaptiste Daroussin static ucl_object_t * 275*4bf54857SBaptiste Daroussin ucl_object_lua_fromtable (lua_State *L, int idx) 276*4bf54857SBaptiste Daroussin { 277*4bf54857SBaptiste Daroussin ucl_object_t *obj, *top = NULL; 278*4bf54857SBaptiste Daroussin size_t keylen; 279*4bf54857SBaptiste Daroussin const char *k; 280*4bf54857SBaptiste Daroussin bool is_array = true; 281*4bf54857SBaptiste Daroussin int max = INT_MIN; 282*4bf54857SBaptiste Daroussin 283*4bf54857SBaptiste Daroussin if (idx < 0) { 284*4bf54857SBaptiste Daroussin /* For negative indicies we want to invert them */ 285*4bf54857SBaptiste Daroussin idx = lua_gettop (L) + idx + 1; 286*4bf54857SBaptiste Daroussin } 287*4bf54857SBaptiste Daroussin /* Check for array */ 288*4bf54857SBaptiste Daroussin lua_pushnil (L); 289*4bf54857SBaptiste Daroussin while (lua_next (L, idx) != 0) { 290*4bf54857SBaptiste Daroussin if (lua_type (L, -2) == LUA_TNUMBER) { 291*4bf54857SBaptiste Daroussin double num = lua_tonumber (L, -2); 292*4bf54857SBaptiste Daroussin if (num == (int)num) { 293*4bf54857SBaptiste Daroussin if (num > max) { 294*4bf54857SBaptiste Daroussin max = num; 295*4bf54857SBaptiste Daroussin } 296*4bf54857SBaptiste Daroussin } 297*4bf54857SBaptiste Daroussin else { 298*4bf54857SBaptiste Daroussin /* Keys are not integer */ 299*4bf54857SBaptiste Daroussin lua_pop (L, 2); 300*4bf54857SBaptiste Daroussin is_array = false; 301*4bf54857SBaptiste Daroussin break; 302*4bf54857SBaptiste Daroussin } 303*4bf54857SBaptiste Daroussin } 304*4bf54857SBaptiste Daroussin else { 305*4bf54857SBaptiste Daroussin /* Keys are not numeric */ 306*4bf54857SBaptiste Daroussin lua_pop (L, 2); 307*4bf54857SBaptiste Daroussin is_array = false; 308*4bf54857SBaptiste Daroussin break; 309*4bf54857SBaptiste Daroussin } 310*4bf54857SBaptiste Daroussin lua_pop (L, 1); 311*4bf54857SBaptiste Daroussin } 312*4bf54857SBaptiste Daroussin 313*4bf54857SBaptiste Daroussin /* Table iterate */ 314*4bf54857SBaptiste Daroussin if (is_array) { 315*4bf54857SBaptiste Daroussin int i; 316*4bf54857SBaptiste Daroussin 317*4bf54857SBaptiste Daroussin top = ucl_object_typed_new (UCL_ARRAY); 318*4bf54857SBaptiste Daroussin for (i = 1; i <= max; i ++) { 319*4bf54857SBaptiste Daroussin lua_pushinteger (L, i); 320*4bf54857SBaptiste Daroussin lua_gettable (L, idx); 321*4bf54857SBaptiste Daroussin obj = ucl_object_lua_fromelt (L, lua_gettop (L)); 322*4bf54857SBaptiste Daroussin if (obj != NULL) { 323*4bf54857SBaptiste Daroussin ucl_array_append (top, obj); 324*4bf54857SBaptiste Daroussin } 325*4bf54857SBaptiste Daroussin } 326*4bf54857SBaptiste Daroussin } 327*4bf54857SBaptiste Daroussin else { 328*4bf54857SBaptiste Daroussin lua_pushnil (L); 329*4bf54857SBaptiste Daroussin top = ucl_object_typed_new (UCL_OBJECT); 330*4bf54857SBaptiste Daroussin while (lua_next (L, idx) != 0) { 331*4bf54857SBaptiste Daroussin /* copy key to avoid modifications */ 332*4bf54857SBaptiste Daroussin k = lua_tolstring (L, -2, &keylen); 333*4bf54857SBaptiste Daroussin obj = ucl_object_lua_fromelt (L, lua_gettop (L)); 334*4bf54857SBaptiste Daroussin 335*4bf54857SBaptiste Daroussin if (obj != NULL) { 336*4bf54857SBaptiste Daroussin ucl_object_insert_key (top, obj, k, keylen, true); 337*4bf54857SBaptiste Daroussin } 338*4bf54857SBaptiste Daroussin lua_pop (L, 1); 339*4bf54857SBaptiste Daroussin } 340*4bf54857SBaptiste Daroussin } 341*4bf54857SBaptiste Daroussin 342*4bf54857SBaptiste Daroussin return top; 343*4bf54857SBaptiste Daroussin } 344*4bf54857SBaptiste Daroussin 345*4bf54857SBaptiste Daroussin /** 346*4bf54857SBaptiste Daroussin * Get a single element from lua to object obj 347*4bf54857SBaptiste Daroussin * @param L 348*4bf54857SBaptiste Daroussin * @param obj 349*4bf54857SBaptiste Daroussin * @param idx 350*4bf54857SBaptiste Daroussin */ 351*4bf54857SBaptiste Daroussin static ucl_object_t * 352*4bf54857SBaptiste Daroussin ucl_object_lua_fromelt (lua_State *L, int idx) 353*4bf54857SBaptiste Daroussin { 354*4bf54857SBaptiste Daroussin int type; 355*4bf54857SBaptiste Daroussin double num; 356*4bf54857SBaptiste Daroussin ucl_object_t *obj = NULL; 357*4bf54857SBaptiste Daroussin struct ucl_lua_funcdata *fd; 358*4bf54857SBaptiste Daroussin 359*4bf54857SBaptiste Daroussin type = lua_type (L, idx); 360*4bf54857SBaptiste Daroussin 361*4bf54857SBaptiste Daroussin switch (type) { 362*4bf54857SBaptiste Daroussin case LUA_TSTRING: 363*4bf54857SBaptiste Daroussin obj = ucl_object_fromstring_common (lua_tostring (L, idx), 0, 0); 364*4bf54857SBaptiste Daroussin break; 365*4bf54857SBaptiste Daroussin case LUA_TNUMBER: 366*4bf54857SBaptiste Daroussin num = lua_tonumber (L, idx); 367*4bf54857SBaptiste Daroussin if (num == (int64_t)num) { 368*4bf54857SBaptiste Daroussin obj = ucl_object_fromint (num); 369*4bf54857SBaptiste Daroussin } 370*4bf54857SBaptiste Daroussin else { 371*4bf54857SBaptiste Daroussin obj = ucl_object_fromdouble (num); 372*4bf54857SBaptiste Daroussin } 373*4bf54857SBaptiste Daroussin break; 374*4bf54857SBaptiste Daroussin case LUA_TBOOLEAN: 375*4bf54857SBaptiste Daroussin obj = ucl_object_frombool (lua_toboolean (L, idx)); 376*4bf54857SBaptiste Daroussin break; 377*4bf54857SBaptiste Daroussin case LUA_TUSERDATA: 378*4bf54857SBaptiste Daroussin if (lua_topointer (L, idx) == ucl_null) { 379*4bf54857SBaptiste Daroussin obj = ucl_object_typed_new (UCL_NULL); 380*4bf54857SBaptiste Daroussin } 381*4bf54857SBaptiste Daroussin break; 382*4bf54857SBaptiste Daroussin case LUA_TTABLE: 383*4bf54857SBaptiste Daroussin case LUA_TFUNCTION: 384*4bf54857SBaptiste Daroussin case LUA_TTHREAD: 385*4bf54857SBaptiste Daroussin if (luaL_getmetafield (L, idx, "__gen_ucl")) { 386*4bf54857SBaptiste Daroussin if (lua_isfunction (L, -1)) { 387*4bf54857SBaptiste Daroussin lua_settop (L, 3); /* gen, obj, func */ 388*4bf54857SBaptiste Daroussin lua_insert (L, 1); /* func, gen, obj */ 389*4bf54857SBaptiste Daroussin lua_insert (L, 2); /* func, obj, gen */ 390*4bf54857SBaptiste Daroussin lua_call(L, 2, 1); 391*4bf54857SBaptiste Daroussin obj = ucl_object_lua_fromelt (L, 1); 392*4bf54857SBaptiste Daroussin } 393*4bf54857SBaptiste Daroussin lua_pop (L, 2); 394*4bf54857SBaptiste Daroussin } 395*4bf54857SBaptiste Daroussin else { 396*4bf54857SBaptiste Daroussin if (type == LUA_TTABLE) { 397*4bf54857SBaptiste Daroussin obj = ucl_object_lua_fromtable (L, idx); 398*4bf54857SBaptiste Daroussin } 399*4bf54857SBaptiste Daroussin else if (type == LUA_TFUNCTION) { 400*4bf54857SBaptiste Daroussin fd = malloc (sizeof (*fd)); 401*4bf54857SBaptiste Daroussin if (fd != NULL) { 402*4bf54857SBaptiste Daroussin lua_pushvalue (L, idx); 403*4bf54857SBaptiste Daroussin fd->L = L; 404*4bf54857SBaptiste Daroussin fd->ret = NULL; 405*4bf54857SBaptiste Daroussin fd->idx = luaL_ref (L, LUA_REGISTRYINDEX); 406*4bf54857SBaptiste Daroussin 407*4bf54857SBaptiste Daroussin obj = ucl_object_new_userdata (lua_ucl_userdata_dtor, 408*4bf54857SBaptiste Daroussin lua_ucl_userdata_emitter); 409*4bf54857SBaptiste Daroussin obj->type = UCL_USERDATA; 410*4bf54857SBaptiste Daroussin obj->value.ud = (void *)fd; 411*4bf54857SBaptiste Daroussin } 412*4bf54857SBaptiste Daroussin } 413*4bf54857SBaptiste Daroussin } 414*4bf54857SBaptiste Daroussin break; 415*4bf54857SBaptiste Daroussin } 416*4bf54857SBaptiste Daroussin 417*4bf54857SBaptiste Daroussin return obj; 418*4bf54857SBaptiste Daroussin } 419*4bf54857SBaptiste Daroussin 420*4bf54857SBaptiste Daroussin /** 421*4bf54857SBaptiste Daroussin * @function ucl_object_lua_import(L, idx) 422*4bf54857SBaptiste Daroussin * Extracts ucl object from lua variable at `idx` position, 423*4bf54857SBaptiste Daroussin * @see ucl_object_push_lua for conversion definitions 424*4bf54857SBaptiste Daroussin * @param {lua_state} L lua state machine pointer 425*4bf54857SBaptiste Daroussin * @param {int} idx index where the source variable is placed 426*4bf54857SBaptiste Daroussin * @return {ucl_object_t} new ucl object extracted from lua variable. Reference count of this object is 1, 427*4bf54857SBaptiste Daroussin * this object thus needs to be unref'ed after usage. 428*4bf54857SBaptiste Daroussin */ 429*4bf54857SBaptiste Daroussin ucl_object_t * 430*4bf54857SBaptiste Daroussin ucl_object_lua_import (lua_State *L, int idx) 431*4bf54857SBaptiste Daroussin { 432*4bf54857SBaptiste Daroussin ucl_object_t *obj; 433*4bf54857SBaptiste Daroussin int t; 434*4bf54857SBaptiste Daroussin 435*4bf54857SBaptiste Daroussin t = lua_type (L, idx); 436*4bf54857SBaptiste Daroussin switch (t) { 437*4bf54857SBaptiste Daroussin case LUA_TTABLE: 438*4bf54857SBaptiste Daroussin obj = ucl_object_lua_fromtable (L, idx); 439*4bf54857SBaptiste Daroussin break; 440*4bf54857SBaptiste Daroussin default: 441*4bf54857SBaptiste Daroussin obj = ucl_object_lua_fromelt (L, idx); 442*4bf54857SBaptiste Daroussin break; 443*4bf54857SBaptiste Daroussin } 444*4bf54857SBaptiste Daroussin 445*4bf54857SBaptiste Daroussin return obj; 446*4bf54857SBaptiste Daroussin } 447*4bf54857SBaptiste Daroussin 448*4bf54857SBaptiste Daroussin static int 449*4bf54857SBaptiste Daroussin lua_ucl_parser_init (lua_State *L) 450*4bf54857SBaptiste Daroussin { 451*4bf54857SBaptiste Daroussin struct ucl_parser *parser, **pparser; 452*4bf54857SBaptiste Daroussin int flags = 0; 453*4bf54857SBaptiste Daroussin 454*4bf54857SBaptiste Daroussin if (lua_gettop (L) >= 1) { 455*4bf54857SBaptiste Daroussin flags = lua_tonumber (L, 1); 456*4bf54857SBaptiste Daroussin } 457*4bf54857SBaptiste Daroussin 458*4bf54857SBaptiste Daroussin parser = ucl_parser_new (flags); 459*4bf54857SBaptiste Daroussin if (parser == NULL) { 460*4bf54857SBaptiste Daroussin lua_pushnil (L); 461*4bf54857SBaptiste Daroussin } 462*4bf54857SBaptiste Daroussin 463*4bf54857SBaptiste Daroussin pparser = lua_newuserdata (L, sizeof (parser)); 464*4bf54857SBaptiste Daroussin *pparser = parser; 465*4bf54857SBaptiste Daroussin luaL_getmetatable (L, PARSER_META); 466*4bf54857SBaptiste Daroussin lua_setmetatable (L, -2); 467*4bf54857SBaptiste Daroussin 468*4bf54857SBaptiste Daroussin return 1; 469*4bf54857SBaptiste Daroussin } 470*4bf54857SBaptiste Daroussin 471*4bf54857SBaptiste Daroussin static struct ucl_parser * 472*4bf54857SBaptiste Daroussin lua_ucl_parser_get (lua_State *L, int index) 473*4bf54857SBaptiste Daroussin { 474*4bf54857SBaptiste Daroussin return *((struct ucl_parser **) luaL_checkudata(L, index, PARSER_META)); 475*4bf54857SBaptiste Daroussin } 476*4bf54857SBaptiste Daroussin 477*4bf54857SBaptiste Daroussin /*** 478*4bf54857SBaptiste Daroussin * @method parser:parse_file(name) 479*4bf54857SBaptiste Daroussin * Parse UCL object from file. 480*4bf54857SBaptiste Daroussin * @param {string} name filename to parse 481*4bf54857SBaptiste Daroussin * @return {bool[, string]} if res is `true` then file has been parsed successfully, otherwise an error string is also returned 482*4bf54857SBaptiste Daroussin @example 483*4bf54857SBaptiste Daroussin local parser = ucl.parser() 484*4bf54857SBaptiste Daroussin local res,err = parser:parse_file('/some/file.conf') 485*4bf54857SBaptiste Daroussin 486*4bf54857SBaptiste Daroussin if not res then 487*4bf54857SBaptiste Daroussin print('parser error: ' .. err) 488*4bf54857SBaptiste Daroussin else 489*4bf54857SBaptiste Daroussin -- Do something with object 490*4bf54857SBaptiste Daroussin end 491*4bf54857SBaptiste Daroussin */ 492*4bf54857SBaptiste Daroussin static int 493*4bf54857SBaptiste Daroussin lua_ucl_parser_parse_file (lua_State *L) 494*4bf54857SBaptiste Daroussin { 495*4bf54857SBaptiste Daroussin struct ucl_parser *parser; 496*4bf54857SBaptiste Daroussin const char *file; 497*4bf54857SBaptiste Daroussin int ret = 2; 498*4bf54857SBaptiste Daroussin 499*4bf54857SBaptiste Daroussin parser = lua_ucl_parser_get (L, 1); 500*4bf54857SBaptiste Daroussin file = luaL_checkstring (L, 2); 501*4bf54857SBaptiste Daroussin 502*4bf54857SBaptiste Daroussin if (parser != NULL && file != NULL) { 503*4bf54857SBaptiste Daroussin if (ucl_parser_add_file (parser, file)) { 504*4bf54857SBaptiste Daroussin lua_pushboolean (L, true); 505*4bf54857SBaptiste Daroussin ret = 1; 506*4bf54857SBaptiste Daroussin } 507*4bf54857SBaptiste Daroussin else { 508*4bf54857SBaptiste Daroussin lua_pushboolean (L, false); 509*4bf54857SBaptiste Daroussin lua_pushstring (L, ucl_parser_get_error (parser)); 510*4bf54857SBaptiste Daroussin } 511*4bf54857SBaptiste Daroussin } 512*4bf54857SBaptiste Daroussin else { 513*4bf54857SBaptiste Daroussin lua_pushboolean (L, false); 514*4bf54857SBaptiste Daroussin lua_pushstring (L, "invalid arguments"); 515*4bf54857SBaptiste Daroussin } 516*4bf54857SBaptiste Daroussin 517*4bf54857SBaptiste Daroussin return ret; 518*4bf54857SBaptiste Daroussin } 519*4bf54857SBaptiste Daroussin 520*4bf54857SBaptiste Daroussin /*** 521*4bf54857SBaptiste Daroussin * @method parser:parse_string(input) 522*4bf54857SBaptiste Daroussin * Parse UCL object from file. 523*4bf54857SBaptiste Daroussin * @param {string} input string to parse 524*4bf54857SBaptiste Daroussin * @return {bool[, string]} if res is `true` then file has been parsed successfully, otherwise an error string is also returned 525*4bf54857SBaptiste Daroussin */ 526*4bf54857SBaptiste Daroussin static int 527*4bf54857SBaptiste Daroussin lua_ucl_parser_parse_string (lua_State *L) 528*4bf54857SBaptiste Daroussin { 529*4bf54857SBaptiste Daroussin struct ucl_parser *parser; 530*4bf54857SBaptiste Daroussin const char *string; 531*4bf54857SBaptiste Daroussin size_t llen; 532*4bf54857SBaptiste Daroussin int ret = 2; 533*4bf54857SBaptiste Daroussin 534*4bf54857SBaptiste Daroussin parser = lua_ucl_parser_get (L, 1); 535*4bf54857SBaptiste Daroussin string = luaL_checklstring (L, 2, &llen); 536*4bf54857SBaptiste Daroussin 537*4bf54857SBaptiste Daroussin if (parser != NULL && string != NULL) { 538*4bf54857SBaptiste Daroussin if (ucl_parser_add_chunk (parser, (const unsigned char *)string, llen)) { 539*4bf54857SBaptiste Daroussin lua_pushboolean (L, true); 540*4bf54857SBaptiste Daroussin ret = 1; 541*4bf54857SBaptiste Daroussin } 542*4bf54857SBaptiste Daroussin else { 543*4bf54857SBaptiste Daroussin lua_pushboolean (L, false); 544*4bf54857SBaptiste Daroussin lua_pushstring (L, ucl_parser_get_error (parser)); 545*4bf54857SBaptiste Daroussin } 546*4bf54857SBaptiste Daroussin } 547*4bf54857SBaptiste Daroussin else { 548*4bf54857SBaptiste Daroussin lua_pushboolean (L, false); 549*4bf54857SBaptiste Daroussin lua_pushstring (L, "invalid arguments"); 550*4bf54857SBaptiste Daroussin } 551*4bf54857SBaptiste Daroussin 552*4bf54857SBaptiste Daroussin return ret; 553*4bf54857SBaptiste Daroussin } 554*4bf54857SBaptiste Daroussin 555*4bf54857SBaptiste Daroussin /*** 556*4bf54857SBaptiste Daroussin * @method parser:get_object() 557*4bf54857SBaptiste Daroussin * Get top object from parser and export it to lua representation. 558*4bf54857SBaptiste Daroussin * @return {variant or nil} ucl object as lua native variable 559*4bf54857SBaptiste Daroussin */ 560*4bf54857SBaptiste Daroussin static int 561*4bf54857SBaptiste Daroussin lua_ucl_parser_get_object (lua_State *L) 562*4bf54857SBaptiste Daroussin { 563*4bf54857SBaptiste Daroussin struct ucl_parser *parser; 564*4bf54857SBaptiste Daroussin ucl_object_t *obj; 565*4bf54857SBaptiste Daroussin int ret = 1; 566*4bf54857SBaptiste Daroussin 567*4bf54857SBaptiste Daroussin parser = lua_ucl_parser_get (L, 1); 568*4bf54857SBaptiste Daroussin obj = ucl_parser_get_object (parser); 569*4bf54857SBaptiste Daroussin 570*4bf54857SBaptiste Daroussin if (obj != NULL) { 571*4bf54857SBaptiste Daroussin ret = ucl_object_push_lua (L, obj, false); 572*4bf54857SBaptiste Daroussin /* no need to keep reference */ 573*4bf54857SBaptiste Daroussin ucl_object_unref (obj); 574*4bf54857SBaptiste Daroussin } 575*4bf54857SBaptiste Daroussin else { 576*4bf54857SBaptiste Daroussin lua_pushnil (L); 577*4bf54857SBaptiste Daroussin } 578*4bf54857SBaptiste Daroussin 579*4bf54857SBaptiste Daroussin return ret; 580*4bf54857SBaptiste Daroussin } 581*4bf54857SBaptiste Daroussin 582*4bf54857SBaptiste Daroussin static int 583*4bf54857SBaptiste Daroussin lua_ucl_parser_gc (lua_State *L) 584*4bf54857SBaptiste Daroussin { 585*4bf54857SBaptiste Daroussin struct ucl_parser *parser; 586*4bf54857SBaptiste Daroussin 587*4bf54857SBaptiste Daroussin parser = lua_ucl_parser_get (L, 1); 588*4bf54857SBaptiste Daroussin ucl_parser_free (parser); 589*4bf54857SBaptiste Daroussin 590*4bf54857SBaptiste Daroussin return 0; 591*4bf54857SBaptiste Daroussin } 592*4bf54857SBaptiste Daroussin 593*4bf54857SBaptiste Daroussin static void 594*4bf54857SBaptiste Daroussin lua_ucl_parser_mt (lua_State *L) 595*4bf54857SBaptiste Daroussin { 596*4bf54857SBaptiste Daroussin luaL_newmetatable (L, PARSER_META); 597*4bf54857SBaptiste Daroussin 598*4bf54857SBaptiste Daroussin lua_pushvalue(L, -1); 599*4bf54857SBaptiste Daroussin lua_setfield(L, -2, "__index"); 600*4bf54857SBaptiste Daroussin 601*4bf54857SBaptiste Daroussin lua_pushcfunction (L, lua_ucl_parser_gc); 602*4bf54857SBaptiste Daroussin lua_setfield (L, -2, "__gc"); 603*4bf54857SBaptiste Daroussin 604*4bf54857SBaptiste Daroussin lua_pushcfunction (L, lua_ucl_parser_parse_file); 605*4bf54857SBaptiste Daroussin lua_setfield (L, -2, "parse_file"); 606*4bf54857SBaptiste Daroussin 607*4bf54857SBaptiste Daroussin lua_pushcfunction (L, lua_ucl_parser_parse_string); 608*4bf54857SBaptiste Daroussin lua_setfield (L, -2, "parse_string"); 609*4bf54857SBaptiste Daroussin 610*4bf54857SBaptiste Daroussin lua_pushcfunction (L, lua_ucl_parser_get_object); 611*4bf54857SBaptiste Daroussin lua_setfield (L, -2, "get_object"); 612*4bf54857SBaptiste Daroussin 613*4bf54857SBaptiste Daroussin lua_pop (L, 1); 614*4bf54857SBaptiste Daroussin } 615*4bf54857SBaptiste Daroussin 616*4bf54857SBaptiste Daroussin static int 617*4bf54857SBaptiste Daroussin lua_ucl_to_string (lua_State *L, const ucl_object_t *obj, enum ucl_emitter type) 618*4bf54857SBaptiste Daroussin { 619*4bf54857SBaptiste Daroussin unsigned char *result; 620*4bf54857SBaptiste Daroussin 621*4bf54857SBaptiste Daroussin result = ucl_object_emit (obj, type); 622*4bf54857SBaptiste Daroussin 623*4bf54857SBaptiste Daroussin if (result != NULL) { 624*4bf54857SBaptiste Daroussin lua_pushstring (L, (const char *)result); 625*4bf54857SBaptiste Daroussin free (result); 626*4bf54857SBaptiste Daroussin } 627*4bf54857SBaptiste Daroussin else { 628*4bf54857SBaptiste Daroussin lua_pushnil (L); 629*4bf54857SBaptiste Daroussin } 630*4bf54857SBaptiste Daroussin 631*4bf54857SBaptiste Daroussin return 1; 632*4bf54857SBaptiste Daroussin } 633*4bf54857SBaptiste Daroussin 634*4bf54857SBaptiste Daroussin static int 635*4bf54857SBaptiste Daroussin lua_ucl_to_json (lua_State *L) 636*4bf54857SBaptiste Daroussin { 637*4bf54857SBaptiste Daroussin ucl_object_t *obj; 638*4bf54857SBaptiste Daroussin int format = UCL_EMIT_JSON; 639*4bf54857SBaptiste Daroussin 640*4bf54857SBaptiste Daroussin if (lua_gettop (L) > 1) { 641*4bf54857SBaptiste Daroussin if (lua_toboolean (L, 2)) { 642*4bf54857SBaptiste Daroussin format = UCL_EMIT_JSON_COMPACT; 643*4bf54857SBaptiste Daroussin } 644*4bf54857SBaptiste Daroussin } 645*4bf54857SBaptiste Daroussin 646*4bf54857SBaptiste Daroussin obj = ucl_object_lua_import (L, 1); 647*4bf54857SBaptiste Daroussin if (obj != NULL) { 648*4bf54857SBaptiste Daroussin lua_ucl_to_string (L, obj, format); 649*4bf54857SBaptiste Daroussin ucl_object_unref (obj); 650*4bf54857SBaptiste Daroussin } 651*4bf54857SBaptiste Daroussin else { 652*4bf54857SBaptiste Daroussin lua_pushnil (L); 653*4bf54857SBaptiste Daroussin } 654*4bf54857SBaptiste Daroussin 655*4bf54857SBaptiste Daroussin return 1; 656*4bf54857SBaptiste Daroussin } 657*4bf54857SBaptiste Daroussin 658*4bf54857SBaptiste Daroussin static int 659*4bf54857SBaptiste Daroussin lua_ucl_to_config (lua_State *L) 660*4bf54857SBaptiste Daroussin { 661*4bf54857SBaptiste Daroussin ucl_object_t *obj; 662*4bf54857SBaptiste Daroussin 663*4bf54857SBaptiste Daroussin obj = ucl_object_lua_import (L, 1); 664*4bf54857SBaptiste Daroussin if (obj != NULL) { 665*4bf54857SBaptiste Daroussin lua_ucl_to_string (L, obj, UCL_EMIT_CONFIG); 666*4bf54857SBaptiste Daroussin ucl_object_unref (obj); 667*4bf54857SBaptiste Daroussin } 668*4bf54857SBaptiste Daroussin else { 669*4bf54857SBaptiste Daroussin lua_pushnil (L); 670*4bf54857SBaptiste Daroussin } 671*4bf54857SBaptiste Daroussin 672*4bf54857SBaptiste Daroussin return 1; 673*4bf54857SBaptiste Daroussin } 674*4bf54857SBaptiste Daroussin 675*4bf54857SBaptiste Daroussin /*** 676*4bf54857SBaptiste Daroussin * @function ucl.to_format(var, format) 677*4bf54857SBaptiste Daroussin * Converts lua variable `var` to the specified `format`. Formats supported are: 678*4bf54857SBaptiste Daroussin * 679*4bf54857SBaptiste Daroussin * - `json` - fine printed json 680*4bf54857SBaptiste Daroussin * - `json-compact` - compacted json 681*4bf54857SBaptiste Daroussin * - `config` - fine printed configuration 682*4bf54857SBaptiste Daroussin * - `ucl` - same as `config` 683*4bf54857SBaptiste Daroussin * - `yaml` - embedded yaml 684*4bf54857SBaptiste Daroussin * 685*4bf54857SBaptiste Daroussin * If `var` contains function, they are called during output formatting and if 686*4bf54857SBaptiste Daroussin * they return string value, then this value is used for ouptut. 687*4bf54857SBaptiste Daroussin * @param {variant} var any sort of lua variable (if userdata then metafield `__to_ucl` is searched for output) 688*4bf54857SBaptiste Daroussin * @param {string} format any available format 689*4bf54857SBaptiste Daroussin * @return {string} string representation of `var` in the specific `format`. 690*4bf54857SBaptiste Daroussin * @example 691*4bf54857SBaptiste Daroussin local table = { 692*4bf54857SBaptiste Daroussin str = 'value', 693*4bf54857SBaptiste Daroussin num = 100500, 694*4bf54857SBaptiste Daroussin null = ucl.null, 695*4bf54857SBaptiste Daroussin func = function () 696*4bf54857SBaptiste Daroussin return 'huh' 697*4bf54857SBaptiste Daroussin end 698*4bf54857SBaptiste Daroussin } 699*4bf54857SBaptiste Daroussin 700*4bf54857SBaptiste Daroussin print(ucl.to_format(table, 'ucl')) 701*4bf54857SBaptiste Daroussin -- Output: 702*4bf54857SBaptiste Daroussin --[[ 703*4bf54857SBaptiste Daroussin num = 100500; 704*4bf54857SBaptiste Daroussin str = "value"; 705*4bf54857SBaptiste Daroussin null = null; 706*4bf54857SBaptiste Daroussin func = "huh"; 707*4bf54857SBaptiste Daroussin --]] 708*4bf54857SBaptiste Daroussin */ 709*4bf54857SBaptiste Daroussin static int 710*4bf54857SBaptiste Daroussin lua_ucl_to_format (lua_State *L) 711*4bf54857SBaptiste Daroussin { 712*4bf54857SBaptiste Daroussin ucl_object_t *obj; 713*4bf54857SBaptiste Daroussin int format = UCL_EMIT_JSON; 714*4bf54857SBaptiste Daroussin 715*4bf54857SBaptiste Daroussin if (lua_gettop (L) > 1) { 716*4bf54857SBaptiste Daroussin if (lua_type (L, 2) == LUA_TNUMBER) { 717*4bf54857SBaptiste Daroussin format = lua_tonumber (L, 2); 718*4bf54857SBaptiste Daroussin if (format < 0 || format >= UCL_EMIT_YAML) { 719*4bf54857SBaptiste Daroussin lua_pushnil (L); 720*4bf54857SBaptiste Daroussin return 1; 721*4bf54857SBaptiste Daroussin } 722*4bf54857SBaptiste Daroussin } 723*4bf54857SBaptiste Daroussin else if (lua_type (L, 2) == LUA_TSTRING) { 724*4bf54857SBaptiste Daroussin const char *strtype = lua_tostring (L, 2); 725*4bf54857SBaptiste Daroussin 726*4bf54857SBaptiste Daroussin if (strcasecmp (strtype, "json") == 0) { 727*4bf54857SBaptiste Daroussin format = UCL_EMIT_JSON; 728*4bf54857SBaptiste Daroussin } 729*4bf54857SBaptiste Daroussin else if (strcasecmp (strtype, "json-compact") == 0) { 730*4bf54857SBaptiste Daroussin format = UCL_EMIT_JSON_COMPACT; 731*4bf54857SBaptiste Daroussin } 732*4bf54857SBaptiste Daroussin else if (strcasecmp (strtype, "yaml") == 0) { 733*4bf54857SBaptiste Daroussin format = UCL_EMIT_YAML; 734*4bf54857SBaptiste Daroussin } 735*4bf54857SBaptiste Daroussin else if (strcasecmp (strtype, "config") == 0 || 736*4bf54857SBaptiste Daroussin strcasecmp (strtype, "ucl") == 0) { 737*4bf54857SBaptiste Daroussin format = UCL_EMIT_CONFIG; 738*4bf54857SBaptiste Daroussin } 739*4bf54857SBaptiste Daroussin } 740*4bf54857SBaptiste Daroussin } 741*4bf54857SBaptiste Daroussin 742*4bf54857SBaptiste Daroussin obj = ucl_object_lua_import (L, 1); 743*4bf54857SBaptiste Daroussin if (obj != NULL) { 744*4bf54857SBaptiste Daroussin lua_ucl_to_string (L, obj, format); 745*4bf54857SBaptiste Daroussin ucl_object_unref (obj); 746*4bf54857SBaptiste Daroussin } 747*4bf54857SBaptiste Daroussin else { 748*4bf54857SBaptiste Daroussin lua_pushnil (L); 749*4bf54857SBaptiste Daroussin } 750*4bf54857SBaptiste Daroussin 751*4bf54857SBaptiste Daroussin return 1; 752*4bf54857SBaptiste Daroussin } 753*4bf54857SBaptiste Daroussin 754*4bf54857SBaptiste Daroussin static int 755*4bf54857SBaptiste Daroussin lua_ucl_null_tostring (lua_State* L) 756*4bf54857SBaptiste Daroussin { 757*4bf54857SBaptiste Daroussin lua_pushstring (L, "null"); 758*4bf54857SBaptiste Daroussin return 1; 759*4bf54857SBaptiste Daroussin } 760*4bf54857SBaptiste Daroussin 761*4bf54857SBaptiste Daroussin static void 762*4bf54857SBaptiste Daroussin lua_ucl_null_mt (lua_State *L) 763*4bf54857SBaptiste Daroussin { 764*4bf54857SBaptiste Daroussin luaL_newmetatable (L, NULL_META); 765*4bf54857SBaptiste Daroussin 766*4bf54857SBaptiste Daroussin lua_pushcfunction (L, lua_ucl_null_tostring); 767*4bf54857SBaptiste Daroussin lua_setfield (L, -2, "__tostring"); 768*4bf54857SBaptiste Daroussin 769*4bf54857SBaptiste Daroussin lua_pop (L, 1); 770*4bf54857SBaptiste Daroussin } 771*4bf54857SBaptiste Daroussin 772*4bf54857SBaptiste Daroussin int 773*4bf54857SBaptiste Daroussin luaopen_ucl (lua_State *L) 774*4bf54857SBaptiste Daroussin { 775*4bf54857SBaptiste Daroussin lua_ucl_parser_mt (L); 776*4bf54857SBaptiste Daroussin lua_ucl_null_mt (L); 777*4bf54857SBaptiste Daroussin 778*4bf54857SBaptiste Daroussin /* Create the refs weak table: */ 779*4bf54857SBaptiste Daroussin lua_createtable (L, 0, 2); 780*4bf54857SBaptiste Daroussin lua_pushliteral (L, "v"); /* tbl, "v" */ 781*4bf54857SBaptiste Daroussin lua_setfield (L, -2, "__mode"); 782*4bf54857SBaptiste Daroussin lua_pushvalue (L, -1); /* tbl, tbl */ 783*4bf54857SBaptiste Daroussin lua_setmetatable (L, -2); /* tbl */ 784*4bf54857SBaptiste Daroussin lua_setfield (L, LUA_REGISTRYINDEX, "ucl.refs"); 785*4bf54857SBaptiste Daroussin 786*4bf54857SBaptiste Daroussin lua_newtable (L); 787*4bf54857SBaptiste Daroussin 788*4bf54857SBaptiste Daroussin lua_pushcfunction (L, lua_ucl_parser_init); 789*4bf54857SBaptiste Daroussin lua_setfield (L, -2, "parser"); 790*4bf54857SBaptiste Daroussin 791*4bf54857SBaptiste Daroussin lua_pushcfunction (L, lua_ucl_to_json); 792*4bf54857SBaptiste Daroussin lua_setfield (L, -2, "to_json"); 793*4bf54857SBaptiste Daroussin 794*4bf54857SBaptiste Daroussin lua_pushcfunction (L, lua_ucl_to_config); 795*4bf54857SBaptiste Daroussin lua_setfield (L, -2, "to_config"); 796*4bf54857SBaptiste Daroussin 797*4bf54857SBaptiste Daroussin lua_pushcfunction (L, lua_ucl_to_format); 798*4bf54857SBaptiste Daroussin lua_setfield (L, -2, "to_format"); 799*4bf54857SBaptiste Daroussin 800*4bf54857SBaptiste Daroussin ucl_null = lua_newuserdata (L, 0); 801*4bf54857SBaptiste Daroussin luaL_getmetatable (L, NULL_META); 802*4bf54857SBaptiste Daroussin lua_setmetatable (L, -2); 803*4bf54857SBaptiste Daroussin 804*4bf54857SBaptiste Daroussin lua_pushvalue (L, -1); 805*4bf54857SBaptiste Daroussin lua_setfield (L, LUA_REGISTRYINDEX, "ucl.null"); 806*4bf54857SBaptiste Daroussin 807*4bf54857SBaptiste Daroussin lua_setfield (L, -2, "null"); 808*4bf54857SBaptiste Daroussin 809*4bf54857SBaptiste Daroussin return 1; 810*4bf54857SBaptiste Daroussin } 811*4bf54857SBaptiste Daroussin 812*4bf54857SBaptiste Daroussin struct ucl_lua_funcdata* 813*4bf54857SBaptiste Daroussin ucl_object_toclosure (const ucl_object_t *obj) 814*4bf54857SBaptiste Daroussin { 815*4bf54857SBaptiste Daroussin if (obj == NULL || obj->type != UCL_USERDATA) { 816*4bf54857SBaptiste Daroussin return NULL; 817*4bf54857SBaptiste Daroussin } 818*4bf54857SBaptiste Daroussin 819*4bf54857SBaptiste Daroussin return (struct ucl_lua_funcdata*)obj->value.ud; 820*4bf54857SBaptiste Daroussin } 821