diff --git a/vendor/README b/vendor/README index 7ca85751..5c4947b2 100644 --- a/vendor/README +++ b/vendor/README @@ -1,4 +1,4 @@ This directory contains external projects, taken from the following locations: scrypt: http://www.tarsnap.com/scrypt.html googletest: https://github.com/google/googletest/tree/release-1.8.0 -spdlog: https://github.com/gabime/spdlog/tree/v0.12.0/include/spdlog +spdlog: https://github.com/gabime/spdlog/tree/v0.13.0/include/spdlog diff --git a/vendor/spdlog/spdlog/async_logger.h b/vendor/spdlog/spdlog/async_logger.h index 1c42fd9c..76d70a3d 100644 --- a/vendor/spdlog/spdlog/async_logger.h +++ b/vendor/spdlog/spdlog/async_logger.h @@ -63,6 +63,11 @@ public: //Wait for the queue to be empty, and flush synchronously //Warning: this can potentialy last forever as we wait it to complete void flush() override; + + // Error handler + virtual void set_error_handler(log_err_handler) override; + virtual log_err_handler error_handler() override; + protected: void _sink_it(details::log_msg& msg) override; void _set_formatter(spdlog::formatter_ptr msg_formatter) override; diff --git a/vendor/spdlog/spdlog/details/async_log_helper.h b/vendor/spdlog/spdlog/details/async_log_helper.h index deb8dcc6..92a0f4cd 100644 --- a/vendor/spdlog/spdlog/details/async_log_helper.h +++ b/vendor/spdlog/spdlog/details/async_log_helper.h @@ -66,7 +66,7 @@ async_msg(async_msg&& other) SPDLOG_NOEXCEPT: msg_type(std::move(other.msg_type)) {} - async_msg(async_msg_type m_type) :msg_type(m_type) + async_msg(async_msg_type m_type):msg_type(m_type) {} async_msg& operator=(async_msg&& other) SPDLOG_NOEXCEPT @@ -85,7 +85,7 @@ async_msg(async_msg&& other) SPDLOG_NOEXCEPT: async_msg& operator=(const async_msg& other) = delete; // construct from log_msg - async_msg(const details::log_msg& m) : + async_msg(const details::log_msg& m): level(m.level), time(m.time), thread_id(m.thread_id), @@ -135,6 +135,7 @@ public: void flush(bool wait_for_q); + void set_error_handler(spdlog::log_err_handler err_handler); private: formatter_ptr _formatter; @@ -221,7 +222,8 @@ inline spdlog::details::async_log_helper::~async_log_helper() _worker_thread.join(); } catch (...) // don't crash in destructor - {} + { + } } @@ -250,28 +252,34 @@ inline void spdlog::details::async_log_helper::push_msg(details::async_log_helpe inline void spdlog::details::async_log_helper::flush(bool wait_for_q) { push_msg(async_msg(async_msg_type::flush)); - if(wait_for_q) + if (wait_for_q) wait_empty_q(); //return only make after the above flush message was processed } inline void spdlog::details::async_log_helper::worker_loop() { - try + if (_worker_warmup_cb) _worker_warmup_cb(); + auto last_pop = details::os::now(); + auto last_flush = last_pop; + auto active = true; + while (active) { - if (_worker_warmup_cb) _worker_warmup_cb(); - 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) - { - _err_handler(ex.what()); - } - catch (...) - { - _err_handler("Unknown exception"); + try + { + active = process_next_msg(last_pop, last_flush); + } + catch (const std::exception &ex) + { + _err_handler(ex.what()); + } + catch (...) + { + _err_handler("Unknown exception"); + } } + if (_worker_teardown_cb) _worker_teardown_cb(); + + } // process next message in the queue @@ -300,7 +308,7 @@ inline bool spdlog::details::async_log_helper::process_next_msg(log_clock::time_ _formatter->format(incoming_log_msg); for (auto &s : _sinks) { - if(s->should_log( incoming_log_msg.level)) + if (s->should_log(incoming_log_msg.level)) { s->log(incoming_log_msg); } @@ -374,5 +382,10 @@ inline void spdlog::details::async_log_helper::wait_empty_q() } } +inline void spdlog::details::async_log_helper::set_error_handler(spdlog::log_err_handler err_handler) +{ + _err_handler = err_handler; +} + diff --git a/vendor/spdlog/spdlog/details/async_logger_impl.h b/vendor/spdlog/spdlog/details/async_logger_impl.h index 2092f06c..487c628a 100644 --- a/vendor/spdlog/spdlog/details/async_logger_impl.h +++ b/vendor/spdlog/spdlog/details/async_logger_impl.h @@ -57,6 +57,19 @@ inline void spdlog::async_logger::flush() _async_log_helper->flush(true); } +// Error handler +inline void spdlog::async_logger::set_error_handler(spdlog::log_err_handler err_handler) +{ + _err_handler = err_handler; + _async_log_helper->set_error_handler(err_handler); + +} +inline spdlog::log_err_handler spdlog::async_logger::error_handler() +{ + return _err_handler; +} + + inline void spdlog::async_logger::_set_formatter(spdlog::formatter_ptr msg_formatter) { _formatter = msg_formatter; diff --git a/vendor/spdlog/spdlog/details/logger_impl.h b/vendor/spdlog/spdlog/details/logger_impl.h index 2b27f105..5bb85f67 100644 --- a/vendor/spdlog/spdlog/details/logger_impl.h +++ b/vendor/spdlog/spdlog/details/logger_impl.h @@ -121,44 +121,42 @@ inline void spdlog::logger::log(level::level_enum lvl, const T& msg) } -template -inline void spdlog::logger::trace(const char* fmt, const Args&... args) +template +inline void spdlog::logger::trace(const char* fmt, const Arg1 &arg1, const Args&... args) { - log(level::trace, fmt, args...); + log(level::trace, fmt, arg1, args...); } -template -inline void spdlog::logger::debug(const char* fmt, const Args&... args) +template +inline void spdlog::logger::debug(const char* fmt, const Arg1 &arg1, const Args&... args) { - log(level::debug, fmt, args...); + log(level::debug, fmt, arg1, args...); } -template -inline void spdlog::logger::info(const char* fmt, const Args&... args) +template +inline void spdlog::logger::info(const char* fmt, const Arg1 &arg1, const Args&... args) { - log(level::info, fmt, args...); + log(level::info, fmt, arg1, args...); } - -template -inline void spdlog::logger::warn(const char* fmt, const Args&... args) +template +inline void spdlog::logger::warn(const char* fmt, const Arg1 &arg1, const Args&... args) { - log(level::warn, fmt, args...); + log(level::warn, fmt, arg1, args...); } -template -inline void spdlog::logger::error(const char* fmt, const Args&... args) +template +inline void spdlog::logger::error(const char* fmt, const Arg1 &arg1, const Args&... args) { - log(level::err, fmt, args...); + log(level::err, fmt, arg1, args...); } -template -inline void spdlog::logger::critical(const char* fmt, const Args&... args) +template +inline void spdlog::logger::critical(const char* fmt, const Arg1 &arg1, const Args&... args) { - log(level::critical, fmt, args...); + log(level::critical, fmt, arg1, args...); } - template inline void spdlog::logger::trace(const T& msg) { diff --git a/vendor/spdlog/spdlog/details/pattern_formatter_impl.h b/vendor/spdlog/spdlog/details/pattern_formatter_impl.h index 2fefaa3c..70b9dc80 100644 --- a/vendor/spdlog/spdlog/details/pattern_formatter_impl.h +++ b/vendor/spdlog/spdlog/details/pattern_formatter_impl.h @@ -82,7 +82,7 @@ static int to12h(const tm& t) using days_array = std::array; static const days_array& days() { - static const days_array arr{ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; + static const days_array arr{ { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" } }; return arr; } class a_formatter:public flag_formatter @@ -96,7 +96,7 @@ class a_formatter:public flag_formatter //Full weekday name static const days_array& full_days() { - static const days_array arr{ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" }; + static const days_array arr{ { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" } }; return arr; } class A_formatter:public flag_formatter @@ -111,7 +111,7 @@ class A_formatter:public flag_formatter using months_array = std::array; static const months_array& months() { - static const months_array arr{ "Jan", "Feb", "Mar", "Apr", "May", "June", "July", "Aug", "Sept", "Oct", "Nov", "Dec" }; + static const months_array arr{ { "Jan", "Feb", "Mar", "Apr", "May", "June", "July", "Aug", "Sept", "Oct", "Nov", "Dec" } }; return arr; } class b_formatter:public flag_formatter @@ -125,7 +125,7 @@ class b_formatter:public flag_formatter //Full month name static const months_array& full_months() { - static const months_array arr{ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" }; + static const months_array arr{ { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" } }; return arr; } class B_formatter:public flag_formatter diff --git a/vendor/spdlog/spdlog/details/spdlog_impl.h b/vendor/spdlog/spdlog/details/spdlog_impl.h index a8011db4..79d3ac45 100644 --- a/vendor/spdlog/spdlog/details/spdlog_impl.h +++ b/vendor/spdlog/spdlog/details/spdlog_impl.h @@ -61,23 +61,23 @@ inline std::shared_ptr spdlog::basic_logger_st(const std::string // Create multi/single threaded rotating file logger inline std::shared_ptr spdlog::rotating_logger_mt(const std::string& logger_name, const filename_t& filename, size_t max_file_size, size_t max_files) { - return create(logger_name, filename, SPDLOG_FILENAME_T("txt"), max_file_size, max_files); + return create(logger_name, filename, max_file_size, max_files); } inline std::shared_ptr spdlog::rotating_logger_st(const std::string& logger_name, const filename_t& filename, size_t max_file_size, size_t max_files) { - return create(logger_name, filename, SPDLOG_FILENAME_T("txt"), max_file_size, max_files); + return create(logger_name, filename, max_file_size, max_files); } // Create file logger which creates new file at midnight): inline std::shared_ptr spdlog::daily_logger_mt(const std::string& logger_name, const filename_t& filename, int hour, int minute) { - return create(logger_name, filename, SPDLOG_FILENAME_T("txt"), hour, minute); + return create(logger_name, filename, hour, minute); } inline std::shared_ptr spdlog::daily_logger_st(const std::string& logger_name, const filename_t& filename, int hour, int minute) { - return create(logger_name, filename, SPDLOG_FILENAME_T("txt"), hour, minute); + return create(logger_name, filename, hour, minute); } diff --git a/vendor/spdlog/spdlog/fmt/bundled/format.cc b/vendor/spdlog/spdlog/fmt/bundled/format.cc index fd8855be..2bd774e4 100644 --- a/vendor/spdlog/spdlog/fmt/bundled/format.cc +++ b/vendor/spdlog/spdlog/fmt/bundled/format.cc @@ -1,29 +1,29 @@ /* -Formatting library for C++ + Formatting library for C++ -Copyright (c) 2012 - 2016, Victor Zverovich -All rights reserved. + Copyright (c) 2012 - 2016, 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: + 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. + 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. -*/ + 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" @@ -71,37 +71,31 @@ using fmt::internal::Arg; // 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_r(int, char *, ...) { + return fmt::internal::Null<>(); } -static inline fmt::internal::Null<> strerror_s(char *, std::size_t, ...) -{ - return fmt::internal::Null<>(); +static inline fmt::internal::Null<> strerror_s(char *, std::size_t, ...) { + return fmt::internal::Null<>(); } namespace fmt { - FMT_FUNC internal::RuntimeError::~RuntimeError() FMT_DTOR_NOEXCEPT - {} - FMT_FUNC FormatError::~FormatError() FMT_DTOR_NOEXCEPT - {} - FMT_FUNC SystemError::~SystemError() FMT_DTOR_NOEXCEPT - {} +FMT_FUNC internal::RuntimeError::~RuntimeError() throw() {} +FMT_FUNC FormatError::~FormatError() throw() {} +FMT_FUNC SystemError::~SystemError() throw() {} - namespace { +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; - } +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 @@ -111,183 +105,380 @@ namespace fmt { # define FMT_SWPRINTF swprintf #endif // defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT) - const char RESET_COLOR[] = "\x1b[0m"; +// Checks if a value fits in int - used to avoid warnings about comparing +// signed and unsigned integers. +template +struct IntChecker { + template + static bool fits_in_int(T value) { + unsigned max = INT_MAX; + return value <= max; + } + static bool fits_in_int(bool) { return true; } +}; - typedef void(*FormatFunc)(Writer &, int, StringRef); +template <> +struct IntChecker { + template + static bool fits_in_int(T value) { + return value >= INT_MIN && value <= INT_MAX; + } + static bool fits_in_int(int) { return true; } +}; - // 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"); +const char RESET_COLOR[] = "\x1b[0m"; - class StrError - { - private: - int error_code_; - char *&buffer_; - std::size_t buffer_size_; +typedef void (*FormatFunc)(Writer &, int, StringRef); - // A noop assignment operator to avoid bogus warnings. - void operator=(const StrError &) - {} +// 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"); - // 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; - } + class StrError { + private: + int error_code_; + char *&buffer_; + std::size_t buffer_size_; - // 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; - } + // A noop assignment operator to avoid bogus warnings. + void operator=(const StrError &) {} - // Handle the case when strerror_r is not available. - int handle(internal::Null<>) - { - return fallback(strerror_s(buffer_, buffer_size_, error_code_)); - } + // 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; + } - // 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; - } + // 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; + } - // Fallback to strerror if strerror_r and strerror_s are not available. - int fallback(internal::Null<>) - { - errno = 0; - buffer_ = strerror(error_code_); - return errno; - } + // Handle the case when strerror_r is not available. + int handle(internal::Null<>) { + return fallback(strerror_s(buffer_, buffer_size_, error_code_)); + } - public: - StrError(int err_code, char *&buf, std::size_t buf_size) - : error_code_(err_code), buffer_(buf), buffer_size_(buf_size) - {} + // 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; + } - int run() - { - // Suppress a warning about unused strerror_r. - strerror_r(0, FMT_NULL, ""); - return handle(strerror_r(error_code_, buffer_, buffer_size_)); - } - }; - return StrError(error_code, buffer, buffer_size).run(); - } + // Fallback to strerror if strerror_r and strerror_s are not available. + int fallback(internal::Null<>) { + errno = 0; + buffer_ = strerror(error_code_); + return errno; + } - void format_error_code(Writer &out, int error_code, - 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 internal::IntTraits::MainType MainType; - MainType abs_value = static_cast(error_code); - if (internal::is_negative(error_code)) { - abs_value = 0 - abs_value; - ++error_code_size; - } - error_code_size += internal::count_digits(abs_value); - if (message.size() <= internal::INLINE_BUFFER_SIZE - error_code_size) - out << message << SEP; - out << ERROR_STR << error_code; - assert(out.size() <= internal::INLINE_BUFFER_SIZE); - } + public: + StrError(int err_code, char *&buf, std::size_t buf_size) + : error_code_(err_code), buffer_(buf), buffer_size_(buf_size) {} - void report_error(FormatFunc func, int error_code, - StringRef message) FMT_NOEXCEPT - { - 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); - } - } // namespace + 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(); +} - namespace internal { +void format_error_code(Writer &out, int error_code, + 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 internal::IntTraits::MainType MainType; + MainType abs_value = static_cast(error_code); + if (internal::is_negative(error_code)) { + abs_value = 0 - abs_value; + ++error_code_size; + } + error_code_size += internal::count_digits(abs_value); + if (message.size() <= internal::INLINE_BUFFER_SIZE - error_code_size) + out << message << SEP; + out << ERROR_STR << error_code; + assert(out.size() <= internal::INLINE_BUFFER_SIZE); +} - // This method is used to preserve binary compatibility with fmt 3.0. - // It can be removed in 4.0. - FMT_FUNC void format_system_error( - Writer &out, int error_code, StringRef message) FMT_NOEXCEPT - { - fmt::format_system_error(out, error_code, message); - } - } // namespace internal +void report_error(FormatFunc func, int error_code, + StringRef message) FMT_NOEXCEPT { + 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); +} - FMT_FUNC void SystemError::init( - int err_code, CStringRef format_str, ArgList args) - { - error_code_ = err_code; - MemoryWriter w; - format_system_error(w, err_code, format(format_str, args)); - std::runtime_error &base = *this; - base = std::runtime_error(w.str()); - } +// IsZeroInt::visit(arg) returns true iff arg is a zero integer. +class IsZeroInt : public ArgVisitor { + public: + template + bool visit_any_int(T value) { return value == 0; } +}; - template - int internal::CharTraits::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); - } +// Checks if an argument is a valid printf width specifier and sets +// left alignment if it is negative. +class WidthHandler : public ArgVisitor { + private: + FormatSpec &spec_; - template - int internal::CharTraits::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); - } + FMT_DISALLOW_COPY_AND_ASSIGN(WidthHandler); - template - const char internal::BasicData::DIGITS[] = - "0001020304050607080910111213141516171819" - "2021222324252627282930313233343536373839" - "4041424344454647484950515253545556575859" - "6061626364656667686970717273747576777879" - "8081828384858687888990919293949596979899"; + public: + explicit WidthHandler(FormatSpec &spec) : spec_(spec) {} + + void report_unhandled_arg() { + FMT_THROW(FormatError("width is not integer")); + } + + template + unsigned visit_any_int(T value) { + typedef typename internal::IntTraits::MainType UnsignedType; + UnsignedType width = static_cast(value); + if (internal::is_negative(value)) { + spec_.align_ = ALIGN_LEFT; + width = 0 - width; + } + if (width > INT_MAX) + FMT_THROW(FormatError("number is too big")); + return static_cast(width); + } +}; + +class PrecisionHandler : public ArgVisitor { + public: + void report_unhandled_arg() { + FMT_THROW(FormatError("precision is not integer")); + } + + template + int visit_any_int(T value) { + if (!IntChecker::is_signed>::fits_in_int(value)) + FMT_THROW(FormatError("number is too big")); + return static_cast(value); + } +}; + +template +struct is_same { + enum { value = 0 }; +}; + +template +struct is_same { + 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 +class ArgConverter : public ArgVisitor, void> { + private: + internal::Arg &arg_; + wchar_t type_; + + FMT_DISALLOW_COPY_AND_ASSIGN(ArgConverter); + + public: + ArgConverter(internal::Arg &arg, wchar_t type) + : arg_(arg), type_(type) {} + + void visit_bool(bool value) { + if (type_ != 's') + visit_any_int(value); + } + + template + void visit_any_int(U value) { + bool is_signed = type_ == 'd' || type_ == 'i'; + using internal::Arg; + typedef typename internal::Conditional< + is_same::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(static_cast(value)); + } else { + arg_.type = Arg::UINT; + typedef typename internal::MakeUnsigned::Type Unsigned; + arg_.uint_value = static_cast(static_cast(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(value); + } else { + arg_.type = Arg::ULONG_LONG; + arg_.ulong_long_value = + static_cast::Type>(value); + } + } + } +}; + +// Converts an integer argument to char for printf. +class CharConverter : public ArgVisitor { + private: + internal::Arg &arg_; + + FMT_DISALLOW_COPY_AND_ASSIGN(CharConverter); + + public: + explicit CharConverter(internal::Arg &arg) : arg_(arg) {} + + template + void visit_any_int(T value) { + arg_.type = internal::Arg::CHAR; + arg_.int_value = static_cast(value); + } +}; +} // namespace + +namespace internal { + +template +class PrintfArgFormatter : + public ArgFormatterBase, Char> { + + void write_null_pointer() { + this->spec().type_ = 0; + this->write("(nil)"); + } + + typedef ArgFormatterBase, Char> Base; + + public: + PrintfArgFormatter(BasicWriter &w, FormatSpec &s) + : ArgFormatterBase, 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 &w = this->writer(); + if (fmt_spec.type_ && fmt_spec.type_ != 'c') + w.write_int(value, fmt_spec); + typedef typename BasicWriter::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(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 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 +int fmt::internal::CharTraits::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 +int fmt::internal::CharTraits::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 +const char fmt::internal::BasicData::DIGITS[] = + "0001020304050607080910111213141516171819" + "2021222324252627282930313233343536373839" + "4041424344454647484950515253545556575859" + "6061626364656667686970717273747576777879" + "8081828384858687888990919293949596979899"; #define FMT_POWERS_OF_10(factor) \ factor * 10, \ @@ -300,284 +491,450 @@ namespace fmt { factor * 100000000, \ factor * 1000000000 - template - const uint32_t internal::BasicData::POWERS_OF_10_32[] = { - 0, FMT_POWERS_OF_10(1) - }; +template +const uint32_t fmt::internal::BasicData::POWERS_OF_10_32[] = { + 0, FMT_POWERS_OF_10(1) +}; - template - const uint64_t internal::BasicData::POWERS_OF_10_64[] = { - 0, - FMT_POWERS_OF_10(1), - FMT_POWERS_OF_10(ULongLong(1000000000)), - // Multiply several constants instead of using a single long long constant - // to avoid warnings about C++98 not supporting long long. - ULongLong(1000000000) * ULongLong(1000000000) * 10 - }; +template +const uint64_t fmt::internal::BasicData::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 internal::report_unknown_type(char code, const char *type) - { - (void)type; - if (std::isprint(static_cast(code))) { - FMT_THROW(FormatError( - format("unknown format code '{}' for {}", code, type))); - } - FMT_THROW(FormatError( - format("unknown format code '\\x{:02x}' for {}", - static_cast(code), type))); - } +FMT_FUNC void fmt::internal::report_unknown_type(char code, const char *type) { + (void)type; + if (std::isprint(static_cast(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(code), type))); +} #if FMT_USE_WINDOWS_H - FMT_FUNC internal::UTF8ToUTF16::UTF8ToUTF16(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(s.size()); - int length = MultiByteToWideChar( - CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, FMT_NULL, 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::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(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 internal::UTF16ToUTF8::UTF16ToUTF8(WStringRef s) - { - if (int error_code = convert(s)) { - FMT_THROW(WindowsError(error_code, - "cannot convert string from UTF-16 to UTF-8")); - } - } +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 internal::UTF16ToUTF8::convert(WStringRef s) - { - if (s.size() > INT_MAX) - return ERROR_INVALID_PARAMETER; - int s_size = static_cast(s.size()); - int length = WideCharToMultiByte( - CP_UTF8, 0, s.data(), s_size, FMT_NULL, 0, FMT_NULL, FMT_NULL); - if (length == 0) - return GetLastError(); - buffer_.resize(length + 1); - length = WideCharToMultiByte( - CP_UTF8, 0, s.data(), s_size, &buffer_[0], length, FMT_NULL, FMT_NULL); - if (length == 0) - return GetLastError(); - buffer_[length] = 0; - return 0; - } +FMT_FUNC int fmt::internal::UTF16ToUTF8::convert(fmt::WStringRef s) { + if (s.size() > INT_MAX) + return ERROR_INVALID_PARAMETER; + int s_size = static_cast(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 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::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 internal::format_windows_error( - Writer &out, int error_code, StringRef message) FMT_NOEXCEPT - { - FMT_TRY{ - MemoryBuffer buffer; - buffer.resize(INLINE_BUFFER_SIZE); - for (;;) { - wchar_t *system_message = &buffer[0]; - int result = FormatMessageW( - FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - FMT_NULL, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - system_message, static_cast(buffer.size()), FMT_NULL); - 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. - } +FMT_FUNC void fmt::internal::format_windows_error( + fmt::Writer &out, int error_code, + fmt::StringRef message) FMT_NOEXCEPT { + FMT_TRY { + MemoryBuffer 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(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 format_system_error( - Writer &out, int error_code, StringRef message) FMT_NOEXCEPT - { - FMT_TRY{ - internal::MemoryBuffer buffer; - buffer.resize(internal::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. - } +FMT_FUNC void fmt::internal::format_system_error( + fmt::Writer &out, int error_code, + fmt::StringRef message) FMT_NOEXCEPT { + FMT_TRY { + MemoryBuffer 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 - void internal::ArgMap::init(const ArgList &args) - { - if (!map_.empty()) - return; - typedef internal::NamedArg NamedArg; - const NamedArg *named_arg = FMT_NULL; - bool use_values = - args.type(ArgList::MAX_PACKED_ARGS - 1) == internal::Arg::NONE; - if (use_values) { - for (unsigned i = 0;/*nothing*/; ++i) { - internal::Arg::Type arg_type = args.type(i); - switch (arg_type) { - case internal::Arg::NONE: - return; - case internal::Arg::NAMED_ARG: - named_arg = static_cast(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(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(args.args_[i].pointer); - map_.push_back(Pair(named_arg->name, *named_arg)); - break; - default: - /*nothing*/; - } - } - } +template +void fmt::internal::ArgMap::init(const ArgList &args) { + if (!map_.empty()) + return; + typedef internal::NamedArg 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(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(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(args.args_[i].pointer); + map_.push_back(Pair(named_arg->name, *named_arg)); + break; + default: + /*nothing*/; + } + } +} - template - void internal::FixedBuffer::grow(std::size_t) - { - FMT_THROW(std::runtime_error("buffer overflow")); - } +template +void fmt::internal::FixedBuffer::grow(std::size_t) { + FMT_THROW(std::runtime_error("buffer overflow")); +} - FMT_FUNC Arg 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(arg.pointer); - break; - default: - /*nothing*/; - } - return arg; - } +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(arg.pointer); + break; + default: + /*nothing*/; + } + return arg; +} - FMT_FUNC void report_system_error( - int error_code, fmt::StringRef message) FMT_NOEXCEPT - { - // 'fmt::' is for bcc32. - report_error(format_system_error, error_code, message); - } +template +void fmt::internal::PrintfFormatter::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 +Arg fmt::internal::PrintfFormatter::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 +unsigned fmt::internal::PrintfFormatter::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 +void fmt::internal::PrintfFormatter::format( + BasicWriter &writer, BasicCStringRef 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(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(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(arg, *++s).visit(arg); + else + ArgConverter(arg, *s).visit(arg); + break; + case 'l': + if (*s == 'l') + ArgConverter(arg, *++s).visit(arg); + else + ArgConverter(arg, *s).visit(arg); + break; + case 'j': + ArgConverter(arg, *s).visit(arg); + break; + case 'z': + ArgConverter(arg, *s).visit(arg); + break; + case 't': + ArgConverter(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(arg, *s).visit(arg); + } + + // Parse type. + if (!*s) + FMT_THROW(FormatError("invalid format string")); + spec.type_ = static_cast(*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(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 report_windows_error( - int error_code, fmt::StringRef message) FMT_NOEXCEPT - { - // 'fmt::' is for bcc32. - report_error(internal::format_windows_error, error_code, message); - } +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 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(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 print(CStringRef format_str, ArgList args) - { - print(stdout, format_str, args); - } +FMT_FUNC void fmt::print(CStringRef format_str, ArgList args) { + print(stdout, format_str, args); +} - FMT_FUNC void print_colored(Color c, CStringRef format, ArgList args) - { - char escape[] = "\x1b[30m"; - escape[3] = static_cast('0' + c); - std::fputs(escape, stdout); - print(format, args); - std::fputs(RESET_COLOR, stdout); - } +FMT_FUNC void fmt::print_colored(Color c, CStringRef format, ArgList args) { + char escape[] = "\x1b[30m"; + escape[3] = static_cast('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(size); +} #ifndef FMT_HEADER_ONLY - template struct internal::BasicData; +template struct fmt::internal::BasicData; - // Explicit instantiations for char. +// Explicit instantiations for char. - template void internal::FixedBuffer::grow(std::size_t); +template void fmt::internal::FixedBuffer::grow(std::size_t); - template void internal::ArgMap::init(const ArgList &args); +template void fmt::internal::ArgMap::init(const fmt::ArgList &args); - template int internal::CharTraits::format_float( - char *buffer, std::size_t size, const char *format, - unsigned width, int precision, double value); +template void fmt::internal::PrintfFormatter::format( + BasicWriter &writer, CStringRef format); - template int internal::CharTraits::format_float( - char *buffer, std::size_t size, const char *format, - unsigned width, int precision, long double value); +template int fmt::internal::CharTraits::format_float( + char *buffer, std::size_t size, const char *format, + unsigned width, int precision, double value); - // Explicit instantiations for wchar_t. +template int fmt::internal::CharTraits::format_float( + char *buffer, std::size_t size, const char *format, + unsigned width, int precision, long double value); - template void internal::FixedBuffer::grow(std::size_t); +// Explicit instantiations for wchar_t. - template void internal::ArgMap::init(const ArgList &args); +template void fmt::internal::FixedBuffer::grow(std::size_t); - template int internal::CharTraits::format_float( - wchar_t *buffer, std::size_t size, const wchar_t *format, - unsigned width, int precision, double value); +template void fmt::internal::ArgMap::init(const fmt::ArgList &args); - template int internal::CharTraits::format_float( - wchar_t *buffer, std::size_t size, const wchar_t *format, - unsigned width, int precision, long double value); +template void fmt::internal::PrintfFormatter::format( + BasicWriter &writer, WCStringRef format); + +template int fmt::internal::CharTraits::format_float( + wchar_t *buffer, std::size_t size, const wchar_t *format, + unsigned width, int precision, double value); + +template int fmt::internal::CharTraits::format_float( + wchar_t *buffer, std::size_t size, const wchar_t *format, + unsigned width, int precision, long double value); #endif // FMT_HEADER_ONLY -} // namespace fmt - #ifdef _MSC_VER # pragma warning(pop) #endif diff --git a/vendor/spdlog/spdlog/fmt/bundled/format.h b/vendor/spdlog/spdlog/fmt/bundled/format.h index e5e2e2ef..64c949be 100644 --- a/vendor/spdlog/spdlog/fmt/bundled/format.h +++ b/vendor/spdlog/spdlog/fmt/bundled/format.h @@ -1,29 +1,29 @@ /* -Formatting library for C++ + Formatting library for C++ -Copyright (c) 2012 - 2016, Victor Zverovich -All rights reserved. + Copyright (c) 2012 - 2016, 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: + 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. + 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. -*/ + 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. + */ #ifndef FMT_FORMAT_H_ #define FMT_FORMAT_H_ @@ -40,9 +40,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -// The fmt library version in the form major * 10000 + minor * 100 + patch. -#define FMT_VERSION 30002 - #ifdef _SECURE_SCL # define FMT_SECURE_SCL _SECURE_SCL #else @@ -183,32 +180,22 @@ typedef __int64 intmax_t; # define FMT_USE_NOEXCEPT 0 #endif -#if FMT_USE_NOEXCEPT || FMT_HAS_FEATURE(cxx_noexcept) || \ - (FMT_GCC_VERSION >= 408 && FMT_HAS_GXX_CXX11) || \ - FMT_MSC_VER >= 1900 -# define FMT_DETECTED_NOEXCEPT noexcept -#else -# define FMT_DETECTED_NOEXCEPT throw() -#endif - #ifndef FMT_NOEXCEPT # if FMT_EXCEPTIONS -# define FMT_NOEXCEPT FMT_DETECTED_NOEXCEPT +# if FMT_USE_NOEXCEPT || FMT_HAS_FEATURE(cxx_noexcept) || \ + (FMT_GCC_VERSION >= 408 && FMT_HAS_GXX_CXX11) || \ + FMT_MSC_VER >= 1900 +# define FMT_NOEXCEPT noexcept +# else +# define FMT_NOEXCEPT throw() +# endif # else # define FMT_NOEXCEPT # endif #endif -// This is needed because GCC still uses throw() in its headers when exceptions -// are disabled. -#if FMT_GCC_VERSION -# define FMT_DTOR_NOEXCEPT FMT_DETECTED_NOEXCEPT -#else -# define FMT_DTOR_NOEXCEPT FMT_NOEXCEPT -#endif - #ifndef FMT_OVERRIDE -# if (defined(FMT_USE_OVERRIDE) && FMT_USE_OVERRIDE) || FMT_HAS_FEATURE(cxx_override) || \ +# if FMT_USE_OVERRIDE || FMT_HAS_FEATURE(cxx_override) || \ (FMT_GCC_VERSION >= 408 && FMT_HAS_GXX_CXX11) || \ FMT_MSC_VER >= 1900 # define FMT_OVERRIDE override @@ -217,15 +204,6 @@ typedef __int64 intmax_t; # endif #endif -#ifndef FMT_NULL -# if FMT_HAS_FEATURE(cxx_nullptr) || \ - (FMT_GCC_VERSION >= 408 && FMT_HAS_GXX_CXX11) || \ - FMT_MSC_VER >= 1600 -# define FMT_NULL nullptr -# else -# define FMT_NULL NULL -# endif -#endif // A macro to disallow the copy constructor and operator= functions // This should be used in the private: declarations for a class @@ -258,21 +236,6 @@ typedef __int64 intmax_t; (!defined(FMT_ICC_VERSION) || FMT_ICC_VERSION >= 1500) #endif -#ifndef FMT_USE_EXTERN_TEMPLATES -// Clang doesn't have a feature check for extern templates so we check -// for variadic templates which were introduced in the same version. -// For GCC according to cppreference.com they were introduced in 3.3. -# define FMT_USE_EXTERN_TEMPLATES \ - ((__clang__ && FMT_USE_VARIADIC_TEMPLATES) || \ - (FMT_GCC_VERSION >= 303 && FMT_HAS_GXX_CXX11)) -#endif - -#ifdef FMT_HEADER_ONLY -// If header only do not use extern templates. -# undef FMT_USE_EXTERN_TEMPLATES -# define FMT_USE_EXTERN_TEMPLATES 0 -#endif - #ifndef FMT_ASSERT # define FMT_ASSERT(condition, message) assert((condition) && message) #endif @@ -399,7 +362,7 @@ namespace std // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=48891 // and the same for isnan and signbit. template <> -class numeric_limits: +class numeric_limits : public std::numeric_limits { public: @@ -435,11 +398,8 @@ public: static bool isnegative(double x) { using namespace fmt::internal; - if (const_check(sizeof(signbit(x)) == sizeof(bool) || - sizeof(signbit(x)) == sizeof(int))) - { + if (const_check(sizeof(signbit(x)) == sizeof(int))) return signbit(x) != 0; - } if (x < 0) return true; if (!isnotanumber(x)) return false; int dec = 0, sign = 0; @@ -471,37 +431,34 @@ typedef BasicWriter WWriter; template class ArgFormatter; -template -class BasicPrintfArgFormatter; - template > class BasicFormatter; /** -\rst -A string reference. It can be constructed from a C string or ``std::string``. + \rst + A string reference. It can be constructed from a C string or ``std::string``. -You can use one of the following typedefs for common character types: + You can use one of the following typedefs for common character types: -+------------+-------------------------+ -| Type | Definition | -+============+=========================+ -| StringRef | BasicStringRef | -+------------+-------------------------+ -| WStringRef | BasicStringRef | -+------------+-------------------------+ + +------------+-------------------------+ + | Type | Definition | + +============+=========================+ + | StringRef | BasicStringRef | + +------------+-------------------------+ + | WStringRef | BasicStringRef | + +------------+-------------------------+ -This class is most useful as a parameter type to allow passing -different types of strings to a function, for example:: + This class is most useful as a parameter type to allow passing + different types of strings to a function, for example:: -template -std::string format(StringRef format_str, const Args & ... args); + template + std::string format(StringRef format_str, const Args & ... args); -format("{}", 42); -format(std::string("{}"), 42); -\endrst -*/ + format("{}", 42); + format(std::string("{}"), 42); + \endrst + */ template class BasicStringRef { @@ -511,33 +468,30 @@ 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 - Constructs a string reference object from a C string computing - the size with ``std::char_traits::length``. - \endrst - */ + \rst + Constructs a string reference object from a C string computing + the size with ``std::char_traits::length``. + \endrst + */ BasicStringRef(const Char *s) - : data_(s), size_(std::char_traits::length(s)) - {} + : data_(s), size_(std::char_traits::length(s)) {} /** - \rst - Constructs a string reference from an ``std::string`` object. - \endrst - */ + \rst + Constructs a string reference from an ``std::string`` object. + \endrst + */ BasicStringRef(const std::basic_string &s) - : data_(s.c_str()), size_(s.size()) - {} + : data_(s.c_str()), size_(s.size()) {} /** - \rst - Converts a string reference to an ``std::string`` object. - \endrst - */ + \rst + Converts a string reference to an ``std::string`` object. + \endrst + */ std::basic_string to_string() const { return std::basic_string(data_, size_); @@ -595,30 +549,30 @@ typedef BasicStringRef StringRef; typedef BasicStringRef WStringRef; /** -\rst -A reference to a null terminated string. It can be constructed from a C -string or ``std::string``. + \rst + A reference to a null terminated string. It can be constructed from a C + string or ``std::string``. -You can use one of the following typedefs for common character types: + You can use one of the following typedefs for common character types: -+-------------+--------------------------+ -| Type | Definition | -+=============+==========================+ -| CStringRef | BasicCStringRef | -+-------------+--------------------------+ -| WCStringRef | BasicCStringRef | -+-------------+--------------------------+ + +-------------+--------------------------+ + | Type | Definition | + +=============+==========================+ + | CStringRef | BasicCStringRef | + +-------------+--------------------------+ + | WCStringRef | BasicCStringRef | + +-------------+--------------------------+ -This class is most useful as a parameter type to allow passing -different types of strings to a function, for example:: + This class is most useful as a parameter type to allow passing + different types of strings to a function, for example:: -template -std::string format(CStringRef format_str, const Args & ... args); + template + std::string format(CStringRef format_str, const Args & ... args); -format("{}", 42); -format(std::string("{}"), 42); -\endrst -*/ + format("{}", 42); + format(std::string("{}"), 42); + \endrst + */ template class BasicCStringRef { @@ -627,16 +581,14 @@ 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 &s): data_(s.c_str()) - {} + \rst + Constructs a string reference from an ``std::string`` object. + \endrst + */ + BasicCStringRef(const std::basic_string &s) : data_(s.c_str()) {} /** Returns the pointer to a C string. */ const Char *c_str() const @@ -649,15 +601,12 @@ typedef BasicCStringRef CStringRef; typedef BasicCStringRef 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()) - {} - FormatError(const FormatError &ferr): std::runtime_error(ferr) - {} - ~FormatError() FMT_DTOR_NOEXCEPT; + : std::runtime_error(message.c_str()) {} + ~FormatError() throw(); }; namespace internal @@ -691,10 +640,7 @@ inline typename MakeUnsigned::Type to_unsigned(Int 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. @@ -713,10 +659,10 @@ inline T *make_ptr(T *ptr, std::size_t) } // namespace internal /** -\rst -A buffer supporting a subset of ``std::vector``'s operations. -\endrst -*/ + \rst + A buffer supporting a subset of ``std::vector``'s operations. + \endrst + */ template class Buffer { @@ -728,21 +674,19 @@ protected: std::size_t size_; std::size_t capacity_; - Buffer(T *ptr = FMT_NULL, std::size_t capacity = 0) - : ptr_(ptr), size_(0), capacity_(capacity) - {} + Buffer(T *ptr = 0, std::size_t capacity = 0) + : ptr_(ptr), size_(0), capacity_(capacity) {} /** - \rst - Increases the buffer capacity to hold at least *size* elements updating - ``ptr_`` and ``capacity_``. - \endrst - */ + \rst + Increases the buffer capacity to hold at least *size* elements updating + ``ptr_`` and ``capacity_``. + \endrst + */ virtual void grow(std::size_t size) = 0; public: - virtual ~Buffer() - {} + virtual ~Buffer() {} /** Returns the size of this buffer. */ std::size_t size() const @@ -757,8 +701,8 @@ public: } /** - Resizes the buffer. If T is a POD type new elements may not be initialized. - */ + Resizes the buffer. If T is a POD type new elements may not be initialized. + */ void resize(std::size_t new_size) { if (new_size > capacity_) @@ -767,20 +711,17 @@ public: } /** - \rst - Reserves space to store at least *capacity* elements. - \endrst - */ + \rst + Reserves space to store at least *capacity* elements. + \endrst + */ void reserve(std::size_t capacity) { if (capacity > capacity_) grow(capacity); } - void clear() FMT_NOEXCEPT - { - size_ = 0; - } + void clear() FMT_NOEXCEPT { size_ = 0; } void push_back(const T &value) { @@ -821,7 +762,7 @@ namespace internal // A memory buffer for trivially copyable/constructible types with the first // SIZE elements stored in the object itself. template > -class MemoryBuffer: private Allocator, public Buffer +class MemoryBuffer : private Allocator, public Buffer { private: T data_[SIZE]; @@ -837,8 +778,7 @@ protected: public: explicit MemoryBuffer(const Allocator &alloc = Allocator()) - : Allocator(alloc), Buffer(data_, SIZE) - {} + : Allocator(alloc), Buffer(data_, SIZE) {} ~MemoryBuffer() { deallocate(); @@ -896,7 +836,7 @@ void MemoryBuffer::grow(std::size_t size) std::size_t new_capacity = this->capacity_ + this->capacity_ / 2; if (size > new_capacity) new_capacity = size; - T *new_ptr = this->allocate(new_capacity, FMT_NULL); + T *new_ptr = this->allocate(new_capacity); // The following code doesn't throw, so the raw pointer above doesn't leak. std::uninitialized_copy(this->ptr_, this->ptr_ + this->size_, make_ptr(new_ptr, new_capacity)); @@ -913,14 +853,13 @@ void MemoryBuffer::grow(std::size_t size) // A fixed-size buffer. template -class FixedBuffer: public fmt::Buffer +class FixedBuffer : public fmt::Buffer { public: - FixedBuffer(Char *array, std::size_t size): fmt::Buffer(array, size) - {} + FixedBuffer(Char *array, std::size_t size) : fmt::Buffer(array, size) {} protected: - FMT_API void grow(std::size_t size) FMT_OVERRIDE; + FMT_API void grow(std::size_t size); }; template @@ -942,7 +881,7 @@ template class CharTraits; template <> -class CharTraits: public BasicCharTraits +class CharTraits : public BasicCharTraits { private: // Conversion from wchar_t to char is not allowed. @@ -960,17 +899,8 @@ public: const char *format, unsigned width, int precision, T value); }; -#if FMT_USE_EXTERN_TEMPLATES -extern template int CharTraits::format_float -(char *buffer, std::size_t size, - const char* format, unsigned width, int precision, double value); -extern template int CharTraits::format_float -(char *buffer, std::size_t size, - const char* format, unsigned width, int precision, long double value); -#endif - template <> -class CharTraits: public BasicCharTraits +class CharTraits : public BasicCharTraits { public: static wchar_t convert(char value) @@ -987,15 +917,6 @@ public: const wchar_t *format, unsigned width, int precision, T value); }; -#if FMT_USE_EXTERN_TEMPLATES -extern template int CharTraits::format_float -(wchar_t *buffer, std::size_t size, - const wchar_t* format, unsigned width, int precision, double value); -extern template int CharTraits::format_float -(wchar_t *buffer, std::size_t size, - const wchar_t* format, unsigned width, int precision, long double value); -#endif - // Checks if a number is negative - used to avoid warnings. template struct SignChecker @@ -1059,7 +980,13 @@ struct FMT_API BasicData static const char DIGITS[]; }; -#if FMT_USE_EXTERN_TEMPLATES +#ifndef FMT_USE_EXTERN_TEMPLATES +// Clang doesn't have a feature check for extern templates so we check +// for variadic templates which were introduced in the same version. +# define FMT_USE_EXTERN_TEMPLATES (__clang__ && FMT_USE_VARIADIC_TEMPLATES) +#endif + +#if FMT_USE_EXTERN_TEMPLATES && !defined(FMT_HEADER_ONLY) extern template struct BasicData; #endif @@ -1108,8 +1035,7 @@ inline unsigned count_digits(uint32_t n) struct NoThousandsSep { template - void operator()(Char *) - {} + void operator()(Char *) {} }; // A functor that adds a thousands separator. @@ -1122,8 +1048,7 @@ private: unsigned digit_index_; public: - explicit ThousandsSep(fmt::StringRef sep): sep_(sep), digit_index_(0) - {} + explicit ThousandsSep(fmt::StringRef sep) : sep_(sep), digit_index_(0) {} template void operator()(Char *&buffer) @@ -1170,8 +1095,7 @@ inline void format_decimal(Char *buffer, UInt value, unsigned num_digits, template inline void format_decimal(Char *buffer, UInt value, unsigned num_digits) { - format_decimal(buffer, value, num_digits, NoThousandsSep()); - return; + return format_decimal(buffer, value, num_digits, NoThousandsSep()); } #ifndef _WIN32 @@ -1218,8 +1142,7 @@ private: MemoryBuffer buffer_; public: - UTF16ToUTF8() - {} + UTF16ToUTF8() {} FMT_API explicit UTF16ToUTF8(WStringRef s); operator StringRef() const { @@ -1248,6 +1171,9 @@ FMT_API void format_windows_error(fmt::Writer &out, int error_code, fmt::StringRef message) FMT_NOEXCEPT; #endif +FMT_API void format_system_error(fmt::Writer &out, int error_code, + fmt::StringRef message) FMT_NOEXCEPT; + // A formatting argument value. struct Value { @@ -1258,7 +1184,7 @@ struct Value std::size_t size; }; - typedef void(*FormatFunc)( + typedef void (*FormatFunc)( void *formatter, const void *arg, void *format_str_ptr); struct CustomValue @@ -1296,19 +1222,16 @@ struct Value // A formatting argument. It is a trivially copyable/constructible type to // allow storage in internal::MemoryBuffer. -struct Arg: Value +struct Arg : Value { Type type; }; template struct NamedArg; -template -struct NamedArgWithType; template -struct Null -{}; +struct Null {}; // A helper class template to enable or disable overloads taking wide // characters and strings in MakeValue. @@ -1339,19 +1262,13 @@ No &convert(...); template struct ConvertToIntImpl { - enum - { - value = ENABLE_CONVERSION - }; + enum { value = ENABLE_CONVERSION }; }; template struct ConvertToIntImpl2 { - enum - { - value = false - }; + enum { value = false }; }; template @@ -1367,14 +1284,8 @@ struct ConvertToIntImpl2 template struct ConvertToInt { - enum - { - enable_conversion = sizeof(fmt::internal::convert(get())) == sizeof(Yes) - }; - enum - { - value = ConvertToIntImpl2::value - }; + enum { enable_conversion = sizeof(convert(get())) == sizeof(Yes) }; + enum { value = ConvertToIntImpl2::value }; }; #define FMT_DISABLE_CONVERSION_TO_INT(Type) \ @@ -1387,8 +1298,7 @@ FMT_DISABLE_CONVERSION_TO_INT(double); FMT_DISABLE_CONVERSION_TO_INT(long double); template -struct EnableIf -{}; +struct EnableIf {}; template struct EnableIf @@ -1409,37 +1319,21 @@ struct Conditional }; // For bcc32 which doesn't understand ! in template arguments. -template +template struct Not { - enum - { - value = 0 - }; + enum { value = 0 }; }; -template <> +template<> struct Not { - enum - { - value = 1 - }; + enum { value = 1 }; }; -template -struct False +template struct LConvCheck { - enum - { - value = 0 - }; -}; - -template struct LConvCheck -{ - LConvCheck(int) - {} + LConvCheck(int) {} }; // Returns the thousands separator for the current locale. @@ -1457,39 +1351,9 @@ inline fmt::StringRef thousands_sep(...) return ""; } -#define FMT_CONCAT(a, b) a##b - -#if FMT_GCC_VERSION >= 303 -# define FMT_UNUSED __attribute__((unused)) -#else -# define FMT_UNUSED -#endif - -#ifndef FMT_USE_STATIC_ASSERT -# define FMT_USE_STATIC_ASSERT 0 -#endif - -#if FMT_USE_STATIC_ASSERT || FMT_HAS_FEATURE(cxx_static_assert) || \ - (FMT_GCC_VERSION >= 403 && FMT_HAS_GXX_CXX11) || _MSC_VER >= 1600 -# define FMT_STATIC_ASSERT(cond, message) static_assert(cond, message) -#else -# define FMT_CONCAT_(a, b) FMT_CONCAT(a, b) -# define FMT_STATIC_ASSERT(cond, message) \ - typedef int FMT_CONCAT_(Assert, __LINE__)[(cond) ? 1 : -1] FMT_UNUSED -#endif - -template -void format_arg(Formatter &, const Char *, const T &) -{ - FMT_STATIC_ASSERT(False::value, - "Cannot format argument. To enable the use of ostream " - "operator<< include fmt/ostream.h. Otherwise provide " - "an overload of format_arg."); -} - // Makes an Arg object from any type. template -class MakeValue: public Arg +class MakeValue : public Arg { public: typedef typename Formatter::Char Char; @@ -1534,14 +1398,13 @@ private: static void format_custom_arg( void *formatter, const void *arg, void *format_str_ptr) { - format_arg(*static_cast(formatter), - *static_cast(format_str_ptr), - *static_cast(arg)); + format(*static_cast(formatter), + *static_cast(format_str_ptr), + *static_cast(arg)); } public: - MakeValue() - {} + MakeValue() {} #define FMT_MAKE_VALUE_(Type, field, TYPE, rhs) \ MakeValue(Type value) { field = rhs; } \ @@ -1660,26 +1523,16 @@ public: { pointer = &value; } - template - MakeValue(const NamedArgWithType &value) - { - pointer = &value; - } template static uint64_t type(const NamedArg &) { return Arg::NAMED_ARG; } - template - static uint64_t type(const NamedArgWithType &) - { - return Arg::NAMED_ARG; - } }; template -class MakeArg: public Arg +class MakeArg : public Arg { public: MakeArg() @@ -1696,34 +1549,25 @@ public: }; template -struct NamedArg: Arg +struct NamedArg : Arg { BasicStringRef name; template NamedArg(BasicStringRef argname, const T &value) - : Arg(MakeArg< BasicFormatter >(value)), name(argname) - {} + : Arg(MakeArg< BasicFormatter >(value)), name(argname) {} }; -template -struct NamedArgWithType: NamedArg -{ - NamedArgWithType(BasicStringRef argname, const T &value) - : NamedArg(argname, value) - {} -}; - -class RuntimeError: public std::runtime_error +class RuntimeError : public std::runtime_error { protected: - RuntimeError(): std::runtime_error("") - {} - RuntimeError(const RuntimeError &rerr): std::runtime_error(rerr) - {} - ~RuntimeError() FMT_DTOR_NOEXCEPT; + RuntimeError() : std::runtime_error("") {} + ~RuntimeError() throw(); }; +template +class PrintfArgFormatter; + template class ArgMap; } // namespace internal @@ -1748,7 +1592,10 @@ private: internal::Arg::Type type(unsigned index) const { - return type(types_, index); + unsigned shift = index * 4; + uint64_t mask = 0xf; + return static_cast( + (types_ & (mask << shift)) >> shift); } template @@ -1756,25 +1603,14 @@ 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) - {} - - uint64_t types() const - { - return types_; - } + : types_(types), args_(args) {} /** Returns the argument at specified index. */ internal::Arg operator[](unsigned index) const @@ -1805,42 +1641,34 @@ public: } return args_[index]; } - - static internal::Arg::Type type(uint64_t types, unsigned index) - { - unsigned shift = index * 4; - uint64_t mask = 0xf; - return static_cast( - (types & (mask << shift)) >> shift); - } }; #define FMT_DISPATCH(call) static_cast(this)->call /** -\rst -An argument visitor based on the `curiously recurring template pattern -`_. + \rst + An argument visitor based on the `curiously recurring template pattern + `_. -To use `~fmt::ArgVisitor` define a subclass that implements some or all of the -visit methods with the same signatures as the methods in `~fmt::ArgVisitor`, -for example, `~fmt::ArgVisitor::visit_int()`. -Pass the subclass as the *Impl* template parameter. Then calling -`~fmt::ArgVisitor::visit` for some argument will dispatch to a visit method -specific to the argument type. For example, if the argument type is -``double`` then the `~fmt::ArgVisitor::visit_double()` method of a subclass -will be called. If the subclass doesn't contain a method with this signature, -then a corresponding method of `~fmt::ArgVisitor` will be called. + To use `~fmt::ArgVisitor` define a subclass that implements some or all of the + visit methods with the same signatures as the methods in `~fmt::ArgVisitor`, + for example, `~fmt::ArgVisitor::visit_int()`. + Pass the subclass as the *Impl* template parameter. Then calling + `~fmt::ArgVisitor::visit` for some argument will dispatch to a visit method + specific to the argument type. For example, if the argument type is + ``double`` then the `~fmt::ArgVisitor::visit_double()` method of a subclass + will be called. If the subclass doesn't contain a method with this signature, + then a corresponding method of `~fmt::ArgVisitor` will be called. -**Example**:: + **Example**:: -class MyArgVisitor : public fmt::ArgVisitor { -public: -void visit_int(int value) { fmt::print("{}", value); } -void visit_double(double value) { fmt::print("{}", value ); } -}; -\endrst -*/ + class MyArgVisitor : public fmt::ArgVisitor { + public: + void visit_int(int value) { fmt::print("{}", value); } + void visit_double(double value) { fmt::print("{}", value ); } + }; + \endrst + */ template class ArgVisitor { @@ -1848,8 +1676,7 @@ private: typedef internal::Arg Arg; public: - void report_unhandled_arg() - {} + void report_unhandled_arg() {} Result visit_unhandled_arg() { @@ -1950,13 +1777,13 @@ public: } /** - \rst - Visits an argument dispatching to the appropriate visit method based on - the argument type. For example, if the argument type is ``double`` then - the `~fmt::ArgVisitor::visit_double()` method of the *Impl* class will be - called. - \endrst - */ + \rst + Visits an argument dispatching to the appropriate visit method based on + the argument type. For example, if the argument type is ``double`` then + the `~fmt::ArgVisitor::visit_double()` method of the *Impl* class will be + called. + \endrst + */ Result visit(const Arg &arg) { switch (arg.type) @@ -2009,12 +1836,11 @@ enum }; // An empty format specifier. -struct EmptySpec -{}; +struct EmptySpec {}; // A type specifier. template -struct TypeSpec: EmptySpec +struct TypeSpec : EmptySpec { Alignment align() const { @@ -2050,8 +1876,7 @@ 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 { @@ -2064,13 +1889,12 @@ 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 { @@ -2085,10 +1909,9 @@ struct AlignSpec: WidthSpec // An alignment and type specifier. template -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 { @@ -2101,7 +1924,7 @@ struct AlignTypeSpec: AlignSpec }; // A full format specifier. -struct FormatSpec: AlignSpec +struct FormatSpec : AlignSpec { unsigned flags_; int precision_; @@ -2109,8 +1932,7 @@ 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 { @@ -2128,15 +1950,14 @@ struct FormatSpec: AlignSpec // An integer format specifier. template , 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 { @@ -2146,7 +1967,7 @@ public: // A string format specifier. template -class StrFormatSpec: public AlignSpec +class StrFormatSpec : public AlignSpec { private: const Char *str_; @@ -2166,41 +1987,41 @@ public: }; /** -Returns an integer format specifier to format the value in base 2. -*/ + Returns an integer format specifier to format the value in base 2. + */ IntFormatSpec > bin(int value); /** -Returns an integer format specifier to format the value in base 8. -*/ + Returns an integer format specifier to format the value in base 8. + */ IntFormatSpec > oct(int value); /** -Returns an integer format specifier to format the value in base 16 using -lower-case letters for the digits above 9. -*/ + Returns an integer format specifier to format the value in base 16 using + lower-case letters for the digits above 9. + */ IntFormatSpec > hex(int value); /** -Returns an integer formatter format specifier to format in base 16 using -upper-case letters for the digits above 9. -*/ + Returns an integer formatter format specifier to format in base 16 using + upper-case letters for the digits above 9. + */ IntFormatSpec > hexu(int value); /** -\rst -Returns an integer format specifier to pad the formatted argument with the -fill character to the specified width using the default (right) numeric -alignment. + \rst + Returns an integer format specifier to pad the formatted argument with the + fill character to the specified width using the default (right) numeric + alignment. -**Example**:: + **Example**:: -MemoryWriter out; -out << pad(hex(0xcafe), 8, '0'); -// out.str() == "0000cafe" + MemoryWriter out; + out << pad(hex(0xcafe), 8, '0'); + // out.str() == "0000cafe" -\endrst -*/ + \endrst + */ template IntFormatSpec, Char> pad( int value, unsigned width, Char fill = ' '); @@ -2262,17 +2083,17 @@ FMT_DEFINE_INT_FORMATTERS(LongLong) FMT_DEFINE_INT_FORMATTERS(ULongLong) /** -\rst -Returns a string formatter that pads the formatted argument with the fill -character to the specified width using the default (left) string alignment. + \rst + Returns a string formatter that pads the formatted argument with the fill + character to the specified width using the default (left) string alignment. -**Example**:: + **Example**:: -std::string s = str(MemoryWriter() << pad("abc", 8)); -// s == "abc " + std::string s = str(MemoryWriter() << pad("abc", 8)); + // s == "abc " -\endrst -*/ + \endrst + */ template inline StrFormatSpec pad( const Char *str, unsigned width, Char fill = ' ') @@ -2302,7 +2123,7 @@ private: public: FMT_API void init(const ArgList &args); - const internal::Arg *find(const fmt::BasicStringRef &name) const + const internal::Arg* find(const fmt::BasicStringRef &name) const { // The list is unsorted, so just return the first matching name. for (typename MapType::const_iterator it = map_.begin(), end = map_.end(); @@ -2311,12 +2132,12 @@ public: if (it->first == name) return &it->second; } - return FMT_NULL; + return 0; } }; template -class ArgFormatterBase: public ArgVisitor +class ArgFormatterBase : public ArgVisitor { private: BasicWriter &writer_; @@ -2350,14 +2171,13 @@ protected: void write(const char *value) { - Arg::StringValue str = { value, value ? std::strlen(value) : 0 }; + Arg::StringValue str = {value, value != 0 ? std::strlen(value) : 0}; writer_.write_str(str, spec_); } public: ArgFormatterBase(BasicWriter &w, FormatSpec &s) - : writer_(w), spec_(s) - {} + : writer_(w), spec_(s) {} template void visit_any_int(T value) @@ -2374,10 +2194,7 @@ public: void visit_bool(bool value) { if (spec_.type_) - { - visit_any_int(value); - return; - } + return visit_any_int(value); write(value); } @@ -2503,27 +2320,48 @@ protected: w << BasicStringRef(start, internal::to_unsigned(end - start)); } }; + +// A printf formatter. +template +class PrintfFormatter : private FormatterBase +{ +private: + void parse_flags(FormatSpec &spec, const Char *&s); + + // Returns the argument with specified index or, if arg_index is equal + // to the maximum unsigned value, the next argument. + Arg get_arg(const Char *s, + unsigned arg_index = (std::numeric_limits::max)()); + + // Parses argument index, flags and width and returns the argument index. + unsigned parse_header(const Char *&s, FormatSpec &spec); + +public: + explicit PrintfFormatter(const ArgList &args) : FormatterBase(args) {} + FMT_API void format(BasicWriter &writer, + BasicCStringRef format_str); +}; } // namespace internal /** -\rst -An argument formatter based on the `curiously recurring template pattern -`_. + \rst + An argument formatter based on the `curiously recurring template pattern + `_. -To use `~fmt::BasicArgFormatter` define a subclass that implements some or -all of the visit methods with the same signatures as the methods in -`~fmt::ArgVisitor`, for example, `~fmt::ArgVisitor::visit_int()`. -Pass the subclass as the *Impl* template parameter. When a formatting -function processes an argument, it will dispatch to a visit method -specific to the argument type. For example, if the argument type is -``double`` then the `~fmt::ArgVisitor::visit_double()` method of a subclass -will be called. If the subclass doesn't contain a method with this signature, -then a corresponding method of `~fmt::BasicArgFormatter` or its superclass -will be called. -\endrst -*/ + To use `~fmt::BasicArgFormatter` define a subclass that implements some or + all of the visit methods with the same signatures as the methods in + `~fmt::ArgVisitor`, for example, `~fmt::ArgVisitor::visit_int()`. + Pass the subclass as the *Impl* template parameter. When a formatting + function processes an argument, it will dispatch to a visit method + specific to the argument type. For example, if the argument type is + ``double`` then the `~fmt::ArgVisitor::visit_double()` method of a subclass + will be called. If the subclass doesn't contain a method with this signature, + then a corresponding method of `~fmt::BasicArgFormatter` or its superclass + will be called. + \endrst + */ template -class BasicArgFormatter: public internal::ArgFormatterBase +class BasicArgFormatter : public internal::ArgFormatterBase { private: BasicFormatter &formatter_; @@ -2531,20 +2369,19 @@ private: public: /** - \rst - Constructs an argument formatter object. - *formatter* is a reference to the main formatter object, *spec* contains - format specifier information for standard argument types, and *fmt* points - to the part of the format string being parsed for custom argument types. - \endrst - */ + \rst + Constructs an argument formatter object. + *formatter* is a reference to the main formatter object, *spec* contains + format specifier information for standard argument types, and *fmt* points + to the part of the format string being parsed for custom argument types. + \endrst + */ BasicArgFormatter(BasicFormatter &formatter, FormatSpec &spec, const Char *fmt) : internal::ArgFormatterBase(formatter.writer(), spec), - formatter_(formatter), format_(fmt) - {} + formatter_(formatter), format_(fmt) {} - /** Formats an argument of a custom (user-defined) type. */ + /** Formats argument of a custom (user-defined) type. */ void visit_custom(internal::Arg::CustomValue c) { c.format(&formatter_, c.value, &format_); @@ -2553,19 +2390,18 @@ public: /** The default argument formatter. */ template -class ArgFormatter: public BasicArgFormatter, Char> +class ArgFormatter : public BasicArgFormatter, Char> { public: /** Constructs an argument formatter object. */ ArgFormatter(BasicFormatter &formatter, FormatSpec &spec, const Char *fmt) - : BasicArgFormatter, Char>(formatter, spec, fmt) - {} + : BasicArgFormatter, Char>(formatter, spec, fmt) {} }; /** This template formats data and writes the output to a writer. */ template -class BasicFormatter: private internal::FormatterBase +class BasicFormatter : private internal::FormatterBase { public: /** The character type for the output. */ @@ -2591,15 +2427,14 @@ private: 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 - */ + \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 &w) - : internal::FormatterBase(args), writer_(w) - {} + : internal::FormatterBase(args), writer_(w) {} /** Returns a reference to the writer associated with this formatter. */ BasicWriter &writer() @@ -2646,7 +2481,7 @@ inline uint64_t make_type(const T &arg) return MakeValue< BasicFormatter >::type(arg); } -template +template struct ArgArray; template @@ -2694,12 +2529,10 @@ struct ArgType { uint64_t type; - ArgType(): type(0) - {} + ArgType() : type(0) {} template - 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() @@ -2813,10 +2646,10 @@ inline uint64_t make_type(FMT_GEN15(FMT_ARG_TYPE_DEFAULT)) FMT_FOR_EACH9(f, x0, x1, x2, x3, x4, x5, x6, x7, x8), f(x9, 9) /** -An error returned by an operating system or a language runtime, -for example a file opening error. + 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); @@ -2826,27 +2659,33 @@ protected: typedef char Char; // For FMT_VARIADIC_CTOR. - SystemError() - {} + SystemError() {} public: /** - \rst - Constructs a :class:`fmt::SystemError` object with a description - formatted with `fmt::format_system_error`. *message* and additional - arguments passed into the constructor are formatted similarly to - `fmt::format`. + \rst + Constructs a :class:`fmt::SystemError` object with the description + of the form - **Example**:: + .. parsed-literal:: + **: ** - // This throws a SystemError with the description - // cannot open file 'madeup': No such file or directory - // or similar (system message may vary). - const char *filename = "madeup"; - std::FILE *file = std::fopen(filename, "r"); - if (!file) - throw fmt::SystemError(errno, "cannot open file '{}'", filename); - \endrst + where ** is the formatted message and ** is + the system message corresponding to the error code. + *error_code* is a system error code as given by ``errno``. + If *error_code* is not a valid error code such as -1, the system message + may look like "Unknown error -1" and is platform-dependent. + + **Example**:: + + // This throws a SystemError with the description + // cannot open file 'madeup': No such file or directory + // or similar (system message may vary). + const char *filename = "madeup"; + std::FILE *file = std::fopen(filename, "r"); + if (!file) + throw fmt::SystemError(errno, "cannot open file '{}'", filename); + \endrst */ SystemError(int error_code, CStringRef message) { @@ -2854,7 +2693,7 @@ public: } FMT_VARIADIC_CTOR(SystemError, init, int, CStringRef) - ~SystemError() FMT_DTOR_NOEXCEPT; + ~SystemError() throw(); int error_code() const { @@ -2863,42 +2702,23 @@ public: }; /** -\rst -Formats an error returned by an operating system or a language runtime, -for example a file opening error, and writes it to *out* in the following -form: + \rst + This template provides operations for formatting and writing data into + a character stream. The output is stored in a buffer provided by a subclass + such as :class:`fmt::BasicMemoryWriter`. -.. parsed-literal:: -**: ** + You can use one of the following typedefs for common character types: -where ** is the passed message and ** is -the system message corresponding to the error code. -*error_code* is a system error code as given by ``errno``. -If *error_code* is not a valid error code such as -1, the system message -may look like "Unknown error -1" and is platform-dependent. -\endrst -*/ -FMT_API void format_system_error(fmt::Writer &out, int error_code, - fmt::StringRef message) FMT_NOEXCEPT; + +---------+----------------------+ + | Type | Definition | + +=========+======================+ + | Writer | BasicWriter | + +---------+----------------------+ + | WWriter | BasicWriter | + +---------+----------------------+ -/** -\rst -This template provides operations for formatting and writing data into -a character stream. The output is stored in a buffer provided by a subclass -such as :class:`fmt::BasicMemoryWriter`. - -You can use one of the following typedefs for common character types: - -+---------+----------------------+ -| Type | Definition | -+=========+======================+ -| Writer | BasicWriter | -+---------+----------------------+ -| WWriter | BasicWriter | -+---------+----------------------+ - -\endrst -*/ + \endrst + */ template class BasicWriter { @@ -3010,52 +2830,48 @@ private: } template - void append_float_length(Char *&, T) - {} + void append_float_length(Char *&, T) {} template friend class internal::ArgFormatterBase; - template - friend class BasicPrintfArgFormatter; + friend class internal::PrintfArgFormatter; protected: /** - Constructs a ``BasicWriter`` object. - */ - explicit BasicWriter(Buffer &b): buffer_(b) - {} + Constructs a ``BasicWriter`` object. + */ + explicit BasicWriter(Buffer &b) : buffer_(b) {} public: /** - \rst - Destroys a ``BasicWriter`` object. - \endrst - */ - virtual ~BasicWriter() - {} + \rst + Destroys a ``BasicWriter`` object. + \endrst + */ + virtual ~BasicWriter() {} /** - Returns the total number of characters written. - */ + Returns the total number of characters written. + */ std::size_t size() const { return buffer_.size(); } /** - Returns a pointer to the output buffer content. No terminating null - character is appended. - */ + Returns a pointer to the output buffer content. No terminating null + character is appended. + */ const Char *data() const FMT_NOEXCEPT { return &buffer_[0]; } /** - Returns a pointer to the output buffer content with terminating null - character appended. - */ + Returns a pointer to the output buffer content with terminating null + character appended. + */ const Char *c_str() const { std::size_t size = buffer_.size(); @@ -3065,40 +2881,40 @@ public: } /** - \rst - Returns the content of the output buffer as an `std::string`. - \endrst - */ + \rst + Returns the content of the output buffer as an `std::string`. + \endrst + */ std::basic_string str() const { return std::basic_string(&buffer_[0], buffer_.size()); } /** - \rst - Writes formatted data. + \rst + Writes formatted data. - *args* is an argument list representing arbitrary arguments. + *args* is an argument list representing arbitrary arguments. - **Example**:: + **Example**:: - MemoryWriter out; - out.write("Current point:\n"); - out.write("({:+f}, {:+f})", -3.14, 3.14); + MemoryWriter out; + out.write("Current point:\n"); + out.write("({:+f}, {:+f})", -3.14, 3.14); - This will write the following output to the ``out`` object: + This will write the following output to the ``out`` object: - .. code-block:: none + .. code-block:: none - Current point: - (-3.140000, +3.140000) + Current point: + (-3.140000, +3.140000) - The output can be accessed using :func:`data()`, :func:`c_str` or - :func:`str` methods. + The output can be accessed using :func:`data()`, :func:`c_str` or + :func:`str` methods. - See also :ref:`syntax`. - \endrst - */ + See also :ref:`syntax`. + \endrst + */ void write(BasicCStringRef format, ArgList args) { BasicFormatter(args, *this).format(format); @@ -3130,10 +2946,10 @@ public: } /** - \rst - Formats *value* and writes it to the stream. - \endrst - */ + \rst + Formats *value* and writes it to the stream. + \endrst + */ BasicWriter &operator<<(ULongLong value) { return *this << IntFormatSpec(value); @@ -3146,11 +2962,11 @@ public: } /** - \rst - Formats *value* using the general format for floating-point numbers - (``'g'``) and writes it to the stream. - \endrst - */ + \rst + Formats *value* using the general format for floating-point numbers + (``'g'``) and writes it to the stream. + \endrst + */ BasicWriter &operator<<(long double value) { write_double(value, FormatSpec()); @@ -3158,8 +2974,8 @@ public: } /** - Writes a character to the stream. - */ + Writes a character to the stream. + */ BasicWriter &operator<<(char value) { buffer_.push_back(value); @@ -3174,10 +2990,10 @@ public: } /** - \rst - Writes *value* to the stream. - \endrst - */ + \rst + Writes *value* to the stream. + \endrst + */ BasicWriter &operator<<(fmt::BasicStringRef value) { const Char *str = value.data(); @@ -3209,15 +3025,9 @@ public: return *this; } - void clear() FMT_NOEXCEPT - { - buffer_.clear(); - } + void clear() FMT_NOEXCEPT { buffer_.clear(); } - Buffer &buffer() FMT_NOEXCEPT - { - return buffer_; - } + Buffer &buffer() FMT_NOEXCEPT { return buffer_; } }; template @@ -3582,10 +3392,7 @@ void BasicWriter::write_double(T value, const FormatSpec &spec) } // 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++ = '%'; @@ -3616,7 +3423,7 @@ void BasicWriter::write_double(T value, const FormatSpec &spec) // Format using snprintf. Char fill = internal::CharTraits::cast(spec.fill()); unsigned n = 0; - Char *start = FMT_NULL; + Char *start = 0; for (;;) { std::size_t buffer_size = buffer_.capacity() - offset; @@ -3680,66 +3487,66 @@ void BasicWriter::write_double(T value, const FormatSpec &spec) } /** -\rst -This class template provides operations for formatting and writing data -into a character stream. The output is stored in a memory buffer that grows -dynamically. + \rst + This class template provides operations for formatting and writing data + into a character stream. The output is stored in a memory buffer that grows + dynamically. -You can use one of the following typedefs for common character types -and the standard allocator: + You can use one of the following typedefs for common character types + and the standard allocator: -+---------------+-----------------------------------------------------+ -| Type | Definition | -+===============+=====================================================+ -| MemoryWriter | BasicMemoryWriter> | -+---------------+-----------------------------------------------------+ -| WMemoryWriter | BasicMemoryWriter> | -+---------------+-----------------------------------------------------+ + +---------------+-----------------------------------------------------+ + | Type | Definition | + +===============+=====================================================+ + | MemoryWriter | BasicMemoryWriter> | + +---------------+-----------------------------------------------------+ + | WMemoryWriter | BasicMemoryWriter> | + +---------------+-----------------------------------------------------+ -**Example**:: + **Example**:: -MemoryWriter out; -out << "The answer is " << 42 << "\n"; -out.write("({:+f}, {:+f})", -3.14, 3.14); + MemoryWriter out; + out << "The answer is " << 42 << "\n"; + out.write("({:+f}, {:+f})", -3.14, 3.14); -This will write the following output to the ``out`` object: + This will write the following output to the ``out`` object: -.. code-block:: none + .. code-block:: none -The answer is 42 -(-3.140000, +3.140000) + The answer is 42 + (-3.140000, +3.140000) -The output can be converted to an ``std::string`` with ``out.str()`` or -accessed as a C string with ``out.c_str()``. -\endrst -*/ + The output can be converted to an ``std::string`` with ``out.str()`` or + accessed as a C string with ``out.c_str()``. + \endrst + */ template > -class BasicMemoryWriter: public BasicWriter +class BasicMemoryWriter : public BasicWriter { private: internal::MemoryBuffer buffer_; public: explicit BasicMemoryWriter(const Allocator& alloc = Allocator()) - : BasicWriter(buffer_), buffer_(alloc) - {} + : BasicWriter(buffer_), buffer_(alloc) {} #if FMT_USE_RVALUE_REFERENCES /** - \rst - Constructs a :class:`fmt::BasicMemoryWriter` object moving the content - of the other object to it. - \endrst - */ + \rst + Constructs a :class:`fmt::BasicMemoryWriter` object moving the content + of the other object to it. + \endrst + */ BasicMemoryWriter(BasicMemoryWriter &&other) : BasicWriter(buffer_), buffer_(std::move(other.buffer_)) - {} + { + } /** - \rst - Moves the content of the other ``BasicMemoryWriter`` object to this one. - \endrst - */ + \rst + Moves the content of the other ``BasicMemoryWriter`` object to this one. + \endrst + */ BasicMemoryWriter &operator=(BasicMemoryWriter &&other) { buffer_ = std::move(other.buffer_); @@ -3752,52 +3559,50 @@ typedef BasicMemoryWriter MemoryWriter; typedef BasicMemoryWriter WMemoryWriter; /** -\rst -This class template provides operations for formatting and writing data -into a fixed-size array. For writing into a dynamically growing buffer -use :class:`fmt::BasicMemoryWriter`. + \rst + This class template provides operations for formatting and writing data + into a fixed-size array. For writing into a dynamically growing buffer + use :class:`fmt::BasicMemoryWriter`. -Any write method will throw ``std::runtime_error`` if the output doesn't fit -into the array. + Any write method will throw ``std::runtime_error`` if the output doesn't fit + into the array. -You can use one of the following typedefs for common character types: + You can use one of the following typedefs for common character types: -+--------------+---------------------------+ -| Type | Definition | -+==============+===========================+ -| ArrayWriter | BasicArrayWriter | -+--------------+---------------------------+ -| WArrayWriter | BasicArrayWriter | -+--------------+---------------------------+ -\endrst -*/ + +--------------+---------------------------+ + | Type | Definition | + +==============+===========================+ + | ArrayWriter | BasicArrayWriter | + +--------------+---------------------------+ + | WArrayWriter | BasicArrayWriter | + +--------------+---------------------------+ + \endrst + */ template -class BasicArrayWriter: public BasicWriter +class BasicArrayWriter : public BasicWriter { private: internal::FixedBuffer buffer_; public: /** - \rst - Constructs a :class:`fmt::BasicArrayWriter` object for *array* of the - given size. - \endrst - */ + \rst + Constructs a :class:`fmt::BasicArrayWriter` object for *array* of the + given size. + \endrst + */ BasicArrayWriter(Char *array, std::size_t size) - : BasicWriter(buffer_), buffer_(array, size) - {} + : BasicWriter(buffer_), buffer_(array, size) {} /** - \rst - Constructs a :class:`fmt::BasicArrayWriter` object for *array* of the - size known at compile time. - \endrst - */ + \rst + Constructs a :class:`fmt::BasicArrayWriter` object for *array* of the + size known at compile time. + \endrst + */ template - explicit BasicArrayWriter(Char(&array)[SIZE]) - : BasicWriter(buffer_), buffer_(array, SIZE) - {} + explicit BasicArrayWriter(Char (&array)[SIZE]) + : BasicWriter(buffer_), buffer_(array, SIZE) {} }; typedef BasicArrayWriter ArrayWriter; @@ -3811,39 +3616,39 @@ 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); public: /** - \rst - Constructs a :class:`fmt::WindowsError` object with the description - of the form + \rst + Constructs a :class:`fmt::WindowsError` object with the description + of the form - .. parsed-literal:: - **: ** + .. parsed-literal:: + **: ** - where ** is the formatted message and ** is the - system message corresponding to the error code. - *error_code* is a Windows error code as given by ``GetLastError``. - If *error_code* is not a valid error code such as -1, the system message - will look like "error -1". + where ** is the formatted message and ** is the + system message corresponding to the error code. + *error_code* is a Windows error code as given by ``GetLastError``. + If *error_code* is not a valid error code such as -1, the system message + will look like "error -1". - **Example**:: + **Example**:: - // This throws a WindowsError with the description - // cannot open file 'madeup': The system cannot find the file specified. - // or similar (system message may vary). - const char *filename = "madeup"; - LPOFSTRUCT of = LPOFSTRUCT(); - HFILE file = OpenFile(filename, &of, OF_READ); - if (file == HFILE_ERROR) { - throw fmt::WindowsError(GetLastError(), - "cannot open file '{}'", filename); - } - \endrst + // This throws a WindowsError with the description + // cannot open file 'madeup': The system cannot find the file specified. + // or similar (system message may vary). + const char *filename = "madeup"; + LPOFSTRUCT of = LPOFSTRUCT(); + HFILE file = OpenFile(filename, &of, OF_READ); + if (file == HFILE_ERROR) { + throw fmt::WindowsError(GetLastError(), + "cannot open file '{}'", filename); + } + \endrst */ WindowsError(int error_code, CStringRef message) { @@ -3859,27 +3664,24 @@ 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 -to specify color (experimental). -Example: -print_colored(fmt::RED, "Elapsed time: {0:.2f} seconds", 1.23); -*/ + Formats a string and prints it to stdout using ANSI escape sequences + to specify color (experimental). + Example: + print_colored(fmt::RED, "Elapsed time: {0:.2f} seconds", 1.23); + */ FMT_API void print_colored(Color c, CStringRef format, ArgList args); /** -\rst -Formats arguments and returns the result as a string. + \rst + Formats arguments and returns the result as a string. -**Example**:: + **Example**:: -std::string message = format("The answer is {}", 42); -\endrst + std::string message = format("The answer is {}", 42); + \endrst */ inline std::string format(CStringRef format_str, ArgList args) { @@ -3896,39 +3698,90 @@ inline std::wstring format(WCStringRef format_str, ArgList args) } /** -\rst -Prints formatted data to the file *f*. + \rst + Prints formatted data to the file *f*. -**Example**:: + **Example**:: -print(stderr, "Don't {}!", "panic"); -\endrst -*/ + print(stderr, "Don't {}!", "panic"); + \endrst + */ FMT_API void print(std::FILE *f, CStringRef format_str, ArgList args); /** -\rst -Prints formatted data to ``stdout``. + \rst + Prints formatted data to ``stdout``. -**Example**:: + **Example**:: -print("Elapsed time: {0:.2f} seconds", 1.23); -\endrst -*/ + print("Elapsed time: {0:.2f} seconds", 1.23); + \endrst + */ FMT_API void print(CStringRef format_str, ArgList args); +template +void printf(BasicWriter &w, BasicCStringRef format, ArgList args) +{ + internal::PrintfFormatter(args).format(w, format); +} + /** -Fast integer formatter. + \rst + Formats arguments and returns the result as a string. + + **Example**:: + + std::string message = fmt::sprintf("The answer is %d", 42); + \endrst */ +inline std::string sprintf(CStringRef format, ArgList args) +{ + MemoryWriter w; + printf(w, format, args); + return w.str(); +} + +inline std::wstring sprintf(WCStringRef format, ArgList args) +{ + WMemoryWriter w; + printf(w, format, args); + return w.str(); +} + +/** + \rst + Prints formatted data to the file *f*. + + **Example**:: + + fmt::fprintf(stderr, "Don't %s!", "panic"); + \endrst + */ +FMT_API int fprintf(std::FILE *f, CStringRef format, ArgList args); + +/** + \rst + Prints formatted data to ``stdout``. + + **Example**:: + + fmt::printf("Elapsed time: %.2f seconds", 1.23); + \endrst + */ +inline int printf(CStringRef format, ArgList args) +{ + return fprintf(stdout, format, args); +} + +/** + Fast integer formatter. + */ 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::digits10 + 3 - }; + enum {BUFFER_SIZE = std::numeric_limits::digits10 + 3}; mutable char buffer_[BUFFER_SIZE]; char *str_; @@ -3981,12 +3834,9 @@ 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. */ std::size_t size() const @@ -3995,18 +3845,18 @@ public: } /** - Returns a pointer to the output buffer content. No terminating null - character is appended. - */ + Returns a pointer to the output buffer content. No terminating null + character is appended. + */ const char *data() const { return str_; } /** - Returns a pointer to the output buffer content with terminating null - character appended. - */ + Returns a pointer to the output buffer content with terminating null + character appended. + */ const char *c_str() const { buffer_[BUFFER_SIZE - 1] = '\0'; @@ -4014,10 +3864,10 @@ public: } /** - \rst - Returns the content of the output buffer as an ``std::string``. - \endrst - */ + \rst + Returns the content of the output buffer as an ``std::string``. + \endrst + */ std::string str() const { return std::string(str_, size()); @@ -4055,25 +3905,25 @@ inline void format_decimal(char *&buffer, T value) } /** -\rst -Returns a named argument for formatting functions. + \rst + Returns a named argument for formatting functions. -**Example**:: + **Example**:: -print("Elapsed time: {s:.2f} seconds", arg("s", 1.23)); + print("Elapsed time: {s:.2f} seconds", arg("s", 1.23)); -\endrst -*/ + \endrst + */ template -inline internal::NamedArgWithType arg(StringRef name, const T &arg) +inline internal::NamedArg arg(StringRef name, const T &arg) { - return internal::NamedArgWithType(name, arg); + return internal::NamedArg(name, arg); } template -inline internal::NamedArgWithType arg(WStringRef name, const T &arg) +inline internal::NamedArg arg(WStringRef name, const T &arg) { - return internal::NamedArgWithType(name, arg); + return internal::NamedArg(name, arg); } // The following two functions are deleted intentionally to disable @@ -4102,6 +3952,7 @@ void arg(WStringRef, const internal::NamedArg&) FMT_DELETED_OR_UNDEFINED; #define FMT_ARG_N(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N #define FMT_RSEQ_N() 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 +#define FMT_CONCAT(a, b) a##b #define FMT_FOR_EACH_(N, f, ...) \ FMT_EXPAND(FMT_CONCAT(FMT_FOR_EACH, N)(f, __VA_ARGS__)) #define FMT_FOR_EACH(f, ...) \ @@ -4156,32 +4007,32 @@ void arg(WStringRef, const internal::NamedArg&) FMT_DELETED_OR_UNDEFINED; #endif // FMT_USE_VARIADIC_TEMPLATES /** -\rst -Defines a variadic function with the specified return type, function name -and argument types passed as variable arguments to this macro. + \rst + Defines a variadic function with the specified return type, function name + and argument types passed as variable arguments to this macro. -**Example**:: + **Example**:: -void print_error(const char *file, int line, const char *format, -fmt::ArgList args) { -fmt::print("{}: {}: ", file, line); -fmt::print(format, args); -} -FMT_VARIADIC(void, print_error, const char *, int, const char *) + void print_error(const char *file, int line, const char *format, + fmt::ArgList args) { + fmt::print("{}: {}: ", file, line); + fmt::print(format, args); + } + FMT_VARIADIC(void, print_error, const char *, int, const char *) -``FMT_VARIADIC`` is used for compatibility with legacy C++ compilers that -don't implement variadic templates. You don't have to use this macro if -you don't need legacy compiler support and can use variadic templates -directly:: + ``FMT_VARIADIC`` is used for compatibility with legacy C++ compilers that + don't implement variadic templates. You don't have to use this macro if + you don't need legacy compiler support and can use variadic templates + directly:: -template -void print_error(const char *file, int line, const char *format, -const Args & ... args) { -fmt::print("{}: {}: ", file, line); -fmt::print(format, args...); -} -\endrst -*/ + template + void print_error(const char *file, int line, const char *format, + const Args & ... args) { + fmt::print("{}: {}: ", file, line); + fmt::print(format, args...); + } + \endrst + */ #define FMT_VARIADIC(ReturnType, func, ...) \ FMT_VARIADIC_(char, ReturnType, func, return func, __VA_ARGS__) @@ -4193,19 +4044,19 @@ fmt::print(format, args...); #define FMT_CAPTURE_ARG_W_(id, index) ::fmt::arg(L###id, id) /** -\rst -Convenient macro to capture the arguments' names and values into several -``fmt::arg(name, value)``. + \rst + Convenient macro to capture the arguments' names and values into several + ``fmt::arg(name, value)``. -**Example**:: + **Example**:: -int x = 1, y = 2; -print("point: ({x}, {y})", FMT_CAPTURE(x, y)); -// same as: -// print("point: ({x}, {y})", arg("x", x), arg("y", y)); + int x = 1, y = 2; + print("point: ({x}, {y})", FMT_CAPTURE(x, y)); + // same as: + // print("point: ({x}, {y})", arg("x", x), arg("y", y)); -\endrst -*/ + \endrst + */ #define FMT_CAPTURE(...) FMT_FOR_EACH(FMT_CAPTURE_ARG_, __VA_ARGS__) #define FMT_CAPTURE_W(...) FMT_FOR_EACH(FMT_CAPTURE_ARG_W_, __VA_ARGS__) @@ -4216,7 +4067,12 @@ FMT_VARIADIC(std::string, format, CStringRef) FMT_VARIADIC_W(std::wstring, format, WCStringRef) FMT_VARIADIC(void, print, CStringRef) FMT_VARIADIC(void, print, std::FILE *, CStringRef) + FMT_VARIADIC(void, print_colored, Color, CStringRef) +FMT_VARIADIC(std::string, sprintf, CStringRef) +FMT_VARIADIC_W(std::wstring, sprintf, WCStringRef) +FMT_VARIADIC(int, printf, CStringRef) +FMT_VARIADIC(int, fprintf, std::FILE *, CStringRef) namespace internal { @@ -4294,7 +4150,7 @@ inline internal::Arg BasicFormatter::get_arg( template inline internal::Arg BasicFormatter::parse_arg_index(const Char *&s) { - const char *error = FMT_NULL; + const char *error = 0; internal::Arg arg = *s < '0' || *s > '9' ? next_arg(error) : get_arg(internal::parse_nonnegative_int(s), error); if (error) @@ -4316,7 +4172,7 @@ inline internal::Arg BasicFormatter::parse_arg_name(const Char *&s) c = *++s; } while (internal::is_name_start(c) || ('0' <= c && c <= '9')); - const char *error = FMT_NULL; + const char *error = 0; internal::Arg arg = get_arg(BasicStringRef(start, s - start), error); if (error) FMT_THROW(FormatError(error)); @@ -4446,7 +4302,7 @@ const Char *BasicFormatter::format( default: FMT_THROW(FormatError("width is not integer")); } - if (value >(std::numeric_limits::max)()) + if (value > (std::numeric_limits::max)()) FMT_THROW(FormatError("number is too big")); spec.width_ = static_cast(value); } @@ -4489,7 +4345,7 @@ const Char *BasicFormatter::format( default: FMT_THROW(FormatError("precision is not integer")); } - if (value >(std::numeric_limits::max)()) + if (value > (std::numeric_limits::max)()) FMT_THROW(FormatError("number is too big")); spec.precision_ = static_cast(value); } @@ -4569,9 +4425,9 @@ struct UdlArg const Char *str; template - NamedArgWithType operator=(T &&value) const + NamedArg operator=(T &&value) const { - return { str, std::forward(value) }; + return {str, std::forward(value)}; } }; @@ -4581,45 +4437,45 @@ inline namespace literals { /** -\rst -C++11 literal equivalent of :func:`fmt::format`. + \rst + C++11 literal equivalent of :func:`fmt::format`. -**Example**:: + **Example**:: -using namespace fmt::literals; -std::string message = "The answer is {}"_format(42); -\endrst -*/ + using namespace fmt::literals; + std::string message = "The answer is {}"_format(42); + \endrst + */ inline internal::UdlFormat operator"" _format(const char *s, std::size_t) { - return { s }; + return {s}; } inline internal::UdlFormat operator"" _format(const wchar_t *s, std::size_t) { - return { s }; + return {s}; } /** -\rst -C++11 literal equivalent of :func:`fmt::arg`. + \rst + C++11 literal equivalent of :func:`fmt::arg`. -**Example**:: + **Example**:: -using namespace fmt::literals; -print("Elapsed time: {s:.2f} seconds", "s"_a=1.23); -\endrst -*/ + using namespace fmt::literals; + print("Elapsed time: {s:.2f} seconds", "s"_a=1.23); + \endrst + */ inline internal::UdlArg operator"" _a(const char *s, std::size_t) { - return { s }; + return {s}; } inline internal::UdlArg operator"" _a(const wchar_t *s, std::size_t) { - return { s }; + return {s}; } } // inline namespace literals diff --git a/vendor/spdlog/spdlog/fmt/bundled/ostream.cc b/vendor/spdlog/spdlog/fmt/bundled/ostream.cc index 2148f3c1..bcb67fe1 100644 --- a/vendor/spdlog/spdlog/fmt/bundled/ostream.cc +++ b/vendor/spdlog/spdlog/fmt/bundled/ostream.cc @@ -1,37 +1,43 @@ /* -Formatting library for C++ - std::ostream support + Formatting library for C++ - std::ostream support -Copyright (c) 2012 - 2016, Victor Zverovich -All rights reserved. + Copyright (c) 2012 - 2016, Victor Zverovich + All rights reserved. -For the license information refer to format.h. -*/ + For the license information refer to format.h. + */ #include "ostream.h" namespace fmt { - namespace internal { - FMT_FUNC void write(std::ostream &os, Writer &w) - { - const char *data = w.data(); - typedef internal::MakeUnsigned::Type UnsignedStreamSize; - UnsignedStreamSize size = w.size(); - UnsignedStreamSize max_size = - internal::to_unsigned((std::numeric_limits::max)()); - do { - UnsignedStreamSize n = size <= max_size ? size : max_size; - os.write(data, static_cast(n)); - data += n; - size -= n; - } while (size != 0); - } - } +namespace { +// Write the content of w to os. +void write(std::ostream &os, Writer &w) { + const char *data = w.data(); + typedef internal::MakeUnsigned::Type UnsignedStreamSize; + UnsignedStreamSize size = w.size(); + UnsignedStreamSize max_size = + internal::to_unsigned((std::numeric_limits::max)()); + do { + UnsignedStreamSize n = size <= max_size ? size : max_size; + os.write(data, static_cast(n)); + data += n; + size -= n; + } while (size != 0); +} +} - FMT_FUNC void print(std::ostream &os, CStringRef format_str, ArgList args) - { - MemoryWriter w; - w.write(format_str, args); - internal::write(os, w); - } +FMT_FUNC void print(std::ostream &os, CStringRef format_str, ArgList args) { + MemoryWriter w; + w.write(format_str, args); + write(os, w); +} + +FMT_FUNC int fprintf(std::ostream &os, CStringRef format, ArgList args) { + MemoryWriter w; + printf(w, format, args); + write(os, w); + return static_cast(w.size()); +} } // namespace fmt diff --git a/vendor/spdlog/spdlog/fmt/bundled/ostream.h b/vendor/spdlog/spdlog/fmt/bundled/ostream.h index 3bdb375b..c52646d0 100644 --- a/vendor/spdlog/spdlog/fmt/bundled/ostream.h +++ b/vendor/spdlog/spdlog/fmt/bundled/ostream.h @@ -1,17 +1,16 @@ /* -Formatting library for C++ - std::ostream support + Formatting library for C++ - std::ostream support -Copyright (c) 2012 - 2016, Victor Zverovich -All rights reserved. + Copyright (c) 2012 - 2016, Victor Zverovich + All rights reserved. -For the license information refer to format.h. -*/ + For the license information refer to format.h. + */ #ifndef FMT_OSTREAM_H_ #define FMT_OSTREAM_H_ -// commented out by spdlog -// #include "format.h" +#include "format.h" #include namespace fmt @@ -21,7 +20,7 @@ namespace internal { template -class FormatBuf: public std::basic_streambuf +class FormatBuf : public std::basic_streambuf { private: typedef typename std::basic_streambuf::int_type int_type; @@ -31,7 +30,7 @@ private: Char *start_; public: - FormatBuf(Buffer &buffer): buffer_(buffer), start_(&buffer[0]) + FormatBuf(Buffer &buffer) : buffer_(buffer), start_(&buffer[0]) { this->setp(start_, start_ + buffer_.capacity()); } @@ -46,7 +45,7 @@ public: start_ = &buffer_[0]; start_[buf_size] = traits_type::to_char_type(ch); - this->setp(start_ + buf_size + 1, start_ + buf_size * 2); + this->setp(start_+ buf_size + 1, start_ + buf_size * 2); } return ch; } @@ -59,7 +58,7 @@ public: Yes &convert(std::ostream &); -struct DummyStream: std::ostream +struct DummyStream : std::ostream { DummyStream(); // Suppress a bogus warning in MSVC. // Hide all operator<< overloads from std::ostream. @@ -77,15 +76,12 @@ struct ConvertToIntImpl value = sizeof(convert(get() << get())) == sizeof(No) }; }; - -// Write the content of w to os. -void write(std::ostream &os, Writer &w); } // namespace internal // Formats a value. template -void format_arg(BasicFormatter &f, - const Char *&format_str, const T &value) +void format(BasicFormatter &f, + const Char *&format_str, const T &value) { internal::MemoryBuffer buffer; @@ -99,16 +95,28 @@ void format_arg(BasicFormatter &f, } /** -\rst -Prints formatted data to the stream *os*. + \rst + Prints formatted data to the stream *os*. -**Example**:: + **Example**:: -print(cerr, "Don't {}!", "panic"); -\endrst -*/ + print(cerr, "Don't {}!", "panic"); + \endrst + */ 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) } // namespace fmt #ifdef FMT_HEADER_ONLY diff --git a/vendor/spdlog/spdlog/fmt/bundled/posix.cc b/vendor/spdlog/spdlog/fmt/bundled/posix.cc new file mode 100644 index 00000000..76eb7f05 --- /dev/null +++ b/vendor/spdlog/spdlog/fmt/bundled/posix.cc @@ -0,0 +1,238 @@ +/* + A C++ interface to POSIX functions. + + Copyright (c) 2012 - 2016, Victor Zverovich + All rights reserved. + + For the license information refer to format.h. + */ + +// Disable bogus MSVC warnings. +#ifndef _CRT_SECURE_NO_WARNINGS +# define _CRT_SECURE_NO_WARNINGS +#endif + +#include "posix.h" + +#include +#include +#include + +#ifndef _WIN32 +# include +#else +# include +# include + +# define O_CREAT _O_CREAT +# define O_TRUNC _O_TRUNC + +# ifndef S_IRUSR +# define S_IRUSR _S_IREAD +# endif + +# ifndef S_IWUSR +# define S_IWUSR _S_IWRITE +# endif + +# ifdef __MINGW32__ +# define _SH_DENYNO 0x40 +# endif + +#endif // _WIN32 + +#ifdef fileno +# undef fileno +#endif + +namespace { +#ifdef _WIN32 +// Return type of read and write functions. +typedef int RWResult; + +// On Windows the count argument to read and write is unsigned, so convert +// it from size_t preventing integer overflow. +inline unsigned convert_rwcount(std::size_t count) { + return count <= UINT_MAX ? static_cast(count) : UINT_MAX; +} +#else +// Return type of read and write functions. +typedef ssize_t RWResult; + +inline std::size_t convert_rwcount(std::size_t count) { return count; } +#endif +} + +fmt::BufferedFile::~BufferedFile() FMT_NOEXCEPT { + if (file_ && FMT_SYSTEM(fclose(file_)) != 0) + fmt::report_system_error(errno, "cannot close file"); +} + +fmt::BufferedFile::BufferedFile( + fmt::CStringRef filename, fmt::CStringRef mode) { + FMT_RETRY_VAL(file_, FMT_SYSTEM(fopen(filename.c_str(), mode.c_str())), 0); + if (!file_) + FMT_THROW(SystemError(errno, "cannot open file {}", filename)); +} + +void fmt::BufferedFile::close() { + if (!file_) + return; + int result = FMT_SYSTEM(fclose(file_)); + file_ = 0; + if (result != 0) + FMT_THROW(SystemError(errno, "cannot close file")); +} + +// A macro used to prevent expansion of fileno on broken versions of MinGW. +#define FMT_ARGS + +int fmt::BufferedFile::fileno() const { + int fd = FMT_POSIX_CALL(fileno FMT_ARGS(file_)); + if (fd == -1) + FMT_THROW(SystemError(errno, "cannot get file descriptor")); + return fd; +} + +fmt::File::File(fmt::CStringRef path, int oflag) { + int mode = S_IRUSR | S_IWUSR; +#if defined(_WIN32) && !defined(__MINGW32__) + fd_ = -1; + FMT_POSIX_CALL(sopen_s(&fd_, path.c_str(), oflag, _SH_DENYNO, mode)); +#else + FMT_RETRY(fd_, FMT_POSIX_CALL(open(path.c_str(), oflag, mode))); +#endif + if (fd_ == -1) + FMT_THROW(SystemError(errno, "cannot open file {}", path)); +} + +fmt::File::~File() FMT_NOEXCEPT { + // Don't retry close in case of EINTR! + // See http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html + if (fd_ != -1 && FMT_POSIX_CALL(close(fd_)) != 0) + fmt::report_system_error(errno, "cannot close file"); +} + +void fmt::File::close() { + if (fd_ == -1) + return; + // Don't retry close in case of EINTR! + // See http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html + int result = FMT_POSIX_CALL(close(fd_)); + fd_ = -1; + if (result != 0) + FMT_THROW(SystemError(errno, "cannot close file")); +} + +fmt::LongLong fmt::File::size() const { +#ifdef _WIN32 + // Use GetFileSize instead of GetFileSizeEx for the case when _WIN32_WINNT + // is less than 0x0500 as is the case with some default MinGW builds. + // Both functions support large file sizes. + DWORD size_upper = 0; + HANDLE handle = reinterpret_cast(_get_osfhandle(fd_)); + DWORD size_lower = FMT_SYSTEM(GetFileSize(handle, &size_upper)); + if (size_lower == INVALID_FILE_SIZE) { + DWORD error = GetLastError(); + if (error != NO_ERROR) + FMT_THROW(WindowsError(GetLastError(), "cannot get file size")); + } + fmt::ULongLong long_size = size_upper; + return (long_size << sizeof(DWORD) * CHAR_BIT) | size_lower; +#else + typedef struct stat Stat; + Stat file_stat = Stat(); + if (FMT_POSIX_CALL(fstat(fd_, &file_stat)) == -1) + FMT_THROW(SystemError(errno, "cannot get file attributes")); + FMT_STATIC_ASSERT(sizeof(fmt::LongLong) >= sizeof(file_stat.st_size), + "return type of File::size is not large enough"); + return file_stat.st_size; +#endif +} + +std::size_t fmt::File::read(void *buffer, std::size_t count) { + RWResult result = 0; + FMT_RETRY(result, FMT_POSIX_CALL(read(fd_, buffer, convert_rwcount(count)))); + if (result < 0) + FMT_THROW(SystemError(errno, "cannot read from file")); + return internal::to_unsigned(result); +} + +std::size_t fmt::File::write(const void *buffer, std::size_t count) { + RWResult result = 0; + FMT_RETRY(result, FMT_POSIX_CALL(write(fd_, buffer, convert_rwcount(count)))); + if (result < 0) + FMT_THROW(SystemError(errno, "cannot write to file")); + return internal::to_unsigned(result); +} + +fmt::File fmt::File::dup(int fd) { + // Don't retry as dup doesn't return EINTR. + // http://pubs.opengroup.org/onlinepubs/009695399/functions/dup.html + int new_fd = FMT_POSIX_CALL(dup(fd)); + if (new_fd == -1) + FMT_THROW(SystemError(errno, "cannot duplicate file descriptor {}", fd)); + return File(new_fd); +} + +void fmt::File::dup2(int fd) { + int result = 0; + FMT_RETRY(result, FMT_POSIX_CALL(dup2(fd_, fd))); + if (result == -1) { + FMT_THROW(SystemError(errno, + "cannot duplicate file descriptor {} to {}", fd_, fd)); + } +} + +void fmt::File::dup2(int fd, ErrorCode &ec) FMT_NOEXCEPT { + int result = 0; + FMT_RETRY(result, FMT_POSIX_CALL(dup2(fd_, fd))); + if (result == -1) + ec = ErrorCode(errno); +} + +void fmt::File::pipe(File &read_end, File &write_end) { + // Close the descriptors first to make sure that assignments don't throw + // and there are no leaks. + read_end.close(); + write_end.close(); + int fds[2] = {}; +#ifdef _WIN32 + // Make the default pipe capacity same as on Linux 2.6.11+. + enum { DEFAULT_CAPACITY = 65536 }; + int result = FMT_POSIX_CALL(pipe(fds, DEFAULT_CAPACITY, _O_BINARY)); +#else + // Don't retry as the pipe function doesn't return EINTR. + // http://pubs.opengroup.org/onlinepubs/009696799/functions/pipe.html + int result = FMT_POSIX_CALL(pipe(fds)); +#endif + if (result != 0) + FMT_THROW(SystemError(errno, "cannot create pipe")); + // The following assignments don't throw because read_fd and write_fd + // are closed. + read_end = File(fds[0]); + write_end = File(fds[1]); +} + +fmt::BufferedFile fmt::File::fdopen(const char *mode) { + // Don't retry as fdopen doesn't return EINTR. + FILE *f = FMT_POSIX_CALL(fdopen(fd_, mode)); + if (!f) + FMT_THROW(SystemError(errno, "cannot associate stream with file descriptor")); + BufferedFile file(f); + fd_ = -1; + return file; +} + +long fmt::getpagesize() { +#ifdef _WIN32 + SYSTEM_INFO si; + GetSystemInfo(&si); + return si.dwPageSize; +#else + long size = FMT_POSIX_CALL(sysconf(_SC_PAGESIZE)); + if (size < 0) + FMT_THROW(SystemError(errno, "cannot get memory page size")); + return size; +#endif +} diff --git a/vendor/spdlog/spdlog/fmt/bundled/posix.h b/vendor/spdlog/spdlog/fmt/bundled/posix.h new file mode 100644 index 00000000..859fcaa7 --- /dev/null +++ b/vendor/spdlog/spdlog/fmt/bundled/posix.h @@ -0,0 +1,443 @@ +/* + A C++ interface to POSIX functions. + + Copyright (c) 2012 - 2016, Victor Zverovich + All rights reserved. + + For the license information refer to format.h. + */ + +#ifndef FMT_POSIX_H_ +#define FMT_POSIX_H_ + +#if defined(__MINGW32__) || defined(__CYGWIN__) +// Workaround MinGW bug https://sourceforge.net/p/mingw/bugs/2024/. +# undef __STRICT_ANSI__ +#endif + +#include +#include // for O_RDONLY +#include // for locale_t +#include +#include // for strtod_l + +#include + +#if defined __APPLE__ || defined(__FreeBSD__) +# include // for LC_NUMERIC_MASK on OS X +#endif + +#include "format.h" + +#ifndef FMT_POSIX +# if defined(_WIN32) && !defined(__MINGW32__) +// Fix warnings about deprecated symbols. +# define FMT_POSIX(call) _##call +# else +# define FMT_POSIX(call) call +# endif +#endif + +// Calls to system functions are wrapped in FMT_SYSTEM for testability. +#ifdef FMT_SYSTEM +# define FMT_POSIX_CALL(call) FMT_SYSTEM(call) +#else +# define FMT_SYSTEM(call) call +# ifdef _WIN32 +// Fix warnings about deprecated symbols. +# define FMT_POSIX_CALL(call) ::_##call +# else +# define FMT_POSIX_CALL(call) ::call +# endif +#endif + +#if FMT_GCC_VERSION >= 407 +# define FMT_UNUSED __attribute__((unused)) +#else +# define FMT_UNUSED +#endif + +#ifndef FMT_USE_STATIC_ASSERT +# define FMT_USE_STATIC_ASSERT 0 +#endif + +#if FMT_USE_STATIC_ASSERT || FMT_HAS_FEATURE(cxx_static_assert) || \ + (FMT_GCC_VERSION >= 403 && FMT_HAS_GXX_CXX11) || _MSC_VER >= 1600 +# define FMT_STATIC_ASSERT(cond, message) static_assert(cond, message) +#else +# define FMT_CONCAT_(a, b) FMT_CONCAT(a, b) +# define FMT_STATIC_ASSERT(cond, message) \ + typedef int FMT_CONCAT_(Assert, __LINE__)[(cond) ? 1 : -1] FMT_UNUSED +#endif + +// Retries the expression while it evaluates to error_result and errno +// equals to EINTR. +#ifndef _WIN32 +# define FMT_RETRY_VAL(result, expression, error_result) \ + do { \ + result = (expression); \ + } while (result == error_result && errno == EINTR) +#else +# define FMT_RETRY_VAL(result, expression, error_result) result = (expression) +#endif + +#define FMT_RETRY(result, expression) FMT_RETRY_VAL(result, expression, -1) + +namespace fmt +{ + +// An error code. +class ErrorCode +{ +private: + int value_; + +public: +explicit ErrorCode(int value = 0) FMT_NOEXCEPT : + value_(value) {} + + int get() const FMT_NOEXCEPT + { + return value_; + } +}; + +// A buffered file. +class BufferedFile +{ +private: + FILE *file_; + + friend class File; + + explicit BufferedFile(FILE *f) : file_(f) {} + +public: + // Constructs a BufferedFile object which doesn't represent any file. +BufferedFile() FMT_NOEXCEPT : + file_(0) {} + + // Destroys the object closing the file it represents if any. + ~BufferedFile() FMT_NOEXCEPT; + +#if !FMT_USE_RVALUE_REFERENCES + // Emulate a move constructor and a move assignment operator if rvalue + // references are not supported. + +private: + // A proxy object to emulate a move constructor. + // It is private to make it impossible call operator Proxy directly. + struct Proxy + { + FILE *file; + }; + +public: + // A "move constructor" for moving from a temporary. +BufferedFile(Proxy p) FMT_NOEXCEPT : + file_(p.file) {} + + // A "move constructor" for moving from an lvalue. +BufferedFile(BufferedFile &f) FMT_NOEXCEPT : + file_(f.file_) + { + f.file_ = 0; + } + + // A "move assignment operator" for moving from a temporary. + BufferedFile &operator=(Proxy p) + { + close(); + file_ = p.file; + return *this; + } + + // A "move assignment operator" for moving from an lvalue. + BufferedFile &operator=(BufferedFile &other) + { + close(); + file_ = other.file_; + other.file_ = 0; + return *this; + } + + // Returns a proxy object for moving from a temporary: + // BufferedFile file = BufferedFile(...); + operator Proxy() FMT_NOEXCEPT + { + Proxy p = {file_}; + file_ = 0; + return p; + } + +#else +private: + FMT_DISALLOW_COPY_AND_ASSIGN(BufferedFile); + +public: +BufferedFile(BufferedFile &&other) FMT_NOEXCEPT : + file_(other.file_) + { + other.file_ = 0; + } + + BufferedFile& operator=(BufferedFile &&other) + { + close(); + file_ = other.file_; + other.file_ = 0; + return *this; + } +#endif + + // Opens a file. + BufferedFile(CStringRef filename, CStringRef mode); + + // Closes the file. + void close(); + + // Returns the pointer to a FILE object representing this file. + FILE *get() const FMT_NOEXCEPT + { + return file_; + } + + // We place parentheses around fileno to workaround a bug in some versions + // of MinGW that define fileno as a macro. + int (fileno)() const; + + void print(CStringRef format_str, const ArgList &args) + { + fmt::print(file_, format_str, args); + } + FMT_VARIADIC(void, print, CStringRef) +}; + +// A file. Closed file is represented by a File object with descriptor -1. +// Methods that are not declared with FMT_NOEXCEPT may throw +// fmt::SystemError in case of failure. Note that some errors such as +// closing the file multiple times will cause a crash on Windows rather +// than an exception. You can get standard behavior by overriding the +// invalid parameter handler with _set_invalid_parameter_handler. +class File +{ +private: + int fd_; // File descriptor. + + // Constructs a File object with a given descriptor. + explicit File(int fd) : fd_(fd) {} + +public: + // Possible values for the oflag argument to the constructor. + enum + { + RDONLY = FMT_POSIX(O_RDONLY), // Open for reading only. + WRONLY = FMT_POSIX(O_WRONLY), // Open for writing only. + RDWR = FMT_POSIX(O_RDWR) // Open for reading and writing. + }; + + // Constructs a File object which doesn't represent any file. +File() FMT_NOEXCEPT : + fd_(-1) {} + + // Opens a file and constructs a File object representing this file. + File(CStringRef path, int oflag); + +#if !FMT_USE_RVALUE_REFERENCES + // Emulate a move constructor and a move assignment operator if rvalue + // references are not supported. + +private: + // A proxy object to emulate a move constructor. + // It is private to make it impossible call operator Proxy directly. + struct Proxy + { + int fd; + }; + +public: + // A "move constructor" for moving from a temporary. +File(Proxy p) FMT_NOEXCEPT : + fd_(p.fd) {} + + // A "move constructor" for moving from an lvalue. +File(File &other) FMT_NOEXCEPT : + fd_(other.fd_) + { + other.fd_ = -1; + } + + // A "move assignment operator" for moving from a temporary. + File &operator=(Proxy p) + { + close(); + fd_ = p.fd; + return *this; + } + + // A "move assignment operator" for moving from an lvalue. + File &operator=(File &other) + { + close(); + fd_ = other.fd_; + other.fd_ = -1; + return *this; + } + + // Returns a proxy object for moving from a temporary: + // File file = File(...); + operator Proxy() FMT_NOEXCEPT + { + Proxy p = {fd_}; + fd_ = -1; + return p; + } + +#else +private: + FMT_DISALLOW_COPY_AND_ASSIGN(File); + +public: +File(File &&other) FMT_NOEXCEPT : + fd_(other.fd_) + { + other.fd_ = -1; + } + + File& operator=(File &&other) + { + close(); + fd_ = other.fd_; + other.fd_ = -1; + return *this; + } +#endif + + // Destroys the object closing the file it represents if any. + ~File() FMT_NOEXCEPT; + + // Returns the file descriptor. + int descriptor() const FMT_NOEXCEPT + { + return fd_; + } + + // Closes the file. + void close(); + + // Returns the file size. The size has signed type for consistency with + // stat::st_size. + LongLong size() const; + + // Attempts to read count bytes from the file into the specified buffer. + std::size_t read(void *buffer, std::size_t count); + + // Attempts to write count bytes from the specified buffer to the file. + std::size_t write(const void *buffer, std::size_t count); + + // Duplicates a file descriptor with the dup function and returns + // the duplicate as a file object. + static File dup(int fd); + + // Makes fd be the copy of this file descriptor, closing fd first if + // necessary. + void dup2(int fd); + + // Makes fd be the copy of this file descriptor, closing fd first if + // necessary. + void dup2(int fd, ErrorCode &ec) FMT_NOEXCEPT; + + // Creates a pipe setting up read_end and write_end file objects for reading + // and writing respectively. + static void pipe(File &read_end, File &write_end); + + // Creates a BufferedFile object associated with this file and detaches + // this File object from the file. + BufferedFile fdopen(const char *mode); +}; + +// Returns the memory page size. +long getpagesize(); + +#if (defined(LC_NUMERIC_MASK) || defined(_MSC_VER)) && \ + !defined(__ANDROID__) && !defined(__CYGWIN__) +# define FMT_LOCALE +#endif + +#ifdef FMT_LOCALE +// A "C" numeric locale. +class Locale +{ +private: +# ifdef _MSC_VER + typedef _locale_t locale_t; + + enum { LC_NUMERIC_MASK = LC_NUMERIC }; + + static locale_t newlocale(int category_mask, const char *locale, locale_t) + { + return _create_locale(category_mask, locale); + } + + static void freelocale(locale_t locale) + { + _free_locale(locale); + } + + static double strtod_l(const char *nptr, char **endptr, _locale_t locale) + { + return _strtod_l(nptr, endptr, locale); + } +# endif + + locale_t locale_; + + FMT_DISALLOW_COPY_AND_ASSIGN(Locale); + +public: + typedef locale_t Type; + + Locale() : locale_(newlocale(LC_NUMERIC_MASK, "C", NULL)) + { + if (!locale_) + FMT_THROW(fmt::SystemError(errno, "cannot create locale")); + } + ~Locale() + { + freelocale(locale_); + } + + Type get() const + { + return locale_; + } + + // Converts string to floating-point number and advances str past the end + // of the parsed input. + double strtod(const char *&str) const + { + char *end = 0; + double result = strtod_l(str, &end, locale_); + str = end; + return result; + } +}; +#endif // FMT_LOCALE +} // namespace fmt + +#if !FMT_USE_RVALUE_REFERENCES +namespace std +{ +// For compatibility with C++98. +inline fmt::BufferedFile &move(fmt::BufferedFile &f) +{ + return f; +} +inline fmt::File &move(fmt::File &f) +{ + return f; +} +} +#endif + +#endif // FMT_POSIX_H_ diff --git a/vendor/spdlog/spdlog/fmt/bundled/printf.h b/vendor/spdlog/spdlog/fmt/bundled/printf.h deleted file mode 100644 index 2b9ddfab..00000000 --- a/vendor/spdlog/spdlog/fmt/bundled/printf.h +++ /dev/null @@ -1,658 +0,0 @@ -/* -Formatting library for C++ - -Copyright (c) 2012 - 2016, Victor Zverovich -All rights reserved. - -For the license information refer to format.h. -*/ - -#ifndef FMT_PRINTF_H_ -#define FMT_PRINTF_H_ - -#include // std::fill_n -#include // std::numeric_limits - -#include "ostream.h" - -namespace fmt -{ -namespace internal -{ - -// Checks if a value fits in int - used to avoid warnings about comparing -// signed and unsigned integers. -template -struct IntChecker -{ - template - static bool fits_in_int(T value) - { - unsigned max = std::numeric_limits::max(); - return value <= max; - } - static bool fits_in_int(bool) - { - return true; - } -}; - -template <> -struct IntChecker -{ - template - static bool fits_in_int(T value) - { - return value >= std::numeric_limits::min() && - value <= std::numeric_limits::max(); - } - static bool fits_in_int(int) - { - return true; - } -}; - -class PrecisionHandler: public ArgVisitor -{ -public: - void report_unhandled_arg() - { - FMT_THROW(FormatError("precision is not integer")); - } - - template - int visit_any_int(T value) - { - if (!IntChecker::is_signed>::fits_in_int(value)) - FMT_THROW(FormatError("number is too big")); - return static_cast(value); - } -}; - -// IsZeroInt::visit(arg) returns true iff arg is a zero integer. -class IsZeroInt: public ArgVisitor -{ -public: - template - bool visit_any_int(T value) - { - return value == 0; - } -}; - -template -struct is_same -{ - enum - { - value = 0 - }; -}; - -template -struct is_same -{ - 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 -class ArgConverter: public ArgVisitor, void> -{ -private: - internal::Arg &arg_; - wchar_t type_; - - FMT_DISALLOW_COPY_AND_ASSIGN(ArgConverter); - -public: - ArgConverter(internal::Arg &arg, wchar_t type) - : arg_(arg), type_(type) - {} - - void visit_bool(bool value) - { - if (type_ != 's') - visit_any_int(value); - } - - template - void visit_any_int(U value) - { - bool is_signed = type_ == 'd' || type_ == 'i'; - using internal::Arg; - typedef typename internal::Conditional< - is_same::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(static_cast(value)); - } - else - { - arg_.type = Arg::UINT; - typedef typename internal::MakeUnsigned::Type Unsigned; - arg_.uint_value = static_cast(static_cast(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(value); - } - else - { - arg_.type = Arg::ULONG_LONG; - arg_.ulong_long_value = - static_cast::Type>(value); - } - } - } -}; - -// Converts an integer argument to char for printf. -class CharConverter: public ArgVisitor -{ -private: - internal::Arg &arg_; - - FMT_DISALLOW_COPY_AND_ASSIGN(CharConverter); - -public: - explicit CharConverter(internal::Arg &arg): arg_(arg) - {} - - template - void visit_any_int(T value) - { - arg_.type = internal::Arg::CHAR; - arg_.int_value = static_cast(value); - } -}; - -// Checks if an argument is a valid printf width specifier and sets -// left alignment if it is negative. -class WidthHandler: public ArgVisitor -{ -private: - FormatSpec &spec_; - - FMT_DISALLOW_COPY_AND_ASSIGN(WidthHandler); - -public: - explicit WidthHandler(FormatSpec &spec): spec_(spec) - {} - - void report_unhandled_arg() - { - FMT_THROW(FormatError("width is not integer")); - } - - template - unsigned visit_any_int(T value) - { - typedef typename internal::IntTraits::MainType UnsignedType; - UnsignedType width = static_cast(value); - if (internal::is_negative(value)) - { - spec_.align_ = ALIGN_LEFT; - width = 0 - width; - } - unsigned int_max = std::numeric_limits::max(); - if (width > int_max) - FMT_THROW(FormatError("number is too big")); - return static_cast(width); - } -}; -} // namespace internal - -/** -\rst -A ``printf`` argument formatter based on the `curiously recurring template -pattern `_. - -To use `~fmt::BasicPrintfArgFormatter` define a subclass that implements some -or all of the visit methods with the same signatures as the methods in -`~fmt::ArgVisitor`, for example, `~fmt::ArgVisitor::visit_int()`. -Pass the subclass as the *Impl* template parameter. When a formatting -function processes an argument, it will dispatch to a visit method -specific to the argument type. For example, if the argument type is -``double`` then the `~fmt::ArgVisitor::visit_double()` method of a subclass -will be called. If the subclass doesn't contain a method with this signature, -then a corresponding method of `~fmt::BasicPrintfArgFormatter` or its -superclass will be called. -\endrst -*/ -template -class BasicPrintfArgFormatter: public internal::ArgFormatterBase -{ -private: - void write_null_pointer() - { - this->spec().type_ = 0; - this->write("(nil)"); - } - - typedef internal::ArgFormatterBase Base; - -public: - /** - \rst - Constructs an argument formatter object. - *writer* is a reference to the output writer and *spec* contains format - specifier information for standard argument types. - \endrst - */ - BasicPrintfArgFormatter(BasicWriter &w, FormatSpec &s) - : internal::ArgFormatterBase(w, s) - {} - - /** Formats an argument of type ``bool``. */ - 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); - } - - /** Formats a character. */ - void visit_char(int value) - { - const FormatSpec &fmt_spec = this->spec(); - BasicWriter &w = this->writer(); - if (fmt_spec.type_ && fmt_spec.type_ != 'c') - w.write_int(value, fmt_spec); - typedef typename BasicWriter::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(value); - } - - /** Formats a null-terminated C string. */ - 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)"); - } - - /** Formats a pointer. */ - void visit_pointer(const void *value) - { - if (value) - return Base::visit_pointer(value); - this->spec().type_ = 0; - write_null_pointer(); - } - - /** Formats an argument of a custom (user-defined) type. */ - void visit_custom(internal::Arg::CustomValue c) - { - BasicFormatter formatter(ArgList(), this->writer()); - const Char format_str[] = { '}', 0 }; - const Char *format = format_str; - c.format(&formatter, c.value, &format); - } -}; - -/** The default printf argument formatter. */ -template -class PrintfArgFormatter - : public BasicPrintfArgFormatter, Char> -{ -public: - /** Constructs an argument formatter object. */ - PrintfArgFormatter(BasicWriter &w, FormatSpec &s) - : BasicPrintfArgFormatter, Char>(w, s) - {} -}; - -/** This template formats data and writes the output to a writer. */ -template > -class PrintfFormatter: private internal::FormatterBase -{ -private: - BasicWriter &writer_; - - void parse_flags(FormatSpec &spec, const Char *&s); - - // Returns the argument with specified index or, if arg_index is equal - // to the maximum unsigned value, the next argument. - internal::Arg get_arg( - const Char *s, - unsigned arg_index = (std::numeric_limits::max)()); - - // Parses argument index, flags and width and returns the argument index. - unsigned parse_header(const Char *&s, FormatSpec &spec); - -public: - /** - \rst - Constructs a ``PrintfFormatter`` object. References to the arguments and - the writer are stored in the formatter object so make sure they have - appropriate lifetimes. - \endrst - */ - explicit PrintfFormatter(const ArgList &al, BasicWriter &w) - : FormatterBase(al), writer_(w) - {} - - /** Formats stored arguments and writes the output to the writer. */ - FMT_API void format(BasicCStringRef format_str); -}; - -template -void PrintfFormatter::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 -internal::Arg PrintfFormatter::get_arg(const Char *s, - unsigned arg_index) -{ - (void)s; - const char *error = FMT_NULL; - internal::Arg arg = arg_index == std::numeric_limits::max() ? - next_arg(error) : FormatterBase::get_arg(arg_index - 1, error); - if (error) - FMT_THROW(FormatError(!*s ? "invalid format string" : error)); - return arg; -} - -template -unsigned PrintfFormatter::parse_header( - const Char *&s, FormatSpec &spec) -{ - unsigned arg_index = std::numeric_limits::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 = internal::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_ = internal::parse_nonnegative_int(s); - } - else if (*s == '*') - { - ++s; - spec.width_ = internal::WidthHandler(spec).visit(get_arg(s)); - } - return arg_index; -} - -template -void PrintfFormatter::format(BasicCStringRef 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(internal::parse_nonnegative_int(s)); - } - else if (*s == '*') - { - ++s; - spec.precision_ = internal::PrecisionHandler().visit(get_arg(s)); - } - } - - using internal::Arg; - Arg arg = get_arg(s, arg_index); - if (spec.flag(HASH_FLAG) && internal::IsZeroInt().visit(arg)) - spec.flags_ &= ~internal::to_unsigned(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. - using internal::ArgConverter; - switch (*s++) - { - case 'h': - if (*s == 'h') - ArgConverter(arg, *++s).visit(arg); - else - ArgConverter(arg, *s).visit(arg); - break; - case 'l': - if (*s == 'l') - ArgConverter(arg, *++s).visit(arg); - else - ArgConverter(arg, *s).visit(arg); - break; - case 'j': - ArgConverter(arg, *s).visit(arg); - break; - case 'z': - ArgConverter(arg, *s).visit(arg); - break; - case 't': - ArgConverter(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(arg, *s).visit(arg); - } - - // Parse type. - if (!*s) - FMT_THROW(FormatError("invalid format string")); - spec.type_ = static_cast(*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 - internal::CharConverter(arg).visit(arg); - break; - } - } - - start = s; - - // Format argument. - AF(writer_, spec).visit(arg); - } - write(writer_, start, s); -} - -template -void printf(BasicWriter &w, BasicCStringRef format, ArgList args) -{ - PrintfFormatter(args, w).format(format); -} - -/** -\rst -Formats arguments and returns the result as a string. - -**Example**:: - -std::string message = fmt::sprintf("The answer is %d", 42); -\endrst -*/ -inline std::string sprintf(CStringRef format, ArgList args) -{ - MemoryWriter w; - printf(w, format, args); - return w.str(); -} -FMT_VARIADIC(std::string, sprintf, CStringRef) - -inline std::wstring sprintf(WCStringRef format, ArgList args) -{ - WMemoryWriter w; - printf(w, format, args); - return w.str(); -} -FMT_VARIADIC_W(std::wstring, sprintf, WCStringRef) - -/** -\rst -Prints formatted data to the file *f*. - -**Example**:: - -fmt::fprintf(stderr, "Don't %s!", "panic"); -\endrst -*/ -FMT_API int fprintf(std::FILE *f, CStringRef format, ArgList args); -FMT_VARIADIC(int, fprintf, std::FILE *, CStringRef) - -/** -\rst -Prints formatted data to ``stdout``. - -**Example**:: - -fmt::printf("Elapsed time: %.2f seconds", 1.23); -\endrst -*/ -inline int printf(CStringRef format, ArgList args) -{ - return fprintf(stdout, format, args); -} -FMT_VARIADIC(int, printf, CStringRef) - -/** -\rst -Prints formatted data to the stream *os*. - -**Example**:: - -fprintf(cerr, "Don't %s!", "panic"); -\endrst -*/ -inline int fprintf(std::ostream &os, CStringRef format_str, ArgList args) -{ - MemoryWriter w; - printf(w, format_str, args); - internal::write(os, w); - return static_cast(w.size()); -} -FMT_VARIADIC(int, fprintf, std::ostream &, CStringRef) -} // namespace fmt - -#ifdef FMT_HEADER_ONLY -# include "printf.cc" -#endif - -#endif // FMT_PRINTF_H_ diff --git a/vendor/spdlog/spdlog/fmt/bundled/time.h b/vendor/spdlog/spdlog/fmt/bundled/time.h new file mode 100644 index 00000000..10c6cfc9 --- /dev/null +++ b/vendor/spdlog/spdlog/fmt/bundled/time.h @@ -0,0 +1,58 @@ +/* + Formatting library for C++ - time formatting + + Copyright (c) 2012 - 2016, Victor Zverovich + All rights reserved. + + For the license information refer to format.h. + */ + +#ifndef FMT_TIME_H_ +#define FMT_TIME_H_ + +#include "format.h" +#include + +namespace fmt +{ +template +void format(BasicFormatter &f, + const char *&format_str, const std::tm &tm) +{ + if (*format_str == ':') + ++format_str; + const char *end = format_str; + while (*end && *end != '}') + ++end; + if (*end != '}') + FMT_THROW(FormatError("missing '}' in format string")); + internal::MemoryBuffer format; + format.append(format_str, end + 1); + format[format.size() - 1] = '\0'; + Buffer &buffer = f.writer().buffer(); + std::size_t start = buffer.size(); + for (;;) + { + std::size_t size = buffer.capacity() - start; + std::size_t count = std::strftime(&buffer[start], size, &format[0], &tm); + if (count != 0) + { + buffer.resize(start + count); + break; + } + if (size >= format.size() * 256) + { + // If the buffer is 256 times larger than the format string, assume + // that `strftime` gives an empty result. There doesn't seem to be a + // better way to distinguish the two cases: + // https://github.com/fmtlib/fmt/issues/367 + break; + } + const std::size_t MIN_GROWTH = 10; + buffer.reserve(buffer.capacity() + (size > MIN_GROWTH ? size : MIN_GROWTH)); + } + format_str = end + 1; +} +} + +#endif // FMT_TIME_H_ diff --git a/vendor/spdlog/spdlog/logger.h b/vendor/spdlog/spdlog/logger.h index a2deb51d..58b4841a 100644 --- a/vendor/spdlog/spdlog/logger.h +++ b/vendor/spdlog/spdlog/logger.h @@ -37,12 +37,12 @@ public: template void log(level::level_enum lvl, const char* fmt, const Args&... args); template void log(level::level_enum lvl, const char* msg); - template void trace(const char* fmt, const Args&... args); - template void debug(const char* fmt, const Args&... args); - template void info(const char* fmt, const Args&... args); - template void warn(const char* fmt, const Args&... args); - template void error(const char* fmt, const Args&... args); - template void critical(const char* fmt, const Args&... args); + template void trace(const char* fmt, const Arg1&, const Args&... args); + template void debug(const char* fmt, const Arg1&, const Args&... args); + template void info(const char* fmt, const Arg1&, const Args&... args); + template void warn(const char* fmt, const Arg1&, const Args&... args); + template void error(const char* fmt, const Arg1&, const Args&... args); + template void critical(const char* fmt, const Arg1&, const Args&... args); template void log(level::level_enum lvl, const T&); template void trace(const T&); @@ -59,10 +59,6 @@ public: void set_pattern(const std::string&); void set_formatter(formatter_ptr); - // error handler - void set_error_handler(log_err_handler); - log_err_handler error_handler(); - // automatically call flush() if message level >= log_level void flush_on(level::level_enum log_level); @@ -70,6 +66,10 @@ public: const std::vector& sinks() const; + // error handler + virtual void set_error_handler(log_err_handler); + virtual log_err_handler error_handler(); + protected: virtual void _sink_it(details::log_msg&); virtual void _set_pattern(const std::string&); diff --git a/vendor/spdlog/spdlog/sinks/file_sinks.h b/vendor/spdlog/spdlog/sinks/file_sinks.h index d40499b6..721a96df 100644 --- a/vendor/spdlog/spdlog/sinks/file_sinks.h +++ b/vendor/spdlog/spdlog/sinks/file_sinks.h @@ -64,16 +64,15 @@ template class rotating_file_sink : public base_sink < Mutex > { public: - rotating_file_sink(const filename_t &base_filename, const filename_t &extension, - std::size_t max_size, std::size_t max_files ) : + rotating_file_sink(const filename_t &base_filename, + std::size_t max_size, std::size_t max_files) : _base_filename(base_filename), - _extension(extension), _max_size(max_size), _max_files(max_files), _current_size(0), _file_helper() { - _file_helper.open(calc_filename(_base_filename, 0, _extension)); + _file_helper.open(calc_filename(_base_filename, 0)); _current_size = _file_helper.size(); //expensive. called only once } @@ -95,21 +94,21 @@ protected: } private: - static filename_t calc_filename(const filename_t& filename, std::size_t index, const filename_t& extension) + static filename_t calc_filename(const filename_t& filename, std::size_t index) { std::conditional::value, fmt::MemoryWriter, fmt::WMemoryWriter>::type w; if (index) - w.write(SPDLOG_FILENAME_T("{}.{}.{}"), filename, index, extension); + w.write(SPDLOG_FILENAME_T("{}.{}"), filename, index); else - w.write(SPDLOG_FILENAME_T("{}.{}"), filename, extension); + w.write(SPDLOG_FILENAME_T("{}"), filename); return w.str(); } // Rotate files: - // log.txt -> log.1.txt - // log.1.txt -> log2.txt - // log.2.txt -> log3.txt - // log.3.txt -> delete + // log.txt -> log.txt.1 + // log.txt.1 -> log.txt.2 + // log.txt.2 -> log.txt.3 + // lo3.txt.3 -> delete void _rotate() { @@ -117,8 +116,8 @@ private: _file_helper.close(); for (auto i = _max_files; i > 0; --i) { - filename_t src = calc_filename(_base_filename, i - 1, _extension); - filename_t target = calc_filename(_base_filename, i, _extension); + filename_t src = calc_filename(_base_filename, i - 1); + filename_t target = calc_filename(_base_filename, i); if (details::file_helper::file_exists(target)) { @@ -135,7 +134,6 @@ private: _file_helper.reopen(true); } filename_t _base_filename; - filename_t _extension; std::size_t _max_size; std::size_t _max_files; std::size_t _current_size; @@ -150,27 +148,27 @@ typedef rotating_file_sinkrotating_file_sink_st; */ 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) + // Create filename for the form basename.YYYY-MM-DD_hh-mm + static filename_t calc_filename(const filename_t& basename) { std::tm tm = spdlog::details::os::localtime(); std::conditional::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); + 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); return w.str(); } }; /* - * Generator of daily log file names in format basename.YYYY-MM-DD.extension + * Generator of daily log file names in format basename.YYYY-MM-DD */ 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) + // Create filename for the form basename.YYYY-MM-DD + static filename_t calc_filename(const filename_t& basename) { std::tm tm = spdlog::details::os::localtime(); std::conditional::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); + w.write(SPDLOG_FILENAME_T("{}_{:04d}-{:02d}-{:02d}"), basename, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday); return w.str(); } }; @@ -185,17 +183,15 @@ public: //create daily file sink which rotates on given time daily_file_sink( const filename_t& base_filename, - const filename_t& extension, int rotation_hour, int rotation_minute) : _base_filename(base_filename), - _extension(extension), _rotation_h(rotation_hour), _rotation_m(rotation_minute) { 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(FileNameCalc::calc_filename(_base_filename, _extension)); + _file_helper.open(FileNameCalc::calc_filename(_base_filename)); } void flush() override @@ -208,7 +204,7 @@ protected: { if (std::chrono::system_clock::now() >= _rotation_tp) { - _file_helper.open(FileNameCalc::calc_filename(_base_filename, _extension)); + _file_helper.open(FileNameCalc::calc_filename(_base_filename)); _rotation_tp = _next_rotation_tp(); } _file_helper.write(msg); @@ -231,7 +227,6 @@ private: } filename_t _base_filename; - filename_t _extension; int _rotation_h; int _rotation_m; std::chrono::system_clock::time_point _rotation_tp; diff --git a/vendor/spdlog/spdlog/spdlog.h b/vendor/spdlog/spdlog/spdlog.h index 6b93a7a1..f6edd647 100644 --- a/vendor/spdlog/spdlog/spdlog.h +++ b/vendor/spdlog/spdlog/spdlog.h @@ -7,7 +7,7 @@ #pragma once -#define SPDLOG_VERSION "0.12.0" +#define SPDLOG_VERSION "0.13.0" #include #include @@ -124,7 +124,7 @@ std::shared_ptr create(const std::string& logger_name, const It& sinks_b // Create and register a logger with templated sink type // Example: -// spdlog::create("mylog", "dailylog_filename", "txt"); +// spdlog::create("mylog", "dailylog_filename"); template std::shared_ptr create(const std::string& logger_name, Args...);