clang-format for header files

- Google Style, Cpp 11
- Break for template and param/arguments
This commit is contained in:
luncliff 2018-12-19 15:42:25 +09:00
parent 3e01376e08
commit 8671608b83
14 changed files with 1854 additions and 1567 deletions

12
.clang-format Normal file
View File

@ -0,0 +1,12 @@
BasedOnStyle: Google
Language: Cpp
Standard: Cpp11
ColumnLimit: 80
AlwaysBreakTemplateDeclarations: true
AllowShortIfStatementsOnASingleLine: false
AlignAfterOpenBracket: AlwaysBreak
BinPackArguments: false
BinPackParameters: false

View File

@ -28,12 +28,14 @@ enum class numeric_system {
// Parses a put_time-like format string and invokes handler actions. // Parses a put_time-like format string and invokes handler actions.
template <typename Char, typename Handler> template <typename Char, typename Handler>
FMT_CONSTEXPR const Char *parse_chrono_format( FMT_CONSTEXPR const Char *parse_chrono_format(const Char *begin,
const Char *begin, const Char *end, Handler &&handler) { const Char *end,
Handler &&handler) {
auto ptr = begin; auto ptr = begin;
while (ptr != end) { while (ptr != end) {
auto c = *ptr; auto c = *ptr;
if (c == '}') break; if (c == '}')
break;
if (c != '%') { if (c != '%') {
++ptr; ++ptr;
continue; continue;
@ -213,7 +215,8 @@ struct chrono_format_checker {
template <typename Int> template <typename Int>
inline int to_int(Int value) { inline int to_int(Int value) {
FMT_ASSERT(value >= (std::numeric_limits<int>::min)() && FMT_ASSERT(value >= (std::numeric_limits<int>::min)() &&
value <= (std::numeric_limits<int>::max)(), "invalid value"); value <= (std::numeric_limits<int>::max)(),
"invalid value");
return static_cast<int>(value); return static_cast<int>(value);
} }
@ -341,30 +344,84 @@ struct chrono_formatter {
}; };
} // namespace internal } // namespace internal
template <typename Period> FMT_CONSTEXPR const char *get_units() { template <typename Period>
FMT_CONSTEXPR const char *get_units() {
return FMT_NULL; return FMT_NULL;
} }
template <> FMT_CONSTEXPR const char *get_units<std::atto>() { return "as"; } template <>
template <> FMT_CONSTEXPR const char *get_units<std::femto>() { return "fs"; } FMT_CONSTEXPR const char *get_units<std::atto>() {
template <> FMT_CONSTEXPR const char *get_units<std::pico>() { return "ps"; } return "as";
template <> FMT_CONSTEXPR const char *get_units<std::nano>() { return "ns"; } }
template <> FMT_CONSTEXPR const char *get_units<std::micro>() { return "µs"; } template <>
template <> FMT_CONSTEXPR const char *get_units<std::milli>() { return "ms"; } FMT_CONSTEXPR const char *get_units<std::femto>() {
template <> FMT_CONSTEXPR const char *get_units<std::centi>() { return "cs"; } return "fs";
template <> FMT_CONSTEXPR const char *get_units<std::deci>() { return "ds"; } }
template <> FMT_CONSTEXPR const char *get_units<std::ratio<1>>() { return "s"; } template <>
template <> FMT_CONSTEXPR const char *get_units<std::deca>() { return "das"; } FMT_CONSTEXPR const char *get_units<std::pico>() {
template <> FMT_CONSTEXPR const char *get_units<std::hecto>() { return "hs"; } return "ps";
template <> FMT_CONSTEXPR const char *get_units<std::kilo>() { return "ks"; } }
template <> FMT_CONSTEXPR const char *get_units<std::mega>() { return "Ms"; } template <>
template <> FMT_CONSTEXPR const char *get_units<std::giga>() { return "Gs"; } FMT_CONSTEXPR const char *get_units<std::nano>() {
template <> FMT_CONSTEXPR const char *get_units<std::tera>() { return "Ts"; } return "ns";
template <> FMT_CONSTEXPR const char *get_units<std::peta>() { return "Ps"; } }
template <> FMT_CONSTEXPR const char *get_units<std::exa>() { return "Es"; } template <>
template <> FMT_CONSTEXPR const char *get_units<std::ratio<60>>() { FMT_CONSTEXPR const char *get_units<std::micro>() {
return "µs";
}
template <>
FMT_CONSTEXPR const char *get_units<std::milli>() {
return "ms";
}
template <>
FMT_CONSTEXPR const char *get_units<std::centi>() {
return "cs";
}
template <>
FMT_CONSTEXPR const char *get_units<std::deci>() {
return "ds";
}
template <>
FMT_CONSTEXPR const char *get_units<std::ratio<1>>() {
return "s";
}
template <>
FMT_CONSTEXPR const char *get_units<std::deca>() {
return "das";
}
template <>
FMT_CONSTEXPR const char *get_units<std::hecto>() {
return "hs";
}
template <>
FMT_CONSTEXPR const char *get_units<std::kilo>() {
return "ks";
}
template <>
FMT_CONSTEXPR const char *get_units<std::mega>() {
return "Ms";
}
template <>
FMT_CONSTEXPR const char *get_units<std::giga>() {
return "Gs";
}
template <>
FMT_CONSTEXPR const char *get_units<std::tera>() {
return "Ts";
}
template <>
FMT_CONSTEXPR const char *get_units<std::peta>() {
return "Ps";
}
template <>
FMT_CONSTEXPR const char *get_units<std::exa>() {
return "Es";
}
template <>
FMT_CONSTEXPR const char *get_units<std::ratio<60>>() {
return "m"; return "m";
} }
template <> FMT_CONSTEXPR const char *get_units<std::ratio<3600>>() { template <>
FMT_CONSTEXPR const char *get_units<std::ratio<3600>>() {
return "h"; return "h";
} }
@ -409,10 +466,12 @@ struct formatter<std::chrono::duration<Rep, Period>, Char> {
FMT_CONSTEXPR auto parse(basic_parse_context<Char> &ctx) FMT_CONSTEXPR auto parse(basic_parse_context<Char> &ctx)
-> decltype(ctx.begin()) { -> decltype(ctx.begin()) {
auto begin = ctx.begin(), end = ctx.end(); auto begin = ctx.begin(), end = ctx.end();
if (begin == end) return begin; if (begin == end)
return begin;
spec_handler handler{*this, ctx}; spec_handler handler{*this, ctx};
begin = internal::parse_align(begin, end, handler); begin = internal::parse_align(begin, end, handler);
if (begin == end) return begin; if (begin == end)
return begin;
begin = internal::parse_width(begin, end, handler); begin = internal::parse_width(begin, end, handler);
end = parse_chrono_format(begin, end, internal::chrono_format_checker()); end = parse_chrono_format(begin, end, internal::chrono_format_checker());
format_str = basic_string_view<Char>(&*begin, end - begin); format_str = basic_string_view<Char>(&*begin, end - begin);
@ -420,8 +479,7 @@ struct formatter<std::chrono::duration<Rep, Period>, Char> {
} }
template <typename FormatContext> template <typename FormatContext>
auto format(const duration &d, FormatContext &ctx) auto format(const duration &d, FormatContext &ctx) -> decltype(ctx.out()) {
-> decltype(ctx.out()) {
auto begin = format_str.begin(), end = format_str.end(); auto begin = format_str.begin(), end = format_str.end();
if (begin == end || *begin == '}') { if (begin == end || *begin == '}') {
memory_buffer buf; memory_buffer buf;
@ -433,8 +491,8 @@ struct formatter<std::chrono::duration<Rep, Period>, Char> {
format_to(buf, "{}[{}/{}]s", d.count(), Period::num, Period::den); format_to(buf, "{}[{}/{}]s", d.count(), Period::num, Period::den);
typedef output_range<decltype(ctx.out()), Char> range; typedef output_range<decltype(ctx.out()), Char> range;
basic_writer<range> w(range(ctx.out())); basic_writer<range> w(range(ctx.out()));
internal::handle_dynamic_spec<internal::width_checker>( internal::handle_dynamic_spec<internal::width_checker>(spec.width_,
spec.width_, width_ref, ctx); width_ref, ctx);
w.write(buf.data(), buf.size(), spec); w.write(buf.data(), buf.size(), spec);
return w.out(); return w.out();
} }

View File

@ -47,6 +47,8 @@ inline void vprint_colored(color c, wstring_view format, wformat_args args) {
#else #else
// clang-format off
enum class color : uint32_t { enum class color : uint32_t {
alice_blue = 0xF0F8FF, // rgb(240,248,255) alice_blue = 0xF0F8FF, // rgb(240,248,255)
antique_white = 0xFAEBD7, // rgb(250,235,215) antique_white = 0xFAEBD7, // rgb(250,235,215)
@ -191,6 +193,8 @@ enum class color : uint32_t {
yellow_green = 0x9ACD32 // rgb(154,205,50) yellow_green = 0x9ACD32 // rgb(154,205,50)
}; // enum class color }; // enum class color
// clang-format on
enum class terminal_color : uint8_t { enum class terminal_color : uint8_t {
black = 30, black = 30,
red, red,
@ -227,7 +231,8 @@ struct rgb {
FMT_CONSTEXPR_DECL rgb(uint32_t hex) FMT_CONSTEXPR_DECL rgb(uint32_t hex)
: r((hex >> 16) & 0xFF), g((hex >> 8) & 0xFF), b((hex)&0xFF) {} : r((hex >> 16) & 0xFF), g((hex >> 8) & 0xFF), b((hex)&0xFF) {}
FMT_CONSTEXPR_DECL rgb(color hex) FMT_CONSTEXPR_DECL rgb(color hex)
: r((uint32_t(hex) >> 16) & 0xFF), g((uint32_t(hex) >> 8) & 0xFF), : r((uint32_t(hex) >> 16) & 0xFF),
g((uint32_t(hex) >> 8) & 0xFF),
b(uint32_t(hex) & 0xFF) {} b(uint32_t(hex) & 0xFF) {}
uint8_t r; uint8_t r;
uint8_t g; uint8_t g;
@ -238,18 +243,16 @@ namespace internal {
// color is a struct of either a rgb color or a terminal color. // color is a struct of either a rgb color or a terminal color.
struct color_type { struct color_type {
FMT_CONSTEXPR color_type() FMT_NOEXCEPT FMT_CONSTEXPR color_type() FMT_NOEXCEPT : is_rgb(), value{} {}
: is_rgb(), value{} {} FMT_CONSTEXPR color_type(color rgb_color) FMT_NOEXCEPT : is_rgb(true),
FMT_CONSTEXPR color_type(color rgb_color) FMT_NOEXCEPT value{} {
: is_rgb(true), value{} {
value.rgb_color = static_cast<uint32_t>(rgb_color); value.rgb_color = static_cast<uint32_t>(rgb_color);
} }
FMT_CONSTEXPR color_type(rgb rgb_color) FMT_NOEXCEPT FMT_CONSTEXPR color_type(rgb rgb_color) FMT_NOEXCEPT : is_rgb(true), value{} {
: is_rgb(true), value{} {
value.rgb_color = (rgb_color.r << 16) + (rgb_color.g << 8) + rgb_color.b; value.rgb_color = (rgb_color.r << 16) + (rgb_color.g << 8) + rgb_color.b;
} }
FMT_CONSTEXPR color_type(terminal_color term_color) FMT_NOEXCEPT FMT_CONSTEXPR color_type(terminal_color term_color) FMT_NOEXCEPT : is_rgb(),
: is_rgb(), value{} { value{} {
value.term_color = static_cast<uint8_t>(term_color); value.term_color = static_cast<uint8_t>(term_color);
} }
bool is_rgb; bool is_rgb;
@ -264,7 +267,9 @@ struct color_type {
class text_style { class text_style {
public: public:
FMT_CONSTEXPR text_style(emphasis em = emphasis()) FMT_NOEXCEPT FMT_CONSTEXPR text_style(emphasis em = emphasis()) FMT_NOEXCEPT
: set_foreground_color(), set_background_color(), ems(em) {} : set_foreground_color(),
set_background_color(),
ems(em) {}
FMT_CONSTEXPR text_style &operator|=(const text_style &rhs) { FMT_CONSTEXPR text_style &operator|=(const text_style &rhs) {
if (!set_foreground_color) { if (!set_foreground_color) {
@ -290,8 +295,8 @@ class text_style {
return *this; return *this;
} }
friend FMT_CONSTEXPR friend FMT_CONSTEXPR text_style operator|(text_style lhs,
text_style operator|(text_style lhs, const text_style &rhs) { const text_style &rhs) {
return lhs |= rhs; return lhs |= rhs;
} }
@ -319,8 +324,8 @@ class text_style {
return *this; return *this;
} }
friend FMT_CONSTEXPR friend FMT_CONSTEXPR text_style operator&(text_style lhs,
text_style operator&(text_style lhs, const text_style &rhs) { const text_style &rhs) {
return lhs &= rhs; return lhs &= rhs;
} }
@ -464,20 +469,19 @@ private:
}; };
template <typename Char> template <typename Char>
FMT_CONSTEXPR ansi_color_escape<Char> FMT_CONSTEXPR ansi_color_escape<Char> make_foreground_color(
make_foreground_color(internal::color_type foreground) FMT_NOEXCEPT { internal::color_type foreground) FMT_NOEXCEPT {
return ansi_color_escape<Char>(foreground, internal::data::FOREGROUND_COLOR); return ansi_color_escape<Char>(foreground, internal::data::FOREGROUND_COLOR);
} }
template <typename Char> template <typename Char>
FMT_CONSTEXPR ansi_color_escape<Char> FMT_CONSTEXPR ansi_color_escape<Char> make_background_color(
make_background_color(internal::color_type background) FMT_NOEXCEPT { internal::color_type background) FMT_NOEXCEPT {
return ansi_color_escape<Char>(background, internal::data::BACKGROUND_COLOR); return ansi_color_escape<Char>(background, internal::data::BACKGROUND_COLOR);
} }
template <typename Char> template <typename Char>
FMT_CONSTEXPR ansi_color_escape<Char> FMT_CONSTEXPR ansi_color_escape<Char> make_emphasis(emphasis em) FMT_NOEXCEPT {
make_emphasis(emphasis em) FMT_NOEXCEPT {
return ansi_color_escape<Char>(em); return ansi_color_escape<Char>(em);
} }
@ -511,15 +515,13 @@ template <>
struct is_string<const std::FILE *> : std::false_type {}; struct is_string<const std::FILE *> : std::false_type {};
} // namespace internal } // namespace internal
template < template <typename S, typename Char = typename internal::char_t<S>::type>
typename S, typename Char = typename internal::char_t<S>::type>
void vprint(std::FILE *f, const text_style &ts, const S &format, void vprint(std::FILE *f, const text_style &ts, const S &format,
basic_format_args<typename buffer_context<Char>::type> args) { basic_format_args<typename buffer_context<Char>::type> args) {
bool has_style = false; bool has_style = false;
if (ts.has_emphasis()) { if (ts.has_emphasis()) {
has_style = true; has_style = true;
internal::fputs<Char>( internal::fputs<Char>(internal::make_emphasis<Char>(ts.get_emphasis()), f);
internal::make_emphasis<Char>(ts.get_emphasis()), f);
} }
if (ts.has_foreground()) { if (ts.has_foreground()) {
has_style = true; has_style = true;
@ -564,8 +566,7 @@ typename std::enable_if<internal::is_string<String>::value>::type print(
*/ */
template <typename String, typename... Args> template <typename String, typename... Args>
typename std::enable_if<internal::is_string<String>::value>::type print( typename std::enable_if<internal::is_string<String>::value>::type print(
const text_style &ts, const String &format_str, const text_style &ts, const String &format_str, const Args &... args) {
const Args &... args) {
return print(stdout, ts, format_str, args...); return print(stdout, ts, format_str, args...);
} }

View File

@ -89,8 +89,8 @@
#endif #endif
#endif #endif
#if FMT_HAS_FEATURE(cxx_explicit_conversions) || \ #if FMT_HAS_FEATURE(cxx_explicit_conversions) || FMT_GCC_VERSION >= 405 || \
FMT_GCC_VERSION >= 405 || FMT_MSC_VER >= 1800 FMT_MSC_VER >= 1800
#define FMT_USE_EXPLICIT 1 #define FMT_USE_EXPLICIT 1
#define FMT_EXPLICIT explicit #define FMT_EXPLICIT explicit
#else #else
@ -147,12 +147,19 @@
#if FMT_HAS_FEATURE(cxx_inline_namespaces) || FMT_GCC_VERSION >= 404 || \ #if FMT_HAS_FEATURE(cxx_inline_namespaces) || FMT_GCC_VERSION >= 404 || \
FMT_MSC_VER >= 1900 FMT_MSC_VER >= 1900
#define FMT_INLINE_NAMESPACE inline namespace #define FMT_INLINE_NAMESPACE inline namespace
# define FMT_END_NAMESPACE }} #define FMT_END_NAMESPACE \
} \
}
#else #else
#define FMT_INLINE_NAMESPACE namespace #define FMT_INLINE_NAMESPACE namespace
# define FMT_END_NAMESPACE } using namespace v5; } #define FMT_END_NAMESPACE \
} \
using namespace v5; \
}
#endif #endif
# define FMT_BEGIN_NAMESPACE namespace fmt { FMT_INLINE_NAMESPACE v5 { #define FMT_BEGIN_NAMESPACE \
namespace fmt { \
FMT_INLINE_NAMESPACE v5 {
#endif #endif
#if !defined(FMT_HEADER_ONLY) && defined(_WIN32) #if !defined(FMT_HEADER_ONLY) && defined(_WIN32)
@ -199,8 +206,8 @@ struct result_of;
template <typename F, typename... Args> template <typename F, typename... Args>
struct result_of<F(Args...)> { struct result_of<F(Args...)> {
// A workaround for gcc 4.4 that doesn't allow F to be a reference. // A workaround for gcc 4.4 that doesn't allow F to be a reference.
typedef typename std::result_of< typedef typename std::result_of<typename std::remove_reference<F>::type(
typename std::remove_reference<F>::type(Args...)>::type type; Args...)>::type type;
}; };
// Casts nonnegative integer to unsigned. // Casts nonnegative integer to unsigned.
@ -225,8 +232,10 @@ class basic_buffer {
// Don't initialize ptr_ since it is not accessed to save a few cycles. // Don't initialize ptr_ since it is not accessed to save a few cycles.
basic_buffer(std::size_t sz) FMT_NOEXCEPT : size_(sz), capacity_(sz) {} basic_buffer(std::size_t sz) FMT_NOEXCEPT : size_(sz), capacity_(sz) {}
basic_buffer(T *p = FMT_NULL, std::size_t sz = 0, std::size_t cap = 0) basic_buffer(T *p = FMT_NULL, std::size_t sz = 0,
FMT_NOEXCEPT: ptr_(p), size_(sz), capacity_(cap) {} std::size_t cap = 0) FMT_NOEXCEPT : ptr_(p),
size_(sz),
capacity_(cap) {}
/** Sets the buffer data and capacity. */ /** Sets the buffer data and capacity. */
void set(T *buf_data, std::size_t buf_capacity) FMT_NOEXCEPT { void set(T *buf_data, std::size_t buf_capacity) FMT_NOEXCEPT {
@ -360,7 +369,8 @@ class basic_string_view {
/** Constructs a string reference object from a C string and a size. */ /** Constructs a string reference object from a C string and a size. */
FMT_CONSTEXPR basic_string_view(const Char *s, size_t count) FMT_NOEXCEPT FMT_CONSTEXPR basic_string_view(const Char *s, size_t count) FMT_NOEXCEPT
: data_(s), size_(count) {} : data_(s),
size_(count) {}
/** /**
\rst \rst
@ -373,13 +383,14 @@ class basic_string_view {
/** Constructs a string reference from a ``std::basic_string`` object. */ /** Constructs a string reference from a ``std::basic_string`` object. */
template <typename Alloc> template <typename Alloc>
FMT_CONSTEXPR basic_string_view( FMT_CONSTEXPR basic_string_view(const std::basic_string<Char, Alloc> &s)
const std::basic_string<Char, Alloc> &s) FMT_NOEXCEPT FMT_NOEXCEPT : data_(s.data()),
: data_(s.data()), size_(s.size()) {} size_(s.size()) {}
#ifdef FMT_STRING_VIEW #ifdef FMT_STRING_VIEW
FMT_CONSTEXPR basic_string_view(FMT_STRING_VIEW<Char> s) FMT_NOEXCEPT FMT_CONSTEXPR basic_string_view(FMT_STRING_VIEW<Char> s) FMT_NOEXCEPT
: data_(s.data()), size_(s.size()) {} : data_(s.data()),
size_(s.size()) {}
#endif #endif
/** Returns a pointer to the string data. */ /** Returns a pointer to the string data. */
@ -451,20 +462,26 @@ typedef basic_string_view<wchar_t> wstring_view;
\endrst \endrst
*/ */
template <typename Char> template <typename Char>
inline basic_string_view<Char> inline basic_string_view<Char> to_string_view(basic_string_view<Char> s) {
to_string_view(basic_string_view<Char> s) { return s; } return s;
}
template <typename Char> template <typename Char>
inline basic_string_view<Char> inline basic_string_view<Char> to_string_view(
to_string_view(const std::basic_string<Char> &s) { return s; } const std::basic_string<Char> &s) {
return s;
}
template <typename Char> template <typename Char>
inline basic_string_view<Char> to_string_view(const Char *s) { return s; } inline basic_string_view<Char> to_string_view(const Char *s) {
return s;
}
#ifdef FMT_STRING_VIEW #ifdef FMT_STRING_VIEW
template <typename Char> template <typename Char>
inline basic_string_view<Char> inline basic_string_view<Char> to_string_view(FMT_STRING_VIEW<Char> s) {
to_string_view(FMT_STRING_VIEW<Char> s) { return s; } return s;
}
#endif #endif
// A base class for compile-time strings. It is defined in the fmt namespace to // A base class for compile-time strings. It is defined in the fmt namespace to
@ -474,11 +491,12 @@ struct compile_string {};
template <typename S> template <typename S>
struct is_compile_string : std::is_base_of<compile_string, S> {}; struct is_compile_string : std::is_base_of<compile_string, S> {};
template < template <typename S, typename Enable = typename std::enable_if<
typename S, is_compile_string<S>::value>::type>
typename Enable = typename std::enable_if<is_compile_string<S>::value>::type> FMT_CONSTEXPR basic_string_view<typename S::char_type> to_string_view(
FMT_CONSTEXPR basic_string_view<typename S::char_type> const S &s) {
to_string_view(const S &s) { return s; } return s;
}
template <typename Context> template <typename Context>
class basic_format_arg; class basic_format_arg;
@ -489,7 +507,8 @@ class basic_format_args;
// A formatter for objects of type T. // A formatter for objects of type T.
template <typename T, typename Char = char, typename Enable = void> template <typename T, typename Char = char, typename Enable = void>
struct formatter { struct formatter {
static_assert(internal::no_formatter_error<T>::value, static_assert(
internal::no_formatter_error<T>::value,
"don't know how to format the type, include fmt/ostream.h if it provides " "don't know how to format the type, include fmt/ostream.h if it provides "
"an operator<< that should be used"); "an operator<< that should be used");
@ -501,19 +520,25 @@ struct formatter {
}; };
template <typename T, typename Char, typename Enable = void> template <typename T, typename Char, typename Enable = void>
struct convert_to_int: std::integral_constant< struct convert_to_int
bool, !std::is_arithmetic<T>::value && std::is_convertible<T, int>::value> {}; : std::integral_constant<bool, !std::is_arithmetic<T>::value &&
std::is_convertible<T, int>::value> {};
namespace internal { namespace internal {
struct dummy_string_view { typedef void char_type; }; struct dummy_string_view {
typedef void char_type;
};
dummy_string_view to_string_view(...); dummy_string_view to_string_view(...);
using fmt::v5::to_string_view; using fmt::v5::to_string_view;
// Specifies whether S is a string type convertible to fmt::basic_string_view. // Specifies whether S is a string type convertible to fmt::basic_string_view.
template <typename S> template <typename S>
struct is_string : std::integral_constant<bool, !std::is_same< struct is_string
dummy_string_view, decltype(to_string_view(declval<S>()))>::value> {}; : std::integral_constant<
bool, !std::is_same<dummy_string_view,
decltype(to_string_view(declval<S>()))>::value> {
};
template <typename S> template <typename S>
struct char_t { struct char_t {
@ -528,13 +553,24 @@ template <typename T, typename Char>
struct named_arg; struct named_arg;
enum type { enum type {
none_type, named_arg_type, none_type,
named_arg_type,
// Integer types should go first, // Integer types should go first,
int_type, uint_type, long_long_type, ulong_long_type, bool_type, char_type, int_type,
uint_type,
long_long_type,
ulong_long_type,
bool_type,
char_type,
last_integer_type = char_type, last_integer_type = char_type,
// followed by floating-point types. // followed by floating-point types.
double_type, long_double_type, last_numeric_type = long_double_type, double_type,
cstring_type, string_type, pointer_type, custom_type long_double_type,
last_numeric_type = long_double_type,
cstring_type,
string_type,
pointer_type,
custom_type
}; };
FMT_CONSTEXPR bool is_integral(type t) { FMT_CONSTEXPR bool is_integral(type t) {
@ -647,7 +683,9 @@ FMT_CONSTEXPR basic_format_arg<Context> make_arg(const T &value);
#define FMT_MAKE_VALUE_SAME(TAG, Type) \ #define FMT_MAKE_VALUE_SAME(TAG, Type) \
template <typename C> \ template <typename C> \
FMT_CONSTEXPR init<C, Type, TAG> make_value(Type val) { return val; } FMT_CONSTEXPR init<C, Type, TAG> make_value(Type val) { \
return val; \
}
FMT_MAKE_VALUE(bool_type, bool, int) FMT_MAKE_VALUE(bool_type, bool, int)
FMT_MAKE_VALUE(int_type, short, int) FMT_MAKE_VALUE(int_type, short, int)
@ -659,12 +697,12 @@ FMT_MAKE_VALUE_SAME(uint_type, unsigned)
// either to int or to long long depending on its size. // either to int or to long long depending on its size.
typedef std::conditional<sizeof(long) == sizeof(int), int, long long>::type typedef std::conditional<sizeof(long) == sizeof(int), int, long long>::type
long_type; long_type;
FMT_MAKE_VALUE( FMT_MAKE_VALUE((sizeof(long) == sizeof(int) ? int_type : long_long_type), long,
(sizeof(long) == sizeof(int) ? int_type : long_long_type), long, long_type) long_type)
typedef std::conditional<sizeof(unsigned long) == sizeof(unsigned), typedef std::conditional<sizeof(unsigned long) == sizeof(unsigned), unsigned,
unsigned, unsigned long long>::type ulong_type; unsigned long long>::type ulong_type;
FMT_MAKE_VALUE( FMT_MAKE_VALUE((sizeof(unsigned long) == sizeof(unsigned) ? uint_type
(sizeof(unsigned long) == sizeof(unsigned) ? uint_type : ulong_long_type), : ulong_long_type),
unsigned long, ulong_type) unsigned long, ulong_type)
FMT_MAKE_VALUE_SAME(long_long_type, long long) FMT_MAKE_VALUE_SAME(long_long_type, long long)
@ -674,14 +712,20 @@ FMT_MAKE_VALUE(uint_type, unsigned char, unsigned)
// This doesn't use FMT_MAKE_VALUE because of ambiguity in gcc 4.4. // This doesn't use FMT_MAKE_VALUE because of ambiguity in gcc 4.4.
template <typename C, typename Char> template <typename C, typename Char>
FMT_CONSTEXPR typename std::enable_if< FMT_CONSTEXPR
std::is_same<typename C::char_type, Char>::value, typename std::enable_if<std::is_same<typename C::char_type, Char>::value,
init<C, int, char_type>>::type make_value(Char val) { return val; } init<C, int, char_type>>::type
make_value(Char val) {
return val;
}
template <typename C> template <typename C>
FMT_CONSTEXPR typename std::enable_if< FMT_CONSTEXPR
!std::is_same<typename C::char_type, char>::value, typename std::enable_if<!std::is_same<typename C::char_type, char>::value,
init<C, int, char_type>>::type make_value(char val) { return val; } init<C, int, char_type>>::type
make_value(char val) {
return val;
}
FMT_MAKE_VALUE(double_type, float, double) FMT_MAKE_VALUE(double_type, float, double)
FMT_MAKE_VALUE_SAME(double_type, double) FMT_MAKE_VALUE_SAME(double_type, double)
@ -722,17 +766,22 @@ typename std::enable_if<!std::is_same<T, typename C::char_type>::value>::type
} }
template <typename C, typename T> template <typename C, typename T>
inline typename std::enable_if< inline
std::is_enum<T>::value && convert_to_int<T, typename C::char_type>::value, typename std::enable_if<std::is_enum<T>::value &&
convert_to_int<T, typename C::char_type>::value,
init<C, int, int_type>>::type init<C, int, int_type>>::type
make_value(const T &val) { return static_cast<int>(val); } make_value(const T &val) {
return static_cast<int>(val);
}
template <typename C, typename T, typename Char = typename C::char_type> template <typename C, typename T, typename Char = typename C::char_type>
inline typename std::enable_if< inline typename std::enable_if<
is_constructible<basic_string_view<Char>, T>::value && is_constructible<basic_string_view<Char>, T>::value &&
!internal::is_string<T>::value, !internal::is_string<T>::value,
init<C, basic_string_view<Char>, string_type>>::type init<C, basic_string_view<Char>, string_type>>::type
make_value(const T &val) { return basic_string_view<Char>(val); } make_value(const T &val) {
return basic_string_view<Char>(val);
}
template <typename C, typename T, typename Char = typename C::char_type> template <typename C, typename T, typename Char = typename C::char_type>
inline typename std::enable_if< inline typename std::enable_if<
@ -743,11 +792,13 @@ inline typename std::enable_if<
// Implicit conversion to std::string is not handled here because it's // Implicit conversion to std::string is not handled here because it's
// unsafe: https://github.com/fmtlib/fmt/issues/729 // unsafe: https://github.com/fmtlib/fmt/issues/729
init<C, const T &, custom_type>>::type init<C, const T &, custom_type>>::type
make_value(const T &val) { return val; } make_value(const T &val) {
return val;
}
template <typename C, typename T> template <typename C, typename T>
init<C, const void*, named_arg_type> init<C, const void *, named_arg_type> make_value(
make_value(const named_arg<T, typename C::char_type> &val) { const named_arg<T, typename C::char_type> &val) {
basic_format_arg<C> arg = make_arg<C>(val.value); basic_format_arg<C> arg = make_arg<C>(val.value);
std::memcpy(val.data, &arg, sizeof(arg)); std::memcpy(val.data, &arg, sizeof(arg));
return static_cast<const void *>(&val); return static_cast<const void *>(&val);
@ -759,8 +810,8 @@ FMT_CONSTEXPR11 typename std::enable_if<
init<C, basic_string_view<typename C::char_type>, string_type>>::type init<C, basic_string_view<typename C::char_type>, string_type>>::type
make_value(const S &val) { make_value(const S &val) {
// Handle adapted strings. // Handle adapted strings.
static_assert(std::is_same< static_assert(std::is_same<typename C::char_type,
typename C::char_type, typename internal::char_t<S>::type>::value, typename internal::char_t<S>::type>::value,
"mismatch between char-types of context and argument"); "mismatch between char-types of context and argument");
return to_string_view(val); return to_string_view(val);
} }
@ -782,8 +833,8 @@ class basic_format_arg {
internal::type type_; internal::type type_;
template <typename ContextType, typename T> template <typename ContextType, typename T>
friend FMT_CONSTEXPR basic_format_arg<ContextType> friend FMT_CONSTEXPR basic_format_arg<ContextType> internal::make_arg(
internal::make_arg(const T &value); const T &value);
template <typename Visitor, typename Ctx> template <typename Visitor, typename Ctx>
friend FMT_CONSTEXPR typename internal::result_of<Visitor(int)>::type friend FMT_CONSTEXPR typename internal::result_of<Visitor(int)>::type
@ -827,8 +878,8 @@ struct monostate {};
\endrst \endrst
*/ */
template <typename Visitor, typename Context> template <typename Visitor, typename Context>
FMT_CONSTEXPR typename internal::result_of<Visitor(int)>::type FMT_CONSTEXPR typename internal::result_of<Visitor(int)>::type visit_format_arg(
visit_format_arg(Visitor &&vis, const basic_format_arg<Context> &arg) { Visitor &&vis, const basic_format_arg<Context> &arg) {
typedef typename Context::char_type char_type; typedef typename Context::char_type char_type;
switch (arg.type_) { switch (arg.type_) {
case internal::none_type: case internal::none_type:
@ -855,8 +906,8 @@ FMT_CONSTEXPR typename internal::result_of<Visitor(int)>::type
case internal::cstring_type: case internal::cstring_type:
return vis(arg.value_.string.value); return vis(arg.value_.string.value);
case internal::string_type: case internal::string_type:
return vis(basic_string_view<char_type>( return vis(basic_string_view<char_type>(arg.value_.string.value,
arg.value_.string.value, arg.value_.string.size)); arg.value_.string.size));
case internal::pointer_type: case internal::pointer_type:
return vis(arg.value_.pointer); return vis(arg.value_.pointer);
case internal::custom_type: case internal::custom_type:
@ -866,8 +917,8 @@ FMT_CONSTEXPR typename internal::result_of<Visitor(int)>::type
} }
template <typename Visitor, typename Context> template <typename Visitor, typename Context>
FMT_CONSTEXPR typename internal::result_of<Visitor(int)>::type FMT_CONSTEXPR typename internal::result_of<Visitor(int)>::type visit(
visit(Visitor &&vis, const basic_format_arg<Context> &arg) { Visitor &&vis, const basic_format_arg<Context> &arg) {
return visit_format_arg(std::forward<Visitor>(vis), arg); return visit_format_arg(std::forward<Visitor>(vis), arg);
} }
@ -883,8 +934,8 @@ class basic_parse_context : private ErrorHandler {
typedef Char char_type; typedef Char char_type;
typedef typename basic_string_view<Char>::iterator iterator; typedef typename basic_string_view<Char>::iterator iterator;
explicit FMT_CONSTEXPR basic_parse_context( explicit FMT_CONSTEXPR basic_parse_context(basic_string_view<Char> format_str,
basic_string_view<Char> format_str, ErrorHandler eh = ErrorHandler()) ErrorHandler eh = ErrorHandler())
: ErrorHandler(eh), format_str_(format_str), next_arg_id_(0) {} : ErrorHandler(eh), format_str_(format_str), next_arg_id_(0) {}
// Returns an iterator to the beginning of the format string range being // Returns an iterator to the beginning of the format string range being
@ -1014,8 +1065,8 @@ class context_base {
// Checks if manual indexing is used and returns the argument with // Checks if manual indexing is used and returns the argument with
// specified index. // specified index.
format_arg get_arg(unsigned arg_id) { format_arg get_arg(unsigned arg_id) {
return this->parse_context().check_arg_id(arg_id) ? return this->parse_context().check_arg_id(arg_id) ? this->do_get_arg(arg_id)
this->do_get_arg(arg_id) : format_arg(); : format_arg();
} }
public: public:
@ -1047,7 +1098,9 @@ struct get_type {
}; };
template <typename Context> template <typename Context>
FMT_CONSTEXPR11 unsigned long long get_types() { return 0; } FMT_CONSTEXPR11 unsigned long long get_types() {
return 0;
}
template <typename Context, typename Arg, typename... Args> template <typename Context, typename Arg, typename... Args>
FMT_CONSTEXPR11 unsigned long long get_types() { FMT_CONSTEXPR11 unsigned long long get_types() {
@ -1063,8 +1116,8 @@ FMT_CONSTEXPR basic_format_arg<Context> make_arg(const T &value) {
} }
template <bool IS_PACKED, typename Context, typename T> template <bool IS_PACKED, typename Context, typename T>
inline typename std::enable_if<IS_PACKED, value<Context>>::type inline typename std::enable_if<IS_PACKED, value<Context>>::type make_arg(
make_arg(const T &value) { const T &value) {
return make_value<Context>(value); return make_value<Context>(value);
} }
@ -1077,8 +1130,8 @@ inline typename std::enable_if<!IS_PACKED, basic_format_arg<Context>>::type
// Formatting context. // Formatting context.
template <typename OutputIt, typename Char> template <typename OutputIt, typename Char>
class basic_format_context : class basic_format_context
public internal::context_base< : public internal::context_base<
OutputIt, basic_format_context<OutputIt, Char>, Char> { OutputIt, basic_format_context<OutputIt, Char>, Char> {
public: public:
/** The character type for the output. */ /** The character type for the output. */
@ -1086,7 +1139,9 @@ class basic_format_context :
// using formatter_type = formatter<T, char_type>; // using formatter_type = formatter<T, char_type>;
template <typename T> template <typename T>
struct formatter_type { typedef formatter<T, char_type> type; }; struct formatter_type {
typedef formatter<T, char_type> type;
};
private: private:
internal::arg_map<basic_format_context> map_; internal::arg_map<basic_format_context> map_;
@ -1123,7 +1178,8 @@ class basic_format_context :
template <typename Char> template <typename Char>
struct buffer_context { struct buffer_context {
typedef basic_format_context< typedef basic_format_context<
std::back_insert_iterator<internal::basic_buffer<Char>>, Char> type; std::back_insert_iterator<internal::basic_buffer<Char>>, Char>
type;
}; };
typedef buffer_context<char>::type format_context; typedef buffer_context<char>::type format_context;
typedef buffer_context<wchar_t>::type wformat_context; typedef buffer_context<wchar_t>::type wformat_context;
@ -1143,8 +1199,8 @@ class format_arg_store {
// Packed is a macro on MinGW so use IS_PACKED instead. // Packed is a macro on MinGW so use IS_PACKED instead.
static const bool IS_PACKED = NUM_ARGS < internal::max_packed_args; static const bool IS_PACKED = NUM_ARGS < internal::max_packed_args;
typedef typename std::conditional<IS_PACKED, typedef typename std::conditional<IS_PACKED, internal::value<Context>,
internal::value<Context>, basic_format_arg<Context>>::type value_type; basic_format_arg<Context>>::type value_type;
// If the arguments are not packed, add one more element to mark the end. // If the arguments are not packed, add one more element to mark the end.
static const size_t DATA_SIZE = static const size_t DATA_SIZE =
@ -1154,9 +1210,8 @@ class format_arg_store {
friend class basic_format_args<Context>; friend class basic_format_args<Context>;
static FMT_CONSTEXPR11 unsigned long long get_types() { static FMT_CONSTEXPR11 unsigned long long get_types() {
return IS_PACKED ? return IS_PACKED ? internal::get_types<Context, Args...>()
internal::get_types<Context, Args...>() : : internal::is_unpacked_bit | NUM_ARGS;
internal::is_unpacked_bit | NUM_ARGS;
} }
public: public:
@ -1170,8 +1225,8 @@ class format_arg_store {
(FMT_MSC_VER && FMT_MSC_VER <= 1800) (FMT_MSC_VER && FMT_MSC_VER <= 1800)
// Workaround array initialization issues in gcc <= 4.5 and MSVC <= 2013. // Workaround array initialization issues in gcc <= 4.5 and MSVC <= 2013.
format_arg_store(const Args &... args) { format_arg_store(const Args &... args) {
value_type init[DATA_SIZE] = value_type init[DATA_SIZE] = {
{internal::make_arg<IS_PACKED, Context>(args)...}; internal::make_arg<IS_PACKED, Context>(args)...};
std::memcpy(data_, init, sizeof(init)); std::memcpy(data_, init, sizeof(init));
} }
#else #else
@ -1194,8 +1249,10 @@ const unsigned long long format_arg_store<Context, Args...>::TYPES =
\endrst \endrst
*/ */
template <typename Context = format_context, typename... Args> template <typename Context = format_context, typename... Args>
inline format_arg_store<Context, Args...> inline format_arg_store<Context, Args...> make_format_args(
make_format_args(const Args &... args) { return {args...}; } const Args &... args) {
return {args...};
}
/** Formatting arguments. */ /** Formatting arguments. */
template <typename Context> template <typename Context>
@ -1222,8 +1279,8 @@ class basic_format_args {
typename internal::type type(unsigned index) const { typename internal::type type(unsigned index) const {
unsigned shift = index * 4; unsigned shift = index * 4;
return static_cast<typename internal::type>( return static_cast<typename internal::type>((types_ & (0xfull << shift)) >>
(types_ & (0xfull << shift)) >> shift); shift);
} }
friend class internal::arg_map<Context>; friend class internal::arg_map<Context>;
@ -1309,13 +1366,13 @@ struct wformat_args : basic_format_args<wformat_context> {
#if FMT_USE_ALIAS_TEMPLATES #if FMT_USE_ALIAS_TEMPLATES
/** String's character type. */ /** String's character type. */
template <typename S> template <typename S>
using char_t = FMT_ENABLE_IF_T( using char_t = FMT_ENABLE_IF_T(internal::is_string<S>::value,
internal::is_string<S>::value, typename internal::char_t<S>::type); typename internal::char_t<S>::type);
#define FMT_CHAR(S) fmt::char_t<S> #define FMT_CHAR(S) fmt::char_t<S>
#else #else
template <typename S> template <typename S>
struct char_t : std::enable_if< struct char_t : std::enable_if<internal::is_string<S>::value,
internal::is_string<S>::value, typename internal::char_t<S>::type> {}; typename internal::char_t<S>::type> {};
#define FMT_CHAR(S) typename char_t<S>::type #define FMT_CHAR(S) typename char_t<S>::type
#endif #endif
@ -1325,8 +1382,8 @@ struct named_arg_base {
basic_string_view<Char> name; basic_string_view<Char> name;
// Serialized value<context>. // Serialized value<context>.
mutable char data[ mutable char
sizeof(basic_format_arg<typename buffer_context<Char>::type>)]; data[sizeof(basic_format_arg<typename buffer_context<Char>::type>)];
named_arg_base(basic_string_view<Char> nm) : name(nm) {} named_arg_base(basic_string_view<Char> nm) : name(nm) {}
@ -1350,16 +1407,16 @@ template <typename... Args, typename S>
inline typename std::enable_if<!is_compile_string<S>::value>::type inline typename std::enable_if<!is_compile_string<S>::value>::type
check_format_string(const S &) {} check_format_string(const S &) {}
template <typename... Args, typename S> template <typename... Args, typename S>
typename std::enable_if<is_compile_string<S>::value>::type typename std::enable_if<is_compile_string<S>::value>::type check_format_string(
check_format_string(S); S);
template <typename S, typename... Args> template <typename S, typename... Args>
struct checked_args : format_arg_store< struct checked_args
typename buffer_context<FMT_CHAR(S)>::type, Args...> { : format_arg_store<typename buffer_context<FMT_CHAR(S)>::type, Args...> {
typedef typename buffer_context<FMT_CHAR(S)>::type context; typedef typename buffer_context<FMT_CHAR(S)>::type context;
checked_args(const S &format_str, const Args &... args): checked_args(const S &format_str, const Args &... args)
format_arg_store<context, Args...>(args...) { : format_arg_store<context, Args...>(args...) {
internal::check_format_string<Args...>(format_str); internal::check_format_string<Args...>(format_str);
} }
@ -1375,7 +1432,7 @@ template <typename Char>
typename buffer_context<Char>::type::iterator vformat_to( typename buffer_context<Char>::type::iterator vformat_to(
internal::basic_buffer<Char> &buf, basic_string_view<Char> format_str, internal::basic_buffer<Char> &buf, basic_string_view<Char> format_str,
basic_format_args<typename buffer_context<Char>::type> args); basic_format_args<typename buffer_context<Char>::type> args);
} } // namespace internal
/** /**
\rst \rst
@ -1411,11 +1468,9 @@ struct is_contiguous<internal::basic_buffer<Char> >: std::true_type {};
/** Formats a string and writes the output to ``out``. */ /** Formats a string and writes the output to ``out``. */
template <typename Container, typename S> template <typename Container, typename S>
typename std::enable_if< typename std::enable_if<is_contiguous<Container>::value,
is_contiguous<Container>::value, std::back_insert_iterator<Container>>::type std::back_insert_iterator<Container>>::type
vformat_to( vformat_to(std::back_insert_iterator<Container> out, const S &format_str,
std::back_insert_iterator<Container> out,
const S &format_str,
basic_format_args<typename buffer_context<FMT_CHAR(S)>::type> args) { basic_format_args<typename buffer_context<FMT_CHAR(S)>::type> args) {
internal::container_buffer<Container> buf(internal::get_container(out)); internal::container_buffer<Container> buf(internal::get_container(out));
internal::vformat_to(buf, to_string_view(format_str), args); internal::vformat_to(buf, to_string_view(format_str), args);
@ -1423,8 +1478,8 @@ typename std::enable_if<
} }
template <typename Container, typename S, typename... Args> template <typename Container, typename S, typename... Args>
inline typename std::enable_if< inline typename std::enable_if<is_contiguous<Container>::value &&
is_contiguous<Container>::value && internal::is_string<S>::value, internal::is_string<S>::value,
std::back_insert_iterator<Container>>::type std::back_insert_iterator<Container>>::type
format_to(std::back_insert_iterator<Container> out, const S &format_str, format_to(std::back_insert_iterator<Container> out, const S &format_str,
const Args &... args) { const Args &... args) {
@ -1450,8 +1505,8 @@ inline std::basic_string<Char> vformat(
\endrst \endrst
*/ */
template <typename S, typename... Args> template <typename S, typename... Args>
inline std::basic_string<FMT_CHAR(S)> format( inline std::basic_string<FMT_CHAR(S)> format(const S &format_str,
const S &format_str, const Args &... args) { const Args &... args) {
return internal::vformat( return internal::vformat(
to_string_view(format_str), to_string_view(format_str),
*internal::checked_args<S, Args...>(format_str, args...)); *internal::checked_args<S, Args...>(format_str, args...));

View File

@ -10,14 +10,13 @@
#include "format.h" #include "format.h"
#include <string.h>
#include <cctype> #include <cctype>
#include <cerrno> #include <cerrno>
#include <climits> #include <climits>
#include <cmath> #include <cmath>
#include <cstdarg> #include <cstdarg>
#include <cstddef> // for std::ptrdiff_t #include <cstddef> // for std::ptrdiff_t
#include <cstring>
#include <cstring> // for std::memmove #include <cstring> // for std::memmove
#if !defined(FMT_STATIC_THOUSANDS_SEPARATOR) #if !defined(FMT_STATIC_THOUSANDS_SEPARATOR)
#include <locale> #include <locale>
@ -96,8 +95,8 @@ typedef void (*FormatFunc)(internal::buffer &, int, string_view);
// ERANGE - buffer is not large enough to store the error message // ERANGE - buffer is not large enough to store the error message
// other - failure // other - failure
// Buffer should be at least of size 1. // Buffer should be at least of size 1.
int safe_strerror( int safe_strerror(int error_code, char *&buffer,
int error_code, char *&buffer, std::size_t buffer_size) FMT_NOEXCEPT { std::size_t buffer_size) FMT_NOEXCEPT {
FMT_ASSERT(buffer != FMT_NULL && buffer_size != 0, "invalid buffer"); FMT_ASSERT(buffer != FMT_NULL && buffer_size != 0, "invalid buffer");
class dispatcher { class dispatcher {
@ -132,8 +131,8 @@ int safe_strerror(
// Fallback to strerror_s when strerror_r is not available. // Fallback to strerror_s when strerror_r is not available.
int fallback(int result) { int fallback(int result) {
// If the buffer is full then the message is probably truncated. // If the buffer is full then the message is probably truncated.
return result == 0 && strlen(buffer_) == buffer_size_ - 1 ? return result == 0 && strlen(buffer_) == buffer_size_ - 1 ? ERANGE
ERANGE : result; : result;
} }
#if !FMT_MSC_VER #if !FMT_MSC_VER
@ -149,9 +148,7 @@ int safe_strerror(
dispatcher(int err_code, char *&buf, std::size_t buf_size) dispatcher(int err_code, char *&buf, std::size_t buf_size)
: error_code_(err_code), buffer_(buf), buffer_size_(buf_size) {} : error_code_(err_code), buffer_(buf), buffer_size_(buf_size) {}
int run() { int run() { return handle(strerror_r(error_code_, buffer_, buffer_size_)); }
return handle(strerror_r(error_code_, buffer_, buffer_size_));
}
}; };
return dispatcher(error_code, buffer, buffer_size).run(); return dispatcher(error_code, buffer, buffer_size).run();
} }
@ -220,10 +217,10 @@ Locale locale_ref::get() const {
template <typename Char> template <typename Char>
FMT_FUNC Char thousands_sep_impl(locale_ref loc) { FMT_FUNC Char thousands_sep_impl(locale_ref loc) {
return std::use_facet<std::numpunct<Char> >( return std::use_facet<std::numpunct<Char>>(loc.get<std::locale>())
loc.get<std::locale>()).thousands_sep(); .thousands_sep();
}
} }
} // namespace internal
#else #else
template <typename Char> template <typename Char>
FMT_FUNC Char internal::thousands_sep_impl(locale_ref) { FMT_FUNC Char internal::thousands_sep_impl(locale_ref) {
@ -231,8 +228,8 @@ FMT_FUNC Char internal::thousands_sep_impl(locale_ref) {
} }
#endif #endif
FMT_FUNC void system_error::init( FMT_FUNC void system_error::init(int err_code, string_view format_str,
int err_code, string_view format_str, format_args args) { format_args args) {
error_code_ = err_code; error_code_ = err_code;
memory_buffer buffer; memory_buffer buffer;
format_system_error(buffer, err_code, vformat(format_str, args)); format_system_error(buffer, err_code, vformat(format_str, args));
@ -242,20 +239,19 @@ FMT_FUNC void system_error::init(
namespace internal { namespace internal {
template <typename T> template <typename T>
int char_traits<char>::format_float( int char_traits<char>::format_float(char *buf, std::size_t size,
char *buf, std::size_t size, const char *format, int precision, T value) { const char *format, int precision,
return precision < 0 ? T value) {
FMT_SNPRINTF(buf, size, format, value) : return precision < 0 ? FMT_SNPRINTF(buf, size, format, value)
FMT_SNPRINTF(buf, size, format, precision, value); : FMT_SNPRINTF(buf, size, format, precision, value);
} }
template <typename T> template <typename T>
int char_traits<wchar_t>::format_float( int char_traits<wchar_t>::format_float(wchar_t *buf, std::size_t size,
wchar_t *buf, std::size_t size, const wchar_t *format, int precision, const wchar_t *format, int precision,
T value) { T value) {
return precision < 0 ? return precision < 0 ? FMT_SWPRINTF(buf, size, format, value)
FMT_SWPRINTF(buf, size, format, value) : : FMT_SWPRINTF(buf, size, format, precision, value);
FMT_SWPRINTF(buf, size, format, precision, value);
} }
template <typename T> template <typename T>
@ -267,33 +263,21 @@ const char basic_data<T>::DIGITS[] =
"8081828384858687888990919293949596979899"; "8081828384858687888990919293949596979899";
#define FMT_POWERS_OF_10(factor) \ #define FMT_POWERS_OF_10(factor) \
factor * 10, \ factor * 10, factor * 100, factor * 1000, factor * 10000, factor * 100000, \
factor * 100, \ factor * 1000000, factor * 10000000, factor * 100000000, \
factor * 1000, \
factor * 10000, \
factor * 100000, \
factor * 1000000, \
factor * 10000000, \
factor * 100000000, \
factor * 1000000000 factor * 1000000000
template <typename T> template <typename T>
const uint32_t basic_data<T>::POWERS_OF_10_32[] = { const uint32_t basic_data<T>::POWERS_OF_10_32[] = {1, FMT_POWERS_OF_10(1)};
1, FMT_POWERS_OF_10(1)
};
template <typename T> template <typename T>
const uint32_t basic_data<T>::ZERO_OR_POWERS_OF_10_32[] = { const uint32_t basic_data<T>::ZERO_OR_POWERS_OF_10_32[] = {0,
0, FMT_POWERS_OF_10(1) FMT_POWERS_OF_10(1)};
};
template <typename T> template <typename T>
const uint64_t basic_data<T>::ZERO_OR_POWERS_OF_10_64[] = { const uint64_t basic_data<T>::ZERO_OR_POWERS_OF_10_64[] = {
0, 0, FMT_POWERS_OF_10(1), FMT_POWERS_OF_10(1000000000ull),
FMT_POWERS_OF_10(1), 10000000000000000000ull};
FMT_POWERS_OF_10(1000000000ull),
10000000000000000000ull
};
// Normalized 64-bit significands of pow(10, k), for k = -348, -340, ..., 340. // Normalized 64-bit significands of pow(10, k), for k = -348, -340, ..., 340.
// These are generated by support/compute-powers.py. // These are generated by support/compute-powers.py.
@ -341,13 +325,16 @@ const int16_t basic_data<T>::POW10_EXPONENTS[] = {
-50, -24, 3, 30, 56, 83, 109, 136, 162, 189, 216, -50, -24, 3, 30, 56, 83, 109, 136, 162, 189, 216,
242, 269, 295, 322, 348, 375, 402, 428, 455, 481, 508, 242, 269, 295, 322, 348, 375, 402, 428, 455, 481, 508,
534, 561, 588, 614, 641, 667, 694, 720, 747, 774, 800, 534, 561, 588, 614, 641, 667, 694, 720, 747, 774, 800,
827, 853, 880, 907, 933, 960, 986, 1013, 1039, 1066 827, 853, 880, 907, 933, 960, 986, 1013, 1039, 1066};
};
template <typename T> const char basic_data<T>::FOREGROUND_COLOR[] = "\x1b[38;2;"; template <typename T>
template <typename T> const char basic_data<T>::BACKGROUND_COLOR[] = "\x1b[48;2;"; const char basic_data<T>::FOREGROUND_COLOR[] = "\x1b[38;2;";
template <typename T> const char basic_data<T>::RESET_COLOR[] = "\x1b[0m"; template <typename T>
template <typename T> const wchar_t basic_data<T>::WRESET_COLOR[] = L"\x1b[0m"; const char basic_data<T>::BACKGROUND_COLOR[] = "\x1b[48;2;";
template <typename T>
const char basic_data<T>::RESET_COLOR[] = "\x1b[0m";
template <typename T>
const wchar_t basic_data<T>::WRESET_COLOR[] = L"\x1b[0m";
// A handmade floating-point number f * pow(2, e). // A handmade floating-point number f * pow(2, e).
class fp { class fp {
@ -416,8 +403,8 @@ class fp {
// (lower) or successor (upper). The upper boundary is normalized and lower // (lower) or successor (upper). The upper boundary is normalized and lower
// has the same exponent but may be not normalized. // has the same exponent but may be not normalized.
void compute_boundaries(fp &lower, fp &upper) const { void compute_boundaries(fp &lower, fp &upper) const {
lower = f == implicit_bit ? lower =
fp((f << 2) - 1, e - 2) : fp((f << 1) - 1, e - 1); f == implicit_bit ? fp((f << 2) - 1, e - 2) : fp((f << 1) - 1, e - 1);
upper = fp((f << 1) + 1, e - 1); upper = fp((f << 1) + 1, e - 1);
upper.normalize<1>(); // 1 is to account for the exponent shift above. upper.normalize<1>(); // 1 is to account for the exponent shift above.
lower.f <<= lower.e - upper.e; lower.f <<= lower.e - upper.e;
@ -432,7 +419,8 @@ inline fp operator-(fp x, fp y) {
} }
// Computes an fp number r with r.f = x.f * y.f / pow(2, 64) rounded to nearest // Computes an fp number r with r.f = x.f * y.f / pow(2, 64) rounded to nearest
// with half-up tie breaking, r.e = x.e + y.e + 64. Result may not be normalized. // with half-up tie breaking, r.e = x.e + y.e + 64. Result may not be
// normalized.
FMT_API fp operator*(fp x, fp y); FMT_API fp operator*(fp x, fp y);
// Returns cached power (of 10) c_k = c_k.f * pow(2, c_k.e) such that its // Returns cached power (of 10) c_k = c_k.f * pow(2, c_k.e) such that its
@ -452,8 +440,8 @@ FMT_FUNC fp operator*(fp x, fp y) {
FMT_FUNC fp get_cached_power(int min_exponent, int &pow10_exponent) { FMT_FUNC fp get_cached_power(int min_exponent, int &pow10_exponent) {
const double one_over_log2_10 = 0.30102999566398114; // 1 / log2(10) const double one_over_log2_10 = 0.30102999566398114; // 1 / log2(10)
int index = static_cast<int>(std::ceil( int index = static_cast<int>(
(min_exponent + fp::significand_size - 1) * one_over_log2_10)); std::ceil((min_exponent + fp::significand_size - 1) * one_over_log2_10));
// Decimal exponent of the first (smallest) cached power of 10. // Decimal exponent of the first (smallest) cached power of 10.
const int first_dec_exp = -348; const int first_dec_exp = -348;
// Difference between 2 consecutive decimal exponents in cached powers of 10. // Difference between 2 consecutive decimal exponents in cached powers of 10.
@ -463,10 +451,11 @@ FMT_FUNC fp get_cached_power(int min_exponent, int &pow10_exponent) {
return fp(data::POW10_SIGNIFICANDS[index], data::POW10_EXPONENTS[index]); return fp(data::POW10_SIGNIFICANDS[index], data::POW10_EXPONENTS[index]);
} }
FMT_FUNC bool grisu2_round( FMT_FUNC bool grisu2_round(char *buf, ptrdiff_t &size, size_t max_digits,
char *buf, ptrdiff_t &size, size_t max_digits, uint64_t delta, uint64_t delta, uint64_t remainder, uint64_t exp,
uint64_t remainder, uint64_t exp, uint64_t diff, int &exp10) { uint64_t diff, int &exp10) {
while (remainder < diff && delta - remainder >= exp && while (
remainder < diff && delta - remainder >= exp &&
(remainder + exp < diff || diff - remainder > remainder + exp - diff)) { (remainder + exp < diff || diff - remainder > remainder + exp - diff)) {
--buf[size - 1]; --buf[size - 1];
remainder += exp; remainder += exp;
@ -481,25 +470,56 @@ FMT_FUNC bool grisu2_round(
} }
// Generates output using Grisu2 digit-gen algorithm. // Generates output using Grisu2 digit-gen algorithm.
FMT_FUNC bool grisu2_gen_digits( FMT_FUNC bool grisu2_gen_digits(char *buf, ptrdiff_t &size, uint32_t hi,
char *buf, ptrdiff_t &size, uint32_t hi, uint64_t lo, int &exp, uint64_t lo, int &exp, uint64_t delta,
uint64_t delta, const fp &one, const fp &diff, size_t max_digits) { const fp &one, const fp &diff,
size_t max_digits) {
// Generate digits for the most significant part (hi). // Generate digits for the most significant part (hi).
while (exp > 0) { while (exp > 0) {
uint32_t digit = 0; uint32_t digit = 0;
// This optimization by miloyip reduces the number of integer divisions by // This optimization by miloyip reduces the number of integer divisions by
// one per iteration. // one per iteration.
switch (exp) { switch (exp) {
case 10: digit = hi / 1000000000; hi %= 1000000000; break; case 10:
case 9: digit = hi / 100000000; hi %= 100000000; break; digit = hi / 1000000000;
case 8: digit = hi / 10000000; hi %= 10000000; break; hi %= 1000000000;
case 7: digit = hi / 1000000; hi %= 1000000; break; break;
case 6: digit = hi / 100000; hi %= 100000; break; case 9:
case 5: digit = hi / 10000; hi %= 10000; break; digit = hi / 100000000;
case 4: digit = hi / 1000; hi %= 1000; break; hi %= 100000000;
case 3: digit = hi / 100; hi %= 100; break; break;
case 2: digit = hi / 10; hi %= 10; break; case 8:
case 1: digit = hi; hi = 0; break; digit = hi / 10000000;
hi %= 10000000;
break;
case 7:
digit = hi / 1000000;
hi %= 1000000;
break;
case 6:
digit = hi / 100000;
hi %= 100000;
break;
case 5:
digit = hi / 10000;
hi %= 10000;
break;
case 4:
digit = hi / 1000;
hi %= 1000;
break;
case 3:
digit = hi / 100;
hi %= 100;
break;
case 2:
digit = hi / 10;
hi %= 10;
break;
case 1:
digit = hi;
hi = 0;
break;
default: default:
FMT_ASSERT(false, "invalid number of digits"); FMT_ASSERT(false, "invalid number of digits");
} }
@ -510,8 +530,8 @@ FMT_FUNC bool grisu2_gen_digits(
if (remainder <= delta || size > static_cast<ptrdiff_t>(max_digits)) { if (remainder <= delta || size > static_cast<ptrdiff_t>(max_digits)) {
return grisu2_round( return grisu2_round(
buf, size, max_digits, delta, remainder, buf, size, max_digits, delta, remainder,
static_cast<uint64_t>(data::POWERS_OF_10_32[exp]) << -one.e, static_cast<uint64_t>(data::POWERS_OF_10_32[exp]) << -one.e, diff.f,
diff.f, exp); exp);
} }
} }
// Generate digits for the least significant part (lo). // Generate digits for the least significant part (lo).
@ -616,8 +636,8 @@ struct fill {
// The number is given as v = f * pow(10, exp), where f has size digits. // The number is given as v = f * pow(10, exp), where f has size digits.
template <typename Handler> template <typename Handler>
FMT_FUNC void grisu2_prettify(const gen_digits_params &params, FMT_FUNC void grisu2_prettify(const gen_digits_params &params, int size,
int size, int exp, Handler &&handler) { int exp, Handler &&handler) {
if (!params.fixed) { if (!params.fixed) {
// Insert a decimal point after the first digit and add an exponent. // Insert a decimal point after the first digit and add an exponent.
handler.insert(1, '.'); handler.insert(1, '.');
@ -660,7 +680,9 @@ struct char_counter {
ptrdiff_t size; ptrdiff_t size;
template <typename F> template <typename F>
void insert(ptrdiff_t, ptrdiff_t n, F) { size += n; } void insert(ptrdiff_t, ptrdiff_t n, F) {
size += n;
}
void insert(ptrdiff_t, char) { ++size; } void insert(ptrdiff_t, char) { ++size; }
void append(ptrdiff_t n, char) { size += n; } void append(ptrdiff_t n, char) { size += n; }
void append(char) { ++size; } void append(char) { ++size; }
@ -678,7 +700,8 @@ FMT_FUNC gen_digits_params process_specs(const core_format_specs &specs,
case 'G': case 'G':
params.upper = true; params.upper = true;
FMT_FALLTHROUGH FMT_FALLTHROUGH
case '\0': case 'g': case '\0':
case 'g':
params.trailing_zeros = (specs.flags & HASH_FLAG) != 0; params.trailing_zeros = (specs.flags & HASH_FLAG) != 0;
if (-4 <= exp && exp < num_digits + 1) { if (-4 <= exp && exp < num_digits + 1) {
params.fixed = true; params.fixed = true;
@ -819,13 +842,13 @@ FMT_FUNC internal::utf8_to_utf16::utf8_to_utf16(string_view s) {
return; return;
} }
int length = MultiByteToWideChar( int length = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, s.data(),
CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, FMT_NULL, 0); s_size, FMT_NULL, 0);
if (length == 0) if (length == 0)
FMT_THROW(windows_error(GetLastError(), ERROR_MSG)); FMT_THROW(windows_error(GetLastError(), ERROR_MSG));
buffer_.resize(length + 1); buffer_.resize(length + 1);
length = MultiByteToWideChar( length = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size,
CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, &buffer_[0], length); &buffer_[0], length);
if (length == 0) if (length == 0)
FMT_THROW(windows_error(GetLastError(), ERROR_MSG)); FMT_THROW(windows_error(GetLastError(), ERROR_MSG));
buffer_[length] = 0; buffer_[length] = 0;
@ -849,21 +872,21 @@ FMT_FUNC int internal::utf16_to_utf8::convert(wstring_view s) {
return 0; return 0;
} }
int length = WideCharToMultiByte( int length = WideCharToMultiByte(CP_UTF8, 0, s.data(), s_size, FMT_NULL, 0,
CP_UTF8, 0, s.data(), s_size, FMT_NULL, 0, FMT_NULL, FMT_NULL); FMT_NULL, FMT_NULL);
if (length == 0) if (length == 0)
return GetLastError(); return GetLastError();
buffer_.resize(length + 1); buffer_.resize(length + 1);
length = WideCharToMultiByte( length = WideCharToMultiByte(CP_UTF8, 0, s.data(), s_size, &buffer_[0],
CP_UTF8, 0, s.data(), s_size, &buffer_[0], length, FMT_NULL, FMT_NULL); length, FMT_NULL, FMT_NULL);
if (length == 0) if (length == 0)
return GetLastError(); return GetLastError();
buffer_[length] = 0; buffer_[length] = 0;
return 0; return 0;
} }
FMT_FUNC void windows_error::init( FMT_FUNC void windows_error::init(int err_code, string_view format_str,
int err_code, string_view format_str, format_args args) { format_args args) {
error_code_ = err_code; error_code_ = err_code;
memory_buffer buffer; memory_buffer buffer;
internal::format_windows_error(buffer, err_code, vformat(format_str, args)); internal::format_windows_error(buffer, err_code, vformat(format_str, args));
@ -871,17 +894,18 @@ FMT_FUNC void windows_error::init(
base = std::runtime_error(to_string(buffer)); base = std::runtime_error(to_string(buffer));
} }
FMT_FUNC void internal::format_windows_error( FMT_FUNC void internal::format_windows_error(internal::buffer &out,
internal::buffer &out, int error_code, string_view message) FMT_NOEXCEPT { int error_code,
string_view message) FMT_NOEXCEPT {
FMT_TRY { FMT_TRY {
wmemory_buffer buf; wmemory_buffer buf;
buf.resize(inline_buffer_size); buf.resize(inline_buffer_size);
for (;;) { for (;;) {
wchar_t *system_message = &buf[0]; wchar_t *system_message = &buf[0];
int result = FormatMessageW( int result = FormatMessageW(
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, FMT_NULL,
FMT_NULL, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), system_message,
system_message, static_cast<uint32_t>(buf.size()), FMT_NULL); static_cast<uint32_t>(buf.size()), FMT_NULL);
if (result != 0) { if (result != 0) {
utf16_to_utf8 utf8_message; utf16_to_utf8 utf8_message;
if (utf8_message.convert(system_message) == ERROR_SUCCESS) { if (utf8_message.convert(system_message) == ERROR_SUCCESS) {
@ -897,14 +921,15 @@ FMT_FUNC void internal::format_windows_error(
break; // Can't get error message, report error code instead. break; // Can't get error message, report error code instead.
buf.resize(buf.size() * 2); buf.resize(buf.size() * 2);
} }
} FMT_CATCH(...) {} }
FMT_CATCH(...) {}
format_error_code(out, error_code, message); format_error_code(out, error_code, message);
} }
#endif // FMT_USE_WINDOWS_H #endif // FMT_USE_WINDOWS_H
FMT_FUNC void format_system_error( FMT_FUNC void format_system_error(internal::buffer &out, int error_code,
internal::buffer &out, int error_code, string_view message) FMT_NOEXCEPT { string_view message) FMT_NOEXCEPT {
FMT_TRY { FMT_TRY {
memory_buffer buf; memory_buffer buf;
buf.resize(inline_buffer_size); buf.resize(inline_buffer_size);
@ -922,7 +947,8 @@ FMT_FUNC void format_system_error(
break; // Can't get error message, report error code instead. break; // Can't get error message, report error code instead.
buf.resize(buf.size() * 2); buf.resize(buf.size() * 2);
} }
} FMT_CATCH(...) {} }
FMT_CATCH(...) {}
format_error_code(out, error_code, message); format_error_code(out, error_code, message);
} }
@ -930,14 +956,14 @@ FMT_FUNC void internal::error_handler::on_error(const char *message) {
FMT_THROW(format_error(message)); FMT_THROW(format_error(message));
} }
FMT_FUNC void report_system_error( FMT_FUNC void report_system_error(int error_code,
int error_code, fmt::string_view message) FMT_NOEXCEPT { fmt::string_view message) FMT_NOEXCEPT {
report_error(format_system_error, error_code, message); report_error(format_system_error, error_code, message);
} }
#if FMT_USE_WINDOWS_H #if FMT_USE_WINDOWS_H
FMT_FUNC void report_windows_error( FMT_FUNC void report_windows_error(int error_code,
int error_code, fmt::string_view message) FMT_NOEXCEPT { fmt::string_view message) FMT_NOEXCEPT {
report_error(internal::format_windows_error, error_code, message); report_error(internal::format_windows_error, error_code, message);
} }
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@ -9,6 +9,7 @@
#define FMT_LOCALE_H_ #define FMT_LOCALE_H_
#include "format.h" #include "format.h"
#include <locale> #include <locale>
FMT_BEGIN_NAMESPACE FMT_BEGIN_NAMESPACE
@ -20,8 +21,8 @@ typename buffer_context<Char>::type::iterator vformat_to(
basic_string_view<Char> format_str, basic_string_view<Char> format_str,
basic_format_args<typename buffer_context<Char>::type> args) { basic_format_args<typename buffer_context<Char>::type> args) {
typedef back_insert_range<basic_buffer<Char>> range; typedef back_insert_range<basic_buffer<Char>> range;
return vformat_to<arg_formatter<range>>( return vformat_to<arg_formatter<range>>(buf, to_string_view(format_str), args,
buf, to_string_view(format_str), args, internal::locale_ref(loc)); internal::locale_ref(loc));
} }
template <typename Char> template <typename Char>
@ -32,7 +33,7 @@ std::basic_string<Char> vformat(
internal::vformat_to(loc, buffer, format_str, args); internal::vformat_to(loc, buffer, format_str, args);
return fmt::to_string(buffer); return fmt::to_string(buffer);
} }
} } // namespace internal
template <typename S, typename Char = FMT_CHAR(S)> template <typename S, typename Char = FMT_CHAR(S)>
inline std::basic_string<Char> vformat( inline std::basic_string<Char> vformat(
@ -42,8 +43,9 @@ inline std::basic_string<Char> vformat(
} }
template <typename S, typename... Args> template <typename S, typename... Args>
inline std::basic_string<FMT_CHAR(S)> format( inline std::basic_string<FMT_CHAR(S)> format(const std::locale &loc,
const std::locale &loc, const S &format_str, const Args &... args) { const S &format_str,
const Args &... args) {
return internal::vformat( return internal::vformat(
loc, to_string_view(format_str), loc, to_string_view(format_str),
*internal::checked_args<S, Args...>(format_str, args...)); *internal::checked_args<S, Args...>(format_str, args...));
@ -60,9 +62,10 @@ inline typename std::enable_if<internal::is_output_iterator<OutputIt>::value,
} }
template <typename OutputIt, typename S, typename... Args> template <typename OutputIt, typename S, typename... Args>
inline typename std::enable_if< inline
internal::is_string<S>::value && typename std::enable_if<internal::is_string<S>::value &&
internal::is_output_iterator<OutputIt>::value, OutputIt>::type internal::is_output_iterator<OutputIt>::value,
OutputIt>::type
format_to(OutputIt out, const std::locale &loc, const S &format_str, format_to(OutputIt out, const std::locale &loc, const S &format_str,
const Args &... args) { const Args &... args) {
internal::check_format_string<Args...>(format_str); internal::check_format_string<Args...>(format_str);

View File

@ -9,6 +9,7 @@
#define FMT_OSTREAM_H_ #define FMT_OSTREAM_H_
#include "format.h" #include "format.h"
#include <ostream> #include <ostream>
FMT_BEGIN_NAMESPACE FMT_BEGIN_NAMESPACE
@ -53,14 +54,16 @@ struct test_stream : std::basic_ostream<Char> {
void operator<<(null); void operator<<(null);
}; };
// Checks if T has a user-defined operator<< (e.g. not a member of std::ostream). // Checks if T has a user-defined operator<< (e.g. not a member of
// std::ostream).
template <typename T, typename Char> template <typename T, typename Char>
class is_streamable { class is_streamable {
private: private:
template <typename U> template <typename U>
static decltype( static decltype(
internal::declval<test_stream<Char>&>() internal::declval<test_stream<Char> &>() << internal::declval<U>(),
<< internal::declval<U>(), std::true_type()) test(int); std::true_type())
test(int);
template <typename> template <typename>
static std::false_type test(...); static std::false_type test(...);
@ -101,20 +104,19 @@ void format_value(basic_buffer<Char> &buffer, const T &value) {
// function (not a member of std::ostream). // function (not a member of std::ostream).
template <typename T, typename Char> template <typename T, typename Char>
struct convert_to_int<T, Char, void> { struct convert_to_int<T, Char, void> {
static const bool value = static const bool value = convert_to_int<T, Char, int>::value &&
convert_to_int<T, Char, int>::value &&
!internal::is_streamable<T, Char>::value; !internal::is_streamable<T, Char>::value;
}; };
// 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, struct formatter<
T,
Char,
typename std::enable_if< typename std::enable_if<
internal::is_streamable<T, Char>::value && internal::is_streamable<T, Char>::value &&
!internal::format_type< !internal::format_type<typename buffer_context<Char>::type, T>::value>::
typename buffer_context<Char>::type, T>::value>::type> type> : formatter<basic_string_view<Char>, Char> {
: formatter<basic_string_view<Char>, Char> {
template <typename Context> template <typename Context>
auto format(const T &value, Context &ctx) -> decltype(ctx.out()) { auto format(const T &value, Context &ctx) -> decltype(ctx.out()) {
basic_memory_buffer<Char> buffer; basic_memory_buffer<Char> buffer;
@ -125,7 +127,8 @@ struct formatter<T, Char,
}; };
template <typename Char> template <typename Char>
inline void vprint(std::basic_ostream<Char> &os, inline void vprint(
std::basic_ostream<Char> &os,
basic_string_view<Char> format_str, basic_string_view<Char> format_str,
basic_format_args<typename buffer_context<Char>::type> args) { basic_format_args<typename buffer_context<Char>::type> args) {
basic_memory_buffer<Char> buffer; basic_memory_buffer<Char> buffer;
@ -142,8 +145,9 @@ inline void vprint(std::basic_ostream<Char> &os,
\endrst \endrst
*/ */
template <typename S, typename... Args> template <typename S, typename... Args>
inline typename std::enable_if<internal::is_string<S>::value>::type inline typename std::enable_if<internal::is_string<S>::value>::type print(
print(std::basic_ostream<FMT_CHAR(S)> &os, const S &format_str, std::basic_ostream<FMT_CHAR(S)> &os,
const S &format_str,
const Args &... args) { const Args &... args) {
internal::checked_args<S, Args...> ca(format_str, args...); internal::checked_args<S, Args...> ca(format_str, args...);
vprint(os, to_string_view(format_str), *ca); vprint(os, to_string_view(format_str), *ca);

View File

@ -143,7 +143,6 @@ class buffered_file {
buffered_file(const buffered_file &) = delete; buffered_file(const buffered_file &) = delete;
void operator=(const buffered_file &) = delete; void operator=(const buffered_file &) = delete;
public: public:
buffered_file(buffered_file &&other) FMT_NOEXCEPT : file_(other.file_) { buffered_file(buffered_file &&other) FMT_NOEXCEPT : file_(other.file_) {
other.file_ = FMT_NULL; other.file_ = FMT_NULL;
@ -211,9 +210,7 @@ class file {
void operator=(const file &) = delete; void operator=(const file &) = delete;
public: public:
file(file &&other) FMT_NOEXCEPT : fd_(other.fd_) { file(file &&other) FMT_NOEXCEPT : fd_(other.fd_) { other.fd_ = -1; }
other.fd_ = -1;
}
file &operator=(file &&other) { file &operator=(file &&other) {
close(); close();
@ -284,9 +281,7 @@ class Locale {
return _create_locale(category_mask, locale); return _create_locale(category_mask, locale);
} }
static void freelocale(locale_t locale) { static void freelocale(locale_t locale) { _free_locale(locale); }
_free_locale(locale);
}
static double strtod_l(const char *nptr, char **endptr, _locale_t locale) { static double strtod_l(const char *nptr, char **endptr, _locale_t locale) {
return _strtod_l(nptr, endptr, locale); return _strtod_l(nptr, endptr, locale);

View File

@ -8,11 +8,11 @@
#ifndef FMT_PRINTF_H_ #ifndef FMT_PRINTF_H_
#define FMT_PRINTF_H_ #define FMT_PRINTF_H_
#include "ostream.h"
#include <algorithm> // std::fill_n #include <algorithm> // std::fill_n
#include <limits> // std::numeric_limits #include <limits> // std::numeric_limits
#include "ostream.h"
FMT_BEGIN_NAMESPACE FMT_BEGIN_NAMESPACE
namespace internal { namespace internal {
@ -43,9 +43,7 @@ class null_terminating_iterator {
return *this; return *this;
} }
FMT_CONSTEXPR Char operator*() const { FMT_CONSTEXPR Char operator*() const { return ptr_ != end_ ? *ptr_ : Char(); }
return ptr_ != end_ ? *ptr_ : Char();
}
FMT_CONSTEXPR null_terminating_iterator operator++() { FMT_CONSTEXPR null_terminating_iterator operator++() {
++ptr_; ++ptr_;
@ -76,8 +74,8 @@ class null_terminating_iterator {
return *this; return *this;
} }
FMT_CONSTEXPR difference_type operator-( FMT_CONSTEXPR difference_type
null_terminating_iterator other) const { operator-(null_terminating_iterator other) const {
return ptr_ - other.ptr_; return ptr_ - other.ptr_;
} }
@ -101,7 +99,9 @@ class null_terminating_iterator {
}; };
template <typename T> template <typename T>
FMT_CONSTEXPR const T *pointer_from(const T *p) { return p; } FMT_CONSTEXPR const T *pointer_from(const T *p) {
return p;
}
template <typename Char> template <typename Char>
FMT_CONSTEXPR const Char *pointer_from(null_terminating_iterator<Char> it) { FMT_CONSTEXPR const Char *pointer_from(null_terminating_iterator<Char> it) {
@ -165,15 +165,16 @@ struct int_checker<true> {
class printf_precision_handler : public function<int> { class printf_precision_handler : public function<int> {
public: public:
template <typename T> template <typename T>
typename std::enable_if<std::is_integral<T>::value, int>::type typename std::enable_if<std::is_integral<T>::value, int>::type operator()(
operator()(T value) { T value) {
if (!int_checker<std::numeric_limits<T>::is_signed>::fits_in_int(value)) if (!int_checker<std::numeric_limits<T>::is_signed>::fits_in_int(value))
FMT_THROW(format_error("number is too big")); FMT_THROW(format_error("number is too big"));
return static_cast<int>(value); return static_cast<int>(value);
} }
template <typename T> template <typename T>
typename std::enable_if<!std::is_integral<T>::value, int>::type operator()(T) { typename std::enable_if<!std::is_integral<T>::value, int>::type operator()(
T) {
FMT_THROW(format_error("precision is not integer")); FMT_THROW(format_error("precision is not integer"));
return 0; return 0;
} }
@ -183,12 +184,16 @@ class printf_precision_handler: public function<int> {
class is_zero_int : public function<bool> { class is_zero_int : public function<bool> {
public: public:
template <typename T> template <typename T>
typename std::enable_if<std::is_integral<T>::value, bool>::type typename std::enable_if<std::is_integral<T>::value, bool>::type operator()(
operator()(T value) { return value == 0; } T value) {
return value == 0;
}
template <typename T> template <typename T>
typename std::enable_if<!std::is_integral<T>::value, bool>::type typename std::enable_if<!std::is_integral<T>::value, bool>::type operator()(
operator()(T) { return false; } T) {
return false;
}
}; };
template <typename T> template <typename T>
@ -217,11 +222,11 @@ class arg_converter: public function<void> {
} }
template <typename U> template <typename U>
typename std::enable_if<std::is_integral<U>::value>::type typename std::enable_if<std::is_integral<U>::value>::type operator()(
operator()(U value) { U value) {
bool is_signed = type_ == 'd' || type_ == 'i'; bool is_signed = type_ == 'd' || type_ == 'i';
typedef typename std::conditional< typedef typename std::conditional<std::is_same<T, void>::value, U, T>::type
std::is_same<T, void>::value, U, T>::type TargetType; TargetType;
if (const_check(sizeof(TargetType) <= sizeof(int))) { if (const_check(sizeof(TargetType) <= sizeof(int))) {
// Extra casts are used to silence warnings. // Extra casts are used to silence warnings.
if (is_signed) { if (is_signed) {
@ -270,8 +275,8 @@ class char_converter: public function<void> {
explicit char_converter(basic_format_arg<Context> &arg) : arg_(arg) {} explicit char_converter(basic_format_arg<Context> &arg) : arg_(arg) {}
template <typename T> template <typename T>
typename std::enable_if<std::is_integral<T>::value>::type typename std::enable_if<std::is_integral<T>::value>::type operator()(
operator()(T value) { T value) {
typedef typename Context::char_type Char; typedef typename Context::char_type Char;
arg_ = internal::make_arg<Context>(static_cast<Char>(value)); arg_ = internal::make_arg<Context>(static_cast<Char>(value));
} }
@ -318,7 +323,9 @@ class printf_width_handler: public function<unsigned> {
}; };
template <typename Char, typename Context> template <typename Char, typename Context>
void printf(basic_buffer<Char> &buf, basic_string_view<Char> format, void printf(
basic_buffer<Char> &buf,
basic_string_view<Char> format,
basic_format_args<Context> args) { basic_format_args<Context> args) {
Context(std::back_inserter(buf), format, args).format(); Context(std::back_inserter(buf), format, args).format();
} }
@ -330,7 +337,8 @@ template <typename Range>
class printf_arg_formatter; class printf_arg_formatter;
template < template <
typename OutputIt, typename Char, typename OutputIt,
typename Char,
typename ArgFormatter = typename ArgFormatter =
printf_arg_formatter<back_insert_range<internal::basic_buffer<Char>>>> printf_arg_formatter<back_insert_range<internal::basic_buffer<Char>>>>
class basic_printf_context; class basic_printf_context;
@ -341,8 +349,8 @@ class basic_printf_context;
\endrst \endrst
*/ */
template <typename Range> template <typename Range>
class printf_arg_formatter: class printf_arg_formatter
public internal::function< : public internal::function<
typename internal::arg_formatter_base<Range>::iterator>, typename internal::arg_formatter_base<Range>::iterator>,
public internal::arg_formatter_base<Range> { public internal::arg_formatter_base<Range> {
private: private:
@ -373,9 +381,13 @@ class printf_arg_formatter:
specifier information for standard argument types. specifier information for standard argument types.
\endrst \endrst
*/ */
printf_arg_formatter(internal::basic_buffer<char_type> &buffer, printf_arg_formatter(
format_specs &spec, context_type &ctx) internal::basic_buffer<char_type> &buffer,
: base(back_insert_range<internal::basic_buffer<char_type>>(buffer), &spec, format_specs &spec,
context_type &ctx)
: base(
back_insert_range<internal::basic_buffer<char_type>>(buffer),
&spec,
ctx.locale()), ctx.locale()),
context_(ctx) {} context_(ctx) {}
@ -435,9 +447,7 @@ class printf_arg_formatter:
return base::operator()(value); return base::operator()(value);
} }
iterator operator()(monostate value) { iterator operator()(monostate value) { return base::operator()(value); }
return base::operator()(value);
}
/** Formats a pointer. */ /** Formats a pointer. */
iterator operator()(const void *value) { iterator operator()(const void *value) {
@ -458,7 +468,9 @@ class printf_arg_formatter:
template <typename T> template <typename T>
struct printf_formatter { struct printf_formatter {
template <typename ParseContext> template <typename ParseContext>
auto parse(ParseContext &ctx) -> decltype(ctx.begin()) { return ctx.begin(); } auto parse(ParseContext &ctx) -> decltype(ctx.begin()) {
return ctx.begin();
}
template <typename FormatContext> template <typename FormatContext>
auto format(const T &value, FormatContext &ctx) -> decltype(ctx.out()) { auto format(const T &value, FormatContext &ctx) -> decltype(ctx.out()) {
@ -473,13 +485,17 @@ class basic_printf_context :
// Inherit publicly as a workaround for the icc bug // Inherit publicly as a workaround for the icc bug
// https://software.intel.com/en-us/forums/intel-c-compiler/topic/783476. // https://software.intel.com/en-us/forums/intel-c-compiler/topic/783476.
public internal::context_base< public internal::context_base<
OutputIt, basic_printf_context<OutputIt, Char, ArgFormatter>, Char> { OutputIt,
basic_printf_context<OutputIt, Char, ArgFormatter>,
Char> {
public: public:
/** The character type for the output. */ /** The character type for the output. */
typedef Char char_type; typedef Char char_type;
template <typename T> template <typename T>
struct formatter_type { typedef printf_formatter<T> type; }; struct formatter_type {
typedef printf_formatter<T> type;
};
private: private:
typedef internal::context_base<OutputIt, basic_printf_context, Char> base; typedef internal::context_base<OutputIt, basic_printf_context, Char> base;
@ -492,8 +508,7 @@ class basic_printf_context :
// Returns the argument with specified index or, if arg_index is equal // Returns the argument with specified index or, if arg_index is equal
// to the maximum unsigned value, the next argument. // to the maximum unsigned value, the next argument.
format_arg get_arg( format_arg get_arg(
iterator it, iterator it, unsigned arg_index = (std::numeric_limits<unsigned>::max)());
unsigned arg_index = (std::numeric_limits<unsigned>::max)());
// Parses argument index, flags and width and returns the argument index. // Parses argument index, flags and width and returns the argument index.
unsigned parse_header(iterator &it, format_specs &spec); unsigned parse_header(iterator &it, format_specs &spec);
@ -506,13 +521,15 @@ class basic_printf_context :
appropriate lifetimes. appropriate lifetimes.
\endrst \endrst
*/ */
basic_printf_context(OutputIt out, basic_string_view<char_type> format_str, basic_printf_context(
OutputIt out,
basic_string_view<char_type> format_str,
basic_format_args<basic_printf_context> args) basic_format_args<basic_printf_context> args)
: base(out, format_str, args) {} : base(out, format_str, args) {}
using base::parse_context;
using base::out;
using base::advance_to; using base::advance_to;
using base::out;
using base::parse_context;
/** Formats stored arguments and writes the output to the range. */ /** Formats stored arguments and writes the output to the range. */
void format(); void format();
@ -600,7 +617,8 @@ void basic_printf_context<OutputIt, Char, AF>::format() {
using internal::pointer_from; using internal::pointer_from;
while (*it) { while (*it) {
char_type c = *it++; char_type c = *it++;
if (c != '%') continue; if (c != '%')
continue;
if (*it == c) { if (*it == c) {
buffer.append(pointer_from(start), pointer_from(it)); buffer.append(pointer_from(start), pointer_from(it));
start = ++it; start = ++it;
@ -679,7 +697,8 @@ void basic_printf_context<OutputIt, Char, AF>::format() {
if (arg.is_integral()) { if (arg.is_integral()) {
// Normalize type. // Normalize type.
switch (spec.type) { switch (spec.type) {
case 'i': case 'u': case 'i':
case 'u':
spec.type = 'd'; spec.type = 'd';
break; break;
case 'c': case 'c':
@ -701,7 +720,9 @@ void basic_printf_context<OutputIt, Char, AF>::format() {
template <typename Buffer> template <typename Buffer>
struct basic_printf_context_t { struct basic_printf_context_t {
typedef basic_printf_context< typedef basic_printf_context<
std::back_insert_iterator<Buffer>, typename Buffer::value_type> type; std::back_insert_iterator<Buffer>,
typename Buffer::value_type>
type;
}; };
typedef basic_printf_context_t<internal::buffer>::type printf_context; typedef basic_printf_context_t<internal::buffer>::type printf_context;
@ -717,8 +738,10 @@ typedef basic_format_args<wprintf_context> wprintf_args;
\endrst \endrst
*/ */
template <typename... Args> template <typename... Args>
inline format_arg_store<printf_context, Args...> inline format_arg_store<printf_context, Args...> make_printf_args(
make_printf_args(const Args &... args) { return {args...}; } const Args &... args) {
return {args...};
}
/** /**
\rst \rst
@ -727,14 +750,17 @@ inline format_arg_store<printf_context, Args...>
\endrst \endrst
*/ */
template <typename... Args> template <typename... Args>
inline format_arg_store<wprintf_context, Args...> inline format_arg_store<wprintf_context, Args...> make_wprintf_args(
make_wprintf_args(const Args &... args) { return {args...}; } const Args &... args) {
return {args...};
}
template <typename S, typename Char = FMT_CHAR(S)> template <typename S, typename Char = FMT_CHAR(S)>
inline std::basic_string<Char> inline std::basic_string<Char> vsprintf(
vsprintf(const S &format, const S &format,
basic_format_args<typename basic_printf_context_t< basic_format_args<
internal::basic_buffer<Char>>::type> args) { typename basic_printf_context_t<internal::basic_buffer<Char>>::type>
args) {
basic_memory_buffer<Char> buffer; basic_memory_buffer<Char> buffer;
printf(buffer, to_string_view(format), args); printf(buffer, to_string_view(format), args);
return to_string(buffer); return to_string(buffer);
@ -757,19 +783,22 @@ inline FMT_ENABLE_IF_T(
typedef internal::basic_buffer<FMT_CHAR(S)> buffer; typedef internal::basic_buffer<FMT_CHAR(S)> buffer;
typedef typename basic_printf_context_t<buffer>::type context; typedef typename basic_printf_context_t<buffer>::type context;
format_arg_store<context, Args...> as{args...}; format_arg_store<context, Args...> as{args...};
return vsprintf(to_string_view(format), return vsprintf(to_string_view(format), basic_format_args<context>(as));
basic_format_args<context>(as));
} }
template <typename S, typename Char = FMT_CHAR(S)> template <typename S, typename Char = FMT_CHAR(S)>
inline int vfprintf(std::FILE *f, const S &format, inline int vfprintf(
basic_format_args<typename basic_printf_context_t< std::FILE *f,
internal::basic_buffer<Char>>::type> args) { const S &format,
basic_format_args<
typename basic_printf_context_t<internal::basic_buffer<Char>>::type>
args) {
basic_memory_buffer<Char> buffer; basic_memory_buffer<Char> buffer;
printf(buffer, to_string_view(format), args); printf(buffer, to_string_view(format), args);
std::size_t size = buffer.size(); std::size_t size = buffer.size();
return std::fwrite( return std::fwrite(buffer.data(), sizeof(Char), size, f) < size
buffer.data(), sizeof(Char), size, f) < size ? -1 : static_cast<int>(size); ? -1
: static_cast<int>(size);
} }
/** /**
@ -788,14 +817,15 @@ inline FMT_ENABLE_IF_T(internal::is_string<S>::value, int)
typedef internal::basic_buffer<FMT_CHAR(S)> buffer; typedef internal::basic_buffer<FMT_CHAR(S)> buffer;
typedef typename basic_printf_context_t<buffer>::type context; typedef typename basic_printf_context_t<buffer>::type context;
format_arg_store<context, Args...> as{args...}; format_arg_store<context, Args...> as{args...};
return vfprintf(f, to_string_view(format), return vfprintf(f, to_string_view(format), basic_format_args<context>(as));
basic_format_args<context>(as));
} }
template <typename S, typename Char = FMT_CHAR(S)> template <typename S, typename Char = FMT_CHAR(S)>
inline int vprintf(const S &format, inline int vprintf(
basic_format_args<typename basic_printf_context_t< const S &format,
internal::basic_buffer<Char>>::type> args) { basic_format_args<
typename basic_printf_context_t<internal::basic_buffer<Char>>::type>
args) {
return vfprintf(stdout, to_string_view(format), args); return vfprintf(stdout, to_string_view(format), args);
} }
@ -815,15 +845,16 @@ inline FMT_ENABLE_IF_T(internal::is_string<S>::value, int)
typedef internal::basic_buffer<FMT_CHAR(S)> buffer; typedef internal::basic_buffer<FMT_CHAR(S)> buffer;
typedef typename basic_printf_context_t<buffer>::type context; typedef typename basic_printf_context_t<buffer>::type context;
format_arg_store<context, Args...> as{args...}; format_arg_store<context, Args...> as{args...};
return vprintf(to_string_view(format_str), return vprintf(to_string_view(format_str), basic_format_args<context>(as));
basic_format_args<context>(as));
} }
template <typename S, typename Char = FMT_CHAR(S)> template <typename S, typename Char = FMT_CHAR(S)>
inline int vfprintf(std::basic_ostream<Char> &os, inline int vfprintf(
std::basic_ostream<Char> &os,
const S &format, const S &format,
basic_format_args<typename basic_printf_context_t< basic_format_args<
internal::basic_buffer<Char>>::type> args) { typename basic_printf_context_t<internal::basic_buffer<Char>>::type>
args) {
basic_memory_buffer<Char> buffer; basic_memory_buffer<Char> buffer;
printf(buffer, to_string_view(format), args); printf(buffer, to_string_view(format), args);
internal::write(os, buffer); internal::write(os, buffer);
@ -840,15 +871,16 @@ inline int vfprintf(std::basic_ostream<Char> &os,
\endrst \endrst
*/ */
template <typename S, typename... Args> template <typename S, typename... Args>
inline FMT_ENABLE_IF_T(internal::is_string<S>::value, int) inline FMT_ENABLE_IF_T(internal::is_string<S>::value, int) fprintf(
fprintf(std::basic_ostream<FMT_CHAR(S)> &os, std::basic_ostream<FMT_CHAR(S)> &os,
const S &format_str, const Args & ... args) { const S &format_str,
const Args &... args) {
internal::check_format_string<Args...>(format_str); internal::check_format_string<Args...>(format_str);
typedef internal::basic_buffer<FMT_CHAR(S)> buffer; typedef internal::basic_buffer<FMT_CHAR(S)> buffer;
typedef typename basic_printf_context_t<buffer>::type context; typedef typename basic_printf_context_t<buffer>::type context;
format_arg_store<context, Args...> as{args...}; format_arg_store<context, Args...> as{args...};
return vfprintf(os, to_string_view(format_str), return vfprintf(
basic_format_args<context>(as)); os, to_string_view(format_str), basic_format_args<context>(as));
} }
FMT_END_NAMESPACE FMT_END_NAMESPACE

View File

@ -13,6 +13,7 @@
#define FMT_RANGES_H_ #define FMT_RANGES_H_
#include "format.h" #include "format.h"
#include <type_traits> #include <type_traits>
// output only up to N items from the range. // output only up to N items from the range.
@ -33,7 +34,8 @@ struct formatting_base {
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 range. FMT_RANGE_OUTPUT_LENGTH_LIMIT; // output only up to N items from the
// range.
Char prefix; Char prefix;
Char delimiter; Char delimiter;
Char postfix; Char postfix;
@ -77,8 +79,8 @@ void copy(char ch, OutputIterator out) {
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(...);
@ -98,9 +100,12 @@ 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< struct is_range_<
T,
typename std::conditional<
false, false,
conditional_helper<decltype(internal::declval<T>().begin()), conditional_helper<
decltype(internal::declval<T>().begin()),
decltype(internal::declval<T>().end())>, decltype(internal::declval<T>().end())>,
void>::type> : std::true_type {}; void>::type> : std::true_type {};
#endif #endif
@ -109,9 +114,10 @@ struct is_range_<T, typename std::conditional<
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(
decltype(std::tuple_size<U>::value, std::tuple_size<U>::value,
internal::declval<typename std::tuple_element<0, U>::type>(), int()); internal::declval<typename std::tuple_element<0, U>::type>(),
int());
template <typename> template <typename>
static void check(...); static void check(...);
@ -133,9 +139,7 @@ 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>
@ -159,8 +163,10 @@ void for_each(index_sequence<Is...>, Tuple &&tup, F &&f) FMT_NOEXCEPT {
} }
template <class T> template <class T>
FMT_CONSTEXPR make_index_sequence<std::tuple_size<T>::value> FMT_CONSTEXPR make_index_sequence<std::tuple_size<T>::value> get_indexes(
get_indexes(T const &) { return {}; } T const &) {
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) {
@ -169,23 +175,30 @@ void for_each(Tuple &&tup, F &&f) {
} }
template <typename Arg> template <typename Arg>
FMT_CONSTEXPR const char* format_str_quoted(bool add_space, const Arg&, FMT_CONSTEXPR const char *format_str_quoted(
bool add_space,
const Arg &,
typename std::enable_if< typename std::enable_if<
!is_like_std_string<typename std::decay<Arg>::type>::value>::type* = nullptr) { !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(bool add_space, const Arg&, FMT_CONSTEXPR const char *format_str_quoted(
bool add_space,
const Arg &,
typename std::enable_if< typename std::enable_if<
is_like_std_string<typename std::decay<Arg>::type>::value>::type* = nullptr) { 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"\"{}\"";
} }
@ -205,7 +218,9 @@ struct is_tuple_like {
}; };
template <typename TupleT, typename Char> template <typename TupleT, typename Char>
struct formatter<TupleT, Char, struct formatter<
TupleT,
Char,
typename std::enable_if<fmt::is_tuple_like<TupleT>::value>::type> { 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()
@ -219,7 +234,8 @@ private:
} }
internal::copy(formatting.delimiter, out); internal::copy(formatting.delimiter, out);
} }
format_to(out, format_to(
out,
internal::format_str_quoted( internal::format_str_quoted(
(formatting.add_delimiter_spaces && i > 0), v), (formatting.add_delimiter_spaces && i > 0), v),
v); v);
@ -228,7 +244,8 @@ private:
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:
@ -262,9 +279,10 @@ struct is_range {
}; };
template <typename RangeT, typename Char> template <typename RangeT, typename Char>
struct formatter<RangeT, Char, struct formatter<
RangeT,
Char,
typename std::enable_if<fmt::is_range<RangeT>::value>::type> { typename std::enable_if<fmt::is_range<RangeT>::value>::type> {
formatting_range<Char> formatting; formatting_range<Char> formatting;
template <typename ParseContext> template <typename ParseContext>
@ -285,7 +303,8 @@ struct formatter<RangeT, Char,
} }
internal::copy(formatting.delimiter, out); internal::copy(formatting.delimiter, out);
} }
format_to(out, format_to(
out,
internal::format_str_quoted( internal::format_str_quoted(
(formatting.add_delimiter_spaces && i > 0), *it), (formatting.add_delimiter_spaces && i > 0), *it),
*it); *it);
@ -305,4 +324,3 @@ struct formatter<RangeT, Char,
FMT_END_NAMESPACE FMT_END_NAMESPACE
#endif // FMT_RANGES_H_ #endif // FMT_RANGES_H_

View File

@ -9,6 +9,7 @@
#define FMT_TIME_H_ #define FMT_TIME_H_
#include "format.h" #include "format.h"
#include <ctime> #include <ctime>
#include <locale> #include <locale>
@ -51,7 +52,8 @@ inline std::tm localtime(std::time_t time) {
bool fallback(internal::null<>) { bool fallback(internal::null<>) {
using namespace fmt::internal; using namespace fmt::internal;
std::tm *tm = std::localtime(&time_); std::tm *tm = std::localtime(&time_);
if (tm) tm_ = *tm; if (tm)
tm_ = *tm;
return tm != FMT_NULL; return tm != FMT_NULL;
} }
#endif #endif
@ -88,7 +90,8 @@ inline std::tm gmtime(std::time_t time) {
#if !FMT_MSC_VER #if !FMT_MSC_VER
bool fallback(internal::null<>) { bool fallback(internal::null<>) {
std::tm *tm = std::gmtime(&time_); std::tm *tm = std::gmtime(&time_);
if (tm) tm_ = *tm; if (tm)
tm_ = *tm;
return tm != FMT_NULL; return tm != FMT_NULL;
} }
#endif #endif
@ -101,16 +104,19 @@ inline std::tm gmtime(std::time_t time) {
} }
namespace internal { namespace internal {
inline std::size_t strftime(char *str, std::size_t count, const char *format, inline std::size_t strftime(
const std::tm *time) { 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, inline std::size_t strftime(
const wchar_t *format, const std::tm *time) { 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> template <typename Char>
struct formatter<std::tm, Char> { struct formatter<std::tm, Char> {
@ -120,8 +126,7 @@ struct formatter<std::tm, Char> {
if (it != ctx.end() && *it == ':') if (it != ctx.end() && *it == ':')
++it; ++it;
auto end = it; auto end = it;
while (end != ctx.end() && *end != '}') while (end != ctx.end() && *end != '}') ++end;
++end;
tm_format.reserve(end - it + 1); tm_format.reserve(end - it + 1);
tm_format.append(it, end); tm_format.append(it, end);
tm_format.push_back('\0'); tm_format.push_back('\0');

View File

@ -16,7 +16,8 @@ template FMT_API std::locale internal::locale_ref::get<std::locale>() const;
template FMT_API char internal::thousands_sep_impl(locale_ref); template FMT_API char internal::thousands_sep_impl(locale_ref);
template FMT_API void internal::basic_buffer<char>::append(const char *, const char *); template FMT_API void internal::basic_buffer<char>::append(
const char *, const char *);
template FMT_API void internal::arg_map<format_context>::init( template FMT_API void internal::arg_map<format_context>::init(
const basic_format_args<format_context> &args); const basic_format_args<format_context> &args);

View File

@ -13,8 +13,8 @@
#include "fmt/posix.h" #include "fmt/posix.h"
#include <limits.h> #include <limits.h>
#include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/types.h>
#ifndef _WIN32 #ifndef _WIN32
#include <unistd.h> #include <unistd.h>
@ -22,8 +22,8 @@
#ifndef WIN32_LEAN_AND_MEAN #ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
#endif #endif
# include <windows.h>
#include <io.h> #include <io.h>
#include <windows.h>
#define O_CREAT _O_CREAT #define O_CREAT _O_CREAT
#define O_TRUNC _O_TRUNC #define O_TRUNC _O_TRUNC
@ -62,7 +62,7 @@ typedef ssize_t RWResult;
inline std::size_t convert_rwcount(std::size_t count) { return count; } inline std::size_t convert_rwcount(std::size_t count) { return count; }
#endif #endif
} } // namespace
FMT_BEGIN_NAMESPACE FMT_BEGIN_NAMESPACE
@ -72,8 +72,8 @@ buffered_file::~buffered_file() FMT_NOEXCEPT {
} }
buffered_file::buffered_file(cstring_view filename, cstring_view mode) { buffered_file::buffered_file(cstring_view filename, cstring_view mode) {
FMT_RETRY_VAL(file_, FMT_RETRY_VAL(
FMT_SYSTEM(fopen(filename.c_str(), mode.c_str())), FMT_NULL); file_, FMT_SYSTEM(fopen(filename.c_str(), mode.c_str())), FMT_NULL);
if (!file_) if (!file_)
FMT_THROW(system_error(errno, "cannot open file {}", filename.c_str())); FMT_THROW(system_error(errno, "cannot open file {}", filename.c_str()));
} }
@ -147,7 +147,8 @@ long long file::size() const {
Stat file_stat = Stat(); Stat file_stat = Stat();
if (FMT_POSIX_CALL(fstat(fd_, &file_stat)) == -1) if (FMT_POSIX_CALL(fstat(fd_, &file_stat)) == -1)
FMT_THROW(system_error(errno, "cannot get file attributes")); FMT_THROW(system_error(errno, "cannot get file attributes"));
static_assert(sizeof(long long) >= sizeof(file_stat.st_size), static_assert(
sizeof(long long) >= sizeof(file_stat.st_size),
"return type of file::size is not large enough"); "return type of file::size is not large enough");
return file_stat.st_size; return file_stat.st_size;
#endif #endif
@ -182,8 +183,8 @@ void file::dup2(int fd) {
int result = 0; int result = 0;
FMT_RETRY(result, FMT_POSIX_CALL(dup2(fd_, fd))); FMT_RETRY(result, FMT_POSIX_CALL(dup2(fd_, fd)));
if (result == -1) { if (result == -1) {
FMT_THROW(system_error(errno, FMT_THROW(system_error(
"cannot duplicate file descriptor {} to {}", fd_, fd)); errno, "cannot duplicate file descriptor {} to {}", fd_, fd));
} }
} }
@ -221,8 +222,8 @@ buffered_file file::fdopen(const char *mode) {
// Don't retry as fdopen doesn't return EINTR. // Don't retry as fdopen doesn't return EINTR.
FILE *f = FMT_POSIX_CALL(fdopen(fd_, mode)); FILE *f = FMT_POSIX_CALL(fdopen(fd_, mode));
if (!f) if (!f)
FMT_THROW(system_error(errno, FMT_THROW(
"cannot associate stream with file descriptor")); system_error(errno, "cannot associate stream with file descriptor"));
buffered_file bf(f); buffered_file bf(f);
fd_ = -1; fd_ = -1;
return bf; return bf;
@ -241,4 +242,3 @@ long getpagesize() {
#endif #endif
} }
FMT_END_NAMESPACE FMT_END_NAMESPACE