constexpr support for source location without leading directory

This commit is contained in:
gabime 2023-10-01 23:54:54 +03:00
parent bd00a0081a
commit 61b11e77b9
3 changed files with 87 additions and 67 deletions

View File

@ -16,20 +16,13 @@
#include <type_traits>
#include "details/null_mutex.h"
#include "source_loc.h"
#include "tweakme.h"
#if __has_include(<version>)
#include <version>
#endif
#if __cpp_lib_source_location >= 201907
#include <source_location>
#define SPDLOG_HAVE_STD_SOURCE_LOCATION
#elif __has_include(<experimental/source_location>)
#include <experimental/source_location>
#define SPDLOG_HAVE_EXPERIMENTAL_SOURCE_LOCATION
#endif
#ifdef SPDLOG_USE_STD_FORMAT
#if __cpp_lib_format >= 202207L
#include <format>
@ -94,7 +87,7 @@ class sink;
#if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES)
using filename_t = std::wstring;
// allow macro expansion to occur in SPDLOG_FILENAME_T
// allow macro expansion to occur in SPDLOG_FILENAME_T
#define SPDLOG_FILENAME_T_INNER(s) L##s
#define SPDLOG_FILENAME_T(s) SPDLOG_FILENAME_T_INNER(s)
#else
@ -180,6 +173,7 @@ using atomic_level_t = std::atomic<level>;
[[nodiscard]] constexpr size_t level_to_number(level lvl) noexcept {
return static_cast<size_t>(lvl);
}
constexpr auto levels_count = level_to_number(level::n_levels);
constexpr std::array<string_view_t, levels_count> level_string_views SPDLOG_LEVEL_NAMES;
constexpr std::array<string_view_t, levels_count> short_level_names SPDLOG_SHORT_LEVEL_NAMES;
@ -214,7 +208,9 @@ enum class pattern_time_type {
class SPDLOG_API spdlog_ex : public std::exception {
public:
explicit spdlog_ex(std::string msg);
spdlog_ex(const std::string &msg, int last_errno);
[[nodiscard]] const char *what() const noexcept override;
private:
@ -222,54 +218,27 @@ private:
};
[[noreturn]] SPDLOG_API void throw_spdlog_ex(const std::string &msg, int last_errno);
[[noreturn]] SPDLOG_API void throw_spdlog_ex(std::string msg);
struct source_loc {
constexpr source_loc() = default;
constexpr source_loc(const char *filename_in,
std::uint_least32_t line_in,
const char *funcname_in)
: filename{filename_in},
line{line_in},
funcname{funcname_in} {}
#ifdef SPDLOG_HAVE_STD_SOURCE_LOCATION
static constexpr source_loc current(
const std::source_location source_location = std::source_location::current()) {
return source_loc{source_location.file_name(), source_location.line(),
source_location.function_name()};
}
#elif defined(SPDLOG_HAVE_EXPERIMENTAL_SOURCE_LOCATION)
static constexpr source_loc current(const std::experimental::source_location source_location =
std::experimental::source_location::current()) {
return source_loc{source_location.file_name(), source_location.line(),
source_location.function_name()};
}
#else // no source location support
static constexpr source_loc current() { return source_loc{}; }
#endif
[[nodiscard]] constexpr bool empty() const noexcept { return line == 0; }
const char *filename{nullptr};
std::uint_least32_t line{0};
const char *funcname{nullptr};
};
// trick to capture format string and caller's source location with variadic template.
// see logger::info() etc. to understand how it's used.
struct loc_with_fmt {
source_loc loc;
string_view_t fmt_string;
template <typename S, typename = is_convertible_to_sv<S>>
constexpr loc_with_fmt(S fmt_str, source_loc loc = source_loc::current()) noexcept
: loc(loc),
fmt_string(fmt_str) {}
#ifndef SPDLOG_USE_STD_FORMAT
constexpr loc_with_fmt(fmt::runtime_format_string<char> fmt_str,
source_loc loc = source_loc::current()) noexcept
: loc(loc),
fmt_string(fmt_str.str) {}
#endif
};
@ -324,11 +293,13 @@ template <typename T, typename... Args>
}
#endif
#else // {fmt} version
template <typename T, typename... Args>
[[nodiscard]] constexpr fmt::basic_string_view<T> to_string_view(
fmt::basic_format_string<T, Args...> fmt) noexcept {
return fmt;
}
#endif
} // namespace details

View File

@ -0,0 +1,74 @@
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
#pragma once
#include <cstdint>
#if __has_include(<version>)
#include <version>
#endif
#if __cpp_lib_source_location >= 201907
#include <source_location>
#define SPDLOG_HAVE_STD_SOURCE_LOCATION
#elif __has_include(<experimental/source_location>)
#include <experimental/source_location>
#define SPDLOG_HAVE_EXPERIMENTAL_SOURCE_LOCATION
#endif
namespace spdlog {
// source location - either initiated from std::source_location or from
// std::experimental::source_location or empty
struct source_loc {
constexpr source_loc() = default;
constexpr source_loc(const char *filename_in,
std::uint_least32_t line_in,
const char *funcname_in)
: filename{filename_in},
short_filename{basename(filename_in)},
line{line_in},
funcname{funcname_in} {}
#ifdef SPDLOG_HAVE_STD_SOURCE_LOCATION
static constexpr source_loc current(
const std::source_location source_location = std::source_location::current()) {
return source_loc{source_location.file_name(), source_location.line(),
source_location.function_name()};
}
#elif defined(SPDLOG_HAVE_EXPERIMENTAL_SOURCE_LOCATION)
static constexpr source_loc current(const std::experimental::source_location source_location =
std::experimental::source_location::current()) {
return source_loc{source_location.file_name(), source_location.line(),
source_location.function_name()};
}
#else // no source location support
static constexpr source_loc current() { return source_loc{}; }
#endif
[[nodiscard]] constexpr bool empty() const noexcept {
return line == 0 || filename == nullptr || short_filename == nullptr;
}
const char *filename{nullptr};
const char *short_filename{nullptr};
std::uint_least32_t line{0};
const char *funcname{nullptr};
// return filename without the leading path
static constexpr const char *basename(const char *path) {
const char *file = path;
while (*path) {
#ifdef _WIN32
if (*path == '\\' || *path == '/')
#else
if (*path == '/')
#endif
{
file = path + 1;
}
++path;
}
return file;
}
};
} // namespace spdlog

View File

@ -679,35 +679,12 @@ public:
explicit short_filename_formatter(padding_info padinfo)
: flag_formatter(padinfo) {}
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable : 4127) // consider using 'if constexpr' instead
#endif // _MSC_VER
static const char *basename(const char *filename) {
// if the size is 2 (1 character + null terminator) we can use the more efficient strrchr
// the branch will be elided by optimizations
if (sizeof(os::folder_seps) == 2) {
const char *rv = std::strrchr(filename, os::folder_seps[0]);
return rv != nullptr ? rv + 1 : filename;
} else {
const std::reverse_iterator<const char *> begin(filename + std::strlen(filename));
const std::reverse_iterator<const char *> end(filename);
const auto it = std::find_first_of(begin, end, std::begin(os::folder_seps),
std::end(os::folder_seps) - 1);
return it != end ? it.base() : filename;
}
}
#ifdef _MSC_VER
#pragma warning(pop)
#endif // _MSC_VER
void format(const details::log_msg &msg, const std::tm &, memory_buf_t &dest) override {
if (msg.source.empty()) {
ScopedPadder p(0, padinfo_, dest);
return;
}
auto filename = basename(msg.source.filename);
const char *filename = msg.source.short_filename;
size_t text_size = padinfo_.enabled() ? std::char_traits<char>::length(filename) : 0;
ScopedPadder p(text_size, padinfo_, dest);
fmt_helper::append_string_view(filename, dest);
@ -841,9 +818,7 @@ public:
// add source location if present
if (!msg.source.empty()) {
dest.push_back('[');
const char *filename =
details::short_filename_formatter<details::null_scoped_padder>::basename(
msg.source.filename);
const char *filename = msg.source.short_filename;
fmt_helper::append_string_view(filename, dest);
dest.push_back(':');
fmt_helper::append_int(msg.source.line, dest);