quill
DynamicFormatArgStore.h
1 
7 #pragma once
8 
9 #include <memory>
10 #include <string>
11 #include <string_view>
12 #include <type_traits>
13 #include <vector>
14 
15 #include "quill/bundled/fmt/base.h"
16 #include "quill/core/Attributes.h"
17 
18 QUILL_BEGIN_NAMESPACE
19 
20 namespace detail
21 {
23 {
24  struct Node
25  {
26  virtual ~Node() = default;
27  std::unique_ptr<Node> next;
28  };
29 
30  template <typename T>
31  struct TypedNode : Node
32  {
33  template <typename Arg>
34  explicit TypedNode(Arg const& arg) : value(arg)
35  {
36  }
37 
38  T value;
39  };
40 
41  std::unique_ptr<Node> _head;
42 
43 public:
44  template <typename T, typename Arg>
45  T const& push(Arg const& arg)
46  {
47  auto new_node = std::unique_ptr<TypedNode<T>>(new TypedNode<T>(arg));
48  T& value = new_node->value;
49  new_node->next = std::move(_head);
50  _head = std::move(new_node);
51  return value;
52  }
53 };
54 } // namespace detail
55 
61 {
62 private:
63  // Storage of basic_format_arg must be contiguous.
64  std::vector<fmtquill::basic_format_arg<fmtquill::format_context>> _data;
65 
66  // Storage of arguments not fitting into basic_format_arg must grow
67  // without relocation because items in data_ refer to it.
68  detail::DynamicArgList _dynamic_arg_list;
69  bool _has_string_related_type{false};
70 
71  template <typename T>
72  void emplace_arg(T const& arg)
73  {
74  _data.emplace_back(arg);
75  }
76 
77 public:
78  DynamicFormatArgStore() = default;
79 
80  QUILL_NODISCARD int size() const { return static_cast<int>(_data.size()); }
81 
82  QUILL_NODISCARD fmtquill::basic_format_arg<fmtquill::format_context> const* data() const
83  {
84  return _data.data();
85  }
86 
98  template <typename T>
99  void push_back(T const& arg)
100  {
101  using char_type = typename fmtquill::format_context::char_type;
102  constexpr auto mapped_type = fmtquill::detail::mapped_type_constant<T, char_type>::value;
103  using stored_type = std::conditional_t<std::is_convertible_v<T, std::string>, std::string, T>;
104 
105  if constexpr (!(std::is_same_v<std::remove_cv_t<std::remove_reference_t<T>>, std::string_view> ||
106  std::is_same_v<std::remove_cv_t<std::remove_reference_t<T>>, fmtquill::string_view> ||
107  (mapped_type != fmtquill::detail::type::cstring_type &&
108  mapped_type != fmtquill::detail::type::string_type &&
109  mapped_type != fmtquill::detail::type::custom_type)))
110  {
111  emplace_arg(_dynamic_arg_list.push<stored_type>(arg));
112  }
113  else
114  {
115  emplace_arg(arg);
116  }
117 
118  if constexpr (std::is_same_v<std::remove_cv_t<std::remove_reference_t<T>>, std::string_view> ||
119  std::is_same_v<std::remove_cv_t<std::remove_reference_t<T>>, fmtquill::string_view> ||
120  (mapped_type == fmtquill::detail::type::cstring_type) ||
121  (mapped_type == fmtquill::detail::type::string_type) ||
122  (mapped_type == fmtquill::detail::type::custom_type) ||
123  (mapped_type == fmtquill::detail::type::char_type))
124  {
125  _has_string_related_type = true;
126  }
127  }
128 
130  void clear()
131  {
132  _data.clear();
133  _dynamic_arg_list = detail::DynamicArgList{};
134  _has_string_related_type = false;
135  }
136 
137  QUILL_NODISCARD bool has_string_related_type() const noexcept { return _has_string_related_type; }
138 };
139 
140 QUILL_END_NAMESPACE
void clear()
Erase all elements from the store.
Definition: DynamicFormatArgStore.h:130
char char_type
The character type for the output.
Definition: base.h:2680
Definition: DynamicFormatArgStore.h:22
Similar to fmt::dynamic_arg_store but better suited to our needs e.g does not include <functional> an...
Definition: DynamicFormatArgStore.h:60
Setups a signal handler to handle fatal signals.
Definition: BackendManager.h:24
Definition: base.h:2147
void push_back(T const &arg)
Adds an argument for later passing to a formatting function.
Definition: DynamicFormatArgStore.h:99