1
0
mirror of https://github.com/VCMP-SqMod/SqMod.git synced 2025-08-03 06:31:47 +02:00

Update the format library to the latest version.

This commit is contained in:
Sandu Liviu Catalin
2016-05-22 23:37:55 +03:00
parent edf4d6cd38
commit 49a9983799
13 changed files with 711 additions and 1106 deletions

View File

@@ -1,7 +1,7 @@
/*
Formatting library for C++
Copyright (c) 2012 - 2015, Victor Zverovich
Copyright (c) 2012 - 2016, Victor Zverovich
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -29,6 +29,7 @@
#define FMT_FORMAT_H_
#include <cassert>
#include <clocale>
#include <cmath>
#include <cstdio>
#include <cstring>
@@ -39,14 +40,6 @@
#include <vector>
#include <utility>
#ifndef FMT_USE_IOSTREAMS
# define FMT_USE_IOSTREAMS 1
#endif
#if FMT_USE_IOSTREAMS
# include <ostream>
#endif
#ifdef _SECURE_SCL
# define FMT_SECURE_SCL _SECURE_SCL
#else
@@ -57,7 +50,13 @@
# include <iterator>
#endif
#if defined(_MSC_VER) && _MSC_VER <= 1500
#ifdef _MSC_VER
# define FMT_MSC_VER _MSC_VER
#else
# define FMT_MSC_VER 0
#endif
#if FMT_MSC_VER && FMT_MSC_VER <= 1500
typedef unsigned __int32 uint32_t;
typedef unsigned __int64 uint64_t;
typedef __int64 intmax_t;
@@ -98,7 +97,13 @@ typedef __int64 intmax_t;
# define FMT_GCC_EXTENSION
#endif
#if defined(__clang__) && !defined(__INTEL_COMPILER)
#if defined(__INTEL_COMPILER)
# define FMT_ICC_VERSION __INTEL_COMPILER
#elif defined(__ICL)
# define FMT_ICC_VERSION __ICL
#endif
#if defined(__clang__) && !defined(FMT_ICC_VERSION)
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wdocumentation"
#endif
@@ -131,7 +136,7 @@ typedef __int64 intmax_t;
// since version 2013.
# define FMT_USE_VARIADIC_TEMPLATES \
(FMT_HAS_FEATURE(cxx_variadic_templates) || \
(FMT_GCC_VERSION >= 404 && FMT_HAS_GXX_CXX11) || _MSC_VER >= 1800)
(FMT_GCC_VERSION >= 404 && FMT_HAS_GXX_CXX11) || FMT_MSC_VER >= 1800)
#endif
#ifndef FMT_USE_RVALUE_REFERENCES
@@ -142,7 +147,7 @@ typedef __int64 intmax_t;
# else
# define FMT_USE_RVALUE_REFERENCES \
(FMT_HAS_FEATURE(cxx_rvalue_references) || \
(FMT_GCC_VERSION >= 403 && FMT_HAS_GXX_CXX11) || _MSC_VER >= 1600)
(FMT_GCC_VERSION >= 403 && FMT_HAS_GXX_CXX11) || FMT_MSC_VER >= 1600)
# endif
#endif
@@ -154,7 +159,7 @@ typedef __int64 intmax_t;
#if defined(__GNUC__) && !defined(__EXCEPTIONS)
# define FMT_EXCEPTIONS 0
#endif
#if defined(_MSC_VER) && !_HAS_EXCEPTIONS
#if FMT_MSC_VER && !_HAS_EXCEPTIONS
# define FMT_EXCEPTIONS 0
#endif
#ifndef FMT_EXCEPTIONS
@@ -169,7 +174,7 @@ typedef __int64 intmax_t;
# endif
#endif
// Define FMT_USE_NOEXCEPT to make C++ Format use noexcept (C++11 feature).
// Define FMT_USE_NOEXCEPT to make fmt use noexcept (C++11 feature).
#ifndef FMT_USE_NOEXCEPT
# define FMT_USE_NOEXCEPT 0
#endif
@@ -178,7 +183,7 @@ typedef __int64 intmax_t;
# if FMT_EXCEPTIONS
# if FMT_USE_NOEXCEPT || FMT_HAS_FEATURE(cxx_noexcept) || \
(FMT_GCC_VERSION >= 408 && FMT_HAS_GXX_CXX11) || \
_MSC_VER >= 1900
FMT_MSC_VER >= 1900
# define FMT_NOEXCEPT noexcept
# else
# define FMT_NOEXCEPT throw()
@@ -195,7 +200,7 @@ typedef __int64 intmax_t;
#endif
#if FMT_USE_DELETED_FUNCTIONS || FMT_HAS_FEATURE(cxx_deleted_functions) || \
(FMT_GCC_VERSION >= 404 && FMT_HAS_GXX_CXX11) || _MSC_VER >= 1800
(FMT_GCC_VERSION >= 404 && FMT_HAS_GXX_CXX11) || FMT_MSC_VER >= 1800
# define FMT_DELETED_OR_UNDEFINED = delete
# define FMT_DISALLOW_COPY_AND_ASSIGN(TypeName) \
TypeName(const TypeName&) = delete; \
@@ -211,10 +216,12 @@ typedef __int64 intmax_t;
// All compilers which support UDLs also support variadic templates. This
// makes the fmt::literals implementation easier. However, an explicit check
// for variadic templates is added here just in case.
// For Intel's compiler both it and the system gcc/msc must support UDLs.
# define FMT_USE_USER_DEFINED_LITERALS \
FMT_USE_VARIADIC_TEMPLATES && FMT_USE_RVALUE_REFERENCES && \
(FMT_HAS_FEATURE(cxx_user_literals) || \
(FMT_GCC_VERSION >= 407 && FMT_HAS_GXX_CXX11) || _MSC_VER >= 1900)
(FMT_GCC_VERSION >= 407 && FMT_HAS_GXX_CXX11) || FMT_MSC_VER >= 1900) && \
(!defined(FMT_ICC_VERSION) || FMT_ICC_VERSION >= 1500)
#endif
#ifndef FMT_ASSERT
@@ -234,7 +241,7 @@ typedef __int64 intmax_t;
// otherwise support __builtin_clz and __builtin_clzll, so
// only define FMT_BUILTIN_CLZ using the MSVC intrinsics
// if the clz and clzll builtins are not available.
#if defined(_MSC_VER) && !defined(FMT_BUILTIN_CLZLL)
#if FMT_MSC_VER && !defined(FMT_BUILTIN_CLZLL)
# include <intrin.h> // _BitScanReverse, _BitScanReverse64
namespace fmt {
@@ -371,18 +378,13 @@ class BasicWriter;
typedef BasicWriter<char> Writer;
typedef BasicWriter<wchar_t> WWriter;
namespace internal {
template <typename Char>
class BasicArgFormatter;
}
class ArgFormatter;
template <typename CharType,
typename ArgFormatter = internal::BasicArgFormatter<CharType> >
typename ArgFormatter = fmt::ArgFormatter<CharType> >
class BasicFormatter;
template <typename Char, typename T>
void format(BasicFormatter<Char> &f, const Char *&format_str, const T &value);
/**
\rst
A string reference. It can be constructed from a C string or ``std::string``.
@@ -834,6 +836,16 @@ struct FMT_API BasicData {
static const char DIGITS[];
};
#ifndef FMT_USE_EXTERN_TEMPLATES
// Clang doesn't have a feature check for extern templates so we check
// for variadic templates which were introduced in the same version.
# define FMT_USE_EXTERN_TEMPLATES (__clang__ && FMT_USE_VARIADIC_TEMPLATES)
#endif
#if FMT_USE_EXTERN_TEMPLATES
extern template struct BasicData<void>;
#endif
typedef BasicData<> Data;
#ifdef FMT_BUILTIN_CLZLL
@@ -871,9 +883,56 @@ inline unsigned count_digits(uint32_t n) {
}
#endif
// A functor that doesn't add a thousands separator.
struct NoThousandsSep {
template <typename Char>
void operator()(Char *) {}
};
// A functor that adds a thousands separator.
class ThousandsSep {
private:
fmt::StringRef sep_;
// Index of a decimal digit with the least significant digit having index 0.
unsigned digit_index_;
public:
explicit ThousandsSep(fmt::StringRef sep) : sep_(sep), digit_index_(0) {}
template <typename Char>
void operator()(Char *&buffer) {
if (++digit_index_ % 3 != 0)
return;
buffer -= sep_.size();
std::uninitialized_copy(sep_.data(), sep_.data() + sep_.size(),
internal::make_ptr(buffer, sep_.size()));
}
};
// Returns the thousands separator for the current locale.
// On android the lconv structure is stubbed using an empty structure.
// The test is for the size only, not for the presense of
// thousands_sep in std::lconv, because if one would add thousands_sep
// at some point, the size of structure would be at least sizeof(char*).
template<typename Lconv, bool=(sizeof(Lconv) >= sizeof(char*))>
struct Locale {
static fmt::StringRef thousands_sep() { return ""; }
};
template<typename Lconv>
struct Locale<Lconv, true> {
static fmt::StringRef thousands_sep() {
return static_cast<Lconv*>(std::localeconv())->thousands_sep;
}
};
// Formats a decimal unsigned integer value writing into buffer.
template <typename UInt, typename Char>
inline void format_decimal(Char *buffer, UInt value, unsigned num_digits) {
// thousands_sep is a functor that is called after writing each char to
// add a thousands separator if necessary.
template <typename UInt, typename Char, typename ThousandsSep>
inline void format_decimal(Char *buffer, UInt value, unsigned num_digits,
ThousandsSep thousands_sep) {
buffer += num_digits;
while (value >= 100) {
// Integer division is slow so do it for a group of two digits instead
@@ -882,7 +941,9 @@ inline void format_decimal(Char *buffer, UInt value, unsigned num_digits) {
unsigned index = static_cast<unsigned>((value % 100) * 2);
value /= 100;
*--buffer = Data::DIGITS[index + 1];
thousands_sep(buffer);
*--buffer = Data::DIGITS[index];
thousands_sep(buffer);
}
if (value < 10) {
*--buffer = static_cast<char>('0' + value);
@@ -893,6 +954,11 @@ inline void format_decimal(Char *buffer, UInt value, unsigned num_digits) {
*--buffer = Data::DIGITS[index];
}
template <typename UInt, typename Char>
inline void format_decimal(Char *buffer, UInt value, unsigned num_digits) {
return format_decimal(buffer, value, num_digits, NoThousandsSep());
}
#ifndef _WIN32
# define FMT_USE_WINDOWS_H 0
#elif !defined(FMT_USE_WINDOWS_H)
@@ -940,9 +1006,6 @@ FMT_API void format_windows_error(fmt::Writer &out, int error_code,
fmt::StringRef message) FMT_NOEXCEPT;
#endif
FMT_API void format_system_error(fmt::Writer &out, int error_code,
fmt::StringRef message) FMT_NOEXCEPT;
// A formatting argument value.
struct Value {
template <typename Char>
@@ -1013,33 +1076,16 @@ struct WCharHelper<T, wchar_t> {
typedef char Yes[1];
typedef char No[2];
// These are non-members to workaround an overload resolution bug in bcc32.
Yes &convert(fmt::ULongLong);
Yes &convert(std::ostream &);
No &convert(...);
template <typename T>
T &get();
struct DummyStream : std::ostream {
DummyStream(); // Suppress a bogus warning in MSVC.
// Hide all operator<< overloads from std::ostream.
void operator<<(Null<>);
};
No &operator<<(std::ostream &, int);
// These are non-members to workaround an overload resolution bug in bcc32.
Yes &convert(fmt::ULongLong);
No &convert(...);
template<typename T, bool ENABLE_CONVERSION>
struct ConvertToIntImpl {
enum { value = false };
};
template<typename T>
struct ConvertToIntImpl<T, true> {
// Convert to int only if T doesn't have an overloaded operator<<.
enum {
value = sizeof(convert(get<DummyStream>() << get<T>())) == sizeof(No)
};
enum { value = ENABLE_CONVERSION };
};
template<typename T, bool ENABLE_CONVERSION>
@@ -1110,7 +1156,7 @@ class MakeValue : public Arg {
// characters and strings into narrow strings as in
// fmt::format("{}", L"test");
// To fix this, use a wide format string: fmt::format(L"{}", L"test").
#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
#if !FMT_MSC_VER || defined(_NATIVE_WCHAR_T_DEFINED)
MakeValue(typename WCharHelper<wchar_t, Char>::Unsupported);
#endif
MakeValue(typename WCharHelper<wchar_t *, Char>::Unsupported);
@@ -1269,123 +1315,6 @@ struct NamedArg : Arg {
: Arg(MakeArg< BasicFormatter<Char> >(value)), name(argname) {}
};
#define FMT_DISPATCH(call) static_cast<Impl*>(this)->call
// An argument visitor.
// To use ArgVisitor define a subclass that implements some or all of the
// visit methods with the same signatures as the methods in ArgVisitor,
// for example, visit_int(int).
// Specify the subclass name as the Impl template parameter. Then calling
// ArgVisitor::visit for some argument will dispatch to a visit method
// specific to the argument type. For example, if the argument type is
// double then visit_double(double) method of a subclass will be called.
// If the subclass doesn't contain a method with this signature, then
// a corresponding method of ArgVisitor will be called.
//
// Example:
// class MyArgVisitor : public ArgVisitor<MyArgVisitor, void> {
// public:
// void visit_int(int value) { print("{}", value); }
// void visit_double(double value) { print("{}", value ); }
// };
//
// ArgVisitor uses the curiously recurring template pattern:
// http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern
template <typename Impl, typename Result>
class ArgVisitor {
public:
void report_unhandled_arg() {}
Result visit_unhandled_arg() {
FMT_DISPATCH(report_unhandled_arg());
return Result();
}
Result visit_int(int value) {
return FMT_DISPATCH(visit_any_int(value));
}
Result visit_long_long(LongLong value) {
return FMT_DISPATCH(visit_any_int(value));
}
Result visit_uint(unsigned value) {
return FMT_DISPATCH(visit_any_int(value));
}
Result visit_ulong_long(ULongLong value) {
return FMT_DISPATCH(visit_any_int(value));
}
Result visit_bool(bool value) {
return FMT_DISPATCH(visit_any_int(value));
}
Result visit_char(int value) {
return FMT_DISPATCH(visit_any_int(value));
}
template <typename T>
Result visit_any_int(T) {
return FMT_DISPATCH(visit_unhandled_arg());
}
Result visit_double(double value) {
return FMT_DISPATCH(visit_any_double(value));
}
Result visit_long_double(long double value) {
return FMT_DISPATCH(visit_any_double(value));
}
template <typename T>
Result visit_any_double(T) {
return FMT_DISPATCH(visit_unhandled_arg());
}
Result visit_cstring(const char *) {
return FMT_DISPATCH(visit_unhandled_arg());
}
Result visit_string(Arg::StringValue<char>) {
return FMT_DISPATCH(visit_unhandled_arg());
}
Result visit_wstring(Arg::StringValue<wchar_t>) {
return FMT_DISPATCH(visit_unhandled_arg());
}
Result visit_pointer(const void *) {
return FMT_DISPATCH(visit_unhandled_arg());
}
Result visit_custom(Arg::CustomValue) {
return FMT_DISPATCH(visit_unhandled_arg());
}
Result visit(const Arg &arg) {
switch (arg.type) {
default:
FMT_ASSERT(false, "invalid argument type");
return Result();
case Arg::INT:
return FMT_DISPATCH(visit_int(arg.int_value));
case Arg::UINT:
return FMT_DISPATCH(visit_uint(arg.uint_value));
case Arg::LONG_LONG:
return FMT_DISPATCH(visit_long_long(arg.long_long_value));
case Arg::ULONG_LONG:
return FMT_DISPATCH(visit_ulong_long(arg.ulong_long_value));
case Arg::BOOL:
return FMT_DISPATCH(visit_bool(arg.int_value != 0));
case Arg::CHAR:
return FMT_DISPATCH(visit_char(arg.int_value));
case Arg::DOUBLE:
return FMT_DISPATCH(visit_double(arg.double_value));
case Arg::LONG_DOUBLE:
return FMT_DISPATCH(visit_long_double(arg.long_double_value));
case Arg::CSTRING:
return FMT_DISPATCH(visit_cstring(arg.string.value));
case Arg::STRING:
return FMT_DISPATCH(visit_string(arg.string));
case Arg::WSTRING:
return FMT_DISPATCH(visit_wstring(arg.wstring));
case Arg::POINTER:
return FMT_DISPATCH(visit_pointer(arg.pointer));
case Arg::CUSTOM:
return FMT_DISPATCH(visit_custom(arg.custom));
}
}
};
class RuntimeError : public std::runtime_error {
protected:
RuntimeError() : std::runtime_error("") {}
@@ -1462,6 +1391,165 @@ class ArgList {
}
};
#define FMT_DISPATCH(call) static_cast<Impl*>(this)->call
/**
\rst
An argument visitor based on the `curiously recurring template pattern
<http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern>`_.
To use `~fmt::ArgVisitor` define a subclass that implements some or all of the
visit methods with the same signatures as the methods in `~fmt::ArgVisitor`,
for example, `~fmt::ArgVisitor::visit_int()`.
Pass the subclass as the *Impl* template parameter. Then calling
`~fmt::ArgVisitor::visit` for some argument will dispatch to a visit method
specific to the argument type. For example, if the argument type is
``double`` then the `~fmt::ArgVisitor::visit_double()` method of a subclass
will be called. If the subclass doesn't contain a method with this signature,
then a corresponding method of `~fmt::ArgVisitor` will be called.
**Example**::
class MyArgVisitor : public fmt::ArgVisitor<MyArgVisitor, void> {
public:
void visit_int(int value) { fmt::print("{}", value); }
void visit_double(double value) { fmt::print("{}", value ); }
};
\endrst
*/
template <typename Impl, typename Result>
class ArgVisitor {
private:
typedef internal::Arg Arg;
public:
void report_unhandled_arg() {}
Result visit_unhandled_arg() {
FMT_DISPATCH(report_unhandled_arg());
return Result();
}
/** Visits an ``int`` argument. **/
Result visit_int(int value) {
return FMT_DISPATCH(visit_any_int(value));
}
/** Visits a ``long long`` argument. **/
Result visit_long_long(LongLong value) {
return FMT_DISPATCH(visit_any_int(value));
}
/** Visits an ``unsigned`` argument. **/
Result visit_uint(unsigned value) {
return FMT_DISPATCH(visit_any_int(value));
}
/** Visits an ``unsigned long long`` argument. **/
Result visit_ulong_long(ULongLong value) {
return FMT_DISPATCH(visit_any_int(value));
}
/** Visits a ``bool`` argument. **/
Result visit_bool(bool value) {
return FMT_DISPATCH(visit_any_int(value));
}
/** Visits a ``char`` or ``wchar_t`` argument. **/
Result visit_char(int value) {
return FMT_DISPATCH(visit_any_int(value));
}
/** Visits an argument of any integral type. **/
template <typename T>
Result visit_any_int(T) {
return FMT_DISPATCH(visit_unhandled_arg());
}
/** Visits a ``double`` argument. **/
Result visit_double(double value) {
return FMT_DISPATCH(visit_any_double(value));
}
/** Visits a ``long double`` argument. **/
Result visit_long_double(long double value) {
return FMT_DISPATCH(visit_any_double(value));
}
/** Visits a ``double`` or ``long double`` argument. **/
template <typename T>
Result visit_any_double(T) {
return FMT_DISPATCH(visit_unhandled_arg());
}
/** Visits a null-terminated C string (``const char *``) argument. **/
Result visit_cstring(const char *) {
return FMT_DISPATCH(visit_unhandled_arg());
}
/** Visits a string argument. **/
Result visit_string(Arg::StringValue<char>) {
return FMT_DISPATCH(visit_unhandled_arg());
}
/** Visits a wide string argument. **/
Result visit_wstring(Arg::StringValue<wchar_t>) {
return FMT_DISPATCH(visit_unhandled_arg());
}
/** Visits a pointer argument. **/
Result visit_pointer(const void *) {
return FMT_DISPATCH(visit_unhandled_arg());
}
/** Visits an argument of a custom (user-defined) type. **/
Result visit_custom(Arg::CustomValue) {
return FMT_DISPATCH(visit_unhandled_arg());
}
/**
\rst
Visits an argument dispatching to the appropriate visit method based on
the argument type. For example, if the argument type is ``double`` then
the `~fmt::ArgVisitor::visit_double()` method of the *Impl* class will be
called.
\endrst
*/
Result visit(const Arg &arg) {
switch (arg.type) {
default:
FMT_ASSERT(false, "invalid argument type");
return Result();
case Arg::INT:
return FMT_DISPATCH(visit_int(arg.int_value));
case Arg::UINT:
return FMT_DISPATCH(visit_uint(arg.uint_value));
case Arg::LONG_LONG:
return FMT_DISPATCH(visit_long_long(arg.long_long_value));
case Arg::ULONG_LONG:
return FMT_DISPATCH(visit_ulong_long(arg.ulong_long_value));
case Arg::BOOL:
return FMT_DISPATCH(visit_bool(arg.int_value != 0));
case Arg::CHAR:
return FMT_DISPATCH(visit_char(arg.int_value));
case Arg::DOUBLE:
return FMT_DISPATCH(visit_double(arg.double_value));
case Arg::LONG_DOUBLE:
return FMT_DISPATCH(visit_long_double(arg.long_double_value));
case Arg::CSTRING:
return FMT_DISPATCH(visit_cstring(arg.string.value));
case Arg::STRING:
return FMT_DISPATCH(visit_string(arg.string));
case Arg::WSTRING:
return FMT_DISPATCH(visit_wstring(arg.wstring));
case Arg::POINTER:
return FMT_DISPATCH(visit_pointer(arg.pointer));
case Arg::CUSTOM:
return FMT_DISPATCH(visit_custom(arg.custom));
}
}
};
enum Alignment {
ALIGN_DEFAULT, ALIGN_LEFT, ALIGN_RIGHT, ALIGN_CENTER, ALIGN_NUMERIC
};
@@ -1688,7 +1776,8 @@ namespace internal {
template <typename Char>
class ArgMap {
private:
typedef std::vector<std::pair<fmt::BasicStringRef<Char>, internal::Arg> > MapType;
typedef std::vector<
std::pair<fmt::BasicStringRef<Char>, internal::Arg> > MapType;
typedef typename MapType::value_type Pair;
MapType map_;
@@ -1805,24 +1894,6 @@ class ArgFormatterBase : public ArgVisitor<Impl, void> {
}
};
// An argument formatter.
template <typename Char>
class BasicArgFormatter :
public ArgFormatterBase<BasicArgFormatter<Char>, Char> {
private:
BasicFormatter<Char> &formatter_;
const Char *format_;
public:
BasicArgFormatter(BasicFormatter<Char> &f, FormatSpec &s, const Char *fmt)
: ArgFormatterBase<BasicArgFormatter<Char>, Char>(f.writer(), s),
formatter_(f), format_(fmt) {}
void visit_custom(Arg::CustomValue c) {
c.format(&formatter_, c.value, &format_);
}
};
class FormatterBase {
private:
ArgList args_;
@@ -1890,6 +1961,59 @@ class PrintfFormatter : private FormatterBase {
};
} // namespace internal
/**
\rst
An argument formatter based on the `curiously recurring template pattern
<http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern>`_.
To use `~fmt::BasicArgFormatter` define a subclass that implements some or
all of the visit methods with the same signatures as the methods in
`~fmt::ArgVisitor`, for example, `~fmt::ArgVisitor::visit_int()`.
Pass the subclass as the *Impl* template parameter. When a formatting
function processes an argument, it will dispatch to a visit method
specific to the argument type. For example, if the argument type is
``double`` then the `~fmt::ArgVisitor::visit_double()` method of a subclass
will be called. If the subclass doesn't contain a method with this signature,
then a corresponding method of `~fmt::BasicArgFormatter` or its superclass
will be called.
\endrst
*/
template <typename Impl, typename Char>
class BasicArgFormatter : public internal::ArgFormatterBase<Impl, Char> {
private:
BasicFormatter<Char, Impl> &formatter_;
const Char *format_;
public:
/**
\rst
Constructs an argument formatter object.
*formatter* is a reference to the main formatter object, *spec* contains
format specifier information for standard argument types, and *fmt* points
to the part of the format string being parsed for custom argument types.
\endrst
*/
BasicArgFormatter(BasicFormatter<Char, Impl> &formatter,
FormatSpec &spec, const Char *fmt)
: internal::ArgFormatterBase<Impl, Char>(formatter.writer(), spec),
formatter_(formatter), format_(fmt) {}
/** Formats argument of a custom (user-defined) type. */
void visit_custom(internal::Arg::CustomValue c) {
c.format(&formatter_, c.value, &format_);
}
};
/** The default argument formatter. */
template <typename Char>
class ArgFormatter : public BasicArgFormatter<ArgFormatter<Char>, Char> {
public:
/** Constructs an argument formatter object. */
ArgFormatter(BasicFormatter<Char> &formatter,
FormatSpec &spec, const Char *fmt)
: BasicArgFormatter<ArgFormatter<Char>, Char>(formatter, spec, fmt) {}
};
/** This template formats data and writes the output to a writer. */
template <typename CharType, typename ArgFormatter>
class BasicFormatter : private internal::FormatterBase {
@@ -1972,11 +2096,15 @@ struct ArgArray<N, true/*IsPacked*/> {
template <typename Formatter, typename T>
static Value make(const T &value) {
#ifdef __clang__
Value result = MakeValue<Formatter>(value);
// Workaround a bug in Apple LLVM version 4.2 (clang-425.0.28) of clang:
// https://github.com/cppformat/cppformat/issues/276
// https://github.com/fmtlib/fmt/issues/276
(void)result.custom.format;
return result;
#else
return MakeValue<Formatter>(value);
#endif
}
};
@@ -2014,38 +2142,6 @@ inline uint64_t make_type(FMT_GEN15(FMT_ARG_TYPE_DEFAULT)) {
(t12.type << 48) | (t13.type << 52) | (t14.type << 56);
}
#endif
template <class Char>
class FormatBuf : public std::basic_streambuf<Char> {
private:
typedef typename std::basic_streambuf<Char>::int_type int_type;
typedef typename std::basic_streambuf<Char>::traits_type traits_type;
Buffer<Char> &buffer_;
Char *start_;
public:
FormatBuf(Buffer<Char> &buffer) : buffer_(buffer), start_(&buffer[0]) {
this->setp(start_, start_ + buffer_.capacity());
}
int_type overflow(int_type ch = traits_type::eof()) {
if (!traits_type::eq_int_type(ch, traits_type::eof())) {
size_t size = this->size();
buffer_.resize(size);
buffer_.reserve(size * 2);
start_ = &buffer_[0];
start_[size] = traits_type::to_char_type(ch);
this->setp(start_+ size + 1, start_ + size * 2);
}
return ch;
}
size_t size() const {
return to_unsigned(this->pptr() - start_);
}
};
} // namespace internal
# define FMT_MAKE_TEMPLATE_ARG(n) typename T##n
@@ -2164,17 +2260,10 @@ class SystemError : public internal::RuntimeError {
public:
/**
\rst
Constructs a :class:`fmt::SystemError` object with the description
of the form
.. parsed-literal::
*<message>*: *<system-message>*
where *<message>* is the formatted message and *<system-message>* is
the system message corresponding to the error code.
*error_code* is a system error code as given by ``errno``.
If *error_code* is not a valid error code such as -1, the system message
may look like "Unknown error -1" and is platform-dependent.
Constructs a :class:`fmt::SystemError` object with a description
formatted with `fmt::format_system_error`. *message* and additional
arguments passed into the constructor are formatted similarly to
`fmt::format`.
**Example**::
@@ -2195,6 +2284,25 @@ class SystemError : public internal::RuntimeError {
int error_code() const { return error_code_; }
};
/**
\rst
Formats an error returned by an operating system or a language runtime,
for example a file opening error, and writes it to *out* in the following
form:
.. parsed-literal::
*<message>*: *<system-message>*
where *<message>* is the passed message and *<system-message>* is
the system message corresponding to the error code.
*error_code* is a system error code as given by ``errno``.
If *error_code* is not a valid error code such as -1, the system message
may look like "Unknown error -1" and is platform-dependent.
\endrst
*/
FMT_API void format_system_error(fmt::Writer &out, int error_code,
fmt::StringRef message) FMT_NOEXCEPT;
/**
\rst
This template provides operations for formatting and writing data into
@@ -2482,6 +2590,8 @@ class BasicWriter {
}
void clear() FMT_NOEXCEPT { buffer_.clear(); }
Buffer<Char> &buffer() FMT_NOEXCEPT { return buffer_; }
};
template <typename Char>
@@ -2627,9 +2737,8 @@ void BasicWriter<Char>::write_int(T value, Spec spec) {
switch (spec.type()) {
case 0: case 'd': {
unsigned num_digits = internal::count_digits(abs_value);
CharPtr p = prepare_int_buffer(
num_digits, spec, prefix, prefix_size) + 1 - num_digits;
internal::format_decimal(get(p), abs_value, num_digits);
CharPtr p = prepare_int_buffer(num_digits, spec, prefix, prefix_size) + 1;
internal::format_decimal(get(p), abs_value, 0);
break;
}
case 'x': case 'X': {
@@ -2684,6 +2793,15 @@ void BasicWriter<Char>::write_int(T value, Spec spec) {
} while ((n >>= 3) != 0);
break;
}
case 'n': {
unsigned num_digits = internal::count_digits(abs_value);
fmt::StringRef sep = internal::Locale<lconv>::thousands_sep();
unsigned size = static_cast<unsigned>(
num_digits + sep.size() * (num_digits - 1) / 3);
CharPtr p = prepare_int_buffer(size, spec, prefix, prefix_size) + 1;
internal::format_decimal(get(p), abs_value, 0, internal::ThousandsSep(sep));
break;
}
default:
internal::report_unknown_type(
spec.type(), spec.flag(CHAR_FLAG) ? "char" : "integer");
@@ -2704,7 +2822,7 @@ void BasicWriter<Char>::write_double(T value, const FormatSpec &spec) {
case 'e': case 'f': case 'g': case 'a':
break;
case 'F':
#ifdef _MSC_VER
#if FMT_MSC_VER
// MSVC's printf doesn't support 'F'.
type = 'f';
#endif
@@ -2797,7 +2915,7 @@ void BasicWriter<Char>::write_double(T value, const FormatSpec &spec) {
Char *start = 0;
for (;;) {
std::size_t buffer_size = buffer_.capacity() - offset;
#ifdef _MSC_VER
#if FMT_MSC_VER
// MSVC's vsnprintf_s doesn't work with zero size, so reserve
// space for at least one extra character to make the size non-zero.
// Note that the buffer's capacity will increase by more than 1.
@@ -2964,20 +3082,6 @@ class BasicArrayWriter : public BasicWriter<Char> {
typedef BasicArrayWriter<char> ArrayWriter;
typedef BasicArrayWriter<wchar_t> WArrayWriter;
// Formats a value.
template <typename Char, typename T>
void format(BasicFormatter<Char> &f, const Char *&format_str, const T &value) {
internal::MemoryBuffer<Char, internal::INLINE_BUFFER_SIZE> buffer;
internal::FormatBuf<Char> format_buf(buffer);
std::basic_ostream<Char> output(&format_buf);
output << value;
BasicStringRef<Char> str(&buffer[0], format_buf.size());
typedef internal::MakeArg< BasicFormatter<Char> > MakeArg;
format_str = f.format(format_str, MakeArg(str));
}
// Reports a system error without throwing an exception.
// Can be used to report errors from destructors.
FMT_API void report_system_error(int error_code,
@@ -3407,32 +3511,6 @@ FMT_VARIADIC_W(std::wstring, sprintf, WCStringRef)
FMT_VARIADIC(int, printf, CStringRef)
FMT_VARIADIC(int, fprintf, std::FILE *, CStringRef)
#if FMT_USE_IOSTREAMS
/**
\rst
Prints formatted data to the stream *os*.
**Example**::
print(cerr, "Don't {}!", "panic");
\endrst
*/
FMT_API void print(std::ostream &os, CStringRef format_str, ArgList args);
FMT_VARIADIC(void, print, std::ostream &, CStringRef)
/**
\rst
Prints formatted data to the stream *os*.
**Example**::
fprintf(cerr, "Don't %s!", "panic");
\endrst
*/
FMT_API int fprintf(std::ostream &os, CStringRef format_str, ArgList args);
FMT_VARIADIC(int, fprintf, std::ostream &, CStringRef)
#endif
namespace internal {
template <typename Char>
inline bool is_name_start(Char c) {
@@ -3782,12 +3860,15 @@ operator"" _a(const wchar_t *s, std::size_t) { return {s}; }
# pragma GCC diagnostic pop
#endif
#if defined(__clang__) && !defined(__INTEL_COMPILER)
#if defined(__clang__) && !defined(FMT_ICC_VERSION)
# pragma clang diagnostic pop
#endif
#ifdef FMT_HEADER_ONLY
# define FMT_FUNC inline
# include "format.cc"
#else
# define FMT_FUNC
#endif
#endif // FMT_FORMAT_H_

133
include/fmt/ostream.h Normal file
View File

@@ -0,0 +1,133 @@
/*
Formatting library for C++ - std::ostream support
Copyright (c) 2012 - 2016, Victor Zverovich
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef FMT_OSTREAM_H_
#define FMT_OSTREAM_H_
#include "format.h"
#include <ostream>
namespace fmt {
namespace internal {
template <class Char>
class FormatBuf : public std::basic_streambuf<Char> {
private:
typedef typename std::basic_streambuf<Char>::int_type int_type;
typedef typename std::basic_streambuf<Char>::traits_type traits_type;
Buffer<Char> &buffer_;
Char *start_;
public:
FormatBuf(Buffer<Char> &buffer) : buffer_(buffer), start_(&buffer[0]) {
this->setp(start_, start_ + buffer_.capacity());
}
int_type overflow(int_type ch = traits_type::eof()) {
if (!traits_type::eq_int_type(ch, traits_type::eof())) {
size_t buf_size = size();
buffer_.resize(buf_size);
buffer_.reserve(buf_size * 2);
start_ = &buffer_[0];
start_[buf_size] = traits_type::to_char_type(ch);
this->setp(start_+ buf_size + 1, start_ + buf_size * 2);
}
return ch;
}
size_t size() const {
return to_unsigned(this->pptr() - start_);
}
};
Yes &convert(std::ostream &);
struct DummyStream : std::ostream {
DummyStream(); // Suppress a bogus warning in MSVC.
// Hide all operator<< overloads from std::ostream.
void operator<<(Null<>);
};
No &operator<<(std::ostream &, int);
template<typename T>
struct ConvertToIntImpl<T, true> {
// Convert to int only if T doesn't have an overloaded operator<<.
enum {
value = sizeof(convert(get<DummyStream>() << get<T>())) == sizeof(No)
};
};
} // namespace internal
// Formats a value.
template <typename Char, typename ArgFormatter, typename T>
void format(BasicFormatter<Char, ArgFormatter> &f,
const Char *&format_str, const T &value) {
internal::MemoryBuffer<Char, internal::INLINE_BUFFER_SIZE> buffer;
internal::FormatBuf<Char> format_buf(buffer);
std::basic_ostream<Char> output(&format_buf);
output << value;
BasicStringRef<Char> str(&buffer[0], format_buf.size());
typedef internal::MakeArg< BasicFormatter<Char> > MakeArg;
format_str = f.format(format_str, MakeArg(str));
}
/**
\rst
Prints formatted data to the stream *os*.
**Example**::
print(cerr, "Don't {}!", "panic");
\endrst
*/
FMT_API void print(std::ostream &os, CStringRef format_str, ArgList args);
FMT_VARIADIC(void, print, std::ostream &, CStringRef)
/**
\rst
Prints formatted data to the stream *os*.
**Example**::
fprintf(cerr, "Don't %s!", "panic");
\endrst
*/
FMT_API int fprintf(std::ostream &os, CStringRef format_str, ArgList args);
FMT_VARIADIC(int, fprintf, std::ostream &, CStringRef)
} // namespace fmt
#ifdef FMT_HEADER_ONLY
# include "ostream.cc"
#endif
#endif // FMT_OSTREAM_H_

403
include/fmt/posix.h Normal file
View File

@@ -0,0 +1,403 @@
/*
A C++ interface to POSIX functions.
Copyright (c) 2014 - 2016, Victor Zverovich
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef FMT_POSIX_H_
#define FMT_POSIX_H_
#ifdef __MINGW32__
// Workaround MinGW bug https://sourceforge.net/p/mingw/bugs/2024/.
# undef __STRICT_ANSI__
#endif
#include <errno.h>
#include <fcntl.h> // for O_RDONLY
#include <locale.h> // for locale_t
#include <stdio.h>
#include <stdlib.h> // for strtod_l
#include <cstddef>
#ifdef __APPLE__
# include <xlocale.h> // for LC_NUMERIC_MASK on OS X
#endif
#include "format.h"
#ifndef FMT_POSIX
# if defined(_WIN32) && !defined(__MINGW32__)
// Fix warnings about deprecated symbols.
# define FMT_POSIX(call) _##call
# else
# define FMT_POSIX(call) call
# endif
#endif
// Calls to system functions are wrapped in FMT_SYSTEM for testability.
#ifdef FMT_SYSTEM
# define FMT_POSIX_CALL(call) FMT_SYSTEM(call)
#else
# define FMT_SYSTEM(call) call
# ifdef _WIN32
// Fix warnings about deprecated symbols.
# define FMT_POSIX_CALL(call) ::_##call
# else
# define FMT_POSIX_CALL(call) ::call
# endif
#endif
#if FMT_GCC_VERSION >= 407
# define FMT_UNUSED __attribute__((unused))
#else
# define FMT_UNUSED
#endif
#ifndef FMT_USE_STATIC_ASSERT
# define FMT_USE_STATIC_ASSERT 0
#endif
#if FMT_USE_STATIC_ASSERT || FMT_HAS_FEATURE(cxx_static_assert) || \
(FMT_GCC_VERSION >= 403 && FMT_HAS_GXX_CXX11) || _MSC_VER >= 1600
# define FMT_STATIC_ASSERT(cond, message) static_assert(cond, message)
#else
# define FMT_CONCAT_(a, b) FMT_CONCAT(a, b)
# define FMT_STATIC_ASSERT(cond, message) \
typedef int FMT_CONCAT_(Assert, __LINE__)[(cond) ? 1 : -1] FMT_UNUSED
#endif
// Retries the expression while it evaluates to error_result and errno
// equals to EINTR.
#ifndef _WIN32
# define FMT_RETRY_VAL(result, expression, error_result) \
do { \
result = (expression); \
} while (result == error_result && errno == EINTR)
#else
# define FMT_RETRY_VAL(result, expression, error_result) result = (expression)
#endif
#define FMT_RETRY(result, expression) FMT_RETRY_VAL(result, expression, -1)
namespace fmt {
// An error code.
class ErrorCode {
private:
int value_;
public:
explicit ErrorCode(int value = 0) FMT_NOEXCEPT : value_(value) {}
int get() const FMT_NOEXCEPT { return value_; }
};
// A buffered file.
class BufferedFile {
private:
FILE *file_;
friend class File;
explicit BufferedFile(FILE *f) : file_(f) {}
public:
// Constructs a BufferedFile object which doesn't represent any file.
BufferedFile() FMT_NOEXCEPT : file_(0) {}
// Destroys the object closing the file it represents if any.
~BufferedFile() FMT_NOEXCEPT;
#if !FMT_USE_RVALUE_REFERENCES
// Emulate a move constructor and a move assignment operator if rvalue
// references are not supported.
private:
// A proxy object to emulate a move constructor.
// It is private to make it impossible call operator Proxy directly.
struct Proxy {
FILE *file;
};
public:
// A "move constructor" for moving from a temporary.
BufferedFile(Proxy p) FMT_NOEXCEPT : file_(p.file) {}
// A "move constructor" for moving from an lvalue.
BufferedFile(BufferedFile &f) FMT_NOEXCEPT : file_(f.file_) {
f.file_ = 0;
}
// A "move assignment operator" for moving from a temporary.
BufferedFile &operator=(Proxy p) {
close();
file_ = p.file;
return *this;
}
// A "move assignment operator" for moving from an lvalue.
BufferedFile &operator=(BufferedFile &other) {
close();
file_ = other.file_;
other.file_ = 0;
return *this;
}
// Returns a proxy object for moving from a temporary:
// BufferedFile file = BufferedFile(...);
operator Proxy() FMT_NOEXCEPT {
Proxy p = {file_};
file_ = 0;
return p;
}
#else
private:
FMT_DISALLOW_COPY_AND_ASSIGN(BufferedFile);
public:
BufferedFile(BufferedFile &&other) FMT_NOEXCEPT : file_(other.file_) {
other.file_ = 0;
}
BufferedFile& operator=(BufferedFile &&other) {
close();
file_ = other.file_;
other.file_ = 0;
return *this;
}
#endif
// Opens a file.
BufferedFile(CStringRef filename, CStringRef mode);
// Closes the file.
void close();
// Returns the pointer to a FILE object representing this file.
FILE *get() const FMT_NOEXCEPT { return file_; }
// We place parentheses around fileno to workaround a bug in some versions
// of MinGW that define fileno as a macro.
int (fileno)() const;
void print(CStringRef format_str, const ArgList &args) {
fmt::print(file_, format_str, args);
}
FMT_VARIADIC(void, print, CStringRef)
};
// A file. Closed file is represented by a File object with descriptor -1.
// Methods that are not declared with FMT_NOEXCEPT may throw
// fmt::SystemError in case of failure. Note that some errors such as
// closing the file multiple times will cause a crash on Windows rather
// than an exception. You can get standard behavior by overriding the
// invalid parameter handler with _set_invalid_parameter_handler.
class File {
private:
int fd_; // File descriptor.
// Constructs a File object with a given descriptor.
explicit File(int fd) : fd_(fd) {}
public:
// Possible values for the oflag argument to the constructor.
enum {
RDONLY = FMT_POSIX(O_RDONLY), // Open for reading only.
WRONLY = FMT_POSIX(O_WRONLY), // Open for writing only.
RDWR = FMT_POSIX(O_RDWR) // Open for reading and writing.
};
// Constructs a File object which doesn't represent any file.
File() FMT_NOEXCEPT : fd_(-1) {}
// Opens a file and constructs a File object representing this file.
File(CStringRef path, int oflag);
#if !FMT_USE_RVALUE_REFERENCES
// Emulate a move constructor and a move assignment operator if rvalue
// references are not supported.
private:
// A proxy object to emulate a move constructor.
// It is private to make it impossible call operator Proxy directly.
struct Proxy {
int fd;
};
public:
// A "move constructor" for moving from a temporary.
File(Proxy p) FMT_NOEXCEPT : fd_(p.fd) {}
// A "move constructor" for moving from an lvalue.
File(File &other) FMT_NOEXCEPT : fd_(other.fd_) {
other.fd_ = -1;
}
// A "move assignment operator" for moving from a temporary.
File &operator=(Proxy p) {
close();
fd_ = p.fd;
return *this;
}
// A "move assignment operator" for moving from an lvalue.
File &operator=(File &other) {
close();
fd_ = other.fd_;
other.fd_ = -1;
return *this;
}
// Returns a proxy object for moving from a temporary:
// File file = File(...);
operator Proxy() FMT_NOEXCEPT {
Proxy p = {fd_};
fd_ = -1;
return p;
}
#else
private:
FMT_DISALLOW_COPY_AND_ASSIGN(File);
public:
File(File &&other) FMT_NOEXCEPT : fd_(other.fd_) {
other.fd_ = -1;
}
File& operator=(File &&other) {
close();
fd_ = other.fd_;
other.fd_ = -1;
return *this;
}
#endif
// Destroys the object closing the file it represents if any.
~File() FMT_NOEXCEPT;
// Returns the file descriptor.
int descriptor() const FMT_NOEXCEPT { return fd_; }
// Closes the file.
void close();
// Returns the file size. The size has signed type for consistency with
// stat::st_size.
LongLong size() const;
// Attempts to read count bytes from the file into the specified buffer.
std::size_t read(void *buffer, std::size_t count);
// Attempts to write count bytes from the specified buffer to the file.
std::size_t write(const void *buffer, std::size_t count);
// Duplicates a file descriptor with the dup function and returns
// the duplicate as a file object.
static File dup(int fd);
// Makes fd be the copy of this file descriptor, closing fd first if
// necessary.
void dup2(int fd);
// Makes fd be the copy of this file descriptor, closing fd first if
// necessary.
void dup2(int fd, ErrorCode &ec) FMT_NOEXCEPT;
// Creates a pipe setting up read_end and write_end file objects for reading
// and writing respectively.
static void pipe(File &read_end, File &write_end);
// Creates a BufferedFile object associated with this file and detaches
// this File object from the file.
BufferedFile fdopen(const char *mode);
};
// Returns the memory page size.
long getpagesize();
#if defined(LC_NUMERIC_MASK) || defined(_MSC_VER)
# define FMT_LOCALE
#endif
#ifdef FMT_LOCALE
// A "C" numeric locale.
class Locale {
private:
# ifdef _MSC_VER
typedef _locale_t locale_t;
enum { LC_NUMERIC_MASK = LC_NUMERIC };
static locale_t newlocale(int category_mask, const char *locale, locale_t) {
return _create_locale(category_mask, locale);
}
static void freelocale(locale_t locale) {
_free_locale(locale);
}
static double strtod_l(const char *nptr, char **endptr, _locale_t locale) {
return _strtod_l(nptr, endptr, locale);
}
# endif
locale_t locale_;
FMT_DISALLOW_COPY_AND_ASSIGN(Locale);
public:
typedef locale_t Type;
Locale() : locale_(newlocale(LC_NUMERIC_MASK, "C", NULL)) {
if (!locale_)
throw fmt::SystemError(errno, "cannot create locale");
}
~Locale() { freelocale(locale_); }
Type get() const { return locale_; }
// Converts string to floating-point number and advances str past the end
// of the parsed input.
double strtod(const char *&str) const {
char *end = 0;
double result = strtod_l(str, &end, locale_);
str = end;
return result;
}
};
#endif // FMT_LOCALE
} // namespace fmt
#if !FMT_USE_RVALUE_REFERENCES
namespace std {
// For compatibility with C++98.
inline fmt::BufferedFile &move(fmt::BufferedFile &f) { return f; }
inline fmt::File &move(fmt::File &f) { return f; }
}
#endif
#endif // FMT_POSIX_H_

36
include/fmt/stringf.h Normal file
View File

@@ -0,0 +1,36 @@
/*
Formatting library for C++ - string utilities
Copyright (c) 2012 - 2016, Victor Zverovich
All rights reserved.
For the license information refer to format.h.
*/
#ifndef FMT_STRING_H_
#define FMT_STRING_H_
#include "format.h"
namespace fmt {
/**
\rst
Converts *value* to ``std::string`` using the default format for type *T*.
**Example**::
#include "fmt/string.h"
std::string answer = fmt::to_string(42);
\endrst
*/
template <typename T>
std::string to_string(const T &value) {
fmt::MemoryWriter w;
w << value;
return w.str();
}
}
#endif // FMT_STRING_H_

64
include/fmt/timef.h Normal file
View File

@@ -0,0 +1,64 @@
/*
Formatting library for C++ - time formatting
Copyright (c) 2012 - 2016, Victor Zverovich
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef FMT_TIME_H_
#define FMT_TIME_H_
#include "fmt/format.h"
#include <ctime>
namespace fmt {
template <typename ArgFormatter>
void format(BasicFormatter<char, ArgFormatter> &f,
const char *&format_str, const std::tm &tm) {
if (*format_str == ':')
++format_str;
const char *end = format_str;
while (*end && *end != '}')
++end;
if (*end != '}')
FMT_THROW(FormatError("missing '}' in format string"));
internal::MemoryBuffer<char, internal::INLINE_BUFFER_SIZE> format;
format.append(format_str, end + 1);
format[format.size() - 1] = '\0';
Buffer<char> &buffer = f.writer().buffer();
std::size_t start = buffer.size();
for (;;) {
std::size_t size = buffer.capacity() - start;
std::size_t count = std::strftime(&buffer[start], size, &format[0], &tm);
if (count != 0) {
buffer.resize(start + count);
break;
}
const std::size_t MIN_GROWTH = 10;
buffer.reserve(buffer.capacity() + size > MIN_GROWTH ? size : MIN_GROWTH);
}
format_str = end + 1;
}
}
#endif // FMT_TIME_H_