Merge branch 'master' into custom_flag

pull/623/head
Fernando Gomes 8 years ago committed by GitHub
commit 40799ff78b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -4,7 +4,7 @@
#
cmake_minimum_required(VERSION 3.1)
project(spdlog VERSION 0.16.3)
project(spdlog VERSION 0.16.3 LANGUAGES CXX)
include(CTest)
include(CMakeDependentOption)
include(GNUInstallDirs)
@ -73,7 +73,6 @@ configure_file("cmake/spdlog.pc.in" "${pkg_config}" @ONLY)
install(
TARGETS spdlog
EXPORT "${targets_export_name}"
INCLUDES DESTINATION "${include_install_dir}"
)
# install headers

@ -21,8 +21,8 @@
# * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
# *************************************************************************/
cmake_minimum_required(VERSION 3.0)
project(SpdlogExamples)
cmake_minimum_required(VERSION 3.1)
project(SpdlogExamples CXX)
if(TARGET spdlog)
# Part of the main project
@ -32,16 +32,16 @@ else()
find_package(spdlog CONFIG REQUIRED)
endif()
find_package(Threads)
find_package(Threads REQUIRED)
add_executable(example example.cpp)
target_link_libraries(example spdlog::spdlog ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries(example spdlog::spdlog Threads::Threads)
add_executable(benchmark bench.cpp)
target_link_libraries(benchmark spdlog::spdlog ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries(benchmark spdlog::spdlog Threads::Threads)
add_executable(multisink multisink.cpp)
target_link_libraries(multisink spdlog::spdlog ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries(multisink spdlog::spdlog Threads::Threads)
enable_testing()
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/logs")

@ -64,9 +64,9 @@ int main(int, char*[])
// Runtime log levels
spd::set_level(spd::level::info); //Set global log level to info
console->debug("This message shold not be displayed!");
console->debug("This message should not be displayed!");
console->set_level(spd::level::debug); // Set specific logger's log level
console->debug("This message shold be displayed..");
console->debug("This message should be displayed..");
// Compile time log levels
// define SPDLOG_DEBUG_ON or SPDLOG_TRACE_ON

@ -5,6 +5,10 @@
#pragma once
#define SPDLOG_VERSION "0.16.3"
#include "tweakme.h"
#include <string>
#include <initializer_list>
#include <chrono>
@ -98,6 +102,8 @@ inline const char* to_short_str(spdlog::level::level_enum l)
{
return short_level_names[l];
}
using level_hasher = std::hash<int>;
} //level

@ -216,9 +216,10 @@ inline spdlog::details::async_log_helper::async_log_helper(
_overflow_policy(overflow_policy),
_worker_warmup_cb(worker_warmup_cb),
_flush_interval_ms(flush_interval_ms),
_worker_teardown_cb(worker_teardown_cb),
_worker_thread(&async_log_helper::worker_loop, this)
{}
_worker_teardown_cb(worker_teardown_cb)
{
_worker_thread = std::thread(&async_log_helper::worker_loop, this);
}
// Send to the worker thread termination message(level=off)
// and wait for it to finish gracefully

@ -369,7 +369,7 @@ inline void spdlog::logger::_default_err_handler(const std::string &msg)
char date_buf[100];
std::strftime(date_buf, sizeof(date_buf), "%Y-%m-%d %H:%M:%S", &tm_time);
details::log_msg err_msg;
err_msg.formatted.write("[*** LOG ERROR ***] [{}] [{}] [{}]{}", name(), msg, date_buf, details::os::eol);
err_msg.formatted.write("[*** LOG ERROR ***] [{}] [{}] [{}]{}", name(), msg, date_buf, details::os::default_eol);
sinks::stderr_sink_mt::instance()->log(err_msg);
_last_err_time = now;
}

@ -140,8 +140,7 @@ inline bool operator!=(const std::tm& tm1, const std::tm& tm2)
#endif
#endif
SPDLOG_CONSTEXPR static const char* eol = SPDLOG_EOL;
SPDLOG_CONSTEXPR static int eol_size = sizeof(SPDLOG_EOL) - 1;
SPDLOG_CONSTEXPR static const char* default_eol = SPDLOG_EOL;
@ -155,10 +154,13 @@ SPDLOG_CONSTEXPR static const char folder_sep = '/';
inline void prevent_child_fd(FILE *f)
{
#ifdef _WIN32
#if !defined(__cplusplus_winrt)
auto file_handle = (HANDLE)_get_osfhandle(_fileno(f));
if (!::SetHandleInformation(file_handle, HANDLE_FLAG_INHERIT, 0))
throw spdlog_ex("SetHandleInformation failed", errno);
#endif
#else
auto fd = fileno(f);
if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1)
@ -352,7 +354,7 @@ inline size_t _thread_id()
//Return current thread id as size_t (from thread local storage)
inline size_t thread_id()
{
#if defined(SPDLOG_DISABLE_TID_CACHING) || (defined(_MSC_VER) && (_MSC_VER < 1900)) || (defined(__clang__) && !__has_feature(cxx_thread_local))
#if defined(SPDLOG_DISABLE_TID_CACHING) || (defined(_MSC_VER) && (_MSC_VER < 1900)) || defined(__cplusplus_winrt ) || (defined(__clang__) && !__has_feature(cxx_thread_local))
return _thread_id();
#else // cache thread id in tls
static thread_local const size_t tid = _thread_id();
@ -368,7 +370,7 @@ inline size_t thread_id()
inline void sleep_for_millis(int milliseconds)
{
#if defined(_WIN32)
Sleep(milliseconds);
::Sleep(milliseconds);
#else
std::this_thread::sleep_for(std::chrono::milliseconds(milliseconds));
#endif
@ -437,7 +439,7 @@ inline int pid()
{
#ifdef _WIN32
return ::_getpid();
return static_cast<int>(::GetCurrentProcessId());
#else
return static_cast<int>(::getpid());
#endif

@ -508,8 +508,8 @@ class full_formatter SPDLOG_FINAL:public flag_formatter
///////////////////////////////////////////////////////////////////////////////
// pattern_formatter inline impl
///////////////////////////////////////////////////////////////////////////////
inline spdlog::pattern_formatter::pattern_formatter(const std::string& pattern, pattern_time_type pattern_time)
: _pattern_time(pattern_time)
inline spdlog::pattern_formatter::pattern_formatter(const std::string& pattern, pattern_time_type pattern_time, const std::string& eol)
: _eol(eol), _pattern_time(pattern_time)
{
compile_pattern(pattern);
}
@ -524,7 +524,6 @@ inline void spdlog::pattern_formatter::compile_pattern(const std::string& patter
{
if (user_chars) //append user chars found so far
_formatters.push_back(std::move(user_chars));
if (++it != end)
handle_flag(*it);
else
@ -549,130 +548,130 @@ inline void spdlog::pattern_formatter::handle_flag(char flag)
{
// logger name
case 'n':
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::name_formatter()));
_formatters.emplace_back(new details::name_formatter());
break;
case 'l':
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::level_formatter()));
_formatters.emplace_back(new details::level_formatter());
break;
case 'L':
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::short_level_formatter()));
_formatters.emplace_back(new details::short_level_formatter());
break;
case('t'):
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::t_formatter()));
_formatters.emplace_back(new details::t_formatter());
break;
case('v'):
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::v_formatter()));
_formatters.emplace_back(new details::v_formatter());
break;
case('a'):
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::a_formatter()));
_formatters.emplace_back(new details::a_formatter());
break;
case('A'):
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::A_formatter()));
_formatters.emplace_back(new details::A_formatter());
break;
case('b'):
case('h'):
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::b_formatter()));
_formatters.emplace_back(new details::b_formatter());
break;
case('B'):
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::B_formatter()));
_formatters.emplace_back(new details::B_formatter());
break;
case('c'):
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::c_formatter()));
_formatters.emplace_back(new details::c_formatter());
break;
case('C'):
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::C_formatter()));
_formatters.emplace_back(new details::C_formatter());
break;
case('Y'):
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::Y_formatter()));
_formatters.emplace_back(new details::Y_formatter());
break;
case('D'):
case('x'):
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::D_formatter()));
_formatters.emplace_back(new details::D_formatter());
break;
case('m'):
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::m_formatter()));
_formatters.emplace_back(new details::m_formatter());
break;
case('d'):
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::d_formatter()));
_formatters.emplace_back(new details::d_formatter());
break;
case('H'):
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::H_formatter()));
_formatters.emplace_back(new details::H_formatter());
break;
case('I'):
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::I_formatter()));
_formatters.emplace_back(new details::I_formatter());
break;
case('M'):
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::M_formatter()));
_formatters.emplace_back(new details::M_formatter());
break;
case('S'):
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::S_formatter()));
_formatters.emplace_back(new details::S_formatter());
break;
case('e'):
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::e_formatter()));
_formatters.emplace_back(new details::e_formatter());
break;
case('f'):
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::f_formatter()));
_formatters.emplace_back(new details::f_formatter());
break;
case('F'):
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::F_formatter()));
_formatters.emplace_back(new details::F_formatter());
break;
case('E'):
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::E_formatter()));
_formatters.emplace_back(new details::E_formatter());
break;
case('p'):
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::p_formatter()));
_formatters.emplace_back(new details::p_formatter());
break;
case('r'):
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::r_formatter()));
_formatters.emplace_back(new details::r_formatter());
break;
case('R'):
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::R_formatter()));
_formatters.emplace_back(new details::R_formatter());
break;
case('T'):
case('X'):
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::T_formatter()));
_formatters.emplace_back(new details::T_formatter());
break;
case('z'):
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::z_formatter()));
_formatters.emplace_back(new details::z_formatter());
break;
case ('+'):
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::full_formatter()));
_formatters.emplace_back(new details::full_formatter());
break;
case ('P'):
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::pid_formatter()));
_formatters.emplace_back(new details::pid_formatter());
break;
case ('i'):
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::i_formatter()));
_formatters.emplace_back(new details::i_formatter());
break;
default: //Unknown flag appears as is
@ -702,5 +701,5 @@ inline void spdlog::pattern_formatter::format(details::log_msg& msg)
f->format(msg, tm_time);
}
//write eol
msg.formatted.write(details::os::eol, details::os::eol_size);
msg.formatted.write(_eol.data(), _eol.size());
}

@ -16,7 +16,7 @@
#include "../sinks/syslog_sink.h"
#endif
#ifdef _WIN32
#if defined _WIN32 && !defined(__cplusplus_winrt)
#include "../sinks/wincolor_sink.h"
#else
#include "../sinks/ansicolor_sink.h"
@ -107,7 +107,8 @@ inline std::shared_ptr<spdlog::logger> spdlog::stderr_logger_st(const std::strin
//
// stdout/stderr color loggers
//
#ifdef _WIN32
#if defined _WIN32 && !defined(__cplusplus_winrt)
inline std::shared_ptr<spdlog::logger> spdlog::stdout_color_mt(const std::string& logger_name)
{
auto sink = std::make_shared<spdlog::sinks::wincolor_stdout_sink_mt>();

@ -72,9 +72,11 @@
// Dummy implementations of strerror_r and strerror_s called if corresponding
// system functions are not available.
FMT_MAYBE_UNUSED
static inline fmt::internal::Null<> strerror_r(int, char *, ...) {
return fmt::internal::Null<>();
}
FMT_MAYBE_UNUSED
static inline fmt::internal::Null<> strerror_s(char *, std::size_t, ...) {
return fmt::internal::Null<>();
}
@ -121,7 +123,7 @@ typedef void (*FormatFunc)(Writer &, int, StringRef);
// Buffer should be at least of size 1.
int safe_strerror(
int error_code, char *&buffer, std::size_t buffer_size) FMT_NOEXCEPT {
FMT_ASSERT(buffer != 0 && buffer_size != 0, "invalid buffer");
FMT_ASSERT(buffer != FMT_NULL && buffer_size != 0, "invalid buffer");
class StrError {
private:
@ -159,6 +161,11 @@ int safe_strerror(
ERANGE : result;
}
#ifdef __c2__
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wdeprecated-declarations"
#endif
// Fallback to strerror if strerror_r and strerror_s are not available.
int fallback(internal::Null<>) {
errno = 0;
@ -166,13 +173,15 @@ int safe_strerror(
return errno;
}
#ifdef __c2__
# pragma clang diagnostic pop
#endif
public:
StrError(int err_code, char *&buf, std::size_t buf_size)
: error_code_(err_code), buffer_(buf), buffer_size_(buf_size) {}
int run() {
// Suppress a warning about unused strerror_r.
strerror_r(0, FMT_NULL, "");
return handle(strerror_r(error_code_, buffer_, buffer_size_));
}
};
@ -396,51 +405,6 @@ FMT_FUNC void format_system_error(
fmt::format_error_code(out, error_code, message); // 'fmt::' is for bcc32.
}
template <typename Char>
void internal::ArgMap<Char>::init(const ArgList &args) {
if (!map_.empty())
return;
typedef internal::NamedArg<Char> NamedArg;
const NamedArg *named_arg = FMT_NULL;
bool use_values =
args.type(ArgList::MAX_PACKED_ARGS - 1) == internal::Arg::NONE;
if (use_values) {
for (unsigned i = 0;/*nothing*/; ++i) {
internal::Arg::Type arg_type = args.type(i);
switch (arg_type) {
case internal::Arg::NONE:
return;
case internal::Arg::NAMED_ARG:
named_arg = static_cast<const NamedArg*>(args.values_[i].pointer);
map_.push_back(Pair(named_arg->name, *named_arg));
break;
default:
/*nothing*/;
}
}
return;
}
for (unsigned i = 0; i != ArgList::MAX_PACKED_ARGS; ++i) {
internal::Arg::Type arg_type = args.type(i);
if (arg_type == internal::Arg::NAMED_ARG) {
named_arg = static_cast<const NamedArg*>(args.args_[i].pointer);
map_.push_back(Pair(named_arg->name, *named_arg));
}
}
for (unsigned i = ArgList::MAX_PACKED_ARGS;/*nothing*/; ++i) {
switch (args.args_[i].type) {
case internal::Arg::NONE:
return;
case internal::Arg::NAMED_ARG:
named_arg = static_cast<const NamedArg*>(args.args_[i].pointer);
map_.push_back(Pair(named_arg->name, *named_arg));
break;
default:
/*nothing*/;
}
}
}
template <typename Char>
void internal::FixedBuffer<Char>::grow(std::size_t) {
FMT_THROW(std::runtime_error("buffer overflow"));
@ -502,8 +466,6 @@ template struct internal::BasicData<void>;
template void internal::FixedBuffer<char>::grow(std::size_t);
template void internal::ArgMap<char>::init(const ArgList &args);
template FMT_API int internal::CharTraits<char>::format_float(
char *buffer, std::size_t size, const char *format,
unsigned width, int precision, double value);
@ -516,8 +478,6 @@ template FMT_API int internal::CharTraits<char>::format_float(
template void internal::FixedBuffer<wchar_t>::grow(std::size_t);
template void internal::ArgMap<wchar_t>::init(const ArgList &args);
template FMT_API int internal::CharTraits<wchar_t>::format_float(
wchar_t *buffer, std::size_t size, const wchar_t *format,
unsigned width, int precision, double value);

@ -28,6 +28,7 @@
#ifndef FMT_FORMAT_H_
#define FMT_FORMAT_H_
#define FMT_INCLUDE
#include <cassert>
#include <clocale>
#include <cmath>
@ -39,11 +40,26 @@
#include <string>
#include <vector>
#include <utility> // for std::pair
#undef FMT_INCLUDE
// The fmt library version in the form major * 10000 + minor * 100 + patch.
#define FMT_VERSION 40000
#define FMT_VERSION 40100
#ifdef _SECURE_SCL
#if defined(__has_include)
# define FMT_HAS_INCLUDE(x) __has_include(x)
#else
# define FMT_HAS_INCLUDE(x) 0
#endif
#if (FMT_HAS_INCLUDE(<string_view>) && __cplusplus > 201402L) || \
(defined(_MSVC_LANG) && _MSVC_LANG > 201402L && _MSC_VER >= 1910)
# include <string_view>
# define FMT_HAS_STRING_VIEW 1
#else
# define FMT_HAS_STRING_VIEW 0
#endif
#if defined _SECURE_SCL && _SECURE_SCL
# define FMT_SECURE_SCL _SECURE_SCL
#else
# define FMT_SECURE_SCL 0
@ -97,7 +113,9 @@ typedef __int64 intmax_t;
# define FMT_HAS_GXX_CXX11 1
# endif
#else
# define FMT_GCC_VERSION 0
# define FMT_GCC_EXTENSION
# define FMT_HAS_GXX_CXX11 0
#endif
#if defined(__INTEL_COMPILER)
@ -135,6 +153,32 @@ typedef __int64 intmax_t;
# define FMT_HAS_CPP_ATTRIBUTE(x) 0
#endif
#if FMT_HAS_CPP_ATTRIBUTE(maybe_unused)
# define FMT_HAS_CXX17_ATTRIBUTE_MAYBE_UNUSED
// VC++ 1910 support /std: option and that will set _MSVC_LANG macro
// Clang with Microsoft CodeGen doesn't define _MSVC_LANG macro
#elif defined(_MSVC_LANG) && _MSVC_LANG > 201402 && _MSC_VER >= 1910
# define FMT_HAS_CXX17_ATTRIBUTE_MAYBE_UNUSED
#endif
#ifdef FMT_HAS_CXX17_ATTRIBUTE_MAYBE_UNUSED
# define FMT_MAYBE_UNUSED [[maybe_unused]]
// g++/clang++ also support [[gnu::unused]]. However, we don't use it.
#elif defined(__GNUC__)
# define FMT_MAYBE_UNUSED __attribute__((unused))
#else
# define FMT_MAYBE_UNUSED
#endif
// Use the compiler's attribute noreturn
#if defined(__MINGW32__) || defined(__MINGW64__)
# define FMT_NORETURN __attribute__((noreturn))
#elif FMT_HAS_CPP_ATTRIBUTE(noreturn) && __cplusplus >= 201103L
# define FMT_NORETURN [[noreturn]]
#else
# define FMT_NORETURN
#endif
#ifndef FMT_USE_VARIADIC_TEMPLATES
// Variadic templates are available in GCC since version 4.4
// (http://gcc.gnu.org/projects/cxx0x.html) and in Visual C++
@ -156,6 +200,12 @@ typedef __int64 intmax_t;
# endif
#endif
#if __cplusplus >= 201103L || FMT_MSC_VER >= 1700
# define FMT_USE_ALLOCATOR_TRAITS 1
#else
# define FMT_USE_ALLOCATOR_TRAITS 0
#endif
// Check if exceptions are disabled.
#if defined(__GNUC__) && !defined(__EXCEPTIONS)
# define FMT_EXCEPTIONS 0
@ -262,11 +312,14 @@ typedef __int64 intmax_t;
// makes the fmt::literals implementation easier. However, an explicit check
// for variadic templates is added here just in case.
// For Intel's compiler both it and the system gcc/msc must support UDLs.
# define FMT_USE_USER_DEFINED_LITERALS \
FMT_USE_VARIADIC_TEMPLATES && FMT_USE_RVALUE_REFERENCES && \
# if FMT_USE_VARIADIC_TEMPLATES && FMT_USE_RVALUE_REFERENCES && \
(FMT_HAS_FEATURE(cxx_user_literals) || \
(FMT_GCC_VERSION >= 407 && FMT_HAS_GXX_CXX11) || FMT_MSC_VER >= 1900) && \
(!defined(FMT_ICC_VERSION) || FMT_ICC_VERSION >= 1500)
# define FMT_USE_USER_DEFINED_LITERALS 1
# else
# define FMT_USE_USER_DEFINED_LITERALS 0
# endif
#endif
#ifndef FMT_USE_EXTERN_TEMPLATES
@ -307,7 +360,10 @@ namespace fmt
{
namespace internal
{
// avoid Clang with Microsoft CodeGen's -Wunknown-pragmas warning
# ifndef __clang__
# pragma intrinsic(_BitScanReverse)
# endif
inline uint32_t clz(uint32_t x)
{
unsigned long r = 0;
@ -322,7 +378,8 @@ inline uint32_t clz(uint32_t x)
}
# define FMT_BUILTIN_CLZ(n) fmt::internal::clz(n)
# ifdef _WIN64
// avoid Clang with Microsoft CodeGen's -Wunknown-pragmas warning
# if defined(_WIN64) && !defined(__clang__)
# pragma intrinsic(_BitScanReverse64)
# endif
@ -546,6 +603,27 @@ public:
const std::basic_string<Char, std::char_traits<Char>, Allocator> &s)
: data_(s.c_str()), size_(s.size()) {}
#if FMT_HAS_STRING_VIEW
/**
\rst
Constructs a string reference from a ``std::basic_string_view`` object.
\endrst
*/
BasicStringRef(
const std::basic_string_view<Char, std::char_traits<Char>> &s)
: data_(s.data()), size_(s.size()) {}
/**
\rst
Converts a string reference to an ``std::string_view`` object.
\endrst
*/
explicit operator std::basic_string_view<Char>() const FMT_NOEXCEPT
{
return std::basic_string_view<Char>(data_, size_);
}
#endif
/**
\rst
Converts a string reference to an ``std::string`` object.
@ -669,7 +747,7 @@ public:
explicit FormatError(CStringRef message)
: std::runtime_error(message.c_str()) {}
FormatError(const FormatError &ferr) : std::runtime_error(ferr) {}
FMT_API ~FormatError() FMT_DTOR_NOEXCEPT;
FMT_API ~FormatError() FMT_DTOR_NOEXCEPT FMT_OVERRIDE;
};
namespace internal
@ -812,7 +890,7 @@ template <typename U>
void Buffer<T>::append(const U *begin, const U *end)
{
FMT_ASSERT(end >= begin, "negative value");
std::size_t new_size = size_ + (end - begin);
std::size_t new_size = size_ + static_cast<std::size_t>(end - begin);
if (new_size > capacity_)
grow(new_size);
std::uninitialized_copy(begin, end,
@ -843,10 +921,7 @@ protected:
public:
explicit MemoryBuffer(const Allocator &alloc = Allocator())
: Allocator(alloc), Buffer<T>(data_, SIZE) {}
~MemoryBuffer()
{
deallocate();
}
~MemoryBuffer() FMT_OVERRIDE { deallocate(); }
#if FMT_USE_RVALUE_REFERENCES
private:
@ -900,7 +975,12 @@ void MemoryBuffer<T, SIZE, Allocator>::grow(std::size_t size)
std::size_t new_capacity = this->capacity_ + this->capacity_ / 2;
if (size > new_capacity)
new_capacity = size;
#if FMT_USE_ALLOCATOR_TRAITS
T *new_ptr =
std::allocator_traits<Allocator>::allocate(*this, new_capacity, FMT_NULL);
#else
T *new_ptr = this->allocate(new_capacity, FMT_NULL);
#endif
// The following code doesn't throw, so the raw pointer above doesn't leak.
std::uninitialized_copy(this->ptr_, this->ptr_ + this->size_,
make_ptr(new_ptr, new_capacity));
@ -1050,7 +1130,7 @@ struct IntTraits
TypeSelector<std::numeric_limits<T>::digits <= 32>::Type MainType;
};
FMT_API void report_unknown_type(char code, const char *type);
FMT_API FMT_NORETURN void report_unknown_type(char code, const char *type);
// Static data is placed in this class template to allow header-only
// configuration.
@ -1335,19 +1415,19 @@ T &get();
Yes &convert(fmt::ULongLong);
No &convert(...);
template<typename T, bool ENABLE_CONVERSION>
template <typename T, bool ENABLE_CONVERSION>
struct ConvertToIntImpl
{
enum { value = ENABLE_CONVERSION };
};
template<typename T, bool ENABLE_CONVERSION>
template <typename T, bool ENABLE_CONVERSION>
struct ConvertToIntImpl2
{
enum { value = false };
};
template<typename T>
template <typename T>
struct ConvertToIntImpl2<T, true>
{
enum
@ -1357,7 +1437,7 @@ struct ConvertToIntImpl2<T, true>
};
};
template<typename T>
template <typename T>
struct ConvertToInt
{
enum
@ -1376,22 +1456,22 @@ FMT_DISABLE_CONVERSION_TO_INT(float);
FMT_DISABLE_CONVERSION_TO_INT(double);
FMT_DISABLE_CONVERSION_TO_INT(long double);
template<bool B, class T = void>
template <bool B, class T = void>
struct EnableIf {};
template<class T>
template <class T>
struct EnableIf<true, T>
{
typedef T type;
};
template<bool B, class T, class F>
template <bool B, class T, class F>
struct Conditional
{
typedef T type;
};
template<class T, class F>
template <class T, class F>
struct Conditional<false, T, F>
{
typedef F type;
@ -1457,10 +1537,10 @@ inline fmt::StringRef thousands_sep(...)
typedef int FMT_CONCAT_(Assert, __LINE__)[(cond) ? 1 : -1] FMT_UNUSED
#endif
template <typename Formatter, typename Char, typename T>
void format_arg(Formatter &, const Char *, const T &)
template <typename Formatter>
void format_arg(Formatter&, ...)
{
FMT_STATIC_ASSERT(FalseType<T>::value,
FMT_STATIC_ASSERT(FalseType<Formatter>::value,
"Cannot format argument. To enable the use of ostream "
"operator<< include fmt/ostream.h. Otherwise provide "
"an overload of format_arg.");
@ -1494,6 +1574,9 @@ private:
MakeValue(typename WCharHelper<wchar_t *, Char>::Unsupported);
MakeValue(typename WCharHelper<const wchar_t *, Char>::Unsupported);
MakeValue(typename WCharHelper<const std::wstring &, Char>::Unsupported);
#if FMT_HAS_STRING_VIEW
MakeValue(typename WCharHelper<const std::wstring_view &, Char>::Unsupported);
#endif
MakeValue(typename WCharHelper<WStringRef, Char>::Unsupported);
void set_string(StringRef str)
@ -1570,6 +1653,26 @@ public:
FMT_MAKE_VALUE(unsigned char, uint_value, UINT)
FMT_MAKE_VALUE(char, int_value, CHAR)
#if __cplusplus >= 201103L
template <
typename T,
typename = typename std::enable_if<
std::is_enum<T>::value && ConvertToInt<T>::value>::type>
MakeValue(T value)
{
int_value = value;
}
template <
typename T,
typename = typename std::enable_if<
std::is_enum<T>::value && ConvertToInt<T>::value>::type>
static uint64_t type(T)
{
return Arg::INT;
}
#endif
#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
MakeValue(typename WCharHelper<wchar_t, Char>::Supported value)
{
@ -1592,6 +1695,9 @@ public:
FMT_MAKE_VALUE(unsigned char *, ustring.value, CSTRING)
FMT_MAKE_VALUE(const unsigned char *, ustring.value, CSTRING)
FMT_MAKE_STR_VALUE(const std::string &, STRING)
#if FMT_HAS_STRING_VIEW
FMT_MAKE_STR_VALUE(const std::string_view &, STRING)
#endif
FMT_MAKE_STR_VALUE(StringRef, STRING)
FMT_MAKE_VALUE_(CStringRef, string.value, CSTRING, value.c_str())
@ -1604,6 +1710,9 @@ public:
FMT_MAKE_WSTR_VALUE(wchar_t *, WSTRING)
FMT_MAKE_WSTR_VALUE(const wchar_t *, WSTRING)
FMT_MAKE_WSTR_VALUE(const std::wstring &, WSTRING)
#if FMT_HAS_STRING_VIEW
FMT_MAKE_WSTR_VALUE(const std::wstring_view &, WSTRING)
#endif
FMT_MAKE_WSTR_VALUE(WStringRef, WSTRING)
FMT_MAKE_VALUE(void *, pointer, POINTER)
@ -1689,7 +1798,7 @@ class RuntimeError : public std::runtime_error
protected:
RuntimeError() : std::runtime_error("") {}
RuntimeError(const RuntimeError &rerr) : std::runtime_error(rerr) {}
FMT_API ~RuntimeError() FMT_DTOR_NOEXCEPT;
FMT_API ~RuntimeError() FMT_DTOR_NOEXCEPT FMT_OVERRIDE;
};
template <typename Char>
@ -2267,7 +2376,7 @@ private:
MapType map_;
public:
FMT_API void init(const ArgList &args);
void init(const ArgList &args);
const internal::Arg *find(const fmt::BasicStringRef<Char> &name) const
{
@ -2282,6 +2391,61 @@ public:
}
};
template <typename Char>
void ArgMap<Char>::init(const ArgList &args)
{
if (!map_.empty())
return;
typedef internal::NamedArg<Char> NamedArg;
const NamedArg *named_arg = FMT_NULL;
bool use_values =
args.type(ArgList::MAX_PACKED_ARGS - 1) == internal::Arg::NONE;
if (use_values)
{
for (unsigned i = 0;/*nothing*/; ++i)
{
internal::Arg::Type arg_type = args.type(i);
switch (arg_type)
{
case internal::Arg::NONE:
return;
case internal::Arg::NAMED_ARG:
named_arg = static_cast<const NamedArg*>(args.values_[i].pointer);
map_.push_back(Pair(named_arg->name, *named_arg));
break;
default:
/*nothing*/
;
}
}
return;
}
for (unsigned i = 0; i != ArgList::MAX_PACKED_ARGS; ++i)
{
internal::Arg::Type arg_type = args.type(i);
if (arg_type == internal::Arg::NAMED_ARG)
{
named_arg = static_cast<const NamedArg*>(args.args_[i].pointer);
map_.push_back(Pair(named_arg->name, *named_arg));
}
}
for (unsigned i = ArgList::MAX_PACKED_ARGS;/*nothing*/; ++i)
{
switch (args.args_[i].type)
{
case internal::Arg::NONE:
return;
case internal::Arg::NAMED_ARG:
named_arg = static_cast<const NamedArg*>(args.args_[i].pointer);
map_.push_back(Pair(named_arg->name, *named_arg));
break;
default:
/*nothing*/
;
}
}
}
template <typename Impl, typename Char, typename Spec = fmt::FormatSpec>
class ArgFormatterBase : public ArgVisitor<Impl, void>
{
@ -2623,7 +2787,8 @@ template <std::size_t N, bool/*IsPacked*/= (N < ArgList::MAX_PACKED_ARGS)>
template <std::size_t N>
struct ArgArray<N, true/*IsPacked*/>
{
typedef Value Type[N > 0 ? N : 1];
// '+' is used to silence GCC -Wduplicated-branches warning.
typedef Value Type[N > 0 ? N : +1];
template <typename Formatter, typename T>
static Value make(const T &value)
@ -2823,7 +2988,7 @@ public:
FMT_DEFAULTED_COPY_CTOR(SystemError)
FMT_VARIADIC_CTOR(SystemError, init, int, CStringRef)
FMT_API ~SystemError() FMT_DTOR_NOEXCEPT;
FMT_API ~SystemError() FMT_DTOR_NOEXCEPT FMT_OVERRIDE;
int error_code() const
{
@ -4057,10 +4222,10 @@ void arg(WStringRef, const internal::NamedArg<Char>&) FMT_DELETED_OR_UNDEFINED;
#define FMT_GET_ARG_NAME(type, index) arg##index
#if FMT_USE_VARIADIC_TEMPLATES
# define FMT_VARIADIC_(Char, ReturnType, func, call, ...) \
# define FMT_VARIADIC_(Const, Char, ReturnType, func, call, ...) \
template <typename... Args> \
ReturnType func(FMT_FOR_EACH(FMT_ADD_ARG_NAME, __VA_ARGS__), \
const Args & ... args) { \
const Args & ... args) Const { \
typedef fmt::internal::ArgArray<sizeof...(Args)> ArgArray; \
typename ArgArray::Type array{ \
ArgArray::template make<fmt::BasicFormatter<Char> >(args)...}; \
@ -4070,35 +4235,35 @@ void arg(WStringRef, const internal::NamedArg<Char>&) FMT_DELETED_OR_UNDEFINED;
#else
// Defines a wrapper for a function taking __VA_ARGS__ arguments
// and n additional arguments of arbitrary types.
# define FMT_WRAP(Char, ReturnType, func, call, n, ...) \
# define FMT_WRAP(Const, Char, ReturnType, func, call, n, ...) \
template <FMT_GEN(n, FMT_MAKE_TEMPLATE_ARG)> \
inline ReturnType func(FMT_FOR_EACH(FMT_ADD_ARG_NAME, __VA_ARGS__), \
FMT_GEN(n, FMT_MAKE_ARG)) { \
FMT_GEN(n, FMT_MAKE_ARG)) Const { \
fmt::internal::ArgArray<n>::Type arr; \
FMT_GEN(n, FMT_ASSIGN_##Char); \
call(FMT_FOR_EACH(FMT_GET_ARG_NAME, __VA_ARGS__), fmt::ArgList( \
fmt::internal::make_type(FMT_GEN(n, FMT_MAKE_REF2)), arr)); \
}
# define FMT_VARIADIC_(Char, ReturnType, func, call, ...) \
inline ReturnType func(FMT_FOR_EACH(FMT_ADD_ARG_NAME, __VA_ARGS__)) { \
# define FMT_VARIADIC_(Const, Char, ReturnType, func, call, ...) \
inline ReturnType func(FMT_FOR_EACH(FMT_ADD_ARG_NAME, __VA_ARGS__)) Const { \
call(FMT_FOR_EACH(FMT_GET_ARG_NAME, __VA_ARGS__), fmt::ArgList()); \
} \
FMT_WRAP(Char, ReturnType, func, call, 1, __VA_ARGS__) \
FMT_WRAP(Char, ReturnType, func, call, 2, __VA_ARGS__) \
FMT_WRAP(Char, ReturnType, func, call, 3, __VA_ARGS__) \
FMT_WRAP(Char, ReturnType, func, call, 4, __VA_ARGS__) \
FMT_WRAP(Char, ReturnType, func, call, 5, __VA_ARGS__) \
FMT_WRAP(Char, ReturnType, func, call, 6, __VA_ARGS__) \
FMT_WRAP(Char, ReturnType, func, call, 7, __VA_ARGS__) \
FMT_WRAP(Char, ReturnType, func, call, 8, __VA_ARGS__) \
FMT_WRAP(Char, ReturnType, func, call, 9, __VA_ARGS__) \
FMT_WRAP(Char, ReturnType, func, call, 10, __VA_ARGS__) \
FMT_WRAP(Char, ReturnType, func, call, 11, __VA_ARGS__) \
FMT_WRAP(Char, ReturnType, func, call, 12, __VA_ARGS__) \
FMT_WRAP(Char, ReturnType, func, call, 13, __VA_ARGS__) \
FMT_WRAP(Char, ReturnType, func, call, 14, __VA_ARGS__) \
FMT_WRAP(Char, ReturnType, func, call, 15, __VA_ARGS__)
FMT_WRAP(Const, Char, ReturnType, func, call, 1, __VA_ARGS__) \
FMT_WRAP(Const, Char, ReturnType, func, call, 2, __VA_ARGS__) \
FMT_WRAP(Const, Char, ReturnType, func, call, 3, __VA_ARGS__) \
FMT_WRAP(Const, Char, ReturnType, func, call, 4, __VA_ARGS__) \
FMT_WRAP(Const, Char, ReturnType, func, call, 5, __VA_ARGS__) \
FMT_WRAP(Const, Char, ReturnType, func, call, 6, __VA_ARGS__) \
FMT_WRAP(Const, Char, ReturnType, func, call, 7, __VA_ARGS__) \
FMT_WRAP(Const, Char, ReturnType, func, call, 8, __VA_ARGS__) \
FMT_WRAP(Const, Char, ReturnType, func, call, 9, __VA_ARGS__) \
FMT_WRAP(Const, Char, ReturnType, func, call, 10, __VA_ARGS__) \
FMT_WRAP(Const, Char, ReturnType, func, call, 11, __VA_ARGS__) \
FMT_WRAP(Const, Char, ReturnType, func, call, 12, __VA_ARGS__) \
FMT_WRAP(Const, Char, ReturnType, func, call, 13, __VA_ARGS__) \
FMT_WRAP(Const, Char, ReturnType, func, call, 14, __VA_ARGS__) \
FMT_WRAP(Const, Char, ReturnType, func, call, 15, __VA_ARGS__)
#endif // FMT_USE_VARIADIC_TEMPLATES
/**
@ -4129,10 +4294,16 @@ void arg(WStringRef, const internal::NamedArg<Char>&) FMT_DELETED_OR_UNDEFINED;
\endrst
*/
#define FMT_VARIADIC(ReturnType, func, ...) \
FMT_VARIADIC_(char, ReturnType, func, return func, __VA_ARGS__)
FMT_VARIADIC_(, char, ReturnType, func, return func, __VA_ARGS__)
#define FMT_VARIADIC_CONST(ReturnType, func, ...) \
FMT_VARIADIC_(const, char, ReturnType, func, return func, __VA_ARGS__)
#define FMT_VARIADIC_W(ReturnType, func, ...) \
FMT_VARIADIC_(wchar_t, ReturnType, func, return func, __VA_ARGS__)
FMT_VARIADIC_(, wchar_t, ReturnType, func, return func, __VA_ARGS__)
#define FMT_VARIADIC_CONST_W(ReturnType, func, ...) \
FMT_VARIADIC_(const, wchar_t, ReturnType, func, return func, __VA_ARGS__)
#define FMT_CAPTURE_ARG_(id, index) ::fmt::arg(#id, id)
@ -4179,20 +4350,22 @@ unsigned parse_nonnegative_int(const Char *&s)
{
assert('0' <= *s && *s <= '9');
unsigned value = 0;
// Convert to unsigned to prevent a warning.
unsigned max_int = (std::numeric_limits<int>::max)();
unsigned big = max_int / 10;
do
{
unsigned new_value = value * 10 + (*s++ - '0');
// Check if value wrapped around.
if (new_value < value)
// Check for overflow.
if (value > big)
{
value = (std::numeric_limits<unsigned>::max)();
value = max_int + 1;
break;
}
value = new_value;
value = value * 10 + (*s - '0');
++s;
}
while ('0' <= *s && *s <= '9');
// Convert to unsigned to prevent a warning.
unsigned max_int = (std::numeric_limits<int>::max)();
if (value > max_int)
FMT_THROW(FormatError("number is too big"));
return value;
@ -4392,7 +4565,8 @@ const Char *BasicFormatter<Char, ArgFormatter>::format(
default:
FMT_THROW(FormatError("width is not integer"));
}
if (value > (std::numeric_limits<int>::max)())
unsigned max_int = (std::numeric_limits<int>::max)();
if (value > max_int)
FMT_THROW(FormatError("number is too big"));
spec.width_ = static_cast<int>(value);
}
@ -4435,7 +4609,8 @@ const Char *BasicFormatter<Char, ArgFormatter>::format(
default:
FMT_THROW(FormatError("precision is not integer"));
}
if (value > (std::numeric_limits<int>::max)())
unsigned max_int = (std::numeric_limits<int>::max)();
if (value > max_int)
FMT_THROW(FormatError("number is too big"));
spec.precision_ = static_cast<int>(value);
}

@ -58,13 +58,15 @@ Yes &convert(std::ostream &);
struct DummyStream : std::ostream
{
DummyStream(); // Suppress a bogus warning in MSVC.
// Hide all operator<< overloads from std::ostream.
void operator<<(Null<>);
template <typename T>
typename EnableIf<sizeof(T) == 0>::type operator<<(const T &);
};
No &operator<<(std::ostream &, int);
template<typename T>
template <typename T>
struct ConvertToIntImpl<T, true>
{
// Convert to int only if T doesn't have an overloaded operator<<.
@ -87,6 +89,7 @@ void format_arg(BasicFormatter<Char, ArgFormatter_> &f,
internal::FormatBuf<Char> format_buf(buffer);
std::basic_ostream<Char> output(&format_buf);
output.exceptions(std::ios_base::failbit | std::ios_base::badbit);
output << value;
BasicStringRef<Char> str(&buffer[0], buffer.size());

@ -152,7 +152,7 @@ public:
visit_any_int(value);
}
void visit_char(char value)
void visit_char(int value)
{
if (type_ != 's')
visit_any_int(value);
@ -170,7 +170,7 @@ public:
using internal::Arg;
typedef typename internal::Conditional<
is_same<T, void>::value, U, T>::type TargetType;
if (sizeof(TargetType) <= sizeof(int))
if (const_check(sizeof(TargetType) <= sizeof(int)))
{
// Extra casts are used to silence warnings.
if (is_signed)

@ -29,11 +29,12 @@ class pattern_formatter SPDLOG_FINAL : public formatter
{
public:
explicit pattern_formatter(const std::string& pattern, pattern_time_type pattern_time = pattern_time_type::local);
explicit pattern_formatter(const std::string& pattern, pattern_time_type pattern_time = pattern_time_type::local, const std::string& eol = spdlog::details::os::default_eol);
pattern_formatter(const pattern_formatter&) = delete;
pattern_formatter& operator=(const pattern_formatter&) = delete;
void format(details::log_msg& msg) override;
private:
const std::string _eol;
const std::string _pattern;
const pattern_time_type _pattern_time;
std::vector<std::unique_ptr<details::flag_formatter>> _formatters;

@ -10,7 +10,7 @@
#include "../details/os.h"
#include <string>
#include <map>
#include <unordered_map>
namespace spdlog
{
@ -104,7 +104,7 @@ protected:
}
FILE* target_file_;
bool should_do_colors_;
std::map<level::level_enum, std::string> colors_;
std::unordered_map<level::level_enum, std::string, level::level_hasher> colors_;
};

@ -81,7 +81,7 @@ public:
// e.g. calc_filename("logs/mylog.txt, 3) => "logs/mylog.3.txt".
static filename_t calc_filename(const filename_t& filename, std::size_t index)
{
std::conditional<std::is_same<filename_t::value_type, char>::value, fmt::MemoryWriter, fmt::WMemoryWriter>::type w;
typename std::conditional<std::is_same<filename_t::value_type, char>::value, fmt::MemoryWriter, fmt::WMemoryWriter>::type w;
if (index)
{
filename_t basename, ext;

@ -11,7 +11,7 @@
#include <mutex>
#include <string>
#include <map>
#include <unordered_map>
#include <wincon.h>
namespace spdlog
@ -50,6 +50,13 @@ public:
wincolor_sink(const wincolor_sink& other) = delete;
wincolor_sink& operator=(const wincolor_sink& other) = delete;
// change the color for the given level
void set_color(level::level_enum level, WORD color)
{
std::lock_guard<Mutex> lock(base_sink<Mutex>::_mutex);
colors_[level] = color;
}
protected:
virtual void _sink_it(const details::log_msg& msg) override
{
@ -64,16 +71,9 @@ protected:
// windows console always flushed?
}
// change the color for the given level
void set_color(level::level_enum level, WORD color)
{
std::lock_guard<Mutex> lock(base_sink<Mutex>::_mutex);
colors_[level] = color;
}
private:
HANDLE out_handle_;
std::map<level::level_enum, WORD> colors_;
std::unordered_map<level::level_enum, WORD, level::level_hasher> colors_;
// set color and return the orig console attributes (for resetting later)
WORD set_console_attribs(WORD attribs)

@ -7,9 +7,7 @@
#pragma once
#define SPDLOG_VERSION "0.16.3"
#include "tweakme.h"
#include "common.h"
#include "logger.h"

@ -1,19 +1,23 @@
#
# Tests
#
project(spdlog-utests CXX)
enable_testing()
find_package(Threads REQUIRED)
find_package(Threads)
# Build Catch unit tests
add_library(catch INTERFACE)
target_include_directories(catch INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
set(SPDLOG_UTESTS_SOURCES
errors.cpp
file_helper.cpp
file_log.cpp
test_misc.cpp
test_pattern_formatter
includes.h
registry.cpp
test_macros.cpp
utils.cpp
utils.h
main.cpp)
file(GLOB catch_tests LIST_DIRECTORIES false RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.cpp *.h *.hpp)
add_executable(${PROJECT_NAME} ${SPDLOG_UTESTS_SOURCES})
target_link_libraries(${PROJECT_NAME} PRIVATE Threads::Threads)
target_link_libraries(${PROJECT_NAME} PRIVATE spdlog)
add_executable(catch_tests ${catch_tests})
target_link_libraries(catch_tests spdlog ${CMAKE_THREAD_LIBS_INIT})
add_test(NAME catch_tests COMMAND catch_tests)
add_test(NAME ${PROJECT_NAME} COMMAND ${PROJECT_NAME})
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/logs")

@ -1,10 +1,10 @@
CXX ?= g++
ifeq ($(STYLE),printf)
$(info *** PRINTF STYLE ***)
CXXFLAGS = -DSPDLOG_FMT_PRINTF -Wall -pedantic -std=c++11 -pthread -O2 -I../include
CXXFLAGS = -DSPDLOG_FMT_PRINTF -Wall -pedantic -std=c++11 -pthread -O3 -I../include
else
$(info *** FORMAT STYLE ***)
CXXFLAGS = -Wall -pedantic -std=c++11 -pthread -O2 -I../include
CXXFLAGS = -Wall -pedantic -std=c++11 -pthread -O3 -I../include
endif
LDPFALGS = -pthread

@ -13,7 +13,7 @@ std::string log_info(const T& what, spdlog::level::level_enum logger_level = spd
oss_logger.set_pattern("%v");
oss_logger.info(what);
return oss.str().substr(0, oss.str().length() - spdlog::details::os::eol_size);
return oss.str().substr(0, oss.str().length() - strlen(spdlog::details::os::default_eol));
}
@ -39,7 +39,6 @@ TEST_CASE("basic_logging ", "[basic_logging]")
//REQUIRE(log_info(some_logged_class("some_val")) == "some_val");
}
TEST_CASE("log_levels", "[log_levels]")
{
REQUIRE(log_info("Hello", spdlog::level::err) == "");
@ -54,3 +53,6 @@ TEST_CASE("log_levels", "[log_levels]")

@ -0,0 +1,69 @@
#include "includes.h"
// log to str and return it
static std::string log_to_str(const std::string& msg, std::shared_ptr<spdlog::formatter> formatter = nullptr)
{
std::ostringstream oss;
auto oss_sink = std::make_shared<spdlog::sinks::ostream_sink_mt>(oss);
spdlog::logger oss_logger("pattern_tester", oss_sink);
oss_logger.set_level(spdlog::level::info);
if (formatter) oss_logger.set_formatter(formatter);
oss_logger.info(msg);
return oss.str();
}
TEST_CASE("custom eol", "[pattern_formatter]")
{
std::string msg = "Hello custom eol test";
std::string eol = ";)";
auto formatter = std::make_shared<spdlog::pattern_formatter>("%v", spdlog::pattern_time_type::local, ";)");
REQUIRE(log_to_str(msg, formatter) == msg + eol);
}
TEST_CASE("empty format", "[pattern_formatter]")
{
auto formatter = std::make_shared<spdlog::pattern_formatter>("", spdlog::pattern_time_type::local, "");
REQUIRE(log_to_str("Some message", formatter) == "");
}
TEST_CASE("empty format2", "[pattern_formatter]")
{
auto formatter = std::make_shared<spdlog::pattern_formatter>("", spdlog::pattern_time_type::local, "\n");
REQUIRE(log_to_str("Some message", formatter) == "\n");
}
TEST_CASE("level", "[pattern_formatter]")
{
auto formatter = std::make_shared<spdlog::pattern_formatter>("[%l] %v", spdlog::pattern_time_type::local, "\n");
REQUIRE(log_to_str("Some message", formatter) == "[info] Some message\n");
}
TEST_CASE("short level", "[pattern_formatter]")
{
auto formatter = std::make_shared<spdlog::pattern_formatter>("[%L] %v", spdlog::pattern_time_type::local, "\n");
REQUIRE(log_to_str("Some message", formatter) == "[I] Some message\n");
}
TEST_CASE("name", "[pattern_formatter]")
{
auto formatter = std::make_shared<spdlog::pattern_formatter>("[%n] %v", spdlog::pattern_time_type::local, "\n");
REQUIRE(log_to_str("Some message", formatter) == "[pattern_tester] Some message\n");
}
TEST_CASE("date MM/DD/YY ", "[pattern_formatter]")
{
using namespace::std::chrono;
auto formatter = std::make_shared<spdlog::pattern_formatter>("%D %v", spdlog::pattern_time_type::local, "\n");
auto now_tm = spdlog::details::os::localtime();
std::stringstream oss;
oss << std::setfill('0') << std::setw(2) << now_tm.tm_mon + 1 << "/" << now_tm.tm_mday << "/" << (now_tm.tm_year + 1900) % 1000 << " Some message\n";
REQUIRE(log_to_str("Some message", formatter) == oss.str());
}

@ -21,6 +21,7 @@
<PropertyGroup Label="Globals">
<ProjectGuid>{59A07559-5F38-4DD6-A7FA-DB4153690B42}</ProjectGuid>
<RootNamespace>tests</RootNamespace>
<WindowsTargetPlatformVersion>10.0.16299.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
@ -128,10 +129,11 @@
<ClCompile Include="errors.cpp" />
<ClCompile Include="file_helper.cpp" />
<ClCompile Include="file_log.cpp" />
<ClCompile Include="format.cpp" />
<ClCompile Include="test_misc.cpp" />
<ClCompile Include="main.cpp" />
<ClCompile Include="registry.cpp" />
<ClCompile Include="test_macros.cpp" />
<ClCompile Include="test_pattern_formatter.cpp" />
<ClCompile Include="utils.cpp" />
</ItemGroup>
<ItemGroup>

@ -18,9 +18,6 @@
<ClCompile Include="file_log.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="format.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="main.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@ -39,6 +36,12 @@
<ClCompile Include="test_macros.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="test_pattern_formatter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="test_misc.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="includes.h">

Loading…
Cancel
Save