Upgrade to fmt 5.x
This commit is contained in:
		
							parent
							
								
									378c7789ba
								
							
						
					
					
						commit
						cdbf2e361b
					
				| @ -158,9 +158,9 @@ public: | |||||||
| 
 | 
 | ||||||
|     spdlog_ex(const std::string &msg, int last_errno) |     spdlog_ex(const std::string &msg, int last_errno) | ||||||
|     { |     { | ||||||
|         fmt::MemoryWriter writer; |         fmt::memory_buffer buf; | ||||||
|         fmt::format_system_error(writer, last_errno, msg); |         fmt::format_system_error(buf, last_errno, msg); | ||||||
|         _msg = writer.str(); |         _msg = fmt::to_string(buf); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     const char *what() const SPDLOG_NOEXCEPT override |     const char *what() const SPDLOG_NOEXCEPT override | ||||||
|  | |||||||
| @ -37,8 +37,8 @@ struct log_msg | |||||||
|     level::level_enum level; |     level::level_enum level; | ||||||
|     log_clock::time_point time; |     log_clock::time_point time; | ||||||
|     size_t thread_id; |     size_t thread_id; | ||||||
|     fmt::MemoryWriter raw; |     fmt::memory_buffer raw; | ||||||
|     fmt::MemoryWriter formatted; |     fmt::memory_buffer formatted; | ||||||
|     size_t msg_id{0}; |     size_t msg_id{0}; | ||||||
|     // info about wrapping the formatted text with color
 |     // info about wrapping the formatted text with color
 | ||||||
|     size_t color_range_start{0}; |     size_t color_range_start{0}; | ||||||
|  | |||||||
| @ -58,12 +58,7 @@ inline void spdlog::logger::log(level::level_enum lvl, const char *fmt, const Ar | |||||||
|     try |     try | ||||||
|     { |     { | ||||||
|         details::log_msg log_msg(&name_, lvl); |         details::log_msg log_msg(&name_, lvl); | ||||||
| 
 |         fmt::format_to(log_msg.raw, fmt, args...); | ||||||
| #if defined(SPDLOG_FMT_PRINTF) |  | ||||||
|         fmt::printf(log_msg.raw, fmt, args...); |  | ||||||
| #else |  | ||||||
|         log_msg.raw.write(fmt, args...); |  | ||||||
| #endif |  | ||||||
|         sink_it_(log_msg); |         sink_it_(log_msg); | ||||||
|     } |     } | ||||||
|     SPDLOG_CATCH_AND_HANDLE |     SPDLOG_CATCH_AND_HANDLE | ||||||
| @ -79,7 +74,7 @@ inline void spdlog::logger::log(level::level_enum lvl, const char *msg) | |||||||
|     try |     try | ||||||
|     { |     { | ||||||
|         details::log_msg log_msg(&name_, lvl); |         details::log_msg log_msg(&name_, lvl); | ||||||
|         log_msg.raw << msg; |         fmt::format_to(log_msg.raw, "{}", msg); | ||||||
|         sink_it_(log_msg); |         sink_it_(log_msg); | ||||||
|     } |     } | ||||||
|     SPDLOG_CATCH_AND_HANDLE |     SPDLOG_CATCH_AND_HANDLE | ||||||
| @ -95,7 +90,7 @@ inline void spdlog::logger::log(level::level_enum lvl, const T &msg) | |||||||
|     try |     try | ||||||
|     { |     { | ||||||
|         details::log_msg log_msg(&name_, lvl); |         details::log_msg log_msg(&name_, lvl); | ||||||
|         log_msg.raw << msg; |         fmt::format_to(log_msg.raw, "{}", msg); | ||||||
|         sink_it_(log_msg); |         sink_it_(log_msg); | ||||||
|     } |     } | ||||||
|     SPDLOG_CATCH_AND_HANDLE |     SPDLOG_CATCH_AND_HANDLE | ||||||
|  | |||||||
| @ -20,8 +20,23 @@ | |||||||
| #include <utility> | #include <utility> | ||||||
| #include <vector> | #include <vector> | ||||||
| 
 | 
 | ||||||
|  | namespace { | ||||||
|  | inline void append_str(const std::string &str, fmt::memory_buffer &dest) | ||||||
|  | { | ||||||
|  |     const char *str_ptr = str.data(); | ||||||
|  |     dest.append(str_ptr, str_ptr + str.size()); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | inline void append_buf(const fmt::memory_buffer &buf, fmt::memory_buffer &dest) | ||||||
|  | { | ||||||
|  |     const char *buf_ptr = buf.data(); | ||||||
|  |     dest.append(buf_ptr, buf_ptr + buf.size()); | ||||||
|  | } | ||||||
|  | } // namespace
 | ||||||
|  | 
 | ||||||
| namespace spdlog { | namespace spdlog { | ||||||
| namespace details { | namespace details { | ||||||
|  | 
 | ||||||
| class flag_formatter | class flag_formatter | ||||||
| { | { | ||||||
| public: | public: | ||||||
| @ -36,7 +51,8 @@ class name_formatter : public flag_formatter | |||||||
| { | { | ||||||
|     void format(details::log_msg &msg, const std::tm &) override |     void format(details::log_msg &msg, const std::tm &) override | ||||||
|     { |     { | ||||||
|         msg.formatted << *msg.logger_name; |         // fmt::format_to(msg.formatted, *msg.logger_name);
 | ||||||
|  |         append_str(*msg.logger_name, msg.formatted); | ||||||
|     } |     } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| @ -45,7 +61,9 @@ class level_formatter : public flag_formatter | |||||||
| { | { | ||||||
|     void format(details::log_msg &msg, const std::tm &) override |     void format(details::log_msg &msg, const std::tm &) override | ||||||
|     { |     { | ||||||
|         msg.formatted << level::to_str(msg.level); |         // msg.formatted << level::to_str(msg.level);
 | ||||||
|  |         auto level_str = level::to_str(msg.level); | ||||||
|  |         fmt::format_to(msg.formatted, "{}", level_str); | ||||||
|     } |     } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| @ -54,7 +72,9 @@ class short_level_formatter : public flag_formatter | |||||||
| { | { | ||||||
|     void format(details::log_msg &msg, const std::tm &) override |     void format(details::log_msg &msg, const std::tm &) override | ||||||
|     { |     { | ||||||
|         msg.formatted << level::to_short_str(msg.level); |         // msg.formatted << level::to_short_str(msg.level);
 | ||||||
|  |         auto level_str = level::to_short_str(msg.level); | ||||||
|  |         fmt::format_to(msg.formatted, "{}", level_str); | ||||||
|     } |     } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| @ -78,7 +98,8 @@ class a_formatter : public flag_formatter | |||||||
| { | { | ||||||
|     void format(details::log_msg &msg, const std::tm &tm_time) override |     void format(details::log_msg &msg, const std::tm &tm_time) override | ||||||
|     { |     { | ||||||
|         msg.formatted << days[tm_time.tm_wday]; |         // msg.formatted << days[tm_time.tm_wday];
 | ||||||
|  |         fmt::format_to(msg.formatted, "{}", days[tm_time.tm_wday]); | ||||||
|     } |     } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| @ -88,7 +109,8 @@ class A_formatter : public flag_formatter | |||||||
| { | { | ||||||
|     void format(details::log_msg &msg, const std::tm &tm_time) override |     void format(details::log_msg &msg, const std::tm &tm_time) override | ||||||
|     { |     { | ||||||
|         msg.formatted << full_days[tm_time.tm_wday]; |         // msg.formatted << full_days[tm_time.tm_wday];
 | ||||||
|  |         fmt::format_to(msg.formatted, "{}", full_days[tm_time.tm_wday]); | ||||||
|     } |     } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| @ -98,7 +120,8 @@ class b_formatter : public flag_formatter | |||||||
| { | { | ||||||
|     void format(details::log_msg &msg, const std::tm &tm_time) override |     void format(details::log_msg &msg, const std::tm &tm_time) override | ||||||
|     { |     { | ||||||
|         msg.formatted << months[tm_time.tm_mon]; |         // msg.formatted << months[tm_time.tm_mon];
 | ||||||
|  |         append_str(months[tm_time.tm_mon], msg.formatted); | ||||||
|     } |     } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| @ -109,31 +132,21 @@ class B_formatter : public flag_formatter | |||||||
| { | { | ||||||
|     void format(details::log_msg &msg, const std::tm &tm_time) override |     void format(details::log_msg &msg, const std::tm &tm_time) override | ||||||
|     { |     { | ||||||
|         msg.formatted << full_months[tm_time.tm_mon]; |         // msg.formatted << full_months[tm_time.tm_mon];
 | ||||||
|  |         append_str(full_months[tm_time.tm_mon], msg.formatted); | ||||||
|     } |     } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| // write 2 ints separated by sep with padding of 2
 |  | ||||||
| static fmt::MemoryWriter &pad_n_join(fmt::MemoryWriter &w, int v1, int v2, char sep) |  | ||||||
| { |  | ||||||
|     w << fmt::pad(v1, 2, '0') << sep << fmt::pad(v2, 2, '0'); |  | ||||||
|     return w; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // write 3 ints separated by sep with padding of 2
 |  | ||||||
| static fmt::MemoryWriter &pad_n_join(fmt::MemoryWriter &w, int v1, int v2, int v3, char sep) |  | ||||||
| { |  | ||||||
|     w << fmt::pad(v1, 2, '0') << sep << fmt::pad(v2, 2, '0') << sep << fmt::pad(v3, 2, '0'); |  | ||||||
|     return w; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // Date and time representation (Thu Aug 23 15:35:46 2014)
 | // Date and time representation (Thu Aug 23 15:35:46 2014)
 | ||||||
| class c_formatter SPDLOG_FINAL : public flag_formatter | class c_formatter SPDLOG_FINAL : public flag_formatter | ||||||
| { | { | ||||||
|     void format(details::log_msg &msg, const std::tm &tm_time) override |     void format(details::log_msg &msg, const std::tm &tm_time) override | ||||||
|     { |     { | ||||||
|         msg.formatted << days[tm_time.tm_wday] << ' ' << months[tm_time.tm_mon] << ' ' << tm_time.tm_mday << ' '; | 
 | ||||||
|         pad_n_join(msg.formatted, tm_time.tm_hour, tm_time.tm_min, tm_time.tm_sec, ':') << ' ' << tm_time.tm_year + 1900; |         // msg.formatted << days[tm_time.tm_wday] << ' ' << months[tm_time.tm_mon] << ' ' << tm_time.tm_mday << ' ';
 | ||||||
|  |         // pad_n_join(msg.formatted, tm_time.tm_hour, tm_time.tm_min, tm_time.tm_sec, ':') << ' ' << tm_time.tm_year + 1900;
 | ||||||
|  |         fmt::format_to(msg.formatted, "{} {} {} {:02}:{:02}:{:02} {}", days[tm_time.tm_wday], months[tm_time.tm_mon], tm_time.tm_mday, | ||||||
|  |             tm_time.tm_hour, tm_time.tm_min, tm_time.tm_sec, tm_time.tm_year + 1900); | ||||||
|     } |     } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| @ -142,7 +155,8 @@ class C_formatter SPDLOG_FINAL : public flag_formatter | |||||||
| { | { | ||||||
|     void format(details::log_msg &msg, const std::tm &tm_time) override |     void format(details::log_msg &msg, const std::tm &tm_time) override | ||||||
|     { |     { | ||||||
|         msg.formatted << fmt::pad(tm_time.tm_year % 100, 2, '0'); |         // msg.formatted << fmt::pad(tm_time.tm_year % 100, 2, '0');
 | ||||||
|  |         fmt::format_to(msg.formatted, "{:02}", tm_time.tm_year % 100); | ||||||
|     } |     } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| @ -151,7 +165,8 @@ class D_formatter SPDLOG_FINAL : public flag_formatter | |||||||
| { | { | ||||||
|     void format(details::log_msg &msg, const std::tm &tm_time) override |     void format(details::log_msg &msg, const std::tm &tm_time) override | ||||||
|     { |     { | ||||||
|         pad_n_join(msg.formatted, tm_time.tm_mon + 1, tm_time.tm_mday, tm_time.tm_year % 100, '/'); |         // pad_n_join(msg.formatted, tm_time.tm_mon + 1, tm_time.tm_mday, tm_time.tm_year % 100, '/');
 | ||||||
|  |         fmt::format_to(msg.formatted, "{:02}/{:02}/{:02}", tm_time.tm_mon + 1, tm_time.tm_mday, tm_time.tm_year % 100); | ||||||
|     } |     } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| @ -160,7 +175,8 @@ class Y_formatter SPDLOG_FINAL : public flag_formatter | |||||||
| { | { | ||||||
|     void format(details::log_msg &msg, const std::tm &tm_time) override |     void format(details::log_msg &msg, const std::tm &tm_time) override | ||||||
|     { |     { | ||||||
|         msg.formatted << tm_time.tm_year + 1900; |         // msg.formatted << tm_time.tm_year + 1900;
 | ||||||
|  |         fmt::format_to(msg.formatted, "{}", tm_time.tm_year + 1900); | ||||||
|     } |     } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| @ -169,7 +185,8 @@ class m_formatter SPDLOG_FINAL : public flag_formatter | |||||||
| { | { | ||||||
|     void format(details::log_msg &msg, const std::tm &tm_time) override |     void format(details::log_msg &msg, const std::tm &tm_time) override | ||||||
|     { |     { | ||||||
|         msg.formatted << fmt::pad(tm_time.tm_mon + 1, 2, '0'); |         // msg.formatted << fmt::pad(tm_time.tm_mon + 1, 2, '0');
 | ||||||
|  |         fmt::format_to(msg.formatted, "{:02}", tm_time.tm_mon + 1); | ||||||
|     } |     } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| @ -178,7 +195,8 @@ class d_formatter SPDLOG_FINAL : public flag_formatter | |||||||
| { | { | ||||||
|     void format(details::log_msg &msg, const std::tm &tm_time) override |     void format(details::log_msg &msg, const std::tm &tm_time) override | ||||||
|     { |     { | ||||||
|         msg.formatted << fmt::pad(tm_time.tm_mday, 2, '0'); |         // msg.formatted << fmt::pad(tm_time.tm_mday, 2, '0');
 | ||||||
|  |         fmt::format_to(msg.formatted, "{:02}", tm_time.tm_mday); | ||||||
|     } |     } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| @ -187,7 +205,8 @@ class H_formatter SPDLOG_FINAL : public flag_formatter | |||||||
| { | { | ||||||
|     void format(details::log_msg &msg, const std::tm &tm_time) override |     void format(details::log_msg &msg, const std::tm &tm_time) override | ||||||
|     { |     { | ||||||
|         msg.formatted << fmt::pad(tm_time.tm_hour, 2, '0'); |         // msg.formatted << fmt::pad(tm_time.tm_hour, 2, '0');
 | ||||||
|  |         fmt::format_to(msg.formatted, "{:02}", tm_time.tm_hour); | ||||||
|     } |     } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| @ -196,7 +215,8 @@ class I_formatter SPDLOG_FINAL : public flag_formatter | |||||||
| { | { | ||||||
|     void format(details::log_msg &msg, const std::tm &tm_time) override |     void format(details::log_msg &msg, const std::tm &tm_time) override | ||||||
|     { |     { | ||||||
|         msg.formatted << fmt::pad(to12h(tm_time), 2, '0'); |         // msg.formatted << fmt::pad(to12h(tm_time), 2, '0');
 | ||||||
|  |         fmt::format_to(msg.formatted, "{:02}", to12h(tm_time)); | ||||||
|     } |     } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| @ -205,7 +225,8 @@ class M_formatter SPDLOG_FINAL : public flag_formatter | |||||||
| { | { | ||||||
|     void format(details::log_msg &msg, const std::tm &tm_time) override |     void format(details::log_msg &msg, const std::tm &tm_time) override | ||||||
|     { |     { | ||||||
|         msg.formatted << fmt::pad(tm_time.tm_min, 2, '0'); |         // msg.formatted << fmt::pad(tm_time.tm_min, 2, '0');
 | ||||||
|  |         fmt::format_to(msg.formatted, "{:02}", tm_time.tm_min); | ||||||
|     } |     } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| @ -214,7 +235,8 @@ class S_formatter SPDLOG_FINAL : public flag_formatter | |||||||
| { | { | ||||||
|     void format(details::log_msg &msg, const std::tm &tm_time) override |     void format(details::log_msg &msg, const std::tm &tm_time) override | ||||||
|     { |     { | ||||||
|         msg.formatted << fmt::pad(tm_time.tm_sec, 2, '0'); |         // msg.formatted << fmt::pad(tm_time.tm_sec, 2, '0');
 | ||||||
|  |         fmt::format_to(msg.formatted, "{:02}", tm_time.tm_sec); | ||||||
|     } |     } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| @ -225,7 +247,8 @@ class e_formatter SPDLOG_FINAL : public flag_formatter | |||||||
|     { |     { | ||||||
|         auto duration = msg.time.time_since_epoch(); |         auto duration = msg.time.time_since_epoch(); | ||||||
|         auto millis = std::chrono::duration_cast<std::chrono::milliseconds>(duration).count() % 1000; |         auto millis = std::chrono::duration_cast<std::chrono::milliseconds>(duration).count() % 1000; | ||||||
|         msg.formatted << fmt::pad(static_cast<int>(millis), 3, '0'); |         // msg.formatted << fmt::pad(static_cast<int>(millis), 3, '0');
 | ||||||
|  |         fmt::format_to(msg.formatted, "{:03}", static_cast<int>(millis)); | ||||||
|     } |     } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| @ -236,7 +259,8 @@ class f_formatter SPDLOG_FINAL : public flag_formatter | |||||||
|     { |     { | ||||||
|         auto duration = msg.time.time_since_epoch(); |         auto duration = msg.time.time_since_epoch(); | ||||||
|         auto micros = std::chrono::duration_cast<std::chrono::microseconds>(duration).count() % 1000000; |         auto micros = std::chrono::duration_cast<std::chrono::microseconds>(duration).count() % 1000000; | ||||||
|         msg.formatted << fmt::pad(static_cast<int>(micros), 6, '0'); |         // msg.formatted << fmt::pad(static_cast<int>(micros), 6, '0');
 | ||||||
|  |         fmt::format_to(msg.formatted, "{:06}", static_cast<int>(micros)); | ||||||
|     } |     } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| @ -247,7 +271,8 @@ class F_formatter SPDLOG_FINAL : public flag_formatter | |||||||
|     { |     { | ||||||
|         auto duration = msg.time.time_since_epoch(); |         auto duration = msg.time.time_since_epoch(); | ||||||
|         auto ns = std::chrono::duration_cast<std::chrono::nanoseconds>(duration).count() % 1000000000; |         auto ns = std::chrono::duration_cast<std::chrono::nanoseconds>(duration).count() % 1000000000; | ||||||
|         msg.formatted << fmt::pad(static_cast<int>(ns), 9, '0'); |         // msg.formatted << fmt::pad(static_cast<int>(ns), 9, '0');
 | ||||||
|  |         fmt::format_to(msg.formatted, "{:06}", static_cast<int>(ns)); | ||||||
|     } |     } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| @ -257,7 +282,8 @@ class E_formatter SPDLOG_FINAL : public flag_formatter | |||||||
|     { |     { | ||||||
|         auto duration = msg.time.time_since_epoch(); |         auto duration = msg.time.time_since_epoch(); | ||||||
|         auto seconds = std::chrono::duration_cast<std::chrono::seconds>(duration).count(); |         auto seconds = std::chrono::duration_cast<std::chrono::seconds>(duration).count(); | ||||||
|         msg.formatted << seconds; |         // msg.formatted << seconds;
 | ||||||
|  |         fmt::format_to(msg.formatted, "{}", seconds); | ||||||
|     } |     } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| @ -266,7 +292,8 @@ class p_formatter SPDLOG_FINAL : public flag_formatter | |||||||
| { | { | ||||||
|     void format(details::log_msg &msg, const std::tm &tm_time) override |     void format(details::log_msg &msg, const std::tm &tm_time) override | ||||||
|     { |     { | ||||||
|         msg.formatted << ampm(tm_time); |         // msg.formatted << ampm(tm_time);
 | ||||||
|  |         fmt::format_to(msg.formatted, "{}", ampm(tm_time)); | ||||||
|     } |     } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| @ -275,7 +302,8 @@ class r_formatter SPDLOG_FINAL : public flag_formatter | |||||||
| { | { | ||||||
|     void format(details::log_msg &msg, const std::tm &tm_time) override |     void format(details::log_msg &msg, const std::tm &tm_time) override | ||||||
|     { |     { | ||||||
|         pad_n_join(msg.formatted, to12h(tm_time), tm_time.tm_min, tm_time.tm_sec, ':') << ' ' << ampm(tm_time); |         // pad_n_join(msg.formatted, to12h(tm_time), tm_time.tm_min, tm_time.tm_sec, ':') << ' ' << ampm(tm_time);
 | ||||||
|  |         fmt::format_to(msg.formatted, "{:02}:{:02}:{02} {}", tm_time.tm_min, tm_time.tm_sec, ampm(tm_time)); | ||||||
|     } |     } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| @ -284,7 +312,8 @@ class R_formatter SPDLOG_FINAL : public flag_formatter | |||||||
| { | { | ||||||
|     void format(details::log_msg &msg, const std::tm &tm_time) override |     void format(details::log_msg &msg, const std::tm &tm_time) override | ||||||
|     { |     { | ||||||
|         pad_n_join(msg.formatted, tm_time.tm_hour, tm_time.tm_min, ':'); |         // pad_n_join(msg.formatted, tm_time.tm_hour, tm_time.tm_min, ':');
 | ||||||
|  |         fmt::format_to(msg.formatted, "{:02}:{:02}", tm_time.tm_hour, tm_time.tm_min); | ||||||
|     } |     } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| @ -293,7 +322,8 @@ class T_formatter SPDLOG_FINAL : public flag_formatter | |||||||
| { | { | ||||||
|     void format(details::log_msg &msg, const std::tm &tm_time) override |     void format(details::log_msg &msg, const std::tm &tm_time) override | ||||||
|     { |     { | ||||||
|         pad_n_join(msg.formatted, tm_time.tm_hour, tm_time.tm_min, tm_time.tm_sec, ':'); |         // pad_n_join(msg.formatted, tm_time.tm_hour, tm_time.tm_min, tm_time.tm_sec, ':');
 | ||||||
|  |         fmt::format_to(msg.formatted, "{:02}:{:02}", tm_time.tm_min, tm_time.tm_sec); | ||||||
|     } |     } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| @ -330,8 +360,9 @@ public: | |||||||
| 
 | 
 | ||||||
|         int h = total_minutes / 60; |         int h = total_minutes / 60; | ||||||
|         int m = total_minutes % 60; |         int m = total_minutes % 60; | ||||||
|         msg.formatted << sign; |         // msg.formatted << sign;
 | ||||||
|         pad_n_join(msg.formatted, h, m, ':'); |         // pad_n_join(msg.formatted, h, m, ':');
 | ||||||
|  |         fmt::format_to(msg.formatted, "{}{:02}:{:02}", sign, h, m); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
| @ -356,7 +387,8 @@ class t_formatter SPDLOG_FINAL : public flag_formatter | |||||||
| { | { | ||||||
|     void format(details::log_msg &msg, const std::tm &) override |     void format(details::log_msg &msg, const std::tm &) override | ||||||
|     { |     { | ||||||
|         msg.formatted << msg.thread_id; |         // msg.formatted << msg.thread_id;
 | ||||||
|  |         fmt::format_to(msg.formatted, "{}", msg.thread_id); | ||||||
|     } |     } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| @ -365,7 +397,8 @@ class pid_formatter SPDLOG_FINAL : public flag_formatter | |||||||
| { | { | ||||||
|     void format(details::log_msg &msg, const std::tm &) override |     void format(details::log_msg &msg, const std::tm &) override | ||||||
|     { |     { | ||||||
|         msg.formatted << details::os::pid(); |         // msg.formatted << details::os::pid();
 | ||||||
|  |         fmt::format_to(msg.formatted, "{}", details::os::pid()); | ||||||
|     } |     } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| @ -374,7 +407,8 @@ class i_formatter SPDLOG_FINAL : public flag_formatter | |||||||
| { | { | ||||||
|     void format(details::log_msg &msg, const std::tm &) override |     void format(details::log_msg &msg, const std::tm &) override | ||||||
|     { |     { | ||||||
|         msg.formatted << fmt::pad(msg.msg_id, 6, '0'); |         // msg.formatted << fmt::pad(msg.msg_id, 6, '0');
 | ||||||
|  |         fmt::format_to(msg.formatted, "{:06}", msg.msg_id); | ||||||
|     } |     } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| @ -382,7 +416,8 @@ class v_formatter SPDLOG_FINAL : public flag_formatter | |||||||
| { | { | ||||||
|     void format(details::log_msg &msg, const std::tm &) override |     void format(details::log_msg &msg, const std::tm &) override | ||||||
|     { |     { | ||||||
|         msg.formatted << fmt::StringRef(msg.raw.data(), msg.raw.size()); |         // msg.formatted << fmt::StringRef(msg.raw.data(), msg.raw.size());
 | ||||||
|  |         append_buf(msg.raw, msg.formatted); | ||||||
|     } |     } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| @ -395,7 +430,8 @@ public: | |||||||
|     } |     } | ||||||
|     void format(details::log_msg &msg, const std::tm &) override |     void format(details::log_msg &msg, const std::tm &) override | ||||||
|     { |     { | ||||||
|         msg.formatted << ch_; |         // msg.formatted << ch_;
 | ||||||
|  |         msg.formatted.push_back(ch_); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
| @ -414,7 +450,8 @@ public: | |||||||
|     } |     } | ||||||
|     void format(details::log_msg &msg, const std::tm &) override |     void format(details::log_msg &msg, const std::tm &) override | ||||||
|     { |     { | ||||||
|         msg.formatted << str_; |         // msg.formatted << str_;
 | ||||||
|  |         append_str(str_, msg.formatted); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
| @ -447,20 +484,7 @@ class full_formatter SPDLOG_FINAL : public flag_formatter | |||||||
|         auto duration = msg.time.time_since_epoch(); |         auto duration = msg.time.time_since_epoch(); | ||||||
|         auto millis = std::chrono::duration_cast<std::chrono::milliseconds>(duration).count() % 1000; |         auto millis = std::chrono::duration_cast<std::chrono::milliseconds>(duration).count() % 1000; | ||||||
| 
 | 
 | ||||||
|         /* Slower version(while still very fast - about 3.2 million lines/sec under 10 threads),
 |         /*
 | ||||||
|         msg.formatted.write("[{:d}-{:02d}-{:02d} {:02d}:{:02d}:{:02d}.{:03d}] [{}] [{}] {} ", |  | ||||||
|         tm_time.tm_year + 1900, |  | ||||||
|         tm_time.tm_mon + 1, |  | ||||||
|         tm_time.tm_mday, |  | ||||||
|         tm_time.tm_hour, |  | ||||||
|         tm_time.tm_min, |  | ||||||
|         tm_time.tm_sec, |  | ||||||
|         static_cast<int>(millis), |  | ||||||
|         msg.logger_name, |  | ||||||
|         level::to_str(msg.level), |  | ||||||
|         msg.raw.str());*/ |  | ||||||
| 
 |  | ||||||
|         // Faster (albeit uglier) way to format the line (5.6 million lines/sec under 10 threads)
 |  | ||||||
|         msg.formatted << '[' << static_cast<unsigned int>(tm_time.tm_year + 1900) << '-' |         msg.formatted << '[' << static_cast<unsigned int>(tm_time.tm_year + 1900) << '-' | ||||||
|                       << fmt::pad(static_cast<unsigned int>(tm_time.tm_mon + 1), 2, '0') << '-' |                       << fmt::pad(static_cast<unsigned int>(tm_time.tm_mon + 1), 2, '0') << '-' | ||||||
|                       << fmt::pad(static_cast<unsigned int>(tm_time.tm_mday), 2, '0') << ' ' |                       << fmt::pad(static_cast<unsigned int>(tm_time.tm_mday), 2, '0') << ' ' | ||||||
| @ -468,6 +492,11 @@ class full_formatter SPDLOG_FINAL : public flag_formatter | |||||||
|                       << fmt::pad(static_cast<unsigned int>(tm_time.tm_min), 2, '0') << ':' |                       << fmt::pad(static_cast<unsigned int>(tm_time.tm_min), 2, '0') << ':' | ||||||
|                       << fmt::pad(static_cast<unsigned int>(tm_time.tm_sec), 2, '0') << '.' |                       << fmt::pad(static_cast<unsigned int>(tm_time.tm_sec), 2, '0') << '.' | ||||||
|                       << fmt::pad(static_cast<unsigned int>(millis), 3, '0') << "] "; |                       << fmt::pad(static_cast<unsigned int>(millis), 3, '0') << "] "; | ||||||
|  |         */ | ||||||
|  | 
 | ||||||
|  |         // fmt::format_to(msg.formatted, "[{:d}-{:02d}-{:02d} {:02d}:{:02d}:{:02d}.{:03d}] [{}] [{}] ",
 | ||||||
|  |         fmt::format_to(msg.formatted, "[{}-{:02}-{:02} {:02}:{:02}:{:02}.{:03}] ", tm_time.tm_year + 1900, tm_time.tm_mon + 1, | ||||||
|  |             tm_time.tm_mday, tm_time.tm_hour, tm_time.tm_min, tm_time.tm_sec, static_cast<int>(millis)); | ||||||
| 
 | 
 | ||||||
|         // no datetime needed
 |         // no datetime needed
 | ||||||
| #else | #else | ||||||
| @ -475,15 +504,24 @@ class full_formatter SPDLOG_FINAL : public flag_formatter | |||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #ifndef SPDLOG_NO_NAME | #ifndef SPDLOG_NO_NAME | ||||||
|         msg.formatted << '[' << *msg.logger_name << "] "; |         // msg.formatted << '[' << *msg.logger_name << "] ";
 | ||||||
|  |         fmt::format_to(msg.formatted, "[{}] ", *msg.logger_name); | ||||||
|  | 
 | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|         msg.formatted << '['; |         // msg.formatted << '[';
 | ||||||
|  |         msg.formatted.push_back('['); | ||||||
|  | 
 | ||||||
|         // wrap the level name with color
 |         // wrap the level name with color
 | ||||||
|         msg.color_range_start = msg.formatted.size(); |         msg.color_range_start = msg.formatted.size(); | ||||||
|         msg.formatted << level::to_str(msg.level); |         // msg.formatted << level::to_str(msg.level);
 | ||||||
|  |         append_str(level::to_str(msg.level), msg.formatted); | ||||||
|         msg.color_range_end = msg.formatted.size(); |         msg.color_range_end = msg.formatted.size(); | ||||||
|         msg.formatted << "] " << fmt::StringRef(msg.raw.data(), msg.raw.size()); | 
 | ||||||
|  |         // msg.formatted << "] " << fmt::StringRef(msg.raw.data(), msg.raw.size());
 | ||||||
|  |         msg.formatted.push_back(']'); | ||||||
|  |         msg.formatted.push_back(' '); | ||||||
|  |         append_buf(msg.raw, msg.formatted); | ||||||
|     } |     } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| @ -703,5 +741,7 @@ inline void spdlog::pattern_formatter::format(details::log_msg &msg) | |||||||
|         f->format(msg, tm_time); |         f->format(msg, tm_time); | ||||||
|     } |     } | ||||||
|     // write eol
 |     // write eol
 | ||||||
|     msg.formatted << eol_; | 
 | ||||||
|  |     // msg.formatted << eol_;
 | ||||||
|  |     append_str(eol_, msg.formatted); | ||||||
| } | } | ||||||
|  | |||||||
| @ -65,15 +65,13 @@ struct async_msg | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // copy into log_msg
 |     // copy into log_msg
 | ||||||
|     void to_log_msg(log_msg &&msg) |     void to_log_msg(log_msg &msg) | ||||||
|     { |     { | ||||||
|         msg.logger_name = &worker_ptr->name(); |         msg.logger_name = &worker_ptr->name(); | ||||||
|         msg.level = level; |         msg.level = level; | ||||||
|         msg.time = time; |         msg.time = time; | ||||||
|         msg.thread_id = thread_id; |         msg.thread_id = thread_id; | ||||||
|         msg.raw.clear(); |         msg.raw.append(txt.data(), txt.data() + txt.size()); | ||||||
|         msg.raw << txt; |  | ||||||
|         msg.formatted.clear(); |  | ||||||
|         msg.msg_id = msg_id; |         msg.msg_id = msg_id; | ||||||
|         msg.color_range_start = 0; |         msg.color_range_start = 0; | ||||||
|         msg.color_range_end = 0; |         msg.color_range_end = 0; | ||||||
| @ -182,7 +180,7 @@ private: | |||||||
|         default: |         default: | ||||||
|         { |         { | ||||||
|             log_msg msg; |             log_msg msg; | ||||||
|             incoming_async_msg.to_log_msg(std::move(msg)); |             incoming_async_msg.to_log_msg(msg); | ||||||
|             incoming_async_msg.worker_ptr->backend_log_(msg); |             incoming_async_msg.worker_ptr->backend_log_(msg); | ||||||
|             return true; |             return true; | ||||||
|         } |         } | ||||||
|  | |||||||
| @ -1,495 +0,0 @@ | |||||||
| /*
 |  | ||||||
|  Formatting library for C++ |  | ||||||
| 
 |  | ||||||
|  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: |  | ||||||
| 
 |  | ||||||
|  1. Redistributions of source code must retain the above copyright notice, this |  | ||||||
|     list of conditions and the following disclaimer. |  | ||||||
|  2. Redistributions in binary form must reproduce the above copyright notice, |  | ||||||
|     this list of conditions and the following disclaimer in the documentation |  | ||||||
|     and/or other materials provided with the distribution. |  | ||||||
| 
 |  | ||||||
|  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |  | ||||||
|  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |  | ||||||
|  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |  | ||||||
|  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR |  | ||||||
|  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |  | ||||||
|  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |  | ||||||
|  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |  | ||||||
|  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |  | ||||||
|  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |  | ||||||
|  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| #include "format.h" |  | ||||||
| 
 |  | ||||||
| #include <string.h> |  | ||||||
| 
 |  | ||||||
| #include <cctype> |  | ||||||
| #include <cerrno> |  | ||||||
| #include <climits> |  | ||||||
| #include <cmath> |  | ||||||
| #include <cstdarg> |  | ||||||
| #include <cstddef>  // for std::ptrdiff_t
 |  | ||||||
| 
 |  | ||||||
| #if defined(_WIN32) && defined(__MINGW32__) |  | ||||||
| # include <cstring> |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| #if FMT_USE_WINDOWS_H |  | ||||||
| # if !defined(FMT_HEADER_ONLY) && !defined(WIN32_LEAN_AND_MEAN) |  | ||||||
| #  define WIN32_LEAN_AND_MEAN |  | ||||||
| # endif |  | ||||||
| # if defined(NOMINMAX) || defined(FMT_WIN_MINMAX) |  | ||||||
| #  include <windows.h> |  | ||||||
| # else |  | ||||||
| #  define NOMINMAX |  | ||||||
| #  include <windows.h> |  | ||||||
| #  undef NOMINMAX |  | ||||||
| # endif |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| #if FMT_EXCEPTIONS |  | ||||||
| # define FMT_TRY try |  | ||||||
| # define FMT_CATCH(x) catch (x) |  | ||||||
| #else |  | ||||||
| # define FMT_TRY if (true) |  | ||||||
| # define FMT_CATCH(x) if (false) |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| #ifdef _MSC_VER |  | ||||||
| # pragma warning(push) |  | ||||||
| # pragma warning(disable: 4127)  // conditional expression is constant
 |  | ||||||
| # pragma warning(disable: 4702)  // unreachable code
 |  | ||||||
| // Disable deprecation warning for strerror. The latter is not called but
 |  | ||||||
| // MSVC fails to detect it.
 |  | ||||||
| # pragma warning(disable: 4996) |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| // Dummy implementations of strerror_r and strerror_s called if corresponding
 |  | ||||||
| // system functions are not available.
 |  | ||||||
| FMT_MAYBE_UNUSED |  | ||||||
| static inline fmt::internal::Null<> strerror_r(int, char *, ...) { |  | ||||||
|   return fmt::internal::Null<>(); |  | ||||||
| } |  | ||||||
| FMT_MAYBE_UNUSED |  | ||||||
| static inline fmt::internal::Null<> strerror_s(char *, std::size_t, ...) { |  | ||||||
|   return fmt::internal::Null<>(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| namespace fmt { |  | ||||||
| 
 |  | ||||||
| FMT_FUNC internal::RuntimeError::~RuntimeError() FMT_DTOR_NOEXCEPT {} |  | ||||||
| FMT_FUNC FormatError::~FormatError() FMT_DTOR_NOEXCEPT {} |  | ||||||
| FMT_FUNC SystemError::~SystemError() FMT_DTOR_NOEXCEPT {} |  | ||||||
| 
 |  | ||||||
| namespace { |  | ||||||
| 
 |  | ||||||
| #ifndef _MSC_VER |  | ||||||
| # define FMT_SNPRINTF snprintf |  | ||||||
| #else  // _MSC_VER
 |  | ||||||
| inline int fmt_snprintf(char *buffer, size_t size, const char *format, ...) { |  | ||||||
|   va_list args; |  | ||||||
|   va_start(args, format); |  | ||||||
|   int result = vsnprintf_s(buffer, size, _TRUNCATE, format, args); |  | ||||||
|   va_end(args); |  | ||||||
|   return result; |  | ||||||
| } |  | ||||||
| # define FMT_SNPRINTF fmt_snprintf |  | ||||||
| #endif  // _MSC_VER
 |  | ||||||
| 
 |  | ||||||
| #if defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT) |  | ||||||
| # define FMT_SWPRINTF snwprintf |  | ||||||
| #else |  | ||||||
| # define FMT_SWPRINTF swprintf |  | ||||||
| #endif // defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT)
 |  | ||||||
| 
 |  | ||||||
| const char RESET_COLOR[] = "\x1b[0m"; |  | ||||||
| 
 |  | ||||||
| typedef void (*FormatFunc)(Writer &, int, StringRef); |  | ||||||
| 
 |  | ||||||
| // Portable thread-safe version of strerror.
 |  | ||||||
| // Sets buffer to point to a string describing the error code.
 |  | ||||||
| // This can be either a pointer to a string stored in buffer,
 |  | ||||||
| // or a pointer to some static immutable string.
 |  | ||||||
| // Returns one of the following values:
 |  | ||||||
| //   0      - success
 |  | ||||||
| //   ERANGE - buffer is not large enough to store the error message
 |  | ||||||
| //   other  - failure
 |  | ||||||
| // Buffer should be at least of size 1.
 |  | ||||||
| int safe_strerror( |  | ||||||
|     int error_code, char *&buffer, std::size_t buffer_size) FMT_NOEXCEPT { |  | ||||||
|   FMT_ASSERT(buffer != FMT_NULL && buffer_size != 0, "invalid buffer"); |  | ||||||
| 
 |  | ||||||
|   class StrError { |  | ||||||
|    private: |  | ||||||
|     int error_code_; |  | ||||||
|     char *&buffer_; |  | ||||||
|     std::size_t buffer_size_; |  | ||||||
| 
 |  | ||||||
|     // A noop assignment operator to avoid bogus warnings.
 |  | ||||||
|     void operator=(const StrError &) {} |  | ||||||
| 
 |  | ||||||
|     // Handle the result of XSI-compliant version of strerror_r.
 |  | ||||||
|     int handle(int result) { |  | ||||||
|       // glibc versions before 2.13 return result in errno.
 |  | ||||||
|       return result == -1 ? errno : result; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     // Handle the result of GNU-specific version of strerror_r.
 |  | ||||||
|     int handle(char *message) { |  | ||||||
|       // If the buffer is full then the message is probably truncated.
 |  | ||||||
|       if (message == buffer_ && strlen(buffer_) == buffer_size_ - 1) |  | ||||||
|         return ERANGE; |  | ||||||
|       buffer_ = message; |  | ||||||
|       return 0; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     // Handle the case when strerror_r is not available.
 |  | ||||||
|     int handle(internal::Null<>) { |  | ||||||
|       return fallback(strerror_s(buffer_, buffer_size_, error_code_)); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     // Fallback to strerror_s when strerror_r is not available.
 |  | ||||||
|     int fallback(int result) { |  | ||||||
|       // If the buffer is full then the message is probably truncated.
 |  | ||||||
|       return result == 0 && strlen(buffer_) == buffer_size_ - 1 ? |  | ||||||
|             ERANGE : result; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| #ifdef __c2__ |  | ||||||
| # pragma clang diagnostic push |  | ||||||
| # pragma clang diagnostic ignored "-Wdeprecated-declarations" |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
|     // Fallback to strerror if strerror_r and strerror_s are not available.
 |  | ||||||
|     int fallback(internal::Null<>) { |  | ||||||
|       errno = 0; |  | ||||||
|       buffer_ = strerror(error_code_); |  | ||||||
|       return errno; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| #ifdef __c2__ |  | ||||||
| # pragma clang diagnostic pop |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
|    public: |  | ||||||
|     StrError(int err_code, char *&buf, std::size_t buf_size) |  | ||||||
|       : error_code_(err_code), buffer_(buf), buffer_size_(buf_size) {} |  | ||||||
| 
 |  | ||||||
|     int run() { |  | ||||||
|       return handle(strerror_r(error_code_, buffer_, buffer_size_)); |  | ||||||
|     } |  | ||||||
|   }; |  | ||||||
|   return StrError(error_code, buffer, buffer_size).run(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| 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<int>::MainType MainType; |  | ||||||
|   MainType abs_value = static_cast<MainType>(error_code); |  | ||||||
|   if (internal::is_negative(error_code)) { |  | ||||||
|     abs_value = 0 - abs_value; |  | ||||||
|     ++error_code_size; |  | ||||||
|   } |  | ||||||
|   error_code_size += 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); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| 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
 |  | ||||||
| 
 |  | ||||||
| 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()); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| template <typename T> |  | ||||||
| int internal::CharTraits<char>::format_float( |  | ||||||
|     char *buffer, std::size_t size, const char *format, |  | ||||||
|     unsigned width, int precision, T value) { |  | ||||||
|   if (width == 0) { |  | ||||||
|     return precision < 0 ? |  | ||||||
|         FMT_SNPRINTF(buffer, size, format, value) : |  | ||||||
|         FMT_SNPRINTF(buffer, size, format, precision, value); |  | ||||||
|   } |  | ||||||
|   return precision < 0 ? |  | ||||||
|       FMT_SNPRINTF(buffer, size, format, width, value) : |  | ||||||
|       FMT_SNPRINTF(buffer, size, format, width, precision, value); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| template <typename T> |  | ||||||
| int internal::CharTraits<wchar_t>::format_float( |  | ||||||
|     wchar_t *buffer, std::size_t size, const wchar_t *format, |  | ||||||
|     unsigned width, int precision, T value) { |  | ||||||
|   if (width == 0) { |  | ||||||
|     return precision < 0 ? |  | ||||||
|         FMT_SWPRINTF(buffer, size, format, value) : |  | ||||||
|         FMT_SWPRINTF(buffer, size, format, precision, value); |  | ||||||
|   } |  | ||||||
|   return precision < 0 ? |  | ||||||
|       FMT_SWPRINTF(buffer, size, format, width, value) : |  | ||||||
|       FMT_SWPRINTF(buffer, size, format, width, precision, value); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| template <typename T> |  | ||||||
| const char internal::BasicData<T>::DIGITS[] = |  | ||||||
|     "0001020304050607080910111213141516171819" |  | ||||||
|     "2021222324252627282930313233343536373839" |  | ||||||
|     "4041424344454647484950515253545556575859" |  | ||||||
|     "6061626364656667686970717273747576777879" |  | ||||||
|     "8081828384858687888990919293949596979899"; |  | ||||||
| 
 |  | ||||||
| #define FMT_POWERS_OF_10(factor) \ |  | ||||||
|   factor * 10, \ |  | ||||||
|   factor * 100, \ |  | ||||||
|   factor * 1000, \ |  | ||||||
|   factor * 10000, \ |  | ||||||
|   factor * 100000, \ |  | ||||||
|   factor * 1000000, \ |  | ||||||
|   factor * 10000000, \ |  | ||||||
|   factor * 100000000, \ |  | ||||||
|   factor * 1000000000 |  | ||||||
| 
 |  | ||||||
| template <typename T> |  | ||||||
| const uint32_t internal::BasicData<T>::POWERS_OF_10_32[] = { |  | ||||||
|   0, FMT_POWERS_OF_10(1) |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| template <typename T> |  | ||||||
| const uint64_t internal::BasicData<T>::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 |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| FMT_FUNC void internal::report_unknown_type(char code, const char *type) { |  | ||||||
|   (void)type; |  | ||||||
|   if (std::isprint(static_cast<unsigned char>(code))) { |  | ||||||
|     FMT_THROW(FormatError( |  | ||||||
|         format("unknown format code '{}' for {}", code, type))); |  | ||||||
|   } |  | ||||||
|   FMT_THROW(FormatError( |  | ||||||
|       format("unknown format code '\\x{:02x}' for {}", |  | ||||||
|         static_cast<unsigned>(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<int>(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 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 int internal::UTF16ToUTF8::convert(WStringRef s) { |  | ||||||
|   if (s.size() > INT_MAX) |  | ||||||
|     return ERROR_INVALID_PARAMETER; |  | ||||||
|   int s_size = static_cast<int>(s.size()); |  | ||||||
|   int length = WideCharToMultiByte( |  | ||||||
|     CP_UTF8, 0, s.data(), s_size, 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 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 internal::format_windows_error( |  | ||||||
|     Writer &out, int error_code, StringRef message) FMT_NOEXCEPT { |  | ||||||
|   FMT_TRY { |  | ||||||
|     MemoryBuffer<wchar_t, INLINE_BUFFER_SIZE> buffer; |  | ||||||
|     buffer.resize(INLINE_BUFFER_SIZE); |  | ||||||
|     for (;;) { |  | ||||||
|       wchar_t *system_message = &buffer[0]; |  | ||||||
|       int result = FormatMessageW( |  | ||||||
|         FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, |  | ||||||
|         FMT_NULL, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), |  | ||||||
|         system_message, static_cast<uint32_t>(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.
 |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| #endif  // FMT_USE_WINDOWS_H
 |  | ||||||
| 
 |  | ||||||
| FMT_FUNC void format_system_error( |  | ||||||
|     Writer &out, int error_code, StringRef message) FMT_NOEXCEPT { |  | ||||||
|   FMT_TRY { |  | ||||||
|     internal::MemoryBuffer<char, internal::INLINE_BUFFER_SIZE> 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.
 |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| template <typename Char> |  | ||||||
| void internal::FixedBuffer<Char>::grow(std::size_t) { |  | ||||||
|   FMT_THROW(std::runtime_error("buffer overflow")); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| FMT_FUNC internal::Arg internal::FormatterBase::do_get_arg( |  | ||||||
|     unsigned arg_index, const char *&error) { |  | ||||||
|   internal::Arg arg = args_[arg_index]; |  | ||||||
|   switch (arg.type) { |  | ||||||
|   case internal::Arg::NONE: |  | ||||||
|     error = "argument index out of range"; |  | ||||||
|     break; |  | ||||||
|   case internal::Arg::NAMED_ARG: |  | ||||||
|     arg = *static_cast<const internal::Arg*>(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); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| #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); |  | ||||||
| } |  | ||||||
| #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 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<char>('0' + c); |  | ||||||
|   std::fputs(escape, stdout); |  | ||||||
|   print(format, args); |  | ||||||
|   std::fputs(RESET_COLOR, stdout); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| #ifndef FMT_HEADER_ONLY |  | ||||||
| 
 |  | ||||||
| template struct internal::BasicData<void>; |  | ||||||
| 
 |  | ||||||
| // Explicit instantiations for char.
 |  | ||||||
| 
 |  | ||||||
| template void internal::FixedBuffer<char>::grow(std::size_t); |  | ||||||
| 
 |  | ||||||
| template FMT_API int internal::CharTraits<char>::format_float( |  | ||||||
|     char *buffer, std::size_t size, const char *format, |  | ||||||
|     unsigned width, int precision, double value); |  | ||||||
| 
 |  | ||||||
| template FMT_API int internal::CharTraits<char>::format_float( |  | ||||||
|     char *buffer, std::size_t size, const char *format, |  | ||||||
|     unsigned width, int precision, long double value); |  | ||||||
| 
 |  | ||||||
| // Explicit instantiations for wchar_t.
 |  | ||||||
| 
 |  | ||||||
| template void internal::FixedBuffer<wchar_t>::grow(std::size_t); |  | ||||||
| 
 |  | ||||||
| template FMT_API int internal::CharTraits<wchar_t>::format_float( |  | ||||||
|     wchar_t *buffer, std::size_t size, const wchar_t *format, |  | ||||||
|     unsigned width, int precision, double value); |  | ||||||
| 
 |  | ||||||
| template FMT_API int internal::CharTraits<wchar_t>::format_float( |  | ||||||
|     wchar_t *buffer, std::size_t size, const wchar_t *format, |  | ||||||
|     unsigned width, int precision, long double value); |  | ||||||
| 
 |  | ||||||
| #endif  // FMT_HEADER_ONLY
 |  | ||||||
| 
 |  | ||||||
| }  // namespace fmt
 |  | ||||||
| 
 |  | ||||||
| #ifdef _MSC_VER |  | ||||||
| # pragma warning(pop) |  | ||||||
| #endif |  | ||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -1,35 +0,0 @@ | |||||||
| /*
 |  | ||||||
|  Formatting library for C++ - std::ostream support |  | ||||||
| 
 |  | ||||||
|  Copyright (c) 2012 - 2016, Victor Zverovich |  | ||||||
|  All rights reserved. |  | ||||||
| 
 |  | ||||||
|  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<std::streamsize>::Type UnsignedStreamSize; |  | ||||||
|   UnsignedStreamSize size = w.size(); |  | ||||||
|   UnsignedStreamSize max_size = |  | ||||||
|       internal::to_unsigned((std::numeric_limits<std::streamsize>::max)()); |  | ||||||
|   do { |  | ||||||
|     UnsignedStreamSize n = size <= max_size ? size : max_size; |  | ||||||
|     os.write(data, static_cast<std::streamsize>(n)); |  | ||||||
|     data += n; |  | ||||||
|     size -= n; |  | ||||||
|   } while (size != 0); |  | ||||||
| } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| FMT_FUNC void print(std::ostream &os, CStringRef format_str, ArgList args) { |  | ||||||
|   MemoryWriter w; |  | ||||||
|   w.write(format_str, args); |  | ||||||
|   internal::write(os, w); |  | ||||||
| } |  | ||||||
| }  // namespace fmt
 |  | ||||||
| @ -1,117 +0,0 @@ | |||||||
| /*
 |  | ||||||
|  Formatting library for C++ - std::ostream support |  | ||||||
| 
 |  | ||||||
|  Copyright (c) 2012 - 2016, Victor Zverovich |  | ||||||
|  All rights reserved. |  | ||||||
| 
 |  | ||||||
|  For the license information refer to format.h. |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| #ifndef FMT_OSTREAM_H_ |  | ||||||
| #define FMT_OSTREAM_H_ |  | ||||||
| 
 |  | ||||||
| #include "format.h" |  | ||||||
| #include <ostream> |  | ||||||
| 
 |  | ||||||
| namespace fmt { |  | ||||||
| 
 |  | ||||||
| namespace internal { |  | ||||||
| 
 |  | ||||||
| template<class Char> |  | ||||||
| class FormatBuf : public std::basic_streambuf<Char> |  | ||||||
| { |  | ||||||
| private: |  | ||||||
|     typedef typename std::basic_streambuf<Char>::int_type int_type; |  | ||||||
|     typedef typename std::basic_streambuf<Char>::traits_type traits_type; |  | ||||||
| 
 |  | ||||||
|     Buffer<Char> &buffer_; |  | ||||||
| 
 |  | ||||||
| public: |  | ||||||
|     FormatBuf(Buffer<Char> &buffer) |  | ||||||
|         : buffer_(buffer) |  | ||||||
|     { |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| protected: |  | ||||||
|     // The put-area is actually always empty. This makes the implementation
 |  | ||||||
|     // simpler and has the advantage that the streambuf and the buffer are always
 |  | ||||||
|     // in sync and sputc never writes into uninitialized memory. The obvious
 |  | ||||||
|     // disadvantage is that each call to sputc always results in a (virtual) call
 |  | ||||||
|     // to overflow. There is no disadvantage here for sputn since this always
 |  | ||||||
|     // results in a call to xsputn.
 |  | ||||||
| 
 |  | ||||||
|     int_type overflow(int_type ch = traits_type::eof()) FMT_OVERRIDE |  | ||||||
|     { |  | ||||||
|         if (!traits_type::eq_int_type(ch, traits_type::eof())) |  | ||||||
|             buffer_.push_back(static_cast<Char>(ch)); |  | ||||||
|         return ch; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     std::streamsize xsputn(const Char *s, std::streamsize count) FMT_OVERRIDE |  | ||||||
|     { |  | ||||||
|         buffer_.append(s, s + count); |  | ||||||
|         return count; |  | ||||||
|     } |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| Yes &convert(std::ostream &); |  | ||||||
| 
 |  | ||||||
| struct DummyStream : std::ostream |  | ||||||
| { |  | ||||||
|     DummyStream(); // Suppress a bogus warning in MSVC.
 |  | ||||||
| 
 |  | ||||||
|     // Hide all operator<< overloads from std::ostream.
 |  | ||||||
|     template<typename T> |  | ||||||
|     typename EnableIf<sizeof(T) == 0>::type operator<<(const T &); |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| No &operator<<(std::ostream &, int); |  | ||||||
| 
 |  | ||||||
| template<typename T> |  | ||||||
| struct ConvertToIntImpl<T, true> |  | ||||||
| { |  | ||||||
|     // Convert to int only if T doesn't have an overloaded operator<<.
 |  | ||||||
|     enum |  | ||||||
|     { |  | ||||||
|         value = sizeof(convert(get<DummyStream>() << get<T>())) == sizeof(No) |  | ||||||
|     }; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| // Write the content of w to os.
 |  | ||||||
| FMT_API void write(std::ostream &os, Writer &w); |  | ||||||
| } // namespace internal
 |  | ||||||
| 
 |  | ||||||
| // Formats a value.
 |  | ||||||
| template<typename Char, typename ArgFormatter_, typename T> |  | ||||||
| void format_arg(BasicFormatter<Char, ArgFormatter_> &f, const Char *&format_str, const T &value) |  | ||||||
| { |  | ||||||
|     internal::MemoryBuffer<Char, internal::INLINE_BUFFER_SIZE> buffer; |  | ||||||
| 
 |  | ||||||
|     internal::FormatBuf<Char> format_buf(buffer); |  | ||||||
|     std::basic_ostream<Char> output(&format_buf); |  | ||||||
|     output.exceptions(std::ios_base::failbit | std::ios_base::badbit); |  | ||||||
|     output << value; |  | ||||||
| 
 |  | ||||||
|     BasicStringRef<Char> str(&buffer[0], buffer.size()); |  | ||||||
|     typedef internal::MakeArg<BasicFormatter<Char>> MakeArg; |  | ||||||
|     format_str = f.format(format_str, MakeArg(str)); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /**
 |  | ||||||
|   \rst |  | ||||||
|   Prints formatted data to the stream *os*. |  | ||||||
| 
 |  | ||||||
|   **Example**:: |  | ||||||
| 
 |  | ||||||
|     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) |  | ||||||
| } // namespace fmt
 |  | ||||||
| 
 |  | ||||||
| #ifdef FMT_HEADER_ONLY |  | ||||||
| #include "ostream.cc" |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| #endif // FMT_OSTREAM_H_
 |  | ||||||
| @ -1,241 +0,0 @@ | |||||||
| /*
 |  | ||||||
|  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 <limits.h> |  | ||||||
| #include <sys/types.h> |  | ||||||
| #include <sys/stat.h> |  | ||||||
| 
 |  | ||||||
| #ifndef _WIN32 |  | ||||||
| # include <unistd.h> |  | ||||||
| #else |  | ||||||
| # ifndef WIN32_LEAN_AND_MEAN |  | ||||||
| #  define WIN32_LEAN_AND_MEAN |  | ||||||
| # endif |  | ||||||
| # include <windows.h> |  | ||||||
| # include <io.h> |  | ||||||
| 
 |  | ||||||
| # 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<unsigned>(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_ = FMT_NULL; |  | ||||||
|   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<HANDLE>(_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 |  | ||||||
| } |  | ||||||
| @ -1,423 +0,0 @@ | |||||||
| /*
 |  | ||||||
|  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 <errno.h> |  | ||||||
| #include <fcntl.h>  // for O_RDONLY |  | ||||||
| #include <locale.h> // for locale_t |  | ||||||
| #include <stdio.h> |  | ||||||
| #include <stdlib.h> // for strtod_l |  | ||||||
| 
 |  | ||||||
| #include <cstddef> |  | ||||||
| 
 |  | ||||||
| #if defined __APPLE__ || defined(__FreeBSD__) |  | ||||||
| #include <xlocale.h> // 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 |  | ||||||
| 
 |  | ||||||
| // 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_(FMT_NULL) {} |  | ||||||
| 
 |  | ||||||
|     // Destroys the object closing the file it represents if any.
 |  | ||||||
|     FMT_API ~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_ = FMT_NULL; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     // 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_ = FMT_NULL; |  | ||||||
|         return *this; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     // Returns a proxy object for moving from a temporary:
 |  | ||||||
|     //   BufferedFile file = BufferedFile(...);
 |  | ||||||
|     operator Proxy() FMT_NOEXCEPT |  | ||||||
|     { |  | ||||||
|         Proxy p = {file_}; |  | ||||||
|         file_ = FMT_NULL; |  | ||||||
|         return p; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| #else |  | ||||||
| private: |  | ||||||
|     FMT_DISALLOW_COPY_AND_ASSIGN(BufferedFile); |  | ||||||
| 
 |  | ||||||
| public: |  | ||||||
|     BufferedFile(BufferedFile &&other) FMT_NOEXCEPT : file_(other.file_) |  | ||||||
|     { |  | ||||||
|         other.file_ = FMT_NULL; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     BufferedFile &operator=(BufferedFile &&other) |  | ||||||
|     { |  | ||||||
|         close(); |  | ||||||
|         file_ = other.file_; |  | ||||||
|         other.file_ = FMT_NULL; |  | ||||||
|         return *this; |  | ||||||
|     } |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
|     // Opens a file.
 |  | ||||||
|     FMT_API BufferedFile(CStringRef filename, CStringRef mode); |  | ||||||
| 
 |  | ||||||
|     // Closes the file.
 |  | ||||||
|     FMT_API 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.
 |  | ||||||
|     FMT_API 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.
 |  | ||||||
|     FMT_API 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.
 |  | ||||||
|     FMT_API ~File() FMT_NOEXCEPT; |  | ||||||
| 
 |  | ||||||
|     // Returns the file descriptor.
 |  | ||||||
|     int descriptor() const FMT_NOEXCEPT |  | ||||||
|     { |  | ||||||
|         return fd_; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     // Closes the file.
 |  | ||||||
|     FMT_API void close(); |  | ||||||
| 
 |  | ||||||
|     // Returns the file size. The size has signed type for consistency with
 |  | ||||||
|     // stat::st_size.
 |  | ||||||
|     FMT_API LongLong size() const; |  | ||||||
| 
 |  | ||||||
|     // Attempts to read count bytes from the file into the specified buffer.
 |  | ||||||
|     FMT_API std::size_t read(void *buffer, std::size_t count); |  | ||||||
| 
 |  | ||||||
|     // Attempts to write count bytes from the specified buffer to the file.
 |  | ||||||
|     FMT_API 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.
 |  | ||||||
|     FMT_API static File dup(int fd); |  | ||||||
| 
 |  | ||||||
|     // Makes fd be the copy of this file descriptor, closing fd first if
 |  | ||||||
|     // necessary.
 |  | ||||||
|     FMT_API void dup2(int fd); |  | ||||||
| 
 |  | ||||||
|     // Makes fd be the copy of this file descriptor, closing fd first if
 |  | ||||||
|     // necessary.
 |  | ||||||
|     FMT_API 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.
 |  | ||||||
|     FMT_API 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.
 |  | ||||||
|     FMT_API 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", FMT_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 = FMT_NULL; |  | ||||||
|         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; |  | ||||||
| } |  | ||||||
| } // namespace std
 |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| #endif // FMT_POSIX_H_
 |  | ||||||
| @ -1,32 +0,0 @@ | |||||||
| /*
 |  | ||||||
|  Formatting library for C++ |  | ||||||
| 
 |  | ||||||
|  Copyright (c) 2012 - 2016, Victor Zverovich |  | ||||||
|  All rights reserved. |  | ||||||
| 
 |  | ||||||
|  For the license information refer to format.h. |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| #include "format.h" |  | ||||||
| #include "printf.h" |  | ||||||
| 
 |  | ||||||
| namespace fmt { |  | ||||||
| 
 |  | ||||||
| template <typename Char> |  | ||||||
| void printf(BasicWriter<Char> &w, BasicCStringRef<Char> format, ArgList args); |  | ||||||
| 
 |  | ||||||
| FMT_FUNC int fprintf(std::FILE *f, CStringRef format, ArgList args) { |  | ||||||
|   MemoryWriter w; |  | ||||||
|   printf(w, format, args); |  | ||||||
|   std::size_t size = w.size(); |  | ||||||
|   return std::fwrite(w.data(), 1, size, f) < size ? -1 : static_cast<int>(size); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| #ifndef FMT_HEADER_ONLY |  | ||||||
| 
 |  | ||||||
| template void PrintfFormatter<char>::format(CStringRef format); |  | ||||||
| template void PrintfFormatter<wchar_t>::format(WCStringRef format); |  | ||||||
| 
 |  | ||||||
| #endif  // FMT_HEADER_ONLY
 |  | ||||||
| 
 |  | ||||||
| }  // namespace fmt
 |  | ||||||
| @ -1,723 +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 <algorithm> // std::fill_n |  | ||||||
| #include <limits>    // 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<bool IsSigned> |  | ||||||
| struct IntChecker |  | ||||||
| { |  | ||||||
|     template<typename T> |  | ||||||
|     static bool fits_in_int(T value) |  | ||||||
|     { |  | ||||||
|         unsigned max = std::numeric_limits<int>::max(); |  | ||||||
|         return value <= max; |  | ||||||
|     } |  | ||||||
|     static bool fits_in_int(bool) |  | ||||||
|     { |  | ||||||
|         return true; |  | ||||||
|     } |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| template<> |  | ||||||
| struct IntChecker<true> |  | ||||||
| { |  | ||||||
|     template<typename T> |  | ||||||
|     static bool fits_in_int(T value) |  | ||||||
|     { |  | ||||||
|         return value >= std::numeric_limits<int>::min() && value <= std::numeric_limits<int>::max(); |  | ||||||
|     } |  | ||||||
|     static bool fits_in_int(int) |  | ||||||
|     { |  | ||||||
|         return true; |  | ||||||
|     } |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| class PrecisionHandler : public ArgVisitor<PrecisionHandler, int> |  | ||||||
| { |  | ||||||
| public: |  | ||||||
|     void report_unhandled_arg() |  | ||||||
|     { |  | ||||||
|         FMT_THROW(FormatError("precision is not integer")); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     template<typename T> |  | ||||||
|     int visit_any_int(T value) |  | ||||||
|     { |  | ||||||
|         if (!IntChecker<std::numeric_limits<T>::is_signed>::fits_in_int(value)) |  | ||||||
|             FMT_THROW(FormatError("number is too big")); |  | ||||||
|         return static_cast<int>(value); |  | ||||||
|     } |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| // IsZeroInt::visit(arg) returns true iff arg is a zero integer.
 |  | ||||||
| class IsZeroInt : public ArgVisitor<IsZeroInt, bool> |  | ||||||
| { |  | ||||||
| public: |  | ||||||
|     template<typename T> |  | ||||||
|     bool visit_any_int(T value) |  | ||||||
|     { |  | ||||||
|         return value == 0; |  | ||||||
|     } |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| // returns the default type for format specific "%s"
 |  | ||||||
| class DefaultType : public ArgVisitor<DefaultType, char> |  | ||||||
| { |  | ||||||
| public: |  | ||||||
|     char visit_char(int) |  | ||||||
|     { |  | ||||||
|         return 'c'; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     char visit_bool(bool) |  | ||||||
|     { |  | ||||||
|         return 's'; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     char visit_pointer(const void *) |  | ||||||
|     { |  | ||||||
|         return 'p'; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     template<typename T> |  | ||||||
|     char visit_any_int(T) |  | ||||||
|     { |  | ||||||
|         return 'd'; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     template<typename T> |  | ||||||
|     char visit_any_double(T) |  | ||||||
|     { |  | ||||||
|         return 'g'; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     char visit_unhandled_arg() |  | ||||||
|     { |  | ||||||
|         return 's'; |  | ||||||
|     } |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| template<typename T, typename U> |  | ||||||
| struct is_same |  | ||||||
| { |  | ||||||
|     enum |  | ||||||
|     { |  | ||||||
|         value = 0 |  | ||||||
|     }; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| template<typename T> |  | ||||||
| struct is_same<T, T> |  | ||||||
| { |  | ||||||
|     enum |  | ||||||
|     { |  | ||||||
|         value = 1 |  | ||||||
|     }; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| // An argument visitor that converts an integer argument to T for printf,
 |  | ||||||
| // if T is an integral type. If T is void, the argument is converted to
 |  | ||||||
| // corresponding signed or unsigned type depending on the type specifier:
 |  | ||||||
| // 'd' and 'i' - signed, other - unsigned)
 |  | ||||||
| template<typename T = void> |  | ||||||
| class ArgConverter : public ArgVisitor<ArgConverter<T>, 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); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     void visit_char(int value) |  | ||||||
|     { |  | ||||||
|         if (type_ != 's') |  | ||||||
|             visit_any_int(value); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     template<typename U> |  | ||||||
|     void visit_any_int(U value) |  | ||||||
|     { |  | ||||||
|         bool is_signed = type_ == 'd' || type_ == 'i'; |  | ||||||
|         if (type_ == 's') |  | ||||||
|         { |  | ||||||
|             is_signed = std::numeric_limits<U>::is_signed; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         using internal::Arg; |  | ||||||
|         typedef typename internal::Conditional<is_same<T, void>::value, U, T>::type TargetType; |  | ||||||
|         if (const_check(sizeof(TargetType) <= sizeof(int))) |  | ||||||
|         { |  | ||||||
|             // Extra casts are used to silence warnings.
 |  | ||||||
|             if (is_signed) |  | ||||||
|             { |  | ||||||
|                 arg_.type = Arg::INT; |  | ||||||
|                 arg_.int_value = static_cast<int>(static_cast<TargetType>(value)); |  | ||||||
|             } |  | ||||||
|             else |  | ||||||
|             { |  | ||||||
|                 arg_.type = Arg::UINT; |  | ||||||
|                 typedef typename internal::MakeUnsigned<TargetType>::Type Unsigned; |  | ||||||
|                 arg_.uint_value = static_cast<unsigned>(static_cast<Unsigned>(value)); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         else |  | ||||||
|         { |  | ||||||
|             if (is_signed) |  | ||||||
|             { |  | ||||||
|                 arg_.type = Arg::LONG_LONG; |  | ||||||
|                 // glibc's printf doesn't sign extend arguments of smaller types:
 |  | ||||||
|                 //   std::printf("%lld", -42);  // prints "4294967254"
 |  | ||||||
|                 // but we don't have to do the same because it's a UB.
 |  | ||||||
|                 arg_.long_long_value = static_cast<LongLong>(value); |  | ||||||
|             } |  | ||||||
|             else |  | ||||||
|             { |  | ||||||
|                 arg_.type = Arg::ULONG_LONG; |  | ||||||
|                 arg_.ulong_long_value = static_cast<typename internal::MakeUnsigned<U>::Type>(value); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| // Converts an integer argument to char for printf.
 |  | ||||||
| class CharConverter : public ArgVisitor<CharConverter, void> |  | ||||||
| { |  | ||||||
| private: |  | ||||||
|     internal::Arg &arg_; |  | ||||||
| 
 |  | ||||||
|     FMT_DISALLOW_COPY_AND_ASSIGN(CharConverter); |  | ||||||
| 
 |  | ||||||
| public: |  | ||||||
|     explicit CharConverter(internal::Arg &arg) |  | ||||||
|         : arg_(arg) |  | ||||||
|     { |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     template<typename T> |  | ||||||
|     void visit_any_int(T value) |  | ||||||
|     { |  | ||||||
|         arg_.type = internal::Arg::CHAR; |  | ||||||
|         arg_.int_value = static_cast<char>(value); |  | ||||||
|     } |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| // Checks if an argument is a valid printf width specifier and sets
 |  | ||||||
| // left alignment if it is negative.
 |  | ||||||
| class WidthHandler : public ArgVisitor<WidthHandler, unsigned> |  | ||||||
| { |  | ||||||
| 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<typename T> |  | ||||||
|     unsigned visit_any_int(T value) |  | ||||||
|     { |  | ||||||
|         typedef typename internal::IntTraits<T>::MainType UnsignedType; |  | ||||||
|         UnsignedType width = static_cast<UnsignedType>(value); |  | ||||||
|         if (internal::is_negative(value)) |  | ||||||
|         { |  | ||||||
|             spec_.align_ = ALIGN_LEFT; |  | ||||||
|             width = 0 - width; |  | ||||||
|         } |  | ||||||
|         unsigned int_max = std::numeric_limits<int>::max(); |  | ||||||
|         if (width > int_max) |  | ||||||
|             FMT_THROW(FormatError("number is too big")); |  | ||||||
|         return static_cast<unsigned>(width); |  | ||||||
|     } |  | ||||||
| }; |  | ||||||
| } // namespace internal
 |  | ||||||
| 
 |  | ||||||
| /**
 |  | ||||||
|   \rst |  | ||||||
|   A ``printf`` argument formatter based on the `curiously recurring template |  | ||||||
|   pattern <http://en.wikipedia.org/wiki/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<typename Impl, typename Char, typename Spec> |  | ||||||
| class BasicPrintfArgFormatter : public internal::ArgFormatterBase<Impl, Char, Spec> |  | ||||||
| { |  | ||||||
| private: |  | ||||||
|     void write_null_pointer() |  | ||||||
|     { |  | ||||||
|         this->spec().type_ = 0; |  | ||||||
|         this->write("(nil)"); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     typedef internal::ArgFormatterBase<Impl, Char, Spec> 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<Char> &w, Spec &s) |  | ||||||
|         : internal::ArgFormatterBase<Impl, Char, Spec>(w, s) |  | ||||||
|     { |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** Formats an argument of type ``bool``. */ |  | ||||||
|     void visit_bool(bool value) |  | ||||||
|     { |  | ||||||
|         Spec &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 Spec &fmt_spec = this->spec(); |  | ||||||
|         BasicWriter<Char> &w = this->writer(); |  | ||||||
|         if (fmt_spec.type_ && fmt_spec.type_ != 'c') |  | ||||||
|             w.write_int(value, fmt_spec); |  | ||||||
|         typedef typename BasicWriter<Char>::CharPtr CharPtr; |  | ||||||
|         CharPtr out = CharPtr(); |  | ||||||
|         if (fmt_spec.width_ > 1) |  | ||||||
|         { |  | ||||||
|             Char fill = ' '; |  | ||||||
|             out = w.grow_buffer(fmt_spec.width_); |  | ||||||
|             if (fmt_spec.align_ != ALIGN_LEFT) |  | ||||||
|             { |  | ||||||
|                 std::fill_n(out, fmt_spec.width_ - 1, fill); |  | ||||||
|                 out += fmt_spec.width_ - 1; |  | ||||||
|             } |  | ||||||
|             else |  | ||||||
|             { |  | ||||||
|                 std::fill_n(out + 1, fmt_spec.width_ - 1, fill); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         else |  | ||||||
|         { |  | ||||||
|             out = w.grow_buffer(1); |  | ||||||
|         } |  | ||||||
|         *out = static_cast<Char>(value); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** 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<Char> 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<typename Char> |  | ||||||
| class PrintfArgFormatter : public BasicPrintfArgFormatter<PrintfArgFormatter<Char>, Char, FormatSpec> |  | ||||||
| { |  | ||||||
| public: |  | ||||||
|     /** Constructs an argument formatter object. */ |  | ||||||
|     PrintfArgFormatter(BasicWriter<Char> &w, FormatSpec &s) |  | ||||||
|         : BasicPrintfArgFormatter<PrintfArgFormatter<Char>, Char, FormatSpec>(w, s) |  | ||||||
|     { |  | ||||||
|     } |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| /** This template formats data and writes the output to a writer. */ |  | ||||||
| template<typename Char, typename ArgFormatter = PrintfArgFormatter<Char>> |  | ||||||
| class PrintfFormatter : private internal::FormatterBase |  | ||||||
| { |  | ||||||
| private: |  | ||||||
|     BasicWriter<Char> &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<unsigned>::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<Char> &w) |  | ||||||
|         : FormatterBase(al) |  | ||||||
|         , writer_(w) |  | ||||||
|     { |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** Formats stored arguments and writes the output to the writer. */ |  | ||||||
|     void format(BasicCStringRef<Char> format_str); |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| template<typename Char, typename AF> |  | ||||||
| void PrintfFormatter<Char, AF>::parse_flags(FormatSpec &spec, const Char *&s) |  | ||||||
| { |  | ||||||
|     for (;;) |  | ||||||
|     { |  | ||||||
|         switch (*s++) |  | ||||||
|         { |  | ||||||
|         case '-': |  | ||||||
|             spec.align_ = ALIGN_LEFT; |  | ||||||
|             break; |  | ||||||
|         case '+': |  | ||||||
|             spec.flags_ |= SIGN_FLAG | PLUS_FLAG; |  | ||||||
|             break; |  | ||||||
|         case '0': |  | ||||||
|             spec.fill_ = '0'; |  | ||||||
|             break; |  | ||||||
|         case ' ': |  | ||||||
|             spec.flags_ |= SIGN_FLAG; |  | ||||||
|             break; |  | ||||||
|         case '#': |  | ||||||
|             spec.flags_ |= HASH_FLAG; |  | ||||||
|             break; |  | ||||||
|         default: |  | ||||||
|             --s; |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| template<typename Char, typename AF> |  | ||||||
| internal::Arg PrintfFormatter<Char, AF>::get_arg(const Char *s, unsigned arg_index) |  | ||||||
| { |  | ||||||
|     (void)s; |  | ||||||
|     const char *error = FMT_NULL; |  | ||||||
|     internal::Arg arg = arg_index == std::numeric_limits<unsigned>::max() ? next_arg(error) : FormatterBase::get_arg(arg_index - 1, error); |  | ||||||
|     if (error) |  | ||||||
|         FMT_THROW(FormatError(!*s ? "invalid format string" : error)); |  | ||||||
|     return arg; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| template<typename Char, typename AF> |  | ||||||
| unsigned PrintfFormatter<Char, AF>::parse_header(const Char *&s, FormatSpec &spec) |  | ||||||
| { |  | ||||||
|     unsigned arg_index = std::numeric_limits<unsigned>::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<typename Char, typename AF> |  | ||||||
| void PrintfFormatter<Char, AF>::format(BasicCStringRef<Char> format_str) |  | ||||||
| { |  | ||||||
|     const Char *start = format_str.c_str(); |  | ||||||
|     const Char *s = start; |  | ||||||
|     while (*s) |  | ||||||
|     { |  | ||||||
|         Char c = *s++; |  | ||||||
|         if (c != '%') |  | ||||||
|             continue; |  | ||||||
|         if (*s == c) |  | ||||||
|         { |  | ||||||
|             write(writer_, start, s); |  | ||||||
|             start = ++s; |  | ||||||
|             continue; |  | ||||||
|         } |  | ||||||
|         write(writer_, start, s - 1); |  | ||||||
| 
 |  | ||||||
|         FormatSpec spec; |  | ||||||
|         spec.align_ = ALIGN_RIGHT; |  | ||||||
| 
 |  | ||||||
|         // Parse argument index, flags and width.
 |  | ||||||
|         unsigned arg_index = parse_header(s, spec); |  | ||||||
| 
 |  | ||||||
|         // Parse precision.
 |  | ||||||
|         if (*s == '.') |  | ||||||
|         { |  | ||||||
|             ++s; |  | ||||||
|             if ('0' <= *s && *s <= '9') |  | ||||||
|             { |  | ||||||
|                 spec.precision_ = static_cast<int>(internal::parse_nonnegative_int(s)); |  | ||||||
|             } |  | ||||||
|             else if (*s == '*') |  | ||||||
|             { |  | ||||||
|                 ++s; |  | ||||||
|                 spec.precision_ = internal::PrecisionHandler().visit(get_arg(s)); |  | ||||||
|             } |  | ||||||
|             else |  | ||||||
|             { |  | ||||||
|                 spec.precision_ = 0; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         using internal::Arg; |  | ||||||
|         Arg arg = get_arg(s, arg_index); |  | ||||||
|         if (spec.flag(HASH_FLAG) && internal::IsZeroInt().visit(arg)) |  | ||||||
|             spec.flags_ &= ~internal::to_unsigned<int>(HASH_FLAG); |  | ||||||
|         if (spec.fill_ == '0') |  | ||||||
|         { |  | ||||||
|             if (arg.type <= Arg::LAST_NUMERIC_TYPE) |  | ||||||
|                 spec.align_ = ALIGN_NUMERIC; |  | ||||||
|             else |  | ||||||
|                 spec.fill_ = ' '; // Ignore '0' flag for non-numeric types.
 |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         // Parse length and convert the argument to the required type.
 |  | ||||||
|         using internal::ArgConverter; |  | ||||||
|         switch (*s++) |  | ||||||
|         { |  | ||||||
|         case 'h': |  | ||||||
|             if (*s == 'h') |  | ||||||
|                 ArgConverter<signed char>(arg, *++s).visit(arg); |  | ||||||
|             else |  | ||||||
|                 ArgConverter<short>(arg, *s).visit(arg); |  | ||||||
|             break; |  | ||||||
|         case 'l': |  | ||||||
|             if (*s == 'l') |  | ||||||
|                 ArgConverter<fmt::LongLong>(arg, *++s).visit(arg); |  | ||||||
|             else |  | ||||||
|                 ArgConverter<long>(arg, *s).visit(arg); |  | ||||||
|             break; |  | ||||||
|         case 'j': |  | ||||||
|             ArgConverter<intmax_t>(arg, *s).visit(arg); |  | ||||||
|             break; |  | ||||||
|         case 'z': |  | ||||||
|             ArgConverter<std::size_t>(arg, *s).visit(arg); |  | ||||||
|             break; |  | ||||||
|         case 't': |  | ||||||
|             ArgConverter<std::ptrdiff_t>(arg, *s).visit(arg); |  | ||||||
|             break; |  | ||||||
|         case 'L': |  | ||||||
|             // printf produces garbage when 'L' is omitted for long double, no
 |  | ||||||
|             // need to do the same.
 |  | ||||||
|             break; |  | ||||||
|         default: |  | ||||||
|             --s; |  | ||||||
|             ArgConverter<void>(arg, *s).visit(arg); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         // Parse type.
 |  | ||||||
|         if (!*s) |  | ||||||
|             FMT_THROW(FormatError("invalid format string")); |  | ||||||
|         spec.type_ = static_cast<char>(*s++); |  | ||||||
| 
 |  | ||||||
|         if (spec.type_ == 's') |  | ||||||
|         { |  | ||||||
|             // set the format type to the default if 's' is specified
 |  | ||||||
|             spec.type_ = internal::DefaultType().visit(arg); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         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); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| inline void printf(Writer &w, CStringRef format, ArgList args) |  | ||||||
| { |  | ||||||
|     PrintfFormatter<char>(args, w).format(format); |  | ||||||
| } |  | ||||||
| FMT_VARIADIC(void, printf, Writer &, CStringRef) |  | ||||||
| 
 |  | ||||||
| inline void printf(WWriter &w, WCStringRef format, ArgList args) |  | ||||||
| { |  | ||||||
|     PrintfFormatter<wchar_t>(args, w).format(format); |  | ||||||
| } |  | ||||||
| FMT_VARIADIC(void, printf, WWriter &, WCStringRef) |  | ||||||
| 
 |  | ||||||
| /**
 |  | ||||||
|   \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<int>(w.size()); |  | ||||||
| } |  | ||||||
| FMT_VARIADIC(int, fprintf, std::ostream &, CStringRef) |  | ||||||
| } // namespace fmt
 |  | ||||||
| 
 |  | ||||||
| #ifdef FMT_HEADER_ONLY |  | ||||||
| #include "printf.cc" |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| #endif // FMT_PRINTF_H_
 |  | ||||||
| @ -1,188 +0,0 @@ | |||||||
| /*
 |  | ||||||
|  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 <ctime> |  | ||||||
| 
 |  | ||||||
| #ifdef _MSC_VER |  | ||||||
| #pragma warning(push) |  | ||||||
| #pragma warning(disable : 4702) // unreachable code
 |  | ||||||
| #pragma warning(disable : 4996) // "deprecated" functions
 |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| namespace fmt { |  | ||||||
| template<typename ArgFormatter> |  | ||||||
| void format_arg(BasicFormatter<char, ArgFormatter> &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<char, internal::INLINE_BUFFER_SIZE> format; |  | ||||||
|     format.append(format_str, end + 1); |  | ||||||
|     format[format.size() - 1] = '\0'; |  | ||||||
|     Buffer<char> &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; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| namespace internal { |  | ||||||
| inline Null<> localtime_r(...) |  | ||||||
| { |  | ||||||
|     return Null<>(); |  | ||||||
| } |  | ||||||
| inline Null<> localtime_s(...) |  | ||||||
| { |  | ||||||
|     return Null<>(); |  | ||||||
| } |  | ||||||
| inline Null<> gmtime_r(...) |  | ||||||
| { |  | ||||||
|     return Null<>(); |  | ||||||
| } |  | ||||||
| inline Null<> gmtime_s(...) |  | ||||||
| { |  | ||||||
|     return Null<>(); |  | ||||||
| } |  | ||||||
| } // namespace internal
 |  | ||||||
| 
 |  | ||||||
| // Thread-safe replacement for std::localtime
 |  | ||||||
| inline std::tm localtime(std::time_t time) |  | ||||||
| { |  | ||||||
|     struct LocalTime |  | ||||||
|     { |  | ||||||
|         std::time_t time_; |  | ||||||
|         std::tm tm_; |  | ||||||
| 
 |  | ||||||
|         LocalTime(std::time_t t) |  | ||||||
|             : time_(t) |  | ||||||
|         { |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         bool run() |  | ||||||
|         { |  | ||||||
|             using namespace fmt::internal; |  | ||||||
|             return handle(localtime_r(&time_, &tm_)); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         bool handle(std::tm *tm) |  | ||||||
|         { |  | ||||||
|             return tm != FMT_NULL; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         bool handle(internal::Null<>) |  | ||||||
|         { |  | ||||||
|             using namespace fmt::internal; |  | ||||||
|             return fallback(localtime_s(&tm_, &time_)); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         bool fallback(int res) |  | ||||||
|         { |  | ||||||
|             return res == 0; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         bool fallback(internal::Null<>) |  | ||||||
|         { |  | ||||||
|             using namespace fmt::internal; |  | ||||||
|             std::tm *tm = std::localtime(&time_); |  | ||||||
|             if (tm) |  | ||||||
|                 tm_ = *tm; |  | ||||||
|             return tm != FMT_NULL; |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
|     LocalTime lt(time); |  | ||||||
|     if (lt.run()) |  | ||||||
|         return lt.tm_; |  | ||||||
|     // Too big time values may be unsupported.
 |  | ||||||
|     FMT_THROW(fmt::FormatError("time_t value out of range")); |  | ||||||
|     return std::tm(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // Thread-safe replacement for std::gmtime
 |  | ||||||
| inline std::tm gmtime(std::time_t time) |  | ||||||
| { |  | ||||||
|     struct GMTime |  | ||||||
|     { |  | ||||||
|         std::time_t time_; |  | ||||||
|         std::tm tm_; |  | ||||||
| 
 |  | ||||||
|         GMTime(std::time_t t) |  | ||||||
|             : time_(t) |  | ||||||
|         { |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         bool run() |  | ||||||
|         { |  | ||||||
|             using namespace fmt::internal; |  | ||||||
|             return handle(gmtime_r(&time_, &tm_)); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         bool handle(std::tm *tm) |  | ||||||
|         { |  | ||||||
|             return tm != FMT_NULL; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         bool handle(internal::Null<>) |  | ||||||
|         { |  | ||||||
|             using namespace fmt::internal; |  | ||||||
|             return fallback(gmtime_s(&tm_, &time_)); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         bool fallback(int res) |  | ||||||
|         { |  | ||||||
|             return res == 0; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         bool fallback(internal::Null<>) |  | ||||||
|         { |  | ||||||
|             std::tm *tm = std::gmtime(&time_); |  | ||||||
|             if (tm != FMT_NULL) |  | ||||||
|                 tm_ = *tm; |  | ||||||
|             return tm != FMT_NULL; |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
|     GMTime gt(time); |  | ||||||
|     if (gt.run()) |  | ||||||
|         return gt.tm_; |  | ||||||
|     // Too big time values may be unsupported.
 |  | ||||||
|     FMT_THROW(fmt::FormatError("time_t value out of range")); |  | ||||||
|     return std::tm(); |  | ||||||
| } |  | ||||||
| } // namespace fmt
 |  | ||||||
| 
 |  | ||||||
| #ifdef _MSC_VER |  | ||||||
| #pragma warning(pop) |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| #endif // FMT_TIME_H_
 |  | ||||||
| @ -1,5 +1,5 @@ | |||||||
| //
 | //
 | ||||||
| // Copyright(c) 2016 Gabi Melman.
 | // Copyright(c) 2016-2018 Gabi Melman.
 | ||||||
| // Distributed under the MIT License (http://opensource.org/licenses/MIT)
 | // Distributed under the MIT License (http://opensource.org/licenses/MIT)
 | ||||||
| //
 | //
 | ||||||
| 
 | 
 | ||||||
| @ -11,23 +11,18 @@ | |||||||
| //
 | //
 | ||||||
| 
 | 
 | ||||||
| #if !defined(SPDLOG_FMT_EXTERNAL) | #if !defined(SPDLOG_FMT_EXTERNAL) | ||||||
| 
 |  | ||||||
| #ifndef FMT_HEADER_ONLY | #ifndef FMT_HEADER_ONLY | ||||||
| #define FMT_HEADER_ONLY | #define FMT_HEADER_ONLY | ||||||
| #endif | #endif | ||||||
| #ifndef FMT_USE_WINDOWS_H | #ifndef FMT_USE_WINDOWS_H | ||||||
| #define FMT_USE_WINDOWS_H 0 | #define FMT_USE_WINDOWS_H 0 | ||||||
| #endif | #endif | ||||||
|  | #include "bundled/core.h" | ||||||
| #include "bundled/format.h" | #include "bundled/format.h" | ||||||
| #if defined(SPDLOG_FMT_PRINTF) |  | ||||||
| #include "bundled/printf.h" |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| #else // external fmtlib
 | #else // external fmtlib
 | ||||||
| 
 | #include <fmt/core.h> | ||||||
| #include <fmt/format.h> | #include <fmt/format.h> | ||||||
| #if defined(SPDLOG_FMT_PRINTF) | #if defined(SPDLOG_FMT_PRINTF) | ||||||
| #include <fmt/printf.h> | #include <fmt/printf.h> | ||||||
| #endif | #endif | ||||||
| 
 |  | ||||||
| #endif | #endif | ||||||
|  | |||||||
| @ -30,10 +30,10 @@ struct default_daily_file_name_calculator | |||||||
|         std::tm tm = spdlog::details::os::localtime(); |         std::tm tm = spdlog::details::os::localtime(); | ||||||
|         filename_t basename, ext; |         filename_t basename, ext; | ||||||
|         std::tie(basename, ext) = details::file_helper::split_by_extenstion(filename); |         std::tie(basename, ext) = details::file_helper::split_by_extenstion(filename); | ||||||
|         std::conditional<std::is_same<filename_t::value_type, char>::value, fmt::MemoryWriter, fmt::WMemoryWriter>::type w; |         std::conditional<std::is_same<filename_t::value_type, char>::value, fmt::memory_buffer, fmt::wmemory_buffer>::type w; | ||||||
|         w.write(SPDLOG_FILENAME_T("{}_{:04d}-{:02d}-{:02d}_{:02d}-{:02d}{}"), basename, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, |         fmt::format_to(w, SPDLOG_FILENAME_T("{}_{:04d}-{:02d}-{:02d}_{:02d}-{:02d}{}"), basename, tm.tm_year + 1900, tm.tm_mon + 1, | ||||||
|             tm.tm_hour, tm.tm_min, ext); |             tm.tm_mday, tm.tm_hour, tm.tm_min, ext); | ||||||
|         return w.str(); |         return fmt::to_string(w); | ||||||
|     } |     } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| @ -48,9 +48,9 @@ struct dateonly_daily_file_name_calculator | |||||||
|         std::tm tm = spdlog::details::os::localtime(); |         std::tm tm = spdlog::details::os::localtime(); | ||||||
|         filename_t basename, ext; |         filename_t basename, ext; | ||||||
|         std::tie(basename, ext) = details::file_helper::split_by_extenstion(filename); |         std::tie(basename, ext) = details::file_helper::split_by_extenstion(filename); | ||||||
|         std::conditional<std::is_same<filename_t::value_type, char>::value, fmt::MemoryWriter, fmt::WMemoryWriter>::type w; |         std::conditional<std::is_same<filename_t::value_type, char>::value, fmt::memory_buffer, fmt::wmemory_buffer>::type w; | ||||||
|         w.write(SPDLOG_FILENAME_T("{}_{:04d}-{:02d}-{:02d}{}"), basename, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, ext); |         fmt::format_to(w, SPDLOG_FILENAME_T("{}_{:04d}-{:02d}-{:02d}{}"), basename, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, ext); | ||||||
|         return w.str(); |         return fmt::to_string(w); | ||||||
|     } |     } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -40,18 +40,18 @@ public: | |||||||
|     // e.g. calc_filename("logs/mylog.txt, 3) => "logs/mylog.3.txt".
 |     // e.g. calc_filename("logs/mylog.txt, 3) => "logs/mylog.3.txt".
 | ||||||
|     static filename_t calc_filename(const filename_t &filename, std::size_t index) |     static filename_t calc_filename(const filename_t &filename, std::size_t index) | ||||||
|     { |     { | ||||||
|         typename std::conditional<std::is_same<filename_t::value_type, char>::value, fmt::MemoryWriter, fmt::WMemoryWriter>::type w; |         typename std::conditional<std::is_same<filename_t::value_type, char>::value, fmt::memory_buffer, fmt::wmemory_buffer>::type w; | ||||||
|         if (index != 0u) |         if (index != 0u) | ||||||
|         { |         { | ||||||
|             filename_t basename, ext; |             filename_t basename, ext; | ||||||
|             std::tie(basename, ext) = details::file_helper::split_by_extenstion(filename); |             std::tie(basename, ext) = details::file_helper::split_by_extenstion(filename); | ||||||
|             w.write(SPDLOG_FILENAME_T("{}.{}{}"), basename, index, ext); |             fmt::format_to(w, SPDLOG_FILENAME_T("{}.{}{}"), basename, index, ext); | ||||||
|         } |         } | ||||||
|         else |         else | ||||||
|         { |         { | ||||||
|             w.write(SPDLOG_FILENAME_T("{}"), filename); |             fmt::format_to(w, SPDLOG_FILENAME_T("{}"), filename); | ||||||
|         } |         } | ||||||
|         return w.str(); |         return fmt::to_string(w); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| protected: | protected: | ||||||
|  | |||||||
| @ -50,7 +50,7 @@ public: | |||||||
| 
 | 
 | ||||||
|     void log(const details::log_msg &msg) override |     void log(const details::log_msg &msg) override | ||||||
|     { |     { | ||||||
|         ::syslog(syslog_prio_from_level(msg), "%s", msg.raw.str().c_str()); |         ::syslog(syslog_prio_from_level(msg), "%s", fmt::to_string(msg.raw).c_str()); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     void flush() override {} |     void flush() override {} | ||||||
|  | |||||||
| @ -1,11 +1,5 @@ | |||||||
| CXX	?= g++ | CXX	?= g++ | ||||||
| ifeq ($(STYLE),printf) | CXXFLAGS	=  -Wall  -pedantic -std=c++11 -pthread -O3 -I../include | ||||||
|     $(info *** PRINTF STYLE ***) |  | ||||||
|     CXXFLAGS	=  -DSPDLOG_FMT_PRINTF -Wall  -pedantic -std=c++11 -pthread -O3 -I../include |  | ||||||
| else |  | ||||||
|     $(info *** FORMAT STYLE ***) |  | ||||||
|     CXXFLAGS	=  -Wall  -pedantic -std=c++11 -pthread -O3 -I../include |  | ||||||
| endif |  | ||||||
| LDPFALGS = -pthread | LDPFALGS = -pthread | ||||||
| 
 | 
 | ||||||
| CPP_FILES := $(wildcard *.cpp) | CPP_FILES := $(wildcard *.cpp) | ||||||
|  | |||||||
| @ -26,13 +26,8 @@ TEST_CASE("default_error_handler", "[errors]]") | |||||||
| 
 | 
 | ||||||
|     auto logger = spdlog::create<spdlog::sinks::simple_file_sink_mt>("test-error", filename, true); |     auto logger = spdlog::create<spdlog::sinks::simple_file_sink_mt>("test-error", filename, true); | ||||||
|     logger->set_pattern("%v"); |     logger->set_pattern("%v"); | ||||||
| #if !defined(SPDLOG_FMT_PRINTF) |  | ||||||
|     logger->info("Test message {} {}", 1); |     logger->info("Test message {} {}", 1); | ||||||
|     logger->info("Test message {}", 2); |     logger->info("Test message {}", 2); | ||||||
| #else |  | ||||||
|     logger->info("Test message %d %d", 1); |  | ||||||
|     logger->info("Test message %d", 2); |  | ||||||
| #endif |  | ||||||
|     logger->flush(); |     logger->flush(); | ||||||
| 
 | 
 | ||||||
|     REQUIRE(file_contents(filename) == std::string("Test message 2\n")); |     REQUIRE(file_contents(filename) == std::string("Test message 2\n")); | ||||||
| @ -50,11 +45,8 @@ TEST_CASE("custom_error_handler", "[errors]]") | |||||||
|     logger->flush_on(spdlog::level::info); |     logger->flush_on(spdlog::level::info); | ||||||
|     logger->set_error_handler([=](const std::string &) { throw custom_ex(); }); |     logger->set_error_handler([=](const std::string &) { throw custom_ex(); }); | ||||||
|     logger->info("Good message #1"); |     logger->info("Good message #1"); | ||||||
| #if !defined(SPDLOG_FMT_PRINTF) | 
 | ||||||
|     REQUIRE_THROWS_AS(logger->info("Bad format msg {} {}", "xxx"), custom_ex); |     REQUIRE_THROWS_AS(logger->info("Bad format msg {} {}", "xxx"), custom_ex); | ||||||
| #else |  | ||||||
|     REQUIRE_THROWS_AS(logger->info("Bad format msg %s %s", "xxx"), custom_ex); |  | ||||||
| #endif |  | ||||||
|     logger->info("Good message #2"); |     logger->info("Good message #2"); | ||||||
|     REQUIRE(count_lines(filename) == 2); |     REQUIRE(count_lines(filename) == 2); | ||||||
| } | } | ||||||
| @ -91,11 +83,7 @@ TEST_CASE("async_error_handler", "[errors]]") | |||||||
|             ofs << err_msg; |             ofs << err_msg; | ||||||
|         }); |         }); | ||||||
|         logger->info("Good message #1"); |         logger->info("Good message #1"); | ||||||
| #if !defined(SPDLOG_FMT_PRINTF) |  | ||||||
|         logger->info("Bad format msg {} {}", "xxx"); |         logger->info("Bad format msg {} {}", "xxx"); | ||||||
| #else |  | ||||||
|         logger->info("Bad format msg %s %s", "xxx"); |  | ||||||
| #endif |  | ||||||
|         logger->info("Good message #2"); |         logger->info("Good message #2"); | ||||||
|         spdlog::drop("logger"); // force logger to drain the queue and shutdown
 |         spdlog::drop("logger"); // force logger to drain the queue and shutdown
 | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -11,13 +11,9 @@ TEST_CASE("simple_file_logger", "[simple_logger]]") | |||||||
|     auto logger = spdlog::create<spdlog::sinks::simple_file_sink_mt>("logger", filename); |     auto logger = spdlog::create<spdlog::sinks::simple_file_sink_mt>("logger", filename); | ||||||
|     logger->set_pattern("%v"); |     logger->set_pattern("%v"); | ||||||
| 
 | 
 | ||||||
| #if !defined(SPDLOG_FMT_PRINTF) |  | ||||||
|     logger->info("Test message {}", 1); |     logger->info("Test message {}", 1); | ||||||
|     logger->info("Test message {}", 2); |     logger->info("Test message {}", 2); | ||||||
| #else | 
 | ||||||
|     logger->info("Test message %d", 1); |  | ||||||
|     logger->info("Test message %d", 2); |  | ||||||
| #endif |  | ||||||
|     logger->flush(); |     logger->flush(); | ||||||
|     REQUIRE(file_contents(filename) == std::string("Test message 1\nTest message 2\n")); |     REQUIRE(file_contents(filename) == std::string("Test message 1\nTest message 2\n")); | ||||||
|     REQUIRE(count_lines(filename) == 2); |     REQUIRE(count_lines(filename) == 2); | ||||||
| @ -35,13 +31,8 @@ TEST_CASE("flush_on", "[flush_on]]") | |||||||
|     logger->trace("Should not be flushed"); |     logger->trace("Should not be flushed"); | ||||||
|     REQUIRE(count_lines(filename) == 0); |     REQUIRE(count_lines(filename) == 0); | ||||||
| 
 | 
 | ||||||
| #if !defined(SPDLOG_FMT_PRINTF) |  | ||||||
|     logger->info("Test message {}", 1); |     logger->info("Test message {}", 1); | ||||||
|     logger->info("Test message {}", 2); |     logger->info("Test message {}", 2); | ||||||
| #else |  | ||||||
|     logger->info("Test message %d", 1); |  | ||||||
|     logger->info("Test message %d", 2); |  | ||||||
| #endif |  | ||||||
|     logger->flush(); |     logger->flush(); | ||||||
|     REQUIRE(file_contents(filename) == std::string("Should not be flushed\nTest message 1\nTest message 2\n")); |     REQUIRE(file_contents(filename) == std::string("Should not be flushed\nTest message 1\nTest message 2\n")); | ||||||
|     REQUIRE(count_lines(filename) == 3); |     REQUIRE(count_lines(filename) == 3); | ||||||
| @ -56,11 +47,7 @@ TEST_CASE("rotating_file_logger1", "[rotating_logger]]") | |||||||
| 
 | 
 | ||||||
|     for (int i = 0; i < 10; ++i) |     for (int i = 0; i < 10; ++i) | ||||||
|     { |     { | ||||||
| #if !defined(SPDLOG_FMT_PRINTF) |  | ||||||
|         logger->info("Test message {}", i); |         logger->info("Test message {}", i); | ||||||
| #else |  | ||||||
|         logger->info("Test message %d", i); |  | ||||||
| #endif |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     logger->flush(); |     logger->flush(); | ||||||
| @ -82,11 +69,8 @@ TEST_CASE("rotating_file_logger2", "[rotating_logger]]") | |||||||
|     REQUIRE(count_lines(filename) == 10); |     REQUIRE(count_lines(filename) == 10); | ||||||
|     for (int i = 0; i < 1000; i++) |     for (int i = 0; i < 1000; i++) | ||||||
|     { |     { | ||||||
| #if !defined(SPDLOG_FMT_PRINTF) | 
 | ||||||
|         logger->info("Test message {}", i); |         logger->info("Test message {}", i); | ||||||
| #else |  | ||||||
|         logger->info("Test message %d", i); |  | ||||||
| #endif |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     logger->flush(); |     logger->flush(); | ||||||
| @ -108,11 +92,7 @@ TEST_CASE("daily_logger", "[daily_logger]]") | |||||||
|     logger->flush_on(spdlog::level::info); |     logger->flush_on(spdlog::level::info); | ||||||
|     for (int i = 0; i < 10; ++i) |     for (int i = 0; i < 10; ++i) | ||||||
|     { |     { | ||||||
| #if !defined(SPDLOG_FMT_PRINTF) |  | ||||||
|         logger->info("Test message {}", i); |         logger->info("Test message {}", i); | ||||||
| #else |  | ||||||
|         logger->info("Test message %d", i); |  | ||||||
| #endif |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     auto filename = w.str(); |     auto filename = w.str(); | ||||||
| @ -133,11 +113,8 @@ TEST_CASE("daily_logger with dateonly calculator", "[daily_logger_dateonly]]") | |||||||
|     auto logger = spdlog::create<sink_type>("logger", basename, 0, 0); |     auto logger = spdlog::create<sink_type>("logger", basename, 0, 0); | ||||||
|     for (int i = 0; i < 10; ++i) |     for (int i = 0; i < 10; ++i) | ||||||
|     { |     { | ||||||
| #if !defined(SPDLOG_FMT_PRINTF) | 
 | ||||||
|         logger->info("Test message {}", i); |         logger->info("Test message {}", i); | ||||||
| #else |  | ||||||
|         logger->info("Test message %d", i); |  | ||||||
| #endif |  | ||||||
|     } |     } | ||||||
|     logger->flush(); |     logger->flush(); | ||||||
|     auto filename = w.str(); |     auto filename = w.str(); | ||||||
| @ -169,11 +146,7 @@ TEST_CASE("daily_logger with custom calculator", "[daily_logger_custom]]") | |||||||
|     auto logger = spdlog::create<sink_type>("logger", basename, 0, 0); |     auto logger = spdlog::create<sink_type>("logger", basename, 0, 0); | ||||||
|     for (int i = 0; i < 10; ++i) |     for (int i = 0; i < 10; ++i) | ||||||
|     { |     { | ||||||
| #if !defined(SPDLOG_FMT_PRINTF) |  | ||||||
|         logger->info("Test message {}", i); |         logger->info("Test message {}", i); | ||||||
| #else |  | ||||||
|         logger->info("Test message %d", i); |  | ||||||
| #endif |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     logger->flush(); |     logger->flush(); | ||||||
|  | |||||||
| @ -31,16 +31,9 @@ TEST_CASE("debug and trace with format strings", "[macros]]") | |||||||
|     logger->set_pattern("%v"); |     logger->set_pattern("%v"); | ||||||
|     logger->set_level(spdlog::level::trace); |     logger->set_level(spdlog::level::trace); | ||||||
| 
 | 
 | ||||||
| #if !defined(SPDLOG_FMT_PRINTF) |  | ||||||
|     SPDLOG_TRACE(logger, "Test message {}", 1); |     SPDLOG_TRACE(logger, "Test message {}", 1); | ||||||
|     // SPDLOG_DEBUG(logger, "Test message 2");
 |     // SPDLOG_DEBUG(logger, "Test message 2");
 | ||||||
|     SPDLOG_DEBUG(logger, "Test message {}", 222); |     SPDLOG_DEBUG(logger, "Test message {}", 222); | ||||||
| #else |  | ||||||
|     SPDLOG_TRACE(logger, "Test message %d", 1); |  | ||||||
|     // SPDLOG_DEBUG(logger, "Test message 2");
 |  | ||||||
|     SPDLOG_DEBUG(logger, "Test message %d", 222); |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
|     logger->flush(); |     logger->flush(); | ||||||
| 
 | 
 | ||||||
|     REQUIRE(ends_with(file_contents(filename), "Test message 222\n")); |     REQUIRE(ends_with(file_contents(filename), "Test message 222\n")); | ||||||
|  | |||||||
| @ -47,8 +47,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "bundled", "bundled", "{F0D4 | |||||||
| 		..\include\spdlog\fmt\bundled\ostream.h = ..\include\spdlog\fmt\bundled\ostream.h | 		..\include\spdlog\fmt\bundled\ostream.h = ..\include\spdlog\fmt\bundled\ostream.h | ||||||
| 		..\include\spdlog\fmt\bundled\posix.cc = ..\include\spdlog\fmt\bundled\posix.cc | 		..\include\spdlog\fmt\bundled\posix.cc = ..\include\spdlog\fmt\bundled\posix.cc | ||||||
| 		..\include\spdlog\fmt\bundled\posix.h = ..\include\spdlog\fmt\bundled\posix.h | 		..\include\spdlog\fmt\bundled\posix.h = ..\include\spdlog\fmt\bundled\posix.h | ||||||
| 		..\include\spdlog\fmt\bundled\printf.cc = ..\include\spdlog\fmt\bundled\printf.cc |  | ||||||
| 		..\include\spdlog\fmt\bundled\printf.h = ..\include\spdlog\fmt\bundled\printf.h |  | ||||||
| 		..\include\spdlog\fmt\bundled\time.h = ..\include\spdlog\fmt\bundled\time.h | 		..\include\spdlog\fmt\bundled\time.h = ..\include\spdlog\fmt\bundled\time.h | ||||||
| 	EndProjectSection | 	EndProjectSection | ||||||
| EndProject | EndProject | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user