Upgraded to fmt ver 5.2.0

pull/836/merge
gabime 7 years ago
parent f4ac67ae1c
commit 3771d12992

@ -0,0 +1,278 @@
// Formatting library for C++ - color support
//
// Copyright (c) 2018 - present, Victor Zverovich and fmt contributors
// All rights reserved.
//
// For the license information refer to format.h.
#ifndef FMT_COLOR_H_
#define FMT_COLOR_H_
#include "format.h"
FMT_BEGIN_NAMESPACE
#ifdef FMT_DEPRECATED_COLORS
// color and (v)print_colored are deprecated.
enum color { black, red, green, yellow, blue, magenta, cyan, white };
FMT_API void vprint_colored(color c, string_view format, format_args args);
FMT_API void vprint_colored(color c, wstring_view format, wformat_args args);
template <typename... Args>
inline void print_colored(color c, string_view format_str,
const Args & ... args) {
vprint_colored(c, format_str, make_format_args(args...));
}
template <typename... Args>
inline void print_colored(color c, wstring_view format_str,
const Args & ... args) {
vprint_colored(c, format_str, make_format_args<wformat_context>(args...));
}
inline void vprint_colored(color c, string_view format, format_args args) {
char escape[] = "\x1b[30m";
escape[3] = static_cast<char>('0' + c);
std::fputs(escape, stdout);
vprint(format, args);
std::fputs(internal::data::RESET_COLOR, stdout);
}
inline void vprint_colored(color c, wstring_view format, wformat_args args) {
wchar_t escape[] = L"\x1b[30m";
escape[3] = static_cast<wchar_t>('0' + c);
std::fputws(escape, stdout);
vprint(format, args);
std::fputws(internal::data::WRESET_COLOR, stdout);
}
#else
// Experimental color support.
enum class color : uint32_t {
alice_blue = 0xF0F8FF, // rgb(240,248,255)
antique_white = 0xFAEBD7, // rgb(250,235,215)
aqua = 0x00FFFF, // rgb(0,255,255)
aquamarine = 0x7FFFD4, // rgb(127,255,212)
azure = 0xF0FFFF, // rgb(240,255,255)
beige = 0xF5F5DC, // rgb(245,245,220)
bisque = 0xFFE4C4, // rgb(255,228,196)
black = 0x000000, // rgb(0,0,0)
blanched_almond = 0xFFEBCD, // rgb(255,235,205)
blue = 0x0000FF, // rgb(0,0,255)
blue_violet = 0x8A2BE2, // rgb(138,43,226)
brown = 0xA52A2A, // rgb(165,42,42)
burly_wood = 0xDEB887, // rgb(222,184,135)
cadet_blue = 0x5F9EA0, // rgb(95,158,160)
chartreuse = 0x7FFF00, // rgb(127,255,0)
chocolate = 0xD2691E, // rgb(210,105,30)
coral = 0xFF7F50, // rgb(255,127,80)
cornflower_blue = 0x6495ED, // rgb(100,149,237)
cornsilk = 0xFFF8DC, // rgb(255,248,220)
crimson = 0xDC143C, // rgb(220,20,60)
cyan = 0x00FFFF, // rgb(0,255,255)
dark_blue = 0x00008B, // rgb(0,0,139)
dark_cyan = 0x008B8B, // rgb(0,139,139)
dark_golden_rod = 0xB8860B, // rgb(184,134,11)
dark_gray = 0xA9A9A9, // rgb(169,169,169)
dark_green = 0x006400, // rgb(0,100,0)
dark_khaki = 0xBDB76B, // rgb(189,183,107)
dark_magenta = 0x8B008B, // rgb(139,0,139)
dark_olive_green = 0x556B2F, // rgb(85,107,47)
dark_orange = 0xFF8C00, // rgb(255,140,0)
dark_orchid = 0x9932CC, // rgb(153,50,204)
dark_red = 0x8B0000, // rgb(139,0,0)
dark_salmon = 0xE9967A, // rgb(233,150,122)
dark_sea_green = 0x8FBC8F, // rgb(143,188,143)
dark_slate_blue = 0x483D8B, // rgb(72,61,139)
dark_slate_gray = 0x2F4F4F, // rgb(47,79,79)
dark_turquoise = 0x00CED1, // rgb(0,206,209)
dark_violet = 0x9400D3, // rgb(148,0,211)
deep_pink = 0xFF1493, // rgb(255,20,147)
deep_sky_blue = 0x00BFFF, // rgb(0,191,255)
dim_gray = 0x696969, // rgb(105,105,105)
dodger_blue = 0x1E90FF, // rgb(30,144,255)
fire_brick = 0xB22222, // rgb(178,34,34)
floral_white = 0xFFFAF0, // rgb(255,250,240)
forest_green = 0x228B22, // rgb(34,139,34)
fuchsia = 0xFF00FF, // rgb(255,0,255)
gainsboro = 0xDCDCDC, // rgb(220,220,220)
ghost_white = 0xF8F8FF, // rgb(248,248,255)
gold = 0xFFD700, // rgb(255,215,0)
golden_rod = 0xDAA520, // rgb(218,165,32)
gray = 0x808080, // rgb(128,128,128)
green = 0x008000, // rgb(0,128,0)
green_yellow = 0xADFF2F, // rgb(173,255,47)
honey_dew = 0xF0FFF0, // rgb(240,255,240)
hot_pink = 0xFF69B4, // rgb(255,105,180)
indian_red = 0xCD5C5C, // rgb(205,92,92)
indigo = 0x4B0082, // rgb(75,0,130)
ivory = 0xFFFFF0, // rgb(255,255,240)
khaki = 0xF0E68C, // rgb(240,230,140)
lavender = 0xE6E6FA, // rgb(230,230,250)
lavender_blush = 0xFFF0F5, // rgb(255,240,245)
lawn_green = 0x7CFC00, // rgb(124,252,0)
lemon_chiffon = 0xFFFACD, // rgb(255,250,205)
light_blue = 0xADD8E6, // rgb(173,216,230)
light_coral = 0xF08080, // rgb(240,128,128)
light_cyan = 0xE0FFFF, // rgb(224,255,255)
light_golden_rod_yellow = 0xFAFAD2, // rgb(250,250,210)
light_gray = 0xD3D3D3, // rgb(211,211,211)
light_green = 0x90EE90, // rgb(144,238,144)
light_pink = 0xFFB6C1, // rgb(255,182,193)
light_salmon = 0xFFA07A, // rgb(255,160,122)
light_sea_green = 0x20B2AA, // rgb(32,178,170)
light_sky_blue = 0x87CEFA, // rgb(135,206,250)
light_slate_gray = 0x778899, // rgb(119,136,153)
light_steel_blue = 0xB0C4DE, // rgb(176,196,222)
light_yellow = 0xFFFFE0, // rgb(255,255,224)
lime = 0x00FF00, // rgb(0,255,0)
lime_green = 0x32CD32, // rgb(50,205,50)
linen = 0xFAF0E6, // rgb(250,240,230)
magenta = 0xFF00FF, // rgb(255,0,255)
maroon = 0x800000, // rgb(128,0,0)
medium_aquamarine = 0x66CDAA, // rgb(102,205,170)
medium_blue = 0x0000CD, // rgb(0,0,205)
medium_orchid = 0xBA55D3, // rgb(186,85,211)
medium_purple = 0x9370DB, // rgb(147,112,219)
medium_sea_green = 0x3CB371, // rgb(60,179,113)
medium_slate_blue = 0x7B68EE, // rgb(123,104,238)
medium_spring_green = 0x00FA9A, // rgb(0,250,154)
medium_turquoise = 0x48D1CC, // rgb(72,209,204)
medium_violet_red = 0xC71585, // rgb(199,21,133)
midnight_blue = 0x191970, // rgb(25,25,112)
mint_cream = 0xF5FFFA, // rgb(245,255,250)
misty_rose = 0xFFE4E1, // rgb(255,228,225)
moccasin = 0xFFE4B5, // rgb(255,228,181)
navajo_white = 0xFFDEAD, // rgb(255,222,173)
navy = 0x000080, // rgb(0,0,128)
old_lace = 0xFDF5E6, // rgb(253,245,230)
olive = 0x808000, // rgb(128,128,0)
olive_drab = 0x6B8E23, // rgb(107,142,35)
orange = 0xFFA500, // rgb(255,165,0)
orange_red = 0xFF4500, // rgb(255,69,0)
orchid = 0xDA70D6, // rgb(218,112,214)
pale_golden_rod = 0xEEE8AA, // rgb(238,232,170)
pale_green = 0x98FB98, // rgb(152,251,152)
pale_turquoise = 0xAFEEEE, // rgb(175,238,238)
pale_violet_red = 0xDB7093, // rgb(219,112,147)
papaya_whip = 0xFFEFD5, // rgb(255,239,213)
peach_puff = 0xFFDAB9, // rgb(255,218,185)
peru = 0xCD853F, // rgb(205,133,63)
pink = 0xFFC0CB, // rgb(255,192,203)
plum = 0xDDA0DD, // rgb(221,160,221)
powder_blue = 0xB0E0E6, // rgb(176,224,230)
purple = 0x800080, // rgb(128,0,128)
rebecca_purple = 0x663399, // rgb(102,51,153)
red = 0xFF0000, // rgb(255,0,0)
rosy_brown = 0xBC8F8F, // rgb(188,143,143)
royal_blue = 0x4169E1, // rgb(65,105,225)
saddle_brown = 0x8B4513, // rgb(139,69,19)
salmon = 0xFA8072, // rgb(250,128,114)
sandy_brown = 0xF4A460, // rgb(244,164,96)
sea_green = 0x2E8B57, // rgb(46,139,87)
sea_shell = 0xFFF5EE, // rgb(255,245,238)
sienna = 0xA0522D, // rgb(160,82,45)
silver = 0xC0C0C0, // rgb(192,192,192)
sky_blue = 0x87CEEB, // rgb(135,206,235)
slate_blue = 0x6A5ACD, // rgb(106,90,205)
slate_gray = 0x708090, // rgb(112,128,144)
snow = 0xFFFAFA, // rgb(255,250,250)
spring_green = 0x00FF7F, // rgb(0,255,127)
steel_blue = 0x4682B4, // rgb(70,130,180)
tan = 0xD2B48C, // rgb(210,180,140)
teal = 0x008080, // rgb(0,128,128)
thistle = 0xD8BFD8, // rgb(216,191,216)
tomato = 0xFF6347, // rgb(255,99,71)
turquoise = 0x40E0D0, // rgb(64,224,208)
violet = 0xEE82EE, // rgb(238,130,238)
wheat = 0xF5DEB3, // rgb(245,222,179)
white = 0xFFFFFF, // rgb(255,255,255)
white_smoke = 0xF5F5F5, // rgb(245,245,245)
yellow = 0xFFFF00, // rgb(255,255,0)
yellow_green = 0x9ACD32, // rgb(154,205,50)
}; // enum class color
// rgb is a struct for red, green and blue colors.
// We use rgb as name because some editors will show it as color direct in the
// editor.
struct rgb {
FMT_CONSTEXPR_DECL rgb() : r(0), g(0), b(0) {}
FMT_CONSTEXPR_DECL rgb(uint8_t r_, uint8_t g_, uint8_t b_)
: r(r_), g(g_), b(b_) {}
FMT_CONSTEXPR_DECL rgb(uint32_t hex)
: r((hex >> 16) & 0xFF), g((hex >> 8) & 0xFF), b((hex) & 0xFF) {}
FMT_CONSTEXPR_DECL rgb(color hex)
: r((uint32_t(hex) >> 16) & 0xFF), g((uint32_t(hex) >> 8) & 0xFF),
b(uint32_t(hex) & 0xFF) {}
uint8_t r;
uint8_t g;
uint8_t b;
};
void vprint_rgb(rgb fd, string_view format, format_args args);
void vprint_rgb(rgb fd, rgb bg, string_view format, format_args args);
/**
Formats a string and prints it to stdout using ANSI escape sequences to
specify foreground color 'fd'.
Example:
fmt::print(fmt::color::red, "Elapsed time: {0:.2f} seconds", 1.23);
*/
template <typename... Args>
inline void print(rgb fd, string_view format_str, const Args & ... args) {
vprint_rgb(fd, format_str, make_format_args(args...));
}
/**
Formats a string and prints it to stdout using ANSI escape sequences to
specify foreground color 'fd' and background color 'bg'.
Example:
fmt::print(fmt::color::red, fmt::color::black,
"Elapsed time: {0:.2f} seconds", 1.23);
*/
template <typename... Args>
inline void print(rgb fd, rgb bg, string_view format_str,
const Args & ... args) {
vprint_rgb(fd, bg, format_str, make_format_args(args...));
}
namespace internal {
FMT_CONSTEXPR void to_esc(uint8_t c, char out[], int offset) {
out[offset + 0] = static_cast<char>('0' + c / 100);
out[offset + 1] = static_cast<char>('0' + c / 10 % 10);
out[offset + 2] = static_cast<char>('0' + c % 10);
}
} // namespace internal
inline void vprint_rgb(rgb fd, string_view format, format_args args) {
char escape_fd[] = "\x1b[38;2;000;000;000m";
internal::to_esc(fd.r, escape_fd, 7);
internal::to_esc(fd.g, escape_fd, 11);
internal::to_esc(fd.b, escape_fd, 15);
std::fputs(escape_fd, stdout);
vprint(format, args);
std::fputs(internal::data::RESET_COLOR, stdout);
}
inline void vprint_rgb(rgb fd, rgb bg, string_view format, format_args args) {
char escape_fd[] = "\x1b[38;2;000;000;000m"; // foreground color
char escape_bg[] = "\x1b[48;2;000;000;000m"; // background color
internal::to_esc(fd.r, escape_fd, 7);
internal::to_esc(fd.g, escape_fd, 11);
internal::to_esc(fd.b, escape_fd, 15);
internal::to_esc(bg.r, escape_bg, 7);
internal::to_esc(bg.g, escape_bg, 11);
internal::to_esc(bg.b, escape_bg, 15);
std::fputs(escape_fd, stdout);
std::fputs(escape_bg, stdout);
vprint(format, args);
std::fputs(internal::data::RESET_COLOR, stdout);
}
#endif
FMT_END_NAMESPACE
#endif // FMT_COLOR_H_

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -14,139 +14,123 @@
FMT_BEGIN_NAMESPACE FMT_BEGIN_NAMESPACE
namespace internal { namespace internal {
template<class Char> template <class Char>
class formatbuf : public std::basic_streambuf<Char> class formatbuf : public std::basic_streambuf<Char> {
{ private:
private: typedef typename std::basic_streambuf<Char>::int_type int_type;
typedef typename std::basic_streambuf<Char>::int_type int_type; typedef typename std::basic_streambuf<Char>::traits_type traits_type;
typedef typename std::basic_streambuf<Char>::traits_type traits_type;
basic_buffer<Char> &buffer_;
basic_buffer<Char> &buffer_;
public:
public: formatbuf(basic_buffer<Char> &buffer) : buffer_(buffer) {}
formatbuf(basic_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
protected: // disadvantage is that each call to sputc always results in a (virtual) call
// The put-area is actually always empty. This makes the implementation // to overflow. There is no disadvantage here for sputn since this always
// simpler and has the advantage that the streambuf and the buffer are always // results in a call to xsputn.
// in sync and sputc never writes into uninitialized memory. The obvious
// disadvantage is that each call to sputc always results in a (virtual) call int_type overflow(int_type ch = traits_type::eof()) FMT_OVERRIDE {
// to overflow. There is no disadvantage here for sputn since this always if (!traits_type::eq_int_type(ch, traits_type::eof()))
// results in a call to xsputn. buffer_.push_back(static_cast<Char>(ch));
return ch;
int_type overflow(int_type ch = traits_type::eof()) FMT_OVERRIDE }
{
if (!traits_type::eq_int_type(ch, traits_type::eof())) std::streamsize xsputn(const Char *s, std::streamsize count) FMT_OVERRIDE {
buffer_.push_back(static_cast<Char>(ch)); buffer_.append(s, s + count);
return ch; return count;
} }
std::streamsize xsputn(const Char *s, std::streamsize count) FMT_OVERRIDE
{
buffer_.append(s, s + count);
return count;
}
}; };
template<typename Char> template <typename Char>
struct test_stream : std::basic_ostream<Char> struct test_stream : std::basic_ostream<Char> {
{ private:
private: struct null;
struct null; // Hide all operator<< from std::basic_ostream<Char>.
// Hide all operator<< from std::basic_ostream<Char>. void operator<<(null);
void operator<<(null);
}; };
// Checks if T has a user-defined operator<< (e.g. not a member of // Checks if T has a user-defined operator<< (e.g. not a member of std::ostream).
// std::ostream). template <typename T, typename Char>
template<typename T, typename Char> class is_streamable {
class is_streamable private:
{ template <typename U>
private: static decltype(
template<typename U> internal::declval<test_stream<Char>&>()
static decltype(internal::declval<test_stream<Char> &>() << internal::declval<U>(), std::true_type()) test(int); << internal::declval<U>(), std::true_type()) test(int);
template<typename>
static std::false_type test(...);
typedef decltype(test<T>(0)) result;
public:
// std::string operator<< is not considered user-defined because we handle
// strings
// specially.
static const bool value = result::value && !std::is_same<T, std::string>::value;
};
// Disable conversion to int if T has an overloaded operator<< which is a free template <typename>
// function (not a member of std::ostream). static std::false_type test(...);
template<typename T, typename Char>
class convert_to_int<T, Char, true> typedef decltype(test<T>(0)) result;
{
public: public:
static const bool value = convert_to_int<T, Char, false>::value && !is_streamable<T, Char>::value; static const bool value = result::value;
}; };
// Write the content of buf to os. // Write the content of buf to os.
template<typename Char> template <typename Char>
void write(std::basic_ostream<Char> &os, basic_buffer<Char> &buf) void write(std::basic_ostream<Char> &os, basic_buffer<Char> &buf) {
{ const Char *data = buf.data();
const Char *data = buf.data(); typedef std::make_unsigned<std::streamsize>::type UnsignedStreamSize;
typedef std::make_unsigned<std::streamsize>::type UnsignedStreamSize; UnsignedStreamSize size = buf.size();
UnsignedStreamSize size = buf.size(); UnsignedStreamSize max_size =
UnsignedStreamSize max_size = internal::to_unsigned((std::numeric_limits<std::streamsize>::max)()); internal::to_unsigned((std::numeric_limits<std::streamsize>::max)());
do do {
{ UnsignedStreamSize n = size <= max_size ? size : max_size;
UnsignedStreamSize n = size <= max_size ? size : max_size; os.write(data, static_cast<std::streamsize>(n));
os.write(data, static_cast<std::streamsize>(n)); data += n;
data += n; size -= n;
size -= n; } while (size != 0);
} while (size != 0);
} }
template<typename Char, typename T> template <typename Char, typename T>
void format_value(basic_buffer<Char> &buffer, const T &value) void format_value(basic_buffer<Char> &buffer, const T &value) {
{ internal::formatbuf<Char> format_buf(buffer);
internal::formatbuf<Char> format_buf(buffer); std::basic_ostream<Char> output(&format_buf);
std::basic_ostream<Char> output(&format_buf); output.exceptions(std::ios_base::failbit | std::ios_base::badbit);
output.exceptions(std::ios_base::failbit | std::ios_base::badbit); output << value;
output << value; buffer.resize(buffer.size());
buffer.resize(buffer.size());
} }
} // namespace internal
// Disable builtin formatting of enums and use operator<< instead. // Disable conversion to int if T has an overloaded operator<< which is a free
template<typename T> // function (not a member of std::ostream).
struct format_enum<T, typename std::enable_if<std::is_enum<T>::value>::type> : std::false_type template <typename T, typename Char>
{ struct convert_to_int<T, Char, void> {
static const bool value =
convert_to_int<T, Char, int>::value &&
!internal::is_streamable<T, Char>::value;
}; };
} // namespace internal
// Formats an object of type T that has an overloaded ostream operator<<. // Formats an object of type T that has an overloaded ostream operator<<.
template<typename T, typename Char> template <typename T, typename Char>
struct formatter<T, Char, typename std::enable_if<internal::is_streamable<T, Char>::value>::type> : formatter<basic_string_view<Char>, Char> struct formatter<T, Char,
{ typename std::enable_if<
internal::is_streamable<T, Char>::value &&
template<typename Context> !internal::format_type<
auto format(const T &value, Context &ctx) -> decltype(ctx.out()) typename buffer_context<Char>::type, T>::value>::type>
{ : formatter<basic_string_view<Char>, Char> {
basic_memory_buffer<Char> buffer;
internal::format_value(buffer, value); template <typename Context>
basic_string_view<Char> str(buffer.data(), buffer.size()); auto format(const T &value, Context &ctx) -> decltype(ctx.out()) {
formatter<basic_string_view<Char>, Char>::format(str, ctx); basic_memory_buffer<Char> buffer;
return ctx.out(); internal::format_value(buffer, value);
} basic_string_view<Char> str(buffer.data(), buffer.size());
return formatter<basic_string_view<Char>, Char>::format(str, ctx);
}
}; };
template<typename Char> template <typename Char>
inline void vprint( inline void vprint(std::basic_ostream<Char> &os,
std::basic_ostream<Char> &os, basic_string_view<Char> format_str, basic_format_args<typename buffer_context<Char>::type> args) basic_string_view<Char> format_str,
{ basic_format_args<typename buffer_context<Char>::type> args) {
basic_memory_buffer<Char> buffer; basic_memory_buffer<Char> buffer;
vformat_to(buffer, format_str, args); vformat_to(buffer, format_str, args);
internal::write(os, buffer); internal::write(os, buffer);
} }
/** /**
\rst \rst
@ -157,17 +141,17 @@ inline void vprint(
fmt::print(cerr, "Don't {}!", "panic"); fmt::print(cerr, "Don't {}!", "panic");
\endrst \endrst
*/ */
template<typename... Args> template <typename... Args>
inline void print(std::ostream &os, string_view format_str, const Args &... args) inline void print(std::ostream &os, string_view format_str,
{ const Args & ... args) {
vprint<char>(os, format_str, make_format_args<format_context>(args...)); vprint<char>(os, format_str, make_format_args<format_context>(args...));
} }
template<typename... Args> template <typename... Args>
inline void print(std::wostream &os, wstring_view format_str, const Args &... args) inline void print(std::wostream &os, wstring_view format_str,
{ const Args & ... args) {
vprint<wchar_t>(os, format_str, make_format_args<wformat_context>(args...)); vprint<wchar_t>(os, format_str, make_format_args<wformat_context>(args...));
} }
FMT_END_NAMESPACE FMT_END_NAMESPACE
#endif // FMT_OSTREAM_H_ #endif // FMT_OSTREAM_H_

@ -10,55 +10,54 @@
#if defined(__MINGW32__) || defined(__CYGWIN__) #if defined(__MINGW32__) || defined(__CYGWIN__)
// Workaround MinGW bug https://sourceforge.net/p/mingw/bugs/2024/. // Workaround MinGW bug https://sourceforge.net/p/mingw/bugs/2024/.
#undef __STRICT_ANSI__ # undef __STRICT_ANSI__
#endif #endif
#include <errno.h> #include <errno.h>
#include <fcntl.h> // for O_RDONLY #include <fcntl.h> // for O_RDONLY
#include <locale.h> // for locale_t #include <locale.h> // for locale_t
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> // for strtod_l #include <stdlib.h> // for strtod_l
#include <cstddef> #include <cstddef>
#if defined __APPLE__ || defined(__FreeBSD__) #if defined __APPLE__ || defined(__FreeBSD__)
#include <xlocale.h> // for LC_NUMERIC_MASK on OS X # include <xlocale.h> // for LC_NUMERIC_MASK on OS X
#endif #endif
#include "format.h" #include "format.h"
#ifndef FMT_POSIX #ifndef FMT_POSIX
#if defined(_WIN32) && !defined(__MINGW32__) # if defined(_WIN32) && !defined(__MINGW32__)
// Fix warnings about deprecated symbols. // Fix warnings about deprecated symbols.
#define FMT_POSIX(call) _##call # define FMT_POSIX(call) _##call
#else # else
#define FMT_POSIX(call) call # define FMT_POSIX(call) call
#endif # endif
#endif #endif
// Calls to system functions are wrapped in FMT_SYSTEM for testability. // Calls to system functions are wrapped in FMT_SYSTEM for testability.
#ifdef FMT_SYSTEM #ifdef FMT_SYSTEM
#define FMT_POSIX_CALL(call) FMT_SYSTEM(call) # define FMT_POSIX_CALL(call) FMT_SYSTEM(call)
#else #else
#define FMT_SYSTEM(call) call # define FMT_SYSTEM(call) call
#ifdef _WIN32 # ifdef _WIN32
// Fix warnings about deprecated symbols. // Fix warnings about deprecated symbols.
#define FMT_POSIX_CALL(call) ::_##call # define FMT_POSIX_CALL(call) ::_##call
#else # else
#define FMT_POSIX_CALL(call) ::call # define FMT_POSIX_CALL(call) ::call
#endif # endif
#endif #endif
// Retries the expression while it evaluates to error_result and errno // Retries the expression while it evaluates to error_result and errno
// equals to EINTR. // equals to EINTR.
#ifndef _WIN32 #ifndef _WIN32
#define FMT_RETRY_VAL(result, expression, error_result) \ # define FMT_RETRY_VAL(result, expression, error_result) \
do \ do { \
{ \ result = (expression); \
result = (expression); \ } while (result == error_result && errno == EINTR)
} while (result == error_result && errno == EINTR)
#else #else
#define FMT_RETRY_VAL(result, expression, error_result) result = (expression) # define FMT_RETRY_VAL(result, expression, error_result) result = (expression)
#endif #endif
#define FMT_RETRY(result, expression) FMT_RETRY_VAL(result, expression, -1) #define FMT_RETRY(result, expression) FMT_RETRY_VAL(result, expression, -1)
@ -90,167 +89,94 @@ FMT_BEGIN_NAMESPACE
format(std::string("{}"), 42); format(std::string("{}"), 42);
\endrst \endrst
*/ */
template<typename Char> template <typename Char>
class basic_cstring_view class basic_cstring_view {
{ private:
private: const Char *data_;
const Char *data_;
public:
public: /** Constructs a string reference object from a C string. */
/** Constructs a string reference object from a C string. */ basic_cstring_view(const Char *s) : data_(s) {}
basic_cstring_view(const Char *s)
: data_(s) /**
{ \rst
} Constructs a string reference from an ``std::string`` object.
\endrst
/** */
\rst basic_cstring_view(const std::basic_string<Char> &s) : data_(s.c_str()) {}
Constructs a string reference from an ``std::string`` object.
\endrst /** Returns the pointer to a C string. */
*/ const Char *c_str() const { return data_; }
basic_cstring_view(const std::basic_string<Char> &s)
: data_(s.c_str())
{
}
/** Returns the pointer to a C string. */
const Char *c_str() const
{
return data_;
}
}; };
typedef basic_cstring_view<char> cstring_view; typedef basic_cstring_view<char> cstring_view;
typedef basic_cstring_view<wchar_t> wcstring_view; typedef basic_cstring_view<wchar_t> wcstring_view;
// An error code. // An error code.
class error_code class error_code {
{ private:
private: int value_;
int value_;
public:
public: explicit error_code(int value = 0) FMT_NOEXCEPT : value_(value) {}
explicit error_code(int value = 0) FMT_NOEXCEPT : value_(value) {}
int get() const FMT_NOEXCEPT { return value_; }
int get() const FMT_NOEXCEPT
{
return value_;
}
}; };
// A buffered file. // A buffered file.
class buffered_file class buffered_file {
{ private:
private: FILE *file_;
FILE *file_;
friend class file;
explicit buffered_file(FILE *f)
: file_(f)
{
}
public:
// Constructs a buffered_file object which doesn't represent any file.
buffered_file() FMT_NOEXCEPT : file_(FMT_NULL) {}
// Destroys the object closing the file it represents if any.
FMT_API ~buffered_file() FMT_DTOR_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.
buffered_file(Proxy p) FMT_NOEXCEPT : file_(p.file) {}
// A "move constructor" for moving from an lvalue.
buffered_file(buffered_file &f) FMT_NOEXCEPT : file_(f.file_)
{
f.file_ = FMT_NULL;
}
// A "move assignment operator" for moving from a temporary.
buffered_file &operator=(Proxy p)
{
close();
file_ = p.file;
return *this;
}
// A "move assignment operator" for moving from an lvalue.
buffered_file &operator=(buffered_file &other)
{
close();
file_ = other.file_;
other.file_ = FMT_NULL;
return *this;
}
// Returns a proxy object for moving from a temporary:
// buffered_file file = buffered_file(...);
operator Proxy() FMT_NOEXCEPT
{
Proxy p = {file_};
file_ = FMT_NULL;
return p;
}
#else friend class file;
private:
FMT_DISALLOW_COPY_AND_ASSIGN(buffered_file); explicit buffered_file(FILE *f) : file_(f) {}
public: public:
buffered_file(buffered_file &&other) FMT_NOEXCEPT : file_(other.file_) // Constructs a buffered_file object which doesn't represent any file.
{ buffered_file() FMT_NOEXCEPT : file_(FMT_NULL) {}
other.file_ = FMT_NULL;
} // Destroys the object closing the file it represents if any.
FMT_API ~buffered_file() FMT_DTOR_NOEXCEPT;
buffered_file &operator=(buffered_file &&other)
{ private:
close(); buffered_file(const buffered_file &) = delete;
file_ = other.file_; void operator=(const buffered_file &) = delete;
other.file_ = FMT_NULL;
return *this;
} public:
#endif buffered_file(buffered_file &&other) FMT_NOEXCEPT : file_(other.file_) {
other.file_ = FMT_NULL;
}
// Opens a file. buffered_file& operator=(buffered_file &&other) {
FMT_API buffered_file(cstring_view filename, cstring_view mode); close();
file_ = other.file_;
other.file_ = FMT_NULL;
return *this;
}
// Closes the file. // Opens a file.
FMT_API void close(); FMT_API buffered_file(cstring_view filename, cstring_view mode);
// Returns the pointer to a FILE object representing this file. // Closes the file.
FILE *get() const FMT_NOEXCEPT FMT_API void close();
{
return file_;
}
// We place parentheses around fileno to workaround a bug in some versions // Returns the pointer to a FILE object representing this file.
// of MinGW that define fileno as a macro. FILE *get() const FMT_NOEXCEPT { return file_; }
FMT_API int(fileno)() const;
void vprint(string_view format_str, format_args args) // We place parentheses around fileno to workaround a bug in some versions
{ // of MinGW that define fileno as a macro.
fmt::vprint(file_, format_str, args); FMT_API int (fileno)() const;
}
template<typename... Args> void vprint(string_view format_str, format_args args) {
inline void print(string_view format_str, const Args &... args) fmt::vprint(file_, format_str, args);
{ }
vprint(format_str, make_format_args(args...));
} template <typename... Args>
inline void print(string_view format_str, const Args & ... args) {
vprint(format_str, make_format_args(args...));
}
}; };
// A file. Closed file is represented by a file object with descriptor -1. // A file. Closed file is represented by a file object with descriptor -1.
@ -259,226 +185,140 @@ public:
// closing the file multiple times will cause a crash on Windows rather // closing the file multiple times will cause a crash on Windows rather
// than an exception. You can get standard behavior by overriding the // than an exception. You can get standard behavior by overriding the
// invalid parameter handler with _set_invalid_parameter_handler. // invalid parameter handler with _set_invalid_parameter_handler.
class file class file {
{ private:
private: int fd_; // File descriptor.
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(cstring_view 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 f = file(...);
operator Proxy() FMT_NOEXCEPT
{
Proxy p = {fd_};
fd_ = -1;
return p;
}
#else // Constructs a file object with a given descriptor.
private: explicit file(int fd) : fd_(fd) {}
FMT_DISALLOW_COPY_AND_ASSIGN(file);
public:
public: // Possible values for the oflag argument to the constructor.
file(file &&other) FMT_NOEXCEPT : fd_(other.fd_) enum {
{ RDONLY = FMT_POSIX(O_RDONLY), // Open for reading only.
other.fd_ = -1; WRONLY = FMT_POSIX(O_WRONLY), // Open for writing only.
} RDWR = FMT_POSIX(O_RDWR) // Open for reading and writing.
};
file &operator=(file &&other)
{ // Constructs a file object which doesn't represent any file.
close(); file() FMT_NOEXCEPT : fd_(-1) {}
fd_ = other.fd_;
other.fd_ = -1; // Opens a file and constructs a file object representing this file.
return *this; FMT_API file(cstring_view path, int oflag);
}
#endif private:
file(const file &) = delete;
void operator=(const file &) = delete;
// Destroys the object closing the file it represents if any. public:
FMT_API ~file() FMT_DTOR_NOEXCEPT; file(file &&other) FMT_NOEXCEPT : fd_(other.fd_) {
other.fd_ = -1;
}
// Returns the file descriptor. file& operator=(file &&other) {
int descriptor() const FMT_NOEXCEPT close();
{ fd_ = other.fd_;
return fd_; other.fd_ = -1;
} return *this;
}
// Closes the file. // Destroys the object closing the file it represents if any.
FMT_API void close(); FMT_API ~file() FMT_DTOR_NOEXCEPT;
// Returns the file size. The size has signed type for consistency with // Returns the file descriptor.
// stat::st_size. int descriptor() const FMT_NOEXCEPT { return fd_; }
FMT_API long long size() const;
// Attempts to read count bytes from the file into the specified buffer. // Closes the file.
FMT_API std::size_t read(void *buffer, std::size_t count); FMT_API void close();
// Attempts to write count bytes from the specified buffer to the file. // Returns the file size. The size has signed type for consistency with
FMT_API std::size_t write(const void *buffer, std::size_t count); // stat::st_size.
FMT_API long long size() const;
// Duplicates a file descriptor with the dup function and returns // Attempts to read count bytes from the file into the specified buffer.
// the duplicate as a file object. FMT_API std::size_t read(void *buffer, std::size_t count);
FMT_API static file dup(int fd);
// Makes fd be the copy of this file descriptor, closing fd first if // Attempts to write count bytes from the specified buffer to the file.
// necessary. FMT_API std::size_t write(const void *buffer, std::size_t count);
FMT_API void dup2(int fd);
// Makes fd be the copy of this file descriptor, closing fd first if // Duplicates a file descriptor with the dup function and returns
// necessary. // the duplicate as a file object.
FMT_API void dup2(int fd, error_code &ec) FMT_NOEXCEPT; FMT_API static file dup(int fd);
// Creates a pipe setting up read_end and write_end file objects for reading // Makes fd be the copy of this file descriptor, closing fd first if
// and writing respectively. // necessary.
FMT_API static void pipe(file &read_end, file &write_end); FMT_API void dup2(int fd);
// Creates a buffered_file object associated with this file and detaches // Makes fd be the copy of this file descriptor, closing fd first if
// this file object from the file. // necessary.
FMT_API buffered_file fdopen(const char *mode); FMT_API void dup2(int fd, error_code &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 buffered_file object associated with this file and detaches
// this file object from the file.
FMT_API buffered_file fdopen(const char *mode);
}; };
// Returns the memory page size. // Returns the memory page size.
long getpagesize(); long getpagesize();
#if (defined(LC_NUMERIC_MASK) || defined(_MSC_VER)) && !defined(__ANDROID__) && !defined(__CYGWIN__) && !defined(__OpenBSD__) #if (defined(LC_NUMERIC_MASK) || defined(_MSC_VER)) && \
#define FMT_LOCALE !defined(__ANDROID__) && !defined(__CYGWIN__) && !defined(__OpenBSD__) && \
!defined(__NEWLIB_H__)
# define FMT_LOCALE
#endif #endif
#ifdef FMT_LOCALE #ifdef FMT_LOCALE
// A "C" numeric locale. // A "C" numeric locale.
class Locale class Locale {
{ private:
private: # ifdef _MSC_VER
#ifdef _MSC_VER typedef _locale_t locale_t;
typedef _locale_t locale_t;
enum { LC_NUMERIC_MASK = LC_NUMERIC };
enum
{ static locale_t newlocale(int category_mask, const char *locale, locale_t) {
LC_NUMERIC_MASK = LC_NUMERIC return _create_locale(category_mask, locale);
}; }
static locale_t newlocale(int category_mask, const char *locale, locale_t) static void freelocale(locale_t locale) {
{ _free_locale(locale);
return _create_locale(category_mask, locale); }
}
static double strtod_l(const char *nptr, char **endptr, _locale_t locale) {
static void freelocale(locale_t locale) return _strtod_l(nptr, endptr, locale);
{ }
_free_locale(locale); # endif
}
locale_t locale_;
static double strtod_l(const char *nptr, char **endptr, _locale_t locale)
{ Locale(const Locale &) = delete;
return _strtod_l(nptr, endptr, locale); void operator=(const Locale &) = delete;
}
#endif public:
typedef locale_t Type;
locale_t locale_;
Locale() : locale_(newlocale(LC_NUMERIC_MASK, "C", FMT_NULL)) {
FMT_DISALLOW_COPY_AND_ASSIGN(Locale); if (!locale_)
FMT_THROW(system_error(errno, "cannot create locale"));
public: }
typedef locale_t Type; ~Locale() { freelocale(locale_); }
Locale() Type get() const { return locale_; }
: locale_(newlocale(LC_NUMERIC_MASK, "C", FMT_NULL))
{ // Converts string to floating-point number and advances str past the end
if (!locale_) // of the parsed input.
FMT_THROW(system_error(errno, "cannot create locale")); double strtod(const char *&str) const {
} char *end = FMT_NULL;
~Locale() double result = strtod_l(str, &end, locale_);
{ str = end;
freelocale(locale_); return result;
} }
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 #endif // FMT_LOCALE
FMT_END_NAMESPACE FMT_END_NAMESPACE
#if !FMT_USE_RVALUE_REFERENCES #endif // FMT_POSIX_H_
namespace std {
// For compatibility with C++98.
inline fmt::buffered_file &move(fmt::buffered_file &f)
{
return f;
}
inline fmt::file &move(fmt::file &f)
{
return f;
}
} // namespace std
#endif
#endif // FMT_POSIX_H_

File diff suppressed because it is too large Load Diff

@ -17,328 +17,289 @@
// output only up to N items from the range. // output only up to N items from the range.
#ifndef FMT_RANGE_OUTPUT_LENGTH_LIMIT #ifndef FMT_RANGE_OUTPUT_LENGTH_LIMIT
#define FMT_RANGE_OUTPUT_LENGTH_LIMIT 256 # define FMT_RANGE_OUTPUT_LENGTH_LIMIT 256
#endif #endif
FMT_BEGIN_NAMESPACE FMT_BEGIN_NAMESPACE
template<typename Char> template <typename Char>
struct formatting_base struct formatting_base {
{ template <typename ParseContext>
template<typename ParseContext> FMT_CONSTEXPR auto parse(ParseContext &ctx) -> decltype(ctx.begin()) {
FMT_CONSTEXPR auto parse(ParseContext &ctx) -> decltype(ctx.begin()) return ctx.begin();
{ }
return ctx.begin();
}
}; };
template<typename Char, typename Enable = void> template <typename Char, typename Enable = void>
struct formatting_range : formatting_base<Char> struct formatting_range : formatting_base<Char> {
{ static FMT_CONSTEXPR_DECL const std::size_t range_length_limit =
static FMT_CONSTEXPR_DECL const std::size_t range_length_limit = FMT_RANGE_OUTPUT_LENGTH_LIMIT; // output only up to N items from the FMT_RANGE_OUTPUT_LENGTH_LIMIT; // output only up to N items from the range.
// range. Char prefix;
Char prefix; Char delimiter;
Char delimiter; Char postfix;
Char postfix; formatting_range() : prefix('{'), delimiter(','), postfix('}') {}
formatting_range() static FMT_CONSTEXPR_DECL const bool add_delimiter_spaces = true;
: prefix('{') static FMT_CONSTEXPR_DECL const bool add_prepostfix_space = false;
, delimiter(',')
, postfix('}')
{
}
static FMT_CONSTEXPR_DECL const bool add_delimiter_spaces = true;
static FMT_CONSTEXPR_DECL const bool add_prepostfix_space = false;
}; };
template<typename Char, typename Enable = void> template <typename Char, typename Enable = void>
struct formatting_tuple : formatting_base<Char> struct formatting_tuple : formatting_base<Char> {
{ Char prefix;
Char prefix; Char delimiter;
Char delimiter; Char postfix;
Char postfix; formatting_tuple() : prefix('('), delimiter(','), postfix(')') {}
formatting_tuple() static FMT_CONSTEXPR_DECL const bool add_delimiter_spaces = true;
: prefix('(') static FMT_CONSTEXPR_DECL const bool add_prepostfix_space = false;
, delimiter(',')
, postfix(')')
{
}
static FMT_CONSTEXPR_DECL const bool add_delimiter_spaces = true;
static FMT_CONSTEXPR_DECL const bool add_prepostfix_space = false;
}; };
namespace internal { namespace internal {
template<typename RangeT, typename OutputIterator> template <typename RangeT, typename OutputIterator>
void copy(const RangeT &range, OutputIterator out) void copy(const RangeT &range, OutputIterator out) {
{ for (auto it = range.begin(), end = range.end(); it != end; ++it)
for (auto it = range.begin(), end = range.end(); it != end; ++it) *out++ = *it;
*out++ = *it;
} }
template<typename OutputIterator> template <typename OutputIterator>
void copy(const char *str, OutputIterator out) void copy(const char *str, OutputIterator out) {
{ const char *p_curr = str;
const char *p_curr = str; while (*p_curr) {
while (*p_curr) *out++ = *p_curr++;
{ }
*out++ = *p_curr++;
}
} }
template<typename OutputIterator> template <typename OutputIterator>
void copy(char ch, OutputIterator out) void copy(char ch, OutputIterator out) {
{ *out++ = ch;
*out++ = ch;
} }
/// Return true value if T has std::string interface, like std::string_view. /// Return true value if T has std::string interface, like std::string_view.
template<typename T> template <typename T>
class is_like_std_string class is_like_std_string {
{ template <typename U>
template<typename U> static auto check(U *p) ->
static auto check(U *p) -> decltype(p->find('a'), p->length(), p->data(), int()); decltype(p->find('a'), p->length(), p->data(), int());
template<typename> template <typename>
static void check(...); static void check(...);
public: public:
static FMT_CONSTEXPR_DECL const bool value = !std::is_void<decltype(check<T>(FMT_NULL))>::value; static FMT_CONSTEXPR_DECL const bool value =
!std::is_void<decltype(check<T>(FMT_NULL))>::value;
}; };
template<typename... Ts> template <typename... Ts>
struct conditional_helper struct conditional_helper {};
{
};
template<typename T, typename _ = void> template <typename T, typename _ = void>
struct is_range_ : std::false_type struct is_range_ : std::false_type {};
{
};
#if !FMT_MSC_VER || FMT_MSC_VER > 1800 #if !FMT_MSC_VER || FMT_MSC_VER > 1800
template<typename T> template <typename T>
struct is_range_<T, typename std::conditional<false, struct is_range_<T, typename std::conditional<
conditional_helper<decltype(internal::declval<T>().begin()), decltype(internal::declval<T>().end())>, void>::type> false,
: std::true_type conditional_helper<decltype(internal::declval<T>().begin()),
{ decltype(internal::declval<T>().end())>,
}; void>::type> : std::true_type {};
#endif #endif
/// tuple_size and tuple_element check. /// tuple_size and tuple_element check.
template<typename T> template <typename T>
class is_tuple_like_ class is_tuple_like_ {
{ template <typename U>
template<typename U> static auto check(U *p) ->
static auto check(U *p) -> decltype(std::tuple_size<U>::value, internal::declval<typename std::tuple_element<0, U>::type>(), int()); decltype(std::tuple_size<U>::value,
template<typename> internal::declval<typename std::tuple_element<0, U>::type>(), int());
static void check(...); template <typename>
static void check(...);
public:
static FMT_CONSTEXPR_DECL const bool value = !std::is_void<decltype(check<T>(FMT_NULL))>::value; public:
static FMT_CONSTEXPR_DECL const bool value =
!std::is_void<decltype(check<T>(FMT_NULL))>::value;
}; };
// Check for integer_sequence // Check for integer_sequence
#if defined(__cpp_lib_integer_sequence) || FMT_MSC_VER >= 1900 #if defined(__cpp_lib_integer_sequence) || FMT_MSC_VER >= 1900
template<typename T, T... N> template <typename T, T... N>
using integer_sequence = std::integer_sequence<T, N...>; using integer_sequence = std::integer_sequence<T, N...>;
template<std::size_t... N> template <std::size_t... N>
using index_sequence = std::index_sequence<N...>; using index_sequence = std::index_sequence<N...>;
template<std::size_t N> template <std::size_t N>
using make_index_sequence = std::make_index_sequence<N>; using make_index_sequence = std::make_index_sequence<N>;
#else #else
template<typename T, T... N> template <typename T, T... N>
struct integer_sequence struct integer_sequence {
{ typedef T value_type;
typedef T value_type;
static FMT_CONSTEXPR std::size_t size() {
static FMT_CONSTEXPR std::size_t size() return sizeof...(N);
{ }
return sizeof...(N);
}
}; };
template<std::size_t... N> template <std::size_t... N>
using index_sequence = integer_sequence<std::size_t, N...>; using index_sequence = integer_sequence<std::size_t, N...>;
template<typename T, std::size_t N, T... Ns> template <typename T, std::size_t N, T... Ns>
struct make_integer_sequence : make_integer_sequence<T, N - 1, N - 1, Ns...> struct make_integer_sequence : make_integer_sequence<T, N - 1, N - 1, Ns...> {};
{ template <typename T, T... Ns>
}; struct make_integer_sequence<T, 0, Ns...> : integer_sequence<T, Ns...> {};
template<typename T, T... Ns>
struct make_integer_sequence<T, 0, Ns...> : integer_sequence<T, Ns...>
{
};
template<std::size_t N> template <std::size_t N>
using make_index_sequence = make_integer_sequence<std::size_t, N>; using make_index_sequence = make_integer_sequence<std::size_t, N>;
#endif #endif
template<class Tuple, class F, size_t... Is> template <class Tuple, class F, size_t... Is>
void for_each(index_sequence<Is...>, Tuple &&tup, F &&f) FMT_NOEXCEPT void for_each(index_sequence<Is...>, Tuple &&tup, F &&f) FMT_NOEXCEPT {
{ using std::get;
using std::get; // using free function get<I>(T) now.
// using free function get<I>(T) now. const int _[] = {0, ((void)f(get<Is>(tup)), 0)...};
const int _[] = {0, ((void)f(get<Is>(tup)), 0)...}; (void)_; // blocks warnings
(void)_; // blocks warnings
} }
template<class T> template <class T>
FMT_CONSTEXPR make_index_sequence<std::tuple_size<T>::value> get_indexes(T const &) FMT_CONSTEXPR make_index_sequence<std::tuple_size<T>::value>
{ get_indexes(T const &) { return {}; }
return {};
}
template<class Tuple, class F> template <class Tuple, class F>
void for_each(Tuple &&tup, F &&f) void for_each(Tuple &&tup, F &&f) {
{ const auto indexes = get_indexes(tup);
const auto indexes = get_indexes(tup); for_each(indexes, std::forward<Tuple>(tup), std::forward<F>(f));
for_each(indexes, std::forward<Tuple>(tup), std::forward<F>(f));
} }
template<typename Arg> template<typename Arg>
FMT_CONSTEXPR const char *format_str_quoted( FMT_CONSTEXPR const char* format_str_quoted(bool add_space, const Arg&,
bool add_space, const Arg &, typename std::enable_if<!is_like_std_string<typename std::decay<Arg>::type>::value>::type * = nullptr) typename std::enable_if<
{ !is_like_std_string<typename std::decay<Arg>::type>::value>::type* = nullptr) {
return add_space ? " {}" : "{}"; return add_space ? " {}" : "{}";
} }
template<typename Arg> template<typename Arg>
FMT_CONSTEXPR const char *format_str_quoted( FMT_CONSTEXPR const char* format_str_quoted(bool add_space, const Arg&,
bool add_space, const Arg &, typename std::enable_if<is_like_std_string<typename std::decay<Arg>::type>::value>::type * = nullptr) typename std::enable_if<
{ is_like_std_string<typename std::decay<Arg>::type>::value>::type* = nullptr) {
return add_space ? " \"{}\"" : "\"{}\""; return add_space ? " \"{}\"" : "\"{}\"";
} }
FMT_CONSTEXPR const char *format_str_quoted(bool add_space, const char *) FMT_CONSTEXPR const char* format_str_quoted(bool add_space, const char*) {
{ return add_space ? " \"{}\"" : "\"{}\"";
return add_space ? " \"{}\"" : "\"{}\"";
} }
FMT_CONSTEXPR const wchar_t *format_str_quoted(bool add_space, const wchar_t *) FMT_CONSTEXPR const wchar_t* format_str_quoted(bool add_space, const wchar_t*) {
{
return add_space ? L" \"{}\"" : L"\"{}\""; return add_space ? L" \"{}\"" : L"\"{}\"";
} }
FMT_CONSTEXPR const char *format_str_quoted(bool add_space, const char) FMT_CONSTEXPR const char* format_str_quoted(bool add_space, const char) {
{
return add_space ? " '{}'" : "'{}'"; return add_space ? " '{}'" : "'{}'";
} }
FMT_CONSTEXPR const wchar_t *format_str_quoted(bool add_space, const wchar_t) FMT_CONSTEXPR const wchar_t* format_str_quoted(bool add_space, const wchar_t) {
{
return add_space ? L" '{}'" : L"'{}'"; return add_space ? L" '{}'" : L"'{}'";
} }
} // namespace internal } // namespace internal
template<typename T> template <typename T>
struct is_tuple_like struct is_tuple_like {
{ static FMT_CONSTEXPR_DECL const bool value =
static FMT_CONSTEXPR_DECL const bool value = internal::is_tuple_like_<T>::value && !internal::is_range_<T>::value; internal::is_tuple_like_<T>::value && !internal::is_range_<T>::value;
}; };
template<typename TupleT, typename Char> template <typename TupleT, typename Char>
struct formatter<TupleT, Char, typename std::enable_if<fmt::is_tuple_like<TupleT>::value>::type> struct formatter<TupleT, Char,
{ typename std::enable_if<fmt::is_tuple_like<TupleT>::value>::type> {
private: private:
// C++11 generic lambda for format() // C++11 generic lambda for format()
template<typename FormatContext> template <typename FormatContext>
struct format_each struct format_each {
{ template <typename T>
template<typename T> void operator()(const T& v) {
void operator()(const T &v) if (i > 0) {
{ if (formatting.add_prepostfix_space) {
if (i > 0) *out++ = ' ';
{
if (formatting.add_prepostfix_space)
{
*out++ = ' ';
}
internal::copy(formatting.delimiter, out);
}
format_to(out, internal::format_str_quoted((formatting.add_delimiter_spaces && i > 0), v), v);
++i;
} }
internal::copy(formatting.delimiter, out);
}
format_to(out,
internal::format_str_quoted(
(formatting.add_delimiter_spaces && i > 0), v),
v);
++i;
}
formatting_tuple<Char> &formatting; formatting_tuple<Char>& formatting;
std::size_t &i; std::size_t& i;
typename std::add_lvalue_reference<decltype(std::declval<FormatContext>().out())>::type out; typename std::add_lvalue_reference<decltype(std::declval<FormatContext>().out())>::type out;
}; };
public: public:
formatting_tuple<Char> formatting; formatting_tuple<Char> formatting;
template<typename ParseContext> template <typename ParseContext>
FMT_CONSTEXPR auto parse(ParseContext &ctx) -> decltype(ctx.begin()) FMT_CONSTEXPR auto parse(ParseContext &ctx) -> decltype(ctx.begin()) {
{ return formatting.parse(ctx);
return formatting.parse(ctx); }
template <typename FormatContext = format_context>
auto format(const TupleT &values, FormatContext &ctx) -> decltype(ctx.out()) {
auto out = ctx.out();
std::size_t i = 0;
internal::copy(formatting.prefix, out);
internal::for_each(values, format_each<FormatContext>{formatting, i, out});
if (formatting.add_prepostfix_space) {
*out++ = ' ';
} }
internal::copy(formatting.postfix, out);
template<typename FormatContext = format_context> return ctx.out();
auto format(const TupleT &values, FormatContext &ctx) -> decltype(ctx.out()) }
{
auto out = ctx.out();
std::size_t i = 0;
internal::copy(formatting.prefix, out);
internal::for_each(values, format_each<FormatContext>{formatting, i, out});
if (formatting.add_prepostfix_space)
{
*out++ = ' ';
}
internal::copy(formatting.postfix, out);
return ctx.out();
}
}; };
template<typename T> template <typename T>
struct is_range struct is_range {
{ static FMT_CONSTEXPR_DECL const bool value =
static FMT_CONSTEXPR_DECL const bool value = internal::is_range_<T>::value && !internal::is_like_std_string<T>::value; internal::is_range_<T>::value && !internal::is_like_std_string<T>::value;
}; };
template<typename RangeT, typename Char> template <typename RangeT, typename Char>
struct formatter<RangeT, Char, typename std::enable_if<fmt::is_range<RangeT>::value>::type> struct formatter<RangeT, Char,
{ typename std::enable_if<fmt::is_range<RangeT>::value>::type> {
formatting_range<Char> formatting; formatting_range<Char> formatting;
template<typename ParseContext> template <typename ParseContext>
FMT_CONSTEXPR auto parse(ParseContext &ctx) -> decltype(ctx.begin()) FMT_CONSTEXPR auto parse(ParseContext &ctx) -> decltype(ctx.begin()) {
{ return formatting.parse(ctx);
return formatting.parse(ctx); }
}
template <typename FormatContext>
template<typename FormatContext> typename FormatContext::iterator format(
typename FormatContext::iterator format(const RangeT &values, FormatContext &ctx) const RangeT &values, FormatContext &ctx) {
{ auto out = ctx.out();
auto out = ctx.out(); internal::copy(formatting.prefix, out);
internal::copy(formatting.prefix, out); std::size_t i = 0;
std::size_t i = 0; for (auto it = values.begin(), end = values.end(); it != end; ++it) {
for (auto it = values.begin(), end = values.end(); it != end; ++it) if (i > 0) {
{ if (formatting.add_prepostfix_space) {
if (i > 0) *out++ = ' ';
{
if (formatting.add_prepostfix_space)
{
*out++ = ' ';
}
internal::copy(formatting.delimiter, out);
}
format_to(out, internal::format_str_quoted((formatting.add_delimiter_spaces && i > 0), *it), *it);
if (++i > formatting.range_length_limit)
{
format_to(out, " ... <other elements>");
break;
}
} }
if (formatting.add_prepostfix_space) internal::copy(formatting.delimiter, out);
{ }
*out++ = ' '; format_to(out,
} internal::format_str_quoted(
internal::copy(formatting.postfix, out); (formatting.add_delimiter_spaces && i > 0), *it),
return ctx.out(); *it);
if (++i > formatting.range_length_limit) {
format_to(out, " ... <other elements>");
break;
}
}
if (formatting.add_prepostfix_space) {
*out++ = ' ';
} }
internal::copy(formatting.postfix, out);
return ctx.out();
}
}; };
FMT_END_NAMESPACE FMT_END_NAMESPACE
#endif // FMT_RANGES_H_ #endif // FMT_RANGES_H_

@ -13,187 +13,144 @@
FMT_BEGIN_NAMESPACE FMT_BEGIN_NAMESPACE
namespace internal { // Prevents expansion of a preceding token as a function-style macro.
inline null<> localtime_r(...) // Usage: f FMT_NOMACRO()
{ #define FMT_NOMACRO
return null<>();
} namespace internal{
inline null<> localtime_s(...) inline null<> localtime_r FMT_NOMACRO(...) { return null<>(); }
{ inline null<> localtime_s(...) { return null<>(); }
return null<>(); inline null<> gmtime_r(...) { return null<>(); }
} inline null<> gmtime_s(...) { return null<>(); }
inline null<> gmtime_r(...)
{
return null<>();
} }
inline null<> gmtime_s(...)
{
return null<>();
}
} // namespace internal
// Thread-safe replacement for std::localtime // Thread-safe replacement for std::localtime
inline std::tm localtime(std::time_t time) inline std::tm localtime(std::time_t time) {
{ struct dispatcher {
struct dispatcher std::time_t time_;
{ std::tm tm_;
std::time_t time_;
std::tm tm_; dispatcher(std::time_t t): time_(t) {}
dispatcher(std::time_t t) bool run() {
: time_(t) using namespace fmt::internal;
{ return handle(localtime_r(&time_, &tm_));
} }
bool run() bool handle(std::tm *tm) { return tm != FMT_NULL; }
{
using namespace fmt::internal; bool handle(internal::null<>) {
return handle(localtime_r(&time_, &tm_)); using namespace fmt::internal;
} return fallback(localtime_s(&tm_, &time_));
}
bool handle(std::tm *tm)
{ bool fallback(int res) { return res == 0; }
return tm != FMT_NULL;
} bool fallback(internal::null<>) {
using namespace fmt::internal;
bool handle(internal::null<>) std::tm *tm = std::localtime(&time_);
{ if (tm) tm_ = *tm;
using namespace fmt::internal; return tm != FMT_NULL;
return fallback(localtime_s(&tm_, &time_)); }
} };
dispatcher lt(time);
bool fallback(int res) if (lt.run())
{ return lt.tm_;
return res == 0; // Too big time values may be unsupported.
} FMT_THROW(format_error("time_t value out of range"));
bool fallback(internal::null<>)
{
using namespace fmt::internal;
std::tm *tm = std::localtime(&time_);
if (tm)
tm_ = *tm;
return tm != FMT_NULL;
}
};
dispatcher lt(time);
if (lt.run())
return lt.tm_;
// Too big time values may be unsupported.
FMT_THROW(format_error("time_t value out of range"));
} }
// Thread-safe replacement for std::gmtime // Thread-safe replacement for std::gmtime
inline std::tm gmtime(std::time_t time) inline std::tm gmtime(std::time_t time) {
{ struct dispatcher {
struct dispatcher std::time_t time_;
{ std::tm tm_;
std::time_t time_;
std::tm tm_; dispatcher(std::time_t t): time_(t) {}
dispatcher(std::time_t t) bool run() {
: time_(t) using namespace fmt::internal;
{ return handle(gmtime_r(&time_, &tm_));
} }
bool run() bool handle(std::tm *tm) { return tm != FMT_NULL; }
{
using namespace fmt::internal; bool handle(internal::null<>) {
return handle(gmtime_r(&time_, &tm_)); using namespace fmt::internal;
} return fallback(gmtime_s(&tm_, &time_));
}
bool handle(std::tm *tm)
{ bool fallback(int res) { return res == 0; }
return tm != FMT_NULL;
} bool fallback(internal::null<>) {
std::tm *tm = std::gmtime(&time_);
bool handle(internal::null<>) if (tm) tm_ = *tm;
{ return tm != FMT_NULL;
using namespace fmt::internal; }
return fallback(gmtime_s(&tm_, &time_)); };
} dispatcher gt(time);
if (gt.run())
bool fallback(int res) return gt.tm_;
{ // Too big time values may be unsupported.
return res == 0; FMT_THROW(format_error("time_t value out of range"));
}
bool fallback(internal::null<>)
{
std::tm *tm = std::gmtime(&time_);
if (tm)
tm_ = *tm;
return tm != FMT_NULL;
}
};
dispatcher gt(time);
if (gt.run())
return gt.tm_;
// Too big time values may be unsupported.
FMT_THROW(format_error("time_t value out of range"));
} }
namespace internal { namespace internal {
inline std::size_t strftime(char *str, std::size_t count, const char *format, const std::tm *time) inline std::size_t strftime(char *str, std::size_t count, const char *format,
{ const std::tm *time) {
return std::strftime(str, count, format, time); return std::strftime(str, count, format, time);
} }
inline std::size_t strftime(wchar_t *str, std::size_t count, const wchar_t *format, const std::tm *time) inline std::size_t strftime(wchar_t *str, std::size_t count,
{ const wchar_t *format, const std::tm *time) {
return std::wcsftime(str, count, format, time); return std::wcsftime(str, count, format, time);
}
} }
} // namespace internal
template<typename Char>
struct formatter<std::tm, Char>
{
template<typename ParseContext>
auto parse(ParseContext &ctx) -> decltype(ctx.begin())
{
auto it = internal::null_terminating_iterator<Char>(ctx);
if (*it == ':')
++it;
auto end = it;
while (*end && *end != '}')
++end;
tm_format.reserve(end - it + 1);
using internal::pointer_from;
tm_format.append(pointer_from(it), pointer_from(end));
tm_format.push_back('\0');
return pointer_from(end);
}
template<typename FormatContext> template <typename Char>
auto format(const std::tm &tm, FormatContext &ctx) -> decltype(ctx.out()) struct formatter<std::tm, Char> {
{ template <typename ParseContext>
internal::basic_buffer<Char> &buf = internal::get_container(ctx.out()); auto parse(ParseContext &ctx) -> decltype(ctx.begin()) {
std::size_t start = buf.size(); auto it = internal::null_terminating_iterator<Char>(ctx);
for (;;) if (*it == ':')
{ ++it;
std::size_t size = buf.capacity() - start; auto end = it;
std::size_t count = internal::strftime(&buf[start], size, &tm_format[0], &tm); while (*end && *end != '}')
if (count != 0) ++end;
{ tm_format.reserve(end - it + 1);
buf.resize(start + count); using internal::pointer_from;
break; tm_format.append(pointer_from(it), pointer_from(end));
} tm_format.push_back('\0');
if (size >= tm_format.size() * 256) return pointer_from(end);
{ }
// 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 template <typename FormatContext>
// better way to distinguish the two cases: auto format(const std::tm &tm, FormatContext &ctx) -> decltype(ctx.out()) {
// https://github.com/fmtlib/fmt/issues/367 internal::basic_buffer<Char> &buf = internal::get_container(ctx.out());
break; std::size_t start = buf.size();
} for (;;) {
const std::size_t MIN_GROWTH = 10; std::size_t size = buf.capacity() - start;
buf.reserve(buf.capacity() + (size > MIN_GROWTH ? size : MIN_GROWTH)); std::size_t count =
} internal::strftime(&buf[start], size, &tm_format[0], &tm);
return ctx.out(); if (count != 0) {
buf.resize(start + count);
break;
}
if (size >= tm_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;
buf.reserve(buf.capacity() + (size > MIN_GROWTH ? size : MIN_GROWTH));
} }
return ctx.out();
}
basic_memory_buffer<Char> tm_format; basic_memory_buffer<Char> tm_format;
}; };
FMT_END_NAMESPACE FMT_END_NAMESPACE
#endif // FMT_TIME_H_ #endif // FMT_TIME_H_

Loading…
Cancel
Save