summaryrefslogtreecommitdiff
path: root/include/ucl++.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/ucl++.h')
-rw-r--r--include/ucl++.h189
1 files changed, 158 insertions, 31 deletions
diff --git a/include/ucl++.h b/include/ucl++.h
index 2c2bdde51559..fb63430d400d 100644
--- a/include/ucl++.h
+++ b/include/ucl++.h
@@ -29,6 +29,7 @@
#include <set>
#include <memory>
#include <iostream>
+#include <tuple>
#include "ucl.h"
@@ -106,7 +107,7 @@ private:
static bool ucl_variable_getter(const unsigned char *data, size_t len,
unsigned char ** /*replace*/, size_t * /*replace_len*/, bool *need_free, void* ud)
{
- *need_free = false;
+ *need_free = false;
auto vars = reinterpret_cast<std::set<std::string> *>(ud);
if (vars && data && len != 0) {
@@ -123,17 +124,17 @@ private:
auto replacer = reinterpret_cast<variable_replacer *>(ud);
if (!replacer) {
return false;
- }
+ }
std::string var_name (data, data + len);
if (!replacer->is_variable (var_name)) {
return false;
- }
+ }
std::string var_value = replacer->replace (var_name);
if (var_value.empty ()) {
return false;
- }
+ }
*replace = (unsigned char *)UCL_ALLOC (var_value.size ());
memcpy (*replace, var_value.data (), var_value.size ());
@@ -152,7 +153,8 @@ private:
config_func (parser);
if (!parse_func (parser)) {
- err.assign (ucl_parser_get_error (parser));
+ const char *error = ucl_parser_get_error (parser); //Assigning here without checking result first causes a
+ if( error != NULL ) err.assign(error); // crash if ucl_parser_get_error returns NULL
ucl_parser_free (parser);
return nullptr;
@@ -168,6 +170,16 @@ private:
std::unique_ptr<ucl_object_t, ucl_deleter> obj;
public:
+ struct macro_handler_s {
+ ucl_macro_handler handler;
+ ucl_context_macro_handler ctx_handler;
+ };
+
+ struct macro_userdata_s {
+ ucl_parser *parser;
+ void *userdata;
+ };
+
class const_iterator {
private:
struct ucl_iter_deleter {
@@ -184,7 +196,7 @@ public:
it = std::shared_ptr<void>(ucl_object_iterate_new (obj.obj.get()),
ucl_iter_deleter());
cur.reset (new Ucl(ucl_object_iterate_safe (it.get(), true)));
- if (cur->type() == UCL_NULL) {
+ if (!cur->obj) {
it.reset ();
cur.reset ();
}
@@ -218,7 +230,7 @@ public:
cur.reset (new Ucl(ucl_object_iterate_safe (it.get(), true)));
}
- if (cur && cur->type() == UCL_NULL) {
+ if (cur && !cur->obj) {
it.reset ();
cur.reset ();
}
@@ -330,7 +342,7 @@ public:
return UCL_NULL;
}
- const std::string key () const {
+ std::string key () const {
std::string res;
if (obj->key) {
@@ -373,7 +385,7 @@ public:
return default_val;
}
- const std::string string_value (const std::string& default_val = "") const
+ std::string string_value (const std::string& default_val = "") const
{
const char* res = nullptr;
@@ -384,7 +396,16 @@ public:
return default_val;
}
- const Ucl at (size_t i) const
+ size_t size () const
+ {
+ if (type () == UCL_ARRAY) {
+ return ucl_array_size (obj.get());
+ }
+
+ return 0;
+ }
+
+ Ucl at (size_t i) const
{
if (type () == UCL_ARRAY) {
return Ucl (ucl_array_find_index (obj.get(), i));
@@ -393,7 +414,7 @@ public:
return Ucl (nullptr);
}
- const Ucl lookup (const std::string &key) const
+ Ucl lookup (const std::string &key) const
{
if (type () == UCL_OBJECT) {
return Ucl (ucl_object_lookup_len (obj.get(),
@@ -403,12 +424,12 @@ public:
return Ucl (nullptr);
}
- inline const Ucl operator[] (size_t i) const
+ inline Ucl operator[] (size_t i) const
{
return at(i);
}
- inline const Ucl operator[](const std::string &key) const
+ inline Ucl operator[](const std::string &key) const
{
return lookup(key);
}
@@ -432,43 +453,116 @@ public:
return out;
}
- static Ucl parse (const std::string &in, std::string &err)
+ static Ucl parse (const std::string &in, std::string &err, enum ucl_duplicate_strategy duplicate_strategy = UCL_DUPLICATE_APPEND)
{
- return parse (in, std::map<std::string, std::string>(), err);
+ return parse (in, std::map<std::string, std::string>(), err, duplicate_strategy);
}
- static Ucl parse (const std::string &in, const std::map<std::string, std::string> &vars, std::string &err)
+ static Ucl parse (const std::string &in, const std::map<std::string, std::string> &vars,
+ std::string &err, enum ucl_duplicate_strategy duplicate_strategy = UCL_DUPLICATE_APPEND)
{
- auto config_func = [&vars] (ucl_parser *parser) {
+ std::vector< std::tuple< std::string, macro_handler_s, void * > > emptyVector;
+ return parse ( in, vars, emptyVector, err, duplicate_strategy );
+ }
+
+ //Macro handler will receive a macro_userdata_s as void *ud
+ static Ucl parse (const std::string &in,
+ std::vector< std::tuple< std::string /*name*/, macro_handler_s, void * /*userdata*/ > > &macros,
+ std::string &err, enum ucl_duplicate_strategy duplicate_strategy = UCL_DUPLICATE_APPEND)
+ {
+ return parse (in, std::map<std::string, std::string>(), macros, err, duplicate_strategy);
+ }
+
+ //Macro handler will receive a macro_userdata_s as void *ud
+ static Ucl parse (const std::string &in, const std::map<std::string, std::string> &vars,
+ std::vector< std::tuple< std::string /*name*/, macro_handler_s, void * /*userdata*/ > > &macros,
+ std::string &err, enum ucl_duplicate_strategy duplicate_strategy = UCL_DUPLICATE_APPEND)
+ {
+ //Preserve macro_userdata_s memory for later use in parse_with_strategy_function()
+ std::vector<macro_userdata_s> userdata_list;
+ userdata_list.reserve (macros.size());
+ auto config_func = [&userdata_list, &vars, &macros] (ucl_parser *parser) {
for (const auto & item : vars) {
ucl_parser_register_variable (parser, item.first.c_str (), item.second.c_str ());
- }
+ }
+ for (auto & macro : macros) {
+ userdata_list.push_back ({parser, std::get<2>(macro)});
+ if (std::get<1>(macro).handler != NULL) {
+ ucl_parser_register_macro (parser,
+ std::get<0>(macro).c_str(),
+ std::get<1>(macro).handler,
+ reinterpret_cast<void*>(&userdata_list.back()));
+ }
+ else if (std::get<1>(macro).ctx_handler != NULL) {
+ ucl_parser_register_context_macro (parser,
+ std::get<0>(macro).c_str(),
+ std::get<1>(macro).ctx_handler,
+ reinterpret_cast<void*>(&userdata_list.back()));
+ }
+ }
};
- auto parse_func = [&in] (ucl_parser *parser) {
- return ucl_parser_add_chunk (parser, (unsigned char *)in.data (), in.size ());
+ auto parse_func = [&in, &duplicate_strategy] (struct ucl_parser *parser) -> bool {
+ return ucl_parser_add_chunk_full (parser,
+ (unsigned char *) in.data (),
+ in.size (),
+ (unsigned int)ucl_parser_get_default_priority (parser),
+ duplicate_strategy,
+ UCL_PARSE_UCL);
};
return parse_with_strategy_function (config_func, parse_func, err);
}
- static Ucl parse (const std::string &in, const variable_replacer &replacer, std::string &err)
+ static Ucl parse (const std::string &in, const variable_replacer &replacer,
+ std::string &err, enum ucl_duplicate_strategy duplicate_strategy = UCL_DUPLICATE_APPEND)
{
- auto config_func = [&replacer] (ucl_parser *parser) {
- ucl_parser_set_variables_handler (parser, ucl_variable_replacer,
- &const_cast<variable_replacer &>(replacer));
+ std::vector< std::tuple< std::string, macro_handler_s, void * > > emptyVector;
+ return parse ( in, replacer, emptyVector, err, duplicate_strategy );
+ }
+
+ //Macro handler will receive a macro_userdata_s as void *ud
+ static Ucl parse (const std::string &in, const variable_replacer &replacer,
+ std::vector< std::tuple< std::string /*name*/, macro_handler_s, void * /*userdata*/ > > &macros,
+ std::string &err, enum ucl_duplicate_strategy duplicate_strategy = UCL_DUPLICATE_APPEND)
+ {
+ //Preserve macro_userdata_s memory for later use in parse_with_strategy_function()
+ std::vector<macro_userdata_s> userdata_list;
+ userdata_list.reserve (macros.size());
+ auto config_func = [&userdata_list, &replacer, &macros] (ucl_parser *parser) {
+ ucl_parser_set_variables_handler (parser, ucl_variable_replacer, &const_cast<variable_replacer &>(replacer));
+ for (auto & macro : macros) {
+ userdata_list.push_back ({parser, std::get<2>(macro)});
+ if (std::get<1>(macro).handler != NULL) {
+ ucl_parser_register_macro (parser,
+ std::get<0>(macro).c_str(),
+ std::get<1>(macro).handler,
+ reinterpret_cast<void*>(&userdata_list.back()));
+ }
+ else if (std::get<1>(macro).ctx_handler != NULL) {
+ ucl_parser_register_context_macro (parser,
+ std::get<0>(macro).c_str(),
+ std::get<1>(macro).ctx_handler,
+ reinterpret_cast<void*>(&userdata_list.back()));
+ }
+ }
};
- auto parse_func = [&in] (ucl_parser *parser) {
- return ucl_parser_add_chunk (parser, (unsigned char *) in.data (), in.size ());
+ auto parse_func = [&in, &duplicate_strategy] (struct ucl_parser *parser) -> bool {
+ return ucl_parser_add_chunk_full (parser,
+ (unsigned char *) in.data (),
+ in.size (),
+ (unsigned int)ucl_parser_get_default_priority (parser),
+ duplicate_strategy,
+ UCL_PARSE_UCL);
};
return parse_with_strategy_function (config_func, parse_func, err);
}
- static Ucl parse (const char *in, std::string &err)
+ static Ucl parse (const char *in, std::string &err, enum ucl_duplicate_strategy duplicate_strategy = UCL_DUPLICATE_APPEND)
{
- return parse (in, std::map<std::string, std::string>(), err);
+ return parse (in, std::map<std::string, std::string>(), err, duplicate_strategy);
}
static Ucl parse (const char *in, const std::map<std::string, std::string> &vars, std::string &err)
@@ -480,13 +574,46 @@ public:
return parse (std::string (in), vars, err);
}
- static Ucl parse (const char *in, const variable_replacer &replacer, std::string &err)
+ //Macro handler will receive a macro_userdata_s as void *ud
+ static Ucl parse (const char *in,
+ std::vector< std::tuple< std::string /*name*/, macro_handler_s, void * /*userdata*/ > > &macros,
+ std::string &err, enum ucl_duplicate_strategy duplicate_strategy = UCL_DUPLICATE_APPEND)
+ {
+ return parse (in, std::map<std::string, std::string>(), macros, err, duplicate_strategy);
+ }
+
+ //Macro handler will receive a macro_userdata_s as void *ud
+ static Ucl parse (const char *in, const std::map<std::string, std::string> &vars,
+ std::vector< std::tuple< std::string /*name*/, macro_handler_s, void * /*userdata*/ > > &macros,
+ std::string &err, enum ucl_duplicate_strategy duplicate_strategy = UCL_DUPLICATE_APPEND)
+ {
+ if (!in) {
+ err = "null input";
+ return nullptr;
+ }
+ return parse (std::string (in), vars, macros, err, duplicate_strategy);
+ }
+
+ static Ucl parse (const char *in, const variable_replacer &replacer,
+ std::string &err, enum ucl_duplicate_strategy duplicate_strategy = UCL_DUPLICATE_APPEND)
+ {
+ if (!in) {
+ err = "null input";
+ return nullptr;
+ }
+ return parse (std::string(in), replacer, err, duplicate_strategy);
+ }
+
+ //Macro handler will receive a macro_userdata_s as void *ud
+ static Ucl parse (const char *in, const variable_replacer &replacer,
+ std::vector< std::tuple< std::string /*name*/, macro_handler_s, void * /*userdata*/ > > &macros,
+ std::string &err, enum ucl_duplicate_strategy duplicate_strategy = UCL_DUPLICATE_APPEND)
{
if (!in) {
err = "null input";
return nullptr;
}
- return parse (std::string(in), replacer, err);
+ return parse (std::string (in), replacer, macros, err, duplicate_strategy);
}
static Ucl parse_from_file (const std::string &filename, std::string &err)
@@ -556,7 +683,7 @@ public:
std::vector<std::string> result;
std::move (vars.begin (), vars.end (), std::back_inserter (result));
- return std::move (result);
+ return result;
}
Ucl& operator= (Ucl rhs)