[med-svn] [spdlog] 01/01: Imported Upstream version 1.8

Michael Crusoe misterc-guest at moszumanska.debian.org
Tue May 17 09:52:42 UTC 2016


This is an automated email from the git hooks/post-receive script.

misterc-guest pushed a commit to annotated tag upstream/1.8
in repository spdlog.

commit 5feb04af06094073890ffbc802a0319b76e557db
Author: Michael R. Crusoe <crusoe at ucdavis.edu>
Date:   Tue May 17 02:46:41 2016 -0700

    Imported Upstream version 1.8
---
 .gitignore                                      |   20 +-
 .travis.yml                                     |  216 +--
 CMakeLists.txt                                  |  135 +-
 LICENSE                                         |    2 +-
 README.md                                       |  315 ++--
 bench/Makefile                                  |  130 +-
 bench/run_all.sh                                |  152 +-
 bench/zf_log-bench-mt.cpp                       |   22 +-
 bench/zf_log-bench.cpp                          |   21 +-
 cmake/spdlog.pc.in                              |    6 +
 example/example.cpp                             |   76 +-
 example/example.vcxproj                         |  178 +-
 example/logs/.gitignore                         |    6 +-
 include/spdlog/async_logger.h                   |   12 +-
 include/spdlog/common.h                         |   45 +-
 include/spdlog/details/async_log_helper.h       |   48 +-
 include/spdlog/details/async_logger_impl.h      |   15 +-
 include/spdlog/details/file_helper.h            |   22 +-
 include/spdlog/details/format.cc                | 2013 ++++++++++++-----------
 include/spdlog/details/format.h                 |  827 ++++++----
 include/spdlog/details/logger_impl.h            |   11 +-
 include/spdlog/details/null_mutex.h             |   23 +-
 include/spdlog/details/os.h                     |   47 +-
 include/spdlog/details/pattern_formatter_impl.h |    4 +
 include/spdlog/details/registry.h               |   34 +-
 include/spdlog/details/spdlog_impl.h            |   47 +-
 include/spdlog/logger.h                         |    8 +-
 include/spdlog/sinks/ansicolor_sink.h           |  115 ++
 include/spdlog/sinks/file_sinks.h               |   81 +-
 include/spdlog/sinks/msvc_sink.h                |    4 +-
 include/spdlog/sinks/stdout_sinks.h             |   32 +-
 include/spdlog/spdlog.h                         |   22 +-
 include/spdlog/tweakme.h                        |   17 +
 tests/Makefile                                  |   44 +-
 tests/file_helper.cpp                           |   20 +-
 tests/file_log.cpp                              |   49 +-
 tests/includes.h                                |    1 +
 tests/tests.vcxproj                             |  282 ++--
 tests/tests.vcxproj.filters                     |   94 +-
 tests/utils.cpp                                 |    6 +-
 40 files changed, 2916 insertions(+), 2286 deletions(-)

diff --git a/.gitignore b/.gitignore
index 6c04147..d0dd396 100644
--- a/.gitignore
+++ b/.gitignore
@@ -29,8 +29,20 @@
 # example  files
 example/*
 !example/example.cpp
+!example/bench.cpp
 !example/utils.h
-!example/makefile
-!example/makefile.clang
-
-
+!example/Makefile*
+!example/example.sln
+!example/example.vcxproj
+!example/CMakeLists.txt
+
+# generated files
+generated
+
+# Cmake
+CMakeCache.txt
+CMakeFiles
+CMakeScripts
+Makefile
+cmake_install.cmake
+install_manifest.txt
diff --git a/.travis.yml b/.travis.yml
index 6364b6a..3cbb527 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,108 +1,108 @@
-# Adapted from various sources, including:
-# - Louis Dionne's Hana: https://github.com/ldionne/hana
-# - Paul Fultz II's FIT: https://github.com/pfultz2/Fit
-# - Eric Niebler's range-v3: https://github.com/ericniebler/range-v3
-language: cpp
-
-# Test matrix:
-# - Build matrix per compiler: C++11/C++14 + Debug/Release
-# - Optionally: AddressSanitizer (ASAN)
-# - Valgrind: all release builds are also tested with valgrind
-# - clang 3.4, 3.5, 3.6, trunk
-#   - Note: 3.4 and trunk are tested with/without ASAN,
-#     the rest is only tested with ASAN=On.
-# - gcc 4.9, 5.0
-#
-matrix:
-  include:
-    # Test clang-3.5: C++11/C++14, Buidd=Debug/Release, ASAN=On/Off
-    - env: CLANG_VERSION=3.5 BUILD_TYPE=Debug CPP=11 ASAN=On LIBCXX=On
-      os: linux
-      addons: &clang35
-        apt:
-          packages:
-            - clang-3.5
-            - valgrind
-          sources:
-            - ubuntu-toolchain-r-test
-            - llvm-toolchain-precise-3.5
-
- 
-    - env: CLANG_VERSION=3.5 BUILD_TYPE=Release CPP=11 ASAN=Off LIBCXX=On
-      os: linux
-      addons: *clang35
-    
-
-
-# Test gcc-4.8: C++11, Build=Debug/Release, ASAN=Off
-    - env: GCC_VERSION=4.8 BUILD_TYPE=Debug CPP=11 ASAN=Off LIBCXX=Off
-      os: linux
-      addons: &gcc48
-        apt:
-          packages:
-            - g++-4.8
-            - valgrind
-          sources:
-            - ubuntu-toolchain-r-test
-
-    - env: GCC_VERSION=4.8 BUILD_TYPE=Release CPP=11 ASAN=Off LIBCXX=Off
-      os: linux
-      addons: *gcc48
-      
-    # Test gcc-4.9: C++11, Build=Debug/Release, ASAN=Off
-    - env: GCC_VERSION=4.9 BUILD_TYPE=Debug CPP=11 ASAN=Off LIBCXX=Off
-      os: linux
-      addons: &gcc49
-        apt:
-          packages:
-            - g++-4.9
-            - valgrind
-          sources:
-            - ubuntu-toolchain-r-test
-
-    - env: GCC_VERSION=4.9 BUILD_TYPE=Release CPP=11 ASAN=Off LIBCXX=Off
-      os: linux
-      addons: *gcc49
-
-# Install dependencies
-before_install:
-  - export CHECKOUT_PATH=`pwd`;
-  - if [ -n "$GCC_VERSION" ]; then export CXX="g++-${GCC_VERSION}" CC="gcc-${GCC_VERSION}"; fi
-  - if [ -n "$CLANG_VERSION" ]; then export CXX="clang++-${CLANG_VERSION}" CC="clang-${CLANG_VERSION}"; fi
-  - if [ "$CLANG_VERSION" == "3.4" ]; then export CXX="/usr/local/clang-3.4/bin/clang++" CC="/usr/local/clang-3.4/bin/clang"; fi
-  - which $CXX
-  - which $CC
-  - which valgrind
-  - if [ -n "$CLANG_VERSION" ]; then sudo CXX=$CXX CC=$CC ./tests/install_libcxx.sh; fi
-
-install:
-  - cd $CHECKOUT_PATH
-
-  # Workaround for valgrind bug: https://bugs.kde.org/show_bug.cgi?id=326469.
-  # It is fixed in valgrind 3.10 so this won't be necessary if someone
-  # replaces the current valgrind (3.7) with valgrind-3.10
-  - sed -i 's/march=native/msse4.2/' example/Makefile
-
-  - if [ ! -d build ]; then mkdir build; fi
-  - export CXX_FLAGS="-I${CHECKOUT_PATH}/include"
-  - export CXX_LINKER_FLAGS=""
-  - if [ -z "$BUILD_TYPE" ]; then export BUILD_TYPE=Release; fi
-  - if [ "$ASAN" == "On"]; then export CXX_FLAGS="${CXX_FLAGS} -fsanitize=address,undefined,integer -fno-omit-frame-pointer -fno-sanitize=unsigned-integer-overflow"; fi
-  - if [ -n "$CLANG_VERSION" ]; then CXX_FLAGS="${CXX_FLAGS} -D__extern_always_inline=inline"; fi
-  - if [ "$LIBCXX" == "On" ]; then CXX_FLAGS="${CXX_FLAGS} -stdlib=libc++ -I/usr/include/c++/v1/"; fi
-  - if [ "$LIBCXX" == "On" ]; then CXX_LINKER_FLAGS="${CXX_FLAGS} -L/usr/lib/ -lc++"; fi
-  - CXX_FLAGS="${CXX_FLAGS} -std=c++${CPP}"
-
-  # Build examples
-  - cd example
-  - if [ "$BUILD_TYPE" == "Release" ]; then make rebuild CXXFLAGS="${CXX_FLAGS} ${CXX_LINKER_FLAGS}" VERBOSE=1; export BIN=example; fi
-  - if [ "$BUILD_TYPE" == "Debug" ]; then make rebuild debug CXXFLAGS="${CXX_FLAGS} ${CXX_LINKER_FLAGS}" VERBOSE=1; export BIN=example-debug; fi
-  
-
-script:
-  - ./"${BIN}"
-  - valgrind --trace-children=yes --leak-check=full ./"${BIN}"
-  - cd $CHECKOUT_PATH/tests; make rebuild; ./tests
-
-notifications:
-  email: false
+# Adapted from various sources, including:
+# - Louis Dionne's Hana: https://github.com/ldionne/hana
+# - Paul Fultz II's FIT: https://github.com/pfultz2/Fit
+# - Eric Niebler's range-v3: https://github.com/ericniebler/range-v3
+language: cpp
+
+# Test matrix:
+# - Build matrix per compiler: C++11/C++14 + Debug/Release
+# - Optionally: AddressSanitizer (ASAN)
+# - Valgrind: all release builds are also tested with valgrind
+# - clang 3.4, 3.5, 3.6, trunk
+#   - Note: 3.4 and trunk are tested with/without ASAN,
+#     the rest is only tested with ASAN=On.
+# - gcc 4.9, 5.0
+#
+matrix:
+  include:
+    # Test clang-3.5: C++11/C++14, Buidd=Debug/Release, ASAN=On/Off
+    - env: CLANG_VERSION=3.5 BUILD_TYPE=Debug CPP=11 ASAN=On LIBCXX=On
+      os: linux
+      addons: &clang35
+        apt:
+          packages:
+            - clang-3.5
+            - valgrind
+          sources:
+            - ubuntu-toolchain-r-test
+            - llvm-toolchain-precise-3.5
+
+ 
+    - env: CLANG_VERSION=3.5 BUILD_TYPE=Release CPP=11 ASAN=Off LIBCXX=On
+      os: linux
+      addons: *clang35
+    
+
+
+# Test gcc-4.8: C++11, Build=Debug/Release, ASAN=Off
+    - env: GCC_VERSION=4.8 BUILD_TYPE=Debug CPP=11 ASAN=Off LIBCXX=Off
+      os: linux
+      addons: &gcc48
+        apt:
+          packages:
+            - g++-4.8
+            - valgrind
+          sources:
+            - ubuntu-toolchain-r-test
+
+    - env: GCC_VERSION=4.8 BUILD_TYPE=Release CPP=11 ASAN=Off LIBCXX=Off
+      os: linux
+      addons: *gcc48
+      
+    # Test gcc-4.9: C++11, Build=Debug/Release, ASAN=Off
+    - env: GCC_VERSION=4.9 BUILD_TYPE=Debug CPP=11 ASAN=Off LIBCXX=Off
+      os: linux
+      addons: &gcc49
+        apt:
+          packages:
+            - g++-4.9
+            - valgrind
+          sources:
+            - ubuntu-toolchain-r-test
+
+    - env: GCC_VERSION=4.9 BUILD_TYPE=Release CPP=11 ASAN=Off LIBCXX=Off
+      os: linux
+      addons: *gcc49
+
+# Install dependencies
+before_install:
+  - export CHECKOUT_PATH=`pwd`;
+  - if [ -n "$GCC_VERSION" ]; then export CXX="g++-${GCC_VERSION}" CC="gcc-${GCC_VERSION}"; fi
+  - if [ -n "$CLANG_VERSION" ]; then export CXX="clang++-${CLANG_VERSION}" CC="clang-${CLANG_VERSION}"; fi
+  - if [ "$CLANG_VERSION" == "3.4" ]; then export CXX="/usr/local/clang-3.4/bin/clang++" CC="/usr/local/clang-3.4/bin/clang"; fi
+  - which $CXX
+  - which $CC
+  - which valgrind
+  - if [ -n "$CLANG_VERSION" ]; then sudo CXX=$CXX CC=$CC ./tests/install_libcxx.sh; fi
+
+install:
+  - cd $CHECKOUT_PATH
+
+  # Workaround for valgrind bug: https://bugs.kde.org/show_bug.cgi?id=326469.
+  # It is fixed in valgrind 3.10 so this won't be necessary if someone
+  # replaces the current valgrind (3.7) with valgrind-3.10
+  - sed -i 's/march=native/msse4.2/' example/Makefile
+
+  - if [ ! -d build ]; then mkdir build; fi
+  - export CXX_FLAGS="-I${CHECKOUT_PATH}/include"
+  - export CXX_LINKER_FLAGS=""
+  - if [ -z "$BUILD_TYPE" ]; then export BUILD_TYPE=Release; fi
+  - if [ "$ASAN" == "On"]; then export CXX_FLAGS="${CXX_FLAGS} -fsanitize=address,undefined,integer -fno-omit-frame-pointer -fno-sanitize=unsigned-integer-overflow"; fi
+  - if [ -n "$CLANG_VERSION" ]; then CXX_FLAGS="${CXX_FLAGS} -D__extern_always_inline=inline"; fi
+  - if [ "$LIBCXX" == "On" ]; then CXX_FLAGS="${CXX_FLAGS} -stdlib=libc++ -I/usr/include/c++/v1/"; fi
+  - if [ "$LIBCXX" == "On" ]; then CXX_LINKER_FLAGS="${CXX_FLAGS} -L/usr/lib/ -lc++"; fi
+  - CXX_FLAGS="${CXX_FLAGS} -std=c++${CPP}"
+
+  # Build examples
+  - cd example
+  - if [ "$BUILD_TYPE" == "Release" ]; then make rebuild CXXFLAGS="${CXX_FLAGS} ${CXX_LINKER_FLAGS}" VERBOSE=1; export BIN=example; fi
+  - if [ "$BUILD_TYPE" == "Debug" ]; then make rebuild debug CXXFLAGS="${CXX_FLAGS} ${CXX_LINKER_FLAGS}" VERBOSE=1; export BIN=example-debug; fi
+  
+
+script:
+  - ./"${BIN}"
+  - valgrind --trace-children=yes --leak-check=full ./"${BIN}"
+  - cd $CHECKOUT_PATH/tests; make rebuild; ./tests
+
+notifications:
+  email: false
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 15553b1..f11d732 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,62 +1,73 @@
-#
-# Copyright(c) 2015 Ruslan Baratov.
-# Distributed under the MIT License (http://opensource.org/licenses/MIT)
-#
-
-cmake_minimum_required(VERSION 3.0)
-project(spdlog VERSION 1.0.0)
-
-add_library(spdlog INTERFACE)
-
-option(SPDLOG_BUILD_EXAMPLES "Build examples" OFF)
-
-target_include_directories(
-    spdlog
-    INTERFACE
-    "$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>"
-    "$<INSTALL_INTERFACE:include>"
-)
-
-if(SPDLOG_BUILD_EXAMPLES)
-  enable_testing()
-  add_subdirectory(example)
-endif()
-
-### Install ###
-# * https://github.com/forexample/package-example
-set(generated_dir "${CMAKE_CURRENT_BINARY_DIR}/generated")
-
-set(config_install_dir "lib/cmake/${PROJECT_NAME}")
-set(include_install_dir "include")
-
-set(version_config "${generated_dir}/${PROJECT_NAME}ConfigVersion.cmake")
-set(project_config "${generated_dir}/${PROJECT_NAME}Config.cmake")
-set(targets_export_name "${PROJECT_NAME}Targets")
-set(namespace "${PROJECT_NAME}::")
-
-include(CMakePackageConfigHelpers)
-write_basic_package_version_file(
-    "${version_config}" COMPATIBILITY SameMajorVersion
-)
-
-# Note: use 'targets_export_name'
-configure_file("cmake/Config.cmake.in" "${project_config}" @ONLY)
-
-install(
-    TARGETS spdlog
-    EXPORT "${targets_export_name}"
-    INCLUDES DESTINATION "${include_install_dir}"
-)
-
-install(DIRECTORY "include/spdlog" DESTINATION "${include_install_dir}")
-
-install(
-    FILES "${project_config}" "${version_config}"
-    DESTINATION "${config_install_dir}"
-)
-
-install(
-    EXPORT "${targets_export_name}"
-    NAMESPACE "${namespace}"
-    DESTINATION "${config_install_dir}"
-)
+#
+# Copyright(c) 2015 Ruslan Baratov.
+# Distributed under the MIT License (http://opensource.org/licenses/MIT)
+#
+
+cmake_minimum_required(VERSION 3.0)
+project(spdlog VERSION 1.0.0)
+
+set(CMAKE_CXX_STANDARD 11)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+
+add_library(spdlog INTERFACE)
+
+option(SPDLOG_BUILD_EXAMPLES "Build examples" OFF)
+
+target_include_directories(
+    spdlog
+    INTERFACE
+    "$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>"
+    "$<INSTALL_INTERFACE:include>"
+)
+
+if(SPDLOG_BUILD_EXAMPLES)
+  enable_testing()
+  add_subdirectory(example)
+endif()
+
+### Install ###
+# * https://github.com/forexample/package-example
+set(generated_dir "${CMAKE_CURRENT_BINARY_DIR}/generated")
+
+set(config_install_dir "lib/cmake/${PROJECT_NAME}")
+set(include_install_dir "include")
+set(pkgconfig_install_dir "lib/pkgconfig")
+
+set(version_config "${generated_dir}/${PROJECT_NAME}ConfigVersion.cmake")
+set(project_config "${generated_dir}/${PROJECT_NAME}Config.cmake")
+set(pkg_config "${generated_dir}/${PROJECT_NAME}.pc")
+set(targets_export_name "${PROJECT_NAME}Targets")
+set(namespace "${PROJECT_NAME}::")
+
+include(CMakePackageConfigHelpers)
+write_basic_package_version_file(
+    "${version_config}" COMPATIBILITY SameMajorVersion
+)
+
+# Note: use 'targets_export_name'
+configure_file("cmake/Config.cmake.in" "${project_config}" @ONLY)
+configure_file("cmake/spdlog.pc.in" "${pkg_config}" @ONLY)
+
+install(
+    TARGETS spdlog
+    EXPORT "${targets_export_name}"
+    INCLUDES DESTINATION "${include_install_dir}"
+)
+
+install(DIRECTORY "include/spdlog" DESTINATION "${include_install_dir}")
+
+install(
+    FILES "${project_config}" "${version_config}"
+    DESTINATION "${config_install_dir}"
+)
+
+install(
+    FILES "${pkg_config}"
+    DESTINATION "${pkgconfig_install_dir}"
+)
+
+install(
+    EXPORT "${targets_export_name}"
+    NAMESPACE "${namespace}"
+    DESTINATION "${config_install_dir}"
+)
diff --git a/LICENSE b/LICENSE
index a199709..806124d 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,6 +1,6 @@
 The MIT License (MIT)
 
-Copyright (c) 2015 Gabi Melman.                                       
+Copyright (c) 2016 Gabi Melman.                                       
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
diff --git a/README.md b/README.md
index bc55968..6416e45 100644
--- a/README.md
+++ b/README.md
@@ -1,157 +1,158 @@
-# spdlog
-
-Very fast, header only, C++ logging library. [![Build Status](https://travis-ci.org/gabime/spdlog.svg?branch=master)](https://travis-ci.org/gabime/spdlog)
-
-## Install
-Just copy the source [folder](https://github.com/gabime/spdlog/tree/master/include/spdlog) to your build tree and use a C++11 compiler
-
-## Platforms
- * Linux (gcc 4.8.1+, clang 3.5+)
- * Windows (visual studio 2013+, cygwin/mingw with g++ 4.9.1+)
- * Mac OSX (clang 3.5+)
-
-##Features
-* Very fast - performance is the primary goal (see [benchmarks](#benchmarks) below).
-* Headers only.
-* No dependencies - just copy and use.
-* Feature rich [call style](#usage-example) using the excellent [cppformat](http://cppformat.github.io/) library.
-* ostream call style is supported too.
-* Extremely fast asynchronous mode (optional) - using lockfree queues and other tricks to reach millions of calls/sec.
-* [Custom](https://github.com/gabime/spdlog/wiki/3.-Custom-formatting) formatting.
-* Multi/Single threaded loggers.
-* Various log targets:
-    * Rotating log files.
-    * Daily log files.
-    * Console logging.
-    * Linux syslog.
-    * Easily extendable with custom log targets  (just implement a single function in the [sink](include/spdlog/sinks/sink.h) interface).
-* Severity based filtering - threshold levels can be modified in runtime as well as in compile time.
-
-
-
-## Benchmarks
-
-Below are some [benchmarks](bench) comparing popular log libraries under Ubuntu 64 bit, Intel i7-4770 CPU @ 3.40GHz
-
-#### Synchronous mode
-Time needed to log 1,000,000 lines in synchronous mode (in seconds, the best of 3 runs):
-
-|threads|boost log 1.54|glog   |easylogging |spdlog|
-|-------|:-------:|:-----:|----------:|------:|
-|1|       4.169s  |1.066s |0.975s     |0.302s|
-|10|     6.180s   |3.032s |2.857s     |0.968s|
-|100|     5.981s  |1.139s |4.512s     |0.497s|
-
-
-#### Asynchronous mode
-Time needed to log 1,000,000 lines in asynchronous mode, i.e. the time it takes to put them in the async queue (in seconds, the best of 3 runs):
-
-|threads|g2log <sup>async logger</sup>   |spdlog <sup>async mode</sup>|
-|:-------|:-----:|-------------------------:|
-|1|       1.850s |0.216s |
-|10|      0.943s  |0.173s|
-|100|      0.959s |0.202s|
-
-
-
-
-## Usage Example
-```c++
-#include <iostream>
-#include "spdlog/spdlog.h"
-
-int main(int, char* [])
-{
-    namespace spd = spdlog;
-    try
-    {
-        //Create console, multithreaded logger
-        auto console = spd::stdout_logger_mt("console");
-        console->info("Welcome to spdlog!") ;
-        console->info("An info message example {}..", 1);
-        console->info() << "Streams are supported too  " << 1;
-
-        //Formatting examples
-        console->info("Easy padding in numbers like {:08d}", 12);
-        console->info("Support for int: {0:d};  hex: {0:x};  oct: {0:o}; bin: {0:b}", 42);
-        console->info("Support for floats {:03.2f}", 1.23456);
-        console->info("Positional args are {1} {0}..", "too", "supported");
-
-        console->info("{:<30}", "left aligned");
-        console->info("{:>30}", "right aligned");
-        console->info("{:^30}", "centered");
-
-        //
-        // Runtime log levels
-        //
-        spd::set_level(spd::level::info); //Set global log level to info
-        console->debug("This message shold not be displayed!");
-        console->set_level(spd::level::debug); // Set specific logger's log level
-        console->debug("Now it should..");
-
-        //
-        // Create a file rotating logger with 5mb size max and 3 rotated files
-        //
-        auto file_logger = spd::rotating_logger_mt("file_logger", "logs/mylogfile", 1048576 * 5, 3);
-        for(int i = 0; i < 10; ++i)
-		      file_logger->info("{} * {} equals {:>10}", i, i, i*i);
-
-        //
-        // Create a daily logger - a new file is created every day on 2:30am
-        //
-        auto daily_logger = spd::daily_logger_mt("daily_logger", "logs/daily", 2, 30);
-
-        //
-        // Customize msg format for all messages
-        //
-        spd::set_pattern("*** [%H:%M:%S %z] [thread %t] %v ***");
-        file_logger->info("This is another message with custom format");
-
-        spd::get("console")->info("loggers can be retrieved from a global registry using the spdlog::get(logger_name) function");
-
-        //
-        // Compile time debug or trace macros.
-        // Enabled #ifdef SPDLOG_DEBUG_ON or #ifdef SPDLOG_TRACE_ON
-        //
-        SPDLOG_TRACE(console, "Enabled only #ifdef SPDLOG_TRACE_ON..{} ,{}", 1, 3.23);
-        SPDLOG_DEBUG(console, "Enabled only #ifdef SPDLOG_DEBUG_ON.. {} ,{}", 1, 3.23);
-
-        //
-        // Asynchronous logging is very fast..
-        // Just call spdlog::set_async_mode(q_size) and all created loggers from now on will be asynchronous..
-        //
-        size_t q_size = 1048576; //queue size must be power of 2
-        spdlog::set_async_mode(q_size);
-        auto async_file= spd::daily_logger_st("async_file_logger", "logs/async_log.txt");
-        async_file->info() << "This is async log.." << "Should be very fast!";
-
-        //
-        // syslog example. linux only..
-        //
-        #ifdef __linux__
-        std::string ident = "spdlog-example";
-        auto syslog_logger = spd::syslog_logger("syslog", ident, LOG_PID);
-        syslog_logger->warn("This is warning that will end up in syslog. This is Linux only!");
-        #endif
-    }
-    catch (const spd::spdlog_ex& ex)
-    {
-        std::cout << "Log failed: " << ex.what() << std::endl;
-    }
-}
-
-
-// Example of user defined class with operator<<
-class some_class {};
-std::ostream& operator<<(std::ostream& os, const some_class& c) { return os << "some_class"; }
-
-void custom_class_example()
-{
-    some_class c;
-    spdlog::get("console")->info("custom class with operator<<: {}..", c);
-    spdlog::get("console")->info() << "custom class with operator<<: " << c << "..";
-}
-```
-
-## Documentation
-Documentation can be found in the [wiki](https://github.com/gabime/spdlog/wiki/1.-QuickStart) pages.
+# spdlog
+
+Very fast, header only, C++ logging library. [![Build Status](https://travis-ci.org/gabime/spdlog.svg?branch=master)](https://travis-ci.org/gabime/spdlog)
+
+## Install
+Just copy the source [folder](https://github.com/gabime/spdlog/tree/master/include/spdlog) to your build tree and use a C++11 compiler
+
+## Platforms
+ * Linux (gcc 4.8.1+, clang 3.5+)
+ * Windows (visual studio 2013+, cygwin/mingw with g++ 4.9.1+)
+ * Mac OSX (clang 3.5+)
+
+##Features
+* Very fast - performance is the primary goal (see [benchmarks](#benchmarks) below).
+* Headers only.
+* No dependencies - just copy and use.
+* Feature rich [call style](#usage-example) using the excellent [cppformat](http://cppformat.github.io/) library.
+* ostream call style is supported too.
+* Extremely fast asynchronous mode (optional) - using lockfree queues and other tricks to reach millions of calls/sec.
+* [Custom](https://github.com/gabime/spdlog/wiki/3.-Custom-formatting) formatting.
+* Multi/Single threaded loggers.
+* Various log targets:
+    * Rotating log files.
+    * Daily log files.
+    * Console logging (colors supported).
+    * Linux syslog.
+    * Easily extendable with custom log targets  (just implement a single function in the [sink](include/spdlog/sinks/sink.h) interface).
+* Severity based filtering - threshold levels can be modified in runtime as well as in compile time.
+
+
+
+## Benchmarks
+
+Below are some [benchmarks](bench) comparing popular log libraries under Ubuntu 64 bit, Intel i7-4770 CPU @ 3.40GHz
+
+#### Synchronous mode
+Time needed to log 1,000,000 lines in synchronous mode (in seconds, the best of 3 runs):
+
+|threads|boost log 1.54|glog   |easylogging |spdlog|
+|-------|:-------:|:-----:|----------:|------:|
+|1|       4.169s  |1.066s |0.975s     |0.302s|
+|10|     6.180s   |3.032s |2.857s     |0.968s|
+|100|     5.981s  |1.139s |4.512s     |0.497s|
+
+
+#### Asynchronous mode
+Time needed to log 1,000,000 lines in asynchronous mode, i.e. the time it takes to put them in the async queue (in seconds, the best of 3 runs):
+
+|threads|g2log <sup>async logger</sup>   |spdlog <sup>async mode</sup>|
+|:-------|:-----:|-------------------------:|
+|1|       1.850s |0.216s |
+|10|      0.943s  |0.173s|
+|100|      0.959s |0.202s|
+
+
+
+
+## Usage Example
+```c++
+#include <iostream>
+#include "spdlog/spdlog.h"
+
+int main(int, char* [])
+{
+    namespace spd = spdlog;
+    try
+    {
+        // console logger (multithreaded and with color)
+        auto console = spd::stdout_logger_mt("console", true);
+        console->info("Welcome to spdlog!") ;
+        console->info("An info message example {}..", 1);
+        console->info() << "Streams are supported too  " << 1;
+
+        //Formatting examples
+        console->info("Easy padding in numbers like {:08d}", 12);
+        console->info("Support for int: {0:d};  hex: {0:x};  oct: {0:o}; bin: {0:b}", 42);
+        console->info("Support for floats {:03.2f}", 1.23456);
+        console->info("Positional args are {1} {0}..", "too", "supported");
+
+        console->info("{:<30}", "left aligned");
+        console->info("{:>30}", "right aligned");
+        console->info("{:^30}", "centered");
+
+        //
+        // Runtime log levels
+        //
+        spd::set_level(spd::level::info); //Set global log level to info
+        console->debug("This message shold not be displayed!");
+        console->set_level(spd::level::debug); // Set specific logger's log level
+        console->debug("Now it should..");
+
+        //
+        // Create a file rotating logger with 5mb size max and 3 rotated files
+        //
+        auto file_logger = spd::rotating_logger_mt("file_logger", "logs/mylogfile", 1048576 * 5, 3);
+        for(int i = 0; i < 10; ++i)
+		      file_logger->info("{} * {} equals {:>10}", i, i, i*i);
+
+        //
+        // Create a daily logger - a new file is created every day on 2:30am
+        //
+        auto daily_logger = spd::daily_logger_mt("daily_logger", "logs/daily", 2, 30);
+
+        //
+        // Customize msg format for all messages
+        //
+        spd::set_pattern("*** [%H:%M:%S %z] [thread %t] %v ***");
+        file_logger->info("This is another message with custom format");
+
+        spd::get("console")->info("loggers can be retrieved from a global registry using the spdlog::get(logger_name) function");
+
+        //
+        // Compile time debug or trace macros.
+        // Enabled #ifdef SPDLOG_DEBUG_ON or #ifdef SPDLOG_TRACE_ON
+        //
+        SPDLOG_TRACE(console, "Enabled only #ifdef SPDLOG_TRACE_ON..{} ,{}", 1, 3.23);
+        SPDLOG_DEBUG(console, "Enabled only #ifdef SPDLOG_DEBUG_ON.. {} ,{}", 1, 3.23);
+
+        //
+        // Asynchronous logging is very fast..
+        // Just call spdlog::set_async_mode(q_size) and all created loggers from now on will be asynchronous..
+        //
+        size_t q_size = 1048576; //queue size must be power of 2
+        spdlog::set_async_mode(q_size);
+        auto async_file= spd::daily_logger_st("async_file_logger", "logs/async_log.txt");
+        async_file->info() << "This is async log.." << "Should be very fast!";
+
+        //
+        // syslog example. linux only..
+        //
+        #ifdef __linux__
+        std::string ident = "spdlog-example";
+        auto syslog_logger = spd::syslog_logger("syslog", ident, LOG_PID);
+        syslog_logger->warn("This is warning that will end up in syslog. This is Linux only!");
+        #endif
+                
+    }
+    catch (const spd::spdlog_ex& ex)
+    {
+        std::cout << "Log failed: " << ex.what() << std::endl;
+    }
+}
+
+
+// Example of user defined class with operator<<
+class some_class {};
+std::ostream& operator<<(std::ostream& os, const some_class& c) { return os << "some_class"; }
+
+void custom_class_example()
+{
+    some_class c;
+    spdlog::get("console")->info("custom class with operator<<: {}..", c);
+    spdlog::get("console")->info() << "custom class with operator<<: " << c << "..";
+}
+```
+
+## Documentation
+Documentation can be found in the [wiki](https://github.com/gabime/spdlog/wiki/1.-QuickStart) pages.
diff --git a/bench/Makefile b/bench/Makefile
index 6331f21..8416d04 100644
--- a/bench/Makefile
+++ b/bench/Makefile
@@ -1,65 +1,65 @@
-CXX	?= g++
-CXXFLAGS	= -march=native -Wall -Wextra -pedantic -std=c++11 -pthread -Wl,--no-as-needed  -I../include
-CXX_RELEASE_FLAGS = -O3 -flto -DNDEBUG
-
-
-binaries=spdlog-bench spdlog-bench-mt spdlog-async zf_log-bench zf_log-bench-mt boost-bench boost-bench-mt glog-bench glog-bench-mt g2log-async easylogging-bench easylogging-bench-mt
-
-all: $(binaries)
-
-spdlog-bench: spdlog-bench.cpp
-	$(CXX) spdlog-bench.cpp -o spdlog-bench $(CXXFLAGS) $(CXX_RELEASE_FLAGS)
-	
-spdlog-bench-mt: spdlog-bench-mt.cpp
-	$(CXX) spdlog-bench-mt.cpp -o spdlog-bench-mt  $(CXXFLAGS) $(CXX_RELEASE_FLAGS)
-	
-spdlog-async: spdlog-async.cpp
-	$(CXX) spdlog-async.cpp -o spdlog-async  $(CXXFLAGS) $(CXX_RELEASE_FLAGS)
-
-
-ZF_LOG_FLAGS = -I../../zf_log.git/zf_log/
-zf_log-bench: zf_log-bench.cpp
-	$(CXX) zf_log-bench.cpp -o zf_log-bench  $(CXXFLAGS) $(CXX_RELEASE_FLAGS) $(ZF_LOG_FLAGS)
-
-zf_log-bench-mt: zf_log-bench-mt.cpp
-	$(CXX) zf_log-bench-mt.cpp -o zf_log-bench-mt  $(CXXFLAGS) $(CXX_RELEASE_FLAGS) $(ZF_LOG_FLAGS)
-	
-
-BOOST_FLAGS	= -DBOOST_LOG_DYN_LINK  -I/usr/include -lboost_log  -lboost_log_setup -lboost_filesystem -lboost_system -lboost_thread -lboost_regex -lboost_date_time -lboost_chrono
-
-boost-bench: boost-bench.cpp
-	$(CXX) boost-bench.cpp -o boost-bench $(CXXFLAGS) $(BOOST_FLAGS) $(CXX_RELEASE_FLAGS)
-	
-boost-bench-mt: boost-bench-mt.cpp
-	$(CXX) boost-bench-mt.cpp -o boost-bench-mt $(CXXFLAGS) $(BOOST_FLAGS) $(CXX_RELEASE_FLAGS)	
-
-
-GLOG_FLAGS = -lglog
-glog-bench: glog-bench.cpp
-	$(CXX) glog-bench.cpp -o glog-bench $(CXXFLAGS) $(GLOG_FLAGS) $(CXX_RELEASE_FLAGS)
-	
-glog-bench-mt: glog-bench-mt.cpp
-	$(CXX) glog-bench-mt.cpp -o glog-bench-mt $(CXXFLAGS) $(GLOG_FLAGS) $(CXX_RELEASE_FLAGS)	
-
-
-G2LOG_FLAGS = -I/home/gabi/devel/g2log/g2log/src -L/home/gabi/devel/g2log/g2log -llib_g2logger 
-g2log-async: g2log-async.cpp
-	$(CXX) g2log-async.cpp -o g2log-async $(CXXFLAGS) $(G2LOG_FLAGS) $(CXX_RELEASE_FLAGS)
-	
-
-EASYL_FLAGS = -I../../easylogging/src/
-easylogging-bench: easylogging-bench.cpp
-	$(CXX) easylogging-bench.cpp -o easylogging-bench $(CXXFLAGS) $(EASYL_FLAGS) $(CXX_RELEASE_FLAGS)
-easylogging-bench-mt: easylogging-bench-mt.cpp
-	$(CXX) easylogging-bench-mt.cpp -o easylogging-bench-mt $(CXXFLAGS) $(EASYL_FLAGS) $(CXX_RELEASE_FLAGS)	
-	
-.PHONY: clean
-
-clean:
-	rm -f *.o logs/* $(binaries)
-
-
-rebuild: clean all
-
-
-
+CXX	?= g++
+CXXFLAGS	= -march=native -Wall -Wextra -pedantic -std=c++11 -pthread -Wl,--no-as-needed  -I../include
+CXX_RELEASE_FLAGS = -O3 -flto -DNDEBUG
+
+
+binaries=spdlog-bench spdlog-bench-mt spdlog-async zf_log-bench zf_log-bench-mt boost-bench boost-bench-mt glog-bench glog-bench-mt g2log-async easylogging-bench easylogging-bench-mt
+
+all: $(binaries)
+
+spdlog-bench: spdlog-bench.cpp
+	$(CXX) spdlog-bench.cpp -o spdlog-bench $(CXXFLAGS) $(CXX_RELEASE_FLAGS)
+	
+spdlog-bench-mt: spdlog-bench-mt.cpp
+	$(CXX) spdlog-bench-mt.cpp -o spdlog-bench-mt  $(CXXFLAGS) $(CXX_RELEASE_FLAGS)
+	
+spdlog-async: spdlog-async.cpp
+	$(CXX) spdlog-async.cpp -o spdlog-async  $(CXXFLAGS) $(CXX_RELEASE_FLAGS)
+
+
+ZF_LOG_FLAGS = -I../../zf_log.git/zf_log/
+zf_log-bench: zf_log-bench.cpp
+	$(CXX) zf_log-bench.cpp -o zf_log-bench  $(CXXFLAGS) $(CXX_RELEASE_FLAGS) $(ZF_LOG_FLAGS)
+
+zf_log-bench-mt: zf_log-bench-mt.cpp
+	$(CXX) zf_log-bench-mt.cpp -o zf_log-bench-mt  $(CXXFLAGS) $(CXX_RELEASE_FLAGS) $(ZF_LOG_FLAGS)
+	
+
+BOOST_FLAGS	= -DBOOST_LOG_DYN_LINK  -I/usr/include -lboost_log  -lboost_log_setup -lboost_filesystem -lboost_system -lboost_thread -lboost_regex -lboost_date_time -lboost_chrono
+
+boost-bench: boost-bench.cpp
+	$(CXX) boost-bench.cpp -o boost-bench $(CXXFLAGS) $(BOOST_FLAGS) $(CXX_RELEASE_FLAGS)
+	
+boost-bench-mt: boost-bench-mt.cpp
+	$(CXX) boost-bench-mt.cpp -o boost-bench-mt $(CXXFLAGS) $(BOOST_FLAGS) $(CXX_RELEASE_FLAGS)	
+
+
+GLOG_FLAGS = -lglog
+glog-bench: glog-bench.cpp
+	$(CXX) glog-bench.cpp -o glog-bench $(CXXFLAGS) $(GLOG_FLAGS) $(CXX_RELEASE_FLAGS)
+	
+glog-bench-mt: glog-bench-mt.cpp
+	$(CXX) glog-bench-mt.cpp -o glog-bench-mt $(CXXFLAGS) $(GLOG_FLAGS) $(CXX_RELEASE_FLAGS)	
+
+
+G2LOG_FLAGS = -I/home/gabi/devel/g2log/g2log/src -L/home/gabi/devel/g2log/g2log -llib_g2logger 
+g2log-async: g2log-async.cpp
+	$(CXX) g2log-async.cpp -o g2log-async $(CXXFLAGS) $(G2LOG_FLAGS) $(CXX_RELEASE_FLAGS)
+	
+
+EASYL_FLAGS = -I../../easylogging/src/
+easylogging-bench: easylogging-bench.cpp
+	$(CXX) easylogging-bench.cpp -o easylogging-bench $(CXXFLAGS) $(EASYL_FLAGS) $(CXX_RELEASE_FLAGS)
+easylogging-bench-mt: easylogging-bench-mt.cpp
+	$(CXX) easylogging-bench-mt.cpp -o easylogging-bench-mt $(CXXFLAGS) $(EASYL_FLAGS) $(CXX_RELEASE_FLAGS)	
+	
+.PHONY: clean
+
+clean:
+	rm -f *.o logs/* $(binaries)
+
+
+rebuild: clean all
+
+
+
diff --git a/bench/run_all.sh b/bench/run_all.sh
index 92fcd9e..fcecc37 100755
--- a/bench/run_all.sh
+++ b/bench/run_all.sh
@@ -1,76 +1,76 @@
-#~/bin/bash
-#execute each bench 3 times and print the timing
-
-exec 2>&1
-
-#execute and time given exe 3 times 
-bench_exe ()
-{	
-	echo "**************** $1 ****************"
-	for i in {1..3}; do 
-		time ./$1 $2; 
-		rm  -f logs/*
-		sleep 3
-	done;
-}
-
-#execute  given async tests 3 times (timing is already builtin)
-bench_async ()
-{	
-	echo "**************** $1 ****************"
-	for i in {1..3}; do 
-		./$1 $2; 
-		echo		
-		rm  -f logs/*
-		sleep 3
-	done;
-}
-
-
-echo "----------------------------------------------------------"
-echo "Single threaded benchmarks.. (1 thread,  1,000,000 lines)"
-echo "----------------------------------------------------------"
-for exe in boost-bench glog-bench easylogging-bench zf_log-bench spdlog-bench;
-do
-	bench_exe $exe 1
-done;
-
-echo "----------------------------------------------------------"
-echo "Multi threaded benchmarks.. (10 threads,  1,000,000 lines)"
-echo "----------------------------------------------------------"
-for exe in boost-bench-mt glog-bench-mt easylogging-bench-mt zf_log-bench-mt spdlog-bench-mt;
-do
-	bench_exe $exe 10
-done;
-
-echo "----------------------------------------------------------"
-echo "Multi threaded benchmarks.. (100 threads,  1,000,000 lines)"
-echo "----------------------------------------------------------"
-for exe in boost-bench-mt glog-bench-mt easylogging-bench-mt zf_log-bench-mt spdlog-bench-mt;
-do
-	bench_exe $exe 100
-done;
-
-echo "---------------------------------------------------------------"
-echo "Async, single threaded benchmark.. (1 thread,  1,000,000 lines)"
-echo "---------------------------------------------------------------"
-for exe in spdlog-async g2log-async
-do
-	bench_async $exe 1
-done;
-
-echo "---------------------------------------------------------------"
-echo "Async, multi threaded benchmark.. (10 threads,  1,000,000 lines)"
-echo "---------------------------------------------------------------"
-for exe in spdlog-async g2log-async
-do
-	bench_async $exe 10
-done;
-
-echo "---------------------------------------------------------------"
-echo "Async, multi threaded benchmark.. (100 threads,  1,000,000 lines)"
-echo "---------------------------------------------------------------"
-for exe in spdlog-async g2log-async
-do
-	bench_async $exe 100
-done;
+#~/bin/bash
+#execute each bench 3 times and print the timing
+
+exec 2>&1
+
+#execute and time given exe 3 times 
+bench_exe ()
+{	
+	echo "**************** $1 ****************"
+	for i in {1..3}; do 
+		time ./$1 $2; 
+		rm  -f logs/*
+		sleep 3
+	done;
+}
+
+#execute  given async tests 3 times (timing is already builtin)
+bench_async ()
+{	
+	echo "**************** $1 ****************"
+	for i in {1..3}; do 
+		./$1 $2; 
+		echo		
+		rm  -f logs/*
+		sleep 3
+	done;
+}
+
+
+echo "----------------------------------------------------------"
+echo "Single threaded benchmarks.. (1 thread,  1,000,000 lines)"
+echo "----------------------------------------------------------"
+for exe in boost-bench glog-bench easylogging-bench zf_log-bench spdlog-bench;
+do
+	bench_exe $exe 1
+done;
+
+echo "----------------------------------------------------------"
+echo "Multi threaded benchmarks.. (10 threads,  1,000,000 lines)"
+echo "----------------------------------------------------------"
+for exe in boost-bench-mt glog-bench-mt easylogging-bench-mt zf_log-bench-mt spdlog-bench-mt;
+do
+	bench_exe $exe 10
+done;
+
+echo "----------------------------------------------------------"
+echo "Multi threaded benchmarks.. (100 threads,  1,000,000 lines)"
+echo "----------------------------------------------------------"
+for exe in boost-bench-mt glog-bench-mt easylogging-bench-mt zf_log-bench-mt spdlog-bench-mt;
+do
+	bench_exe $exe 100
+done;
+
+echo "---------------------------------------------------------------"
+echo "Async, single threaded benchmark.. (1 thread,  1,000,000 lines)"
+echo "---------------------------------------------------------------"
+for exe in spdlog-async g2log-async
+do
+	bench_async $exe 1
+done;
+
+echo "---------------------------------------------------------------"
+echo "Async, multi threaded benchmark.. (10 threads,  1,000,000 lines)"
+echo "---------------------------------------------------------------"
+for exe in spdlog-async g2log-async
+do
+	bench_async $exe 10
+done;
+
+echo "---------------------------------------------------------------"
+echo "Async, multi threaded benchmark.. (100 threads,  1,000,000 lines)"
+echo "---------------------------------------------------------------"
+for exe in spdlog-async g2log-async
+do
+	bench_async $exe 100
+done;
diff --git a/bench/zf_log-bench-mt.cpp b/bench/zf_log-bench-mt.cpp
index 3463d7e..aace277 100644
--- a/bench/zf_log-bench-mt.cpp
+++ b/bench/zf_log-bench-mt.cpp
@@ -11,21 +11,21 @@ int g_fd;
 
 static void output_callback(zf_log_message *msg)
 {
-	*msg->p = '\n';
-	write(g_fd, msg->buf, msg->p - msg->buf + 1);
+    *msg->p = '\n';
+    write(g_fd, msg->buf, msg->p - msg->buf + 1);
 }
 
 using namespace std;
 
 int main(int argc, char* argv[])
 {
-	g_fd = open(g_path, O_APPEND|O_CREAT|O_WRONLY);
-	if (0 > g_fd)
-	{
-		ZF_LOGE_AUX(ZF_LOG_STDERR, "Failed to open log file: %s", g_path);
-		return -1;
-	}
-	zf_log_set_output_callback(ZF_LOG_PUT_STD, output_callback);
+    g_fd = open(g_path, O_APPEND|O_CREAT|O_WRONLY);
+    if (0 > g_fd)
+    {
+        ZF_LOGE_AUX(ZF_LOG_STDERR, "Failed to open log file: %s", g_path);
+        return -1;
+    }
+    zf_log_set_output_callback(ZF_LOG_PUT_STD, output_callback);
 
     int thread_count = 10;
     if(argc > 1)
@@ -42,7 +42,7 @@ int main(int argc, char* argv[])
             {
                 int counter = ++msg_counter;
                 if (counter > howmany) break;
-				ZF_LOGI("zf_log message #%i: This is some text for your pleasure", counter);
+                ZF_LOGI("zf_log message #%i: This is some text for your pleasure", counter);
             }
         }));
     }
@@ -51,6 +51,6 @@ int main(int argc, char* argv[])
     {
         t.join();
     };
-	close(g_fd);
+    close(g_fd);
     return 0;
 }
diff --git a/bench/zf_log-bench.cpp b/bench/zf_log-bench.cpp
index dfa2892..a6e3e1f 100644
--- a/bench/zf_log-bench.cpp
+++ b/bench/zf_log-bench.cpp
@@ -6,22 +6,23 @@ static FILE *g_f;
 
 static void output_callback(zf_log_message *msg)
 {
-	*msg->p = '\n';
-	fwrite(msg->buf, msg->p - msg->buf + 1, 1, g_f);
+    *msg->p = '\n';
+    fwrite(msg->buf, msg->p - msg->buf + 1, 1, g_f);
 }
 
 int main(int, char* [])
 {
-	g_f = fopen(g_path, "wb");
-	if (!g_f) {
-		ZF_LOGE_AUX(ZF_LOG_STDERR, "Failed to open log file: %s", g_path);
-		return -1;
-	}
-	zf_log_set_output_callback(ZF_LOG_PUT_STD, output_callback);
+    g_f = fopen(g_path, "wb");
+    if (!g_f)
+    {
+        ZF_LOGE_AUX(ZF_LOG_STDERR, "Failed to open log file: %s", g_path);
+        return -1;
+    }
+    zf_log_set_output_callback(ZF_LOG_PUT_STD, output_callback);
 
     const int howmany = 1000000;
     for(int i  = 0 ; i < howmany; ++i)
-		ZF_LOGI("zf_log message #%i: This is some text for your pleasure", i);
-	fclose(g_f);
+        ZF_LOGI("zf_log message #%i: This is some text for your pleasure", i);
+    fclose(g_f);
     return 0;
 }
diff --git a/cmake/spdlog.pc.in b/cmake/spdlog.pc.in
new file mode 100644
index 0000000..2c94a0a
--- /dev/null
+++ b/cmake/spdlog.pc.in
@@ -0,0 +1,6 @@
+prefix=@CMAKE_INSTALL_PREFIX@
+includedir=${prefix}/include
+
+Name: @PROJECT_NAME@
+Description: Super fast C++ logging library. 
+Version: @PROJECT_VERSION@
diff --git a/example/example.cpp b/example/example.cpp
index ac45bdd..b3d6c43 100644
--- a/example/example.cpp
+++ b/example/example.cpp
@@ -5,22 +5,27 @@
 //
 // spdlog usage example
 //
+#include "spdlog/spdlog.h"
+
 #include <cstdlib> // EXIT_FAILURE
 #include <iostream>
-#include "spdlog/spdlog.h"
+#include <memory>
 
+void async_example();
+void syslog_example();
+
+namespace spd = spdlog;
 int main(int, char*[])
 {
-    namespace spd = spdlog;
     try
     {
-        //Create console, multithreaded logger
-        auto console = spd::stdout_logger_mt("console");
+        // Multithreaded color console
+        auto console = spd::stdout_logger_mt("console", true);
         console->info("Welcome to spdlog!");
         console->info("An info message example {}..", 1);
         console->info() << "Streams are supported too  " << 1;
 
-        //Formatting examples
+        // Formatting examples
         console->info("Easy padding in numbers like {:08d}", 12);
         console->info("Support for int: {0:d};  hex: {0:x};  oct: {0:o}; bin: {0:b}", 42);
         console->info("Support for floats {:03.2f}", 1.23456);
@@ -30,64 +35,41 @@ int main(int, char*[])
         console->info("{:>30}", "right aligned");
         console->info("{:^30}", "centered");
 
-        //
+        spd::get("console")->info("loggers can be retrieved from a global registry using the spdlog::get(logger_name) function");
+
         // Runtime log levels
-        //
         spd::set_level(spd::level::info); //Set global log level to info
         console->debug("This message shold not be displayed!");
         console->set_level(spd::level::debug); // Set specific logger's log level
-        console->debug("Now it should..");
+        console->debug("This message shold be displayed..");
 
-        //
         // Create a file rotating logger with 5mb size max and 3 rotated files
-        //
         auto file_logger = spd::rotating_logger_mt("file_logger", "logs/mylogfile", 1048576 * 5, 3);
         for (int i = 0; i < 10; ++i)
             file_logger->info("{} * {} equals {:>10}", i, i, i*i);
 
-
-        //
         // Create a daily logger - a new file is created every day on 2:30am
-        //
         auto daily_logger = spd::daily_logger_mt("daily_logger", "logs/daily", 2, 30);
 
-        //
         // Customize msg format for all messages
-        //
         spd::set_pattern("*** [%H:%M:%S %z] [thread %t] %v ***");
         file_logger->info("This is another message with custom format");
 
-        spd::get("console")->info("loggers can be retrieved from a global registry using the spdlog::get(logger_name) function");
 
-        //
         // Compile time debug or trace macros.
         // Enabled #ifdef SPDLOG_DEBUG_ON or #ifdef SPDLOG_TRACE_ON
-        //
         SPDLOG_TRACE(console, "Enabled only #ifdef SPDLOG_TRACE_ON..{} ,{}", 1, 3.23);
         SPDLOG_DEBUG(console, "Enabled only #ifdef SPDLOG_DEBUG_ON.. {} ,{}", 1, 3.23);
 
-        //
         // Asynchronous logging is very fast..
         // Just call spdlog::set_async_mode(q_size) and all created loggers from now on will be asynchronous..
-        //
-        size_t q_size = 1048576; //queue size must be power of 2
-        spdlog::set_async_mode(q_size);
-        auto async_file = spd::daily_logger_st("async_file_logger", "logs/async_log.txt");
-        for (int i = 0; i < 100; ++i)
-            async_file->info("Async message #{}", i);
-
-        //
-        // syslog example. linux only..
-        //
-#ifdef __linux__
-        std::string ident = "spdlog-example";
-        auto syslog_logger = spd::syslog_logger("syslog", ident, LOG_PID);
-        syslog_logger->warn("This is warning that will end up in syslog. This is Linux only!");
-#endif
+        async_example();
+
+        // syslog example. linux/osx only..
+        syslog_example();
 
-        //
-        //Release and close all loggers
-        //
+
+        // Release and close all loggers
         spdlog::drop_all();
     }
 
@@ -100,6 +82,26 @@ int main(int, char*[])
 }
 
 
+void async_example()
+{
+    size_t q_size = 4096; //queue size must be power of 2
+    spdlog::set_async_mode(q_size);
+    auto async_file = spd::daily_logger_st("async_file_logger", "logs/async_log.txt");
+    for (int i = 0; i < 100; ++i)
+        async_file->info("Async message #{}", i);
+}
+
+//syslog example (linux/osx only)
+void syslog_example()
+{
+#if defined (__linux__) || defined(__APPLE__)
+    std::string ident = "spdlog-example";
+    auto syslog_logger = spd::syslog_logger("syslog", ident, LOG_PID);
+    syslog_logger->warn("This is warning that will end up in syslog. This is Linux only!");
+#endif
+}
+
+
 // Example of user defined class with operator<<
 class some_class {};
 std::ostream& operator<<(std::ostream& os, const some_class&)
diff --git a/example/example.vcxproj b/example/example.vcxproj
index a8218f4..b7988fc 100644
--- a/example/example.vcxproj
+++ b/example/example.vcxproj
@@ -1,90 +1,90 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="example.cpp" />
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{9E5AB93A-0CCE-4BAC-9FCB-0FC9CB5EB8D2}</ProjectGuid>
-    <Keyword>Win32Proj</Keyword>
-    <RootNamespace>.</RootNamespace>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <PlatformToolset>v140</PlatformToolset>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <PlatformToolset>v140</PlatformToolset>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <LinkIncremental>true</LinkIncremental>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <LinkIncremental>false</LinkIncremental>
-  </PropertyGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <PrecompiledHeader>
-      </PrecompiledHeader>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PrecompiledHeaderFile />
-      <PrecompiledHeaderOutputFile />
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <PrecompiledHeader>
-      </PrecompiledHeader>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PrecompiledHeaderFile />
-      <PrecompiledHeaderOutputFile />
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-    </Link>
-  </ItemDefinitionGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="example.cpp" />
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{9E5AB93A-0CCE-4BAC-9FCB-0FC9CB5EB8D2}</ProjectGuid>
+    <Keyword>Win32Proj</Keyword>
+    <RootNamespace>.</RootNamespace>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v140</PlatformToolset>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v140</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <LinkIncremental>true</LinkIncremental>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <LinkIncremental>false</LinkIncremental>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PrecompiledHeaderFile />
+      <PrecompiledHeaderOutputFile />
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PrecompiledHeaderFile />
+      <PrecompiledHeaderOutputFile />
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
 </Project>
\ No newline at end of file
diff --git a/example/logs/.gitignore b/example/logs/.gitignore
index 5e7d273..960fe79 100644
--- a/example/logs/.gitignore
+++ b/example/logs/.gitignore
@@ -1,4 +1,2 @@
-# Ignore everything in this directory
-*
-# Except this file
-!.gitignore
+*.txt
+
diff --git a/include/spdlog/async_logger.h b/include/spdlog/async_logger.h
index be21501..786eb02 100644
--- a/include/spdlog/async_logger.h
+++ b/include/spdlog/async_logger.h
@@ -13,7 +13,7 @@
 //    1. Checks if its log level is enough to log the message
 //    2. Push a new copy of the message to a queue (or block the caller until space is available in the queue)
 //    3. will throw spdlog_ex upon log exceptions
-// Upong destruction, logs all remaining messages in the queue before destructing..
+// Upon destruction, logs all remaining messages in the queue before destructing..
 
 #include <spdlog/common.h>
 #include <spdlog/logger.h>
@@ -41,21 +41,24 @@ public:
                  size_t queue_size,
                  const async_overflow_policy overflow_policy =  async_overflow_policy::block_retry,
                  const std::function<void()>& worker_warmup_cb = nullptr,
-                 const std::chrono::milliseconds& flush_interval_ms = std::chrono::milliseconds::zero());
+                 const std::chrono::milliseconds& flush_interval_ms = std::chrono::milliseconds::zero(),
+                 const std::function<void()>& worker_teardown_cb = nullptr);
 
     async_logger(const std::string& logger_name,
                  sinks_init_list sinks,
                  size_t queue_size,
                  const async_overflow_policy overflow_policy = async_overflow_policy::block_retry,
                  const std::function<void()>& worker_warmup_cb = nullptr,
-                 const std::chrono::milliseconds& flush_interval_ms = std::chrono::milliseconds::zero());
+                 const std::chrono::milliseconds& flush_interval_ms = std::chrono::milliseconds::zero(),
+                 const std::function<void()>& worker_teardown_cb = nullptr);
 
     async_logger(const std::string& logger_name,
                  sink_ptr single_sink,
                  size_t queue_size,
                  const async_overflow_policy overflow_policy =  async_overflow_policy::block_retry,
                  const std::function<void()>& worker_warmup_cb = nullptr,
-                 const std::chrono::milliseconds& flush_interval_ms = std::chrono::milliseconds::zero());
+                 const std::chrono::milliseconds& flush_interval_ms = std::chrono::milliseconds::zero(),
+                 const std::function<void()>& worker_teardown_cb = nullptr);
 
 
     void flush() override;
@@ -71,4 +74,3 @@ private:
 
 
 #include <spdlog/details/async_logger_impl.h>
-
diff --git a/include/spdlog/common.h b/include/spdlog/common.h
index 269c881..2156505 100644
--- a/include/spdlog/common.h
+++ b/include/spdlog/common.h
@@ -5,20 +5,30 @@
 
 #pragma once
 
+
 #include <string>
 #include <initializer_list>
 #include <chrono>
 #include <memory>
+#include <atomic>
 #include <exception>
+#if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES)
+#include <codecvt>
+#include <locale>
+#endif
 
-//visual studio does not support noexcept yet
-#ifndef _MSC_VER
-#define SPDLOG_NOEXCEPT noexcept
-#else
+#include <spdlog/details/null_mutex.h>
+
+
+//visual studio upto 2013 does not support noexcept
+#if defined(_MSC_VER) && (_MSC_VER < 1900)
 #define SPDLOG_NOEXCEPT throw()
+#else
+#define SPDLOG_NOEXCEPT noexcept
 #endif
 
 
+
 namespace spdlog
 {
 
@@ -34,7 +44,11 @@ using log_clock = std::chrono::system_clock;
 using sink_ptr = std::shared_ptr < sinks::sink >;
 using sinks_init_list = std::initializer_list < sink_ptr >;
 using formatter_ptr = std::shared_ptr<spdlog::formatter>;
-
+#if defined(SPDLOG_NO_ATOMIC_LEVELS)
+using level_t = details::null_atomic_int;
+#else
+using level_t = std::atomic_int;
+#endif
 
 //Log level enum
 namespace level
@@ -95,4 +109,25 @@ private:
 
 };
 
+//
+// wchar support for windows file names (SPDLOG_WCHAR_FILENAMES must be defined)
+//
+#if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES)
+#define SPDLOG_FILENAME_T(s) L ## s
+using filename_t = std::wstring;
+inline std::string filename_to_str(const filename_t& filename)
+{
+    std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> c;
+    return c.to_bytes(filename);
+}
+#else
+#define SPDLOG_FILENAME_T(s) s
+using filename_t = std::string;
+
+inline std::string filename_to_str(const filename_t& filename)
+{
+    return filename;
+}
+#endif
+
 } //spdlog
diff --git a/include/spdlog/details/async_log_helper.h b/include/spdlog/details/async_log_helper.h
index 8555ef0..eb7f476 100644
--- a/include/spdlog/details/async_log_helper.h
+++ b/include/spdlog/details/async_log_helper.h
@@ -121,7 +121,8 @@ public:
                      size_t queue_size,
                      const async_overflow_policy overflow_policy = async_overflow_policy::block_retry,
                      const std::function<void()>& worker_warmup_cb = nullptr,
-                     const std::chrono::milliseconds& flush_interval_ms = std::chrono::milliseconds::zero());
+                     const std::chrono::milliseconds& flush_interval_ms = std::chrono::milliseconds::zero(),
+                     const std::function<void()>& worker_teardown_cb = nullptr);
 
     void log(const details::log_msg& msg);
 
@@ -157,12 +158,15 @@ private:
     // auto periodic sink flush parameter
     const std::chrono::milliseconds _flush_interval_ms;
 
+    // worker thread teardown callback
+    const std::function<void()> _worker_teardown_cb;
+
     // worker thread
     std::thread _worker_thread;
 
     void push_msg(async_msg&& new_msg);
-    // throw last worker thread exception or if worker thread is not active
 
+    // throw last worker thread exception or if worker thread is not active
     void throw_if_bad_worker();
 
     // worker thread main loop
@@ -190,7 +194,8 @@ inline spdlog::details::async_log_helper::async_log_helper(
     size_t queue_size,
     const async_overflow_policy overflow_policy,
     const std::function<void()>& worker_warmup_cb,
-    const std::chrono::milliseconds& flush_interval_ms):
+    const std::chrono::milliseconds& flush_interval_ms,
+    const std::function<void()>& worker_teardown_cb):
     _formatter(formatter),
     _sinks(sinks),
     _q(queue_size),
@@ -199,6 +204,7 @@ 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)
 {}
 
@@ -216,7 +222,7 @@ inline spdlog::details::async_log_helper::~async_log_helper()
 }
 
 
-//Try to push and block until succeeded
+//Try to push and block until succeeded (if the policy is not to discard when the queue is full)
 inline void spdlog::details::async_log_helper::log(const details::log_msg& msg)
 {
     push_msg(async_msg(msg));
@@ -224,7 +230,6 @@ inline void spdlog::details::async_log_helper::log(const details::log_msg& msg)
 
 }
 
-//Try to push and block until succeeded
 inline void spdlog::details::async_log_helper::push_msg(details::async_log_helper::async_msg&& new_msg)
 {
     throw_if_bad_worker();
@@ -255,6 +260,7 @@ inline void spdlog::details::async_log_helper::worker_loop()
         auto last_pop = details::os::now();
         auto last_flush = last_pop;
         while(process_next_msg(last_pop, last_flush));
+        if (_worker_teardown_cb) _worker_teardown_cb();
     }
     catch (const std::exception& ex)
     {
@@ -267,7 +273,7 @@ inline void spdlog::details::async_log_helper::worker_loop()
 }
 
 // process next message in the queue
-// return true if this thread should still be active (no msg with level::off was received)
+// return true if this thread should still be active (while no terminate msg was received)
 inline bool spdlog::details::async_log_helper::process_next_msg(log_clock::time_point& last_pop, log_clock::time_point& last_flush)
 {
 
@@ -309,6 +315,7 @@ inline bool spdlog::details::async_log_helper::process_next_msg(log_clock::time_
     }
 }
 
+// flush all sinks if _flush_interval_ms has expired
 inline void spdlog::details::async_log_helper::handle_flush_interval(log_clock::time_point& now, log_clock::time_point& last_flush)
 {
     auto should_flush = _flush_requested || (_flush_interval_ms != std::chrono::milliseconds::zero() && now - last_flush >= _flush_interval_ms);
@@ -320,34 +327,37 @@ inline void spdlog::details::async_log_helper::handle_flush_interval(log_clock::
         _flush_requested = false;
     }
 }
+
 inline void spdlog::details::async_log_helper::set_formatter(formatter_ptr msg_formatter)
 {
     _formatter = msg_formatter;
 }
 
 
-// sleep,yield or return immediatly using the time passed since last message as a hint
+// spin, yield or sleep. use the time passed since last message as a hint
 inline void spdlog::details::async_log_helper::sleep_or_yield(const spdlog::log_clock::time_point& now, const spdlog::log_clock::time_point& last_op_time)
 {
-    using std::chrono::milliseconds;
     using namespace std::this_thread;
-
+    using std::chrono::milliseconds;
+    using std::chrono::microseconds;
+       
     auto time_since_op = now - last_op_time;
-
-    // spin upto 1 ms
-    if (time_since_op <= milliseconds(1))
+    
+    // spin upto 50 micros
+    if (time_since_op <= microseconds(50))
         return;
-
-    // yield upto 10ms
-    if (time_since_op <= milliseconds(10))
+        
+    // yield upto 150 micros
+    if (time_since_op <= microseconds(100))
         return yield();
 
 
-    // sleep for half of duration since last op
-    if (time_since_op <= milliseconds(100))
-        return sleep_for(time_since_op / 2);
+    // sleep for 20 ms upto 200 ms
+    if (time_since_op <= milliseconds(200))
+        return sleep_for(milliseconds(20));
 
-    return sleep_for(milliseconds(100));
+    // sleep for 200 ms 
+    return sleep_for(milliseconds(200));
 }
 
 // throw if the worker thread threw an exception or not active
diff --git a/include/spdlog/details/async_logger_impl.h b/include/spdlog/details/async_logger_impl.h
index 140d45f..ebacdb5 100644
--- a/include/spdlog/details/async_logger_impl.h
+++ b/include/spdlog/details/async_logger_impl.h
@@ -23,9 +23,10 @@ inline spdlog::async_logger::async_logger(const std::string& logger_name,
         size_t queue_size,
         const  async_overflow_policy overflow_policy,
         const std::function<void()>& worker_warmup_cb,
-        const std::chrono::milliseconds& flush_interval_ms) :
+        const std::chrono::milliseconds& flush_interval_ms,
+        const std::function<void()>& worker_teardown_cb) :
     logger(logger_name, begin, end),
-    _async_log_helper(new details::async_log_helper(_formatter, _sinks, queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms))
+    _async_log_helper(new details::async_log_helper(_formatter, _sinks, queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb))
 {
 }
 
@@ -34,19 +35,21 @@ inline spdlog::async_logger::async_logger(const std::string& logger_name,
         size_t queue_size,
         const  async_overflow_policy overflow_policy,
         const std::function<void()>& worker_warmup_cb,
-        const std::chrono::milliseconds& flush_interval_ms) :
-    async_logger(logger_name, sinks.begin(), sinks.end(), queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms) {}
+        const std::chrono::milliseconds& flush_interval_ms,
+        const std::function<void()>& worker_teardown_cb) :
+    async_logger(logger_name, sinks.begin(), sinks.end(), queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb) {}
 
 inline spdlog::async_logger::async_logger(const std::string& logger_name,
         sink_ptr single_sink,
         size_t queue_size,
         const  async_overflow_policy overflow_policy,
         const std::function<void()>& worker_warmup_cb,
-        const std::chrono::milliseconds& flush_interval_ms) :
+        const std::chrono::milliseconds& flush_interval_ms,
+        const std::function<void()>& worker_teardown_cb) :
     async_logger(logger_name,
 {
     single_sink
-}, queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms) {}
+      }, queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb) {}
 
 
 inline void spdlog::async_logger::flush()
diff --git a/include/spdlog/details/file_helper.h b/include/spdlog/details/file_helper.h
index e563d00..024a21b 100644
--- a/include/spdlog/details/file_helper.h
+++ b/include/spdlog/details/file_helper.h
@@ -43,11 +43,11 @@ public:
     }
 
 
-    void open(const std::string& fname, bool truncate = false)
+    void open(const filename_t& fname, bool truncate = false)
     {
 
         close();
-        const char* mode = truncate ? "wb" : "ab";
+        auto *mode = truncate ? SPDLOG_FILENAME_T("wb") : SPDLOG_FILENAME_T("ab");
         _filename = fname;
         for (int tries = 0; tries < open_tries; ++tries)
         {
@@ -57,7 +57,7 @@ public:
             std::this_thread::sleep_for(std::chrono::milliseconds(open_interval));
         }
 
-        throw spdlog_ex("Failed opening file " + fname + " for writing");
+        throw spdlog_ex("Failed opening file " + filename_to_str(_filename) + " for writing");
     }
 
     void reopen(bool truncate)
@@ -88,7 +88,7 @@ public:
         size_t msg_size = msg.formatted.size();
         auto data = msg.formatted.data();
         if (std::fwrite(data, 1, msg_size, _fd) != msg_size)
-            throw spdlog_ex("Failed writing to file " + _filename);
+            throw spdlog_ex("Failed writing to file " + filename_to_str(_filename));
 
         if (_force_flush)
             std::fflush(_fd);
@@ -98,19 +98,19 @@ public:
     long size()
     {
         if (!_fd)
-            throw spdlog_ex("Cannot use size() on closed file " + _filename);
+            throw spdlog_ex("Cannot use size() on closed file " + filename_to_str(_filename));
 
         auto pos = ftell(_fd);
         if (fseek(_fd, 0, SEEK_END) != 0)
-            throw spdlog_ex("fseek failed on file " + _filename);
+            throw spdlog_ex("fseek failed on file " + filename_to_str(_filename));
 
         auto file_size = ftell(_fd);
 
         if(fseek(_fd, pos, SEEK_SET) !=0)
-            throw spdlog_ex("fseek failed on file " + _filename);
+            throw spdlog_ex("fseek failed on file " + filename_to_str(_filename));
 
         if (file_size == -1)
-            throw spdlog_ex("ftell failed on file " + _filename);
+            throw spdlog_ex("ftell failed on file " + filename_to_str(_filename));
 
 
         return file_size;
@@ -118,12 +118,12 @@ public:
 
     }
 
-    const std::string& filename() const
+    const filename_t& filename() const
     {
         return _filename;
     }
 
-    static bool file_exists(const std::string& name)
+    static bool file_exists(const filename_t& name)
     {
 
         return os::file_exists(name);
@@ -133,7 +133,7 @@ public:
 
 private:
     FILE* _fd;
-    std::string _filename;
+    filename_t _filename;
     bool _force_flush;
 
 
diff --git a/include/spdlog/details/format.cc b/include/spdlog/details/format.cc
index c77e1ef..cd246e4 100644
--- a/include/spdlog/details/format.cc
+++ b/include/spdlog/details/format.cc
@@ -1,949 +1,1066 @@
-/*
-Formatting library for C++
-
-Copyright (c) 2012 - 2015, Victor Zverovich
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-1. Redistributions of source code must retain the above copyright notice, this
-list of conditions and the following disclaimer.
-2. Redistributions in binary form must reproduce the above copyright notice,
-this list of conditions and the following disclaimer in the documentation
-and/or other materials provided with the distribution.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#include "format.h"
-
-#include <string.h>
-
-#include <cctype>
-#include <cerrno>
-#include <climits>
-#include <cmath>
-#include <cstdarg>
-#include <cstddef>  // for std::ptrdiff_t
-
-#if defined(_WIN32) && defined(__MINGW32__)
-# include <cstring>
-#endif
-
-#if FMT_USE_WINDOWS_H
-# if defined(NOMINMAX) || defined(FMT_WIN_MINMAX)
-#  include <windows.h>
-# else
-#  define NOMINMAX
-#  include <windows.h>
-#  undef NOMINMAX
-# endif
-#endif
-
-using fmt::internal::Arg;
-
-#if FMT_EXCEPTIONS
-# define FMT_TRY try
-# define FMT_CATCH(x) catch (x)
-#else
-# define FMT_TRY if (true)
-# define FMT_CATCH(x) if (false)
-#endif
-
-#ifdef FMT_HEADER_ONLY
-# define FMT_FUNC inline
-#else
-# define FMT_FUNC
-#endif
-
-#ifdef _MSC_VER
-# pragma warning(push)
-# pragma warning(disable: 4127)  // conditional expression is constant
-# pragma warning(disable: 4702)  // unreachable code
-// Disable deprecation warning for strerror. The latter is not called but
-// MSVC fails to detect it.
-# pragma warning(disable: 4996)
-#endif
-
-// Dummy implementations of strerror_r and strerror_s called if corresponding
-// system functions are not available.
-static inline fmt::internal::Null<> strerror_r(int, char *, ...) {
-    return fmt::internal::Null<>();
-}
-static inline fmt::internal::Null<> strerror_s(char *, std::size_t, ...) {
-    return fmt::internal::Null<>();
-}
-
-namespace fmt {
-namespace {
-
-#ifndef _MSC_VER
-# define FMT_SNPRINTF snprintf
-#else  // _MSC_VER
-inline int fmt_snprintf(char *buffer, size_t size, const char *format, ...) {
-    va_list args;
-    va_start(args, format);
-    int result = vsnprintf_s(buffer, size, _TRUNCATE, format, args);
-    va_end(args);
-    return result;
-}
-# define FMT_SNPRINTF fmt_snprintf
-#endif  // _MSC_VER
-
-#if defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT)
-# define FMT_SWPRINTF snwprintf
-#else
-# define FMT_SWPRINTF swprintf
-#endif // defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT)
-
-// Checks if a value fits in int - used to avoid warnings about comparing
-// signed and unsigned integers.
-template <bool IsSigned>
-struct IntChecker {
-    template <typename T>
-    static bool fits_in_int(T value) {
-        unsigned max = INT_MAX;
-        return value <= max;
-    }
-    static bool fits_in_int(bool) {
-        return true;
-    }
-};
-
-template <>
-struct IntChecker<true> {
-    template <typename T>
-    static bool fits_in_int(T value) {
-        return value >= INT_MIN && value <= INT_MAX;
-    }
-    static bool fits_in_int(int) {
-        return true;
-    }
-};
-
-const char RESET_COLOR[] = "\x1b[0m";
-
-typedef void(*FormatFunc)(fmt::Writer &, int, fmt::StringRef);
-
-// Portable thread-safe version of strerror.
-// Sets buffer to point to a string describing the error code.
-// This can be either a pointer to a string stored in buffer,
-// or a pointer to some static immutable string.
-// Returns one of the following values:
-//   0      - success
-//   ERANGE - buffer is not large enough to store the error message
-//   other  - failure
-// 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");
-
-    class StrError {
-    private:
-        int error_code_;
-        char *&buffer_;
-        std::size_t buffer_size_;
-
-        // A noop assignment operator to avoid bogus warnings.
-        void operator=(const StrError &) {}
-
-        // Handle the result of XSI-compliant version of strerror_r.
-        int handle(int result) {
-            // glibc versions before 2.13 return result in errno.
-            return result == -1 ? errno : result;
-        }
-
-        // Handle the result of GNU-specific version of strerror_r.
-        int handle(char *message) {
-            // If the buffer is full then the message is probably truncated.
-            if (message == buffer_ && strlen(buffer_) == buffer_size_ - 1)
-                return ERANGE;
-            buffer_ = message;
-            return 0;
-        }
-
-        // Handle the case when strerror_r is not available.
-        int handle(fmt::internal::Null<>) {
-            return fallback(strerror_s(buffer_, buffer_size_, error_code_));
-        }
-
-        // Fallback to strerror_s when strerror_r is not available.
-        int fallback(int result) {
-            // If the buffer is full then the message is probably truncated.
-            return result == 0 && strlen(buffer_) == buffer_size_ - 1 ?
-            ERANGE : result;
-        }
-
-        // Fallback to strerror if strerror_r and strerror_s are not available.
-        int fallback(fmt::internal::Null<>) {
-            errno = 0;
-            buffer_ = strerror(error_code_);
-            return errno;
-        }
-
-    public:
-        StrError(int err_code, char *&buf, std::size_t buf_size)
-            : error_code_(err_code), buffer_(buf), buffer_size_(buf_size) {}
-
-        int run() {
-            strerror_r(0, 0, "");  // Suppress a warning about unused strerror_r.
-            return handle(strerror_r(error_code_, buffer_, buffer_size_));
-        }
-    };
-    return StrError(error_code, buffer, buffer_size).run();
-}
-
-void format_error_code(fmt::Writer &out, int error_code,
-                       fmt::StringRef message) FMT_NOEXCEPT{
-    // Report error code making sure that the output fits into
-    // INLINE_BUFFER_SIZE to avoid dynamic memory allocation and potential
-    // bad_alloc.
-    out.clear();
-    static const char SEP[] = ": ";
-    static const char ERROR_STR[] = "error ";
-    fmt::internal::IntTraits<int>::MainType ec_value = error_code;
-    // Subtract 2 to account for terminating null characters in SEP and ERROR_STR.
-    std::size_t error_code_size = sizeof(SEP) + sizeof(ERROR_STR) - 2;
-    error_code_size += fmt::internal::count_digits(ec_value);
-    if (message.size() <= fmt::internal::INLINE_BUFFER_SIZE - error_code_size)
-        out << message << SEP;
-    out << ERROR_STR << error_code;
-    assert(out.size() <= fmt::internal::INLINE_BUFFER_SIZE);
-}
-
-void report_error(FormatFunc func,
-                  int error_code, fmt::StringRef message) FMT_NOEXCEPT{
-    fmt::MemoryWriter full_message;
-    func(full_message, error_code, message);
-    // Use Writer::data instead of Writer::c_str to avoid potential memory
-    // allocation.
-    std::fwrite(full_message.data(), full_message.size(), 1, stderr);
-    std::fputc('\n', stderr);
-}
-
-// IsZeroInt::visit(arg) returns true iff arg is a zero integer.
-class IsZeroInt : public fmt::internal::ArgVisitor<IsZeroInt, bool> {
-public:
-    template <typename T>
-    bool visit_any_int(T value) {
-        return value == 0;
-    }
-};
-
-// Checks if an argument is a valid printf width specifier and sets
-// left alignment if it is negative.
-class WidthHandler : public fmt::internal::ArgVisitor<WidthHandler, unsigned> {
-private:
-    fmt::FormatSpec &spec_;
-
-    FMT_DISALLOW_COPY_AND_ASSIGN(WidthHandler);
-
-public:
-    explicit WidthHandler(fmt::FormatSpec &spec) : spec_(spec) {}
-
-    void report_unhandled_arg() {
-        FMT_THROW(fmt::FormatError("width is not integer"));
-    }
-
-    template <typename T>
-    unsigned visit_any_int(T value) {
-        typedef typename fmt::internal::IntTraits<T>::MainType UnsignedType;
-        UnsignedType width = value;
-        if (fmt::internal::is_negative(value)) {
-            spec_.align_ = fmt::ALIGN_LEFT;
-            width = 0 - width;
-        }
-        if (width > INT_MAX)
-            FMT_THROW(fmt::FormatError("number is too big"));
-        return static_cast<unsigned>(width);
-    }
-};
-
-class PrecisionHandler :
-    public fmt::internal::ArgVisitor<PrecisionHandler, int> {
-public:
-    void report_unhandled_arg() {
-        FMT_THROW(fmt::FormatError("precision is not integer"));
-    }
-
-    template <typename T>
-    int visit_any_int(T value) {
-        if (!IntChecker<std::numeric_limits<T>::is_signed>::fits_in_int(value))
-            FMT_THROW(fmt::FormatError("number is too big"));
-        return static_cast<int>(value);
-    }
-};
-
-// Converts an integer argument to an integral type T for printf.
-template <typename T>
-class ArgConverter : public fmt::internal::ArgVisitor<ArgConverter<T>, void> {
-private:
-    fmt::internal::Arg &arg_;
-    wchar_t type_;
-
-    FMT_DISALLOW_COPY_AND_ASSIGN(ArgConverter);
-
-public:
-    ArgConverter(fmt::internal::Arg &arg, wchar_t type)
-        : arg_(arg), type_(type) {}
-
-    void visit_bool(bool value) {
-        if (type_ != 's')
-            visit_any_int(value);
-    }
-
-    template <typename U>
-    void visit_any_int(U value) {
-        bool is_signed = type_ == 'd' || type_ == 'i';
-        using fmt::internal::Arg;
-        if (sizeof(T) <= sizeof(int)) {
-            // Extra casts are used to silence warnings.
-            if (is_signed) {
-                arg_.type = Arg::INT;
-                arg_.int_value = static_cast<int>(static_cast<T>(value));
-            }
-            else {
-                arg_.type = Arg::UINT;
-                arg_.uint_value = static_cast<unsigned>(
-                                      static_cast<typename fmt::internal::MakeUnsigned<T>::Type>(value));
-            }
-        }
-        else {
-            if (is_signed) {
-                arg_.type = Arg::LONG_LONG;
-                arg_.long_long_value =
-                    static_cast<typename fmt::internal::MakeUnsigned<U>::Type>(value);
-            }
-            else {
-                arg_.type = Arg::ULONG_LONG;
-                arg_.ulong_long_value =
-                    static_cast<typename fmt::internal::MakeUnsigned<U>::Type>(value);
-            }
-        }
-    }
-};
-
-// Converts an integer argument to char for printf.
-class CharConverter : public fmt::internal::ArgVisitor<CharConverter, void> {
-private:
-    fmt::internal::Arg &arg_;
-
-    FMT_DISALLOW_COPY_AND_ASSIGN(CharConverter);
-
-public:
-    explicit CharConverter(fmt::internal::Arg &arg) : arg_(arg) {}
-
-    template <typename T>
-    void visit_any_int(T value) {
-        arg_.type = Arg::CHAR;
-        arg_.int_value = static_cast<char>(value);
-    }
-};
-}  // namespace
-
-namespace internal {
-
-template <typename Char>
-class PrintfArgFormatter :
-    public ArgFormatterBase<PrintfArgFormatter<Char>, Char> {
-
-    void write_null_pointer() {
-        this->spec().type_ = 0;
-        this->write("(nil)");
-    }
-
-    typedef ArgFormatterBase<PrintfArgFormatter<Char>, Char> Base;
-
-public:
-    PrintfArgFormatter(BasicWriter<Char> &w, FormatSpec &s)
-        : ArgFormatterBase<PrintfArgFormatter<Char>, Char>(w, s) {}
-
-    void visit_bool(bool value) {
-        FormatSpec &fmt_spec = this->spec();
-        if (fmt_spec.type_ != 's')
-            return this->visit_any_int(value);
-        fmt_spec.type_ = 0;
-        this->write(value);
-    }
-
-    void visit_char(int value) {
-        const FormatSpec &fmt_spec = this->spec();
-        BasicWriter<Char> &w = this->writer();
-        if (fmt_spec.type_ && fmt_spec.type_ != 'c')
-            w.write_int(value, fmt_spec);
-        typedef typename BasicWriter<Char>::CharPtr CharPtr;
-        CharPtr out = CharPtr();
-        if (fmt_spec.width_ > 1) {
-            Char fill = ' ';
-            out = w.grow_buffer(fmt_spec.width_);
-            if (fmt_spec.align_ != ALIGN_LEFT) {
-                std::fill_n(out, fmt_spec.width_ - 1, fill);
-                out += fmt_spec.width_ - 1;
-            }
-            else {
-                std::fill_n(out + 1, fmt_spec.width_ - 1, fill);
-            }
-        }
-        else {
-            out = w.grow_buffer(1);
-        }
-        *out = static_cast<Char>(value);
-    }
-
-    void visit_cstring(const char *value) {
-        if (value)
-            Base::visit_cstring(value);
-        else if (this->spec().type_ == 'p')
-            write_null_pointer();
-        else
-            this->write("(null)");
-    }
-
-    void visit_pointer(const void *value) {
-        if (value)
-            return Base::visit_pointer(value);
-        this->spec().type_ = 0;
-        write_null_pointer();
-    }
-
-    void visit_custom(Arg::CustomValue c) {
-        BasicFormatter<Char> formatter(ArgList(), this->writer());
-        const Char format_str[] = { '}', 0 };
-        const Char *format = format_str;
-        c.format(&formatter, c.value, &format);
-    }
-};
-}  // namespace internal
-}  // namespace fmt
-
-FMT_FUNC void fmt::SystemError::init(
-    int err_code, CStringRef format_str, ArgList args) {
-    error_code_ = err_code;
-    MemoryWriter w;
-    internal::format_system_error(w, err_code, format(format_str, args));
-    std::runtime_error &base = *this;
-    base = std::runtime_error(w.str());
-}
-
-template <typename T>
-int fmt::internal::CharTraits<char>::format_float(
-    char *buffer, std::size_t size, const char *format,
-    unsigned width, int precision, T value) {
-    if (width == 0) {
-        return precision < 0 ?
-               FMT_SNPRINTF(buffer, size, format, value) :
-               FMT_SNPRINTF(buffer, size, format, precision, value);
-    }
-    return precision < 0 ?
-           FMT_SNPRINTF(buffer, size, format, width, value) :
-           FMT_SNPRINTF(buffer, size, format, width, precision, value);
-}
-
-template <typename T>
-int fmt::internal::CharTraits<wchar_t>::format_float(
-    wchar_t *buffer, std::size_t size, const wchar_t *format,
-    unsigned width, int precision, T value) {
-    if (width == 0) {
-        return precision < 0 ?
-               FMT_SWPRINTF(buffer, size, format, value) :
-               FMT_SWPRINTF(buffer, size, format, precision, value);
-    }
-    return precision < 0 ?
-           FMT_SWPRINTF(buffer, size, format, width, value) :
-           FMT_SWPRINTF(buffer, size, format, width, precision, value);
-}
-
-template <typename T>
-const char fmt::internal::BasicData<T>::DIGITS[] =
-    "0001020304050607080910111213141516171819"
-    "2021222324252627282930313233343536373839"
-    "4041424344454647484950515253545556575859"
-    "6061626364656667686970717273747576777879"
-    "8081828384858687888990919293949596979899";
-
-#define FMT_POWERS_OF_10(factor) \
-  factor * 10, \
-  factor * 100, \
-  factor * 1000, \
-  factor * 10000, \
-  factor * 100000, \
-  factor * 1000000, \
-  factor * 10000000, \
-  factor * 100000000, \
-  factor * 1000000000
-
-template <typename T>
-const uint32_t fmt::internal::BasicData<T>::POWERS_OF_10_32[] = {
-    0, FMT_POWERS_OF_10(1)
-};
-
-template <typename T>
-const uint64_t fmt::internal::BasicData<T>::POWERS_OF_10_64[] = {
-    0,
-    FMT_POWERS_OF_10(1),
-    FMT_POWERS_OF_10(fmt::ULongLong(1000000000)),
-    // Multiply several constants instead of using a single long long constant
-    // to avoid warnings about C++98 not supporting long long.
-    fmt::ULongLong(1000000000) * fmt::ULongLong(1000000000) * 10
-};
-
-FMT_FUNC void fmt::internal::report_unknown_type(char code, const char *type) {
-    (void)type;
-    if (std::isprint(static_cast<unsigned char>(code))) {
-        FMT_THROW(fmt::FormatError(
-                      fmt::format("unknown format code '{}' for {}", code, type)));
-    }
-    FMT_THROW(fmt::FormatError(
-                  fmt::format("unknown format code '\\x{:02x}' for {}",
-                              static_cast<unsigned>(code), type)));
-}
-
-#if FMT_USE_WINDOWS_H
-
-FMT_FUNC fmt::internal::UTF8ToUTF16::UTF8ToUTF16(fmt::StringRef s) {
-    static const char ERROR_MSG[] = "cannot convert string from UTF-8 to UTF-16";
-    if (s.size() > INT_MAX)
-        FMT_THROW(WindowsError(ERROR_INVALID_PARAMETER, ERROR_MSG));
-    int s_size = static_cast<int>(s.size());
-    int length = MultiByteToWideChar(
-                     CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, 0, 0);
-    if (length == 0)
-        FMT_THROW(WindowsError(GetLastError(), ERROR_MSG));
-    buffer_.resize(length + 1);
-    length = MultiByteToWideChar(
-                 CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, &buffer_[0], length);
-    if (length == 0)
-        FMT_THROW(WindowsError(GetLastError(), ERROR_MSG));
-    buffer_[length] = 0;
-}
-
-FMT_FUNC fmt::internal::UTF16ToUTF8::UTF16ToUTF8(fmt::WStringRef s) {
-    if (int error_code = convert(s)) {
-        FMT_THROW(WindowsError(error_code,
-                               "cannot convert string from UTF-16 to UTF-8"));
-    }
-}
-
-FMT_FUNC int fmt::internal::UTF16ToUTF8::convert(fmt::WStringRef s) {
-    if (s.size() > INT_MAX)
-        return ERROR_INVALID_PARAMETER;
-    int s_size = static_cast<int>(s.size());
-    int length = WideCharToMultiByte(CP_UTF8, 0, s.data(), s_size, 0, 0, 0, 0);
-    if (length == 0)
-        return GetLastError();
-    buffer_.resize(length + 1);
-    length = WideCharToMultiByte(
-                 CP_UTF8, 0, s.data(), s_size, &buffer_[0], length, 0, 0);
-    if (length == 0)
-        return GetLastError();
-    buffer_[length] = 0;
-    return 0;
-}
-
-FMT_FUNC void fmt::WindowsError::init(
-    int err_code, CStringRef format_str, ArgList args) {
-    error_code_ = err_code;
-    MemoryWriter w;
-    internal::format_windows_error(w, err_code, format(format_str, args));
-    std::runtime_error &base = *this;
-    base = std::runtime_error(w.str());
-}
-
-FMT_FUNC void fmt::internal::format_windows_error(
-    fmt::Writer &out, int error_code,
-    fmt::StringRef message) FMT_NOEXCEPT{
-    class String {
-    private:
-        LPWSTR str_;
-
-    public:
-        String() : str_() {}
-        ~String() {
-            LocalFree(str_);
-        }
-        LPWSTR *ptr() {
-            return &str_;
-        }
-        LPCWSTR c_str() const { return str_; }
-    };
-    FMT_TRY{
-        String system_message;
-        if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
-        FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 0,
-        error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
-        reinterpret_cast<LPWSTR>(system_message.ptr()), 0, 0)) {
-            UTF16ToUTF8 utf8_message;
-            if (utf8_message.convert(system_message.c_str()) == ERROR_SUCCESS) {
-                out << message << ": " << utf8_message;
-                return;
-            }
-        }
-    } FMT_CATCH(...) {}
-    fmt::format_error_code(out, error_code, message);  // 'fmt::' is for bcc32.
-}
-
-#endif  // FMT_USE_WINDOWS_H
-
-FMT_FUNC void fmt::internal::format_system_error(
-    fmt::Writer &out, int error_code,
-    fmt::StringRef message) FMT_NOEXCEPT{
-    FMT_TRY{
-        MemoryBuffer<char, INLINE_BUFFER_SIZE> buffer;
-        buffer.resize(INLINE_BUFFER_SIZE);
-        for (;;) {
-            char *system_message = &buffer[0];
-            int result = safe_strerror(error_code, system_message, buffer.size());
-            if (result == 0) {
-                out << message << ": " << system_message;
-                return;
-            }
-            if (result != ERANGE)
-                break;  // Can't get error message, report error code instead.
-            buffer.resize(buffer.size() * 2);
-        }
-    } FMT_CATCH(...) {}
-    fmt::format_error_code(out, error_code, message);  // 'fmt::' is for bcc32.
-}
-
-template <typename Char>
-void fmt::internal::ArgMap<Char>::init(const ArgList &args) {
-    if (!map_.empty())
-        return;
-    typedef internal::NamedArg<Char> NamedArg;
-    const NamedArg *named_arg = 0;
-    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_.insert(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_.insert(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_.insert(Pair(named_arg->name, *named_arg));
-            break;
-        default:
-            /*nothing*/
-            ;
-        }
-    }
-}
-
-template <typename Char>
-void fmt::internal::FixedBuffer<Char>::grow(std::size_t) {
-    FMT_THROW(std::runtime_error("buffer overflow"));
-}
-
-FMT_FUNC Arg fmt::internal::FormatterBase::do_get_arg(
-    unsigned arg_index, const char *&error) {
-    Arg arg = args_[arg_index];
-    switch (arg.type) {
-    case Arg::NONE:
-        error = "argument index out of range";
-        break;
-    case Arg::NAMED_ARG:
-        arg = *static_cast<const internal::Arg*>(arg.pointer);
-    default:
-        /*nothing*/
-        ;
-    }
-    return arg;
-}
-
-template <typename Char>
-void fmt::internal::PrintfFormatter<Char>::parse_flags(
-    FormatSpec &spec, const Char *&s) {
-    for (;;) {
-        switch (*s++) {
-        case '-':
-            spec.align_ = ALIGN_LEFT;
-            break;
-        case '+':
-            spec.flags_ |= SIGN_FLAG | PLUS_FLAG;
-            break;
-        case '0':
-            spec.fill_ = '0';
-            break;
-        case ' ':
-            spec.flags_ |= SIGN_FLAG;
-            break;
-        case '#':
-            spec.flags_ |= HASH_FLAG;
-            break;
-        default:
-            --s;
-            return;
-        }
-    }
-}
-
-template <typename Char>
-Arg fmt::internal::PrintfFormatter<Char>::get_arg(
-    const Char *s, unsigned arg_index) {
-    (void)s;
-    const char *error = 0;
-    Arg arg = arg_index == UINT_MAX ?
-              next_arg(error) : FormatterBase::get_arg(arg_index - 1, error);
-    if (error)
-        FMT_THROW(FormatError(!*s ? "invalid format string" : error));
-    return arg;
-}
-
-template <typename Char>
-unsigned fmt::internal::PrintfFormatter<Char>::parse_header(
-    const Char *&s, FormatSpec &spec) {
-    unsigned arg_index = UINT_MAX;
-    Char c = *s;
-    if (c >= '0' && c <= '9') {
-        // Parse an argument index (if followed by '$') or a width possibly
-        // preceded with '0' flag(s).
-        unsigned value = parse_nonnegative_int(s);
-        if (*s == '$') {  // value is an argument index
-            ++s;
-            arg_index = value;
-        }
-        else {
-            if (c == '0')
-                spec.fill_ = '0';
-            if (value != 0) {
-                // Nonzero value means that we parsed width and don't need to
-                // parse it or flags again, so return now.
-                spec.width_ = value;
-                return arg_index;
-            }
-        }
-    }
-    parse_flags(spec, s);
-    // Parse width.
-    if (*s >= '0' && *s <= '9') {
-        spec.width_ = parse_nonnegative_int(s);
-    }
-    else if (*s == '*') {
-        ++s;
-        spec.width_ = WidthHandler(spec).visit(get_arg(s));
-    }
-    return arg_index;
-}
-
-template <typename Char>
-void fmt::internal::PrintfFormatter<Char>::format(
-    BasicWriter<Char> &writer, BasicCStringRef<Char> format_str) {
-    const Char *start = format_str.c_str();
-    const Char *s = start;
-    while (*s) {
-        Char c = *s++;
-        if (c != '%') continue;
-        if (*s == c) {
-            write(writer, start, s);
-            start = ++s;
-            continue;
-        }
-        write(writer, start, s - 1);
-
-        FormatSpec spec;
-        spec.align_ = ALIGN_RIGHT;
-
-        // Parse argument index, flags and width.
-        unsigned arg_index = parse_header(s, spec);
-
-        // Parse precision.
-        if (*s == '.') {
-            ++s;
-            if ('0' <= *s && *s <= '9') {
-                spec.precision_ = parse_nonnegative_int(s);
-            }
-            else if (*s == '*') {
-                ++s;
-                spec.precision_ = PrecisionHandler().visit(get_arg(s));
-            }
-        }
-
-        Arg arg = get_arg(s, arg_index);
-        if (spec.flag(HASH_FLAG) && IsZeroInt().visit(arg))
-            spec.flags_ &= ~HASH_FLAG;
-        if (spec.fill_ == '0') {
-            if (arg.type <= Arg::LAST_NUMERIC_TYPE)
-                spec.align_ = ALIGN_NUMERIC;
-            else
-                spec.fill_ = ' ';  // Ignore '0' flag for non-numeric types.
-        }
-
-        // Parse length and convert the argument to the required type.
-        switch (*s++) {
-        case 'h':
-            if (*s == 'h')
-                ArgConverter<signed char>(arg, *++s).visit(arg);
-            else
-                ArgConverter<short>(arg, *s).visit(arg);
-            break;
-        case 'l':
-            if (*s == 'l')
-                ArgConverter<fmt::LongLong>(arg, *++s).visit(arg);
-            else
-                ArgConverter<long>(arg, *s).visit(arg);
-            break;
-        case 'j':
-            ArgConverter<intmax_t>(arg, *s).visit(arg);
-            break;
-        case 'z':
-            ArgConverter<std::size_t>(arg, *s).visit(arg);
-            break;
-        case 't':
-            ArgConverter<std::ptrdiff_t>(arg, *s).visit(arg);
-            break;
-        case 'L':
-            // printf produces garbage when 'L' is omitted for long double, no
-            // need to do the same.
-            break;
-        default:
-            --s;
-            ArgConverter<int>(arg, *s).visit(arg);
-        }
-
-        // Parse type.
-        if (!*s)
-            FMT_THROW(FormatError("invalid format string"));
-        spec.type_ = static_cast<char>(*s++);
-        if (arg.type <= Arg::LAST_INTEGER_TYPE) {
-            // Normalize type.
-            switch (spec.type_) {
-            case 'i':
-            case 'u':
-                spec.type_ = 'd';
-                break;
-            case 'c':
-                // TODO: handle wchar_t
-                CharConverter(arg).visit(arg);
-                break;
-            }
-        }
-
-        start = s;
-
-        // Format argument.
-        internal::PrintfArgFormatter<Char>(writer, spec).visit(arg);
-    }
-    write(writer, start, s);
-}
-
-FMT_FUNC void fmt::report_system_error(
-    int error_code, fmt::StringRef message) FMT_NOEXCEPT{
-    // 'fmt::' is for bcc32.
-    fmt::report_error(internal::format_system_error, error_code, message);
-}
-
-#if FMT_USE_WINDOWS_H
-FMT_FUNC void fmt::report_windows_error(
-    int error_code, fmt::StringRef message) FMT_NOEXCEPT{
-    // 'fmt::' is for bcc32.
-    fmt::report_error(internal::format_windows_error, error_code, message);
-}
-#endif
-
-FMT_FUNC void fmt::print(std::FILE *f, CStringRef format_str, ArgList args) {
-    MemoryWriter w;
-    w.write(format_str, args);
-    std::fwrite(w.data(), 1, w.size(), f);
-}
-
-FMT_FUNC void fmt::print(CStringRef format_str, ArgList args) {
-    print(stdout, format_str, args);
-}
-
-FMT_FUNC void fmt::print(std::ostream &os, CStringRef format_str, ArgList args) {
-    MemoryWriter w;
-    w.write(format_str, args);
-    os.write(w.data(), w.size());
-}
-
-FMT_FUNC void fmt::print_colored(Color c, CStringRef format, ArgList args) {
-    char escape[] = "\x1b[30m";
-    escape[3] = static_cast<char>('0' + c);
-    std::fputs(escape, stdout);
-    print(format, args);
-    std::fputs(RESET_COLOR, stdout);
-}
-
-FMT_FUNC int fmt::fprintf(std::FILE *f, CStringRef format, ArgList args) {
-    MemoryWriter w;
-    printf(w, format, args);
-    std::size_t size = w.size();
-    return std::fwrite(w.data(), 1, size, f) < size ? -1 : static_cast<int>(size);
-}
-
-#ifndef FMT_HEADER_ONLY
-
-template struct fmt::internal::BasicData<void>;
-
-// Explicit instantiations for char.
-
-template void fmt::internal::FixedBuffer<char>::grow(std::size_t);
-
-template void fmt::internal::ArgMap<char>::init(const fmt::ArgList &args);
-
-template void fmt::internal::PrintfFormatter<char>::format(
-    BasicWriter<char> &writer, CStringRef format);
-
-template int fmt::internal::CharTraits<char>::format_float(
-    char *buffer, std::size_t size, const char *format,
-    unsigned width, int precision, double value);
-
-template int fmt::internal::CharTraits<char>::format_float(
-    char *buffer, std::size_t size, const char *format,
-    unsigned width, int precision, long double value);
-
-// Explicit instantiations for wchar_t.
-
-template void fmt::internal::FixedBuffer<wchar_t>::grow(std::size_t);
-
-template void fmt::internal::ArgMap<wchar_t>::init(const fmt::ArgList &args);
-
-template void fmt::internal::PrintfFormatter<wchar_t>::format(
-    BasicWriter<wchar_t> &writer, WCStringRef format);
-
-template int fmt::internal::CharTraits<wchar_t>::format_float(
-    wchar_t *buffer, std::size_t size, const wchar_t *format,
-    unsigned width, int precision, double value);
-
-template int fmt::internal::CharTraits<wchar_t>::format_float(
-    wchar_t *buffer, std::size_t size, const wchar_t *format,
-    unsigned width, int precision, long double value);
-
-#endif  // FMT_HEADER_ONLY
-
-#ifdef _MSC_VER
-# pragma warning(pop)
+/*
+Formatting library for C++
+
+Copyright (c) 2012 - 2015, Victor Zverovich
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "format.h"
+
+#include <string.h>
+
+#include <cctype>
+#include <cerrno>
+#include <climits>
+#include <cmath>
+#include <cstdarg>
+#include <cstddef>  // for std::ptrdiff_t
+
+#if defined(_WIN32) && defined(__MINGW32__)
+# include <cstring>
+#endif
+
+#if FMT_USE_WINDOWS_H
+# if defined(NOMINMAX) || defined(FMT_WIN_MINMAX)
+#  include <windows.h>
+# else
+#  define NOMINMAX
+#  include <windows.h>
+#  undef NOMINMAX
+# endif
+#endif
+
+using fmt::internal::Arg;
+
+#if FMT_EXCEPTIONS
+# define FMT_TRY try
+# define FMT_CATCH(x) catch (x)
+#else
+# define FMT_TRY if (true)
+# define FMT_CATCH(x) if (false)
+#endif
+
+#ifdef FMT_HEADER_ONLY
+# define FMT_FUNC inline
+#else
+# define FMT_FUNC
+#endif
+
+#ifdef _MSC_VER
+# pragma warning(push)
+# pragma warning(disable: 4127)  // conditional expression is constant
+# pragma warning(disable: 4702)  // unreachable code
+// Disable deprecation warning for strerror. The latter is not called but
+// MSVC fails to detect it.
+# pragma warning(disable: 4996)
+#endif
+
+// Dummy implementations of strerror_r and strerror_s called if corresponding
+// system functions are not available.
+static inline fmt::internal::Null<> strerror_r(int, char *, ...)
+{
+	return fmt::internal::Null<>();
+}
+static inline fmt::internal::Null<> strerror_s(char *, std::size_t, ...)
+{
+	return fmt::internal::Null<>();
+}
+
+namespace fmt {
+	namespace {
+
+#ifndef _MSC_VER
+# define FMT_SNPRINTF snprintf
+#else  // _MSC_VER
+		inline int fmt_snprintf(char *buffer, size_t size, const char *format, ...)
+		{
+			va_list args;
+			va_start(args, format);
+			int result = vsnprintf_s(buffer, size, _TRUNCATE, format, args);
+			va_end(args);
+			return result;
+		}
+# define FMT_SNPRINTF fmt_snprintf
+#endif  // _MSC_VER
+
+#if defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT)
+# define FMT_SWPRINTF snwprintf
+#else
+# define FMT_SWPRINTF swprintf
+#endif // defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT)
+
+		// Checks if a value fits in int - used to avoid warnings about comparing
+		// signed and unsigned integers.
+		template <bool IsSigned>
+		struct IntChecker
+		{
+			template <typename T>
+			static bool fits_in_int(T value)
+			{
+				unsigned max = INT_MAX;
+				return value <= max;
+			}
+			static bool fits_in_int(bool)
+			{
+				return true;
+			}
+		};
+
+		template <>
+		struct IntChecker<true>
+		{
+			template <typename T>
+			static bool fits_in_int(T value)
+			{
+				return value >= INT_MIN && value <= INT_MAX;
+			}
+			static bool fits_in_int(int)
+			{
+				return true;
+			}
+		};
+
+		const char RESET_COLOR[] = "\x1b[0m";
+
+		typedef void(*FormatFunc)(fmt::Writer &, int, fmt::StringRef);
+
+		// Portable thread-safe version of strerror.
+		// Sets buffer to point to a string describing the error code.
+		// This can be either a pointer to a string stored in buffer,
+		// or a pointer to some static immutable string.
+		// Returns one of the following values:
+		//   0      - success
+		//   ERANGE - buffer is not large enough to store the error message
+		//   other  - failure
+		// 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");
+
+			class StrError
+			{
+			private:
+				int error_code_;
+				char *&buffer_;
+				std::size_t buffer_size_;
+
+				// A noop assignment operator to avoid bogus warnings.
+				void operator=(const StrError &)
+				{}
+
+				// Handle the result of XSI-compliant version of strerror_r.
+				int handle(int result)
+				{
+					// glibc versions before 2.13 return result in errno.
+					return result == -1 ? errno : result;
+				}
+
+				// Handle the result of GNU-specific version of strerror_r.
+				int handle(char *message)
+				{
+					// If the buffer is full then the message is probably truncated.
+					if (message == buffer_ && strlen(buffer_) == buffer_size_ - 1)
+						return ERANGE;
+					buffer_ = message;
+					return 0;
+				}
+
+				// Handle the case when strerror_r is not available.
+				int handle(fmt::internal::Null<>)
+				{
+					return fallback(strerror_s(buffer_, buffer_size_, error_code_));
+				}
+
+				// Fallback to strerror_s when strerror_r is not available.
+				int fallback(int result)
+				{
+					// If the buffer is full then the message is probably truncated.
+					return result == 0 && strlen(buffer_) == buffer_size_ - 1 ?
+						ERANGE : result;
+				}
+
+				// Fallback to strerror if strerror_r and strerror_s are not available.
+				int fallback(fmt::internal::Null<>)
+				{
+					errno = 0;
+					buffer_ = strerror(error_code_);
+					return errno;
+				}
+
+			public:
+				StrError(int err_code, char *&buf, std::size_t buf_size)
+					: error_code_(err_code), buffer_(buf), buffer_size_(buf_size)
+				{}
+
+				int run()
+				{
+					strerror_r(0, 0, "");  // Suppress a warning about unused strerror_r.
+					return handle(strerror_r(error_code_, buffer_, buffer_size_));
+				}
+			};
+			return StrError(error_code, buffer, buffer_size).run();
+		}
+
+		void format_error_code(fmt::Writer &out, int error_code,
+			fmt::StringRef message) FMT_NOEXCEPT
+		{
+			// Report error code making sure that the output fits into
+			// INLINE_BUFFER_SIZE to avoid dynamic memory allocation and potential
+			// bad_alloc.
+			out.clear();
+			static const char SEP[] = ": ";
+			static const char ERROR_STR[] = "error ";
+			// Subtract 2 to account for terminating null characters in SEP and ERROR_STR.
+			std::size_t error_code_size = sizeof(SEP) + sizeof(ERROR_STR) - 2;
+			typedef fmt::internal::IntTraits<int>::MainType MainType;
+			MainType abs_value = static_cast<MainType>(error_code);
+			if (internal::is_negative(error_code)) {
+				abs_value = 0 - abs_value;
+				++error_code_size;
+			}
+			error_code_size += fmt::internal::count_digits(abs_value);
+			if (message.size() <= fmt::internal::INLINE_BUFFER_SIZE - error_code_size)
+				out << message << SEP;
+			out << ERROR_STR << error_code;
+			assert(out.size() <= fmt::internal::INLINE_BUFFER_SIZE);
+		}
+
+		void report_error(FormatFunc func,
+			int error_code, fmt::StringRef message) FMT_NOEXCEPT
+		{
+			fmt::MemoryWriter full_message;
+			func(full_message, error_code, message);
+			// Use Writer::data instead of Writer::c_str to avoid potential memory
+			// allocation.
+			std::fwrite(full_message.data(), full_message.size(), 1, stderr);
+			std::fputc('\n', stderr);
+		}
+
+		// IsZeroInt::visit(arg) returns true iff arg is a zero integer.
+		class IsZeroInt: public fmt::internal::ArgVisitor<IsZeroInt, bool>
+		{
+		public:
+			template <typename T>
+			bool visit_any_int(T value)
+			{
+				return value == 0;
+			}
+		};
+
+		// Checks if an argument is a valid printf width specifier and sets
+		// left alignment if it is negative.
+		class WidthHandler: public fmt::internal::ArgVisitor<WidthHandler, unsigned>
+		{
+		private:
+			fmt::FormatSpec &spec_;
+
+			FMT_DISALLOW_COPY_AND_ASSIGN(WidthHandler);
+
+		public:
+			explicit WidthHandler(fmt::FormatSpec &spec): spec_(spec)
+			{}
+
+			void report_unhandled_arg()
+			{
+				FMT_THROW(fmt::FormatError("width is not integer"));
+			}
+
+			template <typename T>
+			unsigned visit_any_int(T value)
+			{
+				typedef typename fmt::internal::IntTraits<T>::MainType UnsignedType;
+				UnsignedType width = static_cast<UnsignedType>(value);
+				if (fmt::internal::is_negative(value)) {
+					spec_.align_ = fmt::ALIGN_LEFT;
+					width = 0 - width;
+				}
+				if (width > INT_MAX)
+					FMT_THROW(fmt::FormatError("number is too big"));
+				return static_cast<unsigned>(width);
+			}
+		};
+
+		class PrecisionHandler:
+			public fmt::internal::ArgVisitor<PrecisionHandler, int>
+		{
+		public:
+			void report_unhandled_arg()
+			{
+				FMT_THROW(fmt::FormatError("precision is not integer"));
+			}
+
+			template <typename T>
+			int visit_any_int(T value)
+			{
+				if (!IntChecker<std::numeric_limits<T>::is_signed>::fits_in_int(value))
+					FMT_THROW(fmt::FormatError("number is too big"));
+				return static_cast<int>(value);
+			}
+		};
+
+		template <typename T, typename U>
+		struct is_same
+		{
+			enum
+			{
+				value = 0
+			};
+		};
+
+		template <typename T>
+		struct is_same<T, T>
+		{
+			enum
+			{
+				value = 1
+			};
+		};
+
+		// An argument visitor that converts an integer argument to T for printf,
+		// if T is an integral type. If T is void, the argument is converted to
+		// corresponding signed or unsigned type depending on the type specifier:
+		// 'd' and 'i' - signed, other - unsigned)
+		template <typename T = void>
+		class ArgConverter: public fmt::internal::ArgVisitor<ArgConverter<T>, void>
+		{
+		private:
+			fmt::internal::Arg &arg_;
+			wchar_t type_;
+
+			FMT_DISALLOW_COPY_AND_ASSIGN(ArgConverter);
+
+		public:
+			ArgConverter(fmt::internal::Arg &arg, wchar_t type)
+				: arg_(arg), type_(type)
+			{}
+
+			void visit_bool(bool value)
+			{
+				if (type_ != 's')
+					visit_any_int(value);
+			}
+
+			template <typename U>
+			void visit_any_int(U value)
+			{
+				bool is_signed = type_ == 'd' || type_ == 'i';
+				using fmt::internal::Arg;
+				typedef typename fmt::internal::Conditional<
+					is_same<T, void>::value, U, T>::type TargetType;
+				if (sizeof(TargetType) <= sizeof(int)) {
+					// Extra casts are used to silence warnings.
+					if (is_signed) {
+						arg_.type = Arg::INT;
+						arg_.int_value = static_cast<int>(static_cast<TargetType>(value));
+					}
+					else {
+						arg_.type = Arg::UINT;
+						typedef typename fmt::internal::MakeUnsigned<TargetType>::Type Unsigned;
+						arg_.uint_value = static_cast<unsigned>(static_cast<Unsigned>(value));
+					}
+				}
+				else {
+					if (is_signed) {
+						arg_.type = Arg::LONG_LONG;
+						// glibc's printf doesn't sign extend arguments of smaller types:
+						//   std::printf("%lld", -42);  // prints "4294967254"
+						// but we don't have to do the same because it's a UB.
+						arg_.long_long_value = static_cast<fmt::LongLong>(value);
+					}
+					else {
+						arg_.type = Arg::ULONG_LONG;
+						arg_.ulong_long_value =
+							static_cast<typename fmt::internal::MakeUnsigned<U>::Type>(value);
+					}
+				}
+			}
+		};
+
+		// Converts an integer argument to char for printf.
+		class CharConverter: public fmt::internal::ArgVisitor<CharConverter, void>
+		{
+		private:
+			fmt::internal::Arg &arg_;
+
+			FMT_DISALLOW_COPY_AND_ASSIGN(CharConverter);
+
+		public:
+			explicit CharConverter(fmt::internal::Arg &arg): arg_(arg)
+			{}
+
+			template <typename T>
+			void visit_any_int(T value)
+			{
+				arg_.type = Arg::CHAR;
+				arg_.int_value = static_cast<char>(value);
+			}
+		};
+
+		// Write the content of w to os.
+		void write(std::ostream &os, fmt::Writer &w)
+		{
+			const char *data = w.data();
+			typedef internal::MakeUnsigned<std::streamsize>::Type UnsignedStreamSize;
+			UnsignedStreamSize size = w.size();
+			UnsignedStreamSize max_size =
+				internal::to_unsigned((std::numeric_limits<std::streamsize>::max)());
+			do {
+				UnsignedStreamSize n = size <= max_size ? size : max_size;
+				os.write(data, static_cast<std::streamsize>(n));
+				data += n;
+				size -= n;
+			} while (size != 0);
+		}
+	}  // namespace
+
+	namespace internal {
+
+		template <typename Char>
+		class PrintfArgFormatter:
+			public ArgFormatterBase<PrintfArgFormatter<Char>, Char>
+		{
+
+			void write_null_pointer()
+			{
+				this->spec().type_ = 0;
+				this->write("(nil)");
+			}
+
+			typedef ArgFormatterBase<PrintfArgFormatter<Char>, Char> Base;
+
+		public:
+			PrintfArgFormatter(BasicWriter<Char> &w, FormatSpec &s)
+				: ArgFormatterBase<PrintfArgFormatter<Char>, Char>(w, s)
+			{}
+
+			void visit_bool(bool value)
+			{
+				FormatSpec &fmt_spec = this->spec();
+				if (fmt_spec.type_ != 's')
+					return this->visit_any_int(value);
+				fmt_spec.type_ = 0;
+				this->write(value);
+			}
+
+			void visit_char(int value)
+			{
+				const FormatSpec &fmt_spec = this->spec();
+				BasicWriter<Char> &w = this->writer();
+				if (fmt_spec.type_ && fmt_spec.type_ != 'c')
+					w.write_int(value, fmt_spec);
+				typedef typename BasicWriter<Char>::CharPtr CharPtr;
+				CharPtr out = CharPtr();
+				if (fmt_spec.width_ > 1) {
+					Char fill = ' ';
+					out = w.grow_buffer(fmt_spec.width_);
+					if (fmt_spec.align_ != ALIGN_LEFT) {
+						std::fill_n(out, fmt_spec.width_ - 1, fill);
+						out += fmt_spec.width_ - 1;
+					}
+					else {
+						std::fill_n(out + 1, fmt_spec.width_ - 1, fill);
+					}
+				}
+				else {
+					out = w.grow_buffer(1);
+				}
+				*out = static_cast<Char>(value);
+			}
+
+			void visit_cstring(const char *value)
+			{
+				if (value)
+					Base::visit_cstring(value);
+				else if (this->spec().type_ == 'p')
+					write_null_pointer();
+				else
+					this->write("(null)");
+			}
+
+			void visit_pointer(const void *value)
+			{
+				if (value)
+					return Base::visit_pointer(value);
+				this->spec().type_ = 0;
+				write_null_pointer();
+			}
+
+			void visit_custom(Arg::CustomValue c)
+			{
+				BasicFormatter<Char> formatter(ArgList(), this->writer());
+				const Char format_str[] = { '}', 0 };
+				const Char *format = format_str;
+				c.format(&formatter, c.value, &format);
+			}
+		};
+	}  // namespace internal
+}  // namespace fmt
+
+FMT_FUNC void fmt::SystemError::init(
+	int err_code, CStringRef format_str, ArgList args)
+{
+	error_code_ = err_code;
+	MemoryWriter w;
+	internal::format_system_error(w, err_code, format(format_str, args));
+	std::runtime_error &base = *this;
+	base = std::runtime_error(w.str());
+}
+
+template <typename T>
+int fmt::internal::CharTraits<char>::format_float(
+	char *buffer, std::size_t size, const char *format,
+	unsigned width, int precision, T value)
+{
+	if (width == 0) {
+		return precision < 0 ?
+			FMT_SNPRINTF(buffer, size, format, value) :
+			FMT_SNPRINTF(buffer, size, format, precision, value);
+	}
+	return precision < 0 ?
+		FMT_SNPRINTF(buffer, size, format, width, value) :
+		FMT_SNPRINTF(buffer, size, format, width, precision, value);
+}
+
+template <typename T>
+int fmt::internal::CharTraits<wchar_t>::format_float(
+	wchar_t *buffer, std::size_t size, const wchar_t *format,
+	unsigned width, int precision, T value)
+{
+	if (width == 0) {
+		return precision < 0 ?
+			FMT_SWPRINTF(buffer, size, format, value) :
+			FMT_SWPRINTF(buffer, size, format, precision, value);
+	}
+	return precision < 0 ?
+		FMT_SWPRINTF(buffer, size, format, width, value) :
+		FMT_SWPRINTF(buffer, size, format, width, precision, value);
+}
+
+template <typename T>
+const char fmt::internal::BasicData<T>::DIGITS[] =
+"0001020304050607080910111213141516171819"
+"2021222324252627282930313233343536373839"
+"4041424344454647484950515253545556575859"
+"6061626364656667686970717273747576777879"
+"8081828384858687888990919293949596979899";
+
+#define FMT_POWERS_OF_10(factor) \
+  factor * 10, \
+  factor * 100, \
+  factor * 1000, \
+  factor * 10000, \
+  factor * 100000, \
+  factor * 1000000, \
+  factor * 10000000, \
+  factor * 100000000, \
+  factor * 1000000000
+
+template <typename T>
+const uint32_t fmt::internal::BasicData<T>::POWERS_OF_10_32[] = {
+	0, FMT_POWERS_OF_10(1)
+};
+
+template <typename T>
+const uint64_t fmt::internal::BasicData<T>::POWERS_OF_10_64[] = {
+	0,
+	FMT_POWERS_OF_10(1),
+	FMT_POWERS_OF_10(fmt::ULongLong(1000000000)),
+	// Multiply several constants instead of using a single long long constant
+	// to avoid warnings about C++98 not supporting long long.
+	fmt::ULongLong(1000000000) * fmt::ULongLong(1000000000) * 10
+};
+
+FMT_FUNC void fmt::internal::report_unknown_type(char code, const char *type)
+{
+	(void)type;
+	if (std::isprint(static_cast<unsigned char>(code))) {
+		FMT_THROW(fmt::FormatError(
+			fmt::format("unknown format code '{}' for {}", code, type)));
+	}
+	FMT_THROW(fmt::FormatError(
+		fmt::format("unknown format code '\\x{:02x}' for {}",
+			static_cast<unsigned>(code), type)));
+}
+
+#if FMT_USE_WINDOWS_H
+
+FMT_FUNC fmt::internal::UTF8ToUTF16::UTF8ToUTF16(fmt::StringRef s)
+{
+	static const char ERROR_MSG[] = "cannot convert string from UTF-8 to UTF-16";
+	if (s.size() > INT_MAX)
+		FMT_THROW(WindowsError(ERROR_INVALID_PARAMETER, ERROR_MSG));
+	int s_size = static_cast<int>(s.size());
+	int length = MultiByteToWideChar(
+		CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, 0, 0);
+	if (length == 0)
+		FMT_THROW(WindowsError(GetLastError(), ERROR_MSG));
+	buffer_.resize(length + 1);
+	length = MultiByteToWideChar(
+		CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, &buffer_[0], length);
+	if (length == 0)
+		FMT_THROW(WindowsError(GetLastError(), ERROR_MSG));
+	buffer_[length] = 0;
+}
+
+FMT_FUNC fmt::internal::UTF16ToUTF8::UTF16ToUTF8(fmt::WStringRef s)
+{
+	if (int error_code = convert(s)) {
+		FMT_THROW(WindowsError(error_code,
+			"cannot convert string from UTF-16 to UTF-8"));
+	}
+}
+
+FMT_FUNC int fmt::internal::UTF16ToUTF8::convert(fmt::WStringRef s)
+{
+	if (s.size() > INT_MAX)
+		return ERROR_INVALID_PARAMETER;
+	int s_size = static_cast<int>(s.size());
+	int length = WideCharToMultiByte(CP_UTF8, 0, s.data(), s_size, 0, 0, 0, 0);
+	if (length == 0)
+		return GetLastError();
+	buffer_.resize(length + 1);
+	length = WideCharToMultiByte(
+		CP_UTF8, 0, s.data(), s_size, &buffer_[0], length, 0, 0);
+	if (length == 0)
+		return GetLastError();
+	buffer_[length] = 0;
+	return 0;
+}
+
+FMT_FUNC void fmt::WindowsError::init(
+	int err_code, CStringRef format_str, ArgList args)
+{
+	error_code_ = err_code;
+	MemoryWriter w;
+	internal::format_windows_error(w, err_code, format(format_str, args));
+	std::runtime_error &base = *this;
+	base = std::runtime_error(w.str());
+}
+
+FMT_FUNC void fmt::internal::format_windows_error(
+	fmt::Writer &out, int error_code,
+	fmt::StringRef message) FMT_NOEXCEPT
+{
+	FMT_TRY{
+		MemoryBuffer<wchar_t, INLINE_BUFFER_SIZE> buffer;
+	buffer.resize(INLINE_BUFFER_SIZE);
+	for (;;) {
+		wchar_t *system_message = &buffer[0];
+		int result = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
+			0, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+			system_message, static_cast<uint32_t>(buffer.size()), 0);
+		if (result != 0) {
+			UTF16ToUTF8 utf8_message;
+			if (utf8_message.convert(system_message) == ERROR_SUCCESS) {
+				out << message << ": " << utf8_message;
+				return;
+			}
+			break;
+		}
+		if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
+			break;  // Can't get error message, report error code instead.
+		buffer.resize(buffer.size() * 2);
+	}
+	} FMT_CATCH(...)
+	{}
+	fmt::format_error_code(out, error_code, message);  // 'fmt::' is for bcc32.
+}
+
+#endif  // FMT_USE_WINDOWS_H
+
+FMT_FUNC void fmt::internal::format_system_error(
+	fmt::Writer &out, int error_code,
+	fmt::StringRef message) FMT_NOEXCEPT
+{
+	FMT_TRY{
+		MemoryBuffer<char, INLINE_BUFFER_SIZE> buffer;
+	buffer.resize(INLINE_BUFFER_SIZE);
+	for (;;) {
+		char *system_message = &buffer[0];
+		int result = safe_strerror(error_code, system_message, buffer.size());
+		if (result == 0) {
+			out << message << ": " << system_message;
+			return;
+		}
+		if (result != ERANGE)
+			break;  // Can't get error message, report error code instead.
+		buffer.resize(buffer.size() * 2);
+	}
+	} FMT_CATCH(...)
+	{}
+	fmt::format_error_code(out, error_code, message);  // 'fmt::' is for bcc32.
+}
+
+template <typename Char>
+void fmt::internal::ArgMap<Char>::init(const ArgList &args)
+{
+	if (!map_.empty())
+		return;
+	typedef internal::NamedArg<Char> NamedArg;
+	const NamedArg *named_arg = 0;
+	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 fmt::internal::FixedBuffer<Char>::grow(std::size_t)
+{
+	FMT_THROW(std::runtime_error("buffer overflow"));
+}
+
+FMT_FUNC Arg fmt::internal::FormatterBase::do_get_arg(
+	unsigned arg_index, const char *&error)
+{
+	Arg arg = args_[arg_index];
+	switch (arg.type) {
+	case Arg::NONE:
+		error = "argument index out of range";
+		break;
+	case Arg::NAMED_ARG:
+		arg = *static_cast<const internal::Arg*>(arg.pointer);
+		break;
+	default:
+		/*nothing*/;
+	}
+	return arg;
+}
+
+template <typename Char>
+void fmt::internal::PrintfFormatter<Char>::parse_flags(
+	FormatSpec &spec, const Char *&s)
+{
+	for (;;) {
+		switch (*s++) {
+		case '-':
+			spec.align_ = ALIGN_LEFT;
+			break;
+		case '+':
+			spec.flags_ |= SIGN_FLAG | PLUS_FLAG;
+			break;
+		case '0':
+			spec.fill_ = '0';
+			break;
+		case ' ':
+			spec.flags_ |= SIGN_FLAG;
+			break;
+		case '#':
+			spec.flags_ |= HASH_FLAG;
+			break;
+		default:
+			--s;
+			return;
+		}
+	}
+}
+
+template <typename Char>
+Arg fmt::internal::PrintfFormatter<Char>::get_arg(
+	const Char *s, unsigned arg_index)
+{
+	(void)s;
+	const char *error = 0;
+	Arg arg = arg_index == UINT_MAX ?
+		next_arg(error) : FormatterBase::get_arg(arg_index - 1, error);
+	if (error)
+		FMT_THROW(FormatError(!*s ? "invalid format string" : error));
+	return arg;
+}
+
+template <typename Char>
+unsigned fmt::internal::PrintfFormatter<Char>::parse_header(
+	const Char *&s, FormatSpec &spec)
+{
+	unsigned arg_index = UINT_MAX;
+	Char c = *s;
+	if (c >= '0' && c <= '9') {
+		// Parse an argument index (if followed by '$') or a width possibly
+		// preceded with '0' flag(s).
+		unsigned value = parse_nonnegative_int(s);
+		if (*s == '$') {  // value is an argument index
+			++s;
+			arg_index = value;
+		}
+		else {
+			if (c == '0')
+				spec.fill_ = '0';
+			if (value != 0) {
+				// Nonzero value means that we parsed width and don't need to
+				// parse it or flags again, so return now.
+				spec.width_ = value;
+				return arg_index;
+			}
+		}
+	}
+	parse_flags(spec, s);
+	// Parse width.
+	if (*s >= '0' && *s <= '9') {
+		spec.width_ = parse_nonnegative_int(s);
+	}
+	else if (*s == '*') {
+		++s;
+		spec.width_ = WidthHandler(spec).visit(get_arg(s));
+	}
+	return arg_index;
+}
+
+template <typename Char>
+void fmt::internal::PrintfFormatter<Char>::format(
+	BasicWriter<Char> &writer, BasicCStringRef<Char> format_str)
+{
+	const Char *start = format_str.c_str();
+	const Char *s = start;
+	while (*s) {
+		Char c = *s++;
+		if (c != '%') continue;
+		if (*s == c) {
+			write(writer, start, s);
+			start = ++s;
+			continue;
+		}
+		write(writer, start, s - 1);
+
+		FormatSpec spec;
+		spec.align_ = ALIGN_RIGHT;
+
+		// Parse argument index, flags and width.
+		unsigned arg_index = parse_header(s, spec);
+
+		// Parse precision.
+		if (*s == '.') {
+			++s;
+			if ('0' <= *s && *s <= '9') {
+				spec.precision_ = static_cast<int>(parse_nonnegative_int(s));
+			}
+			else if (*s == '*') {
+				++s;
+				spec.precision_ = PrecisionHandler().visit(get_arg(s));
+			}
+		}
+
+		Arg arg = get_arg(s, arg_index);
+		if (spec.flag(HASH_FLAG) && IsZeroInt().visit(arg))
+			spec.flags_ &= ~to_unsigned<int>(HASH_FLAG);
+		if (spec.fill_ == '0') {
+			if (arg.type <= Arg::LAST_NUMERIC_TYPE)
+				spec.align_ = ALIGN_NUMERIC;
+			else
+				spec.fill_ = ' ';  // Ignore '0' flag for non-numeric types.
+		}
+
+		// Parse length and convert the argument to the required type.
+		switch (*s++) {
+		case 'h':
+			if (*s == 'h')
+				ArgConverter<signed char>(arg, *++s).visit(arg);
+			else
+				ArgConverter<short>(arg, *s).visit(arg);
+			break;
+		case 'l':
+			if (*s == 'l')
+				ArgConverter<fmt::LongLong>(arg, *++s).visit(arg);
+			else
+				ArgConverter<long>(arg, *s).visit(arg);
+			break;
+		case 'j':
+			ArgConverter<intmax_t>(arg, *s).visit(arg);
+			break;
+		case 'z':
+			ArgConverter<std::size_t>(arg, *s).visit(arg);
+			break;
+		case 't':
+			ArgConverter<std::ptrdiff_t>(arg, *s).visit(arg);
+			break;
+		case 'L':
+			// printf produces garbage when 'L' is omitted for long double, no
+			// need to do the same.
+			break;
+		default:
+			--s;
+			ArgConverter<void>(arg, *s).visit(arg);
+		}
+
+		// Parse type.
+		if (!*s)
+			FMT_THROW(FormatError("invalid format string"));
+		spec.type_ = static_cast<char>(*s++);
+		if (arg.type <= Arg::LAST_INTEGER_TYPE) {
+			// Normalize type.
+			switch (spec.type_) {
+			case 'i': case 'u':
+				spec.type_ = 'd';
+				break;
+			case 'c':
+				// TODO: handle wchar_t
+				CharConverter(arg).visit(arg);
+				break;
+			}
+		}
+
+		start = s;
+
+		// Format argument.
+		internal::PrintfArgFormatter<Char>(writer, spec).visit(arg);
+	}
+	write(writer, start, s);
+}
+
+FMT_FUNC void fmt::report_system_error(
+	int error_code, fmt::StringRef message) FMT_NOEXCEPT
+{
+	// 'fmt::' is for bcc32.
+	fmt::report_error(internal::format_system_error, error_code, message);
+}
+
+#if FMT_USE_WINDOWS_H
+FMT_FUNC void fmt::report_windows_error(
+	int error_code, fmt::StringRef message) FMT_NOEXCEPT
+{
+	// 'fmt::' is for bcc32.
+	fmt::report_error(internal::format_windows_error, error_code, message);
+}
+#endif
+
+FMT_FUNC void fmt::print(std::FILE *f, CStringRef format_str, ArgList args)
+{
+	MemoryWriter w;
+	w.write(format_str, args);
+	std::fwrite(w.data(), 1, w.size(), f);
+}
+
+FMT_FUNC void fmt::print(CStringRef format_str, ArgList args)
+{
+	print(stdout, format_str, args);
+}
+
+FMT_FUNC void fmt::print(std::ostream &os, CStringRef format_str,
+	ArgList args)
+{
+	MemoryWriter w;
+	w.write(format_str, args);
+	write(os, w);
+}
+
+FMT_FUNC void fmt::print_colored(Color c, CStringRef format, ArgList args)
+{
+	char escape[] = "\x1b[30m";
+	escape[3] = static_cast<char>('0' + c);
+	std::fputs(escape, stdout);
+	print(format, args);
+	std::fputs(RESET_COLOR, stdout);
+}
+
+FMT_FUNC int fmt::fprintf(std::FILE *f, CStringRef format, ArgList args)
+{
+	MemoryWriter w;
+	printf(w, format, args);
+	std::size_t size = w.size();
+	return std::fwrite(w.data(), 1, size, f) < size ? -1 : static_cast<int>(size);
+}
+
+FMT_FUNC int fmt::fprintf(std::ostream &os, CStringRef format, ArgList args)
+{
+	MemoryWriter w;
+	printf(w, format, args);
+	write(os, w);
+	return static_cast<int>(w.size());
+}
+
+#ifndef FMT_HEADER_ONLY
+
+template struct fmt::internal::BasicData<void>;
+
+// Explicit instantiations for char.
+
+template void fmt::internal::FixedBuffer<char>::grow(std::size_t);
+
+template void fmt::internal::ArgMap<char>::init(const fmt::ArgList &args);
+
+template void fmt::internal::PrintfFormatter<char>::format(
+	BasicWriter<char> &writer, CStringRef format);
+
+template int fmt::internal::CharTraits<char>::format_float(
+	char *buffer, std::size_t size, const char *format,
+	unsigned width, int precision, double value);
+
+template int fmt::internal::CharTraits<char>::format_float(
+	char *buffer, std::size_t size, const char *format,
+	unsigned width, int precision, long double value);
+
+// Explicit instantiations for wchar_t.
+
+template void fmt::internal::FixedBuffer<wchar_t>::grow(std::size_t);
+
+template void fmt::internal::ArgMap<wchar_t>::init(const fmt::ArgList &args);
+
+template void fmt::internal::PrintfFormatter<wchar_t>::format(
+	BasicWriter<wchar_t> &writer, WCStringRef format);
+
+template int fmt::internal::CharTraits<wchar_t>::format_float(
+	wchar_t *buffer, std::size_t size, const wchar_t *format,
+	unsigned width, int precision, double value);
+
+template int fmt::internal::CharTraits<wchar_t>::format_float(
+	wchar_t *buffer, std::size_t size, const wchar_t *format,
+	unsigned width, int precision, long double value);
+
+#endif  // FMT_HEADER_ONLY
+
+#ifdef _MSC_VER
+# pragma warning(pop)
 #endif
\ No newline at end of file
diff --git a/include/spdlog/details/format.h b/include/spdlog/details/format.h
index 2e98d67..8046e61 100644
--- a/include/spdlog/details/format.h
+++ b/include/spdlog/details/format.h
@@ -28,6 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #ifndef FMT_FORMAT_H_
 #define FMT_FORMAT_H_
 
+
 //Added to spdlog version for header only usage
 #define FMT_HEADER_ONLY
 
@@ -36,14 +37,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #define FMT_USE_WINDOWS_H 0
 #endif
 
-#if defined _MSC_VER && _MSC_VER <= 1500
-typedef unsigned int       uint32_t;
-typedef unsigned long long uint64_t;
-typedef long long          intmax_t;
-#else
-#include <stdint.h>
-#endif
-
 #include <cassert>
 #include <cmath>
 #include <cstdio>
@@ -52,7 +45,8 @@ typedef long long          intmax_t;
 #include <memory>
 #include <stdexcept>
 #include <string>
-#include <map>
+#include <vector>
+#include <utility>
 
 #ifndef FMT_USE_IOSTREAMS
 # define FMT_USE_IOSTREAMS 1
@@ -72,6 +66,14 @@ typedef long long          intmax_t;
 # include <iterator>
 #endif
 
+#if defined(_MSC_VER) && _MSC_VER <= 1500
+typedef unsigned __int32 uint32_t;
+typedef unsigned __int64 uint64_t;
+typedef __int64          intmax_t;
+#else
+#include <stdint.h>
+#endif
+
 #if !defined(FMT_HEADER_ONLY) && defined(_WIN32)
 # ifdef FMT_EXPORT
 #  define FMT_API __declspec(dllexport)
@@ -83,46 +85,6 @@ typedef long long          intmax_t;
 # define FMT_API
 #endif
 
-#ifdef _MSC_VER
-# include <intrin.h>  // _BitScanReverse, _BitScanReverse64
-
-namespace fmt
-{
-namespace internal
-{
-# pragma intrinsic(_BitScanReverse)
-inline uint32_t clz(uint32_t x)
-{
-    unsigned long r = 0;
-    _BitScanReverse(&r, x);
-    return 31 - r;
-}
-# define FMT_BUILTIN_CLZ(n) fmt::internal::clz(n)
-
-# ifdef _WIN64
-#  pragma intrinsic(_BitScanReverse64)
-# endif
-
-inline uint32_t clzll(uint64_t x)
-{
-    unsigned long r = 0;
-# ifdef _WIN64
-    _BitScanReverse64(&r, x);
-# else
-    // Scan the high 32 bits.
-    if (_BitScanReverse(&r, static_cast<uint32_t>(x >> 32)))
-        return 63 - (r + 32);
-
-    // Scan the low 32 bits.
-    _BitScanReverse(&r, static_cast<uint32_t>(x));
-# endif
-    return 63 - r;
-}
-# define FMT_BUILTIN_CLZLL(n) fmt::internal::clzll(n)
-}
-}
-#endif
-
 #ifdef __GNUC__
 # define FMT_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
 # define FMT_GCC_EXTENSION __extension__
@@ -197,21 +159,6 @@ inline uint32_t clzll(uint64_t x)
 # include <utility>  // for std::move
 #endif
 
-// Define FMT_USE_NOEXCEPT to make C++ Format use noexcept (C++11 feature).
-#ifndef FMT_USE_NOEXCEPT
-# define FMT_USE_NOEXCEPT 0
-#endif
-
-#ifndef FMT_NOEXCEPT
-# if FMT_USE_NOEXCEPT || FMT_HAS_FEATURE(cxx_noexcept) || \
-   (FMT_GCC_VERSION >= 408 && FMT_HAS_GXX_CXX11) || \
-   _MSC_VER >= 1900
-#  define FMT_NOEXCEPT noexcept
-# else
-#  define FMT_NOEXCEPT throw()
-# endif
-#endif
-
 // Check if exceptions are disabled.
 #if defined(__GNUC__) && !defined(__EXCEPTIONS)
 # define FMT_EXCEPTIONS 0
@@ -231,6 +178,25 @@ inline uint32_t clzll(uint64_t x)
 # endif
 #endif
 
+// Define FMT_USE_NOEXCEPT to make C++ Format use noexcept (C++11 feature).
+#ifndef FMT_USE_NOEXCEPT
+# define FMT_USE_NOEXCEPT 0
+#endif
+
+#ifndef FMT_NOEXCEPT
+# if FMT_EXCEPTIONS
+#  if FMT_USE_NOEXCEPT || FMT_HAS_FEATURE(cxx_noexcept) || \
+    (FMT_GCC_VERSION >= 408 && FMT_HAS_GXX_CXX11) || \
+    _MSC_VER >= 1900
+#   define FMT_NOEXCEPT noexcept
+#  else
+#   define FMT_NOEXCEPT throw()
+#  endif
+# else
+#  define FMT_NOEXCEPT
+# endif
+#endif
+
 // A macro to disallow the copy constructor and operator= functions
 // This should be used in the private: declarations for a class
 #ifndef FMT_USE_DELETED_FUNCTIONS
@@ -264,6 +230,71 @@ inline uint32_t clzll(uint64_t x)
 # define FMT_ASSERT(condition, message) assert((condition) && message)
 #endif
 
+
+#if FMT_GCC_VERSION >= 400 || FMT_HAS_BUILTIN(__builtin_clz)
+# define FMT_BUILTIN_CLZ(n) __builtin_clz(n)
+#endif
+
+#if FMT_GCC_VERSION >= 400 || FMT_HAS_BUILTIN(__builtin_clzll)
+# define FMT_BUILTIN_CLZLL(n) __builtin_clzll(n)
+#endif
+
+// Some compilers masquerade as both MSVC and GCC-likes or
+// otherwise support __builtin_clz and __builtin_clzll, so
+// only define FMT_BUILTIN_CLZ using the MSVC intrinsics
+// if the clz and clzll builtins are not available.
+#if defined(_MSC_VER) && !defined(FMT_BUILTIN_CLZLL)
+# include <intrin.h>  // _BitScanReverse, _BitScanReverse64
+
+namespace fmt
+{
+namespace internal
+{
+# pragma intrinsic(_BitScanReverse)
+inline uint32_t clz(uint32_t x)
+{
+    unsigned long r = 0;
+    _BitScanReverse(&r, x);
+
+    assert(x != 0);
+    // Static analysis complains about using uninitialized data
+    // "r", but the only way that can happen is if "x" is 0,
+    // which the callers guarantee to not happen.
+# pragma warning(suppress: 6102)
+    return 31 - r;
+}
+# define FMT_BUILTIN_CLZ(n) fmt::internal::clz(n)
+
+# ifdef _WIN64
+#  pragma intrinsic(_BitScanReverse64)
+# endif
+
+inline uint32_t clzll(uint64_t x)
+{
+    unsigned long r = 0;
+# ifdef _WIN64
+    _BitScanReverse64(&r, x);
+# else
+    // Scan the high 32 bits.
+    if (_BitScanReverse(&r, static_cast<uint32_t>(x >> 32)))
+        return 63 - (r + 32);
+
+    // Scan the low 32 bits.
+    _BitScanReverse(&r, static_cast<uint32_t>(x));
+# endif
+
+    assert(x != 0);
+    // Static analysis complains about using uninitialized data
+    // "r", but the only way that can happen is if "x" is 0,
+    // which the callers guarantee to not happen.
+# pragma warning(suppress: 6102)
+    return 63 - r;
+}
+# define FMT_BUILTIN_CLZLL(n) fmt::internal::clzll(n)
+}
+}
+#endif
+
 namespace fmt
 {
 namespace internal
@@ -322,7 +353,7 @@ namespace std
 // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=48891
 // and the same for isnan and signbit.
 template <>
-class numeric_limits<fmt::internal::DummyInt> :
+class numeric_limits<fmt::internal::DummyInt>:
     public std::numeric_limits<int>
 {
 public:
@@ -388,7 +419,14 @@ class BasicWriter;
 typedef BasicWriter<char> Writer;
 typedef BasicWriter<wchar_t> WWriter;
 
+namespace internal
+{
 template <typename Char>
+class BasicArgFormatter;
+}
+
+template <typename CharType,
+          typename ArgFormatter = internal::BasicArgFormatter<CharType> >
 class BasicFormatter;
 
 template <typename Char, typename T>
@@ -427,7 +465,8 @@ private:
 
 public:
     /** Constructs a string reference object from a C string and a size. */
-    BasicStringRef(const Char *s, std::size_t size) : data_(s), size_(size) {}
+    BasicStringRef(const Char *s, std::size_t size): data_(s), size_(size)
+    {}
 
     /**
     \rst
@@ -436,7 +475,8 @@ public:
     \endrst
     */
     BasicStringRef(const Char *s)
-        : data_(s), size_(std::char_traits<Char>::length(s)) {}
+        : data_(s), size_(std::char_traits<Char>::length(s))
+    {}
 
     /**
     \rst
@@ -444,7 +484,8 @@ public:
     \endrst
     */
     BasicStringRef(const std::basic_string<Char> &s)
-        : data_(s.c_str()), size_(s.size()) {}
+        : data_(s.c_str()), size_(s.size())
+    {}
 
     /**
     \rst
@@ -456,7 +497,7 @@ public:
         return std::basic_string<Char>(data_, size_);
     }
 
-    /** Returns the pointer to a C string. */
+    /** Returns a pointer to the string data. */
     const Char *data() const
     {
         return data_;
@@ -540,14 +581,16 @@ private:
 
 public:
     /** Constructs a string reference object from a C string. */
-    BasicCStringRef(const Char *s) : data_(s) {}
+    BasicCStringRef(const Char *s): data_(s)
+    {}
 
     /**
     \rst
     Constructs a string reference from an ``std::string`` object.
     \endrst
     */
-    BasicCStringRef(const std::basic_string<Char> &s) : data_(s.c_str()) {}
+    BasicCStringRef(const std::basic_string<Char> &s): data_(s.c_str())
+    {}
 
     /** Returns the pointer to a C string. */
     const Char *c_str() const
@@ -562,18 +605,49 @@ typedef BasicCStringRef<wchar_t> WCStringRef;
 /**
 A formatting error such as invalid format string.
 */
-class FormatError : public std::runtime_error
+class FormatError: public std::runtime_error
 {
 public:
     explicit FormatError(CStringRef message)
-        : std::runtime_error(message.c_str()) {}
+        : std::runtime_error(message.c_str())
+    {}
 };
 
 namespace internal
 {
+
+// MakeUnsigned<T>::Type gives an unsigned type corresponding to integer type T.
+template <typename T>
+struct MakeUnsigned
+{
+    typedef T Type;
+};
+
+#define FMT_SPECIALIZE_MAKE_UNSIGNED(T, U) \
+  template <> \
+  struct MakeUnsigned<T> { typedef U Type; }
+
+FMT_SPECIALIZE_MAKE_UNSIGNED(char, unsigned char);
+FMT_SPECIALIZE_MAKE_UNSIGNED(signed char, unsigned char);
+FMT_SPECIALIZE_MAKE_UNSIGNED(short, unsigned short);
+FMT_SPECIALIZE_MAKE_UNSIGNED(int, unsigned);
+FMT_SPECIALIZE_MAKE_UNSIGNED(long, unsigned long);
+FMT_SPECIALIZE_MAKE_UNSIGNED(LongLong, ULongLong);
+
+// Casts nonnegative integer to unsigned.
+template <typename Int>
+inline typename MakeUnsigned<Int>::Type to_unsigned(Int value)
+{
+    FMT_ASSERT(value >= 0, "negative value");
+    return static_cast<typename MakeUnsigned<Int>::Type>(value);
+}
+
 // The number of characters to store in the MemoryBuffer object itself
 // to avoid dynamic memory allocation.
-enum { INLINE_BUFFER_SIZE = 500 };
+enum
+{
+    INLINE_BUFFER_SIZE = 500
+};
 
 #if FMT_SECURE_SCL
 // Use checked iterator to avoid warnings on MSVC.
@@ -608,7 +682,8 @@ protected:
     std::size_t capacity_;
 
     Buffer(T *ptr = 0, std::size_t capacity = 0)
-        : ptr_(ptr), size_(0), capacity_(capacity) {}
+        : ptr_(ptr), size_(0), capacity_(capacity)
+    {}
 
     /**
     \rst
@@ -619,7 +694,8 @@ protected:
     virtual void grow(std::size_t size) = 0;
 
 public:
-    virtual ~Buffer() {}
+    virtual ~Buffer()
+    {}
 
     /** Returns the size of this buffer. */
     std::size_t size() const
@@ -654,7 +730,10 @@ public:
             grow(capacity);
     }
 
-    void clear() FMT_NOEXCEPT { size_ = 0; }
+    void clear() FMT_NOEXCEPT
+    {
+        size_ = 0;
+    }
 
     void push_back(const T &value)
     {
@@ -681,8 +760,7 @@ template <typename T>
 template <typename U>
 void Buffer<T>::append(const U *begin, const U *end)
 {
-    assert(begin <= end);
-    std::size_t new_size = size_ + (end - begin);
+    std::size_t new_size = size_ + internal::to_unsigned(end - begin);
     if (new_size > capacity_)
         grow(new_size);
     std::uninitialized_copy(begin, end,
@@ -693,10 +771,10 @@ void Buffer<T>::append(const U *begin, const U *end)
 namespace internal
 {
 
-// A memory buffer for POD types with the first SIZE elements stored in
-// the object itself.
+// A memory buffer for trivially copyable/constructible types with the first SIZE
+// elements stored in the object itself.
 template <typename T, std::size_t SIZE, typename Allocator = std::allocator<T> >
-class MemoryBuffer : private Allocator, public Buffer<T>
+class MemoryBuffer: private Allocator, public Buffer<T>
 {
 private:
     T data_[SIZE];
@@ -712,7 +790,8 @@ protected:
 
 public:
     explicit MemoryBuffer(const Allocator &alloc = Allocator())
-        : Allocator(alloc), Buffer<T>(data_, SIZE) {}
+        : Allocator(alloc), Buffer<T>(data_, SIZE)
+    {}
     ~MemoryBuffer()
     {
         deallocate();
@@ -787,10 +866,11 @@ void MemoryBuffer<T, SIZE, Allocator>::grow(std::size_t size)
 
 // A fixed-size buffer.
 template <typename Char>
-class FixedBuffer : public fmt::Buffer<Char>
+class FixedBuffer: public fmt::Buffer<Char>
 {
 public:
-    FixedBuffer(Char *array, std::size_t size) : fmt::Buffer<Char>(array, size) {}
+    FixedBuffer(Char *array, std::size_t size): fmt::Buffer<Char>(array, size)
+    {}
 
 protected:
     FMT_API void grow(std::size_t size);
@@ -815,7 +895,7 @@ template <typename Char>
 class CharTraits;
 
 template <>
-class CharTraits<char> : public BasicCharTraits<char>
+class CharTraits<char>: public BasicCharTraits<char>
 {
 private:
     // Conversion from wchar_t to char is not allowed.
@@ -834,7 +914,7 @@ public:
 };
 
 template <>
-class CharTraits<wchar_t> : public BasicCharTraits<wchar_t>
+class CharTraits<wchar_t>: public BasicCharTraits<wchar_t>
 {
 public:
     static wchar_t convert(char value)
@@ -902,24 +982,6 @@ struct IntTraits
     TypeSelector<std::numeric_limits<T>::digits <= 32>::Type MainType;
 };
 
-// MakeUnsigned<T>::Type gives an unsigned type corresponding to integer type T.
-template <typename T>
-struct MakeUnsigned
-{
-    typedef T Type;
-};
-
-#define FMT_SPECIALIZE_MAKE_UNSIGNED(T, U) \
-  template <> \
-  struct MakeUnsigned<T> { typedef U Type; }
-
-FMT_SPECIALIZE_MAKE_UNSIGNED(char, unsigned char);
-FMT_SPECIALIZE_MAKE_UNSIGNED(signed char, unsigned char);
-FMT_SPECIALIZE_MAKE_UNSIGNED(short, unsigned short);
-FMT_SPECIALIZE_MAKE_UNSIGNED(int, unsigned);
-FMT_SPECIALIZE_MAKE_UNSIGNED(long, unsigned long);
-FMT_SPECIALIZE_MAKE_UNSIGNED(LongLong, ULongLong);
-
 FMT_API void report_unknown_type(char code, const char *type);
 
 // Static data is placed in this class template to allow header-only
@@ -934,14 +996,6 @@ struct FMT_API BasicData
 
 typedef BasicData<> Data;
 
-#if FMT_GCC_VERSION >= 400 || FMT_HAS_BUILTIN(__builtin_clz)
-# define FMT_BUILTIN_CLZ(n) __builtin_clz(n)
-#endif
-
-#if FMT_GCC_VERSION >= 400 || FMT_HAS_BUILTIN(__builtin_clzll)
-# define FMT_BUILTIN_CLZLL(n) __builtin_clzll(n)
-#endif
-
 #ifdef FMT_BUILTIN_CLZLL
 // Returns the number of decimal digits in n. Leading zeros are not counted
 // except for n == 0 in which case count_digits returns 1.
@@ -949,8 +1003,8 @@ inline unsigned count_digits(uint64_t n)
 {
     // Based on http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10
     // and the benchmark https://github.com/localvoid/cxx-benchmark-count-digits.
-    unsigned t = (64 - FMT_BUILTIN_CLZLL(n | 1)) * 1233 >> 12;
-    return t - (n < Data::POWERS_OF_10_64[t]) + 1;
+    int t = (64 - FMT_BUILTIN_CLZLL(n | 1)) * 1233 >> 12;
+    return to_unsigned(t) - (n < Data::POWERS_OF_10_64[t]) + 1;
 }
 #else
 // Fallback version of count_digits used when __builtin_clz is not available.
@@ -976,8 +1030,8 @@ inline unsigned count_digits(uint64_t n)
 // Optional version of count_digits for better performance on 32-bit platforms.
 inline unsigned count_digits(uint32_t n)
 {
-    uint32_t t = (32 - FMT_BUILTIN_CLZ(n | 1)) * 1233 >> 12;
-    return t - (n < Data::POWERS_OF_10_32[t]) + 1;
+    int t = (32 - FMT_BUILTIN_CLZ(n | 1)) * 1233 >> 12;
+    return to_unsigned(t) - (n < Data::POWERS_OF_10_32[t]) + 1;
 }
 #endif
 
@@ -1050,7 +1104,8 @@ private:
     MemoryBuffer<char, INLINE_BUFFER_SIZE> buffer_;
 
 public:
-    UTF16ToUTF8() {}
+    UTF16ToUTF8()
+    {}
     FMT_API explicit UTF16ToUTF8(WStringRef s);
     operator StringRef() const
     {
@@ -1128,9 +1183,9 @@ struct Value
     };
 };
 
-// A formatting argument. It is a POD type to allow storage in
-// internal::MemoryBuffer.
-struct Arg : Value
+// A formatting argument. It is a trivially copyable/constructible type to
+// allow storage in internal::MemoryBuffer.
+struct Arg: Value
 {
     Type type;
 };
@@ -1139,7 +1194,8 @@ template <typename Char>
 struct NamedArg;
 
 template <typename T = void>
-struct Null {};
+struct Null
+{};
 
 // A helper class template to enable or disable overloads taking wide
 // characters and strings in MakeValue.
@@ -1168,7 +1224,7 @@ No &convert(...);
 template <typename T>
 T &get();
 
-struct DummyStream : std::ostream
+struct DummyStream: std::ostream
 {
     DummyStream();  // Suppress a bogus warning in MSVC.
     // Hide all operator<< overloads from std::ostream.
@@ -1180,7 +1236,10 @@ No &operator<<(std::ostream &, int);
 template<typename T, bool ENABLE_CONVERSION>
 struct ConvertToIntImpl
 {
-    enum { value = false };
+    enum
+    {
+        value = false
+    };
 };
 
 template<typename T>
@@ -1196,7 +1255,10 @@ struct ConvertToIntImpl<T, true>
 template<typename T, bool ENABLE_CONVERSION>
 struct ConvertToIntImpl2
 {
-    enum { value = false };
+    enum
+    {
+        value = false
+    };
 };
 
 template<typename T>
@@ -1212,8 +1274,14 @@ struct ConvertToIntImpl2<T, true>
 template<typename T>
 struct ConvertToInt
 {
-    enum { enable_conversion = sizeof(convert(get<T>())) == sizeof(Yes) };
-    enum { value = ConvertToIntImpl2<T, enable_conversion>::value };
+    enum
+    {
+        enable_conversion = sizeof(convert(get<T>())) == sizeof(Yes)
+    };
+    enum
+    {
+        value = ConvertToIntImpl2<T, enable_conversion>::value
+    };
 };
 
 #define FMT_DISABLE_CONVERSION_TO_INT(Type) \
@@ -1226,7 +1294,8 @@ FMT_DISABLE_CONVERSION_TO_INT(double);
 FMT_DISABLE_CONVERSION_TO_INT(long double);
 
 template<bool B, class T = void>
-struct EnableIf {};
+struct EnableIf
+{};
 
 template<class T>
 struct EnableIf<true, T>
@@ -1250,18 +1319,24 @@ struct Conditional<false, T, F>
 template<bool>
 struct Not
 {
-    enum { value = 0 };
+    enum
+    {
+        value = 0
+    };
 };
 
 template<>
 struct Not<false>
 {
-    enum { value = 1 };
+    enum
+    {
+        value = 1
+    };
 };
 
 // Makes an Arg object from any type.
 template <typename Formatter>
-class MakeValue : public Arg
+class MakeValue: public Arg
 {
 public:
     typedef typename Formatter::Char Char;
@@ -1312,7 +1387,8 @@ private:
     }
 
 public:
-    MakeValue() {}
+    MakeValue()
+    {}
 
 #define FMT_MAKE_VALUE_(Type, field, TYPE, rhs) \
   MakeValue(Type value) { field = rhs; } \
@@ -1389,7 +1465,7 @@ public:
 #define FMT_MAKE_WSTR_VALUE(Type, TYPE) \
   MakeValue(typename WCharHelper<Type, Char>::Supported value) { \
     set_string(value); \
-              } \
+  } \
   static uint64_t type(Type) { return Arg::TYPE; }
 
     FMT_MAKE_WSTR_VALUE(wchar_t *, WSTRING)
@@ -1437,19 +1513,32 @@ public:
     }
 };
 
+template <typename Formatter>
+class MakeArg: public Arg
+{
+public:
+    MakeArg()
+    {
+        type = Arg::NONE;
+    }
+
+    template <typename T>
+    MakeArg(const T &value)
+        : Arg(MakeValue<Formatter>(value))
+    {
+        type = static_cast<Arg::Type>(MakeValue<Formatter>::type(value));
+    }
+};
+
 template <typename Char>
-struct NamedArg : Arg
+struct NamedArg: Arg
 {
     BasicStringRef<Char> name;
 
-    typedef internal::MakeValue< BasicFormatter<Char> > MakeValue;
-
     template <typename T>
     NamedArg(BasicStringRef<Char> argname, const T &value)
-        : Arg(MakeValue(value)), name(argname)
-    {
-        type = static_cast<Arg::Type>(MakeValue::type(value));
-    }
+        : Arg(MakeArg< BasicFormatter<Char> >(value)), name(argname)
+    {}
 };
 
 #define FMT_DISPATCH(call) static_cast<Impl*>(this)->call
@@ -1478,7 +1567,8 @@ template <typename Impl, typename Result>
 class ArgVisitor
 {
 public:
-    void report_unhandled_arg() {}
+    void report_unhandled_arg()
+    {}
 
     Result visit_unhandled_arg()
     {
@@ -1588,10 +1678,11 @@ public:
     }
 };
 
-class RuntimeError : public std::runtime_error
+class RuntimeError: public std::runtime_error
 {
 protected:
-    RuntimeError() : std::runtime_error("") {}
+    RuntimeError(): std::runtime_error("")
+    {}
 };
 
 template <typename Char>
@@ -1632,14 +1723,20 @@ private:
 
 public:
     // Maximum number of arguments with packed types.
-    enum { MAX_PACKED_ARGS = 16 };
+    enum
+    {
+        MAX_PACKED_ARGS = 16
+    };
 
-    ArgList() : types_(0) {}
+    ArgList(): types_(0)
+    {}
 
     ArgList(ULongLong types, const internal::Value *values)
-        : types_(types), values_(values) {}
+        : types_(types), values_(values)
+    {}
     ArgList(ULongLong types, const internal::Arg *args)
-        : types_(types), args_(args) {}
+        : types_(types), args_(args)
+    {}
 
     /** Returns the argument at specified index. */
     internal::Arg operator[](unsigned index) const
@@ -1685,11 +1782,12 @@ enum
 };
 
 // An empty format specifier.
-struct EmptySpec {};
+struct EmptySpec
+{};
 
 // A type specifier.
 template <char TYPE>
-struct TypeSpec : EmptySpec
+struct TypeSpec: EmptySpec
 {
     Alignment align() const
     {
@@ -1725,7 +1823,8 @@ struct WidthSpec
     // two specialization of WidthSpec and its subclasses.
     wchar_t fill_;
 
-    WidthSpec(unsigned width, wchar_t fill) : width_(width), fill_(fill) {}
+    WidthSpec(unsigned width, wchar_t fill): width_(width), fill_(fill)
+    {}
 
     unsigned width() const
     {
@@ -1738,12 +1837,13 @@ struct WidthSpec
 };
 
 // An alignment specifier.
-struct AlignSpec : WidthSpec
+struct AlignSpec: WidthSpec
 {
     Alignment align_;
 
     AlignSpec(unsigned width, wchar_t fill, Alignment align = ALIGN_DEFAULT)
-        : WidthSpec(width, fill), align_(align) {}
+        : WidthSpec(width, fill), align_(align)
+    {}
 
     Alignment align() const
     {
@@ -1758,9 +1858,10 @@ struct AlignSpec : WidthSpec
 
 // An alignment and type specifier.
 template <char TYPE>
-struct AlignTypeSpec : AlignSpec
+struct AlignTypeSpec: AlignSpec
 {
-    AlignTypeSpec(unsigned width, wchar_t fill) : AlignSpec(width, fill) {}
+    AlignTypeSpec(unsigned width, wchar_t fill): AlignSpec(width, fill)
+    {}
 
     bool flag(unsigned) const
     {
@@ -1773,7 +1874,7 @@ struct AlignTypeSpec : AlignSpec
 };
 
 // A full format specifier.
-struct FormatSpec : AlignSpec
+struct FormatSpec: AlignSpec
 {
     unsigned flags_;
     int precision_;
@@ -1781,7 +1882,8 @@ struct FormatSpec : AlignSpec
 
     FormatSpec(
         unsigned width = 0, char type = 0, wchar_t fill = ' ')
-        : AlignSpec(width, fill), flags_(0), precision_(-1), type_(type) {}
+        : AlignSpec(width, fill), flags_(0), precision_(-1), type_(type)
+    {}
 
     bool flag(unsigned f) const
     {
@@ -1799,14 +1901,15 @@ struct FormatSpec : AlignSpec
 
 // An integer format specifier.
 template <typename T, typename SpecT = TypeSpec<0>, typename Char = char>
-class IntFormatSpec : public SpecT
+class IntFormatSpec: public SpecT
 {
 private:
     T value_;
 
 public:
     IntFormatSpec(T val, const SpecT &spec = SpecT())
-        : SpecT(spec), value_(val) {}
+        : SpecT(spec), value_(val)
+    {}
 
     T value() const
     {
@@ -1816,7 +1919,7 @@ public:
 
 // A string format specifier.
 template <typename Char>
-class StrFormatSpec : public AlignSpec
+class StrFormatSpec: public AlignSpec
 {
 private:
     const Char *str_;
@@ -1878,26 +1981,26 @@ IntFormatSpec<int, AlignTypeSpec<TYPE_CODE>, Char> pad(
 #define FMT_DEFINE_INT_FORMATTERS(TYPE) \
 inline IntFormatSpec<TYPE, TypeSpec<'b'> > bin(TYPE value) { \
   return IntFormatSpec<TYPE, TypeSpec<'b'> >(value, TypeSpec<'b'>()); \
-    } \
+} \
  \
 inline IntFormatSpec<TYPE, TypeSpec<'o'> > oct(TYPE value) { \
   return IntFormatSpec<TYPE, TypeSpec<'o'> >(value, TypeSpec<'o'>()); \
-    } \
+} \
  \
 inline IntFormatSpec<TYPE, TypeSpec<'x'> > hex(TYPE value) { \
   return IntFormatSpec<TYPE, TypeSpec<'x'> >(value, TypeSpec<'x'>()); \
-    } \
+} \
  \
 inline IntFormatSpec<TYPE, TypeSpec<'X'> > hexu(TYPE value) { \
   return IntFormatSpec<TYPE, TypeSpec<'X'> >(value, TypeSpec<'X'>()); \
-    } \
+} \
  \
 template <char TYPE_CODE> \
 inline IntFormatSpec<TYPE, AlignTypeSpec<TYPE_CODE> > pad( \
     IntFormatSpec<TYPE, TypeSpec<TYPE_CODE> > f, unsigned width) { \
   return IntFormatSpec<TYPE, AlignTypeSpec<TYPE_CODE> >( \
       f.value(), AlignTypeSpec<TYPE_CODE>(width, ' ')); \
-    } \
+} \
  \
 /* For compatibility with older compilers we provide two overloads for pad, */ \
 /* one that takes a fill character and one that doesn't. In the future this */ \
@@ -1909,20 +2012,20 @@ inline IntFormatSpec<TYPE, AlignTypeSpec<TYPE_CODE>, Char> pad( \
     unsigned width, Char fill) { \
   return IntFormatSpec<TYPE, AlignTypeSpec<TYPE_CODE>, Char>( \
       f.value(), AlignTypeSpec<TYPE_CODE>(width, fill)); \
-    } \
+} \
  \
 inline IntFormatSpec<TYPE, AlignTypeSpec<0> > pad( \
     TYPE value, unsigned width) { \
   return IntFormatSpec<TYPE, AlignTypeSpec<0> >( \
       value, AlignTypeSpec<0>(width, ' ')); \
-    } \
+} \
  \
 template <typename Char> \
 inline IntFormatSpec<TYPE, AlignTypeSpec<0>, Char> pad( \
    TYPE value, unsigned width, Char fill) { \
  return IntFormatSpec<TYPE, AlignTypeSpec<0>, Char>( \
      value, AlignTypeSpec<0>(width, fill)); \
-    }
+}
 
 FMT_DEFINE_INT_FORMATTERS(int)
 FMT_DEFINE_INT_FORMATTERS(long)
@@ -1963,7 +2066,7 @@ template <typename Char>
 class ArgMap
 {
 private:
-    typedef std::map<fmt::BasicStringRef<Char>, internal::Arg> MapType;
+    typedef std::vector<std::pair<fmt::BasicStringRef<Char>, internal::Arg> > MapType;
     typedef typename MapType::value_type Pair;
 
     MapType map_;
@@ -1973,13 +2076,19 @@ public:
 
     const internal::Arg* find(const fmt::BasicStringRef<Char> &name) const
     {
-        typename MapType::const_iterator it = map_.find(name);
-        return it != map_.end() ? &it->second : 0;
+        // The list is unsorted, so just return the first matching name.
+        for (typename MapType::const_iterator it = map_.begin(), end = map_.end();
+                it != end; ++it)
+        {
+            if (it->first == name)
+                return &it->second;
+        }
+        return 0;
     }
 };
 
 template <typename Impl, typename Char>
-class ArgFormatterBase : public ArgVisitor<Impl, void>
+class ArgFormatterBase: public ArgVisitor<Impl, void>
 {
 private:
     BasicWriter<Char> &writer_;
@@ -2019,7 +2128,8 @@ protected:
 
 public:
     ArgFormatterBase(BasicWriter<Char> &w, FormatSpec &s)
-        : writer_(w), spec_(s) {}
+        : writer_(w), spec_(s)
+    {}
 
     template <typename T>
     void visit_any_int(T value)
@@ -2109,7 +2219,7 @@ public:
 
 // An argument formatter.
 template <typename Char>
-class BasicArgFormatter :
+class BasicArgFormatter:
     public ArgFormatterBase<BasicArgFormatter<Char>, Char>
 {
 private:
@@ -2119,7 +2229,8 @@ private:
 public:
     BasicArgFormatter(BasicFormatter<Char> &f, FormatSpec &s, const Char *fmt)
         : ArgFormatterBase<BasicArgFormatter<Char>, Char>(f.writer(), s),
-          formatter_(f), format_(fmt) {}
+          formatter_(f), format_(fmt)
+    {}
 
     void visit_custom(Arg::CustomValue c)
     {
@@ -2152,7 +2263,7 @@ protected:
     Arg next_arg(const char *&error)
     {
         if (next_arg_index_ >= 0)
-            return do_get_arg(next_arg_index_++, error);
+            return do_get_arg(internal::to_unsigned(next_arg_index_++), error);
         error = "cannot switch from manual to automatic argument indexing";
         return Arg();
     }
@@ -2179,13 +2290,13 @@ protected:
     void write(BasicWriter<Char> &w, const Char *start, const Char *end)
     {
         if (start != end)
-            w << BasicStringRef<Char>(start, end - start);
+            w << BasicStringRef<Char>(start, internal::to_unsigned(end - start));
     }
 };
 
 // A printf formatter.
 template <typename Char>
-class PrintfFormatter : private FormatterBase
+class PrintfFormatter: private FormatterBase
 {
 private:
     void parse_flags(FormatSpec &spec, const Char *&s);
@@ -2199,17 +2310,19 @@ private:
     unsigned parse_header(const Char *&s, FormatSpec &spec);
 
 public:
-    explicit PrintfFormatter(const ArgList &args) : FormatterBase(args) {}
+    explicit PrintfFormatter(const ArgList &args): FormatterBase(args)
+    {}
     FMT_API void format(BasicWriter<Char> &writer,
                         BasicCStringRef<Char> format_str);
 };
 }  // namespace internal
 
-// A formatter.
-template <typename CharType>
-class BasicFormatter : private internal::FormatterBase
+/** This template formats data and writes the output to a writer. */
+template <typename CharType, typename ArgFormatter>
+class BasicFormatter: private internal::FormatterBase
 {
 public:
+    /** The character type for the output. */
     typedef CharType Char;
 
 private:
@@ -2231,16 +2344,27 @@ private:
     internal::Arg parse_arg_name(const Char *&s);
 
 public:
+    /**
+    \rst
+    Constructs a ``BasicFormatter`` object. References to the arguments and
+    the writer are stored in the formatter object so make sure they have
+    appropriate lifetimes.
+    \endrst
+    */
     BasicFormatter(const ArgList &args, BasicWriter<Char> &w)
-        : internal::FormatterBase(args), writer_(w) {}
+        : internal::FormatterBase(args), writer_(w)
+    {}
 
+    /** Returns a reference to the writer associated with this formatter. */
     BasicWriter<Char> &writer()
     {
         return writer_;
     }
 
+    /** Formats stored arguments and writes the output to the writer. */
     void format(BasicCStringRef<Char> format_str);
 
+    // Formats a single argument and advances format_str, a format string pointer.
     const Char *format(const Char *&format_str, const internal::Arg &arg);
 };
 
@@ -2276,82 +2400,56 @@ inline uint64_t make_type(const T &arg)
     return MakeValue< BasicFormatter<char> >::type(arg);
 }
 
-template <unsigned N>
-struct ArgArray
-{
-    // Computes the argument array size by adding 1 to N, which is the number of
-    // arguments, if N is zero, because array of zero size is invalid, or if N
-    // is greater than ArgList::MAX_PACKED_ARGS to accommodate for an extra
-    // argument that marks the end of the list.
-    enum { SIZE = N + (N == 0 || N >= ArgList::MAX_PACKED_ARGS ? 1 : 0) };
-
-    typedef typename Conditional<
-    (N < ArgList::MAX_PACKED_ARGS), Value, Arg>::type Type[SIZE];
-};
+template <unsigned N, bool/*IsPacked*/ = (N < ArgList::MAX_PACKED_ARGS)>
+          struct ArgArray;
 
-#if FMT_USE_VARIADIC_TEMPLATES
-template <typename Arg, typename... Args>
-inline uint64_t make_type(const Arg &first, const Args & ... tail)
-{
-    return make_type(first) | (make_type(tail...) << 4);
-}
-
-inline void do_set_types(Arg *) {}
-
-template <typename T, typename... Args>
-inline void do_set_types(Arg *args, const T &arg, const Args & ... tail)
+template <unsigned N>
+struct ArgArray<N, true/*IsPacked*/>
 {
-    args->type = static_cast<Arg::Type>(
-                     MakeValue< BasicFormatter<char> >::type(arg));
-    do_set_types(args + 1, tail...);
-}
+    typedef Value Type[N > 0 ? N : 1];
 
-template <typename... Args>
-inline void set_types(Arg *array, const Args & ... args)
+template <typename Formatter, typename T>
+static Value make(const T &value)
 {
-    if (check(sizeof...(Args) > ArgList::MAX_PACKED_ARGS))
-        do_set_types(array, args...);
-    array[sizeof...(Args)].type = Arg::NONE;
+    Value result = MakeValue<Formatter>(value);
+    // Workaround a bug in Apple LLVM version 4.2 (clang-425.0.28) of clang:
+    // https://github.com/cppformat/cppformat/issues/276
+    (void)result.custom.format;
+    return result;
 }
+         };
 
-template <typename... Args>
-inline void set_types(Value *, const Args & ...)
+template <unsigned N>
+struct ArgArray<N, false/*IsPacked*/>
 {
-    // Do nothing as types are passed separately from values.
-}
+    typedef Arg Type[N + 1]; // +1 for the list end Arg::NONE
 
-template <typename Formatter, typename Value>
-inline void store_args(Value *) {}
+    template <typename Formatter, typename T>
+    static Arg make(const T &value)
+    {
+        return MakeArg<Formatter>(value);
+    }
+};
 
-template <typename Formatter, typename Arg, typename T, typename... Args>
-inline void store_args(Arg *args, const T &arg, const Args & ... tail)
+#if FMT_USE_VARIADIC_TEMPLATES
+template <typename Arg, typename... Args>
+inline uint64_t make_type(const Arg &first, const Args & ... tail)
 {
-    // Assign only the Value subobject of Arg and don't overwrite type (if any)
-    // that is assigned by set_types.
-    Value &value = *args;
-    value = MakeValue<Formatter>(arg);
-    store_args<Formatter>(args + 1, tail...);
+    return make_type(first) | (make_type(tail...) << 4);
 }
 
-template <typename Formatter, typename... Args>
-ArgList make_arg_list(typename ArgArray<sizeof...(Args)>::Type array,
-                      const Args & ... args)
-{
-    if (check(sizeof...(Args) >= ArgList::MAX_PACKED_ARGS))
-        set_types(array, args...);
-    store_args<Formatter>(array, args...);
-    return ArgList(make_type(args...), array);
-}
 #else
 
 struct ArgType
 {
     uint64_t type;
 
-    ArgType() : type(0) {}
+    ArgType(): type(0)
+    {}
 
     template <typename T>
-    ArgType(const T &arg) : type(make_type(arg)) {}
+    ArgType(const T &arg) : type(make_type(arg))
+    {}
 };
 
 # define FMT_ARG_TYPE_DEFAULT(n) ArgType t##n = ArgType()
@@ -2366,7 +2464,7 @@ inline uint64_t make_type(FMT_GEN15(FMT_ARG_TYPE_DEFAULT))
 #endif
 
 template <class Char>
-class FormatBuf : public std::basic_streambuf<Char>
+class FormatBuf: public std::basic_streambuf<Char>
 {
 private:
     typedef typename std::basic_streambuf<Char>::int_type int_type;
@@ -2376,7 +2474,7 @@ private:
     Char *start_;
 
 public:
-    FormatBuf(Buffer<Char> &buffer) : buffer_(buffer), start_(&buffer[0])
+    FormatBuf(Buffer<Char> &buffer): buffer_(buffer), start_(&buffer[0])
     {
         this->setp(start_, start_ + buffer_.capacity());
     }
@@ -2385,7 +2483,7 @@ public:
     {
         if (!traits_type::eq_int_type(ch, traits_type::eof()))
         {
-            size_t size = this->pptr() - start_;
+            size_t size = this->size();
             buffer_.resize(size);
             buffer_.reserve(size * 2);
 
@@ -2398,7 +2496,7 @@ public:
 
     size_t size() const
     {
-        return this->pptr() - start_;
+        return to_unsigned(this->pptr() - start_);
     }
 };
 }  // namespace internal
@@ -2416,19 +2514,21 @@ public:
 # define FMT_VARIADIC_VOID(func, arg_type) \
   template <typename... Args> \
   void func(arg_type arg0, const Args & ... args) { \
-    typename fmt::internal::ArgArray<sizeof...(Args)>::Type array; \
-    func(arg0, fmt::internal::make_arg_list< \
-      fmt::BasicFormatter<Char> >(array, args...)); \
-      }
+    typedef fmt::internal::ArgArray<sizeof...(Args)> ArgArray; \
+    typename ArgArray::Type array{ \
+      ArgArray::template make<fmt::BasicFormatter<Char> >(args)...}; \
+    func(arg0, fmt::ArgList(fmt::internal::make_type(args...), array)); \
+  }
 
 // Defines a variadic constructor.
 # define FMT_VARIADIC_CTOR(ctor, func, arg0_type, arg1_type) \
   template <typename... Args> \
   ctor(arg0_type arg0, arg1_type arg1, const Args & ... args) { \
-    typename fmt::internal::ArgArray<sizeof...(Args)>::Type array; \
-    func(arg0, arg1, fmt::internal::make_arg_list< \
-      fmt::BasicFormatter<Char> >(array, args...)); \
-      }
+    typedef fmt::internal::ArgArray<sizeof...(Args)> ArgArray; \
+    typename ArgArray::Type array{ \
+      ArgArray::template make<fmt::BasicFormatter<Char> >(args)...}; \
+    func(arg0, arg1, fmt::ArgList(fmt::internal::make_type(args...), array)); \
+  }
 
 #else
 
@@ -2444,7 +2544,7 @@ public:
     const fmt::internal::ArgArray<n>::Type array = {FMT_GEN(n, FMT_MAKE_REF)}; \
     func(arg1, fmt::ArgList( \
       fmt::internal::make_type(FMT_GEN(n, FMT_MAKE_REF2)), array)); \
-      }
+  }
 
 // Emulates a variadic function returning void on a pre-C++11 compiler.
 # define FMT_VARIADIC_VOID(func, arg_type) \
@@ -2461,7 +2561,7 @@ public:
     const fmt::internal::ArgArray<n>::Type array = {FMT_GEN(n, FMT_MAKE_REF)}; \
     func(arg0, arg1, fmt::ArgList( \
       fmt::internal::make_type(FMT_GEN(n, FMT_MAKE_REF2)), array)); \
-      }
+  }
 
 // Emulates a variadic constructor on a pre-C++11 compiler.
 # define FMT_VARIADIC_CTOR(ctor, func, arg0_type, arg1_type) \
@@ -2503,7 +2603,7 @@ public:
 An error returned by an operating system or a language runtime,
 for example a file opening error.
 */
-class SystemError : public internal::RuntimeError
+class SystemError: public internal::RuntimeError
 {
 private:
     void init(int err_code, CStringRef format_str, ArgList args);
@@ -2513,7 +2613,8 @@ protected:
 
     typedef char Char;  // For FMT_VARIADIC_CTOR.
 
-    SystemError() {}
+    SystemError()
+    {}
 
 public:
     /**
@@ -2623,7 +2724,8 @@ private:
     template <typename Int>
     void write_decimal(Int value)
     {
-        typename internal::IntTraits<Int>::MainType abs_value = value;
+        typedef typename internal::IntTraits<Int>::MainType MainType;
+        MainType abs_value = static_cast<MainType>(value);
         if (internal::is_negative(value))
         {
             abs_value = 0 - abs_value;
@@ -2681,7 +2783,8 @@ private:
     }
 
     template<typename T>
-    void append_float_length(Char *&, T) {}
+    void append_float_length(Char *&, T)
+    {}
 
     template <typename Impl, typename Char_>
     friend class internal::ArgFormatterBase;
@@ -2692,7 +2795,8 @@ protected:
     /**
     Constructs a ``BasicWriter`` object.
     */
-    explicit BasicWriter(Buffer<Char> &b) : buffer_(b) {}
+    explicit BasicWriter(Buffer<Char> &b): buffer_(b)
+    {}
 
 public:
     /**
@@ -2700,7 +2804,8 @@ public:
     Destroys a ``BasicWriter`` object.
     \endrst
     */
-    virtual ~BasicWriter() {}
+    virtual ~BasicWriter()
+    {}
 
     /**
     Returns the total number of characters written.
@@ -2876,7 +2981,10 @@ public:
         return *this;
     }
 
-    void clear() FMT_NOEXCEPT { buffer_.clear(); }
+    void clear() FMT_NOEXCEPT
+    {
+        buffer_.clear();
+    }
 };
 
 template <typename Char>
@@ -2930,9 +3038,9 @@ void BasicWriter<Char>::write_str(
             return;
         }
     }
-    std::size_t precision = spec.precision_;
+    std::size_t precision = static_cast<std::size_t>(spec.precision_);
     if (spec.precision_ >= 0 && precision < str_size)
-        str_size = spec.precision_;
+        str_size = precision;
     write_str(str_value, str_size, spec);
 }
 
@@ -2969,7 +3077,8 @@ BasicWriter<Char>::prepare_int_buffer(
         // is specified.
         if (prefix_size > 0 && prefix[prefix_size - 1] == '0')
             --prefix_size;
-        unsigned number_size = prefix_size + spec.precision();
+        unsigned number_size =
+            prefix_size + internal::to_unsigned(spec.precision());
         AlignSpec subspec(number_size, '0', ALIGN_NUMERIC);
         if (number_size >= width)
             return prepare_int_buffer(num_digits, subspec, prefix, prefix_size);
@@ -3036,7 +3145,7 @@ void BasicWriter<Char>::write_int(T value, Spec spec)
 {
     unsigned prefix_size = 0;
     typedef typename internal::IntTraits<T>::MainType UnsignedType;
-    UnsignedType abs_value = value;
+    UnsignedType abs_value = static_cast<UnsignedType>(value);
     char prefix[4] = "";
     if (internal::is_negative(value))
     {
@@ -3140,8 +3249,7 @@ void BasicWriter<Char>::write_int(T value, Spec spec)
 
 template <typename Char>
 template <typename T>
-void BasicWriter<Char>::write_double(
-    T value, const FormatSpec &spec)
+void BasicWriter<Char>::write_double(T value, const FormatSpec &spec)
 {
     // Check type.
     char type = spec.type();
@@ -3230,7 +3338,10 @@ void BasicWriter<Char>::write_double(
     }
 
     // Build format string.
-    enum { MAX_FORMAT_SIZE = 10 }; // longest format: %#-*.*Lg
+    enum
+    {
+        MAX_FORMAT_SIZE = 10
+    }; // longest format: %#-*.*Lg
     Char format[MAX_FORMAT_SIZE];
     Char *format_ptr = format;
     *format_ptr++ = '%';
@@ -3260,6 +3371,8 @@ void BasicWriter<Char>::write_double(
 
     // Format using snprintf.
     Char fill = internal::CharTraits<Char>::cast(spec.fill());
+    unsigned n = 0;
+    Char *start = 0;
     for (;;)
     {
         std::size_t buffer_size = buffer_.capacity() - offset;
@@ -3273,48 +3386,53 @@ void BasicWriter<Char>::write_double(
             buffer_size = buffer_.capacity() - offset;
         }
 #endif
-        Char *start = &buffer_[offset];
-        int n = internal::CharTraits<Char>::format_float(
-                    start, buffer_size, format, width_for_sprintf, spec.precision(), value);
-        if (n >= 0 && offset + n < buffer_.capacity())
+        start = &buffer_[offset];
+        int result = internal::CharTraits<Char>::format_float(
+                         start, buffer_size, format, width_for_sprintf, spec.precision(), value);
+        if (result >= 0)
         {
-            if (sign)
-            {
-                if ((spec.align() != ALIGN_RIGHT && spec.align() != ALIGN_DEFAULT) ||
-                        *start != ' ')
-                {
-                    *(start - 1) = sign;
-                    sign = 0;
-                }
-                else
-                {
-                    *(start - 1) = fill;
-                }
-                ++n;
-            }
-            if (spec.align() == ALIGN_CENTER &&
-                    spec.width() > static_cast<unsigned>(n))
-            {
-                width = spec.width();
-                CharPtr p = grow_buffer(width);
-                std::memmove(get(p) + (width - n) / 2, get(p), n * sizeof(Char));
-                fill_padding(p, spec.width(), n, fill);
-                return;
-            }
-            if (spec.fill() != ' ' || sign)
-            {
-                while (*start == ' ')
-                    *start++ = fill;
-                if (sign)
-                    *(start - 1) = sign;
-            }
-            grow_buffer(n);
-            return;
+            n = internal::to_unsigned(result);
+            if (offset + n < buffer_.capacity())
+                break;  // The buffer is large enough - continue with formatting.
+            buffer_.reserve(offset + n + 1);
+        }
+        else
+        {
+            // If result is negative we ask to increase the capacity by at least 1,
+            // but as std::vector, the buffer grows exponentially.
+            buffer_.reserve(buffer_.capacity() + 1);
         }
-        // If n is negative we ask to increase the capacity by at least 1,
-        // but as std::vector, the buffer grows exponentially.
-        buffer_.reserve(n >= 0 ? offset + n + 1 : buffer_.capacity() + 1);
     }
+    if (sign)
+    {
+        if ((spec.align() != ALIGN_RIGHT && spec.align() != ALIGN_DEFAULT) ||
+                *start != ' ')
+        {
+            *(start - 1) = sign;
+            sign = 0;
+        }
+        else
+        {
+            *(start - 1) = fill;
+        }
+        ++n;
+    }
+    if (spec.align() == ALIGN_CENTER && spec.width() > n)
+    {
+        width = spec.width();
+        CharPtr p = grow_buffer(width);
+        std::memmove(get(p) + (width - n) / 2, get(p), n * sizeof(Char));
+        fill_padding(p, spec.width(), n, fill);
+        return;
+    }
+    if (spec.fill() != ' ' || sign)
+    {
+        while (*start == ' ')
+            *start++ = fill;
+        if (sign)
+            *(start - 1) = sign;
+    }
+    grow_buffer(n);
 }
 
 /**
@@ -3352,14 +3470,15 @@ accessed as a C string with ``out.c_str()``.
 \endrst
 */
 template <typename Char, typename Allocator = std::allocator<Char> >
-class BasicMemoryWriter : public BasicWriter<Char>
+class BasicMemoryWriter: public BasicWriter<Char>
 {
 private:
     internal::MemoryBuffer<Char, internal::INLINE_BUFFER_SIZE, Allocator> buffer_;
 
 public:
     explicit BasicMemoryWriter(const Allocator& alloc = Allocator())
-        : BasicWriter<Char>(buffer_), buffer_(alloc) {}
+        : BasicWriter<Char>(buffer_), buffer_(alloc)
+    {}
 
 #if FMT_USE_RVALUE_REFERENCES
     /**
@@ -3370,8 +3489,7 @@ public:
     */
     BasicMemoryWriter(BasicMemoryWriter &&other)
         : BasicWriter<Char>(buffer_), buffer_(std::move(other.buffer_))
-    {
-    }
+    {}
 
     /**
     \rst
@@ -3410,7 +3528,7 @@ You can use one of the following typedefs for common character types:
 \endrst
 */
 template <typename Char>
-class BasicArrayWriter : public BasicWriter<Char>
+class BasicArrayWriter: public BasicWriter<Char>
 {
 private:
     internal::FixedBuffer<Char> buffer_;
@@ -3423,7 +3541,8 @@ public:
     \endrst
     */
     BasicArrayWriter(Char *array, std::size_t size)
-        : BasicWriter<Char>(buffer_), buffer_(array, size) {}
+        : BasicWriter<Char>(buffer_), buffer_(array, size)
+    {}
 
     /**
     \rst
@@ -3433,7 +3552,8 @@ public:
     */
     template <std::size_t SIZE>
     explicit BasicArrayWriter(Char(&array)[SIZE])
-        : BasicWriter<Char>(buffer_), buffer_(array, SIZE) {}
+        : BasicWriter<Char>(buffer_), buffer_(array, SIZE)
+    {}
 };
 
 typedef BasicArrayWriter<char> ArrayWriter;
@@ -3450,10 +3570,8 @@ void format(BasicFormatter<Char> &f, const Char *&format_str, const T &value)
     output << value;
 
     BasicStringRef<Char> str(&buffer[0], format_buf.size());
-    typedef internal::MakeValue< BasicFormatter<Char> > MakeValue;
-    internal::Arg arg = MakeValue(str);
-    arg.type = static_cast<internal::Arg::Type>(MakeValue::type(str));
-    format_str = f.format(format_str, arg);
+    typedef internal::MakeArg< BasicFormatter<Char> > MakeArg;
+    format_str = f.format(format_str, MakeArg(str));
 }
 
 // Reports a system error without throwing an exception.
@@ -3464,7 +3582,7 @@ FMT_API void report_system_error(int error_code,
 #if FMT_USE_WINDOWS_H
 
 /** A Windows error. */
-class WindowsError : public SystemError
+class WindowsError: public SystemError
 {
 private:
     FMT_API void init(int error_code, CStringRef format_str, ArgList args);
@@ -3512,7 +3630,10 @@ FMT_API void report_windows_error(int error_code,
 
 #endif
 
-enum Color { BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE };
+enum Color
+{
+    BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE
+};
 
 /**
 Formats a string and prints it to stdout using ANSI escape sequences
@@ -3629,7 +3750,10 @@ class FormatInt
 private:
     // Buffer should be large enough to hold all digits (digits10 + 1),
     // a sign and a null character.
-    enum { BUFFER_SIZE = std::numeric_limits<ULongLong>::digits10 + 3 };
+    enum
+    {
+        BUFFER_SIZE = std::numeric_limits<ULongLong>::digits10 + 3
+    };
     mutable char buffer_[BUFFER_SIZE];
     char *str_;
 
@@ -3682,16 +3806,17 @@ public:
     {
         FormatSigned(value);
     }
-    explicit FormatInt(unsigned value) : str_(format_decimal(value)) {}
-    explicit FormatInt(unsigned long value) : str_(format_decimal(value)) {}
-    explicit FormatInt(ULongLong value) : str_(format_decimal(value)) {}
+    explicit FormatInt(unsigned value): str_(format_decimal(value))
+    {}
+    explicit FormatInt(unsigned long value): str_(format_decimal(value))
+    {}
+    explicit FormatInt(ULongLong value): str_(format_decimal(value))
+    {}
 
-    /**
-    Returns the number of characters written to the output buffer.
-    */
+    /** Returns the number of characters written to the output buffer. */
     std::size_t size() const
     {
-        return buffer_ - str_ + BUFFER_SIZE - 1;
+        return internal::to_unsigned(buffer_ - str_ + BUFFER_SIZE - 1);
     }
 
     /**
@@ -3730,7 +3855,8 @@ public:
 template <typename T>
 inline void format_decimal(char *&buffer, T value)
 {
-    typename internal::IntTraits<T>::MainType abs_value = value;
+    typedef typename internal::IntTraits<T>::MainType MainType;
+    MainType abs_value = static_cast<MainType>(value);
     if (internal::is_negative(value))
     {
         *buffer++ = '-';
@@ -3815,10 +3941,11 @@ void arg(WStringRef, const internal::NamedArg<Char>&) FMT_DELETED_OR_UNDEFINED;
   template <typename... Args> \
   ReturnType func(FMT_FOR_EACH(FMT_ADD_ARG_NAME, __VA_ARGS__), \
       const Args & ... args) { \
-    typename fmt::internal::ArgArray<sizeof...(Args)>::Type array; \
+    typedef fmt::internal::ArgArray<sizeof...(Args)> ArgArray; \
+    typename ArgArray::Type array{ \
+      ArgArray::template make<fmt::BasicFormatter<Char> >(args)...}; \
     call(FMT_FOR_EACH(FMT_GET_ARG_NAME, __VA_ARGS__), \
-      fmt::internal::make_arg_list< \
-        fmt::BasicFormatter<Char> >(array, args...)); \
+      fmt::ArgList(fmt::internal::make_type(args...), array)); \
   }
 #else
 // Defines a wrapper for a function taking __VA_ARGS__ arguments
@@ -3934,6 +4061,18 @@ print(cerr, "Don't {}!", "panic");
 */
 FMT_API void print(std::ostream &os, CStringRef format_str, ArgList args);
 FMT_VARIADIC(void, print, std::ostream &, CStringRef)
+
+/**
+\rst
+Prints formatted data to the stream *os*.
+
+**Example**::
+
+fprintf(cerr, "Don't %s!", "panic");
+\endrst
+*/
+FMT_API int fprintf(std::ostream &os, CStringRef format_str, ArgList args);
+FMT_VARIADIC(int, fprintf, std::ostream &, CStringRef)
 #endif
 
 namespace internal
@@ -3947,7 +4086,7 @@ inline bool is_name_start(Char c)
 // Parses an unsigned integer advancing s to the end of the parsed input.
 // This function assumes that the first character of s is a digit.
 template <typename Char>
-int parse_nonnegative_int(const Char *&s)
+unsigned parse_nonnegative_int(const Char *&s)
 {
     assert('0' <= *s && *s <= '9');
     unsigned value = 0;
@@ -3994,8 +4133,8 @@ void check_sign(const Char *&s, const Arg &arg)
 }
 }  // namespace internal
 
-template <typename Char>
-inline internal::Arg BasicFormatter<Char>::get_arg(
+template <typename Char, typename AF>
+inline internal::Arg BasicFormatter<Char, AF>::get_arg(
     BasicStringRef<Char> arg_name, const char *&error)
 {
     if (check_no_auto_index(error))
@@ -4009,8 +4148,8 @@ inline internal::Arg BasicFormatter<Char>::get_arg(
     return internal::Arg();
 }
 
-template <typename Char>
-inline internal::Arg BasicFormatter<Char>::parse_arg_index(const Char *&s)
+template <typename Char, typename AF>
+inline internal::Arg BasicFormatter<Char, AF>::parse_arg_index(const Char *&s)
 {
     const char *error = 0;
     internal::Arg arg = *s < '0' || *s > '9' ?
@@ -4023,8 +4162,8 @@ inline internal::Arg BasicFormatter<Char>::parse_arg_index(const Char *&s)
     return arg;
 }
 
-template <typename Char>
-inline internal::Arg BasicFormatter<Char>::parse_arg_name(const Char *&s)
+template <typename Char, typename AF>
+inline internal::Arg BasicFormatter<Char, AF>::parse_arg_name(const Char *&s)
 {
     assert(internal::is_name_start(*s));
     const Char *start = s;
@@ -4041,9 +4180,8 @@ inline internal::Arg BasicFormatter<Char>::parse_arg_name(const Char *&s)
     return arg;
 }
 
-// Should be after FormatSpec
-template <typename Char>
-const Char *BasicFormatter<Char>::format(
+template <typename Char, typename ArgFormatter>
+const Char *BasicFormatter<Char, ArgFormatter>::format(
     const Char *&format_str, const internal::Arg &arg)
 {
     using internal::Arg;
@@ -4233,12 +4371,12 @@ const Char *BasicFormatter<Char>::format(
         FMT_THROW(FormatError("missing '}' in format string"));
 
     // Format argument.
-    internal::BasicArgFormatter<Char>(*this, spec, s - 1).visit(arg);
+    ArgFormatter(*this, spec, s - 1).visit(arg);
     return s;
 }
 
-template <typename Char>
-void BasicFormatter<Char>::format(BasicCStringRef<Char> format_str)
+template <typename Char, typename AF>
+void BasicFormatter<Char, AF>::format(BasicCStringRef<Char> format_str)
 {
     const Char *s = format_str.c_str();
     const Char *start = s;
@@ -4358,4 +4496,5 @@ operator"" _a(const wchar_t *s, std::size_t)
 # include "format.cc"
 #endif
 
-#endif  // FMT_FORMAT_H_
\ No newline at end of file
+#endif  // FMT_FORMAT_H_
+
diff --git a/include/spdlog/details/logger_impl.h b/include/spdlog/details/logger_impl.h
index c096382..9f2f13d 100644
--- a/include/spdlog/details/logger_impl.h
+++ b/include/spdlog/details/logger_impl.h
@@ -7,7 +7,6 @@
 
 #include <spdlog/logger.h>
 
-#include <atomic>
 #include <memory>
 #include <string>
 
@@ -22,6 +21,7 @@ inline spdlog::logger::logger(const std::string& logger_name, const It& begin, c
 
     // no support under vs2013 for member initialization for std::atomic
     _level = level::info;
+    _flush_level = level::off;
 }
 
 // ctor with sinks as init list
@@ -267,6 +267,11 @@ inline void spdlog::logger::set_level(spdlog::level::level_enum log_level)
     _level.store(log_level);
 }
 
+inline void spdlog::logger::flush_on(level::level_enum log_level)
+{
+    _flush_level.store(log_level);
+}
+
 inline spdlog::level::level_enum spdlog::logger::level() const
 {
     return static_cast<spdlog::level::level_enum>(_level.load(std::memory_order_relaxed));
@@ -285,6 +290,10 @@ inline void spdlog::logger::_log_msg(details::log_msg& msg)
     _formatter->format(msg);
     for (auto &sink : _sinks)
         sink->log(msg);
+
+    const auto flush_level = _flush_level.load(std::memory_order_relaxed);
+    if (msg.level >= flush_level)
+        flush();
 }
 
 inline void spdlog::logger::_set_pattern(const std::string& pattern)
diff --git a/include/spdlog/details/null_mutex.h b/include/spdlog/details/null_mutex.h
index 19e90bf..67b0aee 100644
--- a/include/spdlog/details/null_mutex.h
+++ b/include/spdlog/details/null_mutex.h
@@ -5,7 +5,8 @@
 
 #pragma once
 
-// null, no cost mutex
+#include <atomic>
+// null, no cost dummy "mutex" and dummy "atomic" int
 
 namespace spdlog
 {
@@ -20,5 +21,25 @@ struct null_mutex
         return true;
     }
 };
+
+struct null_atomic_int
+{
+    int value;
+    null_atomic_int() = default;
+
+    null_atomic_int(int val):value(val)
+    {}
+
+    int load(std::memory_order) const
+    {
+        return value;
+    }
+
+    void store(int val)
+    {
+        value = val;
+    }
+};
+
 }
 }
diff --git a/include/spdlog/details/os.h b/include/spdlog/details/os.h
index ac05a3b..4567fca 100644
--- a/include/spdlog/details/os.h
+++ b/include/spdlog/details/os.h
@@ -12,10 +12,15 @@
 #include <string>
 
 #ifdef _WIN32
-# ifndef WIN32_LEAN_AND_MEAN
-#  define WIN32_LEAN_AND_MEAN
-# endif
-# include <windows.h>
+
+#ifndef NOMINMAX
+#define NOMINMAX //prevent windows redefining min/max
+#endif
+
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#endif
+#include <windows.h>
 
 #ifdef __MINGW32__
 #include <share.h>
@@ -132,24 +137,49 @@ constexpr inline unsigned short eol_size()
 #endif
 
 //fopen_s on non windows for writing
-inline int fopen_s(FILE** fp, const std::string& filename, const char* mode)
+inline int fopen_s(FILE** fp, const filename_t& filename, const filename_t& mode)
 {
 #ifdef _WIN32
-    *fp = _fsopen((filename.c_str()), mode, _SH_DENYWR);
+#ifdef SPDLOG_WCHAR_FILENAMES
+    *fp = _wfsopen((filename.c_str()), mode.c_str(), _SH_DENYWR);
+#else
+    *fp = _fsopen((filename.c_str()), mode.c_str(), _SH_DENYWR);
+#endif
     return *fp == nullptr;
 #else
-    *fp = fopen((filename.c_str()), mode);
+    *fp = fopen((filename.c_str()), mode.c_str());
     return *fp == nullptr;
 #endif
+}
 
+inline int remove(const filename_t &filename)
+{
+#if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES)
+    return _wremove(filename.c_str());
+#else
+    return std::remove(filename.c_str());
+#endif
+}
+
+inline int rename(const filename_t& filename1, const filename_t& filename2)
+{
+#if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES)
+    return _wrename(filename1.c_str(), filename2.c_str());
+#else
+    return std::rename(filename1.c_str(), filename2.c_str());
+#endif
 }
 
 
 //Return if file exists
-inline bool file_exists(const std::string& filename)
+inline bool file_exists(const filename_t& filename)
 {
 #ifdef _WIN32
+#ifdef SPDLOG_WCHAR_FILENAMES
+    auto attribs = GetFileAttributesW(filename.c_str());
+#else
     auto attribs = GetFileAttributesA(filename.c_str());
+#endif
     return (attribs != INVALID_FILE_ATTRIBUTES && !(attribs & FILE_ATTRIBUTE_DIRECTORY));
 #elif __linux__
     struct stat buffer;
@@ -164,7 +194,6 @@ inline bool file_exists(const std::string& filename)
     return false;
 
 #endif
-
 }
 
 //Return utc offset in minutes or throw spdlog_ex on failure
diff --git a/include/spdlog/details/pattern_formatter_impl.h b/include/spdlog/details/pattern_formatter_impl.h
index 3965b83..6a33754 100644
--- a/include/spdlog/details/pattern_formatter_impl.h
+++ b/include/spdlog/details/pattern_formatter_impl.h
@@ -619,7 +619,11 @@ inline void spdlog::pattern_formatter::format(details::log_msg& msg)
             f->format(msg, tm_time);
         }
         //write eol
+#if defined(SPDLOG_EOL)
+        msg.formatted << SPDLOG_EOL;
+#else
         msg.formatted << details::os::eol();
+#endif
     }
     catch(const fmt::FormatError& e)
     {
diff --git a/include/spdlog/details/registry.h b/include/spdlog/details/registry.h
index 78a47fe..7d744f8 100644
--- a/include/spdlog/details/registry.h
+++ b/include/spdlog/details/registry.h
@@ -33,9 +33,9 @@ public:
     void register_logger(std::shared_ptr<logger> logger)
     {
         std::lock_guard<Mutex> lock(_mutex);
-		auto logger_name = logger->name();
-		throw_if_exists(logger_name);		
-		_loggers[logger_name] = logger;
+        auto logger_name = logger->name();
+        throw_if_exists(logger_name);
+        _loggers[logger_name] = logger;
     }
 
 
@@ -48,12 +48,12 @@ public:
 
     template<class It>
     std::shared_ptr<logger> create(const std::string& logger_name, const It& sinks_begin, const It& sinks_end)
-    {        
+    {
         std::lock_guard<Mutex> lock(_mutex);
-		throw_if_exists(logger_name);
-		std::shared_ptr<logger> new_logger;
+        throw_if_exists(logger_name);
+        std::shared_ptr<logger> new_logger;
         if (_async_mode)
-            new_logger = std::make_shared<async_logger>(logger_name, sinks_begin, sinks_end, _async_q_size, _overflow_policy, _worker_warmup_cb, _flush_interval_ms);
+            new_logger = std::make_shared<async_logger>(logger_name, sinks_begin, sinks_end, _async_q_size, _overflow_policy, _worker_warmup_cb, _flush_interval_ms, _worker_teardown_cb);
         else
             new_logger = std::make_shared<logger>(logger_name, sinks_begin, sinks_end);
 
@@ -61,8 +61,8 @@ public:
             new_logger->set_formatter(_formatter);
 
         new_logger->set_level(_level);
-		//Add to registry
-		_loggers[logger_name] = new_logger;
+        //Add to registry
+        _loggers[logger_name] = new_logger;
         return new_logger;
     }
 
@@ -112,7 +112,7 @@ public:
         _level = log_level;
     }
 
-    void set_async_mode(size_t q_size, const async_overflow_policy overflow_policy, const std::function<void()>& worker_warmup_cb, const std::chrono::milliseconds& flush_interval_ms)
+    void set_async_mode(size_t q_size, const async_overflow_policy overflow_policy, const std::function<void()>& worker_warmup_cb, const std::chrono::milliseconds& flush_interval_ms, const std::function<void()>& worker_teardown_cb)
     {
         std::lock_guard<Mutex> lock(_mutex);
         _async_mode = true;
@@ -120,6 +120,7 @@ public:
         _overflow_policy = overflow_policy;
         _worker_warmup_cb = worker_warmup_cb;
         _flush_interval_ms = flush_interval_ms;
+        _worker_teardown_cb = worker_teardown_cb;
     }
 
     void set_sync_mode()
@@ -134,16 +135,16 @@ public:
         return s_instance;
     }
 
-private:    
+private:
     registry_t<Mutex>() {}
     registry_t<Mutex>(const registry_t<Mutex>&) = delete;
     registry_t<Mutex>& operator=(const registry_t<Mutex>&) = delete;
 
-	void throw_if_exists(const std::string &logger_name)
-	{
-		if (_loggers.find(logger_name) != _loggers.end())
-			throw spdlog_ex("logger with name '" + logger_name + "' already exists");
-	}
+    void throw_if_exists(const std::string &logger_name)
+    {
+        if (_loggers.find(logger_name) != _loggers.end())
+            throw spdlog_ex("logger with name '" + logger_name + "' already exists");
+    }
     Mutex _mutex;
     std::unordered_map <std::string, std::shared_ptr<logger>> _loggers;
     formatter_ptr _formatter;
@@ -153,6 +154,7 @@ private:
     async_overflow_policy _overflow_policy = async_overflow_policy::block_retry;
     std::function<void()> _worker_warmup_cb = nullptr;
     std::chrono::milliseconds _flush_interval_ms;
+    std::function<void()> _worker_teardown_cb = nullptr;
 };
 #ifdef SPDLOG_NO_REGISTRY_MUTEX
 typedef registry_t<spdlog::details::null_mutex> registry;
diff --git a/include/spdlog/details/spdlog_impl.h b/include/spdlog/details/spdlog_impl.h
index e3c966d..8337ab4 100644
--- a/include/spdlog/details/spdlog_impl.h
+++ b/include/spdlog/details/spdlog_impl.h
@@ -13,6 +13,7 @@
 #include <spdlog/sinks/file_sinks.h>
 #include <spdlog/sinks/stdout_sinks.h>
 #include <spdlog/sinks/syslog_sink.h>
+#include <spdlog/sinks/ansicolor_sink.h>
 
 #include <chrono>
 #include <functional>
@@ -35,46 +36,53 @@ inline void spdlog::drop(const std::string &name)
 }
 
 // Create multi/single threaded rotating file logger
-inline std::shared_ptr<spdlog::logger> spdlog::rotating_logger_mt(const std::string& logger_name, const std::string& filename, size_t max_file_size, size_t max_files, bool force_flush)
+inline std::shared_ptr<spdlog::logger> spdlog::rotating_logger_mt(const std::string& logger_name, const filename_t& filename, size_t max_file_size, size_t max_files, bool force_flush)
 {
-    return create<spdlog::sinks::rotating_file_sink_mt>(logger_name, filename, "txt", max_file_size, max_files, force_flush);
+    return create<spdlog::sinks::rotating_file_sink_mt>(logger_name, filename, SPDLOG_FILENAME_T("txt"), max_file_size, max_files, force_flush);
 }
 
-inline std::shared_ptr<spdlog::logger> spdlog::rotating_logger_st(const std::string& logger_name, const std::string& filename, size_t max_file_size, size_t max_files, bool force_flush)
+inline std::shared_ptr<spdlog::logger> spdlog::rotating_logger_st(const std::string& logger_name, const filename_t& filename, size_t max_file_size, size_t max_files, bool force_flush)
 {
-    return create<spdlog::sinks::rotating_file_sink_st>(logger_name, filename, "txt", max_file_size, max_files, force_flush);
+    return create<spdlog::sinks::rotating_file_sink_st>(logger_name, filename, SPDLOG_FILENAME_T("txt"), max_file_size, max_files, force_flush);
 }
 
 // Create file logger which creates new file at midnight):
-inline std::shared_ptr<spdlog::logger> spdlog::daily_logger_mt(const std::string& logger_name, const std::string& filename, int hour, int minute, bool force_flush)
+inline std::shared_ptr<spdlog::logger> spdlog::daily_logger_mt(const std::string& logger_name, const filename_t& filename, int hour, int minute, bool force_flush)
 {
-    return create<spdlog::sinks::daily_file_sink_mt>(logger_name, filename, "txt", hour, minute, force_flush);
+    return create<spdlog::sinks::daily_file_sink_mt>(logger_name, filename, SPDLOG_FILENAME_T("txt"), hour, minute, force_flush);
 }
-inline std::shared_ptr<spdlog::logger> spdlog::daily_logger_st(const std::string& logger_name, const std::string& filename, int hour, int minute, bool force_flush)
+
+inline std::shared_ptr<spdlog::logger> spdlog::daily_logger_st(const std::string& logger_name, const filename_t& filename, int hour, int minute, bool force_flush)
 {
-    return create<spdlog::sinks::daily_file_sink_st>(logger_name, filename, "txt", hour, minute, force_flush);
+    return create<spdlog::sinks::daily_file_sink_st>(logger_name, filename, SPDLOG_FILENAME_T("txt"), hour, minute, force_flush);
 }
 
+// Create stdout/stderr loggers (with optinal color support)
+inline std::shared_ptr<spdlog::logger> create_console_logger(const std::string& logger_name, spdlog::sink_ptr sink, bool color)
+{
+    if (color) //use color wrapper sink
+        sink = std::make_shared<spdlog::sinks::ansicolor_sink>(sink);
+    return spdlog::details::registry::instance().create(logger_name, sink);
+}
 
-// Create stdout/stderr loggers
-inline std::shared_ptr<spdlog::logger> spdlog::stdout_logger_mt(const std::string& logger_name)
+inline std::shared_ptr<spdlog::logger> spdlog::stdout_logger_mt(const std::string& logger_name, bool color)
 {
-    return details::registry::instance().create(logger_name, spdlog::sinks::stdout_sink_mt::instance());
+    return create_console_logger(logger_name, sinks::stdout_sink_mt::instance(), color);
 }
 
-inline std::shared_ptr<spdlog::logger> spdlog::stdout_logger_st(const std::string& logger_name)
+inline std::shared_ptr<spdlog::logger> spdlog::stdout_logger_st(const std::string& logger_name, bool color)
 {
-    return details::registry::instance().create(logger_name, spdlog::sinks::stdout_sink_st::instance());
+    return create_console_logger(logger_name, sinks::stdout_sink_st::instance(), color);
 }
 
-inline std::shared_ptr<spdlog::logger> spdlog::stderr_logger_mt(const std::string& logger_name)
+inline std::shared_ptr<spdlog::logger> spdlog::stderr_logger_mt(const std::string& logger_name, bool color)
 {
-    return details::registry::instance().create(logger_name, spdlog::sinks::stderr_sink_mt::instance());
+    return create_console_logger(logger_name, sinks::stderr_sink_mt::instance(), color);
 }
 
-inline std::shared_ptr<spdlog::logger> spdlog::stderr_logger_st(const std::string& logger_name)
+inline std::shared_ptr<spdlog::logger> spdlog::stderr_logger_st(const std::string& logger_name, bool color)
 {
-    return details::registry::instance().create(logger_name, spdlog::sinks::stderr_sink_st::instance());
+    return create_console_logger(logger_name, sinks::stderr_sink_st::instance(), color);
 }
 
 #if defined(__linux__) || defined(__APPLE__)
@@ -124,9 +132,9 @@ inline void spdlog::set_level(level::level_enum log_level)
 }
 
 
-inline void spdlog::set_async_mode(size_t queue_size, const async_overflow_policy overflow_policy, const std::function<void()>& worker_warmup_cb, const std::chrono::milliseconds& flush_interval_ms)
+inline void spdlog::set_async_mode(size_t queue_size, const async_overflow_policy overflow_policy, const std::function<void()>& worker_warmup_cb, const std::chrono::milliseconds& flush_interval_ms, const std::function<void()>& worker_teardown_cb)
 {
-    details::registry::instance().set_async_mode(queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms);
+    details::registry::instance().set_async_mode(queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb);
 }
 
 inline void spdlog::set_sync_mode()
@@ -138,4 +146,3 @@ inline void spdlog::drop_all()
 {
     details::registry::instance().drop_all();
 }
-
diff --git a/include/spdlog/logger.h b/include/spdlog/logger.h
index ebd2dd0..ca94e55 100644
--- a/include/spdlog/logger.h
+++ b/include/spdlog/logger.h
@@ -18,7 +18,6 @@
 
 #include <vector>
 #include <memory>
-#include <atomic>
 #include <string>
 
 namespace spdlog
@@ -42,6 +41,9 @@ public:
     const std::string& name() const;
     bool should_log(level::level_enum) const;
 
+    // automatically call flush() after a message of level log_level or higher is emitted
+    void flush_on(level::level_enum log_level);
+
     // logger.info(cppformat_string, arg1, arg2, arg3, ...) call style
     template <typename... Args> details::line_logger trace(const char* fmt, const Args&... args);
     template <typename... Args> details::line_logger debug(const char* fmt, const Args&... args);
@@ -104,8 +106,8 @@ protected:
     std::string _name;
     std::vector<sink_ptr> _sinks;
     formatter_ptr _formatter;
-    std::atomic_int _level;
-
+    spdlog::level_t _level;
+    spdlog::level_t _flush_level;
 };
 }
 
diff --git a/include/spdlog/sinks/ansicolor_sink.h b/include/spdlog/sinks/ansicolor_sink.h
new file mode 100644
index 0000000..664b259
--- /dev/null
+++ b/include/spdlog/sinks/ansicolor_sink.h
@@ -0,0 +1,115 @@
+//
+// Copyright(c) 2016 Kevin M. Godby (a modified version by spdlog).
+// Distributed under the MIT License (http://opensource.org/licenses/MIT)
+//
+
+#pragma once
+
+#include <spdlog/sinks/base_sink.h>
+#include <spdlog/common.h>
+
+#include <string>
+#include <map>
+
+namespace spdlog
+{
+namespace sinks
+{
+
+/**
+ * @brief The ansi_color_sink is a decorator around another sink and prefixes
+ * the output with an ANSI escape sequence color code depending on the severity
+ * of the message.
+ */
+class ansicolor_sink : public sink
+{
+public:
+    ansicolor_sink(sink_ptr wrapped_sink);
+    virtual ~ansicolor_sink();
+
+    ansicolor_sink(const ansicolor_sink& other) = delete;
+    ansicolor_sink& operator=(const ansicolor_sink& other) = delete;
+
+    virtual void log(const details::log_msg& msg) override;
+    virtual void flush() override;
+
+    void set_color(level::level_enum level, const std::string& color);
+
+    /// Formatting codes
+    const std::string reset      = "\033[00m";
+    const std::string bold       = "\033[1m";
+    const std::string dark       = "\033[2m";
+    const std::string underline  = "\033[4m";
+    const std::string blink      = "\033[5m";
+    const std::string reverse    = "\033[7m";
+    const std::string concealed  = "\033[8m";
+
+    // Foreground colors
+    const std::string grey       = "\033[30m";
+    const std::string red        = "\033[31m";
+    const std::string green      = "\033[32m";
+    const std::string yellow     = "\033[33m";
+    const std::string blue       = "\033[34m";
+    const std::string magenta    = "\033[35m";
+    const std::string cyan       = "\033[36m";
+    const std::string white      = "\033[37m";
+
+    /// Background colors
+    const std::string on_grey    = "\033[40m";
+    const std::string on_red     = "\033[41m";
+    const std::string on_green   = "\033[42m";
+    const std::string on_yellow  = "\033[43m";
+    const std::string on_blue    = "\033[44m";
+    const std::string on_magenta = "\033[45m";
+    const std::string on_cyan    = "\033[46m";
+    const std::string on_white   = "\033[47m";
+
+
+protected:
+    sink_ptr sink_;
+    std::map<level::level_enum, std::string> colors_;
+};
+
+inline ansicolor_sink::ansicolor_sink(sink_ptr wrapped_sink) : sink_(wrapped_sink)
+{
+    colors_[level::trace]    = cyan;
+    colors_[level::debug]    = cyan;
+    colors_[level::info]     = white;
+    colors_[level::notice]   = bold + white;
+    colors_[level::warn]     = bold + yellow;
+    colors_[level::err]      = red;
+    colors_[level::critical] = bold + red;
+    colors_[level::alert]    = bold + white + on_red;
+    colors_[level::emerg]    = bold + yellow + on_red;
+    colors_[level::off]      = reset;
+}
+
+inline void ansicolor_sink::log(const details::log_msg& msg)
+{
+    // Wrap the originally formatted message in color codes
+    const std::string& prefix = colors_[msg.level];
+    const std::string& s = msg.formatted.str();
+    const std::string& suffix = reset;
+    details::log_msg m;
+    m.formatted << prefix  << s << suffix;
+    sink_->log(m);
+}
+
+inline void ansicolor_sink::flush()
+{
+    sink_->flush();
+}
+
+inline void ansicolor_sink::set_color(level::level_enum level, const std::string& color)
+{
+    colors_[level] = color;
+}
+
+inline ansicolor_sink::~ansicolor_sink()
+{
+    flush();
+}
+
+} // namespace sinks
+} // namespace spdlog
+
diff --git a/include/spdlog/sinks/file_sinks.h b/include/spdlog/sinks/file_sinks.h
index c3d214f..e6fe44b 100644
--- a/include/spdlog/sinks/file_sinks.h
+++ b/include/spdlog/sinks/file_sinks.h
@@ -28,7 +28,7 @@ template<class Mutex>
 class simple_file_sink : public base_sink < Mutex >
 {
 public:
-    explicit simple_file_sink(const std::string &filename,
+    explicit simple_file_sink(const filename_t &filename,
                               bool force_flush = false) :
         _file_helper(force_flush)
     {
@@ -58,7 +58,7 @@ template<class Mutex>
 class rotating_file_sink : public base_sink < Mutex >
 {
 public:
-    rotating_file_sink(const std::string &base_filename, const std::string &extension,
+    rotating_file_sink(const filename_t &base_filename, const filename_t &extension,
                        std::size_t max_size, std::size_t max_files,
                        bool force_flush = false) :
         _base_filename(base_filename),
@@ -90,13 +90,13 @@ protected:
     }
 
 private:
-    static std::string calc_filename(const std::string& filename, std::size_t index, const std::string& extension)
+    static filename_t calc_filename(const filename_t& filename, std::size_t index, const filename_t& extension)
     {
-        fmt::MemoryWriter w;
+        std::conditional<std::is_same<filename_t::value_type, char>::value, fmt::MemoryWriter, fmt::WMemoryWriter>::type w;
         if (index)
-            w.write("{}.{}.{}", filename, index, extension);
+            w.write(SPDLOG_FILENAME_T("{}.{}.{}"), filename, index, extension);
         else
-            w.write("{}.{}", filename, extension);
+            w.write(SPDLOG_FILENAME_T("{}.{}"), filename, extension);
         return w.str();
     }
 
@@ -111,25 +111,25 @@ private:
         _file_helper.close();
         for (auto i = _max_files; i > 0; --i)
         {
-            std::string src = calc_filename(_base_filename, i - 1, _extension);
-            std::string target = calc_filename(_base_filename, i, _extension);
+            filename_t src = calc_filename(_base_filename, i - 1, _extension);
+            filename_t target = calc_filename(_base_filename, i, _extension);
 
             if (details::file_helper::file_exists(target))
             {
-                if (std::remove(target.c_str()) != 0)
+                if (details::os::remove(target) != 0)
                 {
-                    throw spdlog_ex("rotating_file_sink: failed removing " + target);
+                    throw spdlog_ex("rotating_file_sink: failed removing " + filename_to_str(target));
                 }
             }
-            if (details::file_helper::file_exists(src) && std::rename(src.c_str(), target.c_str()))
+            if (details::file_helper::file_exists(src) && details::os::rename(src, target))
             {
-                throw spdlog_ex("rotating_file_sink: failed renaming " + src + " to " + target);
+                throw spdlog_ex("rotating_file_sink: failed renaming " + filename_to_str(src) + " to " + filename_to_str(target));
             }
         }
         _file_helper.reopen(true);
     }
-    std::string _base_filename;
-    std::string _extension;
+    filename_t _base_filename;
+    filename_t _extension;
     std::size_t _max_size;
     std::size_t _max_files;
     std::size_t _current_size;
@@ -140,16 +140,46 @@ typedef rotating_file_sink<std::mutex> rotating_file_sink_mt;
 typedef rotating_file_sink<details::null_mutex>rotating_file_sink_st;
 
 /*
+* Default generator of daily log file names.
+*/
+struct default_daily_file_name_calculator
+{
+    //Create filename for the form basename.YYYY-MM-DD_hh-mm.extension
+    static filename_t calc_filename(const filename_t& basename, const filename_t& extension)
+    {
+        std::tm tm = spdlog::details::os::localtime();
+        std::conditional<std::is_same<filename_t::value_type, char>::value, fmt::MemoryWriter, fmt::WMemoryWriter>::type w;
+        w.write(SPDLOG_FILENAME_T("{}_{:04d}-{:02d}-{:02d}_{:02d}-{:02d}.{}"), basename, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, extension);
+        return w.str();
+    }
+};
+
+/*
+* Generator of daily log file names in format basename.YYYY-MM-DD.extension
+*/
+struct dateonly_daily_file_name_calculator
+{
+    //Create filename for the form basename.YYYY-MM-DD.extension
+    static filename_t calc_filename(const filename_t& basename, const filename_t& extension)
+    {
+        std::tm tm = spdlog::details::os::localtime();
+        std::conditional<std::is_same<filename_t::value_type, char>::value, fmt::MemoryWriter, fmt::WMemoryWriter>::type w;
+        w.write(SPDLOG_FILENAME_T("{}_{:04d}-{:02d}-{:02d}.{}"), basename, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, extension);
+        return w.str();
+    }
+};
+
+/*
 * Rotating file sink based on date. rotates at midnight
 */
-template<class Mutex>
+template<class Mutex, class FileNameCalc = default_daily_file_name_calculator>
 class daily_file_sink :public base_sink < Mutex >
 {
 public:
     //create daily file sink which rotates on given time
     daily_file_sink(
-        const std::string& base_filename,
-        const std::string& extension,
+        const filename_t& base_filename,
+        const filename_t& extension,
         int rotation_hour,
         int rotation_minute,
         bool force_flush = false) : _base_filename(base_filename),
@@ -161,7 +191,7 @@ public:
         if (rotation_hour < 0 || rotation_hour > 23 || rotation_minute < 0 || rotation_minute > 59)
             throw spdlog_ex("daily_file_sink: Invalid rotation time in ctor");
         _rotation_tp = _next_rotation_tp();
-        _file_helper.open(calc_filename(_base_filename, _extension));
+        _file_helper.open(FileNameCalc::calc_filename(_base_filename, _extension));
     }
 
     void flush() override
@@ -174,7 +204,7 @@ protected:
     {
         if (std::chrono::system_clock::now() >= _rotation_tp)
         {
-            _file_helper.open(calc_filename(_base_filename, _extension));
+            _file_helper.open(FileNameCalc::calc_filename(_base_filename, _extension));
             _rotation_tp = _next_rotation_tp();
         }
         _file_helper.write(msg);
@@ -197,17 +227,8 @@ private:
             return system_clock::time_point(rotation_time + hours(24));
     }
 
-    //Create filename for the form basename.YYYY-MM-DD.extension
-    static std::string calc_filename(const std::string& basename, const std::string& extension)
-    {
-        std::tm tm = spdlog::details::os::localtime();
-        fmt::MemoryWriter w;
-        w.write("{}_{:04d}-{:02d}-{:02d}_{:02d}-{:02d}.{}", basename, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, extension);
-        return w.str();
-    }
-
-    std::string _base_filename;
-    std::string _extension;
+    filename_t _base_filename;
+    filename_t _extension;
     int _rotation_h;
     int _rotation_m;
     std::chrono::system_clock::time_point _rotation_tp;
diff --git a/include/spdlog/sinks/msvc_sink.h b/include/spdlog/sinks/msvc_sink.h
index 9e101ad..16342ca 100644
--- a/include/spdlog/sinks/msvc_sink.h
+++ b/include/spdlog/sinks/msvc_sink.h
@@ -26,7 +26,7 @@ template<class Mutex>
 class msvc_sink : public base_sink < Mutex >
 {
 public:
-	explicit msvc_sink()
+    explicit msvc_sink()
     {
     }
 
@@ -37,7 +37,7 @@ public:
 protected:
     void _sink_it(const details::log_msg& msg) override
     {
-		OutputDebugStringA(msg.formatted.c_str());
+        OutputDebugStringA(msg.formatted.c_str());
     }
 };
 
diff --git a/include/spdlog/sinks/stdout_sinks.h b/include/spdlog/sinks/stdout_sinks.h
index 85db334..ca4c55a 100644
--- a/include/spdlog/sinks/stdout_sinks.h
+++ b/include/spdlog/sinks/stdout_sinks.h
@@ -5,10 +5,9 @@
 
 #pragma once
 
-#include <spdlog/sinks/ostream_sink.h>
 #include <spdlog/details/null_mutex.h>
 
-#include <iostream>
+#include <cstdio>
 #include <memory>
 #include <mutex>
 
@@ -18,16 +17,27 @@ namespace sinks
 {
 
 template <class Mutex>
-class stdout_sink : public ostream_sink<Mutex>
+class stdout_sink : public base_sink<Mutex>
 {
     using MyType = stdout_sink<Mutex>;
 public:
-    stdout_sink() : ostream_sink<Mutex>(std::cout, true) {}
+    stdout_sink() {}
     static std::shared_ptr<MyType> instance()
     {
         static std::shared_ptr<MyType> instance = std::make_shared<MyType>();
         return instance;
     }
+
+    void _sink_it(const details::log_msg& msg) override
+    {
+        fwrite(msg.formatted.data(), sizeof(char), msg.formatted.size(), stdout);
+        flush();
+    }
+
+    void flush() override
+    {
+        fflush(stdout);
+    }
 };
 
 typedef stdout_sink<details::null_mutex> stdout_sink_st;
@@ -35,17 +45,27 @@ typedef stdout_sink<std::mutex> stdout_sink_mt;
 
 
 template <class Mutex>
-class stderr_sink : public ostream_sink<Mutex>
+class stderr_sink : public base_sink<Mutex>
 {
     using MyType = stderr_sink<Mutex>;
 public:
-    stderr_sink() : ostream_sink<Mutex>(std::cerr, true) {}
+    stderr_sink() {}
     static std::shared_ptr<MyType> instance()
     {
         static std::shared_ptr<MyType> instance = std::make_shared<MyType>();
         return instance;
     }
 
+    void _sink_it(const details::log_msg& msg) override
+    {
+        fwrite(msg.formatted.data(), sizeof(char), msg.formatted.size(), stderr);
+        flush();
+    }
+
+    void flush() override
+    {
+        fflush(stderr);
+    }
 };
 
 typedef stderr_sink<std::mutex> stderr_sink_mt;
diff --git a/include/spdlog/spdlog.h b/include/spdlog/spdlog.h
index b92a239..2dc0209 100644
--- a/include/spdlog/spdlog.h
+++ b/include/spdlog/spdlog.h
@@ -53,7 +53,10 @@ void set_level(level::level_enum log_level);
 // worker_warmup_cb (optional):
 //     callback function that will be called in worker thread upon start (can be used to init stuff like thread affinity)
 //
-void set_async_mode(size_t queue_size, const async_overflow_policy overflow_policy = async_overflow_policy::block_retry, const std::function<void()>& worker_warmup_cb = nullptr, const std::chrono::milliseconds& flush_interval_ms = std::chrono::milliseconds::zero());
+// worker_teardown_cb (optional):
+//     callback function that will be called in worker thread upon exit
+//
+void set_async_mode(size_t queue_size, const async_overflow_policy overflow_policy = async_overflow_policy::block_retry, const std::function<void()>& worker_warmup_cb = nullptr, const std::chrono::milliseconds& flush_interval_ms = std::chrono::milliseconds::zero(), const std::function<void()>& worker_teardown_cb = nullptr);
 
 // Turn off async mode
 void set_sync_mode();
@@ -61,23 +64,22 @@ void set_sync_mode();
 //
 // Create and register multi/single threaded rotating file logger
 //
-std::shared_ptr<logger> rotating_logger_mt(const std::string& logger_name, const std::string& filenameB, size_t max_file_size, size_t max_files, bool force_flush = false);
-std::shared_ptr<logger> rotating_logger_st(const std::string& logger_name, const std::string& filename, size_t max_file_size, size_t max_files, bool force_flush = false);
+std::shared_ptr<logger> rotating_logger_mt(const std::string& logger_name, const filename_t& filename, size_t max_file_size, size_t max_files, bool force_flush = false);
+std::shared_ptr<logger> rotating_logger_st(const std::string& logger_name, const filename_t& filename, size_t max_file_size, size_t max_files, bool force_flush = false);
 
 //
 // Create file logger which creates new file on the given time (default in  midnight):
 //
-std::shared_ptr<logger> daily_logger_mt(const std::string& logger_name, const std::string& filename, int hour=0, int minute=0, bool force_flush = false);
-std::shared_ptr<logger> daily_logger_st(const std::string& logger_name, const std::string& filename, int hour=0, int minute=0, bool force_flush = false);
-
+std::shared_ptr<logger> daily_logger_mt(const std::string& logger_name, const filename_t& filename, int hour=0, int minute=0, bool force_flush = false);
+std::shared_ptr<logger> daily_logger_st(const std::string& logger_name, const filename_t& filename, int hour=0, int minute=0, bool force_flush = false);
 
 //
 // Create and register stdout/stderr loggers
 //
-std::shared_ptr<logger> stdout_logger_mt(const std::string& logger_name);
-std::shared_ptr<logger> stdout_logger_st(const std::string& logger_name);
-std::shared_ptr<logger> stderr_logger_mt(const std::string& logger_name);
-std::shared_ptr<logger> stderr_logger_st(const std::string& logger_name);
+std::shared_ptr<logger> stdout_logger_mt(const std::string& logger_name, bool color = false);
+std::shared_ptr<logger> stdout_logger_st(const std::string& logger_name, bool color = false);
+std::shared_ptr<logger> stderr_logger_mt(const std::string& logger_name, bool color = false);
+std::shared_ptr<logger> stderr_logger_st(const std::string& logger_name, bool color = false);
 
 
 //
diff --git a/include/spdlog/tweakme.h b/include/spdlog/tweakme.h
index f136514..8c0ccfa 100644
--- a/include/spdlog/tweakme.h
+++ b/include/spdlog/tweakme.h
@@ -51,3 +51,20 @@
 // Note that upon creating a logger the registry is modified by spdlog..
 // #define SPDLOG_NO_REGISTRY_MUTEX
 ///////////////////////////////////////////////////////////////////////////////
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Uncomment to avoid spdlog's usage of atomic log levels
+// Use only if your code never modifies a logger's log levels concurrently.
+// #define SPDLOG_NO_ATOMIC_LEVELS
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+// Uncomment to enable usage of wchar_t for file names on Windows.
+// #define SPDLOG_WCHAR_FILENAMES
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+// uncomment the below to override spdlog's default eol
+// #define SPDLOG_EOL "\n"
+///////////////////////////////////////////////////////////////////////////////
diff --git a/tests/Makefile b/tests/Makefile
index 0eec327..97871ba 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -1,22 +1,22 @@
-CXX	?= g++
-CXXFLAGS	=  -Wall  -pedantic -std=c++11 -pthread -O2 -I../include
-LDPFALGS = -pthread
-
-CPP_FILES := $(wildcard *.cpp)
-OBJ_FILES := $(addprefix ./,$(notdir $(CPP_FILES:.cpp=.o)))
-
-    
-tests: $(OBJ_FILES)    
-	$(CXX) $(CXXFLAGS) $(LDPFALGS) -o $@ $^
-	mkdir -p logs
-
-%.o: %.cpp
-	$(CXX) $(CXXFLAGS) -c -o $@ $<
-
-clean:
-	rm -f tests *.o logs/*.txt     
- 
-rebuild: clean tests
-
-
-
+CXX	?= g++
+CXXFLAGS	=  -Wall  -pedantic -std=c++11 -pthread -O2 -I../include
+LDPFALGS = -pthread
+
+CPP_FILES := $(wildcard *.cpp)
+OBJ_FILES := $(addprefix ./,$(notdir $(CPP_FILES:.cpp=.o)))
+
+    
+tests: $(OBJ_FILES)    
+	$(CXX) $(CXXFLAGS) $(LDPFALGS) -o $@ $^
+	mkdir -p logs
+
+%.o: %.cpp
+	$(CXX) $(CXXFLAGS) -c -o $@ $<
+
+clean:
+	rm -f tests *.o logs/*.txt     
+ 
+rebuild: clean tests
+
+
+
diff --git a/tests/file_helper.cpp b/tests/file_helper.cpp
index f57ab70..5f3574d 100644
--- a/tests/file_helper.cpp
+++ b/tests/file_helper.cpp
@@ -5,7 +5,7 @@
 
 using namespace spdlog::details;
 
-static const std::string filename = "logs/file_helper_test.txt";
+static const std::string target_filename = "logs/file_helper_test.txt";
 
 static void write_with_helper(file_helper &helper, size_t howmany)
 {
@@ -20,8 +20,8 @@ TEST_CASE("file_helper_filename", "[file_helper::filename()]]")
     prepare_logdir();
 
     file_helper helper(false);
-    helper.open(filename);
-    REQUIRE(helper.filename() == filename);
+    helper.open(target_filename);
+    REQUIRE(helper.filename() == target_filename);
 }
 
 
@@ -32,28 +32,28 @@ TEST_CASE("file_helper_size", "[file_helper::size()]]")
     auto expected_size = 123;
     {
         file_helper helper(true);
-        helper.open(filename);
+        helper.open(target_filename);
         write_with_helper(helper, expected_size);
         REQUIRE(helper.size() == expected_size);
     }
-    REQUIRE(get_filesize(filename) == expected_size);
+    REQUIRE(get_filesize(target_filename) == expected_size);
 }
 
 
 TEST_CASE("file_helper_exists", "[file_helper::file_exists()]]")
 {
     prepare_logdir();
-    REQUIRE(!file_helper::file_exists(filename));
+    REQUIRE(!file_helper::file_exists(target_filename));
     file_helper helper(false);
-    helper.open(filename);
-    REQUIRE(file_helper::file_exists(filename));
+    helper.open(target_filename);
+    REQUIRE(file_helper::file_exists(target_filename));
 }
 
 TEST_CASE("file_helper_reopen", "[file_helper::reopen()]]")
 {
     prepare_logdir();
     file_helper helper(true);
-    helper.open(filename);
+    helper.open(target_filename);
     write_with_helper(helper, 12);
     REQUIRE(helper.size() == 12);
     helper.reopen(true);
@@ -65,7 +65,7 @@ TEST_CASE("file_helper_reopen2", "[file_helper::reopen(false)]]")
     prepare_logdir();
     auto expected_size = 14;
     file_helper helper(true);
-    helper.open(filename);
+    helper.open(target_filename);
     write_with_helper(helper, expected_size);
     REQUIRE(helper.size() == expected_size);
     helper.reopen(false);
diff --git a/tests/file_log.cpp b/tests/file_log.cpp
index 2abd021..3eedbee 100644
--- a/tests/file_log.cpp
+++ b/tests/file_log.cpp
@@ -77,15 +77,56 @@ TEST_CASE("daily_logger", "[daily_logger]]")
 }
 
 
+TEST_CASE("daily_logger with dateonly calculator", "[daily_logger_dateonly]]")
+{
+    using sink_type = spdlog::sinks::daily_file_sink<
+        std::mutex,
+        spdlog::sinks::dateonly_daily_file_name_calculator>;
 
+    prepare_logdir();
+    //calculate filename (time based)
+    std::string basename = "logs/daily_dateonly";
+    std::tm tm = spdlog::details::os::localtime();
+    fmt::MemoryWriter w;
+    w.write("{}_{:04d}-{:02d}-{:02d}.txt", basename, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday);
 
+    auto logger = spdlog::create<sink_type>("logger", basename, "txt", 0, 0, true);
+    for (int i = 0; i < 10; ++i)
+        logger->info("Test message {}", i);
 
+    auto filename = w.str();
+    REQUIRE(count_lines(filename) == 10);
+}
 
+struct custom_daily_file_name_calculator
+{
+    static spdlog::filename_t calc_filename(const spdlog::filename_t& basename, const spdlog::filename_t& extension)
+    {
+        std::tm tm = spdlog::details::os::localtime();
+        fmt::MemoryWriter w;
+        w.write("{}{:04d}{:02d}{:02d}.{}", basename, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, extension);
+        return w.str();
+    }
+};
+
+TEST_CASE("daily_logger with custom calculator", "[daily_logger_custom]]")
+{
+    using sink_type = spdlog::sinks::daily_file_sink<
+        std::mutex,
+        custom_daily_file_name_calculator>;
 
+    prepare_logdir();
+    //calculate filename (time based)
+    std::string basename = "logs/daily_dateonly";
+    std::tm tm = spdlog::details::os::localtime();
+    fmt::MemoryWriter w;
+    w.write("{}{:04d}{:02d}{:02d}.txt", basename, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday);
 
+    auto logger = spdlog::create<sink_type>("logger", basename, "txt", 0, 0, true);
+    for (int i = 0; i < 10; ++i)
+        logger->info("Test message {}", i);
 
-
-
-
-
+    auto filename = w.str();
+    REQUIRE(count_lines(filename) == 10);
+}
 
diff --git a/tests/includes.h b/tests/includes.h
index 9cdee27..0590fc6 100644
--- a/tests/includes.h
+++ b/tests/includes.h
@@ -12,4 +12,5 @@
 
 #include "../include/spdlog/spdlog.h"
 #include "../include/spdlog/sinks/null_sink.h"
+#include "../include/spdlog/sinks/ostream_sink.h"
 
diff --git a/tests/tests.vcxproj b/tests/tests.vcxproj
index 56787c7..f05c162 100644
--- a/tests/tests.vcxproj
+++ b/tests/tests.vcxproj
@@ -1,141 +1,143 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{59A07559-5F38-4DD6-A7FA-DB4153690B42}</ProjectGuid>
-    <RootNamespace>tests</RootNamespace>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <PlatformToolset>v140</PlatformToolset>
-    <CharacterSet>MultiByte</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <PlatformToolset>v140</PlatformToolset>
-    <CharacterSet>MultiByte</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <PlatformToolset>v140</PlatformToolset>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>MultiByte</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <PlatformToolset>v140</PlatformToolset>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>MultiByte</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup />
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <SDLCheck>true</SDLCheck>
-    </ClCompile>
-    <Link>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <SubSystem>Console</SubSystem>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <SDLCheck>true</SDLCheck>
-      <PreprocessorDefinitions>_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>$(SolutionDir)..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <SubSystem>Console</SubSystem>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <WarningLevel>Level4</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <SDLCheck>true</SDLCheck>
-    </ClCompile>
-    <Link>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <SubSystem>Console</SubSystem>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <ClCompile>
-      <WarningLevel>Level4</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <SDLCheck>true</SDLCheck>
-      <PreprocessorDefinitions>_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>$(SolutionDir)..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <SubSystem>Console</SubSystem>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemGroup>
-    <ClCompile Include="file_helper.cpp" />
-    <ClCompile Include="file_log.cpp" />
-    <ClCompile Include="format.cpp" />
-    <ClCompile Include="main.cpp" />
-    <ClCompile Include="registry.cpp" />
-    <ClCompile Include="utils.cpp" />
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include="catch.hpp" />
-    <ClInclude Include="includes.h" />
-    <ClInclude Include="utils.h" />
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{59A07559-5F38-4DD6-A7FA-DB4153690B42}</ProjectGuid>
+    <RootNamespace>tests</RootNamespace>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v140</PlatformToolset>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v140</PlatformToolset>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v140</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v140</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup />
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <SDLCheck>true</SDLCheck>
+      <AdditionalIncludeDirectories>$(SolutionDir)\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ClCompile>
+    <Link>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Console</SubSystem>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <SDLCheck>true</SDLCheck>
+      <PreprocessorDefinitions>_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>$(SolutionDir)..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ClCompile>
+    <Link>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Console</SubSystem>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <WarningLevel>Level4</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <AdditionalIncludeDirectories>$(SolutionDir)\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ClCompile>
+    <Link>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+      <SubSystem>Console</SubSystem>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <WarningLevel>Level4</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <PreprocessorDefinitions>_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>$(SolutionDir)..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ClCompile>
+    <Link>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+      <SubSystem>Console</SubSystem>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="file_helper.cpp" />
+    <ClCompile Include="file_log.cpp" />
+    <ClCompile Include="format.cpp" />
+    <ClCompile Include="main.cpp" />
+    <ClCompile Include="registry.cpp" />
+    <ClCompile Include="utils.cpp" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="catch.hpp" />
+    <ClInclude Include="includes.h" />
+    <ClInclude Include="utils.h" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
 </Project>
\ No newline at end of file
diff --git a/tests/tests.vcxproj.filters b/tests/tests.vcxproj.filters
index 8a1a5d6..72ca548 100644
--- a/tests/tests.vcxproj.filters
+++ b/tests/tests.vcxproj.filters
@@ -1,48 +1,48 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <Filter Include="Source Files">
-      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
-      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
-    </Filter>
-    <Filter Include="Header Files">
-      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
-      <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
-    </Filter>
-    <Filter Include="Resource Files">
-      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
-      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
-    </Filter>
-  </ItemGroup>
-  <ItemGroup>
-    <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>
-    <ClCompile Include="registry.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="file_helper.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="utils.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include="includes.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="catch.hpp">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="utils.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-  </ItemGroup>
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <Filter Include="Source Files">
+      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+    </Filter>
+    <Filter Include="Header Files">
+      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+      <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
+    </Filter>
+    <Filter Include="Resource Files">
+      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <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>
+    <ClCompile Include="registry.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="file_helper.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="utils.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="includes.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="catch.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="utils.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+  </ItemGroup>
 </Project>
\ No newline at end of file
diff --git a/tests/utils.cpp b/tests/utils.cpp
index 83fdf84..751ff82 100644
--- a/tests/utils.cpp
+++ b/tests/utils.cpp
@@ -4,10 +4,11 @@ void prepare_logdir()
 {
     spdlog::drop_all();
 #ifdef _WIN32
-    system("del /F /Q logs\\*");
+    auto rv = system("del /F /Q logs\\*");
 #else
-    system("rm -f logs/*");
+    auto rv = system("rm -f logs/*");
 #endif
+    (void)rv;
 }
 
 
@@ -42,4 +43,3 @@ std::size_t get_filesize(const std::string& filename)
 
     return ifs.tellg();
 }
-

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-med/spdlog.git



More information about the debian-med-commit mailing list