From a14cb70cb715beb714e7b05d8fe631c0df4a7053 Mon Sep 17 00:00:00 2001 From: Lexi Winter Date: Sun, 22 Jun 2025 15:22:23 +0100 Subject: nihil.ucl: add object comparison and std::format support --- nihil.ucl/emit.ccm | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) (limited to 'nihil.ucl/emit.ccm') diff --git a/nihil.ucl/emit.ccm b/nihil.ucl/emit.ccm index 8fdf616..a451f88 100644 --- a/nihil.ucl/emit.ccm +++ b/nihil.ucl/emit.ccm @@ -7,7 +7,9 @@ module; #include #include #include +#include #include +#include #include #include #include @@ -138,4 +140,75 @@ export auto emit(object const &object, emitter format, &functions, nullptr); } +/* + * Basic ostream printer for UCL; default to JSON since it's probably what + * most people expect. + */ +export auto operator<<(std::ostream &stream, object const &o) + -> std::ostream & +{ + emit(o, emitter::json, std::ostream_iterator(stream)); + return stream; +} + } // namespace nihil::ucl + +/* + * Specialisation of std::formatter<> for object. + */ +template<> +struct std::formatter +{ + nihil::ucl::emitter emitter = nihil::ucl::emitter::json; + + template + constexpr ParseContext::iterator parse(ParseContext& ctx) + { + auto it = ctx.begin(); + auto end = ctx.end(); + + while (it != end) { + switch (*it) { + case 'j': + emitter = nihil::ucl::emitter::json; + break; + case 'J': + emitter = nihil::ucl::emitter::compact_json; + break; + case 'c': + emitter = nihil::ucl::emitter::configuration; + break; + case 'y': + emitter = nihil::ucl::emitter::yaml; + break; + case '}': + return it; + default: + throw std::format_error("Invalid format string " + "for UCL object"); + } + + ++it; + } + + return it; + } + + template + FmtContext::iterator format(nihil::ucl::object const &o, + FmtContext& ctx) const + { + // We can't use emit() here since the context iterator is not + // an std::output_iterator. + + auto out = ctx.out(); + + auto ucl_format = static_cast<::ucl_emitter>(emitter); + auto wrapper = nihil::ucl::emit_wrapper(out); + auto functions = wrapper.get_functions(); + + ::ucl_object_emit_full(o.get_ucl_object(), ucl_format, + &functions, nullptr); + return out; + } +}; -- cgit v1.2.3