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" 20 #include <string_view> 21 #include <type_traits> 29 #if defined(__MINGW32__) 30 #pragma GCC diagnostic push 31 #pragma GCC diagnostic ignored "-Wredundant-decls" 35 QUILL_NODISCARD QUILL_EXPORT QUILL_ATTRIBUTE_USED
extern std::string utf8_encode(std::wstring_view str);
36 QUILL_NODISCARD QUILL_EXPORT QUILL_ATTRIBUTE_USED
extern std::string utf8_encode(std::byte
const* data,
39 #if defined(__MINGW32__) 40 #pragma GCC diagnostic pop 50 typedef std::remove_cv_t<std::remove_reference_t<T>> type;
54 using remove_cvref_t =
typename remove_cvref<T>::type;
57 constexpr
bool always_false_v =
false;
59 template <
typename Arg>
60 void codec_not_found_for_type()
65 "+------------------------------------------------------------------------------+\n" 66 "| Missing Codec for Type 'Arg' |\n" 67 "+------------------------------------------------------------------------------+\n" 69 "Error: A codec for the specified type 'Arg' is not available.\n" 71 "Possible solutions:\n" 72 "1. If Arg is an STL type:\n" 73 " - Ensure you have included the necessary headers for the specific STL type you are using " 74 "from the quill/std folder.\n" 76 "2. If Arg is a user-defined type:\n" 77 " - Use either 'DeferredFormatCodec' or 'DirectFormatCodec'.\n" 78 " - Define a custom Codec for your type.\n" 79 " - Consider converting the value to a string before logging.\n" 81 "Note: The specific type of 'Arg' can be found in the compiler error message.\n" 82 " Look for the instantiation of 'codec_not_found_for_type<Arg>' in the error output.\n" 83 " The compiler should indicate what type 'Arg' represents in this instance.\n" 85 "For more information see https://quillcpp.readthedocs.io/en/latest/cheat_sheet.html\n");
89 QUILL_NODISCARD
inline size_t safe_strnlen(
char const* str,
size_t maxlen) noexcept
96 #if defined(__GNUC__) && !defined(__clang__) 98 #pragma GCC diagnostic push 100 #pragma GCC diagnostic ignored "-Wstringop-overread" 104 asm volatile(
"" :
"+r"(maxlen) : :
"memory");
107 auto end =
static_cast<char const*
>(std::memchr(str,
'\0', maxlen));
109 #if defined(__GNUC__) && !defined(__clang__) 110 #pragma GCC diagnostic pop 113 return end ?
static_cast<size_t>(end - str) : maxlen;
117 QUILL_NODISCARD
inline size_t safe_strnlen(
char const* str) noexcept
119 #if defined(__i386__) || defined(__arm__) 123 static constexpr int32_t max_len = std::numeric_limits<int32_t>::max();
125 static constexpr uint32_t max_len = std::numeric_limits<uint32_t>::max();
128 return safe_strnlen(str, max_len);
131 template <
typename T>
136 template <
typename Allocator>
137 struct is_std_string<
std::basic_string<char, std::char_traits<char>, Allocator>> : std::true_type
143 template <
typename Arg,
typename =
void>
147 QUILL_NODISCARD QUILL_ATTRIBUTE_HOT
static size_t compute_encoded_size(
148 QUILL_MAYBE_UNUSED
detail::SizeCacheVector& conditional_arg_size_cache, QUILL_MAYBE_UNUSED Arg
const& arg) noexcept
150 if constexpr (std::disjunction_v<std::is_arithmetic<Arg>, std::is_enum<Arg>,
151 std::is_same<Arg, void const*>, std::is_same<Arg, void*>>)
155 else if constexpr (std::conjunction_v<std::is_array<Arg>, std::is_same<detail::remove_cvref_t<std::remove_extent_t<Arg>>,
char>>)
157 size_t constexpr N = std::extent_v<Arg>;
158 size_t len = detail::safe_strnlen(arg, N) + 1u;
159 if (QUILL_UNLIKELY(len > std::numeric_limits<uint32_t>::max()))
161 len = std::numeric_limits<uint32_t>::max();
163 return conditional_arg_size_cache.push_back(static_cast<uint32_t>(len));
165 else if constexpr (std::disjunction_v<std::is_same<Arg, char*>, std::is_same<Arg, char const*>>)
169 size_t len = detail::safe_strnlen(arg) + 1u;
170 if (QUILL_UNLIKELY(len > std::numeric_limits<uint32_t>::max()))
172 len = std::numeric_limits<uint32_t>::max();
174 return conditional_arg_size_cache.push_back(static_cast<uint32_t>(len));
182 return sizeof(uint32_t) + static_cast<uint32_t>(arg.length());
186 detail::codec_not_found_for_type<Arg>();
192 QUILL_ATTRIBUTE_HOT
static void encode(std::byte*& buffer,
194 QUILL_MAYBE_UNUSED uint32_t& conditional_arg_size_cache_index,
195 Arg
const& arg) noexcept
197 if constexpr (std::disjunction_v<std::is_arithmetic<Arg>, std::is_enum<Arg>,
198 std::is_same<Arg, void const*>, std::is_same<Arg, void*>>)
200 std::memcpy(buffer, &arg,
sizeof(Arg));
201 buffer +=
sizeof(Arg);
203 else if constexpr (std::conjunction_v<std::is_array<Arg>, std::is_same<detail::remove_cvref_t<std::remove_extent_t<Arg>>,
char>>)
205 size_t constexpr N = std::extent_v<Arg>;
206 uint32_t
const len = conditional_arg_size_cache[conditional_arg_size_cache_index++];
209 std::byte* buf_ptr = buffer;
211 if (QUILL_UNLIKELY(len > N))
214 QUILL_ASSERT(len == N + 1,
"Invalid length for c array in Codec::encode(), expected N + 1");
215 std::memcpy(buf_ptr, arg, N);
216 buf_ptr[N] = std::byte{
'\0'};
220 std::memcpy(buf_ptr, arg, len);
223 buffer = buf_ptr + len;
225 else if constexpr (std::disjunction_v<std::is_same<Arg, char*>, std::is_same<Arg, char const*>>)
228 uint32_t
const len = conditional_arg_size_cache[conditional_arg_size_cache_index++];
231 std::byte* buf_ptr = buffer;
233 if (QUILL_LIKELY(arg !=
nullptr))
236 std::memcpy(buf_ptr, arg, len - 1);
239 buf_ptr[len - 1] = std::byte{
'\0'};
240 buffer = buf_ptr + len;
246 auto const len =
static_cast<uint32_t
>(arg.length());
249 std::byte* buf_ptr = buffer;
250 std::memcpy(buf_ptr, &len,
sizeof(len));
251 buf_ptr +=
sizeof(len);
254 if (QUILL_LIKELY(len != 0))
256 std::memcpy(buf_ptr, arg.data(), len);
259 buffer = buf_ptr + len;
263 detail::codec_not_found_for_type<Arg>();
273 static auto decode_arg(std::byte*& buffer)
275 if constexpr (std::disjunction_v<std::is_arithmetic<Arg>, std::is_enum<Arg>,
276 std::is_same<Arg, void const*>, std::is_same<Arg, void*>>)
279 std::memcpy(&arg, buffer,
sizeof(Arg));
280 buffer +=
sizeof(Arg);
283 else if constexpr (std::disjunction_v<std::is_same<Arg, char*>, std::is_same<Arg, char const*>,
284 std::conjunction<std::is_array<Arg>, std::is_same<detail::remove_cvref_t<std::remove_extent_t<Arg>>,
char>>>)
287 auto arg =
reinterpret_cast<char const*
>(buffer);
289 buffer += detail::safe_strnlen(arg) + 1u;
296 std::memcpy(&len, buffer,
sizeof(len));
297 buffer +=
sizeof(len);
298 auto const arg = std::string_view{
reinterpret_cast<char const*
>(buffer), len};
304 detail::codec_not_found_for_type<Arg>();
312 if constexpr (std::disjunction_v<std::is_arithmetic<Arg>, std::is_enum<Arg>,
313 std::is_same<Arg, void const*>, std::is_same<Arg, void*>>)
315 args_store->
push_back(decode_arg(buffer));
317 else if constexpr (std::disjunction_v<std::is_same<Arg, char*>, std::is_same<Arg, char const*>,
318 std::conjunction<std::is_array<Arg>, std::is_same<detail::remove_cvref_t<std::remove_extent_t<Arg>>,
char>>>)
321 char const* arg = decode_arg(buffer);
326 args_store->
push_back(fmtquill::string_view{arg, detail::safe_strnlen(arg)});
330 std::string_view arg = decode_arg(buffer);
335 args_store->
push_back(fmtquill::string_view{arg.data(), arg.size()});
339 detail::codec_not_found_for_type<Arg>();
353 template <
typename... Args>
355 QUILL_MAYBE_UNUSED
SizeCacheVector& conditional_arg_size_cache, Args
const&... args)
357 if constexpr (!std::conjunction_v<std::disjunction<std::is_arithmetic<remove_cvref_t<Args>>, std::is_same<remove_cvref_t<Args>,
void const*>,
358 std::is_same<remove_cvref_t<Args>,
void*>,
is_std_string<remove_cvref_t<Args>>,
359 std::is_same<remove_cvref_t<Args>, std::string_view>>...>)
363 conditional_arg_size_cache.clear();
380 template <
typename... Args>
384 QUILL_MAYBE_UNUSED uint32_t conditional_arg_size_cache_index{0};
386 static_cast<decltype(args)&&
>(args)),
390 template <
typename... Args>
401 template <
typename... Args>
404 decode_and_store_arg<Args...>(buffer, &args_store);
410 template <
typename... TMembers>
411 size_t compute_total_encoded_size(
detail::SizeCacheVector& conditional_arg_size_cache, TMembers
const&... members)
413 size_t total_size{0};
420 template <
typename... TMembers>
422 uint32_t& conditional_arg_size_cache_index, TMembers
const&... members)
425 conditional_arg_size_cache_index, members)),
430 template <
typename T,
typename... TMembers>
431 void decode_members(std::byte*&
buffer, T&, TMembers&... members)
Definition: UserDefinedDirectFormatFuzzer.cpp:81
void(*)(std::byte *&data, DynamicFormatArgStore &args_store) FormatArgsDecoder
Decode functions.
Definition: Codec.h:399
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:354
Setups a signal handler to handle fatal signals.
Definition: BackendManager.h:24
typename = void for specializations with enable_if
Definition: Codec.h:144
QUILL_ATTRIBUTE_HOT void encode(std::byte *&buffer, SizeCacheVector const &conditional_arg_size_cache, Args &&... args)
Encodes multiple arguments into a buffer.
Definition: Codec.h:381
C++14 implementation of C++20's remove_cvref.
Definition: Codec.h:48
std string detection, ignoring the Allocator type
Definition: Codec.h:132
A contiguous memory buffer with an optional growing ability.
Definition: base.h:1777