diff options
| author | Lexi Winter <lexi@le-fay.org> | 2025-06-22 15:22:23 +0100 |
|---|---|---|
| committer | Lexi Winter <lexi@le-fay.org> | 2025-06-22 15:22:23 +0100 |
| commit | a14cb70cb715beb714e7b05d8fe631c0df4a7053 (patch) | |
| tree | a2a2c80ce3e1b4a28c0868a6db5f6b10f5223350 /nihil.ucl/emit.ccm | |
| parent | f41970666675f873d7c1075efd192f22df8d17fe (diff) | |
| download | nihil-a14cb70cb715beb714e7b05d8fe631c0df4a7053.tar.gz nihil-a14cb70cb715beb714e7b05d8fe631c0df4a7053.tar.bz2 | |
nihil.ucl: add object comparison and std::format support
Diffstat (limited to 'nihil.ucl/emit.ccm')
| -rw-r--r-- | nihil.ucl/emit.ccm | 73 |
1 files changed, 73 insertions, 0 deletions
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 <array> #include <charconv> #include <cstdlib> +#include <format> #include <iterator> +#include <iostream> #include <span> #include <string> #include <utility> @@ -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<char>(stream)); + return stream; +} + } // namespace nihil::ucl + +/* + * Specialisation of std::formatter<> for object. + */ +template<> +struct std::formatter<nihil::ucl::object, char> +{ + nihil::ucl::emitter emitter = nihil::ucl::emitter::json; + + template<class ParseContext> + 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<class FmtContext> + 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; + } +}; |
