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&& arg) : value(_construct(static_cast<Arg&&>(arg)))
35  {
36  }
37 
38  private:
39  template <typename Arg>
40  static T _construct(Arg&& arg)
41  {
42  if constexpr (std::is_move_constructible<T>::value)
43  {
44  return T(static_cast<Arg&&>(arg));
45  }
46  else
47  {
48  // For copy-only types: arg is a named rvalue reference, which is an lvalue expression.
49  // This lvalue can bind to const T& (the copy constructor parameter), resulting in a copy.
50  return T(arg);
51  }
52  }
53 
54  public:
55  T value;
56  };
57 
58  std::unique_ptr<Node> _head;
59 
60 public:
61  template <typename T, typename Arg>
62  T const& push(Arg&& arg)
63  {
64  auto new_node = std::unique_ptr<TypedNode<T>>(new TypedNode<T>(static_cast<Arg&&>(arg)));
65  T& value = new_node->value;
66  new_node->next = static_cast<std::unique_ptr<Node>&&>(_head);
67  _head = static_cast<std::unique_ptr<TypedNode<T>>&&>(new_node);
68  return value;
69  }
70 };
71 } // namespace detail
72 
73 QUILL_BEGIN_EXPORT
74 
80 {
81 private:
82  // Storage of basic_format_arg must be contiguous.
83  std::vector<fmtquill::basic_format_arg<fmtquill::format_context>> _data;
84 
85  // Storage of arguments not fitting into basic_format_arg must grow
86  // without relocation because items in data_ refer to it.
87  detail::DynamicArgList _dynamic_arg_list;
88  bool _has_string_related_type{false};
89 
90  template <typename T>
91  void emplace_arg(T&& arg)
92  {
93  _data.emplace_back(static_cast<T&&>(arg));
94  }
95 
96 public:
97  DynamicFormatArgStore() = default;
98 
99  QUILL_NODISCARD int size() const { return static_cast<int>(_data.size()); }
100 
101  QUILL_NODISCARD fmtquill::basic_format_arg<fmtquill::format_context> const* data() const
102  {
103  return _data.data();
104  }
105 
117  template <typename T>
118  void push_back(T&& arg)
119  {
120  using char_type = typename fmtquill::format_context::char_type;
121  using bare_type = std::remove_cv_t<std::remove_reference_t<T>>;
122  constexpr auto mapped_type = fmtquill::detail::mapped_type_constant<bare_type, char_type>::value;
123  using stored_type =
124  std::conditional_t<std::is_convertible_v<bare_type, std::string>, std::string, bare_type>;
125 
126  if constexpr (!(std::is_same_v<bare_type, std::string_view> || std::is_same_v<bare_type, fmtquill::string_view> ||
127  (mapped_type != fmtquill::detail::type::cstring_type &&
128  mapped_type != fmtquill::detail::type::string_type &&
129  mapped_type != fmtquill::detail::type::custom_type)))
130  {
131  emplace_arg(_dynamic_arg_list.push<stored_type>(static_cast<T&&>(arg)));
132  }
133  else
134  {
135  emplace_arg(static_cast<T&&>(arg));
136  }
137 
138  if constexpr (std::is_same_v<bare_type, std::string_view> || std::is_same_v<bare_type, fmtquill::string_view> ||
139  (mapped_type == fmtquill::detail::type::cstring_type) ||
140  (mapped_type == fmtquill::detail::type::string_type) ||
141  (mapped_type == fmtquill::detail::type::custom_type) ||
142  (mapped_type == fmtquill::detail::type::char_type))
143  {
144  _has_string_related_type = true;
145  }
146  }
147 
149  void clear()
150  {
151  _data.clear();
152  _dynamic_arg_list = detail::DynamicArgList{};
153  _has_string_related_type = false;
154  }
155 
156  QUILL_NODISCARD bool has_string_related_type() const noexcept { return _has_string_related_type; }
157 };
158 
159 QUILL_END_EXPORT
160 
161 QUILL_END_NAMESPACE
void clear()
Erase all elements from the store.
Definition: DynamicFormatArgStore.h:149
char char_type
The character type for the output.
Definition: base.h:2712
Definition: DynamicFormatArgStore.h:22
Similar to fmt::dynamic_arg_store but better suited to our needs e.g.
Definition: DynamicFormatArgStore.h:79
Setups a signal handler to handle fatal signals.
Definition: BackendManager.h:28
Definition: base.h:2200
void push_back(T &&arg)
Adds an argument for later passing to a formatting function.
Definition: DynamicFormatArgStore.h:118