quill
BackendMdcState.h
1 
7 #pragma once
8 
9 #include <cstddef>
10 #include <map>
11 #include <string>
12 #include <string_view>
13 
14 #include "quill/core/Attributes.h"
15 #include "quill/core/QuillError.h"
16 
17 QUILL_BEGIN_NAMESPACE
18 
19 namespace detail
20 {
22 {
23 public:
24  explicit BackendMdcState(std::string const& pattern) : _format_parts(pattern) {}
25 
26  void set(std::string_view key, std::string_view value)
27  {
28  _fields[std::string{key}] = std::string{value};
29  }
30 
31  void erase(std::string_view key) { _fields.erase(std::string{key}); }
32 
33  void clear()
34  {
35  _fields.clear();
36  _formatted_mdc.clear();
37  }
38 
39  QUILL_NODISCARD std::string_view formatted_mdc() const noexcept { return _formatted_mdc; }
40 
41  QUILL_NODISCARD bool empty() const noexcept { return _fields.empty(); }
42 
43  void rebuild_formatted_mdc()
44  {
45  _formatted_mdc.clear();
46 
47  if (_fields.empty())
48  {
49  return;
50  }
51 
52  _formatted_mdc.append(_format_parts.prefix);
53 
54  size_t i = 0;
55  for (auto const& [key, value] : _fields)
56  {
57  _formatted_mdc.append(key);
58  _formatted_mdc.append(_format_parts.kv_sep);
59  _formatted_mdc.append(value);
60 
61  if (++i != _fields.size())
62  {
63  _formatted_mdc.append(_format_parts.field_sep);
64  }
65  }
66 
67  _formatted_mdc.append(_format_parts.suffix);
68  }
69 
70 private:
71  struct FormatParts
72  {
73  std::string prefix;
74  std::string kv_sep;
75  std::string field_sep;
76  std::string suffix;
77 
78  explicit FormatParts(std::string const& pattern)
79  {
80  if (!_set_from_pattern(pattern))
81  {
82  QUILL_THROW(QuillError{
83  "Invalid BackendOptions::mdc_format_pattern. Expected exactly two \"{}\" placeholders "
84  "and at least one trailing character after the second placeholder."});
85  }
86  }
87 
88  private:
89  bool _set_from_pattern(std::string_view pattern)
90  {
91  static constexpr std::string_view placeholder{"{}"};
92 
93  size_t const first = pattern.find(placeholder);
94  if (first == std::string_view::npos)
95  {
96  return false;
97  }
98 
99  size_t const second = pattern.find(placeholder, first + placeholder.size());
100  if (second == std::string_view::npos)
101  {
102  return false;
103  }
104 
105  size_t const third = pattern.find(placeholder, second + placeholder.size());
106  if (third != std::string_view::npos)
107  {
108  return false;
109  }
110 
111  size_t const after_second = second + placeholder.size();
112  if (after_second >= pattern.size())
113  {
114  return false;
115  }
116 
117  prefix.assign(pattern.data(), first);
118  kv_sep.assign(pattern.data() + first + placeholder.size(), second - first - placeholder.size());
119  field_sep.assign(pattern.data() + after_second, pattern.size() - after_second - 1u);
120  suffix.assign(pattern.data() + pattern.size() - 1u, 1u);
121  return true;
122  }
123  };
124 
125  FormatParts _format_parts;
126  std::map<std::string, std::string> _fields;
127  std::string _formatted_mdc;
128 };
129 } // namespace detail
130 
131 QUILL_END_NAMESPACE
Definition: BackendMdcState.h:21
Setups a signal handler to handle fatal signals.
Definition: BackendManager.h:28
Definition: base.h:2200
custom exception
Definition: QuillError.h:47