summaryrefslogtreecommitdiffstats
path: root/src/yajlpp/yajlpp_def.hh
diff options
context:
space:
mode:
Diffstat (limited to 'src/yajlpp/yajlpp_def.hh')
-rw-r--r--src/yajlpp/yajlpp_def.hh467
1 files changed, 386 insertions, 81 deletions
diff --git a/src/yajlpp/yajlpp_def.hh b/src/yajlpp/yajlpp_def.hh
index 22454b1..7bcb687 100644
--- a/src/yajlpp/yajlpp_def.hh
+++ b/src/yajlpp/yajlpp_def.hh
@@ -241,11 +241,13 @@ struct json_path_handler : public json_path_handler_base {
static int null_field_cb(yajlpp_parse_context* ypc)
{
+ ypc->fill_in_source();
return ypc->ypc_current_handler->jph_null_cb(ypc);
}
static int bool_field_cb(yajlpp_parse_context* ypc, int val)
{
+ ypc->fill_in_source();
return ypc->ypc_current_handler->jph_bool_cb(ypc, val);
}
@@ -253,20 +255,36 @@ struct json_path_handler : public json_path_handler_base {
const unsigned char* str,
size_t len)
{
- return ypc->ypc_current_handler->jph_str_cb(ypc, str, len);
+ ypc->fill_in_source();
+ return ypc->ypc_current_handler->jph_str_cb(
+ ypc, string_fragment::from_bytes(str, len));
}
static int int_field_cb(yajlpp_parse_context* ypc, long long val)
{
+ ypc->fill_in_source();
return ypc->ypc_current_handler->jph_integer_cb(ypc, val);
}
static int dbl_field_cb(yajlpp_parse_context* ypc, double val)
{
+ ypc->fill_in_source();
return ypc->ypc_current_handler->jph_double_cb(ypc, val);
}
template<typename T, typename U>
+ static inline U& get_field(T& input, std::shared_ptr<U>(T::*field))
+ {
+ auto& ptr = input.*field;
+
+ if (ptr.get() == nullptr) {
+ ptr = std::make_shared<U>();
+ }
+
+ return *ptr;
+ }
+
+ template<typename T, typename U>
static inline U& get_field(T& input, U(T::*field))
{
return input.*field;
@@ -366,11 +384,64 @@ struct json_path_handler : public json_path_handler_base {
};
template<typename T, typename U>
+ struct LastIsVector<std::shared_ptr<std::vector<U>> T::*> {
+ using value_type = U;
+ static constexpr bool value = true;
+ };
+
+ template<typename T, typename U>
struct LastIsVector<U T::*> {
using value_type = void;
static constexpr bool value = false;
};
+ template<typename T, typename... Args>
+ struct LastIsIntegerVector {
+ using value_type = typename LastIsIntegerVector<Args...>::value_type;
+ static constexpr bool value = LastIsIntegerVector<Args...>::value;
+ };
+
+ template<typename T, typename U>
+ struct LastIsIntegerVector<std::vector<U> T::*> {
+ using value_type = U;
+ static constexpr bool value
+ = std::is_integral<U>::value && !std::is_same<U, bool>::value;
+ };
+
+ template<typename T, typename U>
+ struct LastIsIntegerVector<U T::*> {
+ using value_type = void;
+ static constexpr bool value = false;
+ };
+
+ template<typename T, typename... Args>
+ struct LastIsMap {
+ using key_type = typename LastIsMap<Args...>::key_type;
+ using value_type = typename LastIsMap<Args...>::value_type;
+ static constexpr bool value = LastIsMap<Args...>::value;
+ };
+
+ template<typename T, typename K, typename U>
+ struct LastIsMap<std::shared_ptr<std::map<K, U>> T::*> {
+ using key_type = K;
+ using value_type = U;
+ static constexpr bool value = true;
+ };
+
+ template<typename T, typename K, typename U>
+ struct LastIsMap<std::map<K, U> T::*> {
+ using key_type = K;
+ using value_type = U;
+ static constexpr bool value = true;
+ };
+
+ template<typename T, typename U>
+ struct LastIsMap<U T::*> {
+ using key_type = void;
+ using value_type = void;
+ static constexpr bool value = false;
+ };
+
template<typename T>
static bool is_field_set(const nonstd::optional<T>& field)
{
@@ -434,15 +505,13 @@ struct json_path_handler : public json_path_handler_base {
{
this->add_cb(str_field_cb2);
this->jph_str_cb = [args...](yajlpp_parse_context* ypc,
- const unsigned char* str,
- size_t len) {
- auto obj = ypc->ypc_obj_stack.top();
- auto value_str = std::string((const char*) str, len);
- auto jph = ypc->ypc_current_handler;
+ const string_fragment& value_str) {
+ auto* obj = ypc->ypc_obj_stack.top();
+ const auto* jph = ypc->ypc_current_handler;
jph->validate_string(*ypc, value_str);
json_path_handler::get_field(obj, args...)
- .emplace_back(std::move(value_str));
+ .emplace_back(value_str.to_string());
return 1;
};
@@ -450,10 +519,33 @@ struct json_path_handler : public json_path_handler_base {
}
template<typename... Args,
+ std::enable_if_t<LastIsIntegerVector<Args...>::value, bool> = true>
+ json_path_handler& for_field(Args... args)
+ {
+ this->add_cb(int_field_cb);
+ this->jph_integer_cb
+ = [args...](yajlpp_parse_context* ypc, long long val) {
+ const auto* jph = ypc->ypc_current_handler;
+ auto* obj = ypc->ypc_obj_stack.top();
+
+ if (val < jph->jph_min_value) {
+ jph->report_min_value_error(ypc, val);
+ return 1;
+ }
+
+ json_path_handler::get_field(obj, args...).emplace_back(val);
+
+ return 1;
+ };
+ return *this;
+ }
+
+ template<typename... Args,
std::enable_if_t<LastIsVector<Args...>::value, bool> = true,
std::enable_if_t<
!std::is_same<typename LastIsVector<Args...>::value_type,
- std::string>::value,
+ std::string>::value
+ && !LastIsIntegerVector<Args...>::value,
bool>
= true>
json_path_handler& for_field(Args... args)
@@ -515,16 +607,37 @@ struct json_path_handler : public json_path_handler_base {
{
this->add_cb(str_field_cb2);
this->jph_str_cb = [args...](yajlpp_parse_context* ypc,
- const unsigned char* str,
- size_t len) {
- auto obj = ypc->ypc_obj_stack.top();
+ const string_fragment& value_str) {
+ auto* obj = ypc->ypc_obj_stack.top();
auto key = ypc->get_path_fragment(-1);
json_path_handler::get_field(obj, args...)[key]
- = std::string((const char*) str, len);
+ = value_str.to_string();
return 1;
};
+ this->jph_path_provider =
+ [args...](void* root, std::vector<std::string>& paths_out) {
+ const auto& field = json_path_handler::get_field(root, args...);
+
+ for (const auto& pair : field) {
+ paths_out.emplace_back(pair.first);
+ }
+ };
+ this->jph_field_getter
+ = [args...](void* root,
+ nonstd::optional<std::string> name) -> const void* {
+ const auto& field = json_path_handler::get_field(root, args...);
+ if (!name) {
+ return &field;
+ }
+
+ auto iter = field.find(name.value());
+ if (iter == field.end()) {
+ return nullptr;
+ }
+ return (void*) &iter->second;
+ };
this->jph_gen_callback = [args...](yajlpp_gen_context& ygc,
const json_path_handler_base& jph,
yajl_gen handle) {
@@ -555,6 +668,70 @@ struct json_path_handler : public json_path_handler_base {
}
template<typename... Args,
+ std::enable_if_t<LastIsMap<Args...>::value, bool> = true,
+ std::enable_if_t<
+ std::is_same<intern_string_t,
+ typename LastIsMap<Args...>::key_type>::value,
+ bool>
+ = true>
+ json_path_handler& for_field(Args... args)
+ {
+ this->jph_path_provider =
+ [args...](void* root, std::vector<std::string>& paths_out) {
+ const auto& field = json_path_handler::get_field(root, args...);
+
+ for (const auto& pair : field) {
+ paths_out.emplace_back(std::to_string(pair.first));
+ }
+ };
+ this->jph_obj_provider
+ = [args...](const yajlpp_provider_context& ypc, void* root) {
+ auto& field = json_path_handler::get_field(root, args...);
+
+ return &(field[ypc.get_substr_i(0)]);
+ };
+ return *this;
+ }
+
+ template<
+ typename... Args,
+ std::enable_if_t<LastIsMap<Args...>::value, bool> = true,
+ std::enable_if_t<
+ std::is_same<std::string,
+ typename LastIsMap<Args...>::key_type>::value,
+ bool>
+ = true,
+ std::enable_if_t<
+ !std::is_same<json_any_t,
+ typename LastIsMap<Args...>::value_type>::value
+ && !std::is_same<std::string,
+ typename LastIsMap<Args...>::value_type>::value
+ && !std::is_same<
+ nonstd::optional<std::string>,
+ typename LastIsMap<Args...>::value_type>::value,
+ bool>
+ = true>
+ json_path_handler& for_field(Args... args)
+ {
+ this->jph_path_provider =
+ [args...](void* root, std::vector<std::string>& paths_out) {
+ const auto& field = json_path_handler::get_field(root, args...);
+
+ for (const auto& pair : field) {
+ paths_out.emplace_back(pair.first);
+ }
+ };
+ this->jph_obj_provider
+ = [args...](const yajlpp_provider_context& ypc, void* root) {
+ auto& field = json_path_handler::get_field(root, args...);
+ auto key = ypc.get_substr(0);
+
+ return &(field[key]);
+ };
+ return *this;
+ }
+
+ template<typename... Args,
std::enable_if_t<
LastIs<std::map<std::string, nonstd::optional<std::string>>,
Args...>::value,
@@ -564,13 +741,12 @@ struct json_path_handler : public json_path_handler_base {
{
this->add_cb(str_field_cb2);
this->jph_str_cb = [args...](yajlpp_parse_context* ypc,
- const unsigned char* str,
- size_t len) {
+ const string_fragment& value_str) {
auto obj = ypc->ypc_obj_stack.top();
auto key = ypc->get_path_fragment(-1);
json_path_handler::get_field(obj, args...)[key]
- = std::string((const char*) str, len);
+ = value_str.to_string();
return 1;
};
@@ -642,13 +818,12 @@ struct json_path_handler : public json_path_handler_base {
};
this->add_cb(str_field_cb2);
this->jph_str_cb = [args...](yajlpp_parse_context* ypc,
- const unsigned char* str,
- size_t len) {
+ const string_fragment& value_str) {
auto* obj = ypc->ypc_obj_stack.top();
auto key = ypc->get_path_fragment(-1);
json_path_handler::get_field(obj, args...)[key]
- = std::string((const char*) str, len);
+ = value_str.to_string();
return 1;
};
@@ -691,14 +866,12 @@ struct json_path_handler : public json_path_handler_base {
{
this->add_cb(str_field_cb2);
this->jph_str_cb = [args...](yajlpp_parse_context* ypc,
- const unsigned char* str,
- size_t len) {
- auto obj = ypc->ypc_obj_stack.top();
- auto value_str = std::string((const char*) str, len);
- auto jph = ypc->ypc_current_handler;
+ const string_fragment& value_str) {
+ auto* obj = ypc->ypc_obj_stack.top();
+ const auto* jph = ypc->ypc_current_handler;
jph->validate_string(*ypc, value_str);
- json_path_handler::get_field(obj, args...) = std::move(value_str);
+ json_path_handler::get_field(obj, args...) = value_str.to_string();
return 1;
};
@@ -738,23 +911,22 @@ struct json_path_handler : public json_path_handler_base {
{
this->add_cb(str_field_cb2);
this->jph_str_cb = [args...](yajlpp_parse_context* ypc,
- const unsigned char* str,
- size_t len) {
- auto obj = ypc->ypc_obj_stack.top();
- auto jph = ypc->ypc_current_handler;
+ const string_fragment& value_str) {
+ auto* obj = ypc->ypc_obj_stack.top();
+ const auto* jph = ypc->ypc_current_handler;
date_time_scanner dts;
timeval tv{};
exttm tm;
- if (dts.scan((char*) str, len, nullptr, &tm, tv) == nullptr) {
- ypc->report_error(
- lnav::console::user_message::error(
- attr_line_t("unrecognized timestamp ")
- .append_quoted(
- string_fragment::from_bytes(str, len)))
- .with_snippet(ypc->get_snippet())
- .with_help(jph->get_help_text(ypc)));
+ if (dts.scan(value_str.data(), value_str.length(), nullptr, &tm, tv)
+ == nullptr)
+ {
+ ypc->report_error(lnav::console::user_message::error(
+ attr_line_t("unrecognized timestamp ")
+ .append_quoted(value_str))
+ .with_snippet(ypc->get_snippet())
+ .with_help(jph->get_help_text(ypc)));
} else {
json_path_handler::get_field(obj, args...) = tv;
}
@@ -804,14 +976,20 @@ struct json_path_handler : public json_path_handler_base {
{
this->add_cb(str_field_cb2);
this->jph_str_cb = [args...](yajlpp_parse_context* ypc,
- const unsigned char* str,
- size_t len) {
- auto obj = ypc->ypc_obj_stack.top();
- auto value_str = std::string((const char*) str, len);
- auto jph = ypc->ypc_current_handler;
+ const string_fragment& value_str) {
+ auto* obj = ypc->ypc_obj_stack.top();
+ const auto* jph = ypc->ypc_current_handler;
jph->validate_string(*ypc, value_str);
- json_path_handler::get_field(obj, args...) = std::move(value_str);
+ json_path_handler::get_field(obj, args...) = value_str.to_string();
+
+ return 1;
+ };
+ this->add_cb(null_field_cb);
+ this->jph_null_cb = [args...](yajlpp_parse_context* ypc) {
+ auto* obj = ypc->ypc_obj_stack.top();
+
+ json_path_handler::get_field(obj, args...) = nonstd::nullopt;
return 1;
};
@@ -858,11 +1036,9 @@ struct json_path_handler : public json_path_handler_base {
{
this->add_cb(str_field_cb2);
this->jph_str_cb = [args...](yajlpp_parse_context* ypc,
- const unsigned char* str,
- size_t len) {
- auto obj = ypc->ypc_obj_stack.top();
- auto value_str = std::string((const char*) str, len);
- auto jph = ypc->ypc_current_handler;
+ const string_fragment& value_str) {
+ auto* obj = ypc->ypc_obj_stack.top();
+ const auto* jph = ypc->ypc_current_handler;
jph->validate_string(*ypc, value_str);
auto& field = json_path_handler::get_field(obj, args...);
@@ -870,7 +1046,7 @@ struct json_path_handler : public json_path_handler_base {
field.pp_path = ypc->get_full_path();
field.pp_location.sl_source = ypc->ypc_source;
field.pp_location.sl_line_number = ypc->get_line_number();
- field.pp_value = std::move(value_str);
+ field.pp_value = value_str.to_string();
return 1;
};
@@ -897,6 +1073,10 @@ struct json_path_handler : public json_path_handler_base {
return gen(field.pp_value);
};
+ this->jph_field_getter
+ = [args...](void* root, nonstd::optional<std::string> name) {
+ return (void*) &json_path_handler::get_field(root, args...);
+ };
return *this;
}
@@ -907,11 +1087,9 @@ struct json_path_handler : public json_path_handler_base {
{
this->add_cb(str_field_cb2);
this->jph_str_cb = [args...](yajlpp_parse_context* ypc,
- const unsigned char* str,
- size_t len) {
- auto obj = ypc->ypc_obj_stack.top();
- auto value_str = std::string((const char*) str, len);
- auto jph = ypc->ypc_current_handler;
+ const string_fragment& value_str) {
+ auto* obj = ypc->ypc_obj_stack.top();
+ const auto* jph = ypc->ypc_current_handler;
jph->validate_string(*ypc, value_str);
json_path_handler::get_field(obj, args...)
@@ -945,6 +1123,60 @@ struct json_path_handler : public json_path_handler_base {
return *this;
}
+ template<
+ typename... Args,
+ std::enable_if_t<
+ LastIs<positioned_property<const date::time_zone*>, Args...>::value,
+ bool>
+ = true>
+ json_path_handler& for_field(Args... args)
+ {
+ this->add_cb(str_field_cb2);
+ this->jph_str_cb = [args...](yajlpp_parse_context* ypc,
+ const string_fragment& value_str) {
+ auto* obj = ypc->ypc_obj_stack.top();
+ const auto* jph = ypc->ypc_current_handler;
+
+ try {
+ const auto* tz
+ = date::get_tzdb().locate_zone(value_str.to_string());
+ auto& field = json_path_handler::get_field(obj, args...);
+ field.pp_path = ypc->get_full_path();
+ field.pp_location.sl_source = ypc->ypc_source;
+ field.pp_location.sl_line_number = ypc->get_line_number();
+ field.pp_value = tz;
+ } catch (const std::runtime_error& e) {
+ jph->report_tz_error(ypc, value_str.to_string(), e.what());
+ }
+
+ return 1;
+ };
+ this->jph_gen_callback = [args...](yajlpp_gen_context& ygc,
+ const json_path_handler_base& jph,
+ yajl_gen handle) {
+ const auto& field = json_path_handler::get_field(
+ ygc.ygc_obj_stack.top(), args...);
+
+ if (!ygc.ygc_default_stack.empty()) {
+ const auto& field_def = json_path_handler::get_field(
+ ygc.ygc_default_stack.top(), args...);
+
+ if (field.pp_value == field_def.pp_value) {
+ return yajl_gen_status_ok;
+ }
+ }
+
+ if (ygc.ygc_depth) {
+ yajl_gen_string(handle, jph.jph_property);
+ }
+
+ yajlpp_generator gen(handle);
+
+ return gen(field.pp_value->name());
+ };
+ return *this;
+ }
+
template<typename... Args,
std::enable_if_t<
LastIs<positioned_property<intern_string_t>, Args...>::value,
@@ -954,11 +1186,9 @@ struct json_path_handler : public json_path_handler_base {
{
this->add_cb(str_field_cb2);
this->jph_str_cb = [args...](yajlpp_parse_context* ypc,
- const unsigned char* str,
- size_t len) {
- auto obj = ypc->ypc_obj_stack.top();
- auto value_str = std::string((const char*) str, len);
- auto jph = ypc->ypc_current_handler;
+ const string_fragment& value_str) {
+ auto* obj = ypc->ypc_obj_stack.top();
+ const auto* jph = ypc->ypc_current_handler;
jph->validate_string(*ypc, value_str);
auto& field = json_path_handler::get_field(obj, args...);
@@ -997,7 +1227,7 @@ struct json_path_handler : public json_path_handler_base {
template<typename>
struct int_ {
- typedef int type;
+ using type = int;
};
template<
typename C,
@@ -1009,11 +1239,10 @@ struct json_path_handler : public json_path_handler_base {
json_path_handler& for_field(Args... args, T C::*ptr_arg)
{
this->add_cb(str_field_cb2);
- this->jph_str_cb = [args..., ptr_arg](yajlpp_parse_context* ypc,
- const unsigned char* str,
- size_t len) {
+ this->jph_str_cb = [args..., ptr_arg](
+ yajlpp_parse_context* ypc,
+ const string_fragment& value_frag) {
auto* obj = ypc->ypc_obj_stack.top();
- auto value_frag = string_fragment::from_bytes(str, len);
const auto* jph = ypc->ypc_current_handler;
auto loc = source_location{ypc->ypc_source, ypc->get_line_number()};
@@ -1028,6 +1257,30 @@ struct json_path_handler : public json_path_handler_base {
return 1;
};
+ this->jph_gen_callback
+ = [args..., ptr_arg](yajlpp_gen_context& ygc,
+ const json_path_handler_base& jph,
+ yajl_gen handle) {
+ const auto& field = json_path_handler::get_field(
+ ygc.ygc_obj_stack.top(), args..., ptr_arg);
+
+ if (!ygc.ygc_default_stack.empty()) {
+ const auto& field_def = json_path_handler::get_field(
+ ygc.ygc_default_stack.top(), args..., ptr_arg);
+
+ if (field.pp_value == field_def.pp_value) {
+ return yajl_gen_status_ok;
+ }
+ }
+
+ if (ygc.ygc_depth) {
+ yajl_gen_string(handle, jph.jph_property);
+ }
+
+ yajlpp_generator gen(handle);
+
+ return gen(field.to_string());
+ };
return *this;
}
@@ -1038,7 +1291,7 @@ struct json_path_handler : public json_path_handler_base {
this->add_cb(int_field_cb);
this->jph_integer_cb
= [args...](yajlpp_parse_context* ypc, long long val) {
- auto jph = ypc->ypc_current_handler;
+ const auto* jph = ypc->ypc_current_handler;
auto* obj = ypc->ypc_obj_stack.top();
if (val < jph->jph_min_value) {
@@ -1091,7 +1344,7 @@ struct json_path_handler : public json_path_handler_base {
{
this->add_cb(dbl_field_cb);
this->jph_double_cb = [args...](yajlpp_parse_context* ypc, double val) {
- auto jph = ypc->ypc_current_handler;
+ const auto* jph = ypc->ypc_current_handler;
auto* obj = ypc->ypc_obj_stack.top();
if (val < jph->jph_min_value) {
@@ -1146,18 +1399,16 @@ struct json_path_handler : public json_path_handler_base {
{
this->add_cb(str_field_cb2);
this->jph_str_cb = [args...](yajlpp_parse_context* ypc,
- const unsigned char* str,
- size_t len) {
- auto obj = ypc->ypc_obj_stack.top();
- auto handler = ypc->ypc_current_handler;
- auto parse_res = relative_time::from_str(
- string_fragment::from_bytes(str, len));
+ const string_fragment& value_str) {
+ auto* obj = ypc->ypc_obj_stack.top();
+ const auto* handler = ypc->ypc_current_handler;
+ auto parse_res = relative_time::from_str(value_str);
if (parse_res.isErr()) {
auto parse_error = parse_res.unwrapErr();
- auto value_str = std::string((const char*) str, len);
- handler->report_duration_error(ypc, value_str, parse_error);
+ handler->report_duration_error(
+ ypc, value_str.to_string(), parse_error);
return 1;
}
@@ -1204,18 +1455,16 @@ struct json_path_handler : public json_path_handler_base {
{
this->add_cb(str_field_cb2);
this->jph_str_cb = [args...](yajlpp_parse_context* ypc,
- const unsigned char* str,
- size_t len) {
- auto obj = ypc->ypc_obj_stack.top();
- auto handler = ypc->ypc_current_handler;
- auto res = handler->to_enum_value(string_fragment(str, 0, len));
+ const string_fragment& value_str) {
+ auto* obj = ypc->ypc_obj_stack.top();
+ const auto* handler = ypc->ypc_current_handler;
+ auto res = handler->to_enum_value(value_str);
if (res) {
json_path_handler::get_field(obj, args...)
= (typename LastIsEnum<Args...>::value_type) res.value();
} else {
- handler->report_enum_error(ypc,
- std::string((const char*) str, len));
+ handler->report_enum_error(ypc, value_str.to_string());
}
return 1;
@@ -1325,11 +1574,34 @@ public:
return *this;
}
+ Result<void, std::vector<lnav::console::user_message>> consume(
+ const string_fragment& json)
+ {
+ if (this->yp_parse_context.parse(json) == yajl_status_ok) {
+ if (this->yp_errors.empty()) {
+ return Ok();
+ }
+ }
+
+ return Err(std::move(this->yp_errors));
+ }
+
+ Result<T, std::vector<lnav::console::user_message>> complete()
+ {
+ if (this->yp_parse_context.complete_parse() == yajl_status_ok) {
+ return Ok(std::move(this->yp_obj));
+ }
+
+ return Err(std::move(this->yp_errors));
+ }
+
Result<T, std::vector<lnav::console::user_message>> of(
const string_fragment& json)
{
if (this->yp_parse_context.parse_doc(json)) {
- return Ok(std::move(this->yp_obj));
+ if (this->yp_errors.empty()) {
+ return Ok(std::move(this->yp_obj));
+ }
}
return Err(std::move(this->yp_errors));
@@ -1343,6 +1615,34 @@ private:
};
template<typename T>
+struct typed_json_path_container;
+
+template<typename T>
+struct yajlpp_formatter {
+ const T& yf_obj;
+ const typed_json_path_container<T>& yf_container;
+ yajlpp_gen yf_gen;
+
+ template<typename... Args>
+ yajlpp_formatter<T> with_config(Args... args) &&
+ {
+ yajl_gen_config(this->yf_gen.get_handle(), args...);
+
+ return std::move(*this);
+ }
+
+ std::string to_string() &&
+ {
+ yajlpp_gen_context ygc(this->yf_gen, this->yf_container);
+ ygc.template with_obj(this->yf_obj);
+ ygc.ygc_depth = 1;
+ ygc.gen();
+
+ return this->yf_gen.to_string_fragment().to_string();
+ }
+};
+
+template<typename T>
struct typed_json_path_container : public json_path_container {
typed_json_path_container(std::initializer_list<json_path_handler> children)
: json_path_container(children)
@@ -1366,6 +1666,11 @@ struct typed_json_path_container : public json_path_container {
return yajlpp_parser<T>{src, this};
}
+ yajlpp_formatter<T> formatter_for(const T& obj) const
+ {
+ return yajlpp_formatter<T>{obj, *this};
+ }
+
std::string to_string(const T& obj) const
{
yajlpp_gen gen;