Compare commits

...

37 Commits

Author SHA1 Message Date
Gabi Melman
616caa5d30 Version 1.7.0 2020-07-09 20:24:20 +03:00
Gabi Melman
8236ee3ff6 Update version.h 2020-07-08 19:46:57 +03:00
Gabi Melman
19f2804661 Fix #1611 2020-07-08 18:50:51 +03:00
Gabi Melman
c62ba5f48d Merge pull request #1606 from candrews/fmt-7
fmt 7.0.0 renamed the internal namespace to detail.
2020-07-06 20:41:13 +03:00
Craig Andrews
22bee8128a fmt 7.0.0 renamed the internal namespace to detail.
See: https://github.com/fmtlib/fmt/issues/1538
2020-07-06 13:01:52 -04:00
Gabi Melman
39150eb8c7 Update README.md 2020-06-18 18:43:12 +03:00
Gabi Melman
1b14fa53ef Merge pull request #1591 from Pospelove/cmake-cleanup
Cleanup options-related lines in CMakeLists.txt
2020-06-12 15:29:57 +03:00
Leonid Pospelov
cf55e5d4f8 Cleanup options-related lines in CMakeLists.txt 2020-06-12 14:30:49 +03:00
Gabi Melman
1a1ea028f6 Merge pull request #1587 from podsvirov/increased-tolerance-waiting-time-for-mingw
Twice tolerance waiting time with MinGW
2020-06-10 23:47:19 +03:00
Gabi Melman
814c3445a3 Merge pull request #1586 from podsvirov/fix-shared-non-msvc
Fix shared library building failure on Windows with non MSVC
2020-06-10 23:46:46 +03:00
Konstantin Podsvirov
075dcee042 Twice tolerance waiting time with MinGW
Increased tolerance waiting time for MinGW in dequeue-empty-nowait test
case, because this test case not passed on slow and powerful computers.
2020-06-10 23:44:30 +03:00
Konstantin Podsvirov
fe97a03033 Fix shared library building failure on Windows with non MSVC
For example, now we can built shared library on Window with MinGW.

This changes improve features added in #1467.
2020-06-10 22:56:53 +03:00
Gabi Melman
f593aad786 Update .travis.yml 2020-06-08 18:03:55 +03:00
Gabi Melman
4a8c602a59 Update .travis.yml 2020-06-08 18:03:43 +03:00
Gabi Melman
7143dbc46a Update appveyor.yml 2020-06-08 03:29:58 +03:00
gabime
e69699e12c enable_if 2020-06-08 00:38:30 +03:00
gabime
d6dbdbf27a Revert 7f15fb2a21 since it breaks the ABI 2020-06-07 14:50:57 +03:00
gabime
a0dae55a69 Revert 7f15fb2a21 since it breaks the ABI 2020-06-07 14:38:16 +03:00
Gabi Melman
7f15fb2a21 Merge pull request #1580 from TamasFlorin/custom_rotating_filename
Add support for custom filename calculator in rotating_file_sink.
2020-06-06 22:25:52 +03:00
Tamas Florin
d5aa8db36f Add missing os include for rotating_file_sink. 2020-06-06 21:08:03 +03:00
gabime
357b6c9d8c Added FMT_STRING bench 2020-06-06 14:26:50 +03:00
gabime
b0c4794305 Use default pointer type in enable_if 2020-06-06 14:25:36 +03:00
Tamas Florin
071206ef59 Add support for custom filename calculator in rotating_file_sink. 2020-06-04 13:38:21 +03:00
Gabi Melman
63ab8e6341 Merge pull request #1574 from Tridacnid/tridacnid/FMT_STRING
Add support for FMT_STRING compile time checking.
2020-06-04 11:42:01 +03:00
Joe Burzinski
741b0d6e82 Address code review comments: remove perfect forwarding on FormatString template parameters. 2020-06-03 21:47:48 -05:00
Joe Burzinski
3041faffab Address code review comments: revert perfect forwarding on places that didn't need it, remove negative compilation unit test. 2020-06-02 20:30:25 -05:00
Joe Burzinski
30ee690401 Add support for FMT_STRING compile time checking. Add negative compilation unit test for compilers and c++ standard that support relaxed constexpr. 2020-05-31 13:15:40 -05:00
gabime
22a169bc31 Merge branch 'v1.x' of https://github.com/gabime/spdlog into v1.x 2020-05-27 00:02:51 +03:00
Gabi Melman
ac19803d03 Merge pull request #1571 from IIFE/filename-deadlock
fix deadlock on filename() call. Thanks @IIFE
2020-05-27 00:01:58 +03:00
IIFEgit
95485ee89b keep filename as it's public 2020-05-26 21:59:57 +01:00
gabime
bc61f69058 Bump fmt version to 6.2.1 2020-05-26 23:47:57 +03:00
IIFEgit
0b86d6a451 fix deadlock on filename() call 2020-05-26 21:35:04 +01:00
gabime
0317731dc9 Fix #1569 2020-05-26 23:34:17 +03:00
Gabi Melman
3dedb52163 Merged again pr #1563 2020-05-20 22:50:35 +03:00
Gabi Melman
ad393b83a2 Revert 01dac453db 2020-05-20 22:39:25 +03:00
Gabi Melman
01dac453db Merge pull request #1563 from vekkuli/fix_ringbuffer_sink_last
Fixed ringbuffer_sink last_raw and last_formatted
2020-05-20 22:30:46 +03:00
Jaakko Rantala
03abdf49a0 Fixed ringbuffer_sink last_raw and last_formatted giving the first lim number of elements instead of last. 2020-05-20 19:05:24 +03:00
19 changed files with 208 additions and 254 deletions

View File

@@ -101,10 +101,10 @@ script:
-DCMAKE_CXX_STANDARD=$CPP \ -DCMAKE_CXX_STANDARD=$CPP \
-DSPDLOG_BUILD_EXAMPLE=ON \ -DSPDLOG_BUILD_EXAMPLE=ON \
-DSPDLOG_BUILD_EXAMPLE_HO=ON \ -DSPDLOG_BUILD_EXAMPLE_HO=ON \
-DSPDLOG_ENABLE_WARNINGS=ON \ -DSPDLOG_BUILD_WARNINGS=ON \
-DSPDLOG_BUILD_BENCH=OFF \ -DSPDLOG_BUILD_BENCH=OFF \
-DSPDLOG_BUILD_TESTS=ON \ -DSPDLOG_BUILD_TESTS=ON \
-DSPDLOG_BUILD_TESTS_HO=OFf \ -DSPDLOG_BUILD_TESTS_HO=OFF \
-DSPDLOG_SANITIZE_ADDRESS=$ASAN -DSPDLOG_SANITIZE_ADDRESS=$ASAN
- make VERBOSE=1 -j2 - make VERBOSE=1 -j2

View File

@@ -131,16 +131,15 @@ if(NOT SPDLOG_FMT_EXTERNAL AND NOT SPDLOG_FMT_EXTERNAL_HO)
list(APPEND SPDLOG_SRCS src/fmt.cpp) list(APPEND SPDLOG_SRCS src/fmt.cpp)
endif() endif()
if(WIN32 AND SPDLOG_BUILD_SHARED)
list(APPEND SPDLOG_SRCS ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
endif()
if(SPDLOG_BUILD_SHARED) if(SPDLOG_BUILD_SHARED)
if(WIN32)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/version.rc.in ${CMAKE_CURRENT_BINARY_DIR}/version.rc @ONLY)
list(APPEND SPDLOG_SRCS ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
endif()
add_library(spdlog SHARED ${SPDLOG_SRCS} ${SPDLOG_ALL_HEADERS}) add_library(spdlog SHARED ${SPDLOG_SRCS} ${SPDLOG_ALL_HEADERS})
target_compile_definitions(spdlog PUBLIC SPDLOG_SHARED_LIB) target_compile_definitions(spdlog PUBLIC SPDLOG_SHARED_LIB)
if(WIN32) if(MSVC)
target_compile_options(spdlog PUBLIC /wd4251 /wd4275) target_compile_options(spdlog PUBLIC /wd4251 /wd4275)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/version.rc.in ${CMAKE_CURRENT_BINARY_DIR}/version.rc @ONLY)
endif() endif()
if(NOT SPDLOG_FMT_EXTERNAL AND NOT SPDLOG_FMT_EXTERNAL_HO) if(NOT SPDLOG_FMT_EXTERNAL AND NOT SPDLOG_FMT_EXTERNAL_HO)
target_compile_definitions(spdlog PRIVATE FMT_EXPORT PUBLIC FMT_SHARED) target_compile_definitions(spdlog PRIVATE FMT_EXPORT PUBLIC FMT_SHARED)
@@ -200,49 +199,25 @@ endif()
# --------------------------------------------------------------------------------------- # ---------------------------------------------------------------------------------------
# Misc definitions according to tweak options # Misc definitions according to tweak options
# --------------------------------------------------------------------------------------- # ---------------------------------------------------------------------------------------
if(SPDLOG_WCHAR_SUPPORT) set(SPDLOG_WCHAR_TO_UTF8_SUPPORT ${SPDLOG_WCHAR_SUPPORT})
target_compile_definitions(spdlog PUBLIC SPDLOG_WCHAR_TO_UTF8_SUPPORT) foreach(SPDLOG_OPTION
target_compile_definitions(spdlog_header_only INTERFACE SPDLOG_WCHAR_TO_UTF8_SUPPORT) SPDLOG_WCHAR_TO_UTF8_SUPPORT
endif() SPDLOG_WCHAR_FILENAMES
SPDLOG_NO_EXCEPTIONS
if(SPDLOG_WCHAR_FILENAMES) SPDLOG_CLOCK_COARSE
target_compile_definitions(spdlog PUBLIC SPDLOG_WCHAR_FILENAMES) SPDLOG_PREVENT_CHILD_FD
target_compile_definitions(spdlog_header_only INTERFACE SPDLOG_WCHAR_FILENAMES) SPDLOG_NO_THREAD_ID
endif() SPDLOG_NO_TLS
SPDLOG_NO_ATOMIC_LEVELS
if(SPDLOG_NO_EXCEPTIONS) )
target_compile_definitions(spdlog PUBLIC SPDLOG_NO_EXCEPTIONS) if(${SPDLOG_OPTION})
target_compile_definitions(spdlog PUBLIC ${SPDLOG_OPTION})
target_compile_definitions(spdlog_header_only INTERFACE SPDLOG_NO_EXCEPTIONS) target_compile_definitions(spdlog_header_only INTERFACE ${SPDLOG_OPTION})
if(NOT MSVC)
target_compile_options(spdlog PRIVATE -fno-exceptions)
endif() endif()
endif() endforeach()
if(SPDLOG_CLOCK_COARSE) if(SPDLOG_NO_EXCEPTIONS AND NOT MSVC)
target_compile_definitions(spdlog PRIVATE SPDLOG_CLOCK_COARSE) target_compile_options(spdlog PRIVATE -fno-exceptions)
target_compile_definitions(spdlog_header_only INTERFACE SPDLOG_CLOCK_COARSE)
endif()
if(SPDLOG_PREVENT_CHILD_FD)
target_compile_definitions(spdlog PRIVATE SPDLOG_PREVENT_CHILD_FD)
target_compile_definitions(spdlog_header_only INTERFACE SPDLOG_PREVENT_CHILD_FD)
endif()
if(SPDLOG_NO_THREAD_ID)
target_compile_definitions(spdlog PRIVATE SPDLOG_NO_THREAD_ID)
target_compile_definitions(spdlog_header_only INTERFACE SPDLOG_NO_THREAD_ID)
endif()
if(SPDLOG_NO_TLS)
target_compile_definitions(spdlog PRIVATE SPDLOG_NO_TLS)
target_compile_definitions(spdlog_header_only INTERFACE SPDLOG_NO_TLS)
endif()
if(SPDLOG_NO_ATOMIC_LEVELS)
target_compile_definitions(spdlog PUBLIC SPDLOG_NO_ATOMIC_LEVELS)
target_compile_definitions(spdlog_header_only INTERFACE SPDLOG_NO_ATOMIC_LEVELS)
endif() endif()
# --------------------------------------------------------------------------------------- # ---------------------------------------------------------------------------------------

View File

@@ -418,6 +418,6 @@ Documentation can be found in the [wiki](https://github.com/gabime/spdlog/wiki/1
--- ---
Thanks to [JetBrains](https://www.jetbrains.com/?from=spdlog) for donating licenses to their products to help developing **spdlog** <a href="https://www.jetbrains.com/?from=spdlog"><img src="logos/jetbrains-variant-4.svg" width="94" align="center" /></a> Thanks to [JetBrains](https://www.jetbrains.com/?from=spdlog) for donating product licenses to help develop **spdlog** <a href="https://www.jetbrains.com/?from=spdlog"><img src="logos/jetbrains-variant-4.svg" width="94" align="center" /></a>

View File

@@ -40,7 +40,7 @@ build_script:
set PATH=%PATH%;C:\Program Files\Git\usr\bin set PATH=%PATH%;C:\Program Files\Git\usr\bin
cmake .. -G %GENERATOR% -DCMAKE_BUILD_TYPE=%BUILD_TYPE% -DSPDLOG_WCHAR_SUPPORT=%WCHAR% -DSPDLOG_BUILD_SHARED=%BUILD_SHARED% -DSPDLOG_BUILD_EXAMPLE=ON -DSPDLOG_BUILD_EXAMPLE_HO=ON -DSPDLOG_BUILD_TESTS=ON -DSPDLOG_BUILD_TESTS_HO=OFF -DSPDLOG_ENABLE_WARNINGS=ON cmake .. -G %GENERATOR% -DCMAKE_BUILD_TYPE=%BUILD_TYPE% -DSPDLOG_WCHAR_SUPPORT=%WCHAR% -DSPDLOG_BUILD_SHARED=%BUILD_SHARED% -DSPDLOG_BUILD_EXAMPLE=ON -DSPDLOG_BUILD_EXAMPLE_HO=ON -DSPDLOG_BUILD_TESTS=ON -DSPDLOG_BUILD_TESTS_HO=OFF -DSPDLOG_BUILD_WARNINGS=ON
cmake --build . --config %BUILD_TYPE% cmake --build . --config %BUILD_TYPE%

View File

@@ -39,6 +39,16 @@ void bench_logger(benchmark::State &state, std::shared_ptr<spdlog::logger> logge
} }
} }
void bench_logger_fmt_string(benchmark::State &state, std::shared_ptr<spdlog::logger> logger)
{
int i = 0;
for (auto _ : state)
{
logger->info(FMT_STRING("Hello logger: msg number {}..............."), ++i);
;
}
}
void bench_disabled_macro(benchmark::State &state, std::shared_ptr<spdlog::logger> logger) void bench_disabled_macro(benchmark::State &state, std::shared_ptr<spdlog::logger> logger)
{ {
int i = 0; int i = 0;
@@ -88,6 +98,7 @@ int main(int argc, char *argv[])
auto null_logger_st = std::make_shared<spdlog::logger>("bench", std::make_shared<null_sink_st>()); auto null_logger_st = std::make_shared<spdlog::logger>("bench", std::make_shared<null_sink_st>());
benchmark::RegisterBenchmark("null_sink_st (500_bytes c_str)", bench_c_string, std::move(null_logger_st)); benchmark::RegisterBenchmark("null_sink_st (500_bytes c_str)", bench_c_string, std::move(null_logger_st));
benchmark::RegisterBenchmark("null_sink_st", bench_logger, null_logger_st); benchmark::RegisterBenchmark("null_sink_st", bench_logger, null_logger_st);
benchmark::RegisterBenchmark("null_sink_fmt_string", bench_logger_fmt_string, null_logger_st);
// with backtrace of 64 // with backtrace of 64
auto tracing_null_logger_st = std::make_shared<spdlog::logger>("bench", std::make_shared<null_sink_st>()); auto tracing_null_logger_st = std::make_shared<spdlog::logger>("bench", std::make_shared<null_sink_st>());
tracing_null_logger_st->enable_backtrace(64); tracing_null_logger_st->enable_backtrace(64);

View File

@@ -1,5 +1,5 @@
#define APSTUDIO_READONLY_SYMBOLS #define APSTUDIO_READONLY_SYMBOLS
#include "winres.h" #include <windows.h>
#undef APSTUDIO_READONLY_SYMBOLS #undef APSTUDIO_READONLY_SYMBOLS
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US

View File

@@ -34,7 +34,15 @@ template<typename T>
inline unsigned int count_digits(T n) inline unsigned int count_digits(T n)
{ {
using count_type = typename std::conditional<(sizeof(T) > sizeof(uint32_t)), uint64_t, uint32_t>::type; using count_type = typename std::conditional<(sizeof(T) > sizeof(uint32_t)), uint64_t, uint32_t>::type;
return static_cast<unsigned int>(fmt::internal::count_digits(static_cast<count_type>(n))); return static_cast<unsigned int>(fmt::
// fmt 7.0.0 renamed the internal namespace to detail.
// See: https://github.com/fmtlib/fmt/issues/1538
#if FMT_VERSION < 70000
internal
#else
detail
#endif
::count_digits(static_cast<count_type>(n)));
} }
inline void pad2(int n, memory_buf_t &dest) inline void pad2(int n, memory_buf_t &dest)

View File

@@ -84,7 +84,7 @@ SPDLOG_API bool is_color_terminal() SPDLOG_NOEXCEPT;
SPDLOG_API bool in_terminal(FILE *file) SPDLOG_NOEXCEPT; SPDLOG_API bool in_terminal(FILE *file) SPDLOG_NOEXCEPT;
#if (defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT) || defined(SPDLOG_WCHAR_FILENAMES)) && defined(_WIN32) #if (defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT) || defined(SPDLOG_WCHAR_FILENAMES)) && defined(_WIN32)
void wstr_to_utf8buf(wstring_view_t wstr, memory_buf_t &target); SPDLOG_API void wstr_to_utf8buf(wstring_view_t wstr, memory_buf_t &target);
#endif #endif
// Return directory name from given path or empty string // Return directory name from given path or empty string

View File

@@ -92,7 +92,7 @@ struct formatter<spdlog::details::dump_info<T>>
auto parse(ParseContext &ctx) -> decltype(ctx.begin()) auto parse(ParseContext &ctx) -> decltype(ctx.begin())
{ {
auto it = ctx.begin(); auto it = ctx.begin();
while (*it && *it != '}') while (it != ctx.end() && *it != '}')
{ {
switch (*it) switch (*it)
{ {

View File

@@ -18,7 +18,7 @@
#include <vector> #include <vector>
// The fmt library version in the form major * 10000 + minor * 100 + patch. // The fmt library version in the form major * 10000 + minor * 100 + patch.
#define FMT_VERSION 60200 #define FMT_VERSION 60201
#ifdef __has_feature #ifdef __has_feature
# define FMT_HAS_FEATURE(x) __has_feature(x) # define FMT_HAS_FEATURE(x) __has_feature(x)
@@ -830,7 +830,8 @@ template <typename Char> struct string_value {
template <typename Context> struct custom_value { template <typename Context> struct custom_value {
using parse_context = basic_format_parse_context<typename Context::char_type>; using parse_context = basic_format_parse_context<typename Context::char_type>;
const void* value; const void* value;
void (*format)(const void* arg, parse_context& parse_ctx, Context& ctx); void (*format)(const void* arg,
typename Context::parse_context_type& parse_ctx, Context& ctx);
}; };
// A formatting argument value. // A formatting argument value.
@@ -890,9 +891,9 @@ template <typename Context> class value {
private: private:
// Formats an argument of a custom type, such as a user-defined class. // Formats an argument of a custom type, such as a user-defined class.
template <typename T, typename Formatter> template <typename T, typename Formatter>
static void format_custom_arg( static void format_custom_arg(const void* arg,
const void* arg, basic_format_parse_context<char_type>& parse_ctx, typename Context::parse_context_type& parse_ctx,
Context& ctx) { Context& ctx) {
Formatter f; Formatter f;
parse_ctx.advance_to(f.parse(parse_ctx)); parse_ctx.advance_to(f.parse(parse_ctx));
ctx.advance_to(f.format(*static_cast<const T*>(arg), ctx)); ctx.advance_to(f.format(*static_cast<const T*>(arg), ctx));
@@ -1061,7 +1062,7 @@ template <typename Context> class basic_format_arg {
public: public:
explicit handle(internal::custom_value<Context> custom) : custom_(custom) {} explicit handle(internal::custom_value<Context> custom) : custom_(custom) {}
void format(basic_format_parse_context<char_type>& parse_ctx, void format(typename Context::parse_context_type& parse_ctx,
Context& ctx) const { Context& ctx) const {
custom_.format(custom_.value, parse_ctx, ctx); custom_.format(custom_.value, parse_ctx, ctx);
} }
@@ -1207,13 +1208,16 @@ FMT_CONSTEXPR basic_format_arg<Context> make_arg(const T& value) {
return arg; return arg;
} }
template <bool IS_PACKED, typename Context, typename T, // The type template parameter is there to avoid an ODR violation when using
// a fallback formatter in one translation unit and an implicit conversion in
// another (not recommended).
template <bool IS_PACKED, typename Context, type, typename T,
FMT_ENABLE_IF(IS_PACKED)> FMT_ENABLE_IF(IS_PACKED)>
inline value<Context> make_arg(const T& val) { inline value<Context> make_arg(const T& val) {
return arg_mapper<Context>().map(val); return arg_mapper<Context>().map(val);
} }
template <bool IS_PACKED, typename Context, typename T, template <bool IS_PACKED, typename Context, type, typename T,
FMT_ENABLE_IF(!IS_PACKED)> FMT_ENABLE_IF(!IS_PACKED)>
inline basic_format_arg<Context> make_arg(const T& value) { inline basic_format_arg<Context> make_arg(const T& value) {
return make_arg<Context>(value); return make_arg<Context>(value);
@@ -1272,6 +1276,7 @@ template <typename OutputIt, typename Char> class basic_format_context {
public: public:
using iterator = OutputIt; using iterator = OutputIt;
using format_arg = basic_format_arg<basic_format_context>; using format_arg = basic_format_arg<basic_format_context>;
using parse_context_type = basic_format_parse_context<Char>;
template <typename T> using formatter_type = formatter<T, char_type>; template <typename T> using formatter_type = formatter<T, char_type>;
basic_format_context(const basic_format_context&) = delete; basic_format_context(const basic_format_context&) = delete;
@@ -1346,7 +1351,9 @@ class format_arg_store
#if FMT_GCC_VERSION && FMT_GCC_VERSION < 409 #if FMT_GCC_VERSION && FMT_GCC_VERSION < 409
basic_format_args<Context>(*this), basic_format_args<Context>(*this),
#endif #endif
data_{internal::make_arg<is_packed, Context>(args)...} { data_{internal::make_arg<
is_packed, Context,
internal::mapped_type_constant<Args, Context>::value>(args)...} {
} }
}; };

View File

@@ -9,9 +9,14 @@
#define FMT_OSTREAM_H_ #define FMT_OSTREAM_H_
#include <ostream> #include <ostream>
#include "format.h" #include "format.h"
FMT_BEGIN_NAMESPACE FMT_BEGIN_NAMESPACE
template <typename CHar> class basic_printf_parse_context;
template <typename OutputIt, typename Char> class basic_printf_context;
namespace internal { namespace internal {
template <class Char> class formatbuf : public std::basic_streambuf<Char> { template <class Char> class formatbuf : public std::basic_streambuf<Char> {
@@ -93,9 +98,9 @@ void format_value(buffer<Char>& buf, const T& value,
locale_ref loc = locale_ref()) { locale_ref loc = locale_ref()) {
formatbuf<Char> format_buf(buf); formatbuf<Char> format_buf(buf);
std::basic_ostream<Char> output(&format_buf); std::basic_ostream<Char> output(&format_buf);
#if !defined(FMT_STATIC_THOUSANDS_SEPARATOR) #if !defined(FMT_STATIC_THOUSANDS_SEPARATOR)
if (loc) output.imbue(loc.get<std::locale>()); if (loc) output.imbue(loc.get<std::locale>());
#endif #endif
output.exceptions(std::ios_base::failbit | std::ios_base::badbit); output.exceptions(std::ios_base::failbit | std::ios_base::badbit);
output << value; output << value;
buf.resize(buf.size()); buf.resize(buf.size());
@@ -104,14 +109,32 @@ void format_value(buffer<Char>& buf, const T& value,
// Formats an object of type T that has an overloaded ostream operator<<. // Formats an object of type T that has an overloaded ostream operator<<.
template <typename T, typename Char> template <typename T, typename Char>
struct fallback_formatter<T, Char, enable_if_t<is_streamable<T, Char>::value>> struct fallback_formatter<T, Char, enable_if_t<is_streamable<T, Char>::value>>
: formatter<basic_string_view<Char>, Char> { : private formatter<basic_string_view<Char>, Char> {
template <typename Context> auto parse(basic_format_parse_context<Char>& ctx) -> decltype(ctx.begin()) {
auto format(const T& value, Context& ctx) -> decltype(ctx.out()) { return formatter<basic_string_view<Char>, Char>::parse(ctx);
}
template <typename ParseCtx,
FMT_ENABLE_IF(std::is_same<
ParseCtx, basic_printf_parse_context<Char>>::value)>
auto parse(ParseCtx& ctx) -> decltype(ctx.begin()) {
return ctx.begin();
}
template <typename OutputIt>
auto format(const T& value, basic_format_context<OutputIt, Char>& ctx)
-> OutputIt {
basic_memory_buffer<Char> buffer; basic_memory_buffer<Char> buffer;
format_value(buffer, value, ctx.locale()); format_value(buffer, value, ctx.locale());
basic_string_view<Char> str(buffer.data(), buffer.size()); basic_string_view<Char> str(buffer.data(), buffer.size());
return formatter<basic_string_view<Char>, Char>::format(str, ctx); return formatter<basic_string_view<Char>, Char>::format(str, ctx);
} }
template <typename OutputIt>
auto format(const T& value, basic_printf_context<OutputIt, Char>& ctx)
-> OutputIt {
basic_memory_buffer<Char> buffer;
format_value(buffer, value, ctx.locale());
return std::copy(buffer.begin(), buffer.end(), ctx.out());
}
}; };
} // namespace internal } // namespace internal

View File

@@ -189,6 +189,10 @@ using internal::printf; // For printing into memory_buffer.
template <typename Range> class printf_arg_formatter; template <typename Range> class printf_arg_formatter;
template <typename Char>
class basic_printf_parse_context : public basic_format_parse_context<Char> {
using basic_format_parse_context<Char>::basic_format_parse_context;
};
template <typename OutputIt, typename Char> class basic_printf_context; template <typename OutputIt, typename Char> class basic_printf_context;
/** /**
@@ -324,6 +328,7 @@ template <typename OutputIt, typename Char> class basic_printf_context {
using char_type = Char; using char_type = Char;
using iterator = OutputIt; using iterator = OutputIt;
using format_arg = basic_format_arg<basic_printf_context>; using format_arg = basic_format_arg<basic_printf_context>;
using parse_context_type = basic_printf_parse_context<Char>;
template <typename T> using formatter_type = printf_formatter<T>; template <typename T> using formatter_type = printf_formatter<T>;
private: private:
@@ -331,7 +336,7 @@ template <typename OutputIt, typename Char> class basic_printf_context {
OutputIt out_; OutputIt out_;
basic_format_args<basic_printf_context> args_; basic_format_args<basic_printf_context> args_;
basic_format_parse_context<Char> parse_ctx_; parse_context_type parse_ctx_;
static void parse_flags(format_specs& specs, const Char*& it, static void parse_flags(format_specs& specs, const Char*& it,
const Char* end); const Char* end);
@@ -362,7 +367,7 @@ template <typename OutputIt, typename Char> class basic_printf_context {
format_arg arg(int id) const { return args_.get(id); } format_arg arg(int id) const { return args_.get(id); }
basic_format_parse_context<Char>& parse_context() { return parse_ctx_; } parse_context_type& parse_context() { return parse_ctx_; }
FMT_CONSTEXPR void on_error(const char* message) { FMT_CONSTEXPR void on_error(const char* message) {
parse_ctx_.on_error(message); parse_ctx_.on_error(message);

View File

@@ -73,63 +73,58 @@ public:
void swap(spdlog::logger &other) SPDLOG_NOEXCEPT; void swap(spdlog::logger &other) SPDLOG_NOEXCEPT;
// FormatString is a type derived from fmt::compile_string
template<typename FormatString, typename std::enable_if<fmt::is_compile_string<FormatString>::value, int>::type = 0, typename... Args>
void log(source_loc loc, level::level_enum lvl, const FormatString &fmt, const Args &... args)
{
log_(loc, lvl, fmt, args...);
}
// FormatString is NOT a type derived from fmt::compile_string but is a string_view_t or can be implicitly converted to one
template<typename... Args> template<typename... Args>
void log(source_loc loc, level::level_enum lvl, string_view_t fmt, const Args &... args) void log(source_loc loc, level::level_enum lvl, string_view_t fmt, const Args &... args)
{ {
bool log_enabled = should_log(lvl); log_(loc, lvl, fmt, args...);
bool traceback_enabled = tracer_.enabled();
if (!log_enabled && !traceback_enabled)
{
return;
}
SPDLOG_TRY
{
memory_buf_t buf;
fmt::format_to(buf, fmt, args...);
details::log_msg log_msg(loc, name_, lvl, string_view_t(buf.data(), buf.size()));
log_it_(log_msg, log_enabled, traceback_enabled);
}
SPDLOG_LOGGER_CATCH()
} }
template<typename... Args> template<typename FormatString, typename... Args>
void log(level::level_enum lvl, string_view_t fmt, const Args &... args) void log(level::level_enum lvl, const FormatString &fmt, const Args &... args)
{ {
log(source_loc{}, lvl, fmt, args...); log(source_loc{}, lvl, fmt, args...);
} }
template<typename... Args> template<typename FormatString, typename... Args>
void trace(string_view_t fmt, const Args &... args) void trace(const FormatString &fmt, const Args &... args)
{ {
log(level::trace, fmt, args...); log(level::trace, fmt, args...);
} }
template<typename... Args> template<typename FormatString, typename... Args>
void debug(string_view_t fmt, const Args &... args) void debug(const FormatString &fmt, const Args &... args)
{ {
log(level::debug, fmt, args...); log(level::debug, fmt, args...);
} }
template<typename... Args> template<typename FormatString, typename... Args>
void info(string_view_t fmt, const Args &... args) void info(const FormatString &fmt, const Args &... args)
{ {
log(level::info, fmt, args...); log(level::info, fmt, args...);
} }
template<typename... Args> template<typename FormatString, typename... Args>
void warn(string_view_t fmt, const Args &... args) void warn(const FormatString &fmt, const Args &... args)
{ {
log(level::warn, fmt, args...); log(level::warn, fmt, args...);
} }
template<typename... Args> template<typename FormatString, typename... Args>
void error(string_view_t fmt, const Args &... args) void error(const FormatString &fmt, const Args &... args)
{ {
log(level::err, fmt, args...); log(level::err, fmt, args...);
} }
template<typename... Args> template<typename FormatString, typename... Args>
void critical(string_view_t fmt, const Args &... args) void critical(const FormatString &fmt, const Args &... args)
{ {
log(level::critical, fmt, args...); log(level::critical, fmt, args...);
} }
@@ -140,8 +135,9 @@ public:
log(source_loc{}, lvl, msg); log(source_loc{}, lvl, msg);
} }
// T can be statically converted to string_view // T can be statically converted to string_view and isn't a fmt::compile_string
template<class T, typename std::enable_if<std::is_convertible<const T &, spdlog::string_view_t>::value, T>::type * = nullptr> template<class T, typename std::enable_if<
std::is_convertible<const T &, spdlog::string_view_t>::value && !fmt::is_compile_string<T>::value, int>::type = 0>
void log(source_loc loc, level::level_enum lvl, const T &msg) void log(source_loc loc, level::level_enum lvl, const T &msg)
{ {
log(loc, lvl, string_view_t{msg}); log(loc, lvl, string_view_t{msg});
@@ -181,7 +177,7 @@ public:
// T cannot be statically converted to string_view or wstring_view // T cannot be statically converted to string_view or wstring_view
template<class T, typename std::enable_if<!std::is_convertible<const T &, spdlog::string_view_t>::value && template<class T, typename std::enable_if<!std::is_convertible<const T &, spdlog::string_view_t>::value &&
!is_convertible_to_wstring_view<const T &>::value, !is_convertible_to_wstring_view<const T &>::value,
T>::type * = nullptr> int>::type = 0>
void log(source_loc loc, level::level_enum lvl, const T &msg) void log(source_loc loc, level::level_enum lvl, const T &msg)
{ {
log(loc, lvl, "{}", msg); log(loc, lvl, "{}", msg);
@@ -251,50 +247,8 @@ public:
SPDLOG_LOGGER_CATCH() SPDLOG_LOGGER_CATCH()
} }
template<typename... Args>
void log(level::level_enum lvl, wstring_view_t fmt, const Args &... args)
{
log(source_loc{}, lvl, fmt, args...);
}
template<typename... Args>
void trace(wstring_view_t fmt, const Args &... args)
{
log(level::trace, fmt, args...);
}
template<typename... Args>
void debug(wstring_view_t fmt, const Args &... args)
{
log(level::debug, fmt, args...);
}
template<typename... Args>
void info(wstring_view_t fmt, const Args &... args)
{
log(level::info, fmt, args...);
}
template<typename... Args>
void warn(wstring_view_t fmt, const Args &... args)
{
log(level::warn, fmt, args...);
}
template<typename... Args>
void error(wstring_view_t fmt, const Args &... args)
{
log(level::err, fmt, args...);
}
template<typename... Args>
void critical(wstring_view_t fmt, const Args &... args)
{
log(level::critical, fmt, args...);
}
// T can be statically converted to wstring_view // T can be statically converted to wstring_view
template<class T, typename std::enable_if<is_convertible_to_wstring_view<const T &>::value, T>::type * = nullptr> template<class T, typename std::enable_if<is_convertible_to_wstring_view<const T &>::value, int>::type = 0>
void log(source_loc loc, level::level_enum lvl, const T &msg) void log(source_loc loc, level::level_enum lvl, const T &msg)
{ {
bool log_enabled = should_log(lvl); bool log_enabled = should_log(lvl);
@@ -370,6 +324,26 @@ protected:
err_handler custom_err_handler_{nullptr}; err_handler custom_err_handler_{nullptr};
details::backtracer tracer_; details::backtracer tracer_;
// common implementation for after templated public api has been resolved
template<typename FormatString, typename... Args>
void log_(source_loc loc, level::level_enum lvl, const FormatString &fmt, const Args &... args)
{
bool log_enabled = should_log(lvl);
bool traceback_enabled = tracer_.enabled();
if (!log_enabled && !traceback_enabled)
{
return;
}
SPDLOG_TRY
{
memory_buf_t buf;
fmt::format_to(buf, fmt, args...);
details::log_msg log_msg(loc, name_, lvl, string_view_t(buf.data(), buf.size()));
log_it_(log_msg, log_enabled, traceback_enabled);
}
SPDLOG_LOGGER_CATCH()
}
// log the given message (if the given log level is high enough), // log the given message (if the given log level is high enough),
// and save backtrace (if backtrace is enabled). // and save backtrace (if backtrace is enabled).
void log_it_(const details::log_msg &log_msg, bool log_enabled, bool traceback_enabled); void log_it_(const details::log_msg &log_msg, bool log_enabled, bool traceback_enabled);

View File

@@ -155,7 +155,7 @@ private:
using details::os::filename_to_str; using details::os::filename_to_str;
using details::os::remove_if_exists; using details::os::remove_if_exists;
filename_t current_file = filename(); filename_t current_file = file_helper_.filename();
if (filenames_q_.full()) if (filenames_q_.full())
{ {
auto old_filename = std::move(filenames_q_.front()); auto old_filename = std::move(filenames_q_.front());

View File

@@ -28,10 +28,11 @@ public:
std::vector<details::log_msg_buffer> last_raw(size_t lim = 0) std::vector<details::log_msg_buffer> last_raw(size_t lim = 0)
{ {
std::lock_guard<Mutex> lock(base_sink<Mutex>::mutex_); std::lock_guard<Mutex> lock(base_sink<Mutex>::mutex_);
auto n_items = lim > 0 ? (std::min)(lim, q_.size()) : q_.size(); auto items_available = q_.size();
auto n_items = lim > 0 ? (std::min)(lim, items_available) : items_available;
std::vector<details::log_msg_buffer> ret; std::vector<details::log_msg_buffer> ret;
ret.reserve(n_items); ret.reserve(n_items);
for (size_t i = 0; i < n_items; i++) for (size_t i = (items_available - n_items); i < items_available; i++)
{ {
ret.push_back(q_.at(i)); ret.push_back(q_.at(i));
} }
@@ -41,10 +42,11 @@ public:
std::vector<std::string> last_formatted(size_t lim = 0) std::vector<std::string> last_formatted(size_t lim = 0)
{ {
std::lock_guard<Mutex> lock(base_sink<Mutex>::mutex_); std::lock_guard<Mutex> lock(base_sink<Mutex>::mutex_);
auto n_items = lim > 0 ? (std::min)(lim, q_.size()) : q_.size(); auto items_available = q_.size();
auto n_items = lim > 0 ? (std::min)(lim, items_available) : items_available;
std::vector<std::string> ret; std::vector<std::string> ret;
ret.reserve(n_items); ret.reserve(n_items);
for (size_t i = 0; i < n_items; i++) for (size_t i = (items_available - n_items); i < items_available; i++)
{ {
memory_buf_t formatted; memory_buf_t formatted;
base_sink<Mutex>::formatter_->format(q_.at(i), formatted); base_sink<Mutex>::formatter_->format(q_.at(i), formatted);

View File

@@ -121,50 +121,50 @@ SPDLOG_API spdlog::logger *default_logger_raw();
SPDLOG_API void set_default_logger(std::shared_ptr<spdlog::logger> default_logger); SPDLOG_API void set_default_logger(std::shared_ptr<spdlog::logger> default_logger);
template<typename... Args> template<typename FormatString, typename... Args>
inline void log(source_loc source, level::level_enum lvl, string_view_t fmt, const Args &... args) inline void log(source_loc source, level::level_enum lvl, const FormatString &fmt, const Args &... args)
{ {
default_logger_raw()->log(source, lvl, fmt, args...); default_logger_raw()->log(source, lvl, fmt, args...);
} }
template<typename... Args> template<typename FormatString, typename... Args>
inline void log(level::level_enum lvl, string_view_t fmt, const Args &... args) inline void log(level::level_enum lvl, const FormatString &fmt, const Args &... args)
{ {
default_logger_raw()->log(source_loc{}, lvl, fmt, args...); default_logger_raw()->log(source_loc{}, lvl, fmt, args...);
} }
template<typename... Args> template<typename FormatString, typename... Args>
inline void trace(string_view_t fmt, const Args &... args) inline void trace(const FormatString &fmt, const Args &... args)
{ {
default_logger_raw()->trace(fmt, args...); default_logger_raw()->trace(fmt, args...);
} }
template<typename... Args> template<typename FormatString, typename... Args>
inline void debug(string_view_t fmt, const Args &... args) inline void debug(const FormatString &fmt, const Args &... args)
{ {
default_logger_raw()->debug(fmt, args...); default_logger_raw()->debug(fmt, args...);
} }
template<typename... Args> template<typename FormatString, typename... Args>
inline void info(string_view_t fmt, const Args &... args) inline void info(const FormatString &fmt, const Args &... args)
{ {
default_logger_raw()->info(fmt, args...); default_logger_raw()->info(fmt, args...);
} }
template<typename... Args> template<typename FormatString, typename... Args>
inline void warn(string_view_t fmt, const Args &... args) inline void warn(const FormatString &fmt, const Args &... args)
{ {
default_logger_raw()->warn(fmt, args...); default_logger_raw()->warn(fmt, args...);
} }
template<typename... Args> template<typename FormatString, typename... Args>
inline void error(string_view_t fmt, const Args &... args) inline void error(const FormatString &fmt, const Args &... args)
{ {
default_logger_raw()->error(fmt, args...); default_logger_raw()->error(fmt, args...);
} }
template<typename... Args> template<typename FormatString, typename... Args>
inline void critical(string_view_t fmt, const Args &... args) inline void critical(const FormatString &fmt, const Args &... args)
{ {
default_logger_raw()->critical(fmt, args...); default_logger_raw()->critical(fmt, args...);
} }
@@ -217,57 +217,6 @@ inline void critical(const T &msg)
default_logger_raw()->critical(msg); default_logger_raw()->critical(msg);
} }
#ifdef SPDLOG_WCHAR_TO_UTF8_SUPPORT
template<typename... Args>
inline void log(source_loc source, level::level_enum lvl, wstring_view_t fmt, const Args &... args)
{
default_logger_raw()->log(source, lvl, fmt, args...);
}
template<typename... Args>
inline void log(level::level_enum lvl, wstring_view_t fmt, const Args &... args)
{
default_logger_raw()->log(lvl, fmt, args...);
}
template<typename... Args>
inline void trace(wstring_view_t fmt, const Args &... args)
{
default_logger_raw()->trace(fmt, args...);
}
template<typename... Args>
inline void debug(wstring_view_t fmt, const Args &... args)
{
default_logger_raw()->debug(fmt, args...);
}
template<typename... Args>
inline void info(wstring_view_t fmt, const Args &... args)
{
default_logger_raw()->info(fmt, args...);
}
template<typename... Args>
inline void warn(wstring_view_t fmt, const Args &... args)
{
default_logger_raw()->warn(fmt, args...);
}
template<typename... Args>
inline void error(wstring_view_t fmt, const Args &... args)
{
default_logger_raw()->error(fmt, args...);
}
template<typename... Args>
inline void critical(wstring_view_t fmt, const Args &... args)
{
default_logger_raw()->critical(fmt, args...);
}
#endif // SPDLOG_WCHAR_TO_UTF8_SUPPORT
} // namespace spdlog } // namespace spdlog
// //

View File

@@ -4,7 +4,7 @@
#pragma once #pragma once
#define SPDLOG_VER_MAJOR 1 #define SPDLOG_VER_MAJOR 1
#define SPDLOG_VER_MINOR 6 #define SPDLOG_VER_MINOR 7
#define SPDLOG_VER_PATCH 0 #define SPDLOG_VER_PATCH 0
#define SPDLOG_VERSION (SPDLOG_VER_MAJOR * 10000 + SPDLOG_VER_MINOR * 100 + SPDLOG_VER_PATCH) #define SPDLOG_VERSION (SPDLOG_VER_MAJOR * 10000 + SPDLOG_VER_MINOR * 100 + SPDLOG_VER_PATCH)

View File

@@ -2,46 +2,46 @@ cmake_minimum_required(VERSION 3.2)
project(spdlog_utests CXX) project(spdlog_utests CXX)
if(NOT TARGET spdlog) if (NOT TARGET spdlog)
# Stand-alone build # Stand-alone build
find_package(spdlog REQUIRED) find_package(spdlog REQUIRED)
endif() endif ()
include(../cmake/utils.cmake) include(../cmake/utils.cmake)
find_package(PkgConfig) find_package(PkgConfig)
if(PkgConfig_FOUND) if (PkgConfig_FOUND)
pkg_check_modules(systemd libsystemd) pkg_check_modules(systemd libsystemd)
endif() endif ()
set(SPDLOG_UTESTS_SOURCES set(SPDLOG_UTESTS_SOURCES
test_file_helper.cpp test_file_helper.cpp
test_file_logging.cpp test_file_logging.cpp
test_daily_logger.cpp test_daily_logger.cpp
test_misc.cpp test_misc.cpp
test_eventlog.cpp test_eventlog.cpp
test_pattern_formatter.cpp test_pattern_formatter.cpp
test_async.cpp test_async.cpp
test_registry.cpp test_registry.cpp
test_macros.cpp test_macros.cpp
utils.cpp utils.cpp
main.cpp main.cpp
test_mpmc_q.cpp test_mpmc_q.cpp
test_dup_filter.cpp test_dup_filter.cpp
test_fmt_helper.cpp test_fmt_helper.cpp
test_stdout_api.cpp test_stdout_api.cpp
test_backtrace.cpp test_backtrace.cpp
test_create_dir.cpp test_create_dir.cpp
test_cfg.cpp test_cfg.cpp
test_time_point.cpp) test_time_point.cpp)
if(NOT SPDLOG_NO_EXCEPTIONS) if (NOT SPDLOG_NO_EXCEPTIONS)
list(APPEND SPDLOG_UTESTS_SOURCES test_errors.cpp) list(APPEND SPDLOG_UTESTS_SOURCES test_errors.cpp)
endif() endif ()
if(systemd_FOUND) if (systemd_FOUND)
list(APPEND SPDLOG_UTESTS_SOURCES test_systemd.cpp) list(APPEND SPDLOG_UTESTS_SOURCES test_systemd.cpp)
endif() endif ()
enable_testing() enable_testing()
@@ -49,22 +49,22 @@ function(spdlog_prepare_test test_target spdlog_lib)
add_executable(${test_target} ${SPDLOG_UTESTS_SOURCES}) add_executable(${test_target} ${SPDLOG_UTESTS_SOURCES})
spdlog_enable_warnings(${test_target}) spdlog_enable_warnings(${test_target})
target_link_libraries(${test_target} PRIVATE ${spdlog_lib}) target_link_libraries(${test_target} PRIVATE ${spdlog_lib})
if(systemd_FOUND) if (systemd_FOUND)
target_link_libraries(${test_target} PRIVATE ${systemd_LIBRARIES}) target_link_libraries(${test_target} PRIVATE ${systemd_LIBRARIES})
endif() endif ()
if(SPDLOG_SANITIZE_ADDRESS) if (SPDLOG_SANITIZE_ADDRESS)
spdlog_enable_sanitizer(${test_target}) spdlog_enable_sanitizer(${test_target})
endif() endif ()
add_test(NAME ${test_target} COMMAND ${test_target}) add_test(NAME ${test_target} COMMAND ${test_target})
set_tests_properties(${test_target} PROPERTIES RUN_SERIAL ON) set_tests_properties(${test_target} PROPERTIES RUN_SERIAL ON)
endfunction() endfunction()
# The compiled library tests # The compiled library tests
if(SPDLOG_BUILD_TESTS OR SPDLOG_BUILD_ALL) if (SPDLOG_BUILD_TESTS OR SPDLOG_BUILD_ALL)
spdlog_prepare_test(spdlog-utests spdlog::spdlog) spdlog_prepare_test(spdlog-utests spdlog::spdlog)
endif() endif ()
# The header-only library version tests # The header-only library version tests
if(SPDLOG_BUILD_TESTS_HO OR SPDLOG_BUILD_ALL) if (SPDLOG_BUILD_TESTS_HO OR SPDLOG_BUILD_ALL)
spdlog_prepare_test(spdlog-utests-ho spdlog::spdlog_header_only) spdlog_prepare_test(spdlog-utests-ho spdlog::spdlog_header_only)
endif() endif ()

View File

@@ -10,7 +10,7 @@ static milliseconds millis_from(const test_clock::time_point &tp0)
TEST_CASE("dequeue-empty-nowait", "[mpmc_blocking_q]") TEST_CASE("dequeue-empty-nowait", "[mpmc_blocking_q]")
{ {
size_t q_size = 100; size_t q_size = 100;
milliseconds tolerance_wait(10); milliseconds tolerance_wait(20);
spdlog::details::mpmc_blocking_queue<int> q(q_size); spdlog::details::mpmc_blocking_queue<int> q(q_size);
int popped_item = 0; int popped_item = 0;