Explicit adapter to format any reloco-adapted container.
Explicit adapter to format any reloco-adapted container. reloco::vector<int> my_vec = ...; microfmt::format("{}", microfmt::as_collection_view(my_vec));
#pragma once
#include <reloco/binary_heap.hpp>
#include <reloco/boxed_slice.hpp>
#include <reloco/call_location.hpp>
#include <reloco/cell.hpp>
#include <reloco/checked.hpp>
#include <reloco/collection_view.hpp>
#include <reloco/cow.hpp>
#include <reloco/duration.hpp>
#include <reloco/error.hpp>
#include <reloco/external_vector.hpp>
#include <reloco/fixed_int.hpp>
#include <reloco/fixed_point.hpp>
#include <reloco/flat_hash_map.hpp>
#include <reloco/flat_hash_set.hpp>
#include <reloco/flat_map.hpp>
#include <reloco/flat_set.hpp>
#include <reloco/inline_flat_map.hpp>
#include <reloco/inline_flat_set.hpp>
#include <reloco/inline_string.hpp>
#include <reloco/inline_vec_deque.hpp>
#include <reloco/inline_vector.hpp>
#include <reloco/instant.hpp>
#include <reloco/lifetime.hpp>
#include <reloco/lru_cache.hpp>
#include <reloco/masked_pointer.hpp>
#include <reloco/non_zero.hpp>
#include <reloco/obfuscated_string.hpp>
#include <reloco/ordering.hpp>
#include <reloco/outline_vec_deque.hpp>
#include <reloco/outline_vector.hpp>
#include <reloco/packed_bits.hpp>
#include <reloco/rc.hpp>
#include <reloco/ring_buffer.hpp>
#include <reloco/saturating.hpp>
#include <reloco/shared_ptr.hpp>
#include <reloco/sso_flat_map.hpp>
#include <reloco/sso_flat_set.hpp>
#include <reloco/sso_string.hpp>
#include <reloco/sso_vec_deque.hpp>
#include <reloco/sso_vector.hpp>
#include <reloco/string.hpp>
#include <reloco/tree_map.hpp>
#include <reloco/tree_set.hpp>
#include <reloco/type_id.hpp>
#include <reloco/unique_ptr.hpp>
#include <reloco/variant.hpp>
#include <reloco/vec_deque.hpp>
#include <reloco/vector.hpp>
#include <reloco/wrapping.hpp>
namespace detail {
template <typename Formatter, typename Range>
out.put('[');
bool is_first = true;
for (const auto &elem : range) {
if (!is_first) {
out.write(", ");
}
is_first = false;
elem_formatter.format(elem, out);
}
out.put(']');
}
template <typename KeyFormatter, typename ValueFormatter, typename Range>
void format_reloco_map(
const KeyFormatter &key_formatter,
const ValueFormatter &value_formatter,
const Range &range,
const sink &out)
noexcept {
out.put('{');
bool is_first = true;
for (const auto &entry : range) {
if (!is_first) {
out.write(", ");
}
is_first = false;
key_formatter.format(entry.first, out);
out.write(": ");
value_formatter.format(entry.second, out);
}
out.put('}');
}
}
template <
typename T>
struct formatter<
reloco::collection_view<T>> {
using value_type = std::remove_cv_t<T>;
detail::element_formatter<value_type> underlying_formatter;
constexpr void parse(format_parse_context &ctx) noexcept {
underlying_formatter.parse(ctx);
}
void format(
const reloco::collection_view<T> &view,
const sink &out)
const noexcept {
out.put('[');
bool is_first = true;
view.for_each([this, &is_first, &out](const T &elem) noexcept {
if (!is_first) {
out.write(", ");
}
is_first = false;
underlying_formatter.format(elem, out);
});
out.put(']');
}
};
template <typename Container,
std::enable_if_t<reloco::detail::has_collection_view_traits<std::remove_const_t<Container>>::value, int> = 0>
using traits = reloco::collection_view_traits<std::remove_const_t<Container>>;
using element_type = typename traits::element_type;
return reloco::collection_view<const element_type>(c);
}
template <
typename T>
struct formatter<
reloco::detail::mutable_sequence_container_ref<T>> {
using value_type = std::remove_cv_t<T>;
detail::element_formatter<value_type> underlying_formatter;
constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); }
void format(
const reloco::detail::mutable_sequence_container_ref<T> &cref,
const sink &out)
const noexcept {
out.put('[');
bool is_first = true;
cref.for_each([this, &is_first, &out](T &elem) noexcept {
if (!is_first) {
out.write(", ");
}
is_first = false;
underlying_formatter.format(elem, out);
});
out.put(']');
}
};
template <
typename T,
typename Key>
struct formatter<
reloco::detail::mutable_associative_container_ref<T, Key>> {
using value_type = std::remove_cv_t<T>;
using key_type = std::remove_cv_t<Key>;
detail::element_formatter<key_type> key_formatter;
detail::element_formatter<value_type> value_formatter;
constexpr void parse(format_parse_context &ctx) noexcept {
value_formatter.parse(ctx);
}
void format(
const reloco::detail::mutable_associative_container_ref<T, Key> &cref,
const sink &out)
const noexcept {
out.put('{');
bool is_first = true;
cref.for_each([this, &is_first, &out](const Key &key, T &value) noexcept {
if (!is_first) {
out.write(", ");
}
is_first = false;
key_formatter.format(key, out);
out.write(": ");
value_formatter.format(value, out);
});
out.put('}');
}
};
template <
typename T>
struct formatter<
reloco::vector<T>> {
using value_type = std::remove_cv_t<T>;
detail::element_formatter<value_type> underlying_formatter;
constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); }
void format(
const reloco::vector<T> &
vec,
const sink &out)
const noexcept {
out.put('[');
bool is_first = true;
for (
const auto &elem :
vec) {
if (!is_first) {
out.write(", ");
}
is_first = false;
underlying_formatter.format(elem, out);
}
out.put(']');
}
};
template <
typename T,
typename Compare>
struct formatter<
reloco::flat_set<T, Compare>> {
using value_type = std::remove_cv_t<T>;
detail::element_formatter<value_type> underlying_formatter;
constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); }
void format(
const reloco::flat_set<T, Compare> &set,
const sink &out)
const noexcept {
out.put('[');
bool is_first = true;
for (const auto &elem : set) {
if (!is_first) {
out.write(", ");
}
is_first = false;
underlying_formatter.format(elem, out);
}
out.put(']');
}
};
template <
typename CharT,
typename TraitsT>
struct formatter<
reloco::basic_string<CharT, TraitsT>> {
formatter<reloco::basic_string_view<CharT, TraitsT>> underlying_formatter;
constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); }
void format(
const reloco::basic_string<CharT, TraitsT> &str,
const sink &out)
const noexcept {
underlying_formatter.format(str.view(), out);
}
};
template <std::size_t Capacity, typename CharT, typename TraitsT>
struct formatter<
reloco::basic_inline_string<Capacity, CharT, TraitsT>> {
formatter<reloco::basic_string_view<CharT, TraitsT>> underlying_formatter;
constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); }
void format(
const reloco::basic_inline_string<Capacity, CharT, TraitsT> &str,
const sink &out)
const noexcept {
underlying_formatter.format(str.view(), out);
}
};
template <
typename CharT,
typename TraitsT>
struct formatter<
reloco::basic_sso_string<CharT, TraitsT>> {
formatter<reloco::basic_string_view<CharT, TraitsT>> underlying_formatter;
constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); }
void format(
const reloco::basic_sso_string<CharT, TraitsT> &str,
const sink &out)
const noexcept {
underlying_formatter.format(str.view(), out);
}
};
template <std::
size_t N>
struct formatter<
reloco::obfuscated_decrypted_view<N>> {
formatter<microfmt::string_view> underlying_formatter;
constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); }
void format(
const reloco::obfuscated_decrypted_view<N> &val,
const sink &out)
const noexcept {
underlying_formatter.format(val.view(), out);
}
};
template <>
struct formatter<
reloco::obfuscated_string_ref> {
constexpr void parse(format_parse_context &) const noexcept {}
void format(reloco::obfuscated_string_ref val,
const sink &out)
const noexcept {
val.for_each_byte([&out](char ch) noexcept { out.put(ch); });
}
};
template <std::
size_t N>
struct formatter<
reloco::obfuscated_string<N>> {
formatter<reloco::obfuscated_string_ref> underlying_formatter;
constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); }
void format(
const reloco::obfuscated_string<N> &val,
const sink &out)
const noexcept {
underlying_formatter.format(val.as_ref(), out);
}
};
template <
typename T, std::
size_t Capacity>
struct formatter<
reloco::inline_vector<T, Capacity>> {
using value_type = std::remove_cv_t<T>;
detail::element_formatter<value_type> underlying_formatter;
constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); }
void format(
const reloco::inline_vector<T, Capacity> &
vec,
const sink &out)
const noexcept {
out.put('[');
bool is_first = true;
for (
const auto &elem :
vec) {
if (!is_first) {
out.write(", ");
}
is_first = false;
underlying_formatter.format(elem, out);
}
out.put(']');
}
};
template <typename T, std::size_t Capacity, typename Compare>
struct formatter<
reloco::inline_flat_set<T, Capacity, Compare>> {
using value_type = std::remove_cv_t<T>;
detail::element_formatter<value_type> underlying_formatter;
constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); }
void format(
const reloco::inline_flat_set<T, Capacity, Compare> &set,
const sink &out)
const noexcept {
out.put('[');
bool is_first = true;
for (const auto &elem : set) {
if (!is_first) {
out.write(", ");
}
is_first = false;
underlying_formatter.format(elem, out);
}
out.put(']');
}
};
template <
typename Key,
typename Mapped,
typename Compare>
struct formatter<
reloco::flat_map<Key, Mapped, Compare>> {
detail::element_formatter<std::remove_cv_t<Key>> key_formatter;
detail::element_formatter<std::remove_cv_t<Mapped>> value_formatter;
constexpr void parse(format_parse_context &ctx) noexcept {
key_formatter.parse(ctx);
value_formatter.parse(ctx);
}
void format(
const reloco::flat_map<Key, Mapped, Compare> &map,
const sink &out)
const noexcept {
out.put('{');
bool is_first = true;
for (const auto &entry : map) {
if (!is_first) {
out.write(", ");
}
is_first = false;
key_formatter.format(entry.first, out);
out.write(": ");
value_formatter.format(entry.second, out);
}
out.put('}');
}
};
template <typename Key, typename Mapped, std::size_t Capacity, typename Compare>
struct formatter<
reloco::inline_flat_map<Key, Mapped, Capacity, Compare>> {
detail::element_formatter<std::remove_cv_t<Key>> key_formatter;
detail::element_formatter<std::remove_cv_t<Mapped>> value_formatter;
constexpr void parse(format_parse_context &ctx) noexcept {
key_formatter.parse(ctx);
value_formatter.parse(ctx);
}
void format(
const reloco::inline_flat_map<Key, Mapped, Capacity, Compare> &map,
const sink &out)
const noexcept {
out.put('{');
bool is_first = true;
for (const auto &entry : map) {
if (!is_first) {
out.write(", ");
}
is_first = false;
key_formatter.format(entry.first, out);
out.write(": ");
value_formatter.format(entry.second, out);
}
out.put('}');
}
};
template <
typename T>
struct formatter<
reloco::boxed_slice<T>> {
using value_type = std::remove_cv_t<T>;
detail::element_formatter<value_type> underlying_formatter;
constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); }
void format(
const reloco::boxed_slice<T> &slice,
const sink &out)
const noexcept {
out.put('[');
bool is_first = true;
for (const auto &elem : slice) {
if (!is_first) {
out.write(", ");
}
is_first = false;
underlying_formatter.format(elem, out);
}
out.put(']');
}
};
template <
typename T,
typename Compare>
struct formatter<
reloco::binary_heap<T, Compare>> {
using value_type = std::remove_cv_t<T>;
detail::element_formatter<value_type> underlying_formatter;
constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); }
void format(
const reloco::binary_heap<T, Compare> &heap,
const sink &out)
const noexcept {
out.put('[');
bool is_first = true;
for (const auto &elem : heap) {
if (!is_first) {
out.write(", ");
}
is_first = false;
underlying_formatter.format(elem, out);
}
out.put(']');
}
};
template <
typename T, std::
size_t InlineCapacity>
struct formatter<
reloco::sso_vector<T, InlineCapacity>> {
using value_type = std::remove_cv_t<T>;
detail::element_formatter<value_type> underlying_formatter;
constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); }
void format(
const reloco::sso_vector<T, InlineCapacity> &
vec,
const sink &out)
const noexcept {
out.put('[');
bool is_first = true;
for (
const auto &elem :
vec) {
if (!is_first) {
out.write(", ");
}
is_first = false;
underlying_formatter.format(elem, out);
}
out.put(']');
}
};
template <typename T, std::size_t InlineCapacity, typename Compare>
struct formatter<
reloco::sso_flat_set<T, InlineCapacity, Compare>> {
using value_type = std::remove_cv_t<T>;
detail::element_formatter<value_type> underlying_formatter;
constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); }
void format(
const reloco::sso_flat_set<T, InlineCapacity, Compare> &set,
const sink &out)
const noexcept {
out.put('[');
bool is_first = true;
for (const auto &elem : set) {
if (!is_first) {
out.write(", ");
}
is_first = false;
underlying_formatter.format(elem, out);
}
out.put(']');
}
};
template <typename Key, typename Mapped, std::size_t InlineCapacity, typename Compare>
struct formatter<
reloco::sso_flat_map<Key, Mapped, InlineCapacity, Compare>> {
detail::element_formatter<std::remove_cv_t<Key>> key_formatter;
detail::element_formatter<std::remove_cv_t<Mapped>> value_formatter;
constexpr void parse(format_parse_context &ctx) noexcept {
key_formatter.parse(ctx);
value_formatter.parse(ctx);
}
void format(
const reloco::sso_flat_map<Key, Mapped, InlineCapacity, Compare> &map,
const sink &out)
const noexcept {
out.put('{');
bool is_first = true;
for (const auto &entry : map) {
if (!is_first) {
out.write(", ");
}
is_first = false;
key_formatter.format(entry.first, out);
out.write(": ");
value_formatter.format(entry.second, out);
}
out.put('}');
}
};
template <
typename T>
struct formatter<
reloco::outline_vector<T>> {
using value_type = std::remove_cv_t<T>;
detail::element_formatter<value_type> underlying_formatter;
constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); }
void format(
const reloco::outline_vector<T> &
vec,
const sink &out)
const noexcept {
out.put('[');
bool is_first = true;
for (
const auto &elem :
vec) {
if (!is_first) {
out.write(", ");
}
is_first = false;
underlying_formatter.format(elem, out);
}
out.put(']');
}
};
template <
typename T>
struct formatter<
reloco::vec_deque<T>> {
using value_type = std::remove_cv_t<T>;
detail::element_formatter<value_type> underlying_formatter;
constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); }
void format(
const reloco::vec_deque<T> &deque,
const sink &out)
const noexcept {
out.put('[');
const std::size_t n = deque.size();
for (std::size_t i = 0; i < n; ++i) {
if (i != 0) {
out.write(", ");
}
underlying_formatter.format(deque[i], out);
}
out.put(']');
}
};
template <
typename T, std::
size_t InlineCapacity>
struct formatter<
reloco::sso_vec_deque<T, InlineCapacity>> {
using value_type = std::remove_cv_t<T>;
detail::element_formatter<value_type> underlying_formatter;
constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); }
void format(
const reloco::sso_vec_deque<T, InlineCapacity> &deque,
const sink &out)
const noexcept {
out.put('[');
const std::size_t n = deque.size();
for (std::size_t i = 0; i < n; ++i) {
if (i != 0) {
out.write(", ");
}
underlying_formatter.format(deque[i], out);
}
out.put(']');
}
};
template <
typename T, std::
size_t Capacity>
struct formatter<
reloco::inline_vec_deque<T, Capacity>> {
using value_type = std::remove_cv_t<T>;
detail::element_formatter<value_type> underlying_formatter;
constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); }
void format(
const reloco::inline_vec_deque<T, Capacity> &deque,
const sink &out)
const noexcept {
out.put('[');
const std::size_t n = deque.size();
for (std::size_t i = 0; i < n; ++i) {
if (i != 0) {
out.write(", ");
}
underlying_formatter.format(deque[i], out);
}
out.put(']');
}
};
template <
typename T>
struct formatter<
reloco::outline_vec_deque<T>> {
using value_type = std::remove_cv_t<T>;
detail::element_formatter<value_type> underlying_formatter;
constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); }
void format(
const reloco::outline_vec_deque<T> &deque,
const sink &out)
const noexcept {
out.put('[');
const std::size_t n = deque.size();
for (std::size_t i = 0; i < n; ++i) {
if (i != 0) {
out.write(", ");
}
underlying_formatter.format(deque[i], out);
}
out.put(']');
}
};
template <
typename T,
typename Hash,
typename KeyEqual>
struct formatter<
reloco::flat_hash_set<T, Hash, KeyEqual>> {
using value_type = std::remove_cv_t<T>;
detail::element_formatter<value_type> underlying_formatter;
constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); }
void format(
const reloco::flat_hash_set<T, Hash, KeyEqual> &set,
const sink &out)
const noexcept {
out.put('[');
bool is_first = true;
for (const auto &elem : set) {
if (!is_first) {
out.write(", ");
}
is_first = false;
underlying_formatter.format(elem, out);
}
out.put(']');
}
};
template <typename Key, typename Mapped, typename Hash, typename KeyEqual>
struct formatter<
reloco::flat_hash_map<Key, Mapped, Hash, KeyEqual>> {
detail::element_formatter<std::remove_cv_t<Key>> key_formatter;
detail::element_formatter<std::remove_cv_t<Mapped>> value_formatter;
constexpr void parse(format_parse_context &ctx) noexcept {
key_formatter.parse(ctx);
value_formatter.parse(ctx);
}
void format(
const reloco::flat_hash_map<Key, Mapped, Hash, KeyEqual> &map,
const sink &out)
const noexcept {
out.put('{');
bool is_first = true;
for (const auto &entry : map) {
if (!is_first) {
out.write(", ");
}
is_first = false;
key_formatter.format(entry.first, out);
out.write(": ");
value_formatter.format(entry.second, out);
}
out.put('}');
}
};
template <typename T> struct formatter<value_ptr<T>> {
detail::element_formatter<std::remove_cv_t<T>> underlying_formatter;
constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); }
void format(
const value_ptr<T> &ptr,
const sink &out)
const noexcept {
if (!ptr) {
out.write("(null)");
return;
}
underlying_formatter.format(*ptr.get(), out);
}
};
template <typename T> struct formatter<value_ref<T>> {
detail::element_formatter<std::remove_cv_t<T>> underlying_formatter;
constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); }
void format(
const value_ref<T> &ref,
const sink &out)
const noexcept { underlying_formatter.format(*ref, out); }
};
template <
typename T>
struct formatter<
reloco::unique_ptr<T>> {
detail::element_formatter<std::remove_cv_t<T>> underlying_formatter;
constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); }
void format(
const reloco::unique_ptr<T> &ptr,
const sink &out)
const noexcept {
if (!ptr) {
out.write("(null)");
return;
}
underlying_formatter.format(*ptr.get(), out);
}
};
template <
typename T>
struct formatter<
reloco::shared_ptr<T>> {
detail::element_formatter<std::remove_cv_t<T>> underlying_formatter;
constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); }
void format(
const reloco::shared_ptr<T> &ptr,
const sink &out)
const noexcept {
if (!ptr) {
out.write("(null)");
return;
}
underlying_formatter.format(*ptr.get(), out);
}
};
template <
typename T>
struct formatter<
reloco::weak_ptr<T>> {
detail::element_formatter<std::remove_cv_t<T>> underlying_formatter;
constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); }
void format(
const reloco::weak_ptr<T> &weak,
const sink &out)
const noexcept {
auto locked = weak.lock();
if (!locked.has_value()) {
out.write("(expired)");
return;
}
underlying_formatter.format(*locked.value().get(), out);
}
};
template <
typename T>
struct formatter<
reloco::rc<T>> {
detail::element_formatter<std::remove_cv_t<T>> underlying_formatter;
constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); }
void format(
const reloco::rc<T> &ptr,
const sink &out)
const noexcept {
if (!ptr) {
out.write("(null)");
return;
}
underlying_formatter.format(*ptr.get(), out);
}
};
template <
typename T>
struct formatter<
reloco::weak_rc<T>> {
detail::element_formatter<std::remove_cv_t<T>> underlying_formatter;
constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); }
void format(
const reloco::weak_rc<T> &weak,
const sink &out)
const noexcept {
auto locked = weak.lock();
if (!locked.has_value()) {
out.write("(expired)");
return;
}
underlying_formatter.format(*locked.value().get(), out);
}
};
template <
typename T>
struct formatter<
reloco::cow<T>> {
detail::element_formatter<std::remove_cv_t<T>> underlying_formatter;
constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); }
void format(
const reloco::cow<T> &value,
const sink &out)
const noexcept {
underlying_formatter.format(value.get(), out);
}
};
template <
typename T>
struct formatter<
reloco::non_zero<T>> {
detail::element_formatter<T> underlying_formatter;
constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); }
void format(
const reloco::non_zero<T> &value,
const sink &out)
const noexcept {
underlying_formatter.format(value.get(), out);
}
};
template <
typename T>
struct formatter<
reloco::saturating<T>> {
detail::element_formatter<T> underlying_formatter;
constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); }
void format(
const reloco::saturating<T> &value,
const sink &out)
const noexcept {
underlying_formatter.format(value.get(), out);
}
};
template <
typename T>
struct formatter<
reloco::wrapping<T>> {
detail::element_formatter<T> underlying_formatter;
constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); }
void format(
const reloco::wrapping<T> &value,
const sink &out)
const noexcept {
underlying_formatter.format(value.get(), out);
}
};
template <
typename T>
struct formatter<
reloco::checked<T>> {
detail::element_formatter<T> underlying_formatter;
constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); }
void format(
const reloco::checked<T> &value,
const sink &out)
const noexcept {
underlying_formatter.format(value.get(), out);
}
};
template <>
struct formatter<
reloco::duration> {
uint8_t precision{9};
bool show_unit{true};
constexpr void parse(format_parse_context &ctx) noexcept {
for (char c : ctx.spec()) {
if (c == 'm' || c == '3')
precision = 3;
else if (c == 'u' || c == '6')
precision = 6;
else if (c == 'n' || c == '9')
precision = 9;
else if (c == 'r' || c == 'R')
show_unit = false;
}
}
void format(
const reloco::duration &value,
const sink &out)
const noexcept {
detail::format_unsigned<detail::radix::decimal>(out, value.as_secs(), false, 0);
out.put('.');
if (precision == 3) {
detail::format_unsigned<detail::radix::decimal>(out, value.subsec_millis(), false, 3);
} else if (precision == 6) {
detail::format_unsigned<detail::radix::decimal>(out, value.subsec_micros(), false, 6);
} else {
detail::format_unsigned<detail::radix::decimal>(out, value.subsec_nanos(), false, 9);
}
if (show_unit) {
out.put('s');
}
}
};
template <>
struct formatter<
reloco::instant> {
constexpr void parse(format_parse_context &) noexcept {}
RELOCO_BEGIN_UNSAFE_CODE
void format(
const reloco::instant &value,
const sink &out)
const noexcept {
const reloco::duration since_epoch = value.duration_since(reloco::instant());
const std::uint64_t total_secs = since_epoch.as_secs();
const std::uint32_t hours = static_cast<std::uint32_t>(total_secs / 3600);
const std::uint32_t mins = static_cast<std::uint32_t>((total_secs % 3600) / 60);
const std::uint32_t secs = static_cast<std::uint32_t>(total_secs % 60);
detail::format_unsigned<detail::radix::decimal>(out, hours, false, 2);
out.put(':');
detail::format_unsigned<detail::radix::decimal>(out, mins, false, 2);
out.put(':');
detail::format_unsigned<detail::radix::decimal>(out, secs, false, 2);
out.put('.');
detail::format_unsigned<detail::radix::decimal>(out, since_epoch.subsec_millis(), false, 3);
}
};
template <>
struct formatter<
reloco::ordering> {
constexpr void parse(format_parse_context &) noexcept {}
void format(reloco::ordering value,
const sink &out)
const noexcept {
switch (value) {
case reloco::ordering::less:
out.write("less");
return;
case reloco::ordering::equal:
out.write("equal");
return;
case reloco::ordering::greater:
out.write("greater");
return;
}
out.write("unknown");
}
};
template <>
struct formatter<
reloco::type_id> {
constexpr void parse(format_parse_context &) noexcept {}
RELOCO_BEGIN_UNSAFE_CODE
void format(reloco::type_id value,
const sink &out)
const noexcept {
if (!value) {
out.write("<no type>");
return;
}
const char *name = value.name();
if (name == nullptr) {
out.write("<unnamed type>");
return;
}
out.write(name);
}
};
template <>
struct formatter<
reloco::error> {
constexpr void parse(format_parse_context &) noexcept {}
void format(
const reloco::error &val,
const sink &out)
const noexcept {
using reloco::error;
switch (val) {
case error::allocation_failed:
out.write("allocation_failed");
return;
case error::in_place_growth_failed:
out.write("in_place_growth_failed");
return;
case error::unsupported_operation:
out.write("unsupported_operation");
return;
case error::out_of_range:
out.write("out_of_range");
return;
case error::invalid_argument:
out.write("invalid_argument");
return;
case error::already_exists:
out.write("already_exists");
return;
case error::empty_pointer:
out.write("empty_pointer");
return;
case error::pointer_expired:
out.write("pointer_expired");
return;
case error::no_owner:
out.write("no_owner");
return;
case error::out_of_bounds:
out.write("out_of_bounds");
return;
case error::deadlock:
out.write("deadlock");
return;
case error::invalid_owner:
out.write("invalid_owner");
return;
case error::still_locked:
out.write("still_locked");
return;
case error::not_locked:
out.write("not_locked");
return;
case error::timed_out:
out.write("timed_out");
return;
case error::try_again:
out.write("try_again");
return;
case error::not_initialized:
out.write("not_initialized");
return;
case error::container_empty:
out.write("container_empty");
return;
case error::not_found:
out.write("not_found");
return;
case error::integer_overflow:
out.write("integer_overflow");
return;
case error::division_by_zero:
out.write("division_by_zero");
return;
case error::capacity_exceeded:
out.write("capacity_exceeded");
return;
case error::invalid_state:
out.write("invalid_state");
return;
case error::permission_denied:
out.write("permission_denied");
return;
case error::interrupted:
out.write("interrupted");
return;
case error::resource_exhausted:
out.write("resource_exhausted");
return;
case error::busy:
out.write("busy");
return;
case error::io_error:
out.write("io_error");
return;
case error::operation_canceled:
out.write("operation_canceled");
return;
case error::security_violation:
out.write("security_violation");
return;
case error::page_fault:
out.write("page_fault");
return;
}
}
};
template <
typename T,
typename Compare>
struct formatter<
reloco::tree_set<T, Compare>> {
detail::element_formatter<std::remove_cv_t<T>> underlying_formatter;
constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); }
void format(
const reloco::tree_set<T, Compare> &set,
const sink &out)
const noexcept {
}
};
template <
typename Key,
typename Mapped,
typename Compare>
struct formatter<
reloco::tree_map<Key, Mapped, Compare>> {
detail::element_formatter<std::remove_cv_t<Key>> key_formatter;
detail::element_formatter<std::remove_cv_t<Mapped>> value_formatter;
constexpr void parse(format_parse_context &ctx) noexcept {
key_formatter.parse(ctx);
value_formatter.parse(ctx);
}
void format(
const reloco::tree_map<Key, Mapped, Compare> &map,
const sink &out)
const noexcept {
}
};
template <typename Key, typename Mapped, typename Hash, typename KeyEqual>
struct formatter<
reloco::lru_cache<Key, Mapped, Hash, KeyEqual>> {
detail::element_formatter<std::remove_cv_t<Key>> key_formatter;
detail::element_formatter<std::remove_cv_t<Mapped>> value_formatter;
constexpr void parse(format_parse_context &ctx) noexcept {
key_formatter.parse(ctx);
value_formatter.parse(ctx);
}
void format(
const reloco::lru_cache<Key, Mapped, Hash, KeyEqual> &cache,
const sink &out)
const noexcept {
}
};
template <
typename T>
struct formatter<
reloco::external_vector<T>> {
detail::element_formatter<std::remove_cv_t<T>> underlying_formatter;
constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); }
void format(
const reloco::external_vector<T> &
vec,
const sink &out)
const noexcept {
}
};
#define MICROFMT_RELOCO_RING_FORMATTER(TEMPLATE_HEAD, TYPE) \
TEMPLATE_HEAD struct formatter<TYPE> { \
detail::element_formatter<std::remove_cv_t<T>> underlying_formatter; \
constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); } \
void format(const TYPE &ring, const sink &out) const noexcept { \
detail::format_reloco_sequence(underlying_formatter, ring, out); \
} \
}
#define MICROFMT_COMMA ,
reloco::inline_ring_buffer<T MICROFMT_COMMA N>);
reloco::sso_ring_buffer<T MICROFMT_COMMA N>);
#undef MICROFMT_COMMA
#undef MICROFMT_RELOCO_RING_FORMATTER
template <
typename... Ts>
struct formatter<
reloco::variant<Ts...>> {
formatter<std::variant<Ts...>> base_formatter;
constexpr void parse(format_parse_context &ctx) noexcept { base_formatter.parse(ctx); }
void format(
const reloco::variant<Ts...> &var,
const sink &out)
const noexcept {
base_formatter.format(static_cast<const std::variant<Ts...> &>(var), out);
}
};
template <
typename T>
struct formatter<
reloco::cell<T>> {
detail::element_formatter<std::remove_cv_t<T>> underlying_formatter;
constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); }
void format(
const reloco::cell<T> &c,
const sink &out)
const noexcept { underlying_formatter.format(c.get(), out); }
};
template <>
struct formatter<
reloco::call_location> {
constexpr void parse(format_parse_context &) noexcept {}
void format(
const reloco::call_location &loc,
const sink &out)
const noexcept {
out.write(loc.file != nullptr ? microfmt::string_view(loc.file) : microfmt::string_view("<unknown>"));
out.put(':');
}
};
template <>
struct formatter<
reloco::call_location_ref> {
constexpr void parse(format_parse_context &) noexcept {}
void format(
const reloco::call_location_ref &ref,
const sink &out)
const noexcept {
if (!ref.has_value()) {
out.write("<no location>");
return;
}
formatter<reloco::call_location>{}.format(ref.value(), out);
}
};
template <
typename T>
struct formatter<
reloco::packed_bits<T>> {
formatter<T> underlying_formatter;
constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); }
void format(
const reloco::packed_bits<T> &
bits,
const sink &out)
const noexcept {
underlying_formatter.format(
bits.value(), out);
}
};
template <
typename T,
typename AuthPolicy>
struct formatter<
reloco::masked_pointer<T, AuthPolicy>> {
constexpr void parse(format_parse_context &) noexcept {}
RELOCO_BEGIN_UNSAFE_CODE
void format(
const reloco::masked_pointer<T, AuthPolicy> &ptr,
const sink &out)
const noexcept {
const void *raw = static_cast<const void *>(ptr.get());
if (raw == nullptr) {
out.write("(null)");
return;
}
}
};
template <typename Rep, unsigned FracBits>
struct formatter<
reloco::fixed_point<Rep, FracBits>, std::enable_if_t<std::is_arithmetic_v<Rep>>> {
formatter<double> underlying_formatter;
constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); }
void format(
const reloco::fixed_point<Rep, FracBits> &value,
const sink &out)
const noexcept {
underlying_formatter.format(static_cast<double>(value.raw()) / static_cast<double>(Rep{1} << FracBits), out);
}
};
template <std::size_t N, bool Signed>
struct formatter<
reloco::detail::wide_int<N, Signed>> : detail::int_formatter_specs {
RELOCO_BEGIN_UNSAFE_CODE
void format(
const reloco::detail::wide_int<N, Signed> &val,
const sink &out)
const noexcept {
RELOCO_BEGIN_UNSAFE_BUFFER_USAGE;
constexpr std::size_t limb_count = N / 32;
constexpr std::size_t buf_size = N / 3 + 2;
std::uint32_t mag[limb_count];
const bool negative = val.is_negative();
const reloco::detail::wide_int<N, Signed> abs_val = negative ? -val : val;
for (std::size_t i = 0; i < limb_count; ++i) {
mag[i] = abs_val.limb(i);
}
char buffer[buf_size];
char *end = buffer + buf_size;
char *start = end;
microfmt::string_view prefix{};
if (flags.is_hex) {
const char *lut = flags.uppercase ? "0123456789ABCDEF" : "0123456789abcdef";
for (std::size_t i = 0; i < limb_count; ++i) {
std::uint32_t limb = mag[i];
for (int nibble = 0; nibble < 8; ++nibble) {
*--start = lut[limb & 0xFU];
limb >>= 4;
}
}
while (start < end - 1 && *start == '0') {
++start;
}
if (flags.alt_form) {
prefix = flags.uppercase ? microfmt::string_view("0X") : microfmt::string_view("0x");
}
} else {
std::size_t used = limb_count;
do {
std::uint64_t rem = 0;
for (std::size_t i = used; i-- > 0;) {
const std::uint64_t cur = (rem << 32) | mag[i];
mag[i] = static_cast<std::uint32_t>(cur / 1000000000U);
rem = cur % 1000000000U;
}
while (used > 0 && mag[used - 1] == 0) {
--used;
}
auto chunk = static_cast<std::uint32_t>(rem);
for (int digit = 0; digit < 9 && (used > 0 || chunk != 0 || digit == 0); ++digit) {
*--start = static_cast<char>('0' + chunk % 10U);
chunk /= 10U;
}
} while (used > 0);
}
flags.zero_pad);
RELOCO_END_UNSAFE_BUFFER_USAGE;
}
};
#if defined(__SIZEOF_INT128__)
RELOCO_BEGIN_SUPPRESS_PEDANTIC_INT128
template <typename T>
struct formatter<T, std::enable_if_t<reloco::detail::is_builtin_int128_v<T> && !std::is_integral_v<T>>>
: formatter<reloco::detail::wide_int<128, std::is_same_v<T, __int128>>> {
void format(T val,
const sink &out)
const noexcept {
constexpr bool is_signed = std::is_same_v<T, __int128>;
formatter<reloco::detail::wide_int<128, is_signed>>
::format(reloco::detail::wide_int<128, is_signed>(val), out);
}
};
RELOCO_END_SUPPRESS_PEDANTIC_INT128
#endif
}
Floating-point formatting backed by printf-style specifiers.
Core formatting primitives, sinks, and customization point.
void format_reloco_map(const KeyFormatter &key_formatter, const ValueFormatter &value_formatter, const Range &range, const sink &out) noexcept
Definition reloco.hpp:74
RELOCO_BEGIN_UNSAFE_CODE RELOCO_ALWAYS_INLINE void emit_formatted_int(const sink &out, const char *digits, size_t digits_len, bool is_negative, microfmt::string_view prefix, uint8_t width, bool zero_pad) noexcept
Definition microfmt.hpp:1124
void format_reloco_sequence(const Formatter &elem_formatter, const Range &range, const sink &out) noexcept
Definition reloco.hpp:60
reloco::sink sink
Type-erased, zero-allocation output sink.
Definition microfmt.hpp:46
RELOCO_CONSTEXPR20 void format_to(const sink &out, microfmt::string_view fmt, const Args &...args) noexcept
Definition microfmt.hpp:1766
constexpr auto as_collection_view(Container &c) noexcept
Definition reloco.hpp:141
constexpr bitfield_view bits(uint32_t raw_val, span< const bit_field > fields, bool show_raw_hex=true, microfmt::string_view sep=" | ") noexcept
Definition bitfield.hpp:36
constexpr auto vec(const T(&arr)[N]) noexcept
Definition math.hpp:28
RELOCO_CONSTEXPR20 buffer_sink< N > format(microfmt::string_view fmt, const Args &...args) noexcept
Definition microfmt.hpp:1786
RELOCO_END_UNSAFE_CODE
Definition remote_object.hpp:132
Definition debug_float.hpp:36
`std::variant` and non-owning variant view formatting.