microfmt
Zero-allocation C++ formatting for constrained environments
Loading...
Searching...
No Matches
reloco.hpp
Go to the documentation of this file.
1#pragma once
5#include <reloco/binary_heap.hpp>
6#include <reloco/boxed_slice.hpp>
7#include <reloco/call_location.hpp>
8#include <reloco/cell.hpp>
9#include <reloco/checked.hpp>
10#include <reloco/collection_view.hpp>
11#include <reloco/cow.hpp>
12#include <reloco/duration.hpp>
13#include <reloco/error.hpp>
14#include <reloco/external_vector.hpp>
15#include <reloco/fixed_int.hpp>
16#include <reloco/fixed_point.hpp>
17#include <reloco/flat_hash_map.hpp>
18#include <reloco/flat_hash_set.hpp>
19#include <reloco/flat_map.hpp>
20#include <reloco/flat_set.hpp>
21#include <reloco/inline_flat_map.hpp>
22#include <reloco/inline_flat_set.hpp>
23#include <reloco/inline_string.hpp>
24#include <reloco/inline_vec_deque.hpp>
25#include <reloco/inline_vector.hpp>
26#include <reloco/instant.hpp>
27#include <reloco/lifetime.hpp>
28#include <reloco/lru_cache.hpp>
29#include <reloco/masked_pointer.hpp>
30#include <reloco/non_zero.hpp>
31#include <reloco/obfuscated_string.hpp>
32#include <reloco/ordering.hpp>
33#include <reloco/outline_vec_deque.hpp>
34#include <reloco/outline_vector.hpp>
35#include <reloco/packed_bits.hpp>
36#include <reloco/rc.hpp>
37#include <reloco/ring_buffer.hpp>
38#include <reloco/saturating.hpp>
39#include <reloco/shared_ptr.hpp>
40#include <reloco/sso_flat_map.hpp>
41#include <reloco/sso_flat_set.hpp>
42#include <reloco/sso_string.hpp>
43#include <reloco/sso_vec_deque.hpp>
44#include <reloco/sso_vector.hpp>
45#include <reloco/string.hpp>
46#include <reloco/tree_map.hpp>
47#include <reloco/tree_set.hpp>
48#include <reloco/type_id.hpp>
49#include <reloco/unique_ptr.hpp>
50#include <reloco/variant.hpp>
51#include <reloco/vec_deque.hpp>
52#include <reloco/vector.hpp>
53#include <reloco/wrapping.hpp>
54
55namespace microfmt {
56
57namespace detail {
58
59template <typename Formatter, typename Range>
60void format_reloco_sequence(const Formatter &elem_formatter, const Range &range, const sink &out) noexcept {
61 out.put('[');
62 bool is_first = true;
63 for (const auto &elem : range) {
64 if (!is_first) {
65 out.write(", ");
66 }
67 is_first = false;
68 elem_formatter.format(elem, out);
69 }
70 out.put(']');
71}
72
73template <typename KeyFormatter, typename ValueFormatter, typename Range>
74void format_reloco_map(const KeyFormatter &key_formatter, const ValueFormatter &value_formatter, const Range &range,
75 const sink &out) noexcept {
76 out.put('{');
77 bool is_first = true;
78 for (const auto &entry : range) {
79 if (!is_first) {
80 out.write(", ");
81 }
82 is_first = false;
83 key_formatter.format(entry.first, out);
84 out.write(": ");
85 value_formatter.format(entry.second, out);
86 }
87 out.put('}');
88}
89
90} // namespace detail
91
100template <typename T> struct formatter<reloco::collection_view<T>> {
101 using value_type = std::remove_cv_t<T>;
102
103 // Holds the parsed state (e.g., width, hex flags) for the underlying elements
105
106 constexpr void parse(format_parse_context &ctx) noexcept {
107 // Delegate parsing of the format specifier to the element formatter.
108 // e.g., "{:04x}" parsed here will configure `underlying_formatter` to pad hex.
109 underlying_formatter.parse(ctx);
110 }
111
112 void format(const reloco::collection_view<T> &view, const sink &out) const noexcept {
113 out.put('[');
114
115 bool is_first = true;
116
117 // Type-erased visit across the container's elements
118 view.for_each([this, &is_first, &out](const T &elem) noexcept {
119 if (!is_first) {
120 out.write(", ");
121 }
122 is_first = false;
123
124 // Delegate formatting to the pre-configured element formatter
125 underlying_formatter.format(elem, out);
126 });
127
128 out.put(']');
129 }
130};
131
139template <typename Container,
140 std::enable_if_t<reloco::detail::has_collection_view_traits<std::remove_const_t<Container>>::value, int> = 0>
141constexpr auto as_collection_view(Container &c) noexcept {
142 using traits = reloco::collection_view_traits<std::remove_const_t<Container>>;
143 using element_type = typename traits::element_type;
144
145 // Force a const view for formatting so it can safely bind to both const and non-const containers
146 return reloco::collection_view<const element_type>(c);
147}
148
155template <typename T> struct formatter<reloco::detail::mutable_sequence_container_ref<T>> {
156 using value_type = std::remove_cv_t<T>;
157
159
160 constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); }
161
162 void format(const reloco::detail::mutable_sequence_container_ref<T> &cref, const sink &out) const noexcept {
163 out.put('[');
164 bool is_first = true;
165
166 cref.for_each([this, &is_first, &out](T &elem) noexcept {
167 if (!is_first) {
168 out.write(", ");
169 }
170 is_first = false;
171 underlying_formatter.format(elem, out);
172 });
173
174 out.put(']');
175 }
176};
177
185template <typename T, typename Key> struct formatter<reloco::detail::mutable_associative_container_ref<T, Key>> {
186 using value_type = std::remove_cv_t<T>;
187 using key_type = std::remove_cv_t<Key>;
188
191
192 constexpr void parse(format_parse_context &ctx) noexcept {
193 // Apply parsed specs (like hex formatting) to the values
194 value_formatter.parse(ctx);
195 }
196
197 void format(const reloco::detail::mutable_associative_container_ref<T, Key> &cref, const sink &out) const noexcept {
198 out.put('{');
199 bool is_first = true;
200
201 cref.for_each([this, &is_first, &out](const Key &key, T &value) noexcept {
202 if (!is_first) {
203 out.write(", ");
204 }
205 is_first = false;
206
207 key_formatter.format(key, out);
208 out.write(": ");
209 value_formatter.format(value, out);
210 });
211
212 out.put('}');
213 }
214};
215
216// ============================================================================
217// Direct Formatters for Concrete reloco Containers
218// ============================================================================
219//
220// The `collection_view`/`container_ref` formatters above are a type-erased
221// *fallback* -- they let one formatter instantiation serve any adapted
222// container, at the cost of an explicit `as_collection_view(...)` call at
223// each use site. The formatters below are the "normal" path: they let
224// `microfmt::format("{}", my_vec)` work directly on `reloco::vector<T>` and
225// friends, with no wrapper call needed.
226
233template <typename T> struct formatter<reloco::vector<T>> {
234 using value_type = std::remove_cv_t<T>;
235
237
238 constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); }
239
240 void format(const reloco::vector<T> &vec, const sink &out) const noexcept {
241 out.put('[');
242 bool is_first = true;
243 for (const auto &elem : vec) {
244 if (!is_first) {
245 out.write(", ");
246 }
247 is_first = false;
248 underlying_formatter.format(elem, out);
249 }
250 out.put(']');
251 }
252};
253
260template <typename T, typename Compare> struct formatter<reloco::flat_set<T, Compare>> {
261 using value_type = std::remove_cv_t<T>;
262
264
265 constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); }
266
267 void format(const reloco::flat_set<T, Compare> &set, const sink &out) const noexcept {
268 out.put('[');
269 bool is_first = true;
270 for (const auto &elem : set) {
271 if (!is_first) {
272 out.write(", ");
273 }
274 is_first = false;
275 underlying_formatter.format(elem, out);
276 }
277 out.put(']');
278 }
279};
280
287template <typename CharT, typename TraitsT> struct formatter<reloco::basic_string<CharT, TraitsT>> {
289
290 constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); }
291
292 void format(const reloco::basic_string<CharT, TraitsT> &str, const sink &out) const noexcept {
293 underlying_formatter.format(str.view(), out);
294 }
295};
296
303template <std::size_t Capacity, typename CharT, typename TraitsT>
304struct formatter<reloco::basic_inline_string<Capacity, CharT, TraitsT>> {
306
307 constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); }
308
309 void format(const reloco::basic_inline_string<Capacity, CharT, TraitsT> &str, const sink &out) const noexcept {
310 underlying_formatter.format(str.view(), out);
311 }
312};
313
320template <typename CharT, typename TraitsT> struct formatter<reloco::basic_sso_string<CharT, TraitsT>> {
322
323 constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); }
324
325 void format(const reloco::basic_sso_string<CharT, TraitsT> &str, const sink &out) const noexcept {
326 underlying_formatter.format(str.view(), out);
327 }
328};
329
342template <std::size_t N> struct formatter<reloco::obfuscated_decrypted_view<N>> {
344
345 constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); }
346
347 void format(const reloco::obfuscated_decrypted_view<N> &val, const sink &out) const noexcept {
348 underlying_formatter.format(val.view(), out);
349 }
350};
351
372template <> struct formatter<reloco::obfuscated_string_ref> {
373 constexpr void parse(format_parse_context &) const noexcept {}
374
375 void format(reloco::obfuscated_string_ref val, const sink &out) const noexcept {
376 val.for_each_byte([&out](char ch) noexcept { out.put(ch); });
377 }
378};
379
389template <std::size_t N> struct formatter<reloco::obfuscated_string<N>> {
391
392 constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); }
393
394 void format(const reloco::obfuscated_string<N> &val, const sink &out) const noexcept {
395 underlying_formatter.format(val.as_ref(), out);
396 }
397};
398
405template <typename T, std::size_t Capacity> struct formatter<reloco::inline_vector<T, Capacity>> {
406 using value_type = std::remove_cv_t<T>;
407
409
410 constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); }
411
412 void format(const reloco::inline_vector<T, Capacity> &vec, const sink &out) const noexcept {
413 out.put('[');
414 bool is_first = true;
415 for (const auto &elem : vec) {
416 if (!is_first) {
417 out.write(", ");
418 }
419 is_first = false;
420 underlying_formatter.format(elem, out);
421 }
422 out.put(']');
423 }
424};
425
432template <typename T, std::size_t Capacity, typename Compare>
433struct formatter<reloco::inline_flat_set<T, Capacity, Compare>> {
434 using value_type = std::remove_cv_t<T>;
435
437
438 constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); }
439
440 void format(const reloco::inline_flat_set<T, Capacity, Compare> &set, const sink &out) const noexcept {
441 out.put('[');
442 bool is_first = true;
443 for (const auto &elem : set) {
444 if (!is_first) {
445 out.write(", ");
446 }
447 is_first = false;
448 underlying_formatter.format(elem, out);
449 }
450 out.put(']');
451 }
452};
453
460template <typename Key, typename Mapped, typename Compare> struct formatter<reloco::flat_map<Key, Mapped, Compare>> {
463
464 constexpr void parse(format_parse_context &ctx) noexcept {
465 key_formatter.parse(ctx);
466 value_formatter.parse(ctx);
467 }
468
469 void format(const reloco::flat_map<Key, Mapped, Compare> &map, const sink &out) const noexcept {
470 out.put('{');
471 bool is_first = true;
472 for (const auto &entry : map) {
473 if (!is_first) {
474 out.write(", ");
475 }
476 is_first = false;
477
478 key_formatter.format(entry.first, out);
479 out.write(": ");
480 value_formatter.format(entry.second, out);
481 }
482 out.put('}');
483 }
484};
485
493template <typename Key, typename Mapped, std::size_t Capacity, typename Compare>
494struct formatter<reloco::inline_flat_map<Key, Mapped, Capacity, Compare>> {
497
498 constexpr void parse(format_parse_context &ctx) noexcept {
499 key_formatter.parse(ctx);
500 value_formatter.parse(ctx);
501 }
502
503 void format(const reloco::inline_flat_map<Key, Mapped, Capacity, Compare> &map, const sink &out) const noexcept {
504 out.put('{');
505 bool is_first = true;
506 for (const auto &entry : map) {
507 if (!is_first) {
508 out.write(", ");
509 }
510 is_first = false;
511
512 key_formatter.format(entry.first, out);
513 out.write(": ");
514 value_formatter.format(entry.second, out);
515 }
516 out.put('}');
517 }
518};
519
526template <typename T> struct formatter<reloco::boxed_slice<T>> {
527 using value_type = std::remove_cv_t<T>;
528
530
531 constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); }
532
533 void format(const reloco::boxed_slice<T> &slice, const sink &out) const noexcept {
534 out.put('[');
535 bool is_first = true;
536 for (const auto &elem : slice) {
537 if (!is_first) {
538 out.write(", ");
539 }
540 is_first = false;
541 underlying_formatter.format(elem, out);
542 }
543 out.put(']');
544 }
545};
546
555template <typename T, typename Compare> struct formatter<reloco::binary_heap<T, Compare>> {
556 using value_type = std::remove_cv_t<T>;
557
559
560 constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); }
561
562 void format(const reloco::binary_heap<T, Compare> &heap, const sink &out) const noexcept {
563 out.put('[');
564 bool is_first = true;
565 for (const auto &elem : heap) {
566 if (!is_first) {
567 out.write(", ");
568 }
569 is_first = false;
570 underlying_formatter.format(elem, out);
571 }
572 out.put(']');
573 }
574};
575
582template <typename T, std::size_t InlineCapacity> struct formatter<reloco::sso_vector<T, InlineCapacity>> {
583 using value_type = std::remove_cv_t<T>;
584
586
587 constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); }
588
589 void format(const reloco::sso_vector<T, InlineCapacity> &vec, const sink &out) const noexcept {
590 out.put('[');
591 bool is_first = true;
592 for (const auto &elem : vec) {
593 if (!is_first) {
594 out.write(", ");
595 }
596 is_first = false;
597 underlying_formatter.format(elem, out);
598 }
599 out.put(']');
600 }
601};
602
609template <typename T, std::size_t InlineCapacity, typename Compare>
610struct formatter<reloco::sso_flat_set<T, InlineCapacity, Compare>> {
611 using value_type = std::remove_cv_t<T>;
612
614
615 constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); }
616
617 void format(const reloco::sso_flat_set<T, InlineCapacity, Compare> &set, const sink &out) const noexcept {
618 out.put('[');
619 bool is_first = true;
620 for (const auto &elem : set) {
621 if (!is_first) {
622 out.write(", ");
623 }
624 is_first = false;
625 underlying_formatter.format(elem, out);
626 }
627 out.put(']');
628 }
629};
630
638template <typename Key, typename Mapped, std::size_t InlineCapacity, typename Compare>
639struct formatter<reloco::sso_flat_map<Key, Mapped, InlineCapacity, Compare>> {
642
643 constexpr void parse(format_parse_context &ctx) noexcept {
644 key_formatter.parse(ctx);
645 value_formatter.parse(ctx);
646 }
647
648 void format(const reloco::sso_flat_map<Key, Mapped, InlineCapacity, Compare> &map, const sink &out) const noexcept {
649 out.put('{');
650 bool is_first = true;
651 for (const auto &entry : map) {
652 if (!is_first) {
653 out.write(", ");
654 }
655 is_first = false;
656
657 key_formatter.format(entry.first, out);
658 out.write(": ");
659 value_formatter.format(entry.second, out);
660 }
661 out.put('}');
662 }
663};
664
671template <typename T> struct formatter<reloco::outline_vector<T>> {
672 using value_type = std::remove_cv_t<T>;
673
675
676 constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); }
677
678 void format(const reloco::outline_vector<T> &vec, const sink &out) const noexcept {
679 out.put('[');
680 bool is_first = true;
681 for (const auto &elem : vec) {
682 if (!is_first) {
683 out.write(", ");
684 }
685 is_first = false;
686 underlying_formatter.format(elem, out);
687 }
688 out.put(']');
689 }
690};
691
701template <typename T> struct formatter<reloco::vec_deque<T>> {
702 using value_type = std::remove_cv_t<T>;
703
705
706 constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); }
707
708 void format(const reloco::vec_deque<T> &deque, const sink &out) const noexcept {
709 out.put('[');
710 const std::size_t n = deque.size();
711 for (std::size_t i = 0; i < n; ++i) {
712 if (i != 0) {
713 out.write(", ");
714 }
715 underlying_formatter.format(deque[i], out);
716 }
717 out.put(']');
718 }
719};
720
728template <typename T, std::size_t InlineCapacity> struct formatter<reloco::sso_vec_deque<T, InlineCapacity>> {
729 using value_type = std::remove_cv_t<T>;
730
732
733 constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); }
734
735 void format(const reloco::sso_vec_deque<T, InlineCapacity> &deque, const sink &out) const noexcept {
736 out.put('[');
737 const std::size_t n = deque.size();
738 for (std::size_t i = 0; i < n; ++i) {
739 if (i != 0) {
740 out.write(", ");
741 }
742 underlying_formatter.format(deque[i], out);
743 }
744 out.put(']');
745 }
746};
747
755template <typename T, std::size_t Capacity> struct formatter<reloco::inline_vec_deque<T, Capacity>> {
756 using value_type = std::remove_cv_t<T>;
757
759
760 constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); }
761
762 void format(const reloco::inline_vec_deque<T, Capacity> &deque, const sink &out) const noexcept {
763 out.put('[');
764 const std::size_t n = deque.size();
765 for (std::size_t i = 0; i < n; ++i) {
766 if (i != 0) {
767 out.write(", ");
768 }
769 underlying_formatter.format(deque[i], out);
770 }
771 out.put(']');
772 }
773};
774
782template <typename T> struct formatter<reloco::outline_vec_deque<T>> {
783 using value_type = std::remove_cv_t<T>;
784
786
787 constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); }
788
789 void format(const reloco::outline_vec_deque<T> &deque, const sink &out) const noexcept {
790 out.put('[');
791 const std::size_t n = deque.size();
792 for (std::size_t i = 0; i < n; ++i) {
793 if (i != 0) {
794 out.write(", ");
795 }
796 underlying_formatter.format(deque[i], out);
797 }
798 out.put(']');
799 }
800};
801
811template <typename T, typename Hash, typename KeyEqual> struct formatter<reloco::flat_hash_set<T, Hash, KeyEqual>> {
812 using value_type = std::remove_cv_t<T>;
813
815
816 constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); }
817
818 void format(const reloco::flat_hash_set<T, Hash, KeyEqual> &set, const sink &out) const noexcept {
819 out.put('[');
820 bool is_first = true;
821 for (const auto &elem : set) {
822 if (!is_first) {
823 out.write(", ");
824 }
825 is_first = false;
826 underlying_formatter.format(elem, out);
827 }
828 out.put(']');
829 }
830};
831
840template <typename Key, typename Mapped, typename Hash, typename KeyEqual>
841struct formatter<reloco::flat_hash_map<Key, Mapped, Hash, KeyEqual>> {
844
845 constexpr void parse(format_parse_context &ctx) noexcept {
846 key_formatter.parse(ctx);
847 value_formatter.parse(ctx);
848 }
849
850 void format(const reloco::flat_hash_map<Key, Mapped, Hash, KeyEqual> &map, const sink &out) const noexcept {
851 out.put('{');
852 bool is_first = true;
853 for (const auto &entry : map) {
854 if (!is_first) {
855 out.write(", ");
856 }
857 is_first = false;
858
859 key_formatter.format(entry.first, out);
860 out.write(": ");
861 value_formatter.format(entry.second, out);
862 }
863 out.put('}');
864 }
865};
866
867// ============================================================================
868// Direct Formatters for reloco Pointer/Borrow Wrappers
869// ============================================================================
870//
871// These format transparently: the pointee's value, not the wrapper's address
872// (unlike the GDB pretty printers, which show addresses -- see
873// docs/gdb-pretty-printers.md -- since debugging memory layout and logging a
874// value are different goals). Each requires `formatter<T>` for the pointee
875// type `T`.
876
884template <typename T> struct formatter<value_ptr<T>> {
886
887 constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); }
888
889 void format(const value_ptr<T> &ptr, const sink &out) const noexcept {
890 if (!ptr) {
891 out.write("(null)");
892 return;
893 }
894 underlying_formatter.format(*ptr.get(), out);
895 }
896};
897
905template <typename T> struct formatter<value_ref<T>> {
907
908 constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); }
909
910 void format(const value_ref<T> &ref, const sink &out) const noexcept { underlying_formatter.format(*ref, out); }
911};
912
919template <typename T> struct formatter<reloco::unique_ptr<T>> {
921
922 constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); }
923
924 void format(const reloco::unique_ptr<T> &ptr, const sink &out) const noexcept {
925 if (!ptr) {
926 out.write("(null)");
927 return;
928 }
929 underlying_formatter.format(*ptr.get(), out);
930 }
931};
932
939template <typename T> struct formatter<reloco::shared_ptr<T>> {
941
942 constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); }
943
944 void format(const reloco::shared_ptr<T> &ptr, const sink &out) const noexcept {
945 if (!ptr) {
946 out.write("(null)");
947 return;
948 }
949 underlying_formatter.format(*ptr.get(), out);
950 }
951};
952
960template <typename T> struct formatter<reloco::weak_ptr<T>> {
962
963 constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); }
964
965 void format(const reloco::weak_ptr<T> &weak, const sink &out) const noexcept {
966 auto locked = weak.lock();
967 if (!locked.has_value()) {
968 out.write("(expired)");
969 return;
970 }
971 underlying_formatter.format(*locked.value().get(), out);
972 }
973};
974
981template <typename T> struct formatter<reloco::rc<T>> {
983
984 constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); }
985
986 void format(const reloco::rc<T> &ptr, const sink &out) const noexcept {
987 if (!ptr) {
988 out.write("(null)");
989 return;
990 }
991 underlying_formatter.format(*ptr.get(), out);
992 }
993};
994
1002template <typename T> struct formatter<reloco::weak_rc<T>> {
1004
1005 constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); }
1006
1007 void format(const reloco::weak_rc<T> &weak, const sink &out) const noexcept {
1008 auto locked = weak.lock();
1009 if (!locked.has_value()) {
1010 out.write("(expired)");
1011 return;
1012 }
1013 underlying_formatter.format(*locked.value().get(), out);
1014 }
1015};
1016
1024template <typename T> struct formatter<reloco::cow<T>> {
1026
1027 constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); }
1028
1029 void format(const reloco::cow<T> &value, const sink &out) const noexcept {
1030 underlying_formatter.format(value.get(), out);
1031 }
1032};
1033
1034// ============================================================================
1035// Direct Formatters for reloco Numeric Newtypes
1036// ============================================================================
1037//
1038// `non_zero<T>`/`saturating<T>`/`wrapping<T>`/`checked<T>` all implicitly
1039// convert to their wrapped `T`, but formatter lookup is keyed on the exact
1040// argument type, so each still needs its own (trivial) specialization
1041// forwarding to `formatter<T>`.
1042
1046template <typename T> struct formatter<reloco::non_zero<T>> {
1048
1049 constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); }
1050
1051 void format(const reloco::non_zero<T> &value, const sink &out) const noexcept {
1052 underlying_formatter.format(value.get(), out);
1053 }
1054};
1055
1059template <typename T> struct formatter<reloco::saturating<T>> {
1061
1062 constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); }
1063
1064 void format(const reloco::saturating<T> &value, const sink &out) const noexcept {
1065 underlying_formatter.format(value.get(), out);
1066 }
1067};
1068
1072template <typename T> struct formatter<reloco::wrapping<T>> {
1074
1075 constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); }
1076
1077 void format(const reloco::wrapping<T> &value, const sink &out) const noexcept {
1078 underlying_formatter.format(value.get(), out);
1079 }
1080};
1081
1091template <typename T> struct formatter<reloco::checked<T>> {
1093
1094 constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); }
1095
1096 void format(const reloco::checked<T> &value, const sink &out) const noexcept {
1097 underlying_formatter.format(value.get(), out);
1098 }
1099};
1100
1101// ============================================================================
1102// Direct Formatters for reloco Time Types (duration.hpp / instant.hpp)
1103// ============================================================================
1104
1115template <> struct formatter<reloco::duration> {
1117 uint8_t precision{9};
1119 bool show_unit{true};
1120
1121 constexpr void parse(format_parse_context &ctx) noexcept {
1122 for (char c : ctx.spec()) {
1123 if (c == 'm' || c == '3')
1124 precision = 3;
1125 else if (c == 'u' || c == '6')
1126 precision = 6;
1127 else if (c == 'n' || c == '9')
1128 precision = 9;
1129 else if (c == 'r' || c == 'R')
1130 show_unit = false;
1131 }
1132 }
1133
1134 void format(const reloco::duration &value, const sink &out) const noexcept {
1135 detail::format_unsigned<detail::radix::decimal>(out, value.as_secs(), false, 0);
1136 out.put('.');
1137 if (precision == 3) {
1138 detail::format_unsigned<detail::radix::decimal>(out, value.subsec_millis(), false, 3);
1139 } else if (precision == 6) {
1140 detail::format_unsigned<detail::radix::decimal>(out, value.subsec_micros(), false, 6);
1141 } else {
1142 detail::format_unsigned<detail::radix::decimal>(out, value.subsec_nanos(), false, 9);
1143 }
1144
1145 if (show_unit) {
1146 out.put('s');
1147 }
1148 }
1149};
1150
1163template <> struct formatter<reloco::instant> {
1164 constexpr void parse(format_parse_context &) noexcept {}
1165
1166 // low-level formatting: raw character pointers and integer width conversions bounded by the buffer sizes checked
1167 // here.
1168 RELOCO_BEGIN_UNSAFE_CODE
1169 void format(const reloco::instant &value, const sink &out) const noexcept {
1170 const reloco::duration since_epoch = value.duration_since(reloco::instant());
1171
1172 const std::uint64_t total_secs = since_epoch.as_secs();
1173 const std::uint32_t hours = static_cast<std::uint32_t>(total_secs / 3600);
1174 const std::uint32_t mins = static_cast<std::uint32_t>((total_secs % 3600) / 60);
1175 const std::uint32_t secs = static_cast<std::uint32_t>(total_secs % 60);
1176
1177 detail::format_unsigned<detail::radix::decimal>(out, hours, false, 2);
1178 out.put(':');
1179 detail::format_unsigned<detail::radix::decimal>(out, mins, false, 2);
1180 out.put(':');
1181 detail::format_unsigned<detail::radix::decimal>(out, secs, false, 2);
1182 out.put('.');
1183 detail::format_unsigned<detail::radix::decimal>(out, since_epoch.subsec_millis(), false, 3);
1184 }
1186};
1187
1194template <> struct formatter<reloco::ordering> {
1195 constexpr void parse(format_parse_context &) noexcept {}
1196
1197 void format(reloco::ordering value, const sink &out) const noexcept {
1198 switch (value) {
1199 case reloco::ordering::less:
1200 out.write("less");
1201 return;
1202 case reloco::ordering::equal:
1203 out.write("equal");
1204 return;
1205 case reloco::ordering::greater:
1206 out.write("greater");
1207 return;
1208 }
1209 out.write("unknown");
1210 }
1211};
1212
1225template <> struct formatter<reloco::type_id> {
1226 constexpr void parse(format_parse_context &) noexcept {}
1227
1228 // low-level formatting: raw character pointers and integer width conversions bounded by the buffer sizes checked
1229 // here.
1230 RELOCO_BEGIN_UNSAFE_CODE
1231 void format(reloco::type_id value, const sink &out) const noexcept {
1232 if (!value) {
1233 out.write("<no type>");
1234 return;
1235 }
1236 const char *name = value.name();
1237 if (name == nullptr) {
1238 out.write("<unnamed type>");
1239 return;
1240 }
1241 out.write(name);
1242 }
1244};
1245
1251template <> struct formatter<reloco::error> {
1252 constexpr void parse(format_parse_context &) noexcept {}
1253
1254 void format(const reloco::error &val, const sink &out) const noexcept {
1255 using reloco::error;
1256 switch (val) {
1257 case error::allocation_failed:
1258 out.write("allocation_failed");
1259 return;
1260 case error::in_place_growth_failed:
1261 out.write("in_place_growth_failed");
1262 return;
1263 case error::unsupported_operation:
1264 out.write("unsupported_operation");
1265 return;
1266 case error::out_of_range:
1267 out.write("out_of_range");
1268 return;
1269 case error::invalid_argument:
1270 out.write("invalid_argument");
1271 return;
1272 case error::already_exists:
1273 out.write("already_exists");
1274 return;
1275 case error::empty_pointer:
1276 out.write("empty_pointer");
1277 return;
1278 case error::pointer_expired:
1279 out.write("pointer_expired");
1280 return;
1281 case error::no_owner:
1282 out.write("no_owner");
1283 return;
1284 case error::out_of_bounds:
1285 out.write("out_of_bounds");
1286 return;
1287 case error::deadlock:
1288 out.write("deadlock");
1289 return;
1290 case error::invalid_owner:
1291 out.write("invalid_owner");
1292 return;
1293 case error::still_locked:
1294 out.write("still_locked");
1295 return;
1296 case error::not_locked:
1297 out.write("not_locked");
1298 return;
1299 case error::timed_out:
1300 out.write("timed_out");
1301 return;
1302 case error::try_again:
1303 out.write("try_again");
1304 return;
1305 case error::not_initialized:
1306 out.write("not_initialized");
1307 return;
1308 case error::container_empty:
1309 out.write("container_empty");
1310 return;
1311 case error::not_found:
1312 out.write("not_found");
1313 return;
1314 case error::integer_overflow:
1315 out.write("integer_overflow");
1316 return;
1317 case error::division_by_zero:
1318 out.write("division_by_zero");
1319 return;
1320 case error::capacity_exceeded:
1321 out.write("capacity_exceeded");
1322 return;
1323 case error::invalid_state:
1324 out.write("invalid_state");
1325 return;
1326 case error::permission_denied:
1327 out.write("permission_denied");
1328 return;
1329 case error::interrupted:
1330 out.write("interrupted");
1331 return;
1332 case error::resource_exhausted:
1333 out.write("resource_exhausted");
1334 return;
1335 case error::busy:
1336 out.write("busy");
1337 return;
1338 case error::io_error:
1339 out.write("io_error");
1340 return;
1341 case error::operation_canceled:
1342 out.write("operation_canceled");
1343 return;
1344 case error::security_violation:
1345 out.write("security_violation");
1346 return;
1347 case error::page_fault:
1348 out.write("page_fault");
1349 return;
1350 }
1351 // Defensive fallback for members added to `reloco::error` without a matching case above.
1352 microfmt::format_to(out, "error({})", static_cast<int>(val));
1353 }
1354};
1355
1362template <typename T, typename Compare> struct formatter<reloco::tree_set<T, Compare>> {
1364
1365 constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); }
1366
1367 void format(const reloco::tree_set<T, Compare> &set, const sink &out) const noexcept {
1368 detail::format_reloco_sequence(underlying_formatter, set, out);
1369 }
1370};
1371
1377template <typename Key, typename Mapped, typename Compare> struct formatter<reloco::tree_map<Key, Mapped, Compare>> {
1380
1381 constexpr void parse(format_parse_context &ctx) noexcept {
1382 key_formatter.parse(ctx);
1383 value_formatter.parse(ctx);
1384 }
1385
1386 void format(const reloco::tree_map<Key, Mapped, Compare> &map, const sink &out) const noexcept {
1387 detail::format_reloco_map(key_formatter, value_formatter, map, out);
1388 }
1389};
1390
1397template <typename Key, typename Mapped, typename Hash, typename KeyEqual>
1398struct formatter<reloco::lru_cache<Key, Mapped, Hash, KeyEqual>> {
1401
1402 constexpr void parse(format_parse_context &ctx) noexcept {
1403 key_formatter.parse(ctx);
1404 value_formatter.parse(ctx);
1405 }
1406
1407 void format(const reloco::lru_cache<Key, Mapped, Hash, KeyEqual> &cache, const sink &out) const noexcept {
1408 detail::format_reloco_map(key_formatter, value_formatter, cache, out);
1409 }
1410};
1411
1413template <typename T> struct formatter<reloco::external_vector<T>> {
1415
1416 constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); }
1417
1418 void format(const reloco::external_vector<T> &vec, const sink &out) const noexcept {
1419 detail::format_reloco_sequence(underlying_formatter, vec, out);
1420 }
1421};
1422
1428#define MICROFMT_RELOCO_RING_FORMATTER(TEMPLATE_HEAD, TYPE) \
1429 TEMPLATE_HEAD struct formatter<TYPE> { \
1430 detail::element_formatter<std::remove_cv_t<T>> underlying_formatter; \
1431 constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); } \
1432 void format(const TYPE &ring, const sink &out) const noexcept { \
1433 detail::format_reloco_sequence(underlying_formatter, ring, out); \
1434 } \
1435 }
1436
1437#define MICROFMT_COMMA ,
1438MICROFMT_RELOCO_RING_FORMATTER(template <typename T>, reloco::ring_buffer<T>);
1439MICROFMT_RELOCO_RING_FORMATTER(template <typename T>, reloco::outline_ring_buffer<T>);
1440MICROFMT_RELOCO_RING_FORMATTER(template <typename T>, reloco::ring_buffer_ref<T>);
1441MICROFMT_RELOCO_RING_FORMATTER(template <typename T MICROFMT_COMMA std::size_t N>,
1442 reloco::inline_ring_buffer<T MICROFMT_COMMA N>);
1443MICROFMT_RELOCO_RING_FORMATTER(template <typename T MICROFMT_COMMA std::size_t N>,
1444 reloco::sso_ring_buffer<T MICROFMT_COMMA N>);
1445#undef MICROFMT_COMMA
1446#undef MICROFMT_RELOCO_RING_FORMATTER
1447
1449template <typename... Ts> struct formatter<reloco::variant<Ts...>> {
1450 formatter<std::variant<Ts...>> base_formatter; // std-interop-ok: reloco::variant derives from std::variant
1451
1452 constexpr void parse(format_parse_context &ctx) noexcept { base_formatter.parse(ctx); }
1453
1454 void format(const reloco::variant<Ts...> &var, const sink &out) const noexcept {
1455 base_formatter.format(static_cast<const std::variant<Ts...> &>(var), out); // std-interop-ok: base-class view
1456 }
1457};
1458
1460template <typename T> struct formatter<reloco::cell<T>> {
1462
1463 constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); }
1464
1465 void format(const reloco::cell<T> &c, const sink &out) const noexcept { underlying_formatter.format(c.get(), out); }
1466};
1467
1469template <> struct formatter<reloco::call_location> {
1470 constexpr void parse(format_parse_context &) noexcept {}
1471
1472 void format(const reloco::call_location &loc, const sink &out) const noexcept {
1473 out.write(loc.file != nullptr ? microfmt::string_view(loc.file) : microfmt::string_view("<unknown>"));
1474 out.put(':');
1475 microfmt::format_to(out, "{}", loc.line);
1476 }
1477};
1478
1480template <> struct formatter<reloco::call_location_ref> {
1481 constexpr void parse(format_parse_context &) noexcept {}
1482
1483 void format(const reloco::call_location_ref &ref, const sink &out) const noexcept {
1484 if (!ref.has_value()) {
1485 out.write("<no location>");
1486 return;
1487 }
1488 formatter<reloco::call_location>{}.format(ref.value(), out);
1489 }
1490};
1491
1493template <typename T> struct formatter<reloco::packed_bits<T>> {
1495
1496 constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); }
1497
1498 void format(const reloco::packed_bits<T> &bits, const sink &out) const noexcept {
1499 underlying_formatter.format(bits.value(), out);
1500 }
1501};
1502
1507template <typename T, typename AuthPolicy> struct formatter<reloco::masked_pointer<T, AuthPolicy>> {
1508 constexpr void parse(format_parse_context &) noexcept {}
1509
1510 // low-level formatting: raw character pointers and integer width conversions bounded by the buffer sizes checked
1511 // here.
1512 RELOCO_BEGIN_UNSAFE_CODE
1513 void format(const reloco::masked_pointer<T, AuthPolicy> &ptr, const sink &out) const noexcept {
1514 const void *raw = static_cast<const void *>(ptr.get());
1515 if (raw == nullptr) {
1516 out.write("(null)");
1517 return;
1518 }
1519 microfmt::format_to(out, "{}", raw);
1520 }
1522};
1523
1530template <typename Rep, unsigned FracBits>
1531struct formatter<reloco::fixed_point<Rep, FracBits>, std::enable_if_t<std::is_arithmetic_v<Rep>>> {
1533
1534 constexpr void parse(format_parse_context &ctx) noexcept { underlying_formatter.parse(ctx); }
1535
1536 void format(const reloco::fixed_point<Rep, FracBits> &value, const sink &out) const noexcept {
1537 underlying_formatter.format(static_cast<double>(value.raw()) / static_cast<double>(Rep{1} << FracBits), out);
1538 }
1539};
1540
1547template <std::size_t N, bool Signed>
1548struct formatter<reloco::detail::wide_int<N, Signed>> : detail::int_formatter_specs {
1549 // low-level formatting: raw character pointers and integer width conversions bounded by the buffer sizes checked
1550 // here.
1551 RELOCO_BEGIN_UNSAFE_CODE
1552 void format(const reloco::detail::wide_int<N, Signed> &val, const sink &out) const noexcept {
1553 RELOCO_BEGIN_UNSAFE_BUFFER_USAGE;
1554 constexpr std::size_t limb_count = N / 32;
1555 // Enough for N/4 hex digits or ceil(N * log10(2)) decimal digits.
1556 constexpr std::size_t buf_size = N / 3 + 2;
1557
1558 std::uint32_t mag[limb_count];
1559 const bool negative = val.is_negative();
1560 const reloco::detail::wide_int<N, Signed> abs_val = negative ? -val : val;
1561 for (std::size_t i = 0; i < limb_count; ++i) {
1562 mag[i] = abs_val.limb(i);
1563 }
1564
1565 char buffer[buf_size];
1566 char *end = buffer + buf_size;
1567 char *start = end;
1568
1569 microfmt::string_view prefix{};
1570 if (flags.is_hex) {
1571 const char *lut = flags.uppercase ? "0123456789ABCDEF" : "0123456789abcdef";
1572 for (std::size_t i = 0; i < limb_count; ++i) {
1573 std::uint32_t limb = mag[i];
1574 for (int nibble = 0; nibble < 8; ++nibble) {
1575 *--start = lut[limb & 0xFU];
1576 limb >>= 4;
1577 }
1578 }
1579 // Drop leading zeros, keeping at least one digit.
1580 while (start < end - 1 && *start == '0') {
1581 ++start;
1582 }
1583 if (flags.alt_form) {
1584 prefix = flags.uppercase ? microfmt::string_view("0X") : microfmt::string_view("0x");
1585 }
1586 } else {
1587 std::size_t used = limb_count;
1588 do {
1589 // Divide the magnitude by 10^9 in place, emitting the 9-digit remainder.
1590 std::uint64_t rem = 0;
1591 for (std::size_t i = used; i-- > 0;) {
1592 const std::uint64_t cur = (rem << 32) | mag[i];
1593 mag[i] = static_cast<std::uint32_t>(cur / 1000000000U);
1594 rem = cur % 1000000000U;
1595 }
1596 while (used > 0 && mag[used - 1] == 0) {
1597 --used;
1598 }
1599 auto chunk = static_cast<std::uint32_t>(rem);
1600 for (int digit = 0; digit < 9 && (used > 0 || chunk != 0 || digit == 0); ++digit) {
1601 *--start = static_cast<char>('0' + chunk % 10U);
1602 chunk /= 10U;
1603 }
1604 } while (used > 0);
1605 }
1606
1607 detail::emit_formatted_int(out, start, static_cast<std::size_t>(end - start), negative, prefix, width,
1608 flags.zero_pad);
1609 RELOCO_END_UNSAFE_BUFFER_USAGE;
1610 }
1612};
1613
1614#if defined(__SIZEOF_INT128__)
1615// Feature-tested use of the GCC/Clang __int128 extension: under strict
1616// -std=c++NN it is not std::is_integral, so this formatter is how it reaches
1617// the wide_int formatter. -Wpedantic would otherwise reject the type names.
1618RELOCO_BEGIN_SUPPRESS_PEDANTIC_INT128
1623template <typename T>
1624struct formatter<T, std::enable_if_t<reloco::detail::is_builtin_int128_v<T> && !std::is_integral_v<T>>>
1625 : formatter<reloco::detail::wide_int<128, std::is_same_v<T, __int128>>> {
1626 void format(T val, const sink &out) const noexcept {
1627 constexpr bool is_signed = std::is_same_v<T, __int128>;
1628 formatter<reloco::detail::wide_int<128, is_signed>>::format(reloco::detail::wide_int<128, is_signed>(val), out);
1629 }
1630};
1631RELOCO_END_SUPPRESS_PEDANTIC_INT128
1632#endif
1633
1634} // namespace microfmt
Definition microfmt.hpp:881
Floating-point formatting backed by printf-style specifiers.
#define MICROFMT_RELOCO_RING_FORMATTER(TEMPLATE_HEAD, TYPE)
Formatters for the reloco::ring_buffer family (ring_buffer, outline_ring_buffer, inline_ring_buffer,...
Definition reloco.hpp:1428
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
Definition assert.hpp:19
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
Drop-in replacement for a formatter<T> underlying_formatter; member used by container/wrapper formatt...
Definition microfmt.hpp:1433
constexpr void parse(format_parse_context &ctx) noexcept
Definition microfmt.hpp:1445
void format(const T &value, const sink &out) const noexcept
Definition microfmt.hpp:1447
Definition microfmt.hpp:1159
formatter< reloco::basic_string_view< CharT, TraitsT > > underlying_formatter
Definition reloco.hpp:305
void format(const reloco::basic_inline_string< Capacity, CharT, TraitsT > &str, const sink &out) const noexcept
Definition reloco.hpp:309
constexpr void parse(format_parse_context &ctx) noexcept
Definition reloco.hpp:307
formatter< reloco::basic_string_view< CharT, TraitsT > > underlying_formatter
Definition reloco.hpp:321
constexpr void parse(format_parse_context &ctx) noexcept
Definition reloco.hpp:323
void format(const reloco::basic_sso_string< CharT, TraitsT > &str, const sink &out) const noexcept
Definition reloco.hpp:325
formatter< reloco::basic_string_view< CharT, TraitsT > > underlying_formatter
Definition reloco.hpp:288
constexpr void parse(format_parse_context &ctx) noexcept
Definition reloco.hpp:290
void format(const reloco::basic_string< CharT, TraitsT > &str, const sink &out) const noexcept
Definition reloco.hpp:292
std::remove_cv_t< T > value_type
Definition reloco.hpp:556
constexpr void parse(format_parse_context &ctx) noexcept
Definition reloco.hpp:560
void format(const reloco::binary_heap< T, Compare > &heap, const sink &out) const noexcept
Definition reloco.hpp:562
detail::element_formatter< value_type > underlying_formatter
Definition reloco.hpp:558
detail::element_formatter< value_type > underlying_formatter
Definition reloco.hpp:529
void format(const reloco::boxed_slice< T > &slice, const sink &out) const noexcept
Definition reloco.hpp:533
constexpr void parse(format_parse_context &ctx) noexcept
Definition reloco.hpp:531
std::remove_cv_t< T > value_type
Definition reloco.hpp:527
constexpr void parse(format_parse_context &) noexcept
Definition reloco.hpp:1470
void format(const reloco::call_location &loc, const sink &out) const noexcept
Definition reloco.hpp:1472
void format(const reloco::call_location_ref &ref, const sink &out) const noexcept
Definition reloco.hpp:1483
constexpr void parse(format_parse_context &) noexcept
Definition reloco.hpp:1481
detail::element_formatter< std::remove_cv_t< T > > underlying_formatter
Definition reloco.hpp:1461
void format(const reloco::cell< T > &c, const sink &out) const noexcept
Definition reloco.hpp:1465
constexpr void parse(format_parse_context &ctx) noexcept
Definition reloco.hpp:1463
void format(const reloco::checked< T > &value, const sink &out) const noexcept
Definition reloco.hpp:1096
constexpr void parse(format_parse_context &ctx) noexcept
Definition reloco.hpp:1094
detail::element_formatter< T > underlying_formatter
Definition reloco.hpp:1092
void format(const reloco::collection_view< T > &view, const sink &out) const noexcept
Definition reloco.hpp:112
detail::element_formatter< value_type > underlying_formatter
Definition reloco.hpp:104
constexpr void parse(format_parse_context &ctx) noexcept
Definition reloco.hpp:106
std::remove_cv_t< T > value_type
Definition reloco.hpp:101
void format(const reloco::cow< T > &value, const sink &out) const noexcept
Definition reloco.hpp:1029
detail::element_formatter< std::remove_cv_t< T > > underlying_formatter
Definition reloco.hpp:1025
constexpr void parse(format_parse_context &ctx) noexcept
Definition reloco.hpp:1027
detail::element_formatter< value_type > value_formatter
Definition reloco.hpp:190
detail::element_formatter< key_type > key_formatter
Definition reloco.hpp:189
constexpr void parse(format_parse_context &ctx) noexcept
Definition reloco.hpp:192
void format(const reloco::detail::mutable_associative_container_ref< T, Key > &cref, const sink &out) const noexcept
Definition reloco.hpp:197
detail::element_formatter< value_type > underlying_formatter
Definition reloco.hpp:158
void format(const reloco::detail::mutable_sequence_container_ref< T > &cref, const sink &out) const noexcept
Definition reloco.hpp:162
constexpr void parse(format_parse_context &ctx) noexcept
Definition reloco.hpp:160
RELOCO_BEGIN_UNSAFE_CODE void format(const reloco::detail::wide_int< N, Signed > &val, const sink &out) const noexcept
Definition reloco.hpp:1552
constexpr void parse(format_parse_context &ctx) noexcept
Definition reloco.hpp:1121
void format(const reloco::duration &value, const sink &out) const noexcept
Definition reloco.hpp:1134
void format(const reloco::error &val, const sink &out) const noexcept
Definition reloco.hpp:1254
constexpr void parse(format_parse_context &) noexcept
Definition reloco.hpp:1252
void format(const reloco::external_vector< T > &vec, const sink &out) const noexcept
Definition reloco.hpp:1418
constexpr void parse(format_parse_context &ctx) noexcept
Definition reloco.hpp:1416
detail::element_formatter< std::remove_cv_t< T > > underlying_formatter
Definition reloco.hpp:1414
constexpr void parse(format_parse_context &ctx) noexcept
Definition reloco.hpp:1534
void format(const reloco::fixed_point< Rep, FracBits > &value, const sink &out) const noexcept
Definition reloco.hpp:1536
detail::element_formatter< std::remove_cv_t< Mapped > > value_formatter
Definition reloco.hpp:843
void format(const reloco::flat_hash_map< Key, Mapped, Hash, KeyEqual > &map, const sink &out) const noexcept
Definition reloco.hpp:850
detail::element_formatter< std::remove_cv_t< Key > > key_formatter
Definition reloco.hpp:842
constexpr void parse(format_parse_context &ctx) noexcept
Definition reloco.hpp:845
constexpr void parse(format_parse_context &ctx) noexcept
Definition reloco.hpp:816
std::remove_cv_t< T > value_type
Definition reloco.hpp:812
void format(const reloco::flat_hash_set< T, Hash, KeyEqual > &set, const sink &out) const noexcept
Definition reloco.hpp:818
detail::element_formatter< value_type > underlying_formatter
Definition reloco.hpp:814
detail::element_formatter< std::remove_cv_t< Key > > key_formatter
Definition reloco.hpp:461
void format(const reloco::flat_map< Key, Mapped, Compare > &map, const sink &out) const noexcept
Definition reloco.hpp:469
constexpr void parse(format_parse_context &ctx) noexcept
Definition reloco.hpp:464
detail::element_formatter< std::remove_cv_t< Mapped > > value_formatter
Definition reloco.hpp:462
detail::element_formatter< value_type > underlying_formatter
Definition reloco.hpp:263
constexpr void parse(format_parse_context &ctx) noexcept
Definition reloco.hpp:265
std::remove_cv_t< T > value_type
Definition reloco.hpp:261
void format(const reloco::flat_set< T, Compare > &set, const sink &out) const noexcept
Definition reloco.hpp:267
detail::element_formatter< std::remove_cv_t< Key > > key_formatter
Definition reloco.hpp:495
constexpr void parse(format_parse_context &ctx) noexcept
Definition reloco.hpp:498
void format(const reloco::inline_flat_map< Key, Mapped, Capacity, Compare > &map, const sink &out) const noexcept
Definition reloco.hpp:503
detail::element_formatter< std::remove_cv_t< Mapped > > value_formatter
Definition reloco.hpp:496
std::remove_cv_t< T > value_type
Definition reloco.hpp:434
detail::element_formatter< value_type > underlying_formatter
Definition reloco.hpp:436
void format(const reloco::inline_flat_set< T, Capacity, Compare > &set, const sink &out) const noexcept
Definition reloco.hpp:440
constexpr void parse(format_parse_context &ctx) noexcept
Definition reloco.hpp:438
detail::element_formatter< value_type > underlying_formatter
Definition reloco.hpp:758
void format(const reloco::inline_vec_deque< T, Capacity > &deque, const sink &out) const noexcept
Definition reloco.hpp:762
std::remove_cv_t< T > value_type
Definition reloco.hpp:756
constexpr void parse(format_parse_context &ctx) noexcept
Definition reloco.hpp:760
constexpr void parse(format_parse_context &ctx) noexcept
Definition reloco.hpp:410
void format(const reloco::inline_vector< T, Capacity > &vec, const sink &out) const noexcept
Definition reloco.hpp:412
std::remove_cv_t< T > value_type
Definition reloco.hpp:406
detail::element_formatter< value_type > underlying_formatter
Definition reloco.hpp:408
constexpr void parse(format_parse_context &) noexcept
Definition reloco.hpp:1164
RELOCO_BEGIN_UNSAFE_CODE void format(const reloco::instant &value, const sink &out) const noexcept
Definition reloco.hpp:1169
detail::element_formatter< std::remove_cv_t< Key > > key_formatter
Definition reloco.hpp:1399
void format(const reloco::lru_cache< Key, Mapped, Hash, KeyEqual > &cache, const sink &out) const noexcept
Definition reloco.hpp:1407
detail::element_formatter< std::remove_cv_t< Mapped > > value_formatter
Definition reloco.hpp:1400
constexpr void parse(format_parse_context &ctx) noexcept
Definition reloco.hpp:1402
constexpr void parse(format_parse_context &) noexcept
Definition reloco.hpp:1508
RELOCO_BEGIN_UNSAFE_CODE void format(const reloco::masked_pointer< T, AuthPolicy > &ptr, const sink &out) const noexcept
Definition reloco.hpp:1513
constexpr void parse(format_parse_context &ctx) noexcept
Definition reloco.hpp:1049
void format(const reloco::non_zero< T > &value, const sink &out) const noexcept
Definition reloco.hpp:1051
detail::element_formatter< T > underlying_formatter
Definition reloco.hpp:1047
constexpr void parse(format_parse_context &ctx) noexcept
Definition reloco.hpp:345
void format(const reloco::obfuscated_decrypted_view< N > &val, const sink &out) const noexcept
Definition reloco.hpp:347
formatter< microfmt::string_view > underlying_formatter
Definition reloco.hpp:343
constexpr void parse(format_parse_context &ctx) noexcept
Definition reloco.hpp:392
void format(const reloco::obfuscated_string< N > &val, const sink &out) const noexcept
Definition reloco.hpp:394
formatter< reloco::obfuscated_string_ref > underlying_formatter
Definition reloco.hpp:390
void format(reloco::obfuscated_string_ref val, const sink &out) const noexcept
Definition reloco.hpp:375
constexpr void parse(format_parse_context &) const noexcept
Definition reloco.hpp:373
void format(reloco::ordering value, const sink &out) const noexcept
Definition reloco.hpp:1197
constexpr void parse(format_parse_context &) noexcept
Definition reloco.hpp:1195
constexpr void parse(format_parse_context &ctx) noexcept
Definition reloco.hpp:787
detail::element_formatter< value_type > underlying_formatter
Definition reloco.hpp:785
void format(const reloco::outline_vec_deque< T > &deque, const sink &out) const noexcept
Definition reloco.hpp:789
std::remove_cv_t< T > value_type
Definition reloco.hpp:783
std::remove_cv_t< T > value_type
Definition reloco.hpp:672
void format(const reloco::outline_vector< T > &vec, const sink &out) const noexcept
Definition reloco.hpp:678
constexpr void parse(format_parse_context &ctx) noexcept
Definition reloco.hpp:676
detail::element_formatter< value_type > underlying_formatter
Definition reloco.hpp:674
constexpr void parse(format_parse_context &ctx) noexcept
Definition reloco.hpp:1496
formatter< T > underlying_formatter
Definition reloco.hpp:1494
void format(const reloco::packed_bits< T > &bits, const sink &out) const noexcept
Definition reloco.hpp:1498
constexpr void parse(format_parse_context &ctx) noexcept
Definition reloco.hpp:984
void format(const reloco::rc< T > &ptr, const sink &out) const noexcept
Definition reloco.hpp:986
detail::element_formatter< std::remove_cv_t< T > > underlying_formatter
Definition reloco.hpp:982
detail::element_formatter< T > underlying_formatter
Definition reloco.hpp:1060
constexpr void parse(format_parse_context &ctx) noexcept
Definition reloco.hpp:1062
void format(const reloco::saturating< T > &value, const sink &out) const noexcept
Definition reloco.hpp:1064
constexpr void parse(format_parse_context &ctx) noexcept
Definition reloco.hpp:942
void format(const reloco::shared_ptr< T > &ptr, const sink &out) const noexcept
Definition reloco.hpp:944
detail::element_formatter< std::remove_cv_t< T > > underlying_formatter
Definition reloco.hpp:940
detail::element_formatter< std::remove_cv_t< Mapped > > value_formatter
Definition reloco.hpp:641
void format(const reloco::sso_flat_map< Key, Mapped, InlineCapacity, Compare > &map, const sink &out) const noexcept
Definition reloco.hpp:648
constexpr void parse(format_parse_context &ctx) noexcept
Definition reloco.hpp:643
detail::element_formatter< std::remove_cv_t< Key > > key_formatter
Definition reloco.hpp:640
detail::element_formatter< value_type > underlying_formatter
Definition reloco.hpp:613
void format(const reloco::sso_flat_set< T, InlineCapacity, Compare > &set, const sink &out) const noexcept
Definition reloco.hpp:617
std::remove_cv_t< T > value_type
Definition reloco.hpp:611
constexpr void parse(format_parse_context &ctx) noexcept
Definition reloco.hpp:615
constexpr void parse(format_parse_context &ctx) noexcept
Definition reloco.hpp:733
void format(const reloco::sso_vec_deque< T, InlineCapacity > &deque, const sink &out) const noexcept
Definition reloco.hpp:735
detail::element_formatter< value_type > underlying_formatter
Definition reloco.hpp:731
std::remove_cv_t< T > value_type
Definition reloco.hpp:729
constexpr void parse(format_parse_context &ctx) noexcept
Definition reloco.hpp:587
void format(const reloco::sso_vector< T, InlineCapacity > &vec, const sink &out) const noexcept
Definition reloco.hpp:589
std::remove_cv_t< T > value_type
Definition reloco.hpp:583
detail::element_formatter< value_type > underlying_formatter
Definition reloco.hpp:585
constexpr void parse(format_parse_context &ctx) noexcept
Definition reloco.hpp:1381
detail::element_formatter< std::remove_cv_t< Key > > key_formatter
Definition reloco.hpp:1378
void format(const reloco::tree_map< Key, Mapped, Compare > &map, const sink &out) const noexcept
Definition reloco.hpp:1386
detail::element_formatter< std::remove_cv_t< Mapped > > value_formatter
Definition reloco.hpp:1379
constexpr void parse(format_parse_context &ctx) noexcept
Definition reloco.hpp:1365
detail::element_formatter< std::remove_cv_t< T > > underlying_formatter
Definition reloco.hpp:1363
void format(const reloco::tree_set< T, Compare > &set, const sink &out) const noexcept
Definition reloco.hpp:1367
RELOCO_BEGIN_UNSAFE_CODE void format(reloco::type_id value, const sink &out) const noexcept
Definition reloco.hpp:1231
constexpr void parse(format_parse_context &) noexcept
Definition reloco.hpp:1226
void format(const reloco::unique_ptr< T > &ptr, const sink &out) const noexcept
Definition reloco.hpp:924
detail::element_formatter< std::remove_cv_t< T > > underlying_formatter
Definition reloco.hpp:920
constexpr void parse(format_parse_context &ctx) noexcept
Definition reloco.hpp:922
formatter< std::variant< Ts... > > base_formatter
Definition reloco.hpp:1450
constexpr void parse(format_parse_context &ctx) noexcept
Definition reloco.hpp:1452
void format(const reloco::variant< Ts... > &var, const sink &out) const noexcept
Definition reloco.hpp:1454
detail::element_formatter< value_type > underlying_formatter
Definition reloco.hpp:704
void format(const reloco::vec_deque< T > &deque, const sink &out) const noexcept
Definition reloco.hpp:708
constexpr void parse(format_parse_context &ctx) noexcept
Definition reloco.hpp:706
std::remove_cv_t< T > value_type
Definition reloco.hpp:702
constexpr void parse(format_parse_context &ctx) noexcept
Definition reloco.hpp:238
detail::element_formatter< value_type > underlying_formatter
Definition reloco.hpp:236
void format(const reloco::vector< T > &vec, const sink &out) const noexcept
Definition reloco.hpp:240
std::remove_cv_t< T > value_type
Definition reloco.hpp:234
constexpr void parse(format_parse_context &ctx) noexcept
Definition reloco.hpp:963
void format(const reloco::weak_ptr< T > &weak, const sink &out) const noexcept
Definition reloco.hpp:965
detail::element_formatter< std::remove_cv_t< T > > underlying_formatter
Definition reloco.hpp:961
void format(const reloco::weak_rc< T > &weak, const sink &out) const noexcept
Definition reloco.hpp:1007
detail::element_formatter< std::remove_cv_t< T > > underlying_formatter
Definition reloco.hpp:1003
constexpr void parse(format_parse_context &ctx) noexcept
Definition reloco.hpp:1005
void format(const reloco::wrapping< T > &value, const sink &out) const noexcept
Definition reloco.hpp:1077
constexpr void parse(format_parse_context &ctx) noexcept
Definition reloco.hpp:1075
detail::element_formatter< T > underlying_formatter
Definition reloco.hpp:1073
void format(const value_ptr< T > &ptr, const sink &out) const noexcept
Definition reloco.hpp:889
detail::element_formatter< std::remove_cv_t< T > > underlying_formatter
Definition reloco.hpp:885
constexpr void parse(format_parse_context &ctx) noexcept
Definition reloco.hpp:887
detail::element_formatter< std::remove_cv_t< T > > underlying_formatter
Definition reloco.hpp:906
void format(const value_ref< T > &ref, const sink &out) const noexcept
Definition reloco.hpp:910
constexpr void parse(format_parse_context &ctx) noexcept
Definition reloco.hpp:908
Definition microfmt.hpp:985
`std::variant` and non-owning variant view formatting.