quill
MacroMetadata.h
1 
7 #pragma once
8 
9 #include "quill/core/Attributes.h"
10 #include "quill/core/Common.h"
11 #include "quill/core/LogLevel.h"
12 
13 #include <cstddef>
14 #include <cstdint>
15 #include <string_view>
16 
17 QUILL_BEGIN_NAMESPACE
18 
23 {
24 public:
25  enum Event : uint8_t
26  {
27  None,
28  Log,
29  InitBacktrace,
30  FlushBacktrace,
31  Flush,
32  LogWithRuntimeMetadataDeepCopy,
33  LogWithRuntimeMetadataHybridCopy,
34  LogWithRuntimeMetadataShallowCopy,
35  LoggerRemovalRequest
36  };
37 
38  constexpr MacroMetadata() = default;
39 
40  constexpr MacroMetadata(char const* source_location, char const* caller_function,
41  char const* message_format, char const* tags, LogLevel log_level, Event event) noexcept
42  : _source_location(source_location),
43  _caller_function(caller_function),
44  _message_format(message_format),
45  _tags(tags),
46  _colon_separator_pos(_calc_colon_separator_pos()),
47  _file_name_pos(_calc_file_name_pos()),
48  _log_level(log_level),
49  _event(event)
50  {
51  }
52 
53  QUILL_NODISCARD char const* source_location() const noexcept { return _source_location; }
54 
55  QUILL_NODISCARD char const* caller_function() const noexcept { return _caller_function; }
56 
57  QUILL_NODISCARD char const* message_format() const noexcept { return _message_format; }
58 
59  QUILL_NODISCARD char const* line() const noexcept
60  {
61  return _source_location + _colon_separator_pos + 1;
62  }
63 
64  QUILL_NODISCARD std::string_view full_path() const noexcept
65  {
66  return std::string_view{_source_location, _colon_separator_pos};
67  }
68 
69  QUILL_NODISCARD std::string_view file_name() const noexcept
70  {
71  return std::string_view{_source_location + _file_name_pos,
72  static_cast<size_t>(_colon_separator_pos - _file_name_pos)};
73  }
74 
75  QUILL_NODISCARD char const* short_source_location() const noexcept
76  {
77  return _source_location + _file_name_pos;
78  }
79 
80  QUILL_NODISCARD LogLevel log_level() const noexcept { return _log_level; }
81 
82  QUILL_NODISCARD char const* tags() const noexcept { return _tags; }
83 
84  QUILL_NODISCARD constexpr bool has_named_args() const noexcept
85  {
86  return _contains_named_args(_message_format);
87  }
88 
89  QUILL_NODISCARD Event event() const noexcept { return _event; }
90 
91  /***/
92  QUILL_NODISCARD static constexpr bool _contains_named_args(std::string_view fmt) noexcept
93  {
94  uint32_t pos{0};
95  bool found_named_arg{false};
96 
97  // Iterates the format string and checks if any characters are contained inside `{}`
98  while (pos < fmt.length())
99  {
100  if (fmt[pos] == '{')
101  {
102  ++pos; // consume {
103  if (pos >= fmt.length())
104  {
105  break;
106  }
107 
108  // first character after the {
109  auto const fc = fmt[pos];
110  if (fc == '{')
111  {
112  // this means first '{' was escaped, so we ignore both of them
113  ++pos;
114  continue;
115  }
116 
117  // else look for the next '}'
118  uint32_t char_cnt{0};
119  while (pos < fmt.length())
120  {
121  if (fmt[pos] == '}')
122  {
123  ++pos; // consume }
124  if (pos >= fmt.length())
125  {
126  break;
127  }
128 
129  if (fmt[pos] == '}')
130  {
131  // this means first '}', was escaped ignore it
132  ++pos;
133  ++char_cnt;
134  continue;
135  }
136 
137  // we found '{' match, we can break
138  break;
139  }
140 
141  ++pos;
142  ++char_cnt;
143  }
144 
145  if ((char_cnt != 0) && ((fc >= 'a' && fc <= 'z') || (fc >= 'A' && fc <= 'Z')))
146  {
147  found_named_arg = true;
148  }
149  }
150  ++pos;
151  }
152 
153  return found_named_arg;
154  }
155 
156 private:
157  /***/
158  QUILL_NODISCARD constexpr uint16_t _calc_file_name_pos() const noexcept
159  {
160  char const* source_location = _source_location;
161  char const* file = source_location;
162  while (*source_location)
163  {
164  char cur = *source_location++;
165  if (cur == '/' || cur == detail::PATH_PREFERRED_SEPARATOR)
166  {
167  file = source_location;
168  }
169  }
170  return static_cast<uint16_t>(file - _source_location);
171  }
172 
173  /***/
174  QUILL_NODISCARD constexpr uint16_t _calc_colon_separator_pos() const noexcept
175  {
176  std::string_view const source_loc{_source_location};
177  auto const separator_index = source_loc.rfind(':');
178  return static_cast<uint16_t>(separator_index);
179  }
180 
181 private:
182  char const* _source_location{nullptr};
183  char const* _caller_function{nullptr};
184  char const* _message_format{nullptr};
185  char const* _tags{nullptr};
186  uint16_t _colon_separator_pos{0};
187  uint16_t _file_name_pos{0};
188  LogLevel _log_level{LogLevel::None};
189  Event _event{Event::None};
190 };
191 
192 static_assert(sizeof(MacroMetadata) <= detail::QUILL_CACHE_LINE_SIZE,
193  "Size of MacroMetadata exceeds the cache line size");
194 
195 QUILL_END_NAMESPACE
Captures and stores information about a logging event in compile time.
Definition: MacroMetadata.h:22