diff --git a/include/spdlog/details/fast_oss.h b/include/spdlog/details/fast_oss.h deleted file mode 100644 index 447c1783..00000000 --- a/include/spdlog/details/fast_oss.h +++ /dev/null @@ -1,189 +0,0 @@ -/*************************************************************************/ -/* spdlog - an extremely fast and easy to use c++11 logging library. */ -/* Copyright (c) 2014 Gabi Melman. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#pragma once - -// A faster-than-ostringstream class -// uses stack_buf as the underlying buffer (upto 256 bytes before using the heap) - -#include -#include -#include "fast_istostr.h" -#include "stack_buf.h" -#include - -namespace spdlog -{ -namespace details -{ - -class stack_devicebuf :public std::streambuf -{ -public: - static const unsigned short stack_size = 256; - using stackbuf_t = stack_buf; - - stack_devicebuf() = default; - ~stack_devicebuf() = default; - - stack_devicebuf(const stack_devicebuf& other) :std::basic_streambuf(), _stackbuf(other._stackbuf) - {} - - stack_devicebuf(stack_devicebuf&& other): - std::basic_streambuf(), - _stackbuf(std::move(other._stackbuf)) - { - other.clear(); - } - - stack_devicebuf& operator=(stack_devicebuf other) - { - std::swap(_stackbuf, other._stackbuf); - return *this; - } - - const stackbuf_t& buf() const - { - return _stackbuf; - } - std::size_t size() const - { - return _stackbuf.size(); - } - - void clear() - { - _stackbuf.clear(); - } - -protected: - // copy the give buffer into the accumulated fast buffer - std::streamsize xsputn(const char_type* s, std::streamsize count) override - { - _stackbuf.append(s, static_cast(count)); - return count; - } - - int_type overflow(int_type ch) override - { - if (traits_type::not_eof(ch)) - { - char c = traits_type::to_char_type(ch); - xsputn(&c, 1); - } - return ch; - } -private: - stackbuf_t _stackbuf; -}; - - -class fast_oss :public std::ostream -{ -public: - fast_oss() :std::ostream(&_dev) {} - ~fast_oss() = default; - - fast_oss(const fast_oss& other) :std::basic_ios(), std::ostream(&_dev), _dev(other._dev) - {} - - fast_oss(fast_oss&& other) :std::basic_ios(), std::ostream(&_dev), _dev(std::move(other._dev)) - { - other.clear(); - } - - - fast_oss& operator=(fast_oss other) - { - swap(*this, other); - return *this; - } - - void swap(fast_oss& first, fast_oss& second) // nothrow - { - using std::swap; - swap(first._dev, second._dev); - } - - std::string str() const - { - auto& buffer = _dev.buf(); - const char*data = buffer.data(); - return std::string(data, data+buffer.size()); - } - - const stack_devicebuf::stackbuf_t& buf() const - { - return _dev.buf(); - } - - - std::size_t size() const - { - return _dev.size(); - } - - void clear() - { - _dev.clear(); - } - - // - // The following were added because they significantly boost to perfromance - // - void putc(char c) - { - _dev.sputc(c); - } - - // put int and pad with zeroes if smalled than min_width - void put_int(int n, size_t padding) - { - std::string s; - details::fast_itostr(n, s, padding); - _dev.sputn(s.data(), s.size()); - } - - void put_data(const char* p, std::size_t data_size) - { - _dev.sputn(p, data_size); - } - - void put_str(const std::string& s) - { - _dev.sputn(s.data(), s.size()); - } - - void put_fast_oss(const fast_oss& oss) - { - auto& buffer = oss.buf(); - _dev.sputn(buffer.data(), buffer.size()); - } - - -private: - stack_devicebuf _dev; -}; -} -} diff --git a/include/spdlog/details/file_helper.h b/include/spdlog/details/file_helper.h index db2c9da2..7932a45b 100644 --- a/include/spdlog/details/file_helper.h +++ b/include/spdlog/details/file_helper.h @@ -52,7 +52,7 @@ public: explicit file_helper(bool auto_flush): _fd(nullptr), _auto_flush(auto_flush) - {}; + {}; file_helper(const file_helper&) = delete; file_helper& operator=(const file_helper&) = delete; @@ -99,14 +99,15 @@ public: void write(const log_msg& msg) { - auto& buf = msg.formatted.buf(); - size_t size = buf.size(); - if(std::fwrite(buf.data(), sizeof(char), size, _fd) != size) + + size_t size = msg.formatted.size(); + auto data = msg.formatted.data(); + if(std::fwrite(data, sizeof(char), size, _fd) != size) throw spdlog_ex("Failed writing to file " + _filename); if(_auto_flush) std::fflush(_fd); - + } const std::string& filename() const diff --git a/include/spdlog/details/line_logger.h b/include/spdlog/details/line_logger.h index c16a81ad..d3919b67 100644 --- a/include/spdlog/details/line_logger.h +++ b/include/spdlog/details/line_logger.h @@ -26,7 +26,6 @@ #include "../common.h" #include "../logger.h" -#include "fast_oss.h" // Line logger class - aggregates operator<< calls to fast ostream diff --git a/include/spdlog/details/log_msg.h b/include/spdlog/details/log_msg.h index 19abcfda..b9038cda 100644 --- a/include/spdlog/details/log_msg.h +++ b/include/spdlog/details/log_msg.h @@ -25,7 +25,7 @@ #pragma once #include "../common.h" -#include "./fast_oss.h" +#include "./format.h" namespace spdlog { @@ -42,13 +42,18 @@ struct log_msg raw(), formatted() {} - log_msg(const log_msg& other): + + log_msg(const log_msg& other) : logger_name(other.logger_name), level(other.level), time(other.time), - tm_time(other.tm_time), - raw(other.raw), - formatted(other.formatted) {} + tm_time(other.tm_time) + + { + //fmt::MemoryWriter does not allow copy ctor} + raw.write(other.raw.data(), other.raw.size()); + formatted.write(other.formatted.data(), other.formatted.size()); + } log_msg(log_msg&& other) : logger_name(std::move(other.logger_name)), @@ -56,7 +61,9 @@ struct log_msg time(std::move(other.time)), tm_time(other.tm_time), raw(std::move(other.raw)), - formatted(std::move(other.formatted)) {} + formatted(std::move(other.formatted)) + { + } log_msg& operator=(log_msg&& other) { @@ -84,8 +91,8 @@ struct log_msg level::level_enum level; log_clock::time_point time; std::tm tm_time; - fast_oss raw; - fast_oss formatted; + fmt::MemoryWriter raw; + fmt::MemoryWriter formatted; }; } } diff --git a/include/spdlog/details/pattern_formatter_impl.h b/include/spdlog/details/pattern_formatter_impl.h index aaf4b137..1febb30d 100644 --- a/include/spdlog/details/pattern_formatter_impl.h +++ b/include/spdlog/details/pattern_formatter_impl.h @@ -32,7 +32,6 @@ #include "../formatter.h" #include "./log_msg.h" -#include "./fast_oss.h" #include "./os.h" namespace spdlog @@ -89,7 +88,7 @@ class a_formatter :public flag_formatter { void format(details::log_msg& msg) override { - msg.formatted.put_str(days[msg.tm_time.tm_wday]); + msg.formatted << days[msg.tm_time.tm_wday]; } }; @@ -99,7 +98,7 @@ class A_formatter :public flag_formatter { void format(details::log_msg& msg) override { - msg.formatted.put_str(full_days[msg.tm_time.tm_wday]); + msg.formatted << full_days[msg.tm_time.tm_wday]; } }; @@ -109,7 +108,7 @@ class b_formatter :public flag_formatter { void format(details::log_msg& msg) override { - msg.formatted.put_str(months[msg.tm_time.tm_mon]); + msg.formatted<< months[msg.tm_time.tm_mon]; } }; @@ -119,7 +118,7 @@ class B_formatter :public flag_formatter { void format(details::log_msg& msg) override { - msg.formatted.put_str(full_months[msg.tm_time.tm_mon]); + msg.formatted << full_months[msg.tm_time.tm_mon]; } }; @@ -128,17 +127,14 @@ class c_formatter :public flag_formatter { void format(details::log_msg& msg) override { - msg.formatted.put_str(days[msg.tm_time.tm_wday]); - msg.formatted.putc(' '); - msg.formatted.put_str(months[msg.tm_time.tm_mon]); - msg.formatted.putc(' '); - msg.formatted.put_int(msg.tm_time.tm_mday, 2); - msg.formatted.putc(' '); - msg.formatted.put_int(msg.tm_time.tm_hour, 2); - msg.formatted.putc(':'); - msg.formatted.put_int(msg.tm_time.tm_min, 2); - msg.formatted.putc(':'); - msg.formatted.put_int(msg.tm_time.tm_sec, 2); + msg.formatted.write("{} {} {:02d} {:02d}:{:02d}:{:02d} {:04d}", + days[msg.tm_time.tm_wday], + months[msg.tm_time.tm_mon], + msg.tm_time.tm_mday, + msg.tm_time.tm_hour, + msg.tm_time.tm_min, + msg.tm_time.tm_sec, + msg.tm_time.tm_year + 1900); } }; @@ -148,7 +144,7 @@ class C_formatter :public flag_formatter { void format(details::log_msg& msg) override { - msg.formatted.put_int(msg.tm_time.tm_year % 100, 2); + msg.formatted.write("{02:d}", msg.tm_time.tm_year % 100); } }; @@ -159,11 +155,7 @@ class D_formatter :public flag_formatter { void format(details::log_msg& msg) override { - msg.formatted.put_int(msg.tm_time.tm_mon + 1, 2); - msg.formatted.putc('/'); - msg.formatted.put_int(msg.tm_time.tm_mday, 2); - msg.formatted.putc('/'); - msg.formatted.put_int(msg.tm_time.tm_year % 100, 2); + msg.formatted.write("{:02d}/{:02d}/{:02d}", msg.tm_time.tm_mon + 1, msg.tm_time.tm_mday, msg.tm_time.tm_year % 100); } }; @@ -173,7 +165,7 @@ class Y_formatter :public flag_formatter { void format(details::log_msg& msg) override { - msg.formatted.put_int(msg.tm_time.tm_year + 1900, 4); + msg.formatted.write("{:04d}", msg.tm_time.tm_year + 1900); } }; @@ -182,7 +174,7 @@ class m_formatter :public flag_formatter { void format(details::log_msg& msg) override { - msg.formatted.put_int(msg.tm_time.tm_mon + 1, 2); + msg.formatted.write("{:02d}", msg.tm_time.tm_mon + 1); } }; @@ -191,7 +183,7 @@ class d_formatter :public flag_formatter { void format(details::log_msg& msg) override { - msg.formatted.put_int(msg.tm_time.tm_mday, 2); + msg.formatted.write("{:02d}", msg.tm_time.tm_mday); } }; @@ -200,7 +192,7 @@ class H_formatter :public flag_formatter { void format(details::log_msg& msg) override { - msg.formatted.put_int(msg.tm_time.tm_hour, 2); + msg.formatted.write("{:02d}", msg.tm_time.tm_hour); } }; @@ -209,7 +201,7 @@ class I_formatter :public flag_formatter { void format(details::log_msg& msg) override { - msg.formatted.put_int(to12h(msg.tm_time), 2); + msg.formatted.write("{:02d}", to12h(msg.tm_time)); } }; @@ -218,7 +210,7 @@ class M_formatter :public flag_formatter { void format(details::log_msg& msg) override { - msg.formatted.put_int(msg.tm_time.tm_min, 2); + msg.formatted.write("{:02d}", msg.tm_time.tm_min); } }; @@ -227,7 +219,7 @@ class S_formatter :public flag_formatter { void format(details::log_msg& msg) override { - msg.formatted.put_int(msg.tm_time.tm_sec, 2); + //msg.formatted.put_int(msg.tm_time.tm_sec, 2); } }; @@ -238,7 +230,7 @@ class e_formatter :public flag_formatter { auto duration = msg.time.time_since_epoch(); auto millis = std::chrono::duration_cast(duration).count() % 1000; - msg.formatted.put_int(static_cast(millis), 3); + msg.formatted.write("{03:d}", static_cast(millis)); } }; @@ -247,7 +239,7 @@ class p_formatter :public flag_formatter { void format(details::log_msg& msg) override { - msg.formatted.put_data(ampm(msg.tm_time), 2); + msg.formatted << ampm(msg.tm_time); } }; @@ -257,13 +249,7 @@ class r_formatter :public flag_formatter { void format(details::log_msg& msg) override { - msg.formatted.put_int(to12h(msg.tm_time), 2); - msg.formatted.putc(':'); - msg.formatted.put_int(msg.tm_time.tm_min, 2); - msg.formatted.putc(':'); - msg.formatted.put_int(msg.tm_time.tm_sec, 2); - msg.formatted.putc(' '); - msg.formatted.put_data(ampm(msg.tm_time), 2); + msg.formatted.write("{:02d}:{:02d}:{:02d} {}", to12h(msg.tm_time), msg.tm_time.tm_min, msg.tm_time.tm_sec, ampm(msg.tm_time)); } }; @@ -272,9 +258,7 @@ class R_formatter :public flag_formatter { void format(details::log_msg& msg) override { - msg.formatted.put_int(msg.tm_time.tm_hour, 2); - msg.formatted.putc(':'); - msg.formatted.put_int(msg.tm_time.tm_min, 2); + msg.formatted.write("{:02d}:{:02d}", msg.tm_time.tm_hour, msg.tm_time.tm_min); } }; @@ -284,14 +268,11 @@ class T_formatter :public flag_formatter { void format(details::log_msg& msg) override { - msg.formatted.put_int(msg.tm_time.tm_hour, 2); - msg.formatted.putc(':'); - msg.formatted.put_int(msg.tm_time.tm_min, 2); - msg.formatted.putc(':'); - msg.formatted.put_int(msg.tm_time.tm_sec, 2); + msg.formatted.write("{:02d}:{:02d}:{:02d}", msg.tm_time.tm_hour, msg.tm_time.tm_min, msg.tm_time.tm_sec); } }; + // ISO 8601 offset from UTC in timezone (HH:MM) class z_formatter :public flag_formatter { @@ -311,7 +292,7 @@ public: _value = get_value(msg); _last_update = msg.time; } - msg.formatted.put_str(_value); + msg.formatted << _value; } private: log_clock::time_point _last_update; @@ -323,23 +304,21 @@ private: int total_minutes = os::utc_minutes_offset(msg.tm_time); int h = total_minutes / 60; int m = total_minutes % 60; - fast_oss oss; - oss.putc(h < 0 ? '-' : '+'); - oss.put_int(h, 2); - oss.putc(':'); - oss.put_int(m, 2); - return oss.str(); + fmt::MemoryWriter w; + w.write("{} {:02d}:{:02d}", h >= 0 ? '+' : '-', h, m); + return w.str(); } }; + //Thread id class t_formatter :public flag_formatter { void format(details::log_msg& msg) override { - msg.formatted << std::this_thread::get_id(); + msg.formatted << std::this_thread::get_id().hash(); } }; @@ -348,7 +327,7 @@ class v_formatter :public flag_formatter { void format(details::log_msg& msg) override { - msg.formatted.put_fast_oss(msg.raw); + msg.formatted.write(msg.raw.data(), msg.raw.size()); } }; @@ -359,7 +338,7 @@ public: {} void format(details::log_msg& msg) override { - msg.formatted.putc(_ch); + msg.formatted << _ch; } private: char _ch; @@ -378,7 +357,7 @@ public: } void format(details::log_msg& msg) override { - msg.formatted.put_str(_str); + msg.formatted << _str; } private: std::string _str; @@ -390,27 +369,20 @@ class full_formatter :public flag_formatter { void format(details::log_msg& msg) override { - msg.formatted.putc('['); - msg.formatted.put_int(msg.tm_time.tm_year+1900, 4); - msg.formatted.putc('-'); - msg.formatted.put_int(msg.tm_time.tm_mon+ 1, 2); - msg.formatted.putc('-'); - msg.formatted.put_int(msg.tm_time.tm_mday, 2); - msg.formatted.putc(' '); - msg.formatted.put_int(msg.tm_time.tm_hour, 2); - msg.formatted.putc(':'); - msg.formatted.put_int(msg.tm_time.tm_min, 2); - msg.formatted.putc(':'); - msg.formatted.put_int(msg.tm_time.tm_sec, 2); - //millis - msg.formatted.putc('.'); auto duration = msg.time.time_since_epoch(); auto millis = std::chrono::duration_cast(duration).count() % 1000; - msg.formatted.put_int(static_cast(millis), 3); - msg.formatted.putc(']'); - msg.formatted << " [" << msg.logger_name << "] [" << level::to_str(msg.level) << "] "; - msg.formatted.put_fast_oss(msg.raw); + msg.formatted.write("[{:d}-{:02d}-{:02d} {:02d}:{:02d}:{:02d}.{:03d}] [{}] [{}] ", + msg.tm_time.tm_year + 1900, + msg.tm_time.tm_mon + 1, + msg.tm_time.tm_mday, + msg.tm_time.tm_hour, + msg.tm_time.tm_min, + msg.tm_time.tm_sec, + static_cast(millis), + msg.logger_name, + level::to_str(msg.level)); + msg.formatted.write(msg.raw.str()); } }; @@ -457,7 +429,7 @@ inline void spdlog::pattern_formatter::handle_flag(char flag) { switch (flag) { - // logger name + // logger name case 'n': _formatters.push_back(std::unique_ptr(new details::name_formatter())); break; diff --git a/include/spdlog/details/stack_buf.h b/include/spdlog/details/stack_buf.h deleted file mode 100644 index 7b120967..00000000 --- a/include/spdlog/details/stack_buf.h +++ /dev/null @@ -1,134 +0,0 @@ -/*************************************************************************/ -/* spdlog - an extremely fast and easy to use c++11 logging library. */ -/* Copyright (c) 2014 Gabi Melman. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#pragma once - -#include -#include -#include -#include - -namespace spdlog -{ -namespace details -{ - -// Fast memory storage on the stack when possible or in std::vector -template -class stack_buf -{ -public: - static const unsigned short stack_size = STACK_SIZE; - stack_buf() :_v(), _stack_size(0) {} - ~stack_buf() = default; - stack_buf(const stack_buf& other) :stack_buf(other, delegate_copy_or_move {}) - {} - - stack_buf(stack_buf&& other) :stack_buf(other, delegate_copy_or_move {}) - { - other.clear(); - } - template - stack_buf& operator=(T1&& other) - { - _stack_size = other._stack_size; - if (other.vector_used()) - _v = std::forward(other)._v; - else - std::copy_n(other._stack_array.begin(), other._stack_size, _stack_array.begin()); - return *this; - } - - void append(const char* buf, std::size_t buf_size) - { - //If we are aleady using _v, forget about the stack - if (vector_used()) - { - _v.insert(_v.end(), buf, buf + buf_size); - } - //Try use the stack - else - { - if (_stack_size + buf_size <= STACK_SIZE) - { - std::memcpy(&_stack_array[_stack_size], buf, buf_size); - _stack_size += buf_size; - } - //Not enough stack space. Copy all to _v - else - { - _v.reserve(_stack_size + buf_size); - _v.insert(_v.end(), _stack_array.begin(), _stack_array.begin() + _stack_size); - _v.insert(_v.end(), buf, buf + buf_size); - } - } - } - - - void clear() - { - _stack_size = 0; - _v.clear(); - } - - const char* data() const - { - if (vector_used()) - return _v.data(); - else - return _stack_array.data(); - } - - std::size_t size() const - { - if (vector_used()) - return _v.size(); - else - return _stack_size; - } - -private: - struct delegate_copy_or_move {}; - template - stack_buf(T1&& other, delegate_copy_or_move) - { - _stack_size = other._stack_size; - if (other.vector_used()) - _v = std::forward(other)._v; - else - std::copy_n(other._stack_array.begin(), other._stack_size, _stack_array.begin()); - } - - inline bool vector_used() const - { - return !(_v.empty()); - } - - std::vector _v; - std::array _stack_array; - std::size_t _stack_size; -}; - -} -} //namespace spdlog { namespace details {