mirror of
https://github.com/gabime/spdlog.git
synced 2024-12-25 01:51:38 +08:00
constexpr support for source location without leading directory
This commit is contained in:
parent
bd00a0081a
commit
61b11e77b9
@ -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
|
||||
|
74
include/spdlog/source_loc.h
Normal file
74
include/spdlog/source_loc.h
Normal 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
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user