+++ /dev/null
-/* Copyright (c) 2013, Vsevolod Stakhov
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "lua_common.h"
-
-/**
- * @file lua rcl bindings
- */
-
-static gint lua_rcl_obj_push_array (lua_State *L, const ucl_object_t *obj);
-static gint lua_rcl_obj_push_simple (lua_State *L, const ucl_object_t *obj, gboolean allow_array);
-static ucl_object_t* lua_rcl_table_get (lua_State *L, gint idx);
-static ucl_object_t* lua_rcl_elt_get (lua_State *L, gint idx);
-
-/**
- * Push a single element of an object to lua
- * @param L
- * @param key
- * @param obj
- */
-static void
-lua_rcl_obj_push_elt (lua_State *L, const char *key, const ucl_object_t *obj)
-{
- lua_pushstring (L, key);
- lua_rcl_obj_push (L, obj, TRUE);
- lua_settable (L, -3);
-}
-
-/**
- * Push a single object to lua
- * @param L
- * @param obj
- * @return
- */
-static gint
-lua_rcl_obj_push_obj (lua_State *L, const ucl_object_t *obj, gboolean allow_array)
-{
- const ucl_object_t *cur;
- ucl_object_iter_t it = NULL;
-
- if (allow_array && obj->next != NULL) {
- /* Actually we need to push this as an array */
- return lua_rcl_obj_push_array (L, obj);
- }
-
- lua_newtable (L);
- while ((cur = ucl_iterate_object (obj, &it, true)) != NULL) {
- lua_rcl_obj_push_elt (L, ucl_object_key (cur), cur);
- }
-
- return 1;
-}
-
-/**
- * Push an array to lua as table indexed by integers
- * @param L
- * @param obj
- * @return
- */
-static gint
-lua_rcl_obj_push_array (lua_State *L, const ucl_object_t *obj)
-{
- const ucl_object_t *cur;
- gint i = 1;
-
- lua_newtable (L);
-
- LL_FOREACH (obj, cur) {
- lua_rcl_obj_push (L, cur, FALSE);
- lua_rawseti (L, -2, i);
- i ++;
- }
-
- return 1;
-}
-
-/**
- * Push a simple object to lua depending on its actual type
- */
-static gint
-lua_rcl_obj_push_simple (lua_State *L, const ucl_object_t *obj, gboolean allow_array)
-{
- if (allow_array && obj->next != NULL) {
- /* Actually we need to push this as an array */
- return lua_rcl_obj_push_array (L, obj);
- }
-
- switch (obj->type) {
- case UCL_BOOLEAN:
- lua_pushboolean (L, ucl_obj_toboolean (obj));
- break;
- case UCL_STRING:
- lua_pushstring (L, ucl_obj_tostring (obj));
- break;
- case UCL_INT:
-#if LUA_VERSION_NUM >= 501
- lua_pushinteger (L, ucl_obj_toint (obj));
-#else
- lua_pushnumber (L, ucl_obj_toint (obj));
-#endif
- break;
- case UCL_FLOAT:
- case UCL_TIME:
- lua_pushnumber (L, ucl_obj_todouble (obj));
- break;
- default:
- lua_pushnil (L);
- break;
- }
-
- return 1;
-}
-
-/**
- * Push an object to lua
- * @param L lua state
- * @param obj object to push
- */
-gint
-lua_rcl_obj_push (lua_State *L, const ucl_object_t *obj, gboolean allow_array)
-{
- switch (obj->type) {
- case UCL_OBJECT:
- return lua_rcl_obj_push_obj (L, obj, allow_array);
- case UCL_ARRAY:
- return lua_rcl_obj_push_array (L, obj->value.av);
- default:
- return lua_rcl_obj_push_simple (L, obj, allow_array);
- }
-}
-
-/**
- * Parse lua table into object top
- * @param L
- * @param top
- * @param idx
- */
-static ucl_object_t *
-lua_rcl_table_get (lua_State *L, gint idx)
-{
- ucl_object_t *obj, *top = NULL;
- gsize keylen;
- const gchar *k;
-
- /* Table iterate */
- lua_pushvalue (L, idx);
- lua_pushnil (L);
- top = ucl_object_typed_new (UCL_OBJECT);
- while (lua_next (L, -2) != 0) {
- /* copy key to avoid modifications */
- lua_pushvalue (L, -2);
- k = lua_tolstring (L, -1, &keylen);
- obj = lua_rcl_elt_get (L, -2);
- ucl_object_insert_key (top, obj, k, keylen, true);
- lua_pop (L, 2);
- }
- lua_pop (L, 1);
-
- return top;
-}
-
-/**
- * Get a single element from lua to object obj
- * @param L
- * @param obj
- * @param idx
- */
-static ucl_object_t *
-lua_rcl_elt_get (lua_State *L, gint idx)
-{
- gint type;
- ucl_object_t *obj;
-
- type = lua_type (L, idx);
-
- switch (type) {
- case LUA_TFUNCTION:
- lua_pushvalue (L, idx);
- obj = ucl_object_new ();
- obj->type = UCL_USERDATA;
- obj->value.ud = GINT_TO_POINTER (luaL_ref (L, LUA_REGISTRYINDEX));
- break;
- case LUA_TSTRING:
- obj = ucl_object_fromstring_common (lua_tostring (L, idx), 0, 0);
- break;
- case LUA_TNUMBER:
- obj = ucl_object_fromdouble (lua_tonumber (L, idx));
- break;
- case LUA_TBOOLEAN:
- obj = ucl_object_frombool (lua_toboolean (L, idx));
- break;
- case LUA_TTABLE:
- obj = lua_rcl_table_get (L, idx);
- break;
- }
-
- return obj;
-}
-
-/**
- * Extract rcl object from lua object
- * @param L
- * @return
- */
-ucl_object_t *
-lua_rcl_obj_get (lua_State *L, gint idx)
-{
- ucl_object_t *obj;
- gint t;
-
- t = lua_type (L, idx);
- switch (t) {
- case LUA_TTABLE:
- /* We assume all tables as objects, not arrays */
- obj = lua_rcl_table_get (L, idx);
- break;
- default:
- obj = lua_rcl_elt_get (L, idx);
- break;
- }
-
- return obj;
-}