lua_ucl.c (b626f5a73a48f44a31a200291b141e1da408a2ff) lua_ucl.c (d9f0ce31900a48d1a2bfc1c8c86f79d1e831451a)
1/* Copyright (c) 2014, Vsevolod Stakhov
2 * All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above copyright

--- 15 unchanged lines hidden (view full) ---

24/**
25 * @file lua ucl bindings
26 */
27
28#include "ucl.h"
29#include "ucl_internal.h"
30#include "lua_ucl.h"
31#include <strings.h>
1/* Copyright (c) 2014, Vsevolod Stakhov
2 * All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above copyright

--- 15 unchanged lines hidden (view full) ---

24/**
25 * @file lua ucl bindings
26 */
27
28#include "ucl.h"
29#include "ucl_internal.h"
30#include "lua_ucl.h"
31#include <strings.h>
32#include <zconf.h>
32
33/***
34 * @module ucl
35 * This lua module allows to parse objects from strings and to store data into
36 * ucl objects. It uses `libucl` C library to parse and manipulate with ucl objects.
37 * @example
38local ucl = require("ucl")
39

--- 104 unchanged lines hidden (view full) ---

144 int nelt = 0;
145
146 if (allow_array && obj->next != NULL) {
147 /* Actually we need to push this as an array */
148 return ucl_object_lua_push_array (L, obj);
149 }
150
151 /* Optimize allocation by preallocation of table */
33
34/***
35 * @module ucl
36 * This lua module allows to parse objects from strings and to store data into
37 * ucl objects. It uses `libucl` C library to parse and manipulate with ucl objects.
38 * @example
39local ucl = require("ucl")
40

--- 104 unchanged lines hidden (view full) ---

145 int nelt = 0;
146
147 if (allow_array && obj->next != NULL) {
148 /* Actually we need to push this as an array */
149 return ucl_object_lua_push_array (L, obj);
150 }
151
152 /* Optimize allocation by preallocation of table */
152 while (ucl_iterate_object (obj, &it, true) != NULL) {
153 while (ucl_object_iterate (obj, &it, true) != NULL) {
153 nelt ++;
154 }
155
156 lua_createtable (L, 0, nelt);
157 it = NULL;
158
154 nelt ++;
155 }
156
157 lua_createtable (L, 0, nelt);
158 it = NULL;
159
159 while ((cur = ucl_iterate_object (obj, &it, true)) != NULL) {
160 while ((cur = ucl_object_iterate (obj, &it, true)) != NULL) {
160 ucl_object_lua_push_element (L, ucl_object_key (cur), cur);
161 }
162
163 return 1;
164}
165
166/**
167 * Push an array to lua as table indexed by integers

--- 248 unchanged lines hidden (view full) ---

416 fd = malloc (sizeof (*fd));
417 if (fd != NULL) {
418 lua_pushvalue (L, idx);
419 fd->L = L;
420 fd->ret = NULL;
421 fd->idx = luaL_ref (L, LUA_REGISTRYINDEX);
422
423 obj = ucl_object_new_userdata (lua_ucl_userdata_dtor,
161 ucl_object_lua_push_element (L, ucl_object_key (cur), cur);
162 }
163
164 return 1;
165}
166
167/**
168 * Push an array to lua as table indexed by integers

--- 248 unchanged lines hidden (view full) ---

417 fd = malloc (sizeof (*fd));
418 if (fd != NULL) {
419 lua_pushvalue (L, idx);
420 fd->L = L;
421 fd->ret = NULL;
422 fd->idx = luaL_ref (L, LUA_REGISTRYINDEX);
423
424 obj = ucl_object_new_userdata (lua_ucl_userdata_dtor,
424 lua_ucl_userdata_emitter);
425 obj->type = UCL_USERDATA;
426 obj->value.ud = (void *)fd;
425 lua_ucl_userdata_emitter, (void *)fd);
427 }
428 }
429 }
430 break;
431 }
432
433 return obj;
434}

--- 74 unchanged lines hidden (view full) ---

509}
510
511static ucl_object_t *
512lua_ucl_object_get (lua_State *L, int index)
513{
514 return *((ucl_object_t **) luaL_checkudata(L, index, OBJECT_META));
515}
516
426 }
427 }
428 }
429 break;
430 }
431
432 return obj;
433}

--- 74 unchanged lines hidden (view full) ---

508}
509
510static ucl_object_t *
511lua_ucl_object_get (lua_State *L, int index)
512{
513 return *((ucl_object_t **) luaL_checkudata(L, index, OBJECT_META));
514}
515
516static void
517lua_ucl_push_opaque (lua_State *L, ucl_object_t *obj)
518{
519 ucl_object_t **pobj;
520
521 pobj = lua_newuserdata (L, sizeof (*pobj));
522 *pobj = obj;
523 luaL_getmetatable (L, OBJECT_META);
524 lua_setmetatable (L, -2);
525}
526
517/***
518 * @method parser:parse_file(name)
519 * Parse UCL object from file.
520 * @param {string} name filename to parse
521 * @return {bool[, string]} if res is `true` then file has been parsed successfully, otherwise an error string is also returned
522@example
523local parser = ucl.parser()
524local res,err = parser:parse_file('/some/file.conf')

--- 99 unchanged lines hidden (view full) ---

624 * Get top object from parser and export it to userdata object without
625 * unwrapping to lua.
626 * @return {ucl.object or nil} ucl object wrapped variable
627 */
628static int
629lua_ucl_parser_get_object_wrapped (lua_State *L)
630{
631 struct ucl_parser *parser;
527/***
528 * @method parser:parse_file(name)
529 * Parse UCL object from file.
530 * @param {string} name filename to parse
531 * @return {bool[, string]} if res is `true` then file has been parsed successfully, otherwise an error string is also returned
532@example
533local parser = ucl.parser()
534local res,err = parser:parse_file('/some/file.conf')

--- 99 unchanged lines hidden (view full) ---

634 * Get top object from parser and export it to userdata object without
635 * unwrapping to lua.
636 * @return {ucl.object or nil} ucl object wrapped variable
637 */
638static int
639lua_ucl_parser_get_object_wrapped (lua_State *L)
640{
641 struct ucl_parser *parser;
632 ucl_object_t *obj, **pobj;
642 ucl_object_t *obj;
633 int ret = 1;
634
635 parser = lua_ucl_parser_get (L, 1);
636 obj = ucl_parser_get_object (parser);
637
638 if (obj != NULL) {
643 int ret = 1;
644
645 parser = lua_ucl_parser_get (L, 1);
646 obj = ucl_parser_get_object (parser);
647
648 if (obj != NULL) {
639 pobj = lua_newuserdata (L, sizeof (*pobj));
640 *pobj = obj;
641 luaL_getmetatable (L, OBJECT_META);
642 lua_setmetatable (L, -2);
649 lua_ucl_push_opaque (L, obj);
643 }
644 else {
645 lua_pushnil (L);
646 }
647
648 return ret;
649}
650

--- 150 unchanged lines hidden (view full) ---

801 else {
802 lua_pushnil (L);
803 }
804
805 return 1;
806}
807
808/***
650 }
651 else {
652 lua_pushnil (L);
653 }
654
655 return ret;
656}
657

--- 150 unchanged lines hidden (view full) ---

808 else {
809 lua_pushnil (L);
810 }
811
812 return 1;
813}
814
815/***
809 * @method object:validate(schema, path)
816 * @method object:validate(schema[, path[, ext_refs]])
810 * Validates the given ucl object using schema object represented as another
811 * opaque ucl object. You can also specify path in the form `#/path/def` to
812 * specify the specific schema element to perform validation.
813 *
814 * @param {ucl.object} schema schema object
815 * @param {string} path optional path for validation procedure
817 * Validates the given ucl object using schema object represented as another
818 * opaque ucl object. You can also specify path in the form `#/path/def` to
819 * specify the specific schema element to perform validation.
820 *
821 * @param {ucl.object} schema schema object
822 * @param {string} path optional path for validation procedure
816 * @return {result,err} two values: boolean result and the corresponding error
823 * @return {result,err} two values: boolean result and the corresponding
824 * error, if `ext_refs` are also specified, then they are returned as opaque
825 * ucl object as {result,err,ext_refs}
817 */
818static int
819lua_ucl_object_validate (lua_State *L)
820{
826 */
827static int
828lua_ucl_object_validate (lua_State *L)
829{
821 ucl_object_t *obj, *schema;
830 ucl_object_t *obj, *schema, *ext_refs = NULL;
822 const ucl_object_t *schema_elt;
823 bool res = false;
824 struct ucl_schema_error err;
825 const char *path = NULL;
826
827 obj = lua_ucl_object_get (L, 1);
828 schema = lua_ucl_object_get (L, 2);
829
830 if (schema && obj && ucl_object_type (schema) == UCL_OBJECT) {
831 const ucl_object_t *schema_elt;
832 bool res = false;
833 struct ucl_schema_error err;
834 const char *path = NULL;
835
836 obj = lua_ucl_object_get (L, 1);
837 schema = lua_ucl_object_get (L, 2);
838
839 if (schema && obj && ucl_object_type (schema) == UCL_OBJECT) {
831 if (lua_gettop (L) > 2 && lua_type (L, 3) == LUA_TSTRING) {
832 path = lua_tostring (L, 3);
833 if (path[0] == '#') {
834 path ++;
840 if (lua_gettop (L) > 2) {
841 if (lua_type (L, 3) == LUA_TSTRING) {
842 path = lua_tostring (L, 3);
843 if (path[0] == '#') {
844 path++;
845 }
835 }
846 }
847 else if (lua_type (L, 3) == LUA_TUSERDATA || lua_type (L, 3) ==
848 LUA_TTABLE) {
849 /* External refs */
850 ext_refs = lua_ucl_object_get (L, 3);
851 }
852
853 if (lua_gettop (L) > 3) {
854 if (lua_type (L, 4) == LUA_TUSERDATA || lua_type (L, 4) ==
855 LUA_TTABLE) {
856 /* External refs */
857 ext_refs = lua_ucl_object_get (L, 4);
858 }
859 }
836 }
837
838 if (path) {
860 }
861
862 if (path) {
839 schema_elt = ucl_lookup_path_char (schema, path, '/');
863 schema_elt = ucl_object_lookup_path_char (schema, path, '/');
840 }
841 else {
842 /* Use the top object */
843 schema_elt = schema;
844 }
845
846 if (schema_elt) {
864 }
865 else {
866 /* Use the top object */
867 schema_elt = schema;
868 }
869
870 if (schema_elt) {
847 res = ucl_object_validate (schema_elt, obj, &err);
871 res = ucl_object_validate_root_ext (schema_elt, obj, schema,
872 ext_refs, &err);
848
849 if (res) {
850 lua_pushboolean (L, res);
851 lua_pushnil (L);
873
874 if (res) {
875 lua_pushboolean (L, res);
876 lua_pushnil (L);
877
878 if (ext_refs) {
879 lua_ucl_push_opaque (L, ext_refs);
880 }
852 }
853 else {
854 lua_pushboolean (L, res);
855 lua_pushfstring (L, "validation error: %s", err.msg);
881 }
882 else {
883 lua_pushboolean (L, res);
884 lua_pushfstring (L, "validation error: %s", err.msg);
885
886 if (ext_refs) {
887 lua_ucl_push_opaque (L, ext_refs);
888 }
856 }
857 }
858 else {
859 lua_pushboolean (L, res);
860
889 }
890 }
891 else {
892 lua_pushboolean (L, res);
893
861 if (path) {
862 lua_pushfstring (L, "cannot find the requested path: %s", path);
894 lua_pushfstring (L, "cannot find the requested path: %s", path);
895
896 if (ext_refs) {
897 lua_ucl_push_opaque (L, ext_refs);
863 }
898 }
864 else {
865 /* Should not be reached */
866 lua_pushstring (L, "unknown error");
867 }
868 }
869 }
870 else {
871 lua_pushboolean (L, res);
872 lua_pushstring (L, "invalid object or schema");
873 }
874
899 }
900 }
901 else {
902 lua_pushboolean (L, res);
903 lua_pushstring (L, "invalid object or schema");
904 }
905
906 if (ext_refs) {
907 return 3;
908 }
909
875 return 2;
876}
877
878static int
879lua_ucl_object_gc (lua_State *L)
880{
881 ucl_object_t *obj;
882

--- 256 unchanged lines hidden ---
910 return 2;
911}
912
913static int
914lua_ucl_object_gc (lua_State *L)
915{
916 ucl_object_t *obj;
917

--- 256 unchanged lines hidden ---