9 #include "quill/bundled/fmt/base.h" 11 #include "quill/core/Attributes.h" 12 #include "quill/core/DynamicFormatArgStore.h" 13 #include "quill/core/InlinedVector.h" 21 #include <string_view> 22 #include <type_traits> 30 #if defined(__MINGW32__) 31 #pragma GCC diagnostic push 32 #pragma GCC diagnostic ignored "-Wredundant-decls" 36 QUILL_NODISCARD QUILL_EXPORT QUILL_ATTRIBUTE_USED
extern std::string utf8_encode(std::wstring_view str);
37 QUILL_NODISCARD QUILL_EXPORT QUILL_ATTRIBUTE_USED
extern std::string utf8_encode(std::byte
const* data,
40 #if defined(__MINGW32__) 41 #pragma GCC diagnostic pop 51 typedef std::remove_cv_t<std::remove_reference_t<T>> type;
55 using remove_cvref_t =
typename remove_cvref<T>::type;
58 constexpr
bool always_false_v =
false;
60 template <
typename Arg>
61 void codec_not_found_for_type()
66 "+------------------------------------------------------------------------------+\n" 67 "| Missing Codec for Type 'Arg' |\n" 68 "+------------------------------------------------------------------------------+\n" 70 "Error: A codec for the specified type 'Arg' is not available.\n" 72 "Possible solutions:\n" 73 "1. If Arg is an STL type:\n" 74 " - Ensure you have included the necessary headers for the specific STL type you are using " 75 "from the quill/std folder.\n" 77 "2. If Arg is a user-defined type:\n" 78 " - Use either 'DeferredFormatCodec' or 'DirectFormatCodec'.\n" 79 " - Define a custom Codec for your type.\n" 80 " - Consider converting the value to a string before logging.\n" 82 "Note: The specific type of 'Arg' can be found in the compiler error message.\n" 83 " Look for the instantiation of 'codec_not_found_for_type<Arg>' in the error output.\n" 84 " The compiler should indicate what type 'Arg' represents in this instance.\n" 86 "For more information see https://quillcpp.readthedocs.io/en/latest/cheat_sheet.html\n");
90 QUILL_NODISCARD
inline size_t safe_strnlen(
char const* str,
size_t maxlen) noexcept
97 #if defined(__GNUC__) && !defined(__clang__) 99 #pragma GCC diagnostic push 101 #pragma GCC diagnostic ignored "-Wstringop-overread" 105 auto end =
static_cast<char const*
>(std::memchr(str,
'\0', maxlen));
107 #if defined(__GNUC__) && !defined(__clang__) 108 #pragma GCC diagnostic pop 111 return end ?
static_cast<size_t>(end - str) : maxlen;
115 QUILL_NODISCARD
inline size_t safe_strnlen(
char const* str) noexcept
117 #if defined(__i386__) || defined(__arm__) 121 static constexpr int32_t max_len = std::numeric_limits<int32_t>::max();
123 static constexpr uint32_t max_len = std::numeric_limits<uint32_t>::max();
126 return safe_strnlen(str, max_len);
129 template <
typename T>
134 template <
typename Allocator>
135 struct is_std_string<
std::basic_string<char, std::char_traits<char>, Allocator>> : std::true_type
141 template <
typename Arg,
typename =
void>
145 QUILL_NODISCARD QUILL_ATTRIBUTE_HOT
static size_t compute_encoded_size(
146 QUILL_MAYBE_UNUSED
detail::SizeCacheVector& conditional_arg_size_cache, QUILL_MAYBE_UNUSED Arg
const& arg) noexcept
148 if constexpr (std::disjunction_v<std::is_arithmetic<Arg>, std::is_enum<Arg>,
149 std::is_same<Arg, void const*>, std::is_same<Arg, void*>>)
153 else if constexpr (std::conjunction_v<std::is_array<Arg>, std::is_same<detail::remove_cvref_t<std::remove_extent_t<Arg>>,
char>>)
155 size_t constexpr N = std::extent_v<Arg>;
156 size_t len = detail::safe_strnlen(arg, N) + 1u;
157 if (QUILL_UNLIKELY(len > std::numeric_limits<uint32_t>::max()))
159 len = std::numeric_limits<uint32_t>::max();
161 return conditional_arg_size_cache.push_back(static_cast<uint32_t>(len));
163 else if constexpr (std::disjunction_v<std::is_same<Arg, char*>, std::is_same<Arg, char const*>>)
167 size_t len = detail::safe_strnlen(arg) + 1u;
168 if (QUILL_UNLIKELY(len > std::numeric_limits<uint32_t>::max()))
170 len = std::numeric_limits<uint32_t>::max();
172 return conditional_arg_size_cache.push_back(static_cast<uint32_t>(len));
180 return sizeof(uint32_t) + static_cast<uint32_t>(arg.length());
184 detail::codec_not_found_for_type<Arg>();
190 QUILL_ATTRIBUTE_HOT
static void encode(std::byte*& buffer,
192 QUILL_MAYBE_UNUSED uint32_t& conditional_arg_size_cache_index,
193 Arg
const& arg) noexcept
195 if constexpr (std::disjunction_v<std::is_arithmetic<Arg>, std::is_enum<Arg>,
196 std::is_same<Arg, void const*>, std::is_same<Arg, void*>>)
198 std::memcpy(buffer, &arg,
sizeof(Arg));
199 buffer +=
sizeof(Arg);
201 else if constexpr (std::conjunction_v<std::is_array<Arg>, std::is_same<detail::remove_cvref_t<std::remove_extent_t<Arg>>,
char>>)
203 size_t constexpr N = std::extent_v<Arg>;
204 uint32_t
const len = conditional_arg_size_cache[conditional_arg_size_cache_index++];
206 if (QUILL_UNLIKELY(len > N))
209 assert(len == N + 1);
210 std::memcpy(buffer, arg, N);
211 buffer[N] = std::byte{
'\0'};
215 std::memcpy(buffer, arg, len);
220 else if constexpr (std::disjunction_v<std::is_same<Arg, char*>, std::is_same<Arg, char const*>>)
223 uint32_t
const len = conditional_arg_size_cache[conditional_arg_size_cache_index++];
228 std::memcpy(buffer, arg, len - 1);
231 buffer[len - 1] = std::byte{
'\0'};
238 auto const len =
static_cast<uint32_t
>(arg.length());
239 std::memcpy(buffer, &len,
sizeof(len));
240 buffer +=
sizeof(len);
241 std::memcpy(buffer, arg.data(), len);
246 detail::codec_not_found_for_type<Arg>();
256 static auto decode_arg(std::byte*& buffer)
258 if constexpr (std::disjunction_v<std::is_arithmetic<Arg>, std::is_enum<Arg>,
259 std::is_same<Arg, void const*>, std::is_same<Arg, void*>>)
262 std::memcpy(&arg, buffer,
sizeof(Arg));
263 buffer +=
sizeof(Arg);
266 else if constexpr (std::disjunction_v<std::is_same<Arg, char*>, std::is_same<Arg, char const*>,
267 std::conjunction<std::is_array<Arg>, std::is_same<detail::remove_cvref_t<std::remove_extent_t<Arg>>,
char>>>)
270 auto arg =
reinterpret_cast<char const*
>(buffer);
272 buffer += detail::safe_strnlen(arg) + 1u;
279 std::memcpy(&len, buffer,
sizeof(len));
280 buffer +=
sizeof(len);
281 auto const arg = std::string_view{
reinterpret_cast<char const*
>(buffer), len};
287 detail::codec_not_found_for_type<Arg>();
295 if constexpr (std::disjunction_v<std::is_arithmetic<Arg>, std::is_enum<Arg>,
296 std::is_same<Arg, void const*>, std::is_same<Arg, void*>>)
298 args_store->
push_back(decode_arg(buffer));
300 else if constexpr (std::disjunction_v<std::is_same<Arg, char*>, std::is_same<Arg, char const*>,
301 std::conjunction<std::is_array<Arg>, std::is_same<detail::remove_cvref_t<std::remove_extent_t<Arg>>,
char>>>)
304 char const* arg = decode_arg(buffer);
309 args_store->
push_back(fmtquill::string_view{arg, detail::safe_strnlen(arg)});
313 std::string_view arg = decode_arg(buffer);
318 args_store->
push_back(fmtquill::string_view{arg.data(), arg.size()});
322 detail::codec_not_found_for_type<Arg>();
336 template <
typename... Args>
338 QUILL_MAYBE_UNUSED
SizeCacheVector& conditional_arg_size_cache, Args
const&... args)
340 if constexpr (!std::conjunction_v<std::disjunction<
341 std::is_arithmetic<remove_cvref_t<Args>>, std::is_enum<remove_cvref_t<Args>>,
342 std::is_same<remove_cvref_t<Args>,
void const*>, std::is_same<remove_cvref_t<Args>,
void*>,
343 is_std_string<remove_cvref_t<Args>>, std::is_same<remove_cvref_t<Args>, std::string_view>>...>)
347 conditional_arg_size_cache.clear();
364 template <
typename... Args>
368 QUILL_MAYBE_UNUSED uint32_t conditional_arg_size_cache_index{0};
373 template <
typename... Args>
384 template <
typename... Args>
388 decode_and_store_arg<Args...>(buffer, &args_store);
394 template <
typename... TMembers>
395 size_t compute_total_encoded_size(
detail::SizeCacheVector& conditional_arg_size_cache, TMembers
const&... members)
397 size_t total_size{0};
404 template <
typename... TMembers>
406 uint32_t& conditional_arg_size_cache_index, TMembers
const&... members)
409 conditional_arg_size_cache_index, members)),
414 template <
typename T,
typename... TMembers>
415 void decode_members(std::byte*&
buffer, T&, TMembers&... members)
void(*)(std::byte *&data, DynamicFormatArgStore &args_store) FormatArgsDecoder
Decode functions.
Definition: Codec.h:382
QUILL_NODISCARD QUILL_ATTRIBUTE_HOT size_t compute_encoded_size_and_cache_string_lengths(QUILL_MAYBE_UNUSED SizeCacheVector &conditional_arg_size_cache, Args const &... args)
Calculates the total size required to encode the provided arguments.
Definition: Codec.h:337
Setups a signal handler to handle fatal signals.
Definition: BackendManager.h:24
typename = void for specializations with enable_if
Definition: Codec.h:142
QUILL_ATTRIBUTE_HOT void encode(std::byte *&buffer, SizeCacheVector const &conditional_arg_size_cache, Args const &... args)
Encodes multiple arguments into a buffer.
Definition: Codec.h:365
C++14 implementation of C++20's remove_cvref.
Definition: Codec.h:49
std string detection, ignoring the Allocator type
Definition: Codec.h:130
A contiguous memory buffer with an optional growing ability.
Definition: base.h:1751