xref: /freebsd/contrib/libucl/lua/lua_ucl.c (revision 81ad6265)
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
9  *         notice, this list of conditions and the following disclaimer in the
10  *         documentation and/or other materials provided with the distribution.
11  *
12  * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY
13  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
14  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
15  * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY
16  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
17  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
18  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
19  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
20  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
21  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22  */
23 
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 
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
38 local ucl = require("ucl")
39 
40 local parser = ucl.parser()
41 local res,err = parser:parse_string('{key=value}')
42 
43 if not res then
44 	print('parser error: ' .. err)
45 else
46 	local obj = parser:get_object()
47 	local got = ucl.to_format(obj, 'json')
48 endif
49 
50 local table = {
51   str = 'value',
52   num = 100500,
53   null = ucl.null,
54   func = function ()
55     return 'huh'
56   end
57 }
58 
59 print(ucl.to_format(table, 'ucl'))
60 -- Output:
61 --[[
62 num = 100500;
63 str = "value";
64 null = null;
65 func = "huh";
66 --]]
67  */
68 
69 #define PARSER_META "ucl.parser.meta"
70 #define EMITTER_META "ucl.emitter.meta"
71 #define NULL_META "ucl.null.meta"
72 #define OBJECT_META "ucl.object.meta"
73 #define UCL_OBJECT_TYPE_META "ucl.type.object"
74 #define UCL_ARRAY_TYPE_META "ucl.type.array"
75 #define UCL_IMPL_ARRAY_TYPE_META "ucl.type.impl_array"
76 
77 static int ucl_object_lua_push_array (lua_State *L, const ucl_object_t *obj, int flags);
78 static int ucl_object_lua_push_scalar (lua_State *L, const ucl_object_t *obj, int flags);
79 static int ucl_object_push_lua_common (lua_State *L, const ucl_object_t *obj, int flags);
80 static ucl_object_t* ucl_object_lua_fromtable (lua_State *L, int idx, ucl_string_flags_t flags);
81 static ucl_object_t* ucl_object_lua_fromelt (lua_State *L, int idx, ucl_string_flags_t flags);
82 
83 static void *ucl_null;
84 
85 
86 enum lua_ucl_push_flags {
87 	LUA_UCL_DEFAULT_FLAGS = 0,
88 	LUA_UCL_ALLOW_ARRAY = (1u << 0u),
89 	LUA_UCL_CONVERT_NIL = (1u << 1u),
90 };
91 
92 /**
93  * Push a single element of an object to lua
94  * @param L
95  * @param key
96  * @param obj
97  */
98 static void
99 ucl_object_lua_push_element (lua_State *L, const char *key,
100 		const ucl_object_t *obj, int flags)
101 {
102 	lua_pushstring (L, key);
103 	ucl_object_push_lua_common (L, obj, flags|LUA_UCL_ALLOW_ARRAY);
104 	lua_settable (L, -3);
105 }
106 
107 static void
108 lua_ucl_userdata_dtor (void *ud)
109 {
110 	struct ucl_lua_funcdata *fd = (struct ucl_lua_funcdata *)ud;
111 
112 	luaL_unref (fd->L, LUA_REGISTRYINDEX, fd->idx);
113 	if (fd->ret != NULL) {
114 		free (fd->ret);
115 	}
116 	free (fd);
117 }
118 
119 static const char *
120 lua_ucl_userdata_emitter (void *ud)
121 {
122 	struct ucl_lua_funcdata *fd = (struct ucl_lua_funcdata *)ud;
123 	const char *out = "";
124 
125 	lua_rawgeti (fd->L, LUA_REGISTRYINDEX, fd->idx);
126 
127 	lua_pcall (fd->L, 0, 1, 0);
128 	out = lua_tostring (fd->L, -1);
129 
130 	if (out != NULL) {
131 		/* We need to store temporary string in a more appropriate place */
132 		if (fd->ret) {
133 			free (fd->ret);
134 		}
135 		fd->ret = strdup (out);
136 	}
137 
138 	lua_settop (fd->L, 0);
139 
140 	return fd->ret;
141 }
142 
143 /**
144  * Push a single object to lua
145  * @param L
146  * @param obj
147  * @return
148  */
149 static int
150 ucl_object_lua_push_object (lua_State *L, const ucl_object_t *obj,
151 		int flags)
152 {
153 	const ucl_object_t *cur;
154 	ucl_object_iter_t it = NULL;
155 
156 	if ((flags & LUA_UCL_ALLOW_ARRAY) && obj->next != NULL) {
157 		/* Actually we need to push this as an array */
158 		return ucl_object_lua_push_array (L, obj, flags);
159 	}
160 
161 	lua_createtable (L, 0, obj->len);
162 	it = NULL;
163 
164 	while ((cur = ucl_object_iterate (obj, &it, true)) != NULL) {
165 		ucl_object_lua_push_element (L, ucl_object_key (cur), cur, flags);
166 	}
167 
168 	luaL_getmetatable (L, UCL_OBJECT_TYPE_META);
169 	lua_setmetatable (L, -2);
170 
171 	return 1;
172 }
173 
174 /**
175  * Push an array to lua as table indexed by integers
176  * @param L
177  * @param obj
178  * @return
179  */
180 static int
181 ucl_object_lua_push_array (lua_State *L, const ucl_object_t *obj, int flags)
182 {
183 	const ucl_object_t *cur;
184 	ucl_object_iter_t it;
185 	int i = 1, nelt = 0;
186 
187 	if (obj->type == UCL_ARRAY) {
188 		nelt = obj->len;
189 		it = ucl_object_iterate_new (obj);
190 		lua_createtable (L, nelt, 0);
191 
192 		while ((cur = ucl_object_iterate_safe (it, true))) {
193 			ucl_object_push_lua (L, cur, (flags & ~LUA_UCL_ALLOW_ARRAY));
194 			lua_rawseti (L, -2, i);
195 			i ++;
196 		}
197 
198 		luaL_getmetatable (L, UCL_ARRAY_TYPE_META);
199 		lua_setmetatable (L, -2);
200 
201 		ucl_object_iterate_free (it);
202 	}
203 	else {
204 		/* Optimize allocation by preallocation of table */
205 		LL_FOREACH (obj, cur) {
206 			nelt ++;
207 		}
208 
209 		lua_createtable (L, nelt, 0);
210 
211 		LL_FOREACH (obj, cur) {
212 			ucl_object_push_lua (L, cur, (flags & ~LUA_UCL_ALLOW_ARRAY));
213 			lua_rawseti (L, -2, i);
214 			i ++;
215 		}
216 
217 		luaL_getmetatable (L, UCL_IMPL_ARRAY_TYPE_META);
218 		lua_setmetatable (L, -2);
219 	}
220 
221 	return 1;
222 }
223 
224 /**
225  * Push a simple object to lua depending on its actual type
226  */
227 static int
228 ucl_object_lua_push_scalar (lua_State *L, const ucl_object_t *obj,
229 		int flags)
230 {
231 	struct ucl_lua_funcdata *fd;
232 
233 	if ((flags & LUA_UCL_ALLOW_ARRAY) && obj->next != NULL) {
234 		/* Actually we need to push this as an array */
235 		return ucl_object_lua_push_array (L, obj, flags);
236 	}
237 
238 	switch (obj->type) {
239 	case UCL_BOOLEAN:
240 		lua_pushboolean (L, ucl_obj_toboolean (obj));
241 		break;
242 	case UCL_STRING:
243 		lua_pushstring (L, ucl_obj_tostring (obj));
244 		break;
245 	case UCL_INT:
246 #if LUA_VERSION_NUM >= 501
247 		lua_pushinteger (L, ucl_obj_toint (obj));
248 #else
249 		lua_pushnumber (L, ucl_obj_toint (obj));
250 #endif
251 		break;
252 	case UCL_FLOAT:
253 	case UCL_TIME:
254 		lua_pushnumber (L, ucl_obj_todouble (obj));
255 		break;
256 	case UCL_NULL:
257 		if (flags & LUA_UCL_CONVERT_NIL) {
258 			lua_pushboolean (L, false);
259 		}
260 		else {
261 			lua_getfield (L, LUA_REGISTRYINDEX, "ucl.null");
262 		}
263 		break;
264 	case UCL_USERDATA:
265 		fd = (struct ucl_lua_funcdata *)obj->value.ud;
266 		lua_rawgeti (L, LUA_REGISTRYINDEX, fd->idx);
267 		break;
268 	default:
269 		lua_pushnil (L);
270 		break;
271 	}
272 
273 	return 1;
274 }
275 
276 static int
277 ucl_object_push_lua_common (lua_State *L, const ucl_object_t *obj, int flags)
278 {
279 	switch (obj->type) {
280 	case UCL_OBJECT:
281 		return ucl_object_lua_push_object (L, obj, flags);
282 	case UCL_ARRAY:
283 		return ucl_object_lua_push_array (L, obj, flags);
284 	default:
285 		return ucl_object_lua_push_scalar (L, obj, flags);
286 	}
287 }
288 
289 /***
290  * @function ucl_object_push_lua(L, obj, allow_array)
291  * This is a `C` function to push `UCL` object as lua variable. This function
292  * converts `obj` to lua representation using the following conversions:
293  *
294  * - *scalar* values are directly presented by lua objects
295  * - *userdata* values are converted to lua function objects using `LUA_REGISTRYINDEX`,
296  * this can be used to pass functions from lua to c and vice-versa
297  * - *arrays* are converted to lua tables with numeric indicies suitable for `ipairs` iterations
298  * - *objects* are converted to lua tables with string indicies
299  * @param {lua_State} L lua state pointer
300  * @param {ucl_object_t} obj object to push
301  * @param {bool} allow_array expand implicit arrays (should be true for all but partial arrays)
302  * @return {int} `1` if an object is pushed to lua
303  */
304 int
305 ucl_object_push_lua (lua_State *L, const ucl_object_t *obj, bool allow_array)
306 {
307 	return ucl_object_push_lua_common (L, obj,
308 			allow_array ? LUA_UCL_ALLOW_ARRAY : LUA_UCL_DEFAULT_FLAGS);
309 }
310 
311 int
312 ucl_object_push_lua_filter_nil (lua_State *L, const ucl_object_t *obj, bool allow_array)
313 {
314 	return ucl_object_push_lua_common (L, obj,
315 			allow_array ? (LUA_UCL_ALLOW_ARRAY|LUA_UCL_CONVERT_NIL) :
316 			(LUA_UCL_DEFAULT_FLAGS|LUA_UCL_CONVERT_NIL));
317 }
318 
319 /**
320  * Parse lua table into object top
321  * @param L
322  * @param top
323  * @param idx
324  */
325 static ucl_object_t *
326 ucl_object_lua_fromtable (lua_State *L, int idx, ucl_string_flags_t flags)
327 {
328 	ucl_object_t *obj, *top = NULL, *cur;
329 	size_t keylen;
330 	const char *k;
331 	bool is_array = true, is_implicit = false, found_mt = false;
332 	size_t max = 0, nelts = 0;
333 
334 	if (idx < 0) {
335 		/* For negative indicies we want to invert them */
336 		idx = lua_gettop (L) + idx + 1;
337 	}
338 
339 	/* First, we check from metatable */
340 	if (luaL_getmetafield (L, idx, "class") != 0) {
341 
342 		if (lua_type (L, -1) == LUA_TSTRING) {
343 			const char *classname = lua_tostring (L, -1);
344 
345 			if (strcmp (classname, UCL_OBJECT_TYPE_META) == 0) {
346 				is_array = false;
347 				found_mt = true;
348 			} else if (strcmp (classname, UCL_ARRAY_TYPE_META) == 0) {
349 				is_array = true;
350 				found_mt = true;
351 #if LUA_VERSION_NUM >= 502
352 				max = lua_rawlen (L, idx);
353 #else
354 				max = lua_objlen (L, idx);
355 #endif
356 				nelts = max;
357 			} else if (strcmp (classname, UCL_IMPL_ARRAY_TYPE_META) == 0) {
358 				is_array = true;
359 				is_implicit = true;
360 				found_mt = true;
361 #if LUA_VERSION_NUM >= 502
362 				max = lua_rawlen (L, idx);
363 #else
364 				max = lua_objlen (L, idx);
365 #endif
366 				nelts = max;
367 			}
368 		}
369 
370 		lua_pop (L, 1);
371 	}
372 
373 	if (!found_mt) {
374 		/* Check for array (it is all inefficient) */
375 		lua_pushnil (L);
376 
377 		while (lua_next (L, idx) != 0) {
378 			lua_pushvalue (L, -2);
379 
380 			if (lua_type (L, -1) == LUA_TNUMBER) {
381 				double num = lua_tonumber (L, -1);
382 				if (num == (int) num) {
383 					if (num > max) {
384 						max = num;
385 					}
386 				}
387 				else {
388 					/* Keys are not integer */
389 					is_array = false;
390 				}
391 			}
392 			else {
393 				/* Keys are not numeric */
394 				is_array = false;
395 			}
396 
397 			lua_pop (L, 2);
398 			nelts ++;
399 		}
400 	}
401 
402 	/* Table iterate */
403 	if (is_array) {
404 		int i;
405 
406 		if (!is_implicit) {
407 			top = ucl_object_typed_new (UCL_ARRAY);
408 			ucl_object_reserve (top, nelts);
409 		}
410 		else {
411 			top = NULL;
412 		}
413 
414 		for (i = 1; i <= max; i ++) {
415 			lua_pushinteger (L, i);
416 			lua_gettable (L, idx);
417 
418 			obj = ucl_object_lua_fromelt (L, lua_gettop (L), flags);
419 
420 			if (obj != NULL) {
421 				if (is_implicit) {
422 					DL_APPEND (top, obj);
423 				}
424 				else {
425 					ucl_array_append (top, obj);
426 				}
427 			}
428 			lua_pop (L, 1);
429 		}
430 	}
431 	else {
432 		lua_pushnil (L);
433 		top = ucl_object_typed_new (UCL_OBJECT);
434 		ucl_object_reserve (top, nelts);
435 
436 		while (lua_next (L, idx) != 0) {
437 			/* copy key to avoid modifications */
438 			lua_pushvalue (L, -2);
439 			k = lua_tolstring (L, -1, &keylen);
440 			obj = ucl_object_lua_fromelt (L, lua_gettop (L) - 1, flags);
441 
442 			if (obj != NULL) {
443 				ucl_object_insert_key (top, obj, k, keylen, true);
444 
445 				DL_FOREACH (obj, cur) {
446 					if (cur->keylen == 0) {
447 						cur->keylen = obj->keylen;
448 						cur->key = obj->key;
449 					}
450 				}
451 			}
452 			lua_pop (L, 2);
453 		}
454 	}
455 
456 	return top;
457 }
458 
459 /**
460  * Get a single element from lua to object obj
461  * @param L
462  * @param obj
463  * @param idx
464  */
465 static ucl_object_t *
466 ucl_object_lua_fromelt (lua_State *L, int idx, ucl_string_flags_t flags)
467 {
468 	int type;
469 	double num;
470 	ucl_object_t *obj = NULL;
471 	struct ucl_lua_funcdata *fd;
472 	const char *str;
473 	size_t sz;
474 
475 	type = lua_type (L, idx);
476 
477 	switch (type) {
478 	case LUA_TSTRING:
479 		str = lua_tolstring (L, idx, &sz);
480 
481 		if (str) {
482 			obj = ucl_object_fromstring_common (str, sz, flags);
483 		}
484 		else {
485 			obj = ucl_object_typed_new (UCL_NULL);
486 		}
487 		break;
488 	case LUA_TNUMBER:
489 		num = lua_tonumber (L, idx);
490 		if (num == (int64_t)num) {
491 			obj = ucl_object_fromint (num);
492 		}
493 		else {
494 			obj = ucl_object_fromdouble (num);
495 		}
496 		break;
497 	case LUA_TBOOLEAN:
498 		obj = ucl_object_frombool (lua_toboolean (L, idx));
499 		break;
500 	case LUA_TUSERDATA:
501 		if (lua_topointer (L, idx) == ucl_null) {
502 			obj = ucl_object_typed_new (UCL_NULL);
503 		}
504 		break;
505 	case LUA_TTABLE:
506 	case LUA_TFUNCTION:
507 	case LUA_TTHREAD:
508 		if (luaL_getmetafield (L, idx, "__gen_ucl")) {
509 			if (lua_isfunction (L, -1)) {
510 				lua_settop (L, 3); /* gen, obj, func */
511 				lua_insert (L, 1); /* func, gen, obj */
512 				lua_insert (L, 2); /* func, obj, gen */
513 				lua_call(L, 2, 1);
514 				obj = ucl_object_lua_fromelt (L, 1, flags);
515 			}
516 			lua_pop (L, 2);
517 		}
518 		else {
519 			if (type == LUA_TTABLE) {
520 				obj = ucl_object_lua_fromtable (L, idx, flags);
521 			}
522 			else if (type == LUA_TFUNCTION) {
523 				fd = malloc (sizeof (*fd));
524 				if (fd != NULL) {
525 					lua_pushvalue (L, idx);
526 					fd->L = L;
527 					fd->ret = NULL;
528 					fd->idx = luaL_ref (L, LUA_REGISTRYINDEX);
529 
530 					obj = ucl_object_new_userdata (lua_ucl_userdata_dtor,
531 							lua_ucl_userdata_emitter, (void *)fd);
532 				}
533 			}
534 		}
535 		break;
536 	}
537 
538 	return obj;
539 }
540 
541 /**
542  * @function ucl_object_lua_import(L, idx)
543  * Extracts ucl object from lua variable at `idx` position,
544  * @see ucl_object_push_lua for conversion definitions
545  * @param {lua_state} L lua state machine pointer
546  * @param {int} idx index where the source variable is placed
547  * @return {ucl_object_t} new ucl object extracted from lua variable. Reference count of this object is 1,
548  * this object thus needs to be unref'ed after usage.
549  */
550 ucl_object_t *
551 ucl_object_lua_import (lua_State *L, int idx)
552 {
553 	ucl_object_t *obj;
554 	int t;
555 
556 	t = lua_type (L, idx);
557 	switch (t) {
558 	case LUA_TTABLE:
559 		obj = ucl_object_lua_fromtable (L, idx, 0);
560 		break;
561 	default:
562 		obj = ucl_object_lua_fromelt (L, idx, 0);
563 		break;
564 	}
565 
566 	return obj;
567 }
568 
569 /**
570  * @function ucl_object_lua_import_escape(L, idx)
571  * Extracts ucl object from lua variable at `idx` position escaping JSON strings
572  * @see ucl_object_push_lua for conversion definitions
573  * @param {lua_state} L lua state machine pointer
574  * @param {int} idx index where the source variable is placed
575  * @return {ucl_object_t} new ucl object extracted from lua variable. Reference count of this object is 1,
576  * this object thus needs to be unref'ed after usage.
577  */
578 ucl_object_t *
579 ucl_object_lua_import_escape (lua_State *L, int idx)
580 {
581 	ucl_object_t *obj;
582 	int t;
583 
584 	t = lua_type (L, idx);
585 	switch (t) {
586 	case LUA_TTABLE:
587 		obj = ucl_object_lua_fromtable (L, idx, UCL_STRING_RAW);
588 		break;
589 	default:
590 		obj = ucl_object_lua_fromelt (L, idx, UCL_STRING_RAW);
591 		break;
592 	}
593 
594 	return obj;
595 }
596 
597 static int
598 lua_ucl_to_string (lua_State *L, const ucl_object_t *obj, enum ucl_emitter type)
599 {
600 	unsigned char *result;
601 
602 	result = ucl_object_emit (obj, type);
603 
604 	if (result != NULL) {
605 		lua_pushstring (L, (const char *)result);
606 		free (result);
607 	}
608 	else {
609 		lua_pushnil (L);
610 	}
611 
612 	return 1;
613 }
614 
615 static int
616 lua_ucl_parser_init (lua_State *L)
617 {
618 	struct ucl_parser *parser, **pparser;
619 	int flags = UCL_PARSER_NO_FILEVARS;
620 
621 	if (lua_gettop (L) >= 1) {
622 		flags = lua_tonumber (L, 1);
623 	}
624 
625 	parser = ucl_parser_new (flags);
626 	if (parser == NULL) {
627 		lua_pushnil (L);
628 		return 1;
629 	}
630 
631 	pparser = lua_newuserdata (L, sizeof (parser));
632 	*pparser = parser;
633 	luaL_getmetatable (L, PARSER_META);
634 	lua_setmetatable (L, -2);
635 
636 	return 1;
637 }
638 
639 static struct ucl_parser *
640 lua_ucl_parser_get (lua_State *L, int index)
641 {
642 	return *((struct ucl_parser **) luaL_checkudata(L, index, PARSER_META));
643 }
644 
645 static ucl_object_t *
646 lua_ucl_object_get (lua_State *L, int index)
647 {
648 	return *((ucl_object_t **) luaL_checkudata(L, index, OBJECT_META));
649 }
650 
651 static void
652 lua_ucl_push_opaque (lua_State *L, ucl_object_t *obj)
653 {
654 	ucl_object_t **pobj;
655 
656 	pobj = lua_newuserdata (L, sizeof (*pobj));
657 	*pobj = obj;
658 	luaL_getmetatable (L, OBJECT_META);
659 	lua_setmetatable (L, -2);
660 }
661 
662 static inline enum ucl_parse_type
663 lua_ucl_str_to_parse_type (const char *str)
664 {
665 	enum ucl_parse_type type = UCL_PARSE_UCL;
666 
667 	if (str != NULL) {
668 		if (strcasecmp (str, "msgpack") == 0) {
669 			type = UCL_PARSE_MSGPACK;
670 		}
671 		else if (strcasecmp (str, "sexp") == 0 ||
672 				strcasecmp (str, "csexp") == 0) {
673 			type = UCL_PARSE_CSEXP;
674 		}
675 		else if (strcasecmp (str, "auto") == 0) {
676 			type = UCL_PARSE_AUTO;
677 		}
678 	}
679 
680 	return type;
681 }
682 
683 /***
684  * @method parser:parse_file(name)
685  * Parse UCL object from file.
686  * @param {string} name filename to parse
687  * @return {bool[, string]} if res is `true` then file has been parsed successfully, otherwise an error string is also returned
688 @example
689 local parser = ucl.parser()
690 local res,err = parser:parse_file('/some/file.conf')
691 
692 if not res then
693 	print('parser error: ' .. err)
694 else
695 	-- Do something with object
696 end
697  */
698 static int
699 lua_ucl_parser_parse_file (lua_State *L)
700 {
701 	struct ucl_parser *parser;
702 	const char *file;
703 	int ret = 2;
704 
705 	parser = lua_ucl_parser_get (L, 1);
706 	file = luaL_checkstring (L, 2);
707 
708 	if (parser != NULL && file != NULL) {
709 		if (ucl_parser_add_file (parser, file)) {
710 			lua_pushboolean (L, true);
711 			ret = 1;
712 		}
713 		else {
714 			lua_pushboolean (L, false);
715 			lua_pushstring (L, ucl_parser_get_error (parser));
716 		}
717 	}
718 	else {
719 		lua_pushboolean (L, false);
720 		lua_pushstring (L, "invalid arguments");
721 	}
722 
723 	return ret;
724 }
725 
726 /***
727  * @method parser:register_variable(name, value)
728  * Register parser variable
729  * @param {string} name name of variable
730  * @param {string} value value of variable
731  * @return {bool} success
732 @example
733 local parser = ucl.parser()
734 local res = parser:register_variable('CONFDIR', '/etc/foo')
735  */
736 static int
737 lua_ucl_parser_register_variable (lua_State *L)
738 {
739 	struct ucl_parser *parser;
740 	const char *name, *value;
741 	int ret = 2;
742 
743 	parser = lua_ucl_parser_get (L, 1);
744 	name = luaL_checkstring (L, 2);
745 	value = luaL_checkstring (L, 3);
746 
747 	if (parser != NULL && name != NULL && value != NULL) {
748 		ucl_parser_register_variable (parser, name, value);
749 		lua_pushboolean (L, true);
750 		ret = 1;
751 	}
752 	else {
753 		return luaL_error (L, "invalid arguments");
754 	}
755 
756 	return ret;
757 }
758 
759 /***
760  * @method parser:register_variables(vars)
761  * Register parser variables
762  * @param {table} vars names/values of variables
763  * @return {bool} success
764 @example
765 local parser = ucl.parser()
766 local res = parser:register_variables({CONFDIR = '/etc/foo', VARDIR = '/var'})
767  */
768 static int
769 lua_ucl_parser_register_variables (lua_State *L)
770 {
771 	struct ucl_parser *parser;
772 	const char *name, *value;
773 	int ret = 2;
774 
775 	parser = lua_ucl_parser_get (L, 1);
776 
777 	if (parser != NULL && lua_type (L, 2) == LUA_TTABLE) {
778 		for (lua_pushnil (L); lua_next (L, 2); lua_pop (L, 1)) {
779 			lua_pushvalue (L, -2);
780 			name = luaL_checkstring (L, -1);
781 			value = luaL_checkstring (L, -2);
782 			ucl_parser_register_variable (parser, name, value);
783 			lua_pop (L, 1);
784 		}
785 
786 		lua_pushboolean (L, true);
787 		ret = 1;
788 	}
789 	else {
790 		return luaL_error (L, "invalid arguments");
791 	}
792 
793 	return ret;
794 }
795 
796 /***
797  * @method parser:parse_string(input)
798  * Parse UCL object from file.
799  * @param {string} input string to parse
800  * @return {bool[, string]} if res is `true` then file has been parsed successfully, otherwise an error string is also returned
801  */
802 static int
803 lua_ucl_parser_parse_string (lua_State *L)
804 {
805 	struct ucl_parser *parser;
806 	const char *string;
807 	size_t llen;
808 	enum ucl_parse_type type = UCL_PARSE_UCL;
809 	int ret = 2;
810 
811 	parser = lua_ucl_parser_get (L, 1);
812 	string = luaL_checklstring (L, 2, &llen);
813 
814 	if (lua_type (L, 3) == LUA_TSTRING) {
815 		type = lua_ucl_str_to_parse_type (lua_tostring (L, 3));
816 	}
817 
818 	if (parser != NULL && string != NULL) {
819 		if (ucl_parser_add_chunk_full (parser, (const unsigned char *)string,
820 				llen, 0, UCL_DUPLICATE_APPEND, type)) {
821 			lua_pushboolean (L, true);
822 			ret = 1;
823 		}
824 		else {
825 			lua_pushboolean (L, false);
826 			lua_pushstring (L, ucl_parser_get_error (parser));
827 		}
828 	}
829 	else {
830 		lua_pushboolean (L, false);
831 		lua_pushstring (L, "invalid arguments");
832 	}
833 
834 	return ret;
835 }
836 
837 struct _rspamd_lua_text {
838 	const char *start;
839 	unsigned int len;
840 	unsigned int flags;
841 };
842 
843 /***
844  * @method parser:parse_text(input)
845  * Parse UCL object from text object (Rspamd specific).
846  * @param {rspamd_text} input text to parse
847  * @return {bool[, string]} if res is `true` then file has been parsed successfully, otherwise an error string is also returned
848  */
849 static int
850 lua_ucl_parser_parse_text (lua_State *L)
851 {
852 	struct ucl_parser *parser;
853 	struct _rspamd_lua_text *t;
854 	enum ucl_parse_type type = UCL_PARSE_UCL;
855 	int ret = 2;
856 
857 	parser = lua_ucl_parser_get (L, 1);
858 	t = lua_touserdata (L, 2);
859 
860 	if (lua_type (L, 3) == LUA_TSTRING) {
861 		type = lua_ucl_str_to_parse_type (lua_tostring (L, 3));
862 	}
863 
864 	if (parser != NULL && t != NULL) {
865 		if (ucl_parser_add_chunk_full (parser, (const unsigned char *)t->start,
866 				t->len, 0, UCL_DUPLICATE_APPEND, type)) {
867 			lua_pushboolean (L, true);
868 			ret = 1;
869 		}
870 		else {
871 			lua_pushboolean (L, false);
872 			lua_pushstring (L, ucl_parser_get_error (parser));
873 		}
874 	}
875 	else {
876 		lua_pushboolean (L, false);
877 		lua_pushstring (L, "invalid arguments");
878 	}
879 
880 	return ret;
881 }
882 
883 /***
884  * @method parser:get_object()
885  * Get top object from parser and export it to lua representation.
886  * @return {variant or nil} ucl object as lua native variable
887  */
888 static int
889 lua_ucl_parser_get_object (lua_State *L)
890 {
891 	struct ucl_parser *parser;
892 	ucl_object_t *obj;
893 	int ret = 1;
894 
895 	parser = lua_ucl_parser_get (L, 1);
896 	obj = ucl_parser_get_object (parser);
897 
898 	if (obj != NULL) {
899 		ret = ucl_object_push_lua (L, obj, false);
900 		/* no need to keep reference */
901 		ucl_object_unref (obj);
902 	}
903 	else {
904 		lua_pushnil (L);
905 	}
906 
907 	return ret;
908 }
909 
910 /***
911  * @method parser:get_object_wrapped()
912  * Get top object from parser and export it to userdata object without
913  * unwrapping to lua.
914  * @return {ucl.object or nil} ucl object wrapped variable
915  */
916 static int
917 lua_ucl_parser_get_object_wrapped (lua_State *L)
918 {
919 	struct ucl_parser *parser;
920 	ucl_object_t *obj;
921 	int ret = 1;
922 
923 	parser = lua_ucl_parser_get (L, 1);
924 	obj = ucl_parser_get_object (parser);
925 
926 	if (obj != NULL) {
927 		lua_ucl_push_opaque (L, obj);
928 	}
929 	else {
930 		lua_pushnil (L);
931 	}
932 
933 	return ret;
934 }
935 
936 /***
937  * @method parser:validate(schema)
938  * Validates the top object in the parser against schema. Schema might be
939  * another object or a string that represents file to load schema from.
940  *
941  * @param {string/table} schema input schema
942  * @return {result,err} two values: boolean result and the corresponding error
943  *
944  */
945 static int
946 lua_ucl_parser_validate (lua_State *L)
947 {
948 	struct ucl_parser *parser, *schema_parser;
949 	ucl_object_t *schema;
950 	const char *schema_file;
951 	struct ucl_schema_error err;
952 
953 	parser = lua_ucl_parser_get (L, 1);
954 
955 	if (parser && parser->top_obj) {
956 		if (lua_type (L, 2) == LUA_TTABLE) {
957 			schema = ucl_object_lua_import (L, 2);
958 
959 			if (schema == NULL) {
960 				lua_pushboolean (L, false);
961 				lua_pushstring (L, "cannot load schema from lua table");
962 
963 				return 2;
964 			}
965 		}
966 		else if (lua_type (L, 2) == LUA_TSTRING) {
967 			schema_parser = ucl_parser_new (0);
968 			schema_file = luaL_checkstring (L, 2);
969 
970 			if (!ucl_parser_add_file (schema_parser, schema_file)) {
971 				lua_pushboolean (L, false);
972 				lua_pushfstring (L, "cannot parse schema file \"%s\": "
973 						"%s", schema_file, ucl_parser_get_error (parser));
974 				ucl_parser_free (schema_parser);
975 
976 				return 2;
977 			}
978 
979 			schema = ucl_parser_get_object (schema_parser);
980 			ucl_parser_free (schema_parser);
981 		}
982 		else {
983 			lua_pushboolean (L, false);
984 			lua_pushstring (L, "invalid schema argument");
985 
986 			return 2;
987 		}
988 
989 		if (!ucl_object_validate (schema, parser->top_obj, &err)) {
990 			lua_pushboolean (L, false);
991 			lua_pushfstring (L, "validation error: "
992 					"%s", err.msg);
993 		}
994 		else {
995 			lua_pushboolean (L, true);
996 			lua_pushnil (L);
997 		}
998 
999 		ucl_object_unref (schema);
1000 	}
1001 	else {
1002 		lua_pushboolean (L, false);
1003 		lua_pushstring (L, "invalid parser or empty top object");
1004 	}
1005 
1006 	return 2;
1007 }
1008 
1009 static int
1010 lua_ucl_parser_gc (lua_State *L)
1011 {
1012 	struct ucl_parser *parser;
1013 
1014 	parser = lua_ucl_parser_get (L, 1);
1015 	ucl_parser_free (parser);
1016 
1017 	return 0;
1018 }
1019 
1020 /***
1021  * @method object:unwrap()
1022  * Unwraps opaque ucl object to the native lua object (performing copying)
1023  * @return {variant} any lua object
1024  */
1025 static int
1026 lua_ucl_object_unwrap (lua_State *L)
1027 {
1028 	ucl_object_t *obj;
1029 
1030 	obj = lua_ucl_object_get (L, 1);
1031 
1032 	if (obj) {
1033 		ucl_object_push_lua (L, obj, true);
1034 	}
1035 	else {
1036 		lua_pushnil (L);
1037 	}
1038 
1039 	return 1;
1040 }
1041 
1042 static inline enum ucl_emitter
1043 lua_ucl_str_to_emit_type (const char *strtype)
1044 {
1045 	enum ucl_emitter format = UCL_EMIT_JSON_COMPACT;
1046 
1047 	if (strcasecmp (strtype, "json") == 0) {
1048 		format = UCL_EMIT_JSON;
1049 	}
1050 	else if (strcasecmp (strtype, "json-compact") == 0) {
1051 		format = UCL_EMIT_JSON_COMPACT;
1052 	}
1053 	else if (strcasecmp (strtype, "yaml") == 0) {
1054 		format = UCL_EMIT_YAML;
1055 	}
1056 	else if (strcasecmp (strtype, "config") == 0 ||
1057 			strcasecmp (strtype, "ucl") == 0) {
1058 		format = UCL_EMIT_CONFIG;
1059 	}
1060 
1061 	return format;
1062 }
1063 
1064 /***
1065  * @method object:tostring(type)
1066  * Unwraps opaque ucl object to string (json by default). Optionally you can
1067  * specify output format:
1068  *
1069  * - `json` - fine printed json
1070  * - `json-compact` - compacted json
1071  * - `config` - fine printed configuration
1072  * - `ucl` - same as `config`
1073  * - `yaml` - embedded yaml
1074  * @param {string} type optional
1075  * @return {string} string representation of the opaque ucl object
1076  */
1077 static int
1078 lua_ucl_object_tostring (lua_State *L)
1079 {
1080 	ucl_object_t *obj;
1081 	enum ucl_emitter format = UCL_EMIT_JSON_COMPACT;
1082 
1083 	obj = lua_ucl_object_get (L, 1);
1084 
1085 	if (obj) {
1086 		if (lua_gettop (L) > 1) {
1087 			if (lua_type (L, 2) == LUA_TSTRING) {
1088 				const char *strtype = lua_tostring (L, 2);
1089 
1090 				format = lua_ucl_str_to_emit_type (strtype);
1091 			}
1092 		}
1093 
1094 		return lua_ucl_to_string (L, obj, format);
1095 	}
1096 	else {
1097 		lua_pushnil (L);
1098 	}
1099 
1100 	return 1;
1101 }
1102 
1103 /***
1104  * @method object:validate(schema[, path[, ext_refs]])
1105  * Validates the given ucl object using schema object represented as another
1106  * opaque ucl object. You can also specify path in the form `#/path/def` to
1107  * specify the specific schema element to perform validation.
1108  *
1109  * @param {ucl.object} schema schema object
1110  * @param {string} path optional path for validation procedure
1111  * @return {result,err} two values: boolean result and the corresponding
1112  * error, if `ext_refs` are also specified, then they are returned as opaque
1113  * ucl object as {result,err,ext_refs}
1114  */
1115 static int
1116 lua_ucl_object_validate (lua_State *L)
1117 {
1118 	ucl_object_t *obj, *schema, *ext_refs = NULL;
1119 	const ucl_object_t *schema_elt;
1120 	bool res = false;
1121 	struct ucl_schema_error err;
1122 	const char *path = NULL;
1123 
1124 	obj = lua_ucl_object_get (L, 1);
1125 	schema = lua_ucl_object_get (L, 2);
1126 
1127 	if (schema && obj && ucl_object_type (schema) == UCL_OBJECT) {
1128 		if (lua_gettop (L) > 2) {
1129 			if (lua_type (L, 3) == LUA_TSTRING) {
1130 				path = lua_tostring (L, 3);
1131 				if (path[0] == '#') {
1132 					path++;
1133 				}
1134 			}
1135 			else if (lua_type (L, 3) == LUA_TUSERDATA || lua_type (L, 3) ==
1136 						LUA_TTABLE) {
1137 				/* External refs */
1138 				ext_refs = lua_ucl_object_get (L, 3);
1139 			}
1140 
1141 			if (lua_gettop (L) > 3) {
1142 				if (lua_type (L, 4) == LUA_TUSERDATA || lua_type (L, 4) ==
1143 						LUA_TTABLE) {
1144 					/* External refs */
1145 					ext_refs = lua_ucl_object_get (L, 4);
1146 				}
1147 			}
1148 		}
1149 
1150 		if (path) {
1151 			schema_elt = ucl_object_lookup_path_char (schema, path, '/');
1152 		}
1153 		else {
1154 			/* Use the top object */
1155 			schema_elt = schema;
1156 		}
1157 
1158 		if (schema_elt) {
1159 			res = ucl_object_validate_root_ext (schema_elt, obj, schema,
1160 					ext_refs, &err);
1161 
1162 			if (res) {
1163 				lua_pushboolean (L, res);
1164 				lua_pushnil (L);
1165 
1166 				if (ext_refs) {
1167 					lua_ucl_push_opaque (L, ext_refs);
1168 				}
1169 			}
1170 			else {
1171 				lua_pushboolean (L, res);
1172 				lua_pushfstring (L, "validation error: %s", err.msg);
1173 
1174 				if (ext_refs) {
1175 					lua_ucl_push_opaque (L, ext_refs);
1176 				}
1177 			}
1178 		}
1179 		else {
1180 			lua_pushboolean (L, res);
1181 
1182 			lua_pushfstring (L, "cannot find the requested path: %s", path);
1183 
1184 			if (ext_refs) {
1185 				lua_ucl_push_opaque (L, ext_refs);
1186 			}
1187 		}
1188 	}
1189 	else {
1190 		lua_pushboolean (L, res);
1191 		lua_pushstring (L, "invalid object or schema");
1192 	}
1193 
1194 	if (ext_refs) {
1195 		return 3;
1196 	}
1197 
1198 	return 2;
1199 }
1200 
1201 static int
1202 lua_ucl_object_gc (lua_State *L)
1203 {
1204 	ucl_object_t *obj;
1205 
1206 	obj = lua_ucl_object_get (L, 1);
1207 
1208 	ucl_object_unref (obj);
1209 
1210 	return 0;
1211 }
1212 
1213 static void
1214 lua_ucl_parser_mt (lua_State *L)
1215 {
1216 	luaL_newmetatable (L, PARSER_META);
1217 
1218 	lua_pushvalue(L, -1);
1219 	lua_setfield(L, -2, "__index");
1220 
1221 	lua_pushcfunction (L, lua_ucl_parser_gc);
1222 	lua_setfield (L, -2, "__gc");
1223 
1224 	lua_pushcfunction (L, lua_ucl_parser_parse_file);
1225 	lua_setfield (L, -2, "parse_file");
1226 
1227 	lua_pushcfunction (L, lua_ucl_parser_parse_string);
1228 	lua_setfield (L, -2, "parse_string");
1229 
1230 	lua_pushcfunction (L, lua_ucl_parser_parse_text);
1231 	lua_setfield (L, -2, "parse_text");
1232 
1233 	lua_pushcfunction (L, lua_ucl_parser_register_variable);
1234 	lua_setfield (L, -2, "register_variable");
1235 
1236 	lua_pushcfunction (L, lua_ucl_parser_register_variables);
1237 	lua_setfield (L, -2, "register_variables");
1238 
1239 	lua_pushcfunction (L, lua_ucl_parser_get_object);
1240 	lua_setfield (L, -2, "get_object");
1241 
1242 	lua_pushcfunction (L, lua_ucl_parser_get_object_wrapped);
1243 	lua_setfield (L, -2, "get_object_wrapped");
1244 
1245 	lua_pushcfunction (L, lua_ucl_parser_validate);
1246 	lua_setfield (L, -2, "validate");
1247 
1248 	lua_pop (L, 1);
1249 }
1250 
1251 static void
1252 lua_ucl_object_mt (lua_State *L)
1253 {
1254 	luaL_newmetatable (L, OBJECT_META);
1255 
1256 	lua_pushvalue(L, -1);
1257 	lua_setfield(L, -2, "__index");
1258 
1259 	lua_pushcfunction (L, lua_ucl_object_gc);
1260 	lua_setfield (L, -2, "__gc");
1261 
1262 	lua_pushcfunction (L, lua_ucl_object_tostring);
1263 	lua_setfield (L, -2, "__tostring");
1264 
1265 	lua_pushcfunction (L, lua_ucl_object_tostring);
1266 	lua_setfield (L, -2, "tostring");
1267 
1268 	lua_pushcfunction (L, lua_ucl_object_unwrap);
1269 	lua_setfield (L, -2, "unwrap");
1270 
1271 	lua_pushcfunction (L, lua_ucl_object_unwrap);
1272 	lua_setfield (L, -2, "tolua");
1273 
1274 	lua_pushcfunction (L, lua_ucl_object_validate);
1275 	lua_setfield (L, -2, "validate");
1276 
1277 	lua_pushstring (L, OBJECT_META);
1278 	lua_setfield (L, -2, "class");
1279 
1280 	lua_pop (L, 1);
1281 }
1282 
1283 static void
1284 lua_ucl_types_mt (lua_State *L)
1285 {
1286 	luaL_newmetatable (L, UCL_OBJECT_TYPE_META);
1287 
1288 	lua_pushcfunction (L, lua_ucl_object_tostring);
1289 	lua_setfield (L, -2, "__tostring");
1290 
1291 	lua_pushcfunction (L, lua_ucl_object_tostring);
1292 	lua_setfield (L, -2, "tostring");
1293 
1294 	lua_pushstring (L, UCL_OBJECT_TYPE_META);
1295 	lua_setfield (L, -2, "class");
1296 
1297 	lua_pop (L, 1);
1298 
1299 	luaL_newmetatable (L, UCL_ARRAY_TYPE_META);
1300 
1301 	lua_pushcfunction (L, lua_ucl_object_tostring);
1302 	lua_setfield (L, -2, "__tostring");
1303 
1304 	lua_pushcfunction (L, lua_ucl_object_tostring);
1305 	lua_setfield (L, -2, "tostring");
1306 
1307 	lua_pushstring (L, UCL_ARRAY_TYPE_META);
1308 	lua_setfield (L, -2, "class");
1309 
1310 	lua_pop (L, 1);
1311 
1312 	luaL_newmetatable (L, UCL_IMPL_ARRAY_TYPE_META);
1313 
1314 	lua_pushcfunction (L, lua_ucl_object_tostring);
1315 	lua_setfield (L, -2, "__tostring");
1316 
1317 	lua_pushcfunction (L, lua_ucl_object_tostring);
1318 	lua_setfield (L, -2, "tostring");
1319 
1320 	lua_pushstring (L, UCL_IMPL_ARRAY_TYPE_META);
1321 	lua_setfield (L, -2, "class");
1322 
1323 	lua_pop (L, 1);
1324 }
1325 
1326 static int
1327 lua_ucl_to_json (lua_State *L)
1328 {
1329 	ucl_object_t *obj;
1330 	int format = UCL_EMIT_JSON;
1331 
1332 	if (lua_gettop (L) > 1) {
1333 		if (lua_toboolean (L, 2)) {
1334 			format = UCL_EMIT_JSON_COMPACT;
1335 		}
1336 	}
1337 
1338 	obj = ucl_object_lua_import (L, 1);
1339 	if (obj != NULL) {
1340 		lua_ucl_to_string (L, obj, format);
1341 		ucl_object_unref (obj);
1342 	}
1343 	else {
1344 		lua_pushnil (L);
1345 	}
1346 
1347 	return 1;
1348 }
1349 
1350 static int
1351 lua_ucl_to_config (lua_State *L)
1352 {
1353 	ucl_object_t *obj;
1354 
1355 	obj = ucl_object_lua_import (L, 1);
1356 	if (obj != NULL) {
1357 		lua_ucl_to_string (L, obj, UCL_EMIT_CONFIG);
1358 		ucl_object_unref (obj);
1359 	}
1360 	else {
1361 		lua_pushnil (L);
1362 	}
1363 
1364 	return 1;
1365 }
1366 
1367 /***
1368  * @function ucl.to_format(var, format)
1369  * Converts lua variable `var` to the specified `format`. Formats supported are:
1370  *
1371  * - `json` - fine printed json
1372  * - `json-compact` - compacted json
1373  * - `config` - fine printed configuration
1374  * - `ucl` - same as `config`
1375  * - `yaml` - embedded yaml
1376  *
1377  * If `var` contains function, they are called during output formatting and if
1378  * they return string value, then this value is used for output.
1379  * @param {variant} var any sort of lua variable (if userdata then metafield `__to_ucl` is searched for output)
1380  * @param {string} format any available format
1381  * @return {string} string representation of `var` in the specific `format`.
1382  * @example
1383 local table = {
1384   str = 'value',
1385   num = 100500,
1386   null = ucl.null,
1387   func = function ()
1388     return 'huh'
1389   end
1390 }
1391 
1392 print(ucl.to_format(table, 'ucl'))
1393 -- Output:
1394 --[[
1395 num = 100500;
1396 str = "value";
1397 null = null;
1398 func = "huh";
1399 --]]
1400  */
1401 static int
1402 lua_ucl_to_format (lua_State *L)
1403 {
1404 	ucl_object_t *obj;
1405 	int format = UCL_EMIT_JSON;
1406 	bool sort = false;
1407 
1408 	if (lua_gettop (L) > 1) {
1409 		if (lua_type (L, 2) == LUA_TNUMBER) {
1410 			format = lua_tonumber (L, 2);
1411 			if (format < 0 || format >= UCL_EMIT_YAML) {
1412 				lua_pushnil (L);
1413 				return 1;
1414 			}
1415 		}
1416 		else if (lua_type (L, 2) == LUA_TSTRING) {
1417 			const char *strtype = lua_tostring (L, 2);
1418 
1419 			if (strcasecmp (strtype, "json") == 0) {
1420 				format = UCL_EMIT_JSON;
1421 			}
1422 			else if (strcasecmp (strtype, "json-compact") == 0) {
1423 				format = UCL_EMIT_JSON_COMPACT;
1424 			}
1425 			else if (strcasecmp (strtype, "yaml") == 0) {
1426 				format = UCL_EMIT_YAML;
1427 			}
1428 			else if (strcasecmp (strtype, "config") == 0 ||
1429 				strcasecmp (strtype, "ucl") == 0) {
1430 				format = UCL_EMIT_CONFIG;
1431 			}
1432 			else if (strcasecmp (strtype, "msgpack") == 0) {
1433 				format = UCL_EMIT_MSGPACK;
1434 			}
1435 		}
1436 
1437 		if (lua_isboolean (L, 3)) {
1438 			sort = lua_toboolean (L, 3);
1439 		}
1440 	}
1441 
1442 	obj = ucl_object_lua_import (L, 1);
1443 
1444 	if (obj != NULL) {
1445 
1446 		if (sort) {
1447 			if (ucl_object_type (obj) == UCL_OBJECT) {
1448 				ucl_object_sort_keys (obj, UCL_SORT_KEYS_RECURSIVE);
1449 			}
1450 		}
1451 
1452 		lua_ucl_to_string (L, obj, format);
1453 		ucl_object_unref (obj);
1454 	}
1455 	else {
1456 		lua_pushnil (L);
1457 	}
1458 
1459 	return 1;
1460 }
1461 
1462 static int
1463 lua_ucl_null_tostring (lua_State* L)
1464 {
1465 	lua_pushstring (L, "null");
1466 	return 1;
1467 }
1468 
1469 static void
1470 lua_ucl_null_mt (lua_State *L)
1471 {
1472 	luaL_newmetatable (L, NULL_META);
1473 
1474 	lua_pushcfunction (L, lua_ucl_null_tostring);
1475 	lua_setfield (L, -2, "__tostring");
1476 
1477 	lua_pop (L, 1);
1478 }
1479 
1480 int
1481 luaopen_ucl (lua_State *L)
1482 {
1483 	lua_ucl_parser_mt (L);
1484 	lua_ucl_null_mt (L);
1485 	lua_ucl_object_mt (L);
1486 	lua_ucl_types_mt (L);
1487 
1488 	/* Create the refs weak table: */
1489 	lua_createtable (L, 0, 2);
1490 	lua_pushliteral (L, "v"); /* tbl, "v" */
1491 	lua_setfield (L, -2, "__mode");
1492 	lua_pushvalue (L, -1); /* tbl, tbl */
1493 	lua_setmetatable (L, -2); /* tbl */
1494 	lua_setfield (L, LUA_REGISTRYINDEX, "ucl.refs");
1495 
1496 	lua_newtable (L);
1497 
1498 	lua_pushcfunction (L, lua_ucl_parser_init);
1499 	lua_setfield (L, -2, "parser");
1500 
1501 	lua_pushcfunction (L, lua_ucl_to_json);
1502 	lua_setfield (L, -2, "to_json");
1503 
1504 	lua_pushcfunction (L, lua_ucl_to_config);
1505 	lua_setfield (L, -2, "to_config");
1506 
1507 	lua_pushcfunction (L, lua_ucl_to_format);
1508 	lua_setfield (L, -2, "to_format");
1509 
1510 	ucl_null = lua_newuserdata (L, 0);
1511 	luaL_getmetatable (L, NULL_META);
1512 	lua_setmetatable (L, -2);
1513 
1514 	lua_pushvalue (L, -1);
1515 	lua_setfield (L, LUA_REGISTRYINDEX, "ucl.null");
1516 
1517 	lua_setfield (L, -2, "null");
1518 
1519 	return 1;
1520 }
1521 
1522 struct ucl_lua_funcdata*
1523 ucl_object_toclosure (const ucl_object_t *obj)
1524 {
1525 	if (obj == NULL || obj->type != UCL_USERDATA) {
1526 		return NULL;
1527 	}
1528 
1529 	return (struct ucl_lua_funcdata*)obj->value.ud;
1530 }
1531