xref: /freebsd/contrib/libucl/include/ucl++.h (revision a0409676120c1e558d0ade943019934e0f15118d)
139ee7a7aSBaptiste Daroussin /*
239ee7a7aSBaptiste Daroussin  * Copyright (c) 2015, Vsevolod Stakhov
339ee7a7aSBaptiste Daroussin  * All rights reserved.
439ee7a7aSBaptiste Daroussin  *
539ee7a7aSBaptiste Daroussin  * Redistribution and use in source and binary forms, with or without
639ee7a7aSBaptiste Daroussin  * modification, are permitted provided that the following conditions are met:
739ee7a7aSBaptiste Daroussin  *	 * Redistributions of source code must retain the above copyright
839ee7a7aSBaptiste Daroussin  *	   notice, this list of conditions and the following disclaimer.
939ee7a7aSBaptiste Daroussin  *	 * Redistributions in binary form must reproduce the above copyright
1039ee7a7aSBaptiste Daroussin  *	   notice, this list of conditions and the following disclaimer in the
1139ee7a7aSBaptiste Daroussin  *	   documentation and/or other materials provided with the distribution.
1239ee7a7aSBaptiste Daroussin  *
1339ee7a7aSBaptiste Daroussin  * THIS SOFTWARE IS PROVIDED BY AUTHOR ''AS IS'' AND ANY
1439ee7a7aSBaptiste Daroussin  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
1539ee7a7aSBaptiste Daroussin  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
1639ee7a7aSBaptiste Daroussin  * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY
1739ee7a7aSBaptiste Daroussin  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
1839ee7a7aSBaptiste Daroussin  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
1939ee7a7aSBaptiste Daroussin  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
2039ee7a7aSBaptiste Daroussin  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2139ee7a7aSBaptiste Daroussin  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
2239ee7a7aSBaptiste Daroussin  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2339ee7a7aSBaptiste Daroussin  */
2439ee7a7aSBaptiste Daroussin 
2539ee7a7aSBaptiste Daroussin #pragma once
2639ee7a7aSBaptiste Daroussin #include <string>
27273c26a3SBaptiste Daroussin #include <vector>
28273c26a3SBaptiste Daroussin #include <map>
29273c26a3SBaptiste Daroussin #include <set>
3039ee7a7aSBaptiste Daroussin #include <memory>
3139ee7a7aSBaptiste Daroussin #include <iostream>
32*a0409676SBaptiste Daroussin #include <tuple>
3339ee7a7aSBaptiste Daroussin 
3439ee7a7aSBaptiste Daroussin #include "ucl.h"
3539ee7a7aSBaptiste Daroussin 
3639ee7a7aSBaptiste Daroussin // C++11 API inspired by json11: https://github.com/dropbox/json11/
3739ee7a7aSBaptiste Daroussin 
3839ee7a7aSBaptiste Daroussin namespace ucl {
3939ee7a7aSBaptiste Daroussin 
4039ee7a7aSBaptiste Daroussin struct ucl_map_construct_t { };
4139ee7a7aSBaptiste Daroussin constexpr ucl_map_construct_t ucl_map_construct = ucl_map_construct_t();
4239ee7a7aSBaptiste Daroussin struct ucl_array_construct_t { };
4339ee7a7aSBaptiste Daroussin constexpr ucl_array_construct_t ucl_array_construct = ucl_array_construct_t();
4439ee7a7aSBaptiste Daroussin 
4539ee7a7aSBaptiste Daroussin class Ucl final {
4639ee7a7aSBaptiste Daroussin private:
4739ee7a7aSBaptiste Daroussin 
4839ee7a7aSBaptiste Daroussin 	struct ucl_deleter {
operatorucl_deleter4939ee7a7aSBaptiste Daroussin 		void operator() (ucl_object_t *obj) {
5039ee7a7aSBaptiste Daroussin 			ucl_object_unref (obj);
5139ee7a7aSBaptiste Daroussin 		}
5239ee7a7aSBaptiste Daroussin 	};
5339ee7a7aSBaptiste Daroussin 
5439ee7a7aSBaptiste Daroussin 	static int
append_char(unsigned char c,size_t nchars,void * ud)5539ee7a7aSBaptiste Daroussin 	append_char (unsigned char c, size_t nchars, void *ud)
5639ee7a7aSBaptiste Daroussin 	{
5739ee7a7aSBaptiste Daroussin 		std::string *out = reinterpret_cast<std::string *>(ud);
5839ee7a7aSBaptiste Daroussin 
5939ee7a7aSBaptiste Daroussin 		out->append (nchars, (char)c);
6039ee7a7aSBaptiste Daroussin 
6139ee7a7aSBaptiste Daroussin 		return nchars;
6239ee7a7aSBaptiste Daroussin 	}
6339ee7a7aSBaptiste Daroussin 	static int
append_len(unsigned const char * str,size_t len,void * ud)6439ee7a7aSBaptiste Daroussin 	append_len (unsigned const char *str, size_t len, void *ud)
6539ee7a7aSBaptiste Daroussin 	{
6639ee7a7aSBaptiste Daroussin 		std::string *out = reinterpret_cast<std::string *>(ud);
6739ee7a7aSBaptiste Daroussin 
6839ee7a7aSBaptiste Daroussin 		out->append ((const char *)str, len);
6939ee7a7aSBaptiste Daroussin 
7039ee7a7aSBaptiste Daroussin 		return len;
7139ee7a7aSBaptiste Daroussin 	}
7239ee7a7aSBaptiste Daroussin 	static int
append_int(int64_t elt,void * ud)7339ee7a7aSBaptiste Daroussin 	append_int (int64_t elt, void *ud)
7439ee7a7aSBaptiste Daroussin 	{
7539ee7a7aSBaptiste Daroussin 		std::string *out = reinterpret_cast<std::string *>(ud);
7639ee7a7aSBaptiste Daroussin 		auto nstr = std::to_string (elt);
7739ee7a7aSBaptiste Daroussin 
7839ee7a7aSBaptiste Daroussin 		out->append (nstr);
7939ee7a7aSBaptiste Daroussin 
8039ee7a7aSBaptiste Daroussin 		return nstr.size ();
8139ee7a7aSBaptiste Daroussin 	}
8239ee7a7aSBaptiste Daroussin 	static int
append_double(double elt,void * ud)8339ee7a7aSBaptiste Daroussin 	append_double (double elt, void *ud)
8439ee7a7aSBaptiste Daroussin 	{
8539ee7a7aSBaptiste Daroussin 		std::string *out = reinterpret_cast<std::string *>(ud);
8639ee7a7aSBaptiste Daroussin 		auto nstr = std::to_string (elt);
8739ee7a7aSBaptiste Daroussin 
8839ee7a7aSBaptiste Daroussin 		out->append (nstr);
8939ee7a7aSBaptiste Daroussin 
9039ee7a7aSBaptiste Daroussin 		return nstr.size ();
9139ee7a7aSBaptiste Daroussin 	}
9239ee7a7aSBaptiste Daroussin 
default_emit_funcs()9339ee7a7aSBaptiste Daroussin 	static struct ucl_emitter_functions default_emit_funcs()
9439ee7a7aSBaptiste Daroussin 	{
9539ee7a7aSBaptiste Daroussin 		struct ucl_emitter_functions func = {
9639ee7a7aSBaptiste Daroussin 			Ucl::append_char,
9739ee7a7aSBaptiste Daroussin 			Ucl::append_len,
9839ee7a7aSBaptiste Daroussin 			Ucl::append_int,
9939ee7a7aSBaptiste Daroussin 			Ucl::append_double,
10039ee7a7aSBaptiste Daroussin 			nullptr,
10139ee7a7aSBaptiste Daroussin 			nullptr
10239ee7a7aSBaptiste Daroussin 		};
10339ee7a7aSBaptiste Daroussin 
10439ee7a7aSBaptiste Daroussin 		return func;
10539ee7a7aSBaptiste Daroussin 	};
10639ee7a7aSBaptiste Daroussin 
ucl_variable_getter(const unsigned char * data,size_t len,unsigned char **,size_t *,bool * need_free,void * ud)107273c26a3SBaptiste Daroussin 	static bool ucl_variable_getter(const unsigned char *data, size_t len,
108273c26a3SBaptiste Daroussin 			unsigned char ** /*replace*/, size_t * /*replace_len*/, bool *need_free, void* ud)
109273c26a3SBaptiste Daroussin 	{
110273c26a3SBaptiste Daroussin 		*need_free = false;
111273c26a3SBaptiste Daroussin 
112273c26a3SBaptiste Daroussin 		auto vars = reinterpret_cast<std::set<std::string> *>(ud);
113273c26a3SBaptiste Daroussin 		if (vars && data && len != 0) {
114273c26a3SBaptiste Daroussin 			vars->emplace (data, data + len);
115273c26a3SBaptiste Daroussin 		}
116273c26a3SBaptiste Daroussin 		return false;
117273c26a3SBaptiste Daroussin 	}
118273c26a3SBaptiste Daroussin 
ucl_variable_replacer(const unsigned char * data,size_t len,unsigned char ** replace,size_t * replace_len,bool * need_free,void * ud)119273c26a3SBaptiste Daroussin 	static bool ucl_variable_replacer (const unsigned char *data, size_t len,
120273c26a3SBaptiste Daroussin 			unsigned char **replace, size_t *replace_len, bool *need_free, void* ud)
121273c26a3SBaptiste Daroussin 	{
122273c26a3SBaptiste Daroussin 		*need_free = false;
123273c26a3SBaptiste Daroussin 
124273c26a3SBaptiste Daroussin 		auto replacer = reinterpret_cast<variable_replacer *>(ud);
125273c26a3SBaptiste Daroussin 		if (!replacer) {
126273c26a3SBaptiste Daroussin 			return false;
127273c26a3SBaptiste Daroussin 		}
128273c26a3SBaptiste Daroussin 
129273c26a3SBaptiste Daroussin 		std::string var_name (data, data + len);
130273c26a3SBaptiste Daroussin 		if (!replacer->is_variable (var_name)) {
131273c26a3SBaptiste Daroussin 			return false;
132273c26a3SBaptiste Daroussin 		}
133273c26a3SBaptiste Daroussin 
134273c26a3SBaptiste Daroussin 		std::string var_value = replacer->replace (var_name);
135273c26a3SBaptiste Daroussin 		if (var_value.empty ()) {
136273c26a3SBaptiste Daroussin 			return false;
137273c26a3SBaptiste Daroussin  		}
138273c26a3SBaptiste Daroussin 
139273c26a3SBaptiste Daroussin 		*replace = (unsigned char *)UCL_ALLOC (var_value.size ());
140273c26a3SBaptiste Daroussin 		memcpy (*replace, var_value.data (), var_value.size ());
141273c26a3SBaptiste Daroussin 
142273c26a3SBaptiste Daroussin 		*replace_len = var_value.size ();
143273c26a3SBaptiste Daroussin 		*need_free = true;
144273c26a3SBaptiste Daroussin 
145273c26a3SBaptiste Daroussin 		return true;
146273c26a3SBaptiste Daroussin 	}
147273c26a3SBaptiste Daroussin 
148273c26a3SBaptiste Daroussin 	template <typename C, typename P>
parse_with_strategy_function(C config_func,P parse_func,std::string & err)149273c26a3SBaptiste Daroussin 	static Ucl parse_with_strategy_function (C config_func, P parse_func, std::string &err)
150273c26a3SBaptiste Daroussin 	{
151273c26a3SBaptiste Daroussin 		auto parser = ucl_parser_new (UCL_PARSER_DEFAULT);
152273c26a3SBaptiste Daroussin 
153273c26a3SBaptiste Daroussin 		config_func (parser);
154273c26a3SBaptiste Daroussin 
155273c26a3SBaptiste Daroussin 		if (!parse_func (parser)) {
156*a0409676SBaptiste Daroussin 			const char *error = ucl_parser_get_error (parser); //Assigning here without checking result first causes a
157*a0409676SBaptiste Daroussin 			if( error != NULL ) err.assign(error);             //	crash if ucl_parser_get_error returns NULL
158273c26a3SBaptiste Daroussin 			ucl_parser_free (parser);
159273c26a3SBaptiste Daroussin 
160273c26a3SBaptiste Daroussin 			return nullptr;
161273c26a3SBaptiste Daroussin 		}
162273c26a3SBaptiste Daroussin 
163273c26a3SBaptiste Daroussin 		auto obj = ucl_parser_get_object (parser);
164273c26a3SBaptiste Daroussin 		ucl_parser_free (parser);
165273c26a3SBaptiste Daroussin 
166273c26a3SBaptiste Daroussin 		// Obj will handle ownership
167273c26a3SBaptiste Daroussin 		return Ucl (obj);
168273c26a3SBaptiste Daroussin 	}
169273c26a3SBaptiste Daroussin 
17039ee7a7aSBaptiste Daroussin 	std::unique_ptr<ucl_object_t, ucl_deleter> obj;
17139ee7a7aSBaptiste Daroussin 
17239ee7a7aSBaptiste Daroussin public:
173*a0409676SBaptiste Daroussin 	struct macro_handler_s {
174*a0409676SBaptiste Daroussin 		ucl_macro_handler         handler;
175*a0409676SBaptiste Daroussin 		ucl_context_macro_handler ctx_handler;
176*a0409676SBaptiste Daroussin 	};
177*a0409676SBaptiste Daroussin 
178*a0409676SBaptiste Daroussin 	struct macro_userdata_s {
179*a0409676SBaptiste Daroussin 		ucl_parser    *parser;
180*a0409676SBaptiste Daroussin 		void          *userdata;
181*a0409676SBaptiste Daroussin 	};
182*a0409676SBaptiste Daroussin 
18339ee7a7aSBaptiste Daroussin 	class const_iterator {
18439ee7a7aSBaptiste Daroussin 	private:
18539ee7a7aSBaptiste Daroussin 		struct ucl_iter_deleter {
operatorucl_iter_deleter18639ee7a7aSBaptiste Daroussin 			void operator() (ucl_object_iter_t it) {
18739ee7a7aSBaptiste Daroussin 				ucl_object_iterate_free (it);
18839ee7a7aSBaptiste Daroussin 			}
18939ee7a7aSBaptiste Daroussin 		};
19039ee7a7aSBaptiste Daroussin 		std::shared_ptr<void> it;
19139ee7a7aSBaptiste Daroussin 		std::unique_ptr<Ucl> cur;
19239ee7a7aSBaptiste Daroussin 	public:
19339ee7a7aSBaptiste Daroussin 		typedef std::forward_iterator_tag iterator_category;
19439ee7a7aSBaptiste Daroussin 
const_iterator(const Ucl & obj)19539ee7a7aSBaptiste Daroussin 		const_iterator(const Ucl &obj) {
19639ee7a7aSBaptiste Daroussin 			it = std::shared_ptr<void>(ucl_object_iterate_new (obj.obj.get()),
19739ee7a7aSBaptiste Daroussin 				ucl_iter_deleter());
19839ee7a7aSBaptiste Daroussin 			cur.reset (new Ucl(ucl_object_iterate_safe (it.get(), true)));
199*a0409676SBaptiste Daroussin 			if (!cur->obj) {
200d9f0ce31SBaptiste Daroussin 				it.reset ();
201d9f0ce31SBaptiste Daroussin 				cur.reset ();
202d9f0ce31SBaptiste Daroussin 			}
20339ee7a7aSBaptiste Daroussin 		}
20439ee7a7aSBaptiste Daroussin 
const_iterator()20539ee7a7aSBaptiste Daroussin 		const_iterator() {}
206d9f0ce31SBaptiste Daroussin 		const_iterator(const const_iterator &other) = delete;
207d9f0ce31SBaptiste Daroussin 		const_iterator(const_iterator &&other) = default;
~const_iterator()20839ee7a7aSBaptiste Daroussin 		~const_iterator() {}
20939ee7a7aSBaptiste Daroussin 
210d9f0ce31SBaptiste Daroussin 		const_iterator& operator=(const const_iterator &other) = delete;
211d9f0ce31SBaptiste Daroussin 		const_iterator& operator=(const_iterator &&other) = default;
21239ee7a7aSBaptiste Daroussin 
21339ee7a7aSBaptiste Daroussin 		bool operator==(const const_iterator &other) const
21439ee7a7aSBaptiste Daroussin 		{
21539ee7a7aSBaptiste Daroussin 			if (cur && other.cur) {
21639ee7a7aSBaptiste Daroussin 				return cur->obj.get() == other.cur->obj.get();
21739ee7a7aSBaptiste Daroussin 			}
21839ee7a7aSBaptiste Daroussin 
21939ee7a7aSBaptiste Daroussin 			return !cur && !other.cur;
22039ee7a7aSBaptiste Daroussin 		}
22139ee7a7aSBaptiste Daroussin 
22239ee7a7aSBaptiste Daroussin 		bool operator!=(const const_iterator &other) const
22339ee7a7aSBaptiste Daroussin 		{
22439ee7a7aSBaptiste Daroussin 			return !(*this == other);
22539ee7a7aSBaptiste Daroussin 		}
22639ee7a7aSBaptiste Daroussin 
22739ee7a7aSBaptiste Daroussin 		const_iterator& operator++()
22839ee7a7aSBaptiste Daroussin 		{
22939ee7a7aSBaptiste Daroussin 			if (it) {
23039ee7a7aSBaptiste Daroussin 				cur.reset (new Ucl(ucl_object_iterate_safe (it.get(), true)));
23139ee7a7aSBaptiste Daroussin 			}
23239ee7a7aSBaptiste Daroussin 
233*a0409676SBaptiste Daroussin 			if (cur && !cur->obj) {
23439ee7a7aSBaptiste Daroussin 				it.reset ();
23539ee7a7aSBaptiste Daroussin 				cur.reset ();
23639ee7a7aSBaptiste Daroussin 			}
23739ee7a7aSBaptiste Daroussin 
23839ee7a7aSBaptiste Daroussin 			return *this;
23939ee7a7aSBaptiste Daroussin 		}
24039ee7a7aSBaptiste Daroussin 
24139ee7a7aSBaptiste Daroussin 		const Ucl& operator*() const
24239ee7a7aSBaptiste Daroussin 		{
24339ee7a7aSBaptiste Daroussin 			return *cur;
24439ee7a7aSBaptiste Daroussin 		}
24539ee7a7aSBaptiste Daroussin 		const Ucl* operator->() const
24639ee7a7aSBaptiste Daroussin 		{
24739ee7a7aSBaptiste Daroussin 			return cur.get();
24839ee7a7aSBaptiste Daroussin 		}
24939ee7a7aSBaptiste Daroussin 	};
25039ee7a7aSBaptiste Daroussin 
251273c26a3SBaptiste Daroussin 	struct variable_replacer {
~variable_replacervariable_replacer252273c26a3SBaptiste Daroussin 		virtual ~variable_replacer() {}
253273c26a3SBaptiste Daroussin 
is_variablevariable_replacer254273c26a3SBaptiste Daroussin 		virtual bool is_variable (const std::string &str) const
255273c26a3SBaptiste Daroussin 		{
256273c26a3SBaptiste Daroussin 			return !str.empty ();
257273c26a3SBaptiste Daroussin 		}
258273c26a3SBaptiste Daroussin 
259273c26a3SBaptiste Daroussin 		virtual std::string replace (const std::string &var) const = 0;
260273c26a3SBaptiste Daroussin 	};
261273c26a3SBaptiste Daroussin 
26239ee7a7aSBaptiste Daroussin 	// We grab ownership if get non-const ucl_object_t
Ucl(ucl_object_t * other)26339ee7a7aSBaptiste Daroussin 	Ucl(ucl_object_t *other) {
26439ee7a7aSBaptiste Daroussin 		obj.reset (other);
26539ee7a7aSBaptiste Daroussin 	}
26639ee7a7aSBaptiste Daroussin 
26739ee7a7aSBaptiste Daroussin 	// Shared ownership
Ucl(const ucl_object_t * other)26839ee7a7aSBaptiste Daroussin 	Ucl(const ucl_object_t *other) {
26939ee7a7aSBaptiste Daroussin 		obj.reset (ucl_object_ref (other));
27039ee7a7aSBaptiste Daroussin 	}
27139ee7a7aSBaptiste Daroussin 
Ucl(const Ucl & other)27239ee7a7aSBaptiste Daroussin 	Ucl(const Ucl &other) {
27339ee7a7aSBaptiste Daroussin 		obj.reset (ucl_object_ref (other.obj.get()));
27439ee7a7aSBaptiste Daroussin 	}
27539ee7a7aSBaptiste Daroussin 
Ucl(Ucl && other)27639ee7a7aSBaptiste Daroussin 	Ucl(Ucl &&other) {
27739ee7a7aSBaptiste Daroussin 		obj.swap (other.obj);
27839ee7a7aSBaptiste Daroussin 	}
27939ee7a7aSBaptiste Daroussin 
Ucl()28039ee7a7aSBaptiste Daroussin 	Ucl() noexcept {
28139ee7a7aSBaptiste Daroussin 		obj.reset (ucl_object_typed_new (UCL_NULL));
28239ee7a7aSBaptiste Daroussin 	}
Ucl(std::nullptr_t)28339ee7a7aSBaptiste Daroussin 	Ucl(std::nullptr_t) noexcept {
28439ee7a7aSBaptiste Daroussin 		obj.reset (ucl_object_typed_new (UCL_NULL));
28539ee7a7aSBaptiste Daroussin 	}
Ucl(double value)28639ee7a7aSBaptiste Daroussin 	Ucl(double value) {
28739ee7a7aSBaptiste Daroussin 		obj.reset (ucl_object_typed_new (UCL_FLOAT));
28839ee7a7aSBaptiste Daroussin 		obj->value.dv = value;
28939ee7a7aSBaptiste Daroussin 	}
Ucl(int64_t value)29039ee7a7aSBaptiste Daroussin 	Ucl(int64_t value) {
29139ee7a7aSBaptiste Daroussin 		obj.reset (ucl_object_typed_new (UCL_INT));
29239ee7a7aSBaptiste Daroussin 		obj->value.iv = value;
29339ee7a7aSBaptiste Daroussin 	}
Ucl(bool value)29439ee7a7aSBaptiste Daroussin 	Ucl(bool value) {
29539ee7a7aSBaptiste Daroussin 		obj.reset (ucl_object_typed_new (UCL_BOOLEAN));
29639ee7a7aSBaptiste Daroussin 		obj->value.iv = static_cast<int64_t>(value);
29739ee7a7aSBaptiste Daroussin 	}
Ucl(const std::string & value)29839ee7a7aSBaptiste Daroussin 	Ucl(const std::string &value) {
29939ee7a7aSBaptiste Daroussin 		obj.reset (ucl_object_fromstring_common (value.data (), value.size (),
30039ee7a7aSBaptiste Daroussin 				UCL_STRING_RAW));
30139ee7a7aSBaptiste Daroussin 	}
Ucl(const char * value)30239ee7a7aSBaptiste Daroussin 	Ucl(const char *value) {
30339ee7a7aSBaptiste Daroussin 		obj.reset (ucl_object_fromstring_common (value, 0, UCL_STRING_RAW));
30439ee7a7aSBaptiste Daroussin 	}
30539ee7a7aSBaptiste Daroussin 
30639ee7a7aSBaptiste Daroussin 	// Implicit constructor: anything with a to_json() function.
30739ee7a7aSBaptiste Daroussin 	template <class T, class = decltype(&T::to_ucl)>
Ucl(const T & t)30839ee7a7aSBaptiste Daroussin 	Ucl(const T &t) : Ucl(t.to_ucl()) {}
30939ee7a7aSBaptiste Daroussin 
31039ee7a7aSBaptiste Daroussin 	// Implicit constructor: map-like objects (std::map, std::unordered_map, etc)
31139ee7a7aSBaptiste Daroussin 	template <class M, typename std::enable_if<
31239ee7a7aSBaptiste Daroussin 		std::is_constructible<std::string, typename M::key_type>::value
31339ee7a7aSBaptiste Daroussin 		&& std::is_constructible<Ucl, typename M::mapped_type>::value,
31439ee7a7aSBaptiste Daroussin 		int>::type = 0>
Ucl(const M & m)31539ee7a7aSBaptiste Daroussin 	Ucl(const M &m) {
31639ee7a7aSBaptiste Daroussin 		obj.reset (ucl_object_typed_new (UCL_OBJECT));
31739ee7a7aSBaptiste Daroussin 		auto cobj = obj.get ();
31839ee7a7aSBaptiste Daroussin 
31939ee7a7aSBaptiste Daroussin 		for (const auto &e : m) {
32039ee7a7aSBaptiste Daroussin 			ucl_object_insert_key (cobj, ucl_object_ref (e.second.obj.get()),
32139ee7a7aSBaptiste Daroussin 					e.first.data (), e.first.size (), true);
32239ee7a7aSBaptiste Daroussin 		}
32339ee7a7aSBaptiste Daroussin 	}
32439ee7a7aSBaptiste Daroussin 
32539ee7a7aSBaptiste Daroussin 	// Implicit constructor: vector-like objects (std::list, std::vector, std::set, etc)
32639ee7a7aSBaptiste Daroussin 	template <class V, typename std::enable_if<
32739ee7a7aSBaptiste Daroussin 		std::is_constructible<Ucl, typename V::value_type>::value,
32839ee7a7aSBaptiste Daroussin 		int>::type = 0>
Ucl(const V & v)32939ee7a7aSBaptiste Daroussin 	Ucl(const V &v) {
33039ee7a7aSBaptiste Daroussin 		obj.reset (ucl_object_typed_new (UCL_ARRAY));
33139ee7a7aSBaptiste Daroussin 		auto cobj = obj.get ();
33239ee7a7aSBaptiste Daroussin 
33339ee7a7aSBaptiste Daroussin 		for (const auto &e : v) {
33439ee7a7aSBaptiste Daroussin 			ucl_array_append (cobj, ucl_object_ref (e.obj.get()));
33539ee7a7aSBaptiste Daroussin 		}
33639ee7a7aSBaptiste Daroussin 	}
33739ee7a7aSBaptiste Daroussin 
type()33839ee7a7aSBaptiste Daroussin 	ucl_type_t type () const {
33939ee7a7aSBaptiste Daroussin 		if (obj) {
34039ee7a7aSBaptiste Daroussin 			return ucl_object_type (obj.get ());
34139ee7a7aSBaptiste Daroussin 		}
34239ee7a7aSBaptiste Daroussin 		return UCL_NULL;
34339ee7a7aSBaptiste Daroussin 	}
34439ee7a7aSBaptiste Daroussin 
key()345*a0409676SBaptiste Daroussin 	std::string key () const {
34639ee7a7aSBaptiste Daroussin 		std::string res;
34739ee7a7aSBaptiste Daroussin 
34839ee7a7aSBaptiste Daroussin 		if (obj->key) {
34939ee7a7aSBaptiste Daroussin 			res.assign (obj->key, obj->keylen);
35039ee7a7aSBaptiste Daroussin 		}
35139ee7a7aSBaptiste Daroussin 
35239ee7a7aSBaptiste Daroussin 		return res;
35339ee7a7aSBaptiste Daroussin 	}
35439ee7a7aSBaptiste Daroussin 
355d9f0ce31SBaptiste Daroussin 	double number_value (const double default_val = 0.0) const
35639ee7a7aSBaptiste Daroussin 	{
357d9f0ce31SBaptiste Daroussin 		double res;
35839ee7a7aSBaptiste Daroussin 
359d9f0ce31SBaptiste Daroussin 		if (ucl_object_todouble_safe(obj.get(), &res)) {
36039ee7a7aSBaptiste Daroussin 			return res;
36139ee7a7aSBaptiste Daroussin 		}
36239ee7a7aSBaptiste Daroussin 
363d9f0ce31SBaptiste Daroussin 		return default_val;
364d9f0ce31SBaptiste Daroussin 	}
365d9f0ce31SBaptiste Daroussin 
366d9f0ce31SBaptiste Daroussin 	int64_t int_value (const int64_t default_val = 0) const
367d9f0ce31SBaptiste Daroussin 	{
368d9f0ce31SBaptiste Daroussin 		int64_t res;
369d9f0ce31SBaptiste Daroussin 
370d9f0ce31SBaptiste Daroussin 		if (ucl_object_toint_safe(obj.get(), &res)) {
371d9f0ce31SBaptiste Daroussin 			return res;
372d9f0ce31SBaptiste Daroussin 		}
373d9f0ce31SBaptiste Daroussin 
374d9f0ce31SBaptiste Daroussin 		return default_val;
375d9f0ce31SBaptiste Daroussin 	}
376d9f0ce31SBaptiste Daroussin 
377d9f0ce31SBaptiste Daroussin 	bool bool_value (const bool default_val = false) const
378d9f0ce31SBaptiste Daroussin 	{
379d9f0ce31SBaptiste Daroussin 		bool res;
380d9f0ce31SBaptiste Daroussin 
381d9f0ce31SBaptiste Daroussin 		if (ucl_object_toboolean_safe(obj.get(), &res)) {
382d9f0ce31SBaptiste Daroussin 			return res;
383d9f0ce31SBaptiste Daroussin 		}
384d9f0ce31SBaptiste Daroussin 
385d9f0ce31SBaptiste Daroussin 		return default_val;
386d9f0ce31SBaptiste Daroussin 	}
387d9f0ce31SBaptiste Daroussin 
388*a0409676SBaptiste Daroussin 	std::string string_value (const std::string& default_val = "") const
389d9f0ce31SBaptiste Daroussin 	{
390d9f0ce31SBaptiste Daroussin 		const char* res = nullptr;
391d9f0ce31SBaptiste Daroussin 
392d9f0ce31SBaptiste Daroussin 		if (ucl_object_tostring_safe(obj.get(), &res)) {
393d9f0ce31SBaptiste Daroussin 			return res;
394d9f0ce31SBaptiste Daroussin 		}
395d9f0ce31SBaptiste Daroussin 
396d9f0ce31SBaptiste Daroussin 		return default_val;
397d9f0ce31SBaptiste Daroussin 	}
398d9f0ce31SBaptiste Daroussin 
size()399*a0409676SBaptiste Daroussin 	size_t size () const
400*a0409676SBaptiste Daroussin 	{
401*a0409676SBaptiste Daroussin 		if (type () == UCL_ARRAY) {
402*a0409676SBaptiste Daroussin 			return ucl_array_size (obj.get());
403*a0409676SBaptiste Daroussin 		}
404*a0409676SBaptiste Daroussin 
405*a0409676SBaptiste Daroussin 		return 0;
406*a0409676SBaptiste Daroussin 	}
407*a0409676SBaptiste Daroussin 
at(size_t i)408*a0409676SBaptiste Daroussin 	Ucl at (size_t i) const
40939ee7a7aSBaptiste Daroussin 	{
41039ee7a7aSBaptiste Daroussin 		if (type () == UCL_ARRAY) {
41139ee7a7aSBaptiste Daroussin 			return Ucl (ucl_array_find_index (obj.get(), i));
41239ee7a7aSBaptiste Daroussin 		}
41339ee7a7aSBaptiste Daroussin 
41439ee7a7aSBaptiste Daroussin 		return Ucl (nullptr);
41539ee7a7aSBaptiste Daroussin 	}
41639ee7a7aSBaptiste Daroussin 
lookup(const std::string & key)417*a0409676SBaptiste Daroussin 	Ucl lookup (const std::string &key) const
41839ee7a7aSBaptiste Daroussin 	{
41939ee7a7aSBaptiste Daroussin 		if (type () == UCL_OBJECT) {
420d9f0ce31SBaptiste Daroussin 			return Ucl (ucl_object_lookup_len (obj.get(),
42139ee7a7aSBaptiste Daroussin 					key.data (), key.size ()));
42239ee7a7aSBaptiste Daroussin 		}
42339ee7a7aSBaptiste Daroussin 
42439ee7a7aSBaptiste Daroussin 		return Ucl (nullptr);
42539ee7a7aSBaptiste Daroussin 	}
426d9f0ce31SBaptiste Daroussin 
427*a0409676SBaptiste Daroussin 	inline Ucl operator[] (size_t i) const
428d9f0ce31SBaptiste Daroussin 	{
429d9f0ce31SBaptiste Daroussin 		return at(i);
430d9f0ce31SBaptiste Daroussin 	}
431d9f0ce31SBaptiste Daroussin 
432*a0409676SBaptiste Daroussin 	inline Ucl operator[](const std::string &key) const
433d9f0ce31SBaptiste Daroussin 	{
434d9f0ce31SBaptiste Daroussin 		return lookup(key);
435d9f0ce31SBaptiste Daroussin 	}
43639ee7a7aSBaptiste Daroussin 	// Serialize.
43739ee7a7aSBaptiste Daroussin 	void dump (std::string &out, ucl_emitter_t type = UCL_EMIT_JSON) const
43839ee7a7aSBaptiste Daroussin 	{
43939ee7a7aSBaptiste Daroussin 		struct ucl_emitter_functions cbdata;
44039ee7a7aSBaptiste Daroussin 
44139ee7a7aSBaptiste Daroussin 		cbdata = Ucl::default_emit_funcs();
44239ee7a7aSBaptiste Daroussin 		cbdata.ud = reinterpret_cast<void *>(&out);
44339ee7a7aSBaptiste Daroussin 
444d9f0ce31SBaptiste Daroussin 		ucl_object_emit_full (obj.get(), type, &cbdata, nullptr);
44539ee7a7aSBaptiste Daroussin 	}
44639ee7a7aSBaptiste Daroussin 
44739ee7a7aSBaptiste Daroussin 	std::string dump (ucl_emitter_t type = UCL_EMIT_JSON) const
44839ee7a7aSBaptiste Daroussin 	{
44939ee7a7aSBaptiste Daroussin 		std::string out;
45039ee7a7aSBaptiste Daroussin 
45139ee7a7aSBaptiste Daroussin 		dump (out, type);
45239ee7a7aSBaptiste Daroussin 
45339ee7a7aSBaptiste Daroussin 		return out;
45439ee7a7aSBaptiste Daroussin 	}
45539ee7a7aSBaptiste Daroussin 
456*a0409676SBaptiste Daroussin 	static Ucl parse (const std::string &in, std::string &err, enum ucl_duplicate_strategy duplicate_strategy = UCL_DUPLICATE_APPEND)
45739ee7a7aSBaptiste Daroussin 	{
458*a0409676SBaptiste Daroussin 		return parse (in, std::map<std::string, std::string>(), err, duplicate_strategy);
45939ee7a7aSBaptiste Daroussin 	}
46039ee7a7aSBaptiste Daroussin 
461*a0409676SBaptiste Daroussin 	static Ucl parse (const std::string &in, const std::map<std::string, std::string> &vars,
462*a0409676SBaptiste Daroussin 			std::string &err, enum ucl_duplicate_strategy duplicate_strategy = UCL_DUPLICATE_APPEND)
463273c26a3SBaptiste Daroussin 	{
464*a0409676SBaptiste Daroussin 		std::vector< std::tuple< std::string, macro_handler_s, void * > > emptyVector;
465*a0409676SBaptiste Daroussin 		return parse ( in, vars, emptyVector, err, duplicate_strategy );
466*a0409676SBaptiste Daroussin 	}
467*a0409676SBaptiste Daroussin 
468*a0409676SBaptiste Daroussin 	//Macro handler will receive a macro_userdata_s as void *ud
469*a0409676SBaptiste Daroussin 	static Ucl parse (const std::string &in,
470*a0409676SBaptiste Daroussin 			std::vector< std::tuple< std::string /*name*/, macro_handler_s, void * /*userdata*/ > > &macros,
471*a0409676SBaptiste Daroussin 			std::string &err, enum ucl_duplicate_strategy duplicate_strategy = UCL_DUPLICATE_APPEND)
472*a0409676SBaptiste Daroussin 	{
473*a0409676SBaptiste Daroussin 		return parse (in, std::map<std::string, std::string>(), macros, err, duplicate_strategy);
474*a0409676SBaptiste Daroussin 	}
475*a0409676SBaptiste Daroussin 
476*a0409676SBaptiste Daroussin 	//Macro handler will receive a macro_userdata_s as void *ud
477*a0409676SBaptiste Daroussin 	static Ucl parse (const std::string &in, const std::map<std::string, std::string> &vars,
478*a0409676SBaptiste Daroussin 			std::vector< std::tuple< std::string /*name*/, macro_handler_s, void * /*userdata*/ > > &macros,
479*a0409676SBaptiste Daroussin 			std::string &err, enum ucl_duplicate_strategy duplicate_strategy = UCL_DUPLICATE_APPEND)
480*a0409676SBaptiste Daroussin 	{
481*a0409676SBaptiste Daroussin 		//Preserve macro_userdata_s memory for later use in parse_with_strategy_function()
482*a0409676SBaptiste Daroussin 		std::vector<macro_userdata_s> userdata_list;
483*a0409676SBaptiste Daroussin 		userdata_list.reserve (macros.size());
484*a0409676SBaptiste Daroussin 		auto config_func = [&userdata_list, &vars, &macros] (ucl_parser *parser) {
485273c26a3SBaptiste Daroussin 			for (const auto & item : vars) {
486273c26a3SBaptiste Daroussin 				ucl_parser_register_variable (parser, item.first.c_str (), item.second.c_str ());
487273c26a3SBaptiste Daroussin 			}
488*a0409676SBaptiste Daroussin 			for (auto & macro : macros) {
489*a0409676SBaptiste Daroussin 				userdata_list.push_back ({parser, std::get<2>(macro)});
490*a0409676SBaptiste Daroussin 				if (std::get<1>(macro).handler != NULL) {
491*a0409676SBaptiste Daroussin 					ucl_parser_register_macro (parser,
492*a0409676SBaptiste Daroussin 								std::get<0>(macro).c_str(),
493*a0409676SBaptiste Daroussin 								std::get<1>(macro).handler,
494*a0409676SBaptiste Daroussin 								reinterpret_cast<void*>(&userdata_list.back()));
495*a0409676SBaptiste Daroussin 				}
496*a0409676SBaptiste Daroussin 				else if (std::get<1>(macro).ctx_handler != NULL) {
497*a0409676SBaptiste Daroussin 					ucl_parser_register_context_macro (parser,
498*a0409676SBaptiste Daroussin 									std::get<0>(macro).c_str(),
499*a0409676SBaptiste Daroussin 									std::get<1>(macro).ctx_handler,
500*a0409676SBaptiste Daroussin 									reinterpret_cast<void*>(&userdata_list.back()));
501*a0409676SBaptiste Daroussin 				}
502*a0409676SBaptiste Daroussin 			}
503273c26a3SBaptiste Daroussin 		};
50439ee7a7aSBaptiste Daroussin 
505*a0409676SBaptiste Daroussin 		auto parse_func = [&in, &duplicate_strategy] (struct ucl_parser *parser) -> bool {
506*a0409676SBaptiste Daroussin 			return ucl_parser_add_chunk_full (parser,
507*a0409676SBaptiste Daroussin 							(unsigned char *) in.data (),
508*a0409676SBaptiste Daroussin 							in.size (),
509*a0409676SBaptiste Daroussin 							(unsigned int)ucl_parser_get_default_priority (parser),
510*a0409676SBaptiste Daroussin 							duplicate_strategy,
511*a0409676SBaptiste Daroussin 							UCL_PARSE_UCL);
512273c26a3SBaptiste Daroussin 		};
513273c26a3SBaptiste Daroussin 
514273c26a3SBaptiste Daroussin 		return parse_with_strategy_function (config_func, parse_func, err);
515273c26a3SBaptiste Daroussin 	}
516273c26a3SBaptiste Daroussin 
517*a0409676SBaptiste Daroussin 	static Ucl parse (const std::string &in, const variable_replacer &replacer,
518*a0409676SBaptiste Daroussin 			std::string &err, enum ucl_duplicate_strategy duplicate_strategy = UCL_DUPLICATE_APPEND)
519273c26a3SBaptiste Daroussin 	{
520*a0409676SBaptiste Daroussin 		std::vector< std::tuple< std::string, macro_handler_s, void * > > emptyVector;
521*a0409676SBaptiste Daroussin 		return parse ( in, replacer, emptyVector, err, duplicate_strategy );
522*a0409676SBaptiste Daroussin 	}
523*a0409676SBaptiste Daroussin 
524*a0409676SBaptiste Daroussin 	//Macro handler will receive a macro_userdata_s as void *ud
525*a0409676SBaptiste Daroussin 	static Ucl parse (const std::string &in, const variable_replacer &replacer,
526*a0409676SBaptiste Daroussin 			std::vector< std::tuple< std::string /*name*/, macro_handler_s, void * /*userdata*/ > > &macros,
527*a0409676SBaptiste Daroussin 			std::string &err, enum ucl_duplicate_strategy duplicate_strategy = UCL_DUPLICATE_APPEND)
528*a0409676SBaptiste Daroussin 	{
529*a0409676SBaptiste Daroussin 		//Preserve macro_userdata_s memory for later use in parse_with_strategy_function()
530*a0409676SBaptiste Daroussin 		std::vector<macro_userdata_s> userdata_list;
531*a0409676SBaptiste Daroussin 		userdata_list.reserve (macros.size());
532*a0409676SBaptiste Daroussin 		auto config_func = [&userdata_list, &replacer, &macros] (ucl_parser *parser) {
533*a0409676SBaptiste Daroussin 			ucl_parser_set_variables_handler (parser, ucl_variable_replacer, &const_cast<variable_replacer &>(replacer));
534*a0409676SBaptiste Daroussin 			for (auto & macro : macros) {
535*a0409676SBaptiste Daroussin 				userdata_list.push_back ({parser, std::get<2>(macro)});
536*a0409676SBaptiste Daroussin 				if (std::get<1>(macro).handler != NULL) {
537*a0409676SBaptiste Daroussin 					ucl_parser_register_macro (parser,
538*a0409676SBaptiste Daroussin 								std::get<0>(macro).c_str(),
539*a0409676SBaptiste Daroussin 								std::get<1>(macro).handler,
540*a0409676SBaptiste Daroussin 								reinterpret_cast<void*>(&userdata_list.back()));
541*a0409676SBaptiste Daroussin 				}
542*a0409676SBaptiste Daroussin 				else if (std::get<1>(macro).ctx_handler != NULL) {
543*a0409676SBaptiste Daroussin 					ucl_parser_register_context_macro (parser,
544*a0409676SBaptiste Daroussin 									std::get<0>(macro).c_str(),
545*a0409676SBaptiste Daroussin 									std::get<1>(macro).ctx_handler,
546*a0409676SBaptiste Daroussin 									reinterpret_cast<void*>(&userdata_list.back()));
547*a0409676SBaptiste Daroussin 				}
548*a0409676SBaptiste Daroussin 			}
549273c26a3SBaptiste Daroussin 		};
550273c26a3SBaptiste Daroussin 
551*a0409676SBaptiste Daroussin 		auto parse_func = [&in, &duplicate_strategy] (struct ucl_parser *parser) -> bool {
552*a0409676SBaptiste Daroussin 			return ucl_parser_add_chunk_full (parser,
553*a0409676SBaptiste Daroussin 							(unsigned char *) in.data (),
554*a0409676SBaptiste Daroussin 							in.size (),
555*a0409676SBaptiste Daroussin 							(unsigned int)ucl_parser_get_default_priority (parser),
556*a0409676SBaptiste Daroussin 							duplicate_strategy,
557*a0409676SBaptiste Daroussin 							UCL_PARSE_UCL);
558273c26a3SBaptiste Daroussin 		};
559273c26a3SBaptiste Daroussin 
560273c26a3SBaptiste Daroussin 		return parse_with_strategy_function (config_func, parse_func, err);
56139ee7a7aSBaptiste Daroussin 	}
56239ee7a7aSBaptiste Daroussin 
563*a0409676SBaptiste Daroussin 	static Ucl parse (const char *in, std::string &err, enum ucl_duplicate_strategy duplicate_strategy = UCL_DUPLICATE_APPEND)
56439ee7a7aSBaptiste Daroussin 	{
565*a0409676SBaptiste Daroussin 		return parse (in, std::map<std::string, std::string>(), err, duplicate_strategy);
566273c26a3SBaptiste Daroussin 	}
567273c26a3SBaptiste Daroussin 
parse(const char * in,const std::map<std::string,std::string> & vars,std::string & err)568273c26a3SBaptiste Daroussin 	static Ucl parse (const char *in, const std::map<std::string, std::string> &vars, std::string &err)
569273c26a3SBaptiste Daroussin 	{
570273c26a3SBaptiste Daroussin 		if (!in) {
57139ee7a7aSBaptiste Daroussin 			err = "null input";
57239ee7a7aSBaptiste Daroussin 			return nullptr;
57339ee7a7aSBaptiste Daroussin 		}
574273c26a3SBaptiste Daroussin 		return parse (std::string (in), vars, err);
57539ee7a7aSBaptiste Daroussin 	}
57639ee7a7aSBaptiste Daroussin 
577*a0409676SBaptiste Daroussin 	//Macro handler will receive a macro_userdata_s as void *ud
578*a0409676SBaptiste Daroussin 	static Ucl parse (const char *in,
579*a0409676SBaptiste Daroussin 			std::vector< std::tuple< std::string /*name*/, macro_handler_s, void * /*userdata*/ > > &macros,
580*a0409676SBaptiste Daroussin 			std::string &err, enum ucl_duplicate_strategy duplicate_strategy = UCL_DUPLICATE_APPEND)
581*a0409676SBaptiste Daroussin 	{
582*a0409676SBaptiste Daroussin 		return parse (in, std::map<std::string, std::string>(), macros, err, duplicate_strategy);
583*a0409676SBaptiste Daroussin 	}
584*a0409676SBaptiste Daroussin 
585*a0409676SBaptiste Daroussin 	//Macro handler will receive a macro_userdata_s as void *ud
586*a0409676SBaptiste Daroussin 	static Ucl parse (const char *in, const std::map<std::string, std::string> &vars,
587*a0409676SBaptiste Daroussin 			std::vector< std::tuple< std::string /*name*/, macro_handler_s, void * /*userdata*/ > > &macros,
588*a0409676SBaptiste Daroussin 			std::string &err, enum ucl_duplicate_strategy duplicate_strategy = UCL_DUPLICATE_APPEND)
58939ee7a7aSBaptiste Daroussin 	{
590273c26a3SBaptiste Daroussin 		if (!in) {
591273c26a3SBaptiste Daroussin 			err = "null input";
592273c26a3SBaptiste Daroussin 			return nullptr;
593273c26a3SBaptiste Daroussin 		}
594*a0409676SBaptiste Daroussin 		return parse (std::string (in), vars, macros, err, duplicate_strategy);
595*a0409676SBaptiste Daroussin 	}
596*a0409676SBaptiste Daroussin 
597*a0409676SBaptiste Daroussin 	static Ucl parse (const char *in, const variable_replacer &replacer,
598*a0409676SBaptiste Daroussin 			std::string &err, enum ucl_duplicate_strategy duplicate_strategy = UCL_DUPLICATE_APPEND)
599*a0409676SBaptiste Daroussin 	{
600*a0409676SBaptiste Daroussin 		if (!in) {
601*a0409676SBaptiste Daroussin 			err = "null input";
602*a0409676SBaptiste Daroussin 			return nullptr;
603*a0409676SBaptiste Daroussin 		}
604*a0409676SBaptiste Daroussin 		return parse (std::string(in), replacer, err, duplicate_strategy);
605*a0409676SBaptiste Daroussin 	}
606*a0409676SBaptiste Daroussin 
607*a0409676SBaptiste Daroussin 	//Macro handler will receive a macro_userdata_s as void *ud
608*a0409676SBaptiste Daroussin 	static Ucl parse (const char *in, const variable_replacer &replacer,
609*a0409676SBaptiste Daroussin 			std::vector< std::tuple< std::string /*name*/, macro_handler_s, void * /*userdata*/ > > &macros,
610*a0409676SBaptiste Daroussin 			std::string &err, enum ucl_duplicate_strategy duplicate_strategy = UCL_DUPLICATE_APPEND)
611*a0409676SBaptiste Daroussin 	{
612*a0409676SBaptiste Daroussin 		if (!in) {
613*a0409676SBaptiste Daroussin 			err = "null input";
614*a0409676SBaptiste Daroussin 			return nullptr;
615*a0409676SBaptiste Daroussin 		}
616*a0409676SBaptiste Daroussin 		return parse (std::string (in), replacer, macros, err, duplicate_strategy);
617273c26a3SBaptiste Daroussin 	}
618273c26a3SBaptiste Daroussin 
parse_from_file(const std::string & filename,std::string & err)619273c26a3SBaptiste Daroussin 	static Ucl parse_from_file (const std::string &filename, std::string &err)
620273c26a3SBaptiste Daroussin 	{
621273c26a3SBaptiste Daroussin 		return parse_from_file (filename, std::map<std::string, std::string>(), err);
622273c26a3SBaptiste Daroussin 	}
623273c26a3SBaptiste Daroussin 
parse_from_file(const std::string & filename,const std::map<std::string,std::string> & vars,std::string & err)624273c26a3SBaptiste Daroussin 	static Ucl parse_from_file (const std::string &filename, const std::map<std::string, std::string> &vars, std::string &err)
625273c26a3SBaptiste Daroussin 	{
626273c26a3SBaptiste Daroussin 		auto config_func = [&vars] (ucl_parser *parser) {
627273c26a3SBaptiste Daroussin 			for (const auto & item : vars) {
628273c26a3SBaptiste Daroussin 				ucl_parser_register_variable (parser, item.first.c_str (), item.second.c_str ());
629273c26a3SBaptiste Daroussin             }
630273c26a3SBaptiste Daroussin 		};
631273c26a3SBaptiste Daroussin 
632273c26a3SBaptiste Daroussin 		auto parse_func = [&filename] (ucl_parser *parser) {
633273c26a3SBaptiste Daroussin 			return ucl_parser_add_file (parser, filename.c_str ());
634273c26a3SBaptiste Daroussin 		};
635273c26a3SBaptiste Daroussin 
636273c26a3SBaptiste Daroussin 		return parse_with_strategy_function (config_func, parse_func, err);
637273c26a3SBaptiste Daroussin 	}
638273c26a3SBaptiste Daroussin 
parse_from_file(const std::string & filename,const variable_replacer & replacer,std::string & err)639273c26a3SBaptiste Daroussin 	static Ucl parse_from_file (const std::string &filename, const variable_replacer &replacer, std::string &err)
640273c26a3SBaptiste Daroussin 	{
641273c26a3SBaptiste Daroussin 		auto config_func = [&replacer] (ucl_parser *parser) {
642273c26a3SBaptiste Daroussin 			ucl_parser_set_variables_handler (parser, ucl_variable_replacer,
643273c26a3SBaptiste Daroussin 				&const_cast<variable_replacer &>(replacer));
644273c26a3SBaptiste Daroussin 		};
645273c26a3SBaptiste Daroussin 
646273c26a3SBaptiste Daroussin 		auto parse_func = [&filename] (ucl_parser *parser) {
647273c26a3SBaptiste Daroussin 			return ucl_parser_add_file (parser, filename.c_str ());
648273c26a3SBaptiste Daroussin 		};
649273c26a3SBaptiste Daroussin 
650273c26a3SBaptiste Daroussin 		return parse_with_strategy_function (config_func, parse_func, err);
651273c26a3SBaptiste Daroussin 	}
652273c26a3SBaptiste Daroussin 
find_variable(const std::string & in)653273c26a3SBaptiste Daroussin 	static std::vector<std::string> find_variable (const std::string &in)
654273c26a3SBaptiste Daroussin 	{
655273c26a3SBaptiste Daroussin 		auto parser = ucl_parser_new (UCL_PARSER_DEFAULT);
656273c26a3SBaptiste Daroussin 
657273c26a3SBaptiste Daroussin 		std::set<std::string> vars;
658273c26a3SBaptiste Daroussin 		ucl_parser_set_variables_handler (parser, ucl_variable_getter, &vars);
659273c26a3SBaptiste Daroussin 		ucl_parser_add_chunk (parser, (const unsigned char *)in.data (), in.size ());
660273c26a3SBaptiste Daroussin 		ucl_parser_free (parser);
661273c26a3SBaptiste Daroussin 
662273c26a3SBaptiste Daroussin 		std::vector<std::string> result;
663273c26a3SBaptiste Daroussin 		std::move (vars.begin (), vars.end (), std::back_inserter (result));
664273c26a3SBaptiste Daroussin 		return result;
665273c26a3SBaptiste Daroussin 	}
666273c26a3SBaptiste Daroussin 
find_variable(const char * in)667273c26a3SBaptiste Daroussin 	static std::vector<std::string> find_variable (const char *in)
668273c26a3SBaptiste Daroussin 	{
669273c26a3SBaptiste Daroussin 		if (!in) {
670273c26a3SBaptiste Daroussin 			return std::vector<std::string>();
671273c26a3SBaptiste Daroussin 		}
672273c26a3SBaptiste Daroussin 		return find_variable (std::string (in));
673273c26a3SBaptiste Daroussin 	}
674273c26a3SBaptiste Daroussin 
find_variable_from_file(const std::string & filename)675273c26a3SBaptiste Daroussin 	static std::vector<std::string> find_variable_from_file (const std::string &filename)
676273c26a3SBaptiste Daroussin 	{
677273c26a3SBaptiste Daroussin 		auto parser = ucl_parser_new (UCL_PARSER_DEFAULT);
678273c26a3SBaptiste Daroussin 
679273c26a3SBaptiste Daroussin 		std::set<std::string> vars;
680273c26a3SBaptiste Daroussin 		ucl_parser_set_variables_handler (parser, ucl_variable_getter, &vars);
681273c26a3SBaptiste Daroussin 		ucl_parser_add_file (parser, filename.c_str ());
682273c26a3SBaptiste Daroussin 		ucl_parser_free (parser);
683273c26a3SBaptiste Daroussin 
684273c26a3SBaptiste Daroussin 		std::vector<std::string> result;
685273c26a3SBaptiste Daroussin 		std::move (vars.begin (), vars.end (), std::back_inserter (result));
686*a0409676SBaptiste Daroussin 		return result;
68739ee7a7aSBaptiste Daroussin 	}
68839ee7a7aSBaptiste Daroussin 
689d9f0ce31SBaptiste Daroussin 	Ucl& operator= (Ucl rhs)
690d9f0ce31SBaptiste Daroussin 	{
691d9f0ce31SBaptiste Daroussin 		obj.swap (rhs.obj);
692d9f0ce31SBaptiste Daroussin 		return *this;
693d9f0ce31SBaptiste Daroussin 	}
694d9f0ce31SBaptiste Daroussin 
69539ee7a7aSBaptiste Daroussin 	bool operator== (const Ucl &rhs) const
69639ee7a7aSBaptiste Daroussin 	{
69739ee7a7aSBaptiste Daroussin 		return ucl_object_compare (obj.get(), rhs.obj.get ()) == 0;
69839ee7a7aSBaptiste Daroussin 	}
69939ee7a7aSBaptiste Daroussin 	bool operator< (const Ucl &rhs) const
70039ee7a7aSBaptiste Daroussin 	{
70139ee7a7aSBaptiste Daroussin 		return ucl_object_compare (obj.get(), rhs.obj.get ()) < 0;
70239ee7a7aSBaptiste Daroussin 	}
70339ee7a7aSBaptiste Daroussin 	bool operator!= (const Ucl &rhs) const { return !(*this == rhs); }
70439ee7a7aSBaptiste Daroussin 	bool operator<= (const Ucl &rhs) const { return !(rhs < *this); }
70539ee7a7aSBaptiste Daroussin 	bool operator> (const Ucl &rhs) const { return (rhs < *this); }
70639ee7a7aSBaptiste Daroussin 	bool operator>= (const Ucl &rhs) const { return !(*this < rhs); }
70739ee7a7aSBaptiste Daroussin 
708d9f0ce31SBaptiste Daroussin 	explicit operator bool () const
70939ee7a7aSBaptiste Daroussin 	{
71039ee7a7aSBaptiste Daroussin 		if (!obj || type() == UCL_NULL) {
71139ee7a7aSBaptiste Daroussin 			return false;
71239ee7a7aSBaptiste Daroussin 		}
71339ee7a7aSBaptiste Daroussin 
71439ee7a7aSBaptiste Daroussin 		if (type () == UCL_BOOLEAN) {
71539ee7a7aSBaptiste Daroussin 			return bool_value ();
71639ee7a7aSBaptiste Daroussin 		}
71739ee7a7aSBaptiste Daroussin 
71839ee7a7aSBaptiste Daroussin 		return true;
71939ee7a7aSBaptiste Daroussin 	}
72039ee7a7aSBaptiste Daroussin 
begin()72139ee7a7aSBaptiste Daroussin 	const_iterator begin() const
72239ee7a7aSBaptiste Daroussin 	{
72339ee7a7aSBaptiste Daroussin 		return const_iterator(*this);
72439ee7a7aSBaptiste Daroussin 	}
cbegin()72539ee7a7aSBaptiste Daroussin 	const_iterator cbegin() const
72639ee7a7aSBaptiste Daroussin 	{
72739ee7a7aSBaptiste Daroussin 		return const_iterator(*this);
72839ee7a7aSBaptiste Daroussin 	}
end()72939ee7a7aSBaptiste Daroussin 	const_iterator end() const
73039ee7a7aSBaptiste Daroussin 	{
73139ee7a7aSBaptiste Daroussin 		return const_iterator();
73239ee7a7aSBaptiste Daroussin 	}
cend()73339ee7a7aSBaptiste Daroussin 	const_iterator cend() const
73439ee7a7aSBaptiste Daroussin 	{
73539ee7a7aSBaptiste Daroussin 		return const_iterator();
73639ee7a7aSBaptiste Daroussin 	}
73739ee7a7aSBaptiste Daroussin };
73839ee7a7aSBaptiste Daroussin 
73939ee7a7aSBaptiste Daroussin };
740