This commit is contained in:
commit
d55dee7042
30
README.rst
30
README.rst
@ -42,8 +42,8 @@ Features
|
||||
performance of IOStreams. See `Speed tests`_ and
|
||||
`Fast integer to string conversion in C++
|
||||
<http://zverovich.net/2013/09/07/integer-to-string-conversion-in-cplusplus.html>`_.
|
||||
* Small code size both in terms of source code (the core library consists of a
|
||||
single header file and a single source file) and compiled code.
|
||||
* Small code size both in terms of source code (the core library consists of two
|
||||
header files and a single source file) and compiled code.
|
||||
See `Compile time and code bloat`_.
|
||||
* Reliability: the library has an extensive set of `unit tests
|
||||
<https://github.com/fmtlib/fmt/tree/master/test>`_.
|
||||
@ -84,24 +84,24 @@ Format strings can be checked at compile time:
|
||||
.. code:: c++
|
||||
|
||||
// test.cc
|
||||
using namespace fmt::literals;
|
||||
std::string s = "{2}"_format(42);
|
||||
#include <fmt/format.h>
|
||||
std::string s = fmt::format(fmt("{2}"), 42);
|
||||
|
||||
.. code::
|
||||
|
||||
$ g++ -Iinclude test.cc -std=c++14
|
||||
...
|
||||
test.cc:5:31: note: in instantiation of function template specialization
|
||||
'fmt::internal::udl_formatter<char, '{', '2', '}'>::operator()<int>' requested
|
||||
here
|
||||
std::string s = "{2}"_format(42);
|
||||
^
|
||||
include/fmt/format.h:3838:7: note: non-constexpr function 'on_error' cannot be
|
||||
used in a constant expression
|
||||
on_error("argument index out of range");
|
||||
^
|
||||
test.cc:2:22: note: in instantiation of function template specialization 'fmt::format<S, int>' requested here
|
||||
std::string s = fmt::format(fmt("{2}"), 42);
|
||||
^
|
||||
include/fmt/core.h:749:19: note: non-constexpr function 'on_error' cannot be used in a constant expression
|
||||
ErrorHandler::on_error(message);
|
||||
^
|
||||
include/fmt/format.h:2081:16: note: in call to '&checker.context_->on_error(&"argument index out of range"[0])'
|
||||
context_.on_error("argument index out of range");
|
||||
^
|
||||
|
||||
fmt can be used as a safe portable replacement for ``itoa``:
|
||||
{fmt} can be used as a safe portable replacement for ``itoa``:
|
||||
|
||||
.. code:: c++
|
||||
|
||||
@ -159,6 +159,8 @@ Projects using this library
|
||||
|
||||
* `AMPL/MP <https://github.com/ampl/mp>`_:
|
||||
An open-source library for mathematical programming
|
||||
|
||||
* `AvioBook <https://www.aviobook.aero/en>`_: A comprehensive aircraft operations suite.
|
||||
|
||||
* `CUAUV <http://cuauv.org/>`_: Cornell University's autonomous underwater vehicle
|
||||
|
||||
|
||||
425
doc/api.rst
425
doc/api.rst
@ -4,52 +4,249 @@
|
||||
API Reference
|
||||
*************
|
||||
|
||||
All functions and classes provided by the fmt library reside
|
||||
in namespace ``fmt`` and macros have prefix ``FMT_``. For brevity the
|
||||
namespace is usually omitted in examples.
|
||||
The {fmt} library API consists of the following parts:
|
||||
|
||||
Format API
|
||||
==========
|
||||
* :ref:`fmt/core.h <core-api>`: the core API providing argument handling
|
||||
facilities and a lightweight subset of formatting functions
|
||||
* :ref:`fmt/format.h <format-api>`: the full format API providing compile-time
|
||||
format string checks, output iterator and user-defined type support
|
||||
* :ref:`fmt/time.h <time-api>`: date and time formatting
|
||||
* :ref:`fmt/ostream.h <ostream-api>`: ``std::ostream`` support
|
||||
* :ref:`fmt/printf.h <printf-api>`: ``printf`` formatting
|
||||
|
||||
The following functions defined in ``fmt/format.h`` use :ref:`format string
|
||||
syntax <syntax>` similar to the one used by Python's `str.format
|
||||
<http://docs.python.org/3/library/stdtypes.html#str.format>`_ function.
|
||||
All functions and types provided by the library reside in namespace ``fmt`` and
|
||||
macros have prefix ``FMT_`` or ``fmt``.
|
||||
|
||||
.. _core-api:
|
||||
|
||||
Core API
|
||||
========
|
||||
|
||||
``fmt/core.h`` defines the core API which provides argument handling facilities
|
||||
and a lightweight subset of formatting functions.
|
||||
|
||||
The following functions use :ref:`format string syntax <syntax>`
|
||||
imilar to that of Python's `str.format
|
||||
<http://docs.python.org/3/library/stdtypes.html#str.format>`_.
|
||||
They take *format_str* and *args* as arguments.
|
||||
|
||||
*format_str* is a format string that contains literal text and replacement
|
||||
fields surrounded by braces ``{}``. The fields are replaced with formatted
|
||||
arguments in the resulting string.
|
||||
|
||||
*args* is an argument list representing arbitrary arguments.
|
||||
|
||||
The `performance of the format API
|
||||
<https://github.com/fmtlib/fmt/blob/master/README.rst#speed-tests>`_ is close
|
||||
to that of glibc's ``printf`` and better than the performance of IOStreams.
|
||||
For even better speed use the `write API`_.
|
||||
*args* is an argument list representing objects to be formatted.
|
||||
|
||||
.. _format:
|
||||
|
||||
.. doxygenfunction:: format(CStringRef, ArgList)
|
||||
|
||||
.. doxygenfunction:: operator""_format(const char *, std::size_t)
|
||||
.. doxygenfunction:: format(string_view, const Args&...)
|
||||
.. doxygenfunction:: vformat(string_view, format_args)
|
||||
|
||||
.. _print:
|
||||
|
||||
.. doxygenfunction:: print(CStringRef, ArgList)
|
||||
.. doxygenfunction:: print(string_view, const Args&...)
|
||||
.. doxygenfunction:: vprint(string_view, format_args)
|
||||
|
||||
.. doxygenfunction:: print(std::FILE *, CStringRef, ArgList)
|
||||
.. doxygenfunction:: print(std::FILE *, string_view, const Args&...)
|
||||
.. doxygenfunction:: vprint(std::FILE *, string_view, format_args)
|
||||
|
||||
.. doxygenclass:: fmt::BasicFormatter
|
||||
.. _format-api:
|
||||
|
||||
Named arguments
|
||||
---------------
|
||||
|
||||
.. doxygenfunction:: fmt::arg(string_view, const T&)
|
||||
|
||||
Argument lists
|
||||
--------------
|
||||
|
||||
.. doxygenclass:: fmt::basic_format_args
|
||||
:members:
|
||||
|
||||
.. doxygenstruct:: fmt::format_args
|
||||
|
||||
.. doxygenfunction:: fmt::make_args(const Args&...)
|
||||
|
||||
Compatibility
|
||||
-------------
|
||||
|
||||
.. doxygenclass:: fmt::basic_string_view
|
||||
:members:
|
||||
|
||||
Format API
|
||||
==========
|
||||
|
||||
``fmt/format.h`` defines the full format API providing compile-time format
|
||||
string checks, output iterator and user-defined type support.
|
||||
|
||||
Compile-time format string checks
|
||||
---------------------------------
|
||||
|
||||
.. doxygendefine:: fmt
|
||||
|
||||
Formatting user-defined types
|
||||
-----------------------------
|
||||
|
||||
To make a user-defined type formattable, specialize the ``formatter<T>`` struct
|
||||
template and implement ``parse`` and ``format`` methods::
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
struct point { double x, y; };
|
||||
|
||||
namespace fmt {
|
||||
template <>
|
||||
struct formatter<point> {
|
||||
template <typename ParseContext>
|
||||
constexpr auto parse(ParseContext &ctx) { return ctx.begin(); }
|
||||
|
||||
template <typename FormatContext>
|
||||
auto format(const point &p, FormatContext &ctx) {
|
||||
return format_to(ctx.begin(), "({:.1f}, {:.1f})", p.x, p.y);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Then you can pass objects of type ``point`` to any formatting function::
|
||||
|
||||
point p = {1, 2};
|
||||
std::string s = fmt::format("{}", p);
|
||||
// s == "(1.0, 2.0)"
|
||||
|
||||
In the example above the ``formatter<point>::parse`` function ignores the
|
||||
contents of the format string referred to by ``ctx.begin()`` so the object will
|
||||
always be formatted in the same way. See ``formatter<tm>::parse`` in
|
||||
:file:`fmt/time.h` for an advanced example of how to parse the format string and
|
||||
customize the formatted output.
|
||||
|
||||
This section shows how to define a custom format function for a user-defined
|
||||
type. The next section describes how to get ``fmt`` to use a conventional stream
|
||||
output ``operator<<`` when one is defined for a user-defined type.
|
||||
|
||||
Output iterator support
|
||||
-----------------------
|
||||
|
||||
.. doxygenfunction:: fmt::format_to(OutputIt, string_view, const Args&...)
|
||||
|
||||
Literal-based API
|
||||
-----------------
|
||||
|
||||
The following user-defined literals are defined in ``fmt/format.h``.
|
||||
|
||||
.. doxygenfunction:: operator""_format(const char *, std::size_t)
|
||||
|
||||
.. doxygenfunction:: operator""_a(const char *, std::size_t)
|
||||
|
||||
Utilities
|
||||
---------
|
||||
|
||||
.. doxygenfunction:: fmt::to_string(const T&)
|
||||
|
||||
.. doxygenclass:: fmt::basic_memory_buffer
|
||||
:protected-members:
|
||||
:members:
|
||||
|
||||
System errors
|
||||
-------------
|
||||
|
||||
.. doxygenclass:: fmt::system_error
|
||||
:members:
|
||||
|
||||
.. doxygenfunction:: fmt::format_system_error
|
||||
|
||||
.. doxygenclass:: fmt::windows_error
|
||||
:members:
|
||||
|
||||
.. _formatstrings:
|
||||
|
||||
Custom allocators
|
||||
-----------------
|
||||
|
||||
The {fmt} library supports custom dynamic memory allocators.
|
||||
A custom allocator class can be specified as a template argument to
|
||||
:class:`fmt::basic_memory_buffer`::
|
||||
|
||||
using custom_memory_buffer =
|
||||
fmt::basic_memory_buffer<char, fmt::inline_buffer_size, custom_allocator>;
|
||||
|
||||
It is also possible to write a formatting function that uses a custom
|
||||
allocator::
|
||||
|
||||
using custom_string =
|
||||
std::basic_string<char, std::char_traits<char>, custom_allocator>;
|
||||
|
||||
custom_string vformat(custom_allocator alloc, fmt::string_view format_str,
|
||||
fmt::format_args args) {
|
||||
custom_memory_buffer buf(alloc);
|
||||
fmt::vformat_to(buf, format_str, args);
|
||||
return custom_string(buf.data(), buf.size(), alloc);
|
||||
}
|
||||
|
||||
template <typename ...Args>
|
||||
inline custom_string format(custom_allocator alloc,
|
||||
fmt::string_view format_str,
|
||||
const Args & ... args) {
|
||||
return vformat(alloc, format_str, fmt::make_args(args...));
|
||||
}
|
||||
Custom formatting of built-in types
|
||||
-----------------------------------
|
||||
|
||||
It is possible to change the way arguments are formatted by providing a
|
||||
custom argument formatter class::
|
||||
|
||||
using arg_formatter =
|
||||
fmt::arg_formatter<fmt::back_insert_range<fmt::internal::buffer>>;
|
||||
|
||||
// A custom argument formatter that formats negative integers as unsigned
|
||||
// with the ``x`` format specifier.
|
||||
class custom_arg_formatter : public arg_formatter {
|
||||
public:
|
||||
custom_arg_formatter(fmt::context &ctx, fmt::format_specs &spec)
|
||||
: arg_formatter(ctx, spec) {}
|
||||
|
||||
using arg_formatter::operator();
|
||||
|
||||
void operator()(int value) {
|
||||
if (spec().type() == 'x')
|
||||
(*this)(static_cast<unsigned>(value)); // convert to unsigned and format
|
||||
else
|
||||
arg_formatter::operator()(value);
|
||||
}
|
||||
};
|
||||
|
||||
std::string custom_vformat(fmt::string_view format_str, fmt::format_args args) {
|
||||
fmt::memory_buffer buffer;
|
||||
// Pass custom argument formatter as a template arg to vformat_to.
|
||||
fmt::vformat_to<custom_arg_formatter>(buffer, format_str, args);
|
||||
return fmt::to_string(buffer);
|
||||
}
|
||||
|
||||
template <typename ...Args>
|
||||
inline std::string custom_format(
|
||||
fmt::string_view format_str, const Args &... args) {
|
||||
return custom_vformat(format_str, fmt::make_args(args...));
|
||||
}
|
||||
|
||||
std::string s = custom_format("{:x}", -42); // s == "ffffffd6"
|
||||
|
||||
.. doxygenclass:: fmt::ArgVisitor
|
||||
:members:
|
||||
|
||||
.. doxygenclass:: fmt::arg_formatter_base
|
||||
:members:
|
||||
|
||||
.. doxygenclass:: fmt::arg_formatter
|
||||
:members:
|
||||
|
||||
.. _time-api:
|
||||
|
||||
Date and time formatting
|
||||
------------------------
|
||||
========================
|
||||
|
||||
The library supports `strftime
|
||||
<http://en.cppreference.com/w/cpp/chrono/c/strftime>`_-like date and time
|
||||
formatting::
|
||||
|
||||
#include "fmt/time.h"
|
||||
#include <fmt/time.h>
|
||||
|
||||
std::time_t t = std::time(nullptr);
|
||||
// Prints "The date is 2016-04-29." (with the current date)
|
||||
@ -58,111 +255,35 @@ formatting::
|
||||
The format string syntax is described in the documentation of
|
||||
`strftime <http://en.cppreference.com/w/cpp/chrono/c/strftime>`_.
|
||||
|
||||
Formatting user-defined types
|
||||
-----------------------------
|
||||
|
||||
To make a user-defined type formattable, specialize the ``formatter<T>`` struct
|
||||
template and implement ``parse`` and ``format`` methods::
|
||||
|
||||
struct MyStruct { double x, y; };
|
||||
|
||||
namespace fmt {
|
||||
template <>
|
||||
struct formatter<MyStruct> {
|
||||
template <typename ParseContext>
|
||||
auto parse(ParseContext &ctx) { return ctx.begin(); }
|
||||
|
||||
template <typename FormatContext>
|
||||
auto format(const MyStruct &s, FormatContext &ctx) {
|
||||
fmt::format_to(ctx.begin(), "[MyStruct: x={:.1f}, y={:.2f}]", s.x, s.y);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Then you can pass objects of type ``MyStruct`` to any formatting function::
|
||||
|
||||
MyStruct m = {1, 2};
|
||||
std::string s = fmt::format("m={}", m);
|
||||
// s == "m=[MyStruct: x=1.0, y=2.00]"
|
||||
|
||||
In the example above the ``formatter<MyStruct>::parse`` function ignores the
|
||||
contents of the format string referred to by ``ctx.begin()`` so the object will
|
||||
always be formatted as specified. See ``formatter<tm>::parse`` in
|
||||
:file:`fmt/time.h` for an advanced example of how to parse the format string and
|
||||
customize the formatted output.
|
||||
|
||||
This section shows how to define a custom format function for a user-defined
|
||||
type. The next section describes how to get ``fmt`` to use a conventional stream
|
||||
output ``operator<<`` when one is defined for a user-defined type.
|
||||
.. _ostream-api:
|
||||
|
||||
``std::ostream`` support
|
||||
------------------------
|
||||
========================
|
||||
|
||||
The header ``fmt/ostream.h`` provides ``std::ostream`` support including
|
||||
formatting of user-defined types that have overloaded ``operator<<``::
|
||||
``fmt/ostream.h`` provides ``std::ostream`` support including formatting of
|
||||
user-defined types that have overloaded ``operator<<``::
|
||||
|
||||
#include "fmt/ostream.h"
|
||||
#include <fmt/ostream.h>
|
||||
|
||||
class Date {
|
||||
class date {
|
||||
int year_, month_, day_;
|
||||
public:
|
||||
Date(int year, int month, int day): year_(year), month_(month), day_(day) {}
|
||||
date(int year, int month, int day): year_(year), month_(month), day_(day) {}
|
||||
|
||||
friend std::ostream &operator<<(std::ostream &os, const Date &d) {
|
||||
friend std::ostream &operator<<(std::ostream &os, const date &d) {
|
||||
return os << d.year_ << '-' << d.month_ << '-' << d.day_;
|
||||
}
|
||||
};
|
||||
|
||||
std::string s = fmt::format("The date is {}", Date(2012, 12, 9));
|
||||
std::string s = fmt::format("The date is {}", date(2012, 12, 9));
|
||||
// s == "The date is 2012-12-9"
|
||||
|
||||
.. doxygenfunction:: print(std::ostream&, CStringRef, ArgList)
|
||||
.. doxygenfunction:: print(std::ostream&, string_view, const Args&...)
|
||||
|
||||
Argument formatters
|
||||
-------------------
|
||||
.. _printf-api:
|
||||
|
||||
It is possible to change the way arguments are formatted by providing a
|
||||
custom argument formatter class::
|
||||
|
||||
// A custom argument formatter that formats negative integers as unsigned
|
||||
// with the ``x`` format specifier.
|
||||
class CustomArgFormatter :
|
||||
public fmt::BasicArgFormatter<CustomArgFormatter, char> {
|
||||
public:
|
||||
CustomArgFormatter(fmt::BasicFormatter<char, CustomArgFormatter> &f,
|
||||
fmt::FormatSpec &s, const char *fmt)
|
||||
: fmt::BasicArgFormatter<CustomArgFormatter, char>(f, s, fmt) {}
|
||||
|
||||
void visit_int(int value) {
|
||||
if (spec().type() == 'x')
|
||||
visit_uint(value); // convert to unsigned and format
|
||||
else
|
||||
fmt::BasicArgFormatter<CustomArgFormatter, char>::visit_int(value);
|
||||
}
|
||||
};
|
||||
|
||||
std::string custom_format(const char *format_str, fmt::ArgList args) {
|
||||
fmt::MemoryWriter writer;
|
||||
// Pass custom argument formatter as a template arg to BasicFormatter.
|
||||
fmt::BasicFormatter<char, CustomArgFormatter> formatter(args, writer);
|
||||
formatter.format(format_str);
|
||||
return writer.str();
|
||||
}
|
||||
FMT_VARIADIC(std::string, custom_format, const char *)
|
||||
|
||||
std::string s = custom_format("{:x}", -42); // s == "ffffffd6"
|
||||
|
||||
.. doxygenclass:: fmt::ArgVisitor
|
||||
:members:
|
||||
|
||||
.. doxygenclass:: fmt::BasicArgFormatter
|
||||
:members:
|
||||
|
||||
.. doxygenclass:: fmt::ArgFormatter
|
||||
:members:
|
||||
|
||||
Printf formatting
|
||||
-----------------
|
||||
``printf`` formatting
|
||||
=====================
|
||||
|
||||
The header ``fmt/printf.h`` provides ``printf``-like formatting functionality.
|
||||
The following functions use `printf format string syntax
|
||||
@ -171,22 +292,13 @@ the POSIX extension for positional arguments. Unlike their standard
|
||||
counterparts, the ``fmt`` functions are type-safe and throw an exception if an
|
||||
argument type doesn't match its format specification.
|
||||
|
||||
.. doxygenfunction:: printf(CStringRef, ArgList)
|
||||
.. doxygenfunction:: printf(string_view, const Args&...)
|
||||
|
||||
.. doxygenfunction:: fprintf(std::FILE *, CStringRef, ArgList)
|
||||
.. doxygenfunction:: fprintf(std::FILE *, string_view, const Args&...)
|
||||
|
||||
.. doxygenfunction:: fprintf(std::ostream&, CStringRef, ArgList)
|
||||
.. doxygenfunction:: fprintf(std::ostream&, string_view, const Args&...)
|
||||
|
||||
.. doxygenfunction:: sprintf(CStringRef, ArgList)
|
||||
|
||||
.. doxygenclass:: fmt::PrintfFormatter
|
||||
:members:
|
||||
|
||||
.. doxygenclass:: fmt::BasicPrintfArgFormatter
|
||||
:members:
|
||||
|
||||
.. doxygenclass:: fmt::PrintfArgFormatter
|
||||
:members:
|
||||
.. doxygenfunction:: sprintf(string_view, const Args&...)
|
||||
|
||||
Write API
|
||||
=========
|
||||
@ -194,14 +306,14 @@ Write API
|
||||
The write API provides classes for writing formatted data into character
|
||||
streams. It is usually faster than the `format API`_ but, as IOStreams,
|
||||
may result in larger compiled code size. The main writer class is
|
||||
`~fmt::BasicMemoryWriter` which stores its output in a memory buffer and
|
||||
`~fmt::basic_memory_writer` which stores its output in a memory buffer and
|
||||
provides direct access to it. It is possible to create custom writers that
|
||||
store output elsewhere by subclassing `~fmt::BasicWriter`.
|
||||
|
||||
.. doxygenclass:: fmt::BasicWriter
|
||||
:members:
|
||||
|
||||
.. doxygenclass:: fmt::BasicMemoryWriter
|
||||
.. doxygenclass:: fmt::basic_memory_writer
|
||||
:members:
|
||||
|
||||
.. doxygenclass:: fmt::BasicArrayWriter
|
||||
@ -220,64 +332,3 @@ store output elsewhere by subclassing `~fmt::BasicWriter`.
|
||||
|
||||
.. doxygenfunction:: pad(int, unsigned, Char)
|
||||
|
||||
Utilities
|
||||
=========
|
||||
|
||||
.. doxygenfunction:: fmt::arg(StringRef, const T&)
|
||||
|
||||
.. doxygenfunction:: operator""_a(const char *, std::size_t)
|
||||
|
||||
.. doxygendefine:: FMT_CAPTURE
|
||||
|
||||
.. doxygendefine:: FMT_VARIADIC
|
||||
|
||||
.. doxygenclass:: fmt::ArgList
|
||||
:members:
|
||||
|
||||
.. doxygenfunction:: fmt::to_string(const T&)
|
||||
|
||||
.. doxygenclass:: fmt::BasicStringRef
|
||||
:members:
|
||||
|
||||
.. doxygenclass:: fmt::BasicCStringRef
|
||||
:members:
|
||||
|
||||
.. doxygenclass:: fmt::Buffer
|
||||
:protected-members:
|
||||
:members:
|
||||
|
||||
System errors
|
||||
=============
|
||||
|
||||
.. doxygenclass:: fmt::SystemError
|
||||
:members:
|
||||
|
||||
.. doxygenfunction:: fmt::format_system_error
|
||||
|
||||
.. doxygenclass:: fmt::WindowsError
|
||||
:members:
|
||||
|
||||
.. _formatstrings:
|
||||
|
||||
Custom allocators
|
||||
=================
|
||||
|
||||
The fmt library supports custom dynamic memory allocators.
|
||||
A custom allocator class can be specified as a template argument to
|
||||
:class:`fmt::BasicMemoryWriter`::
|
||||
|
||||
typedef fmt::BasicMemoryWriter<char, CustomAllocator> CustomMemoryWriter;
|
||||
|
||||
It is also possible to write a formatting function that uses a custom
|
||||
allocator::
|
||||
|
||||
typedef std::basic_string<char, std::char_traits<char>, CustomAllocator>
|
||||
CustomString;
|
||||
|
||||
CustomString format(CustomAllocator alloc, fmt::CStringRef format_str,
|
||||
fmt::ArgList args) {
|
||||
CustomMemoryWriter writer(alloc);
|
||||
writer.write(format_str, args);
|
||||
return CustomString(writer.data(), writer.size(), alloc);
|
||||
}
|
||||
FMT_VARIADIC(CustomString, format, CustomAllocator, fmt::CStringRef)
|
||||
|
||||
@ -62,8 +62,8 @@ def create_build_env(dirname='virtualenv'):
|
||||
def build_docs(version='dev', **kwargs):
|
||||
doc_dir = kwargs.get('doc_dir', os.path.dirname(os.path.realpath(__file__)))
|
||||
work_dir = kwargs.get('work_dir', '.')
|
||||
include_dir = kwargs.get('include_dir',
|
||||
os.path.join(os.path.dirname(doc_dir), 'fmt'))
|
||||
include_dir = kwargs.get(
|
||||
'include_dir', os.path.join(os.path.dirname(doc_dir), 'include', 'fmt'))
|
||||
# Build docs.
|
||||
cmd = ['doxygen', '-']
|
||||
p = Popen(cmd, stdin=PIPE)
|
||||
@ -74,8 +74,8 @@ def build_docs(version='dev', **kwargs):
|
||||
GENERATE_MAN = NO
|
||||
GENERATE_RTF = NO
|
||||
CASE_SENSE_NAMES = NO
|
||||
INPUT = {0}/container.h {0}/format.h {0}/ostream.h \
|
||||
{0}/printf.h {0}/string.h
|
||||
INPUT = {0}/core.h {0}/format.h {0}/ostream.h \
|
||||
{0}/printf.h {0}/time.h
|
||||
QUIET = YES
|
||||
JAVADOC_AUTOBRIEF = YES
|
||||
AUTOLINK_SUPPORT = NO
|
||||
|
||||
@ -47,7 +47,7 @@ source_suffix = '.rst'
|
||||
|
||||
# General information about the project.
|
||||
project = u'fmt'
|
||||
copyright = u'2012-2015, Victor Zverovich'
|
||||
copyright = u'2012-present, Victor Zverovich'
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
|
||||
@ -25,7 +25,7 @@ The replacement-based Format API provides a safe alternative to ``printf``,
|
||||
``sprintf`` and friends with comparable or `better performance
|
||||
<http://zverovich.net/2013/09/07/integer-to-string-conversion-in-cplusplus.html>`_.
|
||||
The `format string syntax <syntax.html>`_ is similar to the one used by
|
||||
`str.format <http://docs.python.org/2/library/stdtypes.html#str.format>`_
|
||||
`str.format <http://docs.python.org/3/library/stdtypes.html#str.format>`_
|
||||
in Python:
|
||||
|
||||
.. code:: c++
|
||||
|
||||
@ -24,7 +24,7 @@
|
||||
# define FMT_HAS_FEATURE(x) 0
|
||||
#endif
|
||||
|
||||
#if defined(__has_include)
|
||||
#ifdef __has_include
|
||||
# define FMT_HAS_INCLUDE(x) __has_include(x)
|
||||
#else
|
||||
# define FMT_HAS_INCLUDE(x) 0
|
||||
@ -36,7 +36,7 @@
|
||||
# define FMT_GCC_VERSION 0
|
||||
#endif
|
||||
|
||||
#if __cplusplus >= 201103L || defined __GXX_EXPERIMENTAL_CXX0X__
|
||||
#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)
|
||||
# define FMT_HAS_GXX_CXX11 FMT_GCC_VERSION
|
||||
#else
|
||||
# define FMT_HAS_GXX_CXX11 0
|
||||
@ -72,17 +72,26 @@
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if FMT_HAS_FEATURE(cxx_explicit_conversions)
|
||||
# define FMT_EXPLICIT explicit
|
||||
#else
|
||||
# define FMT_EXPLICIT
|
||||
#endif
|
||||
|
||||
#ifndef FMT_NULL
|
||||
# if FMT_HAS_FEATURE(cxx_nullptr) || \
|
||||
(FMT_GCC_VERSION >= 408 && FMT_HAS_GXX_CXX11) || \
|
||||
FMT_MSC_VER >= 1600
|
||||
# define FMT_NULL nullptr
|
||||
# define FMT_USE_NULLPTR 1
|
||||
# else
|
||||
# define FMT_NULL NULL
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#define FMT_USE_STRONG_ENUMS FMT_HAS_FEATURE(cxx_strong_enums)
|
||||
#ifndef FMT_USE_NULLPTR
|
||||
# define FMT_USE_NULLPTR 0
|
||||
#endif
|
||||
|
||||
// Check if exceptions are disabled.
|
||||
#if defined(__GNUC__) && !defined(__EXCEPTIONS)
|
||||
@ -148,19 +157,36 @@
|
||||
#if (FMT_HAS_INCLUDE(<string_view>) && __cplusplus > 201402L) || \
|
||||
(defined(_MSVC_LANG) && _MSVC_LANG > 201402L && _MSC_VER >= 1910)
|
||||
# include <string_view>
|
||||
namespace fmt { using std::basic_string_view; }
|
||||
// std::experimental::basic_string_view::remove_prefix isn't constexpr in gcc 6.
|
||||
# define FMT_USE_STD_STRING_VIEW
|
||||
// std::experimental::basic_string_view::remove_prefix isn't constexpr until
|
||||
// gcc 7.3.
|
||||
#elif (FMT_HAS_INCLUDE(<experimental/string_view>) && \
|
||||
(FMT_GCC_VERSION == 0 || FMT_GCC_VERSION >= 700) && \
|
||||
(FMT_GCC_VERSION == 0 || FMT_GCC_VERSION >= 730) && \
|
||||
__cplusplus >= 201402L)
|
||||
# include <experimental/string_view>
|
||||
namespace fmt { using std::experimental::basic_string_view; }
|
||||
#else
|
||||
# define FMT_USE_EXPERIMENTAL_STRING_VIEW
|
||||
#endif
|
||||
|
||||
// std::result_of is defined in <functional> in gcc 4.4.
|
||||
#if FMT_GCC_VERSION && FMT_GCC_VERSION <= 404
|
||||
# include <functional>
|
||||
#endif
|
||||
|
||||
namespace fmt {
|
||||
|
||||
// An implementation of declval for pre-C++11 compilers such as gcc 4.
|
||||
namespace internal {
|
||||
template <typename T>
|
||||
typename std::add_rvalue_reference<T>::type declval() FMT_NOEXCEPT;
|
||||
}
|
||||
|
||||
/**
|
||||
\rst
|
||||
An implementation of ``std::basic_string_view`` for pre-C++17. It provides a
|
||||
subset of the API.
|
||||
subset of the API. ``fmt::basic_string_view`` is used for format strings even
|
||||
if ``std::string_view`` is available to prevent issues when a library is
|
||||
compiled with a different ``-std`` option than the client code (which is not
|
||||
recommended).
|
||||
\endrst
|
||||
*/
|
||||
template <typename Char>
|
||||
@ -170,10 +196,22 @@ class basic_string_view {
|
||||
size_t size_;
|
||||
|
||||
public:
|
||||
using char_type = Char;
|
||||
using iterator = const Char *;
|
||||
typedef Char char_type;
|
||||
typedef const Char *iterator;
|
||||
|
||||
FMT_CONSTEXPR basic_string_view() FMT_NOEXCEPT : data_(0), size_(0) {}
|
||||
// Standard basic_string_view type.
|
||||
#if defined(FMT_USE_STD_STRING_VIEW)
|
||||
typedef std::basic_string_view<Char> type;
|
||||
#elif defined(FMT_USE_EXPERIMENTAL_STRING_VIEW)
|
||||
typedef std::experimental::basic_string_view<Char> type;
|
||||
#else
|
||||
struct type {
|
||||
const char *data() const { return FMT_NULL; }
|
||||
size_t size() const { return 0; };
|
||||
};
|
||||
#endif
|
||||
|
||||
FMT_CONSTEXPR basic_string_view() FMT_NOEXCEPT : data_(FMT_NULL), size_(0) {}
|
||||
|
||||
/** Constructs a string reference object from a C string and a size. */
|
||||
FMT_CONSTEXPR basic_string_view(const Char *s, size_t size) FMT_NOEXCEPT
|
||||
@ -198,6 +236,9 @@ class basic_string_view {
|
||||
const std::basic_string<Char, Alloc> &s) FMT_NOEXCEPT
|
||||
: data_(s.c_str()), size_(s.size()) {}
|
||||
|
||||
FMT_CONSTEXPR basic_string_view(type s) FMT_NOEXCEPT
|
||||
: data_(s.data()), size_(s.size()) {}
|
||||
|
||||
/** Returns a pointer to the string data. */
|
||||
const Char *data() const { return data_; }
|
||||
|
||||
@ -240,12 +281,9 @@ class basic_string_view {
|
||||
return lhs.compare(rhs) >= 0;
|
||||
}
|
||||
};
|
||||
} // namespace fmt
|
||||
#endif
|
||||
|
||||
namespace fmt {
|
||||
using string_view = basic_string_view<char>;
|
||||
using wstring_view = basic_string_view<wchar_t>;
|
||||
typedef basic_string_view<char> string_view;
|
||||
typedef basic_string_view<wchar_t> wstring_view;
|
||||
|
||||
template <typename Context>
|
||||
class basic_arg;
|
||||
@ -287,7 +325,8 @@ class basic_buffer {
|
||||
virtual void grow(std::size_t capacity) = 0;
|
||||
|
||||
public:
|
||||
using value_type = T;
|
||||
typedef T value_type;
|
||||
typedef const T &const_reference;
|
||||
|
||||
virtual ~basic_buffer() {}
|
||||
|
||||
@ -337,8 +376,8 @@ class basic_buffer {
|
||||
const T &operator[](std::size_t index) const { return ptr_[index]; }
|
||||
};
|
||||
|
||||
using buffer = basic_buffer<char>;
|
||||
using wbuffer = basic_buffer<wchar_t>;
|
||||
typedef basic_buffer<char> buffer;
|
||||
typedef basic_buffer<wchar_t> wbuffer;
|
||||
|
||||
// A container-backed buffer.
|
||||
template <typename Container>
|
||||
@ -347,7 +386,7 @@ class container_buffer : public basic_buffer<typename Container::value_type> {
|
||||
Container &container_;
|
||||
|
||||
protected:
|
||||
virtual void grow(std::size_t capacity) {
|
||||
void grow(std::size_t capacity) FMT_OVERRIDE {
|
||||
container_.resize(capacity);
|
||||
this->set(&container_[0], capacity);
|
||||
}
|
||||
@ -358,11 +397,6 @@ class container_buffer : public basic_buffer<typename Container::value_type> {
|
||||
container_(c) {}
|
||||
};
|
||||
|
||||
// A helper function to suppress bogus "conditional expression is constant"
|
||||
// warnings.
|
||||
template <typename T>
|
||||
inline T const_check(T value) { return value; }
|
||||
|
||||
struct error_handler {
|
||||
FMT_CONSTEXPR error_handler() {}
|
||||
FMT_CONSTEXPR error_handler(const error_handler &) {}
|
||||
@ -395,40 +429,32 @@ template <typename T, typename Char>
|
||||
struct is_named_arg<named_arg<T, Char>> : std::true_type {};
|
||||
|
||||
enum type {
|
||||
NONE, NAMED_ARG,
|
||||
none_type, name_arg_type,
|
||||
// Integer types should go first,
|
||||
INT, UINT, LONG_LONG, ULONG_LONG, BOOL, CHAR, LAST_INTEGER_TYPE = CHAR,
|
||||
int_type, uint_type, long_long_type, ulong_long_type, bool_type, char_type,
|
||||
last_integer_type = char_type,
|
||||
// followed by floating-point types.
|
||||
DOUBLE, LONG_DOUBLE, LAST_NUMERIC_TYPE = LONG_DOUBLE,
|
||||
CSTRING, STRING, POINTER, CUSTOM
|
||||
double_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_ASSERT(t != internal::NAMED_ARG, "invalid argument type");
|
||||
return t > internal::NONE && t <= internal::LAST_INTEGER_TYPE;
|
||||
FMT_ASSERT(t != internal::name_arg_type, "invalid argument type");
|
||||
return t > internal::none_type && t <= internal::last_integer_type;
|
||||
}
|
||||
|
||||
FMT_CONSTEXPR bool is_arithmetic(type t) {
|
||||
FMT_ASSERT(t != internal::NAMED_ARG, "invalid argument type");
|
||||
return t > internal::NONE && t <= internal::LAST_NUMERIC_TYPE;
|
||||
FMT_ASSERT(t != internal::name_arg_type, "invalid argument type");
|
||||
return t > internal::none_type && t <= internal::last_numeric_type;
|
||||
}
|
||||
|
||||
template <typename T, bool ENABLE = true>
|
||||
template <typename T, typename Char, bool ENABLE = true>
|
||||
struct convert_to_int {
|
||||
enum {
|
||||
value = !std::is_arithmetic<T>::value && std::is_convertible<T, int>::value
|
||||
value = !std::is_arithmetic<T>::value && std::is_convertible<T, int>::value
|
||||
};
|
||||
};
|
||||
|
||||
#define FMT_DISABLE_CONVERSION_TO_INT(Type) \
|
||||
template <> \
|
||||
struct convert_to_int<Type> { enum { value = 0 }; }
|
||||
|
||||
// Silence warnings about convering float to int.
|
||||
FMT_DISABLE_CONVERSION_TO_INT(float);
|
||||
FMT_DISABLE_CONVERSION_TO_INT(double);
|
||||
FMT_DISABLE_CONVERSION_TO_INT(long double);
|
||||
|
||||
template <typename Char>
|
||||
struct string_value {
|
||||
const Char *value;
|
||||
@ -445,7 +471,7 @@ struct custom_value {
|
||||
template <typename Context>
|
||||
class value {
|
||||
public:
|
||||
using char_type = typename Context::char_type;
|
||||
typedef typename Context::char_type char_type;
|
||||
|
||||
union {
|
||||
int int_value;
|
||||
@ -501,7 +527,7 @@ class value {
|
||||
// Get the formatter type through the context to allow different contexts
|
||||
// have different extension points, e.g. `formatter<T>` for `format` and
|
||||
// `printf_formatter<T>` for `printf`.
|
||||
typename Context::template formatter_type<T> f;
|
||||
typename Context::template formatter_type<T>::type f;
|
||||
auto &&parse_ctx = ctx.parse_context();
|
||||
parse_ctx.advance_to(f.parse(parse_ctx));
|
||||
ctx.advance_to(f.format(*static_cast<const T*>(arg), ctx));
|
||||
@ -520,85 +546,97 @@ template <typename Context, typename T>
|
||||
FMT_CONSTEXPR basic_arg<Context> make_arg(const T &value);
|
||||
|
||||
#define FMT_MAKE_VALUE(TAG, ArgType, ValueType) \
|
||||
template <typename C, typename char_type = typename C::char_type> \
|
||||
template <typename C> \
|
||||
FMT_CONSTEXPR typed_value<C, TAG> make_value(ArgType val) { \
|
||||
return static_cast<ValueType>(val); \
|
||||
}
|
||||
|
||||
FMT_MAKE_VALUE(BOOL, bool, int)
|
||||
FMT_MAKE_VALUE(INT, short, int)
|
||||
FMT_MAKE_VALUE(UINT, unsigned short, unsigned)
|
||||
FMT_MAKE_VALUE(INT, int, int)
|
||||
FMT_MAKE_VALUE(UINT, unsigned, unsigned)
|
||||
FMT_MAKE_VALUE(bool_type, bool, int)
|
||||
FMT_MAKE_VALUE(int_type, short, int)
|
||||
FMT_MAKE_VALUE(uint_type, unsigned short, unsigned)
|
||||
FMT_MAKE_VALUE(int_type, int, int)
|
||||
FMT_MAKE_VALUE(uint_type, unsigned, unsigned)
|
||||
|
||||
// To minimize the number of types we need to deal with, long is translated
|
||||
// either to int or to long long depending on its size.
|
||||
using long_type =
|
||||
std::conditional<sizeof(long) == sizeof(int), int, long long>::type;
|
||||
FMT_MAKE_VALUE((sizeof(long) == sizeof(int) ? INT : LONG_LONG), long, long_type)
|
||||
using ulong_type =
|
||||
std::conditional<sizeof(unsigned long) == sizeof(unsigned),
|
||||
unsigned, unsigned long long>::type;
|
||||
FMT_MAKE_VALUE((sizeof(unsigned long) == sizeof(unsigned) ? UINT : ULONG_LONG),
|
||||
typedef std::conditional<sizeof(long) == sizeof(int), int, long long>::type
|
||||
long_type;
|
||||
FMT_MAKE_VALUE(
|
||||
(sizeof(long) == sizeof(int) ? int_type : long_long_type), long, long_type)
|
||||
typedef std::conditional<sizeof(unsigned long) == sizeof(unsigned),
|
||||
unsigned, unsigned long long>::type ulong_type;
|
||||
FMT_MAKE_VALUE(
|
||||
(sizeof(unsigned long) == sizeof(unsigned) ? uint_type : ulong_long_type),
|
||||
unsigned long, ulong_type)
|
||||
|
||||
FMT_MAKE_VALUE(LONG_LONG, long long, long long)
|
||||
FMT_MAKE_VALUE(ULONG_LONG, unsigned long long, unsigned long long)
|
||||
FMT_MAKE_VALUE(INT, signed char, int)
|
||||
FMT_MAKE_VALUE(UINT, unsigned char, unsigned)
|
||||
FMT_MAKE_VALUE(CHAR, char, int)
|
||||
FMT_MAKE_VALUE(long_long_type, long long, long long)
|
||||
FMT_MAKE_VALUE(ulong_long_type, unsigned long long, unsigned long long)
|
||||
FMT_MAKE_VALUE(int_type, signed char, int)
|
||||
FMT_MAKE_VALUE(uint_type, unsigned char, unsigned)
|
||||
FMT_MAKE_VALUE(char_type, char, int)
|
||||
|
||||
#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
|
||||
template <typename C>
|
||||
inline typed_value<C, CHAR> make_value(wchar_t val) {
|
||||
inline typed_value<C, char_type> make_value(wchar_t val) {
|
||||
require_wchar<typename C::char_type>();
|
||||
return static_cast<int>(val);
|
||||
}
|
||||
#endif
|
||||
|
||||
FMT_MAKE_VALUE(DOUBLE, float, double)
|
||||
FMT_MAKE_VALUE(DOUBLE, double, double)
|
||||
FMT_MAKE_VALUE(LONG_DOUBLE, long double, long double)
|
||||
FMT_MAKE_VALUE(double_type, float, double)
|
||||
FMT_MAKE_VALUE(double_type, double, double)
|
||||
FMT_MAKE_VALUE(long_double_type, long double, long double)
|
||||
|
||||
// Formatting of wide strings into a narrow buffer and multibyte strings
|
||||
// into a wide buffer is disallowed (https://github.com/fmtlib/fmt/pull/606).
|
||||
FMT_MAKE_VALUE(CSTRING, char_type*, const char_type*)
|
||||
FMT_MAKE_VALUE(CSTRING, const char_type*, const char_type*)
|
||||
FMT_MAKE_VALUE(cstring_type, typename C::char_type*,
|
||||
const typename C::char_type*)
|
||||
FMT_MAKE_VALUE(cstring_type, const typename C::char_type*,
|
||||
const typename C::char_type*)
|
||||
|
||||
FMT_MAKE_VALUE(CSTRING, signed char*, const signed char*)
|
||||
FMT_MAKE_VALUE(CSTRING, const signed char*, const signed char*)
|
||||
FMT_MAKE_VALUE(CSTRING, unsigned char*, const unsigned char*)
|
||||
FMT_MAKE_VALUE(CSTRING, const unsigned char*, const unsigned char*)
|
||||
FMT_MAKE_VALUE(STRING, basic_string_view<char_type>,
|
||||
basic_string_view<char_type>)
|
||||
FMT_MAKE_VALUE(STRING, const std::basic_string<char_type>&,
|
||||
basic_string_view<char_type>)
|
||||
FMT_MAKE_VALUE(POINTER, void*, const void*)
|
||||
FMT_MAKE_VALUE(POINTER, const void*, const void*)
|
||||
FMT_MAKE_VALUE(POINTER, std::nullptr_t, const void*)
|
||||
FMT_MAKE_VALUE(cstring_type, signed char*, const signed char*)
|
||||
FMT_MAKE_VALUE(cstring_type, const signed char*, const signed char*)
|
||||
FMT_MAKE_VALUE(cstring_type, unsigned char*, const unsigned char*)
|
||||
FMT_MAKE_VALUE(cstring_type, const unsigned char*, const unsigned char*)
|
||||
FMT_MAKE_VALUE(string_type, basic_string_view<typename C::char_type>,
|
||||
basic_string_view<typename C::char_type>)
|
||||
FMT_MAKE_VALUE(string_type,
|
||||
typename basic_string_view<typename C::char_type>::type,
|
||||
basic_string_view<typename C::char_type>)
|
||||
FMT_MAKE_VALUE(string_type, const std::basic_string<typename C::char_type>&,
|
||||
basic_string_view<typename C::char_type>)
|
||||
FMT_MAKE_VALUE(pointer_type, void*, const void*)
|
||||
FMT_MAKE_VALUE(pointer_type, const void*, const void*)
|
||||
|
||||
#if FMT_USE_NULLPTR
|
||||
FMT_MAKE_VALUE(pointer_type, std::nullptr_t, const void*)
|
||||
#endif
|
||||
|
||||
// Formatting of arbitrary pointers is disallowed. If you want to output a
|
||||
// pointer cast it to "void *" or "const void *". In particular, this forbids
|
||||
// formatting of "[const] volatile char *" which is printed as bool by
|
||||
// iostreams.
|
||||
template <typename T>
|
||||
void make_value(const T *p) {
|
||||
void make_value(const T *) {
|
||||
static_assert(!sizeof(T), "formatting of non-void pointers is disallowed");
|
||||
}
|
||||
|
||||
template <typename C, typename T>
|
||||
inline typename std::enable_if<
|
||||
convert_to_int<T>::value && std::is_enum<T>::value,
|
||||
typed_value<C, INT>>::type
|
||||
std::is_enum<T>::value && convert_to_int<T, typename C::char_type>::value,
|
||||
typed_value<C, int_type>>::type
|
||||
make_value(const T &val) { return static_cast<int>(val); }
|
||||
|
||||
template <typename C, typename T>
|
||||
template <typename C, typename T, typename Char = typename C::char_type>
|
||||
inline typename std::enable_if<
|
||||
!convert_to_int<T>::value, typed_value<C, CUSTOM>>::type
|
||||
!convert_to_int<T, Char>::value &&
|
||||
!std::is_convertible<T, basic_string_view<Char>>::value &&
|
||||
!std::is_convertible<T, std::basic_string<Char>>::value,
|
||||
typed_value<C, custom_type>>::type
|
||||
make_value(const T &val) { return val; }
|
||||
|
||||
template <typename C, typename T>
|
||||
typed_value<C, NAMED_ARG>
|
||||
typed_value<C, name_arg_type>
|
||||
make_value(const named_arg<T, typename C::char_type> &val) {
|
||||
basic_arg<C> arg = make_arg<C>(val.value);
|
||||
std::memcpy(val.data, &arg, sizeof(arg));
|
||||
@ -606,10 +644,20 @@ typed_value<C, NAMED_ARG>
|
||||
}
|
||||
|
||||
// Maximum number of arguments with packed types.
|
||||
enum { MAX_PACKED_ARGS = 15 };
|
||||
enum { max_packed_args = 15 };
|
||||
|
||||
template <typename Context>
|
||||
class arg_map;
|
||||
|
||||
template <typename>
|
||||
struct result_of;
|
||||
|
||||
template <typename F, typename... Args>
|
||||
struct result_of<F(Args...)> {
|
||||
// A workaround for gcc 4.4 that doesn't allow F to be a reference.
|
||||
typedef typename std::result_of<
|
||||
typename std::remove_reference<F>::type(Args...)>::type type;
|
||||
};
|
||||
}
|
||||
|
||||
// A formatting argument. It is a trivially copyable/constructible type to
|
||||
@ -624,13 +672,13 @@ class basic_arg {
|
||||
friend FMT_CONSTEXPR basic_arg<ContextType> internal::make_arg(const T &value);
|
||||
|
||||
template <typename Visitor, typename Ctx>
|
||||
friend FMT_CONSTEXPR typename std::result_of<Visitor(int)>::type
|
||||
friend FMT_CONSTEXPR typename internal::result_of<Visitor(int)>::type
|
||||
visit(Visitor &&vis, basic_arg<Ctx> arg);
|
||||
|
||||
friend class basic_format_args<Context>;
|
||||
friend class internal::arg_map<Context>;
|
||||
|
||||
using char_type = typename Context::char_type;
|
||||
typedef typename Context::char_type char_type;
|
||||
|
||||
public:
|
||||
class handle {
|
||||
@ -643,17 +691,17 @@ class basic_arg {
|
||||
internal::custom_value<Context> custom_;
|
||||
};
|
||||
|
||||
FMT_CONSTEXPR basic_arg() : type_(internal::NONE) {}
|
||||
FMT_CONSTEXPR basic_arg() : type_(internal::none_type) {}
|
||||
|
||||
explicit operator bool() const FMT_NOEXCEPT {
|
||||
return type_ != internal::NONE;
|
||||
FMT_EXPLICIT operator bool() const FMT_NOEXCEPT {
|
||||
return type_ != internal::none_type;
|
||||
}
|
||||
|
||||
internal::type type() const { return type_; }
|
||||
|
||||
bool is_integral() const { return internal::is_integral(type_); }
|
||||
bool is_arithmetic() const { return internal::is_arithmetic(type_); }
|
||||
bool is_pointer() const { return type_ == internal::POINTER; }
|
||||
bool is_pointer() const { return type_ == internal::pointer_type; }
|
||||
};
|
||||
|
||||
// Parsing context consisting of a format string range being parsed and an
|
||||
@ -665,8 +713,8 @@ class basic_parse_context : private ErrorHandler {
|
||||
int next_arg_id_;
|
||||
|
||||
public:
|
||||
using char_type = Char;
|
||||
using iterator = typename basic_string_view<Char>::iterator;
|
||||
typedef Char char_type;
|
||||
typedef typename basic_string_view<Char>::iterator iterator;
|
||||
|
||||
explicit FMT_CONSTEXPR basic_parse_context(
|
||||
basic_string_view<Char> format_str, ErrorHandler eh = ErrorHandler())
|
||||
@ -706,8 +754,8 @@ class basic_parse_context : private ErrorHandler {
|
||||
FMT_CONSTEXPR ErrorHandler error_handler() const { return *this; }
|
||||
};
|
||||
|
||||
using parse_context = basic_parse_context<char>;
|
||||
using wparse_context = basic_parse_context<wchar_t>;
|
||||
typedef basic_parse_context<char> parse_context;
|
||||
typedef basic_parse_context<wchar_t> wparse_context;
|
||||
|
||||
namespace internal {
|
||||
// A map from argument names to their values for named arguments.
|
||||
@ -716,15 +764,15 @@ class arg_map {
|
||||
private:
|
||||
FMT_DISALLOW_COPY_AND_ASSIGN(arg_map);
|
||||
|
||||
using char_type = typename Context::char_type;
|
||||
typedef typename Context::char_type char_type;
|
||||
|
||||
struct entry {
|
||||
basic_string_view<char_type> name;
|
||||
basic_arg<Context> arg;
|
||||
};
|
||||
|
||||
entry *map_ = nullptr;
|
||||
unsigned size_ = 0;
|
||||
entry *map_;
|
||||
unsigned size_;
|
||||
|
||||
void push_back(value<Context> val) {
|
||||
const internal::named_arg_base<char_type> &named = val.as_named_arg();
|
||||
@ -733,7 +781,7 @@ class arg_map {
|
||||
}
|
||||
|
||||
public:
|
||||
arg_map() {}
|
||||
arg_map() : map_(FMT_NULL), size_(0) {}
|
||||
void init(const basic_format_args<Context> &args);
|
||||
~arg_map() { delete [] map_; }
|
||||
|
||||
@ -750,7 +798,7 @@ class arg_map {
|
||||
template <typename OutputIt, typename Context, typename Char>
|
||||
class context_base {
|
||||
public:
|
||||
using iterator = OutputIt;
|
||||
typedef OutputIt iterator;
|
||||
|
||||
private:
|
||||
basic_parse_context<Char> parse_context_;
|
||||
@ -758,8 +806,8 @@ class context_base {
|
||||
basic_format_args<Context> args_;
|
||||
|
||||
protected:
|
||||
using char_type = Char;
|
||||
using format_arg = basic_arg<Context>;
|
||||
typedef Char char_type;
|
||||
typedef basic_arg<Context> format_arg;
|
||||
|
||||
context_base(OutputIt out, basic_string_view<char_type> format_str,
|
||||
basic_format_args<Context> args)
|
||||
@ -794,7 +842,7 @@ class context_base {
|
||||
void on_error(const char *message) { parse_context_.on_error(message); }
|
||||
|
||||
// Returns an iterator to the beginning of the output range.
|
||||
auto begin() { return out_; }
|
||||
iterator begin() { return out_; }
|
||||
|
||||
// Advances the begin iterator to ``it``.
|
||||
void advance_to(iterator it) { out_ = it; }
|
||||
@ -803,49 +851,34 @@ class context_base {
|
||||
// Extracts a reference to the container from back_insert_iterator.
|
||||
template <typename Container>
|
||||
inline Container &get_container(std::back_insert_iterator<Container> it) {
|
||||
using iterator = std::back_insert_iterator<Container>;
|
||||
struct accessor: iterator {
|
||||
accessor(iterator it) : iterator(it) {}
|
||||
using iterator::container;
|
||||
typedef std::back_insert_iterator<Container> bi_iterator;
|
||||
struct accessor: bi_iterator {
|
||||
accessor(bi_iterator it) : bi_iterator(it) {}
|
||||
using bi_iterator::container;
|
||||
};
|
||||
return *accessor(it).container;
|
||||
}
|
||||
} // namespace internal
|
||||
|
||||
template <typename OutputIt, typename T = typename OutputIt::value_type>
|
||||
class output_range {
|
||||
private:
|
||||
OutputIt it_;
|
||||
|
||||
// Unused yet.
|
||||
using sentinel = void;
|
||||
sentinel end() const;
|
||||
|
||||
public:
|
||||
using value_type = T;
|
||||
|
||||
explicit output_range(OutputIt it): it_(it) {}
|
||||
OutputIt begin() const { return it_; }
|
||||
};
|
||||
|
||||
// Formatting context.
|
||||
template <typename OutputIt, typename Char>
|
||||
class basic_context :
|
||||
public internal::context_base<OutputIt, basic_context<OutputIt, Char>, Char> {
|
||||
public:
|
||||
/** The character type for the output. */
|
||||
using char_type = Char;
|
||||
typedef Char char_type;
|
||||
|
||||
// using formatter_type = formatter<T, char_type>;
|
||||
template <typename T>
|
||||
using formatter_type = formatter<T, char_type>;
|
||||
struct formatter_type { typedef formatter<T, char_type> type; };
|
||||
|
||||
private:
|
||||
internal::arg_map<basic_context> map_;
|
||||
|
||||
FMT_DISALLOW_COPY_AND_ASSIGN(basic_context);
|
||||
|
||||
using base = internal::context_base<OutputIt, basic_context, Char>;
|
||||
using format_arg = typename base::format_arg;
|
||||
typedef internal::context_base<OutputIt, basic_context, Char> base;
|
||||
typedef typename base::format_arg format_arg;
|
||||
using base::get_arg;
|
||||
|
||||
public:
|
||||
@ -872,19 +905,18 @@ class basic_context :
|
||||
};
|
||||
|
||||
template <typename Char>
|
||||
using buffer_context_t = basic_context<
|
||||
std::back_insert_iterator<internal::basic_buffer<Char>>, Char>;
|
||||
using context = buffer_context_t<char>;
|
||||
using wcontext = buffer_context_t<wchar_t>;
|
||||
struct buffer_context {
|
||||
typedef basic_context<
|
||||
std::back_insert_iterator<internal::basic_buffer<Char>>, Char> type;
|
||||
};
|
||||
typedef buffer_context<char>::type context;
|
||||
typedef buffer_context<wchar_t>::type wcontext;
|
||||
|
||||
namespace internal {
|
||||
template <typename Context, typename T>
|
||||
class get_type {
|
||||
private:
|
||||
static const T& val();
|
||||
|
||||
public:
|
||||
using value_type = decltype(make_value<Context>(val()));
|
||||
struct get_type {
|
||||
typedef decltype(make_value<Context>(
|
||||
declval<typename std::decay<T>::type&>())) value_type;
|
||||
static const type value = value_type::type_tag;
|
||||
};
|
||||
|
||||
@ -923,10 +955,10 @@ class arg_store {
|
||||
static const size_t NUM_ARGS = sizeof...(Args);
|
||||
|
||||
// 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;
|
||||
|
||||
using value_type = typename std::conditional<
|
||||
IS_PACKED, internal::value<Context>, basic_arg<Context>>::type;
|
||||
typedef typename std::conditional<
|
||||
IS_PACKED, internal::value<Context>, basic_arg<Context>>::type value_type;
|
||||
|
||||
// If the arguments are not packed, add one more element to mark the end.
|
||||
value_type data_[NUM_ARGS + (IS_PACKED && NUM_ARGS != 0 ? 0 : 1)];
|
||||
@ -934,8 +966,15 @@ class arg_store {
|
||||
public:
|
||||
static const uint64_t TYPES;
|
||||
|
||||
#if FMT_GCC_VERSION && FMT_GCC_VERSION <= 405 && !defined(__clang__)
|
||||
// Workaround an array initialization bug in gcc 4.5 and earlier.
|
||||
arg_store(const Args &... args) {
|
||||
data_ = {internal::make_arg<IS_PACKED, Context>(args)...};
|
||||
}
|
||||
#else
|
||||
arg_store(const Args &... args)
|
||||
: data_{internal::make_arg<IS_PACKED, Context>(args)...} {}
|
||||
#endif
|
||||
|
||||
basic_format_args<Context> operator*() const { return *this; }
|
||||
|
||||
@ -961,15 +1000,15 @@ inline arg_store<context, Args...> make_args(const Args & ... args) {
|
||||
template <typename Context>
|
||||
class basic_format_args {
|
||||
public:
|
||||
using size_type = unsigned;
|
||||
using format_arg = basic_arg<Context> ;
|
||||
typedef unsigned size_type;
|
||||
typedef basic_arg<Context> format_arg;
|
||||
|
||||
private:
|
||||
// To reduce compiled code size per formatting function call, types of first
|
||||
// MAX_PACKED_ARGS arguments are passed in the types_ field.
|
||||
// max_packed_args arguments are passed in the types_ field.
|
||||
uint64_t types_;
|
||||
union {
|
||||
// If the number of arguments is less than MAX_PACKED_ARGS, the argument
|
||||
// If the number of arguments is less than max_packed_args, the argument
|
||||
// values are stored in values_, otherwise they are stored in args_.
|
||||
// This is done to reduce compiled code size as storing larger objects
|
||||
// may require more code (at least on x86-64) even if the same amount of
|
||||
@ -997,10 +1036,10 @@ class basic_format_args {
|
||||
return index < num_args ? args_[index] : format_arg();
|
||||
}
|
||||
format_arg arg;
|
||||
if (index > internal::MAX_PACKED_ARGS)
|
||||
if (index > internal::max_packed_args)
|
||||
return arg;
|
||||
arg.type_ = type(index);
|
||||
if (arg.type_ == internal::NONE)
|
||||
if (arg.type_ == internal::none_type)
|
||||
return arg;
|
||||
internal::value<Context> &val = arg.value_;
|
||||
val = values_[index];
|
||||
@ -1019,19 +1058,25 @@ class basic_format_args {
|
||||
/** Returns the argument at specified index. */
|
||||
format_arg operator[](size_type index) const {
|
||||
format_arg arg = get(index);
|
||||
return arg.type_ == internal::NAMED_ARG ?
|
||||
return arg.type_ == internal::name_arg_type ?
|
||||
arg.value_.as_named_arg().template deserialize<Context>() : arg;
|
||||
}
|
||||
|
||||
unsigned max_size() const {
|
||||
int64_t signed_types = static_cast<int64_t>(types_);
|
||||
return signed_types < 0 ?
|
||||
-signed_types : static_cast<int64_t>(internal::MAX_PACKED_ARGS);
|
||||
-signed_types : static_cast<int64_t>(internal::max_packed_args);
|
||||
}
|
||||
};
|
||||
|
||||
using format_args = basic_format_args<context>;
|
||||
using wformat_args = basic_format_args<wcontext>;
|
||||
/** An alias to ``basic_format_args<context>``. */
|
||||
// It is a separate type rather than a typedef to make symbols readable.
|
||||
struct format_args: basic_format_args<context> {
|
||||
template <typename ...Args>
|
||||
format_args(Args && ... arg)
|
||||
: basic_format_args<context>(std::forward<Args>(arg)...) {};
|
||||
};
|
||||
typedef basic_format_args<wcontext> wformat_args;
|
||||
|
||||
namespace internal {
|
||||
template <typename Char>
|
||||
@ -1062,11 +1107,11 @@ struct named_arg : named_arg_base<Char> {
|
||||
|
||||
/**
|
||||
\rst
|
||||
Returns a named argument for formatting functions.
|
||||
Returns a named argument to be used in a formatting function.
|
||||
|
||||
**Example**::
|
||||
|
||||
print("Elapsed time: {s:.2f} seconds", arg("s", 1.23));
|
||||
fmt::print("Elapsed time: {s:.2f} seconds", fmt::arg("s", 1.23));
|
||||
\endrst
|
||||
*/
|
||||
template <typename T>
|
||||
@ -1081,29 +1126,29 @@ inline internal::named_arg<T, wchar_t> arg(wstring_view name, const T &arg) {
|
||||
|
||||
// This function template is deleted intentionally to disable nested named
|
||||
// arguments as in ``format("{}", arg("a", arg("b", 42)))``.
|
||||
template <typename S, typename... T>
|
||||
void arg(S, internal::named_arg<T...>) FMT_DELETED;
|
||||
template <typename S, typename T, typename Char>
|
||||
void arg(S, internal::named_arg<T, Char>) FMT_DELETED;
|
||||
|
||||
enum Color { BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE };
|
||||
enum color { black, red, green, yellow, blue, magenta, cyan, white };
|
||||
|
||||
FMT_API void vprint_colored(Color c, string_view format, format_args args);
|
||||
FMT_API void vprint_colored(color c, string_view format, format_args args);
|
||||
|
||||
/**
|
||||
Formats a string and prints it to stdout using ANSI escape sequences to
|
||||
specify color (experimental).
|
||||
Example:
|
||||
print_colored(fmt::RED, "Elapsed time: {0:.2f} seconds", 1.23);
|
||||
fmt::print_colored(fmt::RED, "Elapsed time: {0:.2f} seconds", 1.23);
|
||||
*/
|
||||
template <typename... Args>
|
||||
inline void print_colored(Color c, string_view format_str,
|
||||
inline void print_colored(color c, string_view format_str,
|
||||
const Args & ... args) {
|
||||
vprint_colored(c, format_str, make_args(args...));
|
||||
}
|
||||
|
||||
void vformat_to(internal::buffer &buf, string_view format_str,
|
||||
format_args args);
|
||||
void vformat_to(internal::wbuffer &buf, wstring_view format_str,
|
||||
wformat_args args);
|
||||
context::iterator vformat_to(internal::buffer &buf, string_view format_str,
|
||||
format_args args);
|
||||
wcontext::iterator vformat_to(internal::wbuffer &buf, wstring_view format_str,
|
||||
wformat_args args);
|
||||
|
||||
template <typename Container>
|
||||
struct is_contiguous : std::false_type {};
|
||||
@ -1116,11 +1161,14 @@ struct is_contiguous<fmt::internal::basic_buffer<Char>> : std::true_type {};
|
||||
|
||||
/** Formats a string and writes the output to ``out``. */
|
||||
template <typename Container>
|
||||
typename std::enable_if<is_contiguous<Container>::value>::type
|
||||
typename std::enable_if<
|
||||
is_contiguous<Container>::value, std::back_insert_iterator<Container>>::type
|
||||
vformat_to(std::back_insert_iterator<Container> out,
|
||||
string_view format_str, format_args args) {
|
||||
internal::container_buffer<Container> buf(internal::get_container(out));
|
||||
auto& container = internal::get_container(out);
|
||||
internal::container_buffer<Container> buf(container);
|
||||
vformat_to(buf, format_str, args);
|
||||
return std::back_inserter(container);
|
||||
}
|
||||
|
||||
std::string vformat(string_view format_str, format_args args);
|
||||
@ -1132,16 +1180,22 @@ std::wstring vformat(wstring_view format_str, wformat_args args);
|
||||
|
||||
**Example**::
|
||||
|
||||
std::string message = format("The answer is {}", 42);
|
||||
#include <fmt/core.h>
|
||||
std::string message = fmt::format("The answer is {}", 42);
|
||||
\endrst
|
||||
*/
|
||||
template <typename... Args>
|
||||
inline std::string format(string_view format_str, const Args & ... args) {
|
||||
return vformat(format_str, make_args(args...));
|
||||
// This should be just
|
||||
// return vformat(format_str, make_args(args...));
|
||||
// but gcc has trouble optimizing the latter, so break it down.
|
||||
arg_store<context, Args...> as(args...);
|
||||
return vformat(format_str, as);
|
||||
}
|
||||
template <typename... Args>
|
||||
inline std::wstring format(wstring_view format_str, const Args & ... args) {
|
||||
return vformat(format_str, make_args<wcontext>(args...));
|
||||
arg_store<wcontext, Args...> as(args...);
|
||||
return vformat(format_str, as);
|
||||
}
|
||||
|
||||
FMT_API void vprint(std::FILE *f, string_view format_str, format_args args);
|
||||
@ -1152,12 +1206,13 @@ FMT_API void vprint(std::FILE *f, string_view format_str, format_args args);
|
||||
|
||||
**Example**::
|
||||
|
||||
print(stderr, "Don't {}!", "panic");
|
||||
fmt::print(stderr, "Don't {}!", "panic");
|
||||
\endrst
|
||||
*/
|
||||
template <typename... Args>
|
||||
inline void print(std::FILE *f, string_view format_str, const Args & ... args) {
|
||||
vprint(f, format_str, make_args(args...));
|
||||
arg_store<context, Args...> as(args...);
|
||||
vprint(f, format_str, as);
|
||||
}
|
||||
|
||||
FMT_API void vprint(string_view format_str, format_args args);
|
||||
@ -1168,12 +1223,13 @@ FMT_API void vprint(string_view format_str, format_args args);
|
||||
|
||||
**Example**::
|
||||
|
||||
print("Elapsed time: {0:.2f} seconds", 1.23);
|
||||
fmt::print("Elapsed time: {0:.2f} seconds", 1.23);
|
||||
\endrst
|
||||
*/
|
||||
template <typename... Args>
|
||||
inline void print(string_view format_str, const Args & ... args) {
|
||||
vprint(format_str, make_args(args...));
|
||||
arg_store<context, Args...> as(args...);
|
||||
vprint(format_str, as);
|
||||
}
|
||||
} // namespace fmt
|
||||
|
||||
|
||||
@ -166,7 +166,7 @@ int safe_strerror(
|
||||
void format_error_code(internal::buffer &out, int error_code,
|
||||
string_view message) FMT_NOEXCEPT {
|
||||
// Report error code making sure that the output fits into
|
||||
// INLINE_BUFFER_SIZE to avoid dynamic memory allocation and potential
|
||||
// inline_buffer_size to avoid dynamic memory allocation and potential
|
||||
// bad_alloc.
|
||||
out.resize(0);
|
||||
static const char SEP[] = ": ";
|
||||
@ -181,13 +181,13 @@ void format_error_code(internal::buffer &out, int error_code,
|
||||
}
|
||||
error_code_size += internal::count_digits(abs_value);
|
||||
writer w(out);
|
||||
if (message.size() <= internal::INLINE_BUFFER_SIZE - error_code_size) {
|
||||
if (message.size() <= inline_buffer_size - error_code_size) {
|
||||
w.write(message);
|
||||
w.write(SEP);
|
||||
}
|
||||
w.write(ERROR_STR);
|
||||
w.write(error_code);
|
||||
assert(out.size() <= internal::INLINE_BUFFER_SIZE);
|
||||
assert(out.size() <= inline_buffer_size);
|
||||
}
|
||||
|
||||
void report_error(FormatFunc func, int error_code,
|
||||
@ -332,7 +332,7 @@ FMT_FUNC void internal::format_windows_error(
|
||||
internal::buffer &out, int error_code, string_view message) FMT_NOEXCEPT {
|
||||
FMT_TRY {
|
||||
wmemory_buffer buf;
|
||||
buf.resize(INLINE_BUFFER_SIZE);
|
||||
buf.resize(inline_buffer_size);
|
||||
for (;;) {
|
||||
wchar_t *system_message = &buf[0];
|
||||
int result = FormatMessageW(
|
||||
@ -364,7 +364,7 @@ FMT_FUNC void format_system_error(
|
||||
internal::buffer &out, int error_code, string_view message) FMT_NOEXCEPT {
|
||||
FMT_TRY {
|
||||
memory_buffer buf;
|
||||
buf.resize(internal::INLINE_BUFFER_SIZE);
|
||||
buf.resize(inline_buffer_size);
|
||||
for (;;) {
|
||||
char *system_message = &buf[0];
|
||||
int result = safe_strerror(error_code, system_message, buf.size());
|
||||
@ -414,7 +414,7 @@ FMT_FUNC void vprint(string_view format_str, format_args args) {
|
||||
vprint(stdout, format_str, args);
|
||||
}
|
||||
|
||||
FMT_FUNC void vprint_colored(Color c, string_view format, format_args args) {
|
||||
FMT_FUNC void vprint_colored(color c, string_view format, format_args args) {
|
||||
char escape[] = "\x1b[30m";
|
||||
escape[3] = static_cast<char>('0' + c);
|
||||
std::fputs(escape, stdout);
|
||||
@ -434,7 +434,8 @@ template char internal::thousands_sep(locale_provider *lp);
|
||||
|
||||
template void basic_fixed_buffer<char>::grow(std::size_t);
|
||||
|
||||
template void internal::arg_map<context>::init(const format_args &args);
|
||||
template void internal::arg_map<context>::init(
|
||||
const basic_format_args<context> &args);
|
||||
|
||||
template FMT_API int internal::char_traits<char>::format_float(
|
||||
char *buffer, std::size_t size, const char *format,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -46,28 +46,31 @@ class FormatBuf : public std::basic_streambuf<Char> {
|
||||
}
|
||||
};
|
||||
|
||||
struct test_stream : std::ostream {
|
||||
template <typename Char>
|
||||
struct test_stream : std::basic_ostream<Char> {
|
||||
private:
|
||||
struct null;
|
||||
// Hide all operator<< from std::ostream.
|
||||
// Hide all operator<< from std::basic_ostream<Char>.
|
||||
void operator<<(null);
|
||||
};
|
||||
|
||||
// Disable conversion to int if T has an overloaded operator<< which is a free
|
||||
// function (not a member of std::ostream).
|
||||
template <typename T>
|
||||
class convert_to_int<T, true> {
|
||||
template <typename T, typename Char>
|
||||
class convert_to_int<T, Char, true> {
|
||||
private:
|
||||
template <typename U>
|
||||
static decltype(
|
||||
std::declval<test_stream&>() << std::declval<U>(), std::true_type())
|
||||
test(int);
|
||||
internal::declval<test_stream<Char>&>()
|
||||
<< internal::declval<U>(), std::true_type()) test(int);
|
||||
|
||||
template <typename>
|
||||
static std::false_type test(...);
|
||||
|
||||
typedef decltype(test<T>(0)) result;
|
||||
|
||||
public:
|
||||
static const bool value = !decltype(test<T>(0))::value;
|
||||
static const bool value = !result::value;
|
||||
};
|
||||
|
||||
// Write the content of buf to os.
|
||||
@ -104,8 +107,8 @@ struct format_enum<T,
|
||||
// Formats an object of type T that has an overloaded ostream operator<<.
|
||||
template <typename T, typename Char>
|
||||
struct formatter<T, Char,
|
||||
typename std::enable_if<
|
||||
!internal::format_type<buffer_context_t<Char>, T>::value>::type>
|
||||
typename std::enable_if<!internal::format_type<
|
||||
typename buffer_context<Char>::type, T>::value>::type>
|
||||
: formatter<basic_string_view<Char>, Char> {
|
||||
|
||||
template <typename Context>
|
||||
@ -130,7 +133,7 @@ inline void vprint(std::ostream &os, string_view format_str, format_args args) {
|
||||
|
||||
**Example**::
|
||||
|
||||
print(cerr, "Don't {}!", "panic");
|
||||
fmt::print(cerr, "Don't {}!", "panic");
|
||||
\endrst
|
||||
*/
|
||||
template <typename... Args>
|
||||
|
||||
@ -71,7 +71,8 @@ fmt::BufferedFile::~BufferedFile() FMT_NOEXCEPT {
|
||||
|
||||
fmt::BufferedFile::BufferedFile(
|
||||
fmt::cstring_view filename, fmt::cstring_view mode) {
|
||||
FMT_RETRY_VAL(file_, FMT_SYSTEM(fopen(filename.c_str(), mode.c_str())), 0);
|
||||
FMT_RETRY_VAL(file_,
|
||||
FMT_SYSTEM(fopen(filename.c_str(), mode.c_str())), FMT_NULL);
|
||||
if (!file_)
|
||||
FMT_THROW(system_error(errno, "cannot open file {}", filename.c_str()));
|
||||
}
|
||||
@ -180,8 +181,8 @@ void fmt::File::dup2(int fd) {
|
||||
int result = 0;
|
||||
FMT_RETRY(result, FMT_POSIX_CALL(dup2(fd_, fd)));
|
||||
if (result == -1) {
|
||||
throw system_error(errno,
|
||||
"cannot duplicate file descriptor {} to {}", fd_, fd);
|
||||
FMT_THROW(system_error(errno,
|
||||
"cannot duplicate file descriptor {} to {}", fd_, fd));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -134,7 +134,7 @@ class BufferedFile {
|
||||
|
||||
public:
|
||||
// Constructs a BufferedFile object which doesn't represent any file.
|
||||
BufferedFile() FMT_NOEXCEPT : file_(0) {}
|
||||
BufferedFile() FMT_NOEXCEPT : file_(FMT_NULL) {}
|
||||
|
||||
// Destroys the object closing the file it represents if any.
|
||||
FMT_API ~BufferedFile() FMT_DTOR_NOEXCEPT;
|
||||
@ -353,7 +353,7 @@ class File {
|
||||
long getpagesize();
|
||||
|
||||
#if (defined(LC_NUMERIC_MASK) || defined(_MSC_VER)) && \
|
||||
!defined(__ANDROID__) && !defined(__CYGWIN__)
|
||||
!defined(__ANDROID__) && !defined(__CYGWIN__) && !defined(__OpenBSD__)
|
||||
# define FMT_LOCALE
|
||||
#endif
|
||||
|
||||
|
||||
@ -19,7 +19,7 @@ namespace internal {
|
||||
// Checks if a value fits in int - used to avoid warnings about comparing
|
||||
// signed and unsigned integers.
|
||||
template <bool IsSigned>
|
||||
struct IntChecker {
|
||||
struct int_checker {
|
||||
template <typename T>
|
||||
static bool fits_in_int(T value) {
|
||||
unsigned max = std::numeric_limits<int>::max();
|
||||
@ -29,7 +29,7 @@ struct IntChecker {
|
||||
};
|
||||
|
||||
template <>
|
||||
struct IntChecker<true> {
|
||||
struct int_checker<true> {
|
||||
template <typename T>
|
||||
static bool fits_in_int(T value) {
|
||||
return value >= std::numeric_limits<int>::min() &&
|
||||
@ -38,12 +38,12 @@ struct IntChecker<true> {
|
||||
static bool fits_in_int(int) { return true; }
|
||||
};
|
||||
|
||||
class PrintfPrecisionHandler {
|
||||
class printf_precision_handler: public function<int> {
|
||||
public:
|
||||
template <typename T>
|
||||
typename std::enable_if<std::is_integral<T>::value, int>::type
|
||||
operator()(T value) {
|
||||
if (!IntChecker<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"));
|
||||
return static_cast<int>(value);
|
||||
}
|
||||
@ -57,7 +57,7 @@ class PrintfPrecisionHandler {
|
||||
};
|
||||
|
||||
// An argument visitor that returns true iff arg is a zero integer.
|
||||
class IsZeroInt {
|
||||
class is_zero_int: public function<bool> {
|
||||
public:
|
||||
template <typename T>
|
||||
typename std::enable_if<std::is_integral<T>::value, bool>::type
|
||||
@ -73,11 +73,11 @@ struct make_unsigned_or_bool : std::make_unsigned<T> {};
|
||||
|
||||
template <>
|
||||
struct make_unsigned_or_bool<bool> {
|
||||
using type = bool;
|
||||
typedef bool type;
|
||||
};
|
||||
|
||||
template <typename T, typename Context>
|
||||
class ArgConverter {
|
||||
class arg_converter: public function<void> {
|
||||
private:
|
||||
typedef typename Context::char_type Char;
|
||||
|
||||
@ -85,7 +85,7 @@ class ArgConverter {
|
||||
typename Context::char_type type_;
|
||||
|
||||
public:
|
||||
ArgConverter(basic_arg<Context> &arg, Char type)
|
||||
arg_converter(basic_arg<Context> &arg, Char type)
|
||||
: arg_(arg), type_(type) {}
|
||||
|
||||
void operator()(bool value) {
|
||||
@ -134,19 +134,19 @@ class ArgConverter {
|
||||
// unsigned).
|
||||
template <typename T, typename Context, typename Char>
|
||||
void convert_arg(basic_arg<Context> &arg, Char type) {
|
||||
visit(ArgConverter<T, Context>(arg, type), arg);
|
||||
visit(arg_converter<T, Context>(arg, type), arg);
|
||||
}
|
||||
|
||||
// Converts an integer argument to char for printf.
|
||||
template <typename Context>
|
||||
class CharConverter {
|
||||
class char_converter: public function<void> {
|
||||
private:
|
||||
basic_arg<Context> &arg_;
|
||||
|
||||
FMT_DISALLOW_COPY_AND_ASSIGN(CharConverter);
|
||||
FMT_DISALLOW_COPY_AND_ASSIGN(char_converter);
|
||||
|
||||
public:
|
||||
explicit CharConverter(basic_arg<Context> &arg) : arg_(arg) {}
|
||||
explicit char_converter(basic_arg<Context> &arg) : arg_(arg) {}
|
||||
|
||||
template <typename T>
|
||||
typename std::enable_if<std::is_integral<T>::value>::type
|
||||
@ -163,16 +163,16 @@ class CharConverter {
|
||||
// Checks if an argument is a valid printf width specifier and sets
|
||||
// left alignment if it is negative.
|
||||
template <typename Char>
|
||||
class PrintfWidthHandler {
|
||||
class printf_width_handler: public function<unsigned> {
|
||||
private:
|
||||
typedef basic_format_specs<Char> format_specs;
|
||||
|
||||
format_specs &spec_;
|
||||
|
||||
FMT_DISALLOW_COPY_AND_ASSIGN(PrintfWidthHandler);
|
||||
FMT_DISALLOW_COPY_AND_ASSIGN(printf_width_handler);
|
||||
|
||||
public:
|
||||
explicit PrintfWidthHandler(format_specs &spec) : spec_(spec) {}
|
||||
explicit printf_width_handler(format_specs &spec) : spec_(spec) {}
|
||||
|
||||
template <typename T>
|
||||
typename std::enable_if<std::is_integral<T>::value, unsigned>::type
|
||||
@ -213,12 +213,13 @@ class basic_printf_context;
|
||||
\endrst
|
||||
*/
|
||||
template <typename Range>
|
||||
class printf_arg_formatter : public internal::arg_formatter_base<Range> {
|
||||
class printf_arg_formatter:
|
||||
public internal::function<void>, public internal::arg_formatter_base<Range> {
|
||||
private:
|
||||
using char_type = typename Range::value_type;
|
||||
using iterator = decltype(std::declval<Range>().begin());
|
||||
using base = internal::arg_formatter_base<Range>;
|
||||
using context_type = basic_printf_context<iterator, char_type>;
|
||||
typedef typename Range::value_type char_type;
|
||||
typedef decltype(internal::declval<Range>().begin()) iterator;
|
||||
typedef internal::arg_formatter_base<Range> base;
|
||||
typedef basic_printf_context<iterator, char_type> context_type;
|
||||
|
||||
context_type &context_;
|
||||
|
||||
@ -228,7 +229,7 @@ class printf_arg_formatter : public internal::arg_formatter_base<Range> {
|
||||
}
|
||||
|
||||
public:
|
||||
using format_specs = typename base::format_specs;
|
||||
typedef typename base::format_specs format_specs;
|
||||
|
||||
/**
|
||||
\rst
|
||||
@ -290,7 +291,7 @@ class printf_arg_formatter : public internal::arg_formatter_base<Range> {
|
||||
template <typename T>
|
||||
struct printf_formatter {
|
||||
template <typename ParseContext>
|
||||
auto parse(ParseContext &ctx) { return ctx.begin(); }
|
||||
auto parse(ParseContext &ctx) -> decltype(ctx.begin()) { return ctx.begin(); }
|
||||
|
||||
template <typename FormatContext>
|
||||
auto format(const T &value, FormatContext &ctx) -> decltype(ctx.begin()) {
|
||||
@ -306,16 +307,16 @@ class basic_printf_context :
|
||||
OutputIt, basic_printf_context<OutputIt, Char, ArgFormatter>, Char> {
|
||||
public:
|
||||
/** The character type for the output. */
|
||||
using char_type = Char;
|
||||
typedef Char char_type;
|
||||
|
||||
template <typename T>
|
||||
using formatter_type = printf_formatter<T>;
|
||||
struct formatter_type { typedef printf_formatter<T> type; };
|
||||
|
||||
private:
|
||||
using base = internal::context_base<OutputIt, basic_printf_context, Char>;
|
||||
using format_arg = typename base::format_arg;
|
||||
using format_specs = basic_format_specs<char_type>;
|
||||
using iterator = internal::null_terminating_iterator<char_type>;
|
||||
typedef internal::context_base<OutputIt, basic_printf_context, Char> base;
|
||||
typedef typename base::format_arg format_arg;
|
||||
typedef basic_format_specs<char_type> format_specs;
|
||||
typedef internal::null_terminating_iterator<char_type> iterator;
|
||||
|
||||
void parse_flags(format_specs &spec, iterator &it);
|
||||
|
||||
@ -417,7 +418,7 @@ unsigned basic_printf_context<OutputIt, Char, AF>::parse_header(
|
||||
} else if (*it == '*') {
|
||||
++it;
|
||||
spec.width_ =
|
||||
visit(internal::PrintfWidthHandler<char_type>(spec), get_arg(it));
|
||||
visit(internal::printf_width_handler<char_type>(spec), get_arg(it));
|
||||
}
|
||||
return arg_index;
|
||||
}
|
||||
@ -453,14 +454,14 @@ void basic_printf_context<OutputIt, Char, AF>::format() {
|
||||
} else if (*it == '*') {
|
||||
++it;
|
||||
spec.precision_ =
|
||||
visit(internal::PrintfPrecisionHandler(), get_arg(it));
|
||||
visit(internal::printf_precision_handler(), get_arg(it));
|
||||
} else {
|
||||
spec.precision_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
format_arg arg = get_arg(it, arg_index);
|
||||
if (spec.flag(HASH_FLAG) && visit(internal::IsZeroInt(), arg))
|
||||
if (spec.flag(HASH_FLAG) && visit(internal::is_zero_int(), arg))
|
||||
spec.flags_ &= ~internal::to_unsigned<int>(HASH_FLAG);
|
||||
if (spec.fill_ == '0') {
|
||||
if (arg.is_arithmetic())
|
||||
@ -514,7 +515,7 @@ void basic_printf_context<OutputIt, Char, AF>::format() {
|
||||
break;
|
||||
case 'c':
|
||||
// TODO: handle wchar_t
|
||||
visit(internal::CharConverter<basic_printf_context>(arg), arg);
|
||||
visit(internal::char_converter<basic_printf_context>(arg), arg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -534,10 +535,12 @@ void printf(internal::basic_buffer<Char> &buf, basic_string_view<Char> format,
|
||||
}
|
||||
|
||||
template <typename Buffer>
|
||||
using printf_context = basic_printf_context<
|
||||
std::back_insert_iterator<Buffer>, typename Buffer::value_type>;
|
||||
struct printf_context {
|
||||
typedef basic_printf_context<
|
||||
std::back_insert_iterator<Buffer>, typename Buffer::value_type> type;
|
||||
};
|
||||
|
||||
using printf_args = basic_format_args<printf_context<internal::buffer>>;
|
||||
typedef basic_format_args<printf_context<internal::buffer>::type> printf_args;
|
||||
|
||||
inline std::string vsprintf(string_view format, printf_args args) {
|
||||
memory_buffer buffer;
|
||||
@ -557,12 +560,12 @@ inline std::string vsprintf(string_view format, printf_args args) {
|
||||
template <typename... Args>
|
||||
inline std::string sprintf(string_view format_str, const Args & ... args) {
|
||||
return vsprintf(format_str,
|
||||
make_args<printf_context<internal::buffer>>(args...));
|
||||
make_args<typename printf_context<internal::buffer>::type>(args...));
|
||||
}
|
||||
|
||||
inline std::wstring vsprintf(
|
||||
wstring_view format,
|
||||
basic_format_args<printf_context<internal::wbuffer>> args) {
|
||||
basic_format_args<printf_context<internal::wbuffer>::type> args) {
|
||||
wmemory_buffer buffer;
|
||||
printf(buffer, format, args);
|
||||
return to_string(buffer);
|
||||
@ -570,7 +573,8 @@ inline std::wstring vsprintf(
|
||||
|
||||
template <typename... Args>
|
||||
inline std::wstring sprintf(wstring_view format_str, const Args & ... args) {
|
||||
auto vargs = make_args<printf_context<internal::wbuffer>>(args...);
|
||||
auto vargs = make_args<
|
||||
typename printf_context<internal::wbuffer>::type>(args...);
|
||||
return vsprintf(format_str, vargs);
|
||||
}
|
||||
|
||||
@ -593,7 +597,8 @@ inline int vfprintf(std::FILE *f, string_view format, printf_args args) {
|
||||
*/
|
||||
template <typename... Args>
|
||||
inline int fprintf(std::FILE *f, string_view format_str, const Args & ... args) {
|
||||
auto vargs = make_args<printf_context<internal::buffer>>(args...);
|
||||
auto vargs = make_args<
|
||||
typename printf_context<internal::buffer>::type>(args...);
|
||||
return vfprintf(f, format_str, vargs);
|
||||
}
|
||||
|
||||
@ -613,7 +618,7 @@ inline int vprintf(string_view format, printf_args args) {
|
||||
template <typename... Args>
|
||||
inline int printf(string_view format_str, const Args & ... args) {
|
||||
return vprintf(format_str,
|
||||
make_args<printf_context<internal::buffer>>(args...));
|
||||
make_args<typename printf_context<internal::buffer>::type>(args...));
|
||||
}
|
||||
|
||||
inline int vfprintf(std::ostream &os, string_view format_str,
|
||||
@ -630,13 +635,14 @@ inline int vfprintf(std::ostream &os, string_view format_str,
|
||||
|
||||
**Example**::
|
||||
|
||||
fprintf(cerr, "Don't %s!", "panic");
|
||||
fmt::fprintf(cerr, "Don't %s!", "panic");
|
||||
\endrst
|
||||
*/
|
||||
template <typename... Args>
|
||||
inline int fprintf(std::ostream &os, string_view format_str,
|
||||
const Args & ... args) {
|
||||
auto vargs = make_args<printf_context<internal::buffer>>(args...);
|
||||
auto vargs = make_args<
|
||||
typename printf_context<internal::buffer>::type>(args...);
|
||||
return vfprintf(os, format_str, vargs);
|
||||
}
|
||||
} // namespace fmt
|
||||
|
||||
@ -40,6 +40,17 @@ if (FMT_USE_CPP14)
|
||||
check_cxx_compiler_flag(-std=c++1y HAVE_STD_CPP1Y_FLAG)
|
||||
if (HAVE_STD_CPP1Y_FLAG)
|
||||
set(CPP14_FLAG -std=c++1y)
|
||||
else ()
|
||||
# Fallback on c++11 if c++14 is not available.
|
||||
check_cxx_compiler_flag(-std=c++11 HAVE_STD_CPP11_FLAG)
|
||||
if (HAVE_STD_CPP11_FLAG)
|
||||
set(CPP14_FLAG -std=c++11)
|
||||
else ()
|
||||
check_cxx_compiler_flag(-std=c++0x HAVE_STD_CPP0X_FLAG)
|
||||
if (HAVE_STD_CPP0X_FLAG)
|
||||
set(CPP14_FLAG -std=c++0x)
|
||||
endif ()
|
||||
endif ()
|
||||
endif ()
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
@ -1,29 +1,9 @@
|
||||
/*
|
||||
Assertion tests
|
||||
|
||||
Copyright (c) 2015, 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.
|
||||
*/
|
||||
// Formatting library for C++ - assertion tests
|
||||
//
|
||||
// Copyright (c) 2012 - present, Victor Zverovich
|
||||
// All rights reserved.
|
||||
//
|
||||
// For the license information refer to format.h.
|
||||
|
||||
#include "fmt/core.h"
|
||||
#include "gtest/gtest.h"
|
||||
@ -37,5 +17,6 @@
|
||||
#endif
|
||||
|
||||
TEST(AssertTest, Fail) {
|
||||
EXPECT_DEBUG_DEATH_IF_SUPPORTED(FMT_ASSERT(false, "don't panic!"), "don't panic!");
|
||||
EXPECT_DEBUG_DEATH_IF_SUPPORTED(
|
||||
FMT_ASSERT(false, "don't panic!"), "don't panic!");
|
||||
}
|
||||
|
||||
@ -47,22 +47,12 @@ endfunction ()
|
||||
# check if the source file skeleton compiles
|
||||
expect_compile("")
|
||||
|
||||
# MakeArg doesn't accept [const] volatile char *.
|
||||
expect_compile_error("volatile char s[] = \"test\"; (fmt::internal::MakeArg<char>)(s);")
|
||||
expect_compile_error("const volatile char s[] = \"test\"; (fmt::internal::MakeArg<char>)(s);")
|
||||
|
||||
# MakeArg<char> doesn't accept wchar_t.
|
||||
expect_compile_error("fmt::internal::MakeValue<char>(L'a');")
|
||||
expect_compile_error("fmt::internal::MakeValue<char>(L\"test\");")
|
||||
|
||||
# Writing a wide character to a character stream Writer is forbidden.
|
||||
expect_compile_error("fmt::MemoryWriter() << L'a';")
|
||||
expect_compile_error("fmt::MemoryWriter() << fmt::pad(\"abc\", 5, L' ');")
|
||||
expect_compile_error("fmt::MemoryWriter() << fmt::pad(42, 5, L' ');")
|
||||
|
||||
# Formatting a wide character with a narrow format string is forbidden.
|
||||
expect_compile_error("fmt::format(\"{}\", L'a';")
|
||||
|
||||
# Formatting a wide string with a narrow format string is forbidden.
|
||||
expect_compile_error("fmt::format(\"{}\", L\"foo\";")
|
||||
|
||||
# Make sure that compiler features detected in the header
|
||||
# match the features detected in CMake.
|
||||
if (SUPPORTS_USER_DEFINED_LITERALS)
|
||||
|
||||
@ -1,94 +0,0 @@
|
||||
/*
|
||||
Tests of container utilities
|
||||
|
||||
Copyright (c) 2012 - 2016, Victor Zverovich
|
||||
All rights reserved.
|
||||
|
||||
For the license information refer to format.h.
|
||||
*/
|
||||
|
||||
#include "fmt/container.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using fmt::internal::ContainerBuffer;
|
||||
|
||||
TEST(ContainerBufferTest, Empty) {
|
||||
std::string data;
|
||||
ContainerBuffer<std::string> buffer(data);
|
||||
EXPECT_EQ(0u, buffer.size());
|
||||
EXPECT_EQ(0u, buffer.capacity());
|
||||
}
|
||||
|
||||
TEST(ContainerBufferTest, Reserve) {
|
||||
std::string data;
|
||||
ContainerBuffer<std::string> buffer(data);
|
||||
std::size_t capacity = std::string().capacity() + 10;
|
||||
buffer.reserve(capacity);
|
||||
EXPECT_EQ(0u, buffer.size());
|
||||
EXPECT_EQ(capacity, buffer.capacity());
|
||||
}
|
||||
|
||||
TEST(ContainerBufferTest, Resize) {
|
||||
std::string data;
|
||||
ContainerBuffer<std::string> buffer(data);
|
||||
std::size_t size = std::string().capacity() + 10;
|
||||
buffer.resize(size);
|
||||
EXPECT_EQ(size, buffer.size());
|
||||
EXPECT_EQ(size, buffer.capacity());
|
||||
}
|
||||
|
||||
TEST(ContainerBufferTest, Append) {
|
||||
std::string data("Why so");
|
||||
const std::string serious(" serious");
|
||||
ContainerBuffer<std::string> buffer(data);
|
||||
buffer.append(serious.c_str(), serious.c_str() + serious.length());
|
||||
EXPECT_EQ("Why so serious", data);
|
||||
EXPECT_EQ(data.length(), buffer.size());
|
||||
}
|
||||
|
||||
TEST(BasicContainerWriterTest, String) {
|
||||
std::string data;
|
||||
fmt::BasicContainerWriter<std::string> out(data);
|
||||
out << "The answer is " << 42 << "\n";
|
||||
EXPECT_EQ("The answer is 42\n", data);
|
||||
EXPECT_EQ(17u, out.size());
|
||||
}
|
||||
|
||||
TEST(BasicContainerWriterTest, WString) {
|
||||
std::wstring data;
|
||||
fmt::BasicContainerWriter<std::wstring> out(data);
|
||||
out << "The answer is " << 42 << "\n";
|
||||
EXPECT_EQ(L"The answer is 42\n", data);
|
||||
EXPECT_EQ(17u, out.size());
|
||||
}
|
||||
|
||||
TEST(BasicContainerWriterTest, Vector) {
|
||||
std::vector<char> data;
|
||||
fmt::BasicContainerWriter<std::vector<char> > out(data);
|
||||
out << "The answer is " << 42 << "\n";
|
||||
EXPECT_EQ(17u, data.size());
|
||||
EXPECT_EQ(out.size(), data.size());
|
||||
}
|
||||
|
||||
TEST(BasicContainerWriterTest, StringAppend) {
|
||||
std::string data("The");
|
||||
fmt::BasicContainerWriter<std::string> out(data);
|
||||
EXPECT_EQ(3u, data.size());
|
||||
EXPECT_EQ(3u, out.size());
|
||||
out << " answer is " << 42 << "\n";
|
||||
EXPECT_EQ("The answer is 42\n", data);
|
||||
EXPECT_EQ(17u, out.size());
|
||||
}
|
||||
|
||||
TEST(BasicContainerWriterTest, VectorAppend) {
|
||||
std::vector<char> data;
|
||||
data.push_back('T');
|
||||
data.push_back('h');
|
||||
data.push_back('e');
|
||||
fmt::BasicContainerWriter<std::vector<char> > out(data);
|
||||
EXPECT_EQ(3u, data.size());
|
||||
EXPECT_EQ(3u, out.size());
|
||||
out << " answer is " << 42 << "\n";
|
||||
EXPECT_EQ(17u, data.size());
|
||||
EXPECT_EQ(17u, out.size());
|
||||
}
|
||||
@ -1,28 +1,22 @@
|
||||
/*
|
||||
Custom argument formatter tests
|
||||
// Formatting library for C++ - custom argument formatter tests
|
||||
//
|
||||
// Copyright (c) 2012 - present, Victor Zverovich
|
||||
// All rights reserved.
|
||||
//
|
||||
// For the license information refer to format.h.
|
||||
|
||||
Copyright (c) 2016, Victor Zverovich
|
||||
All rights reserved.
|
||||
|
||||
For the license information refer to format.h.
|
||||
*/
|
||||
|
||||
#include "fmt/printf.h"
|
||||
#include "fmt/format.h"
|
||||
#include "gtest-extra.h"
|
||||
|
||||
using fmt::printf_arg_formatter;
|
||||
|
||||
// A custom argument formatter that doesn't print `-` for floating-point values
|
||||
// rounded to 0.
|
||||
class CustomArgFormatter :
|
||||
class custom_arg_formatter :
|
||||
public fmt::arg_formatter<fmt::back_insert_range<fmt::internal::buffer>> {
|
||||
public:
|
||||
using range = fmt::back_insert_range<fmt::internal::buffer>;
|
||||
using iterator = decltype(std::declval<range>().begin());
|
||||
using base = fmt::arg_formatter<range>;
|
||||
typedef fmt::back_insert_range<fmt::internal::buffer> range;
|
||||
typedef fmt::arg_formatter<range> base;
|
||||
|
||||
CustomArgFormatter(fmt::basic_context<iterator, char> &ctx,
|
||||
fmt::format_specs &s)
|
||||
custom_arg_formatter(fmt::context &ctx, fmt::format_specs &s)
|
||||
: base(ctx, s) {}
|
||||
|
||||
using base::operator();
|
||||
@ -37,7 +31,7 @@ class CustomArgFormatter :
|
||||
std::string custom_vformat(fmt::string_view format_str, fmt::format_args args) {
|
||||
fmt::memory_buffer buffer;
|
||||
// Pass custom argument formatter as a template arg to vwrite.
|
||||
fmt::do_vformat_to<CustomArgFormatter>(buffer, format_str, args);
|
||||
fmt::vformat_to<custom_arg_formatter>(buffer, format_str, args);
|
||||
return std::string(buffer.data(), buffer.size());
|
||||
}
|
||||
|
||||
|
||||
@ -1,35 +1,15 @@
|
||||
/*
|
||||
Formatting library implementation tests.
|
||||
|
||||
Copyright (c) 2012-2014, 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.
|
||||
*/
|
||||
// Formatting library for C++ - formatting library implementation tests
|
||||
//
|
||||
// Copyright (c) 2012 - present, Victor Zverovich
|
||||
// All rights reserved.
|
||||
//
|
||||
// For the license information refer to format.h.
|
||||
|
||||
#define FMT_NOEXCEPT
|
||||
#undef FMT_SHARED
|
||||
#include "test-assert.h"
|
||||
|
||||
// Include format.cc instead of format.h to test implementation-specific stuff.
|
||||
// Include format.cc instead of format.h to test implementation.
|
||||
#include "fmt/format.cc"
|
||||
#include "fmt/printf.h"
|
||||
|
||||
@ -44,7 +24,7 @@
|
||||
#undef max
|
||||
|
||||
template <typename T>
|
||||
struct ValueExtractor {
|
||||
struct ValueExtractor: fmt::internal::function<T> {
|
||||
T operator()(T value) {
|
||||
return value;
|
||||
}
|
||||
@ -59,7 +39,7 @@ struct ValueExtractor {
|
||||
TEST(FormatTest, ArgConverter) {
|
||||
long long value = std::numeric_limits<long long>::max();
|
||||
auto arg = fmt::internal::make_arg<fmt::context>(value);
|
||||
visit(fmt::internal::ArgConverter<long long, fmt::context>(arg, 'd'), arg);
|
||||
visit(fmt::internal::arg_converter<long long, fmt::context>(arg, 'd'), arg);
|
||||
EXPECT_EQ(value, visit(ValueExtractor<long long>(), arg));
|
||||
}
|
||||
|
||||
@ -114,7 +94,7 @@ TEST(FormatTest, FormatErrorCode) {
|
||||
{
|
||||
fmt::memory_buffer buffer;
|
||||
std::string prefix(
|
||||
fmt::internal::INLINE_BUFFER_SIZE - msg.size() - sep.size() + 1, 'x');
|
||||
fmt::inline_buffer_size - msg.size() - sep.size() + 1, 'x');
|
||||
fmt::format_error_code(buffer, 42, prefix);
|
||||
EXPECT_EQ(msg, to_string(buffer));
|
||||
}
|
||||
@ -124,10 +104,10 @@ TEST(FormatTest, FormatErrorCode) {
|
||||
msg = fmt::format("error {}", codes[i]);
|
||||
fmt::memory_buffer buffer;
|
||||
std::string prefix(
|
||||
fmt::internal::INLINE_BUFFER_SIZE - msg.size() - sep.size(), 'x');
|
||||
fmt::inline_buffer_size - msg.size() - sep.size(), 'x');
|
||||
fmt::format_error_code(buffer, codes[i], prefix);
|
||||
EXPECT_EQ(prefix + sep + msg, to_string(buffer));
|
||||
std::size_t size = fmt::internal::INLINE_BUFFER_SIZE;
|
||||
std::size_t size = fmt::inline_buffer_size;
|
||||
EXPECT_EQ(size, buffer.size());
|
||||
buffer.resize(0);
|
||||
// Test with a message that doesn't fit into the buffer.
|
||||
|
||||
@ -1,29 +1,9 @@
|
||||
/*
|
||||
Formatting library tests.
|
||||
|
||||
Copyright (c) 2012-2014, 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.
|
||||
*/
|
||||
// Formatting library for C++ - formatting library tests
|
||||
//
|
||||
// Copyright (c) 2012 - present, Victor Zverovich
|
||||
// All rights reserved.
|
||||
//
|
||||
// For the license information refer to format.h.
|
||||
|
||||
#include <cctype>
|
||||
#include <cfloat>
|
||||
@ -89,7 +69,7 @@ void std_format(long double value, std::wstring &result) {
|
||||
template <typename Char, typename T>
|
||||
::testing::AssertionResult check_write(const T &value, const char *type) {
|
||||
fmt::basic_memory_buffer<Char> buffer;
|
||||
using range = fmt::back_insert_range<fmt::internal::basic_buffer<Char>>;
|
||||
typedef fmt::back_insert_range<fmt::internal::basic_buffer<Char>> range;
|
||||
fmt::basic_writer<range> writer(buffer);
|
||||
writer.write(value);
|
||||
std::basic_string<Char> actual = to_string(buffer);
|
||||
@ -137,6 +117,8 @@ TEST(StringViewTest, Ctor) {
|
||||
EXPECT_EQ(4u, string_view(std::string("defg")).size());
|
||||
}
|
||||
|
||||
// GCC 4.6 doesn't have std::is_copy_*.
|
||||
#if FMT_GCC_VERSION && FMT_GCC_VERSION >= 407
|
||||
TEST(WriterTest, NotCopyConstructible) {
|
||||
EXPECT_FALSE(std::is_copy_constructible<fmt::writer>::value);
|
||||
}
|
||||
@ -144,6 +126,7 @@ TEST(WriterTest, NotCopyConstructible) {
|
||||
TEST(WriterTest, NotCopyAssignable) {
|
||||
EXPECT_FALSE(std::is_copy_assignable<fmt::writer>::value);
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST(WriterTest, Data) {
|
||||
memory_buffer buf;
|
||||
@ -209,11 +192,11 @@ TEST(WriterTest, WriteDoubleWithFilledBuffer) {
|
||||
memory_buffer buf;
|
||||
fmt::writer writer(buf);
|
||||
// Fill the buffer.
|
||||
for (int i = 0; i < fmt::internal::INLINE_BUFFER_SIZE; ++i)
|
||||
for (int i = 0; i < fmt::inline_buffer_size; ++i)
|
||||
writer.write(' ');
|
||||
writer.write(1.2);
|
||||
fmt::string_view sv(buf.data(), buf.size());
|
||||
sv.remove_prefix(fmt::internal::INLINE_BUFFER_SIZE);
|
||||
sv.remove_prefix(fmt::inline_buffer_size);
|
||||
EXPECT_EQ("1.2", sv);
|
||||
}
|
||||
|
||||
@ -459,9 +442,9 @@ TEST(FormatterTest, ManyArgs) {
|
||||
format_error, "argument index out of range");
|
||||
EXPECT_THROW_MSG(TestFormat<21>::format("{21}"),
|
||||
format_error, "argument index out of range");
|
||||
enum { MAX_PACKED_ARGS = fmt::internal::MAX_PACKED_ARGS };
|
||||
std::string format_str = fmt::format("{{{}}}", MAX_PACKED_ARGS + 1);
|
||||
EXPECT_THROW_MSG(TestFormat<MAX_PACKED_ARGS>::format(format_str),
|
||||
enum { max_packed_args = fmt::internal::max_packed_args };
|
||||
std::string format_str = fmt::format("{{{}}}", max_packed_args + 1);
|
||||
EXPECT_THROW_MSG(TestFormat<max_packed_args>::format(format_str),
|
||||
format_error, "argument index out of range");
|
||||
}
|
||||
|
||||
@ -549,6 +532,7 @@ TEST(FormatterTest, NumericAlign) {
|
||||
format_error, "format specifier requires numeric argument");
|
||||
EXPECT_THROW_MSG(format("{0:=8}", reinterpret_cast<void*>(0xface)),
|
||||
format_error, "format specifier requires numeric argument");
|
||||
EXPECT_EQ(" 1", fmt::format("{:= }", 1.0));
|
||||
}
|
||||
|
||||
TEST(FormatterTest, CenterAlign) {
|
||||
@ -1202,7 +1186,9 @@ TEST(FormatterTest, FormatPointer) {
|
||||
EXPECT_EQ("0x" + std::string(sizeof(void*) * CHAR_BIT / 4, 'f'),
|
||||
format("{0}", reinterpret_cast<void*>(~uintptr_t())));
|
||||
EXPECT_EQ("0x1234", format("{}", fmt::ptr(reinterpret_cast<int*>(0x1234))));
|
||||
EXPECT_EQ("0x0", format("{}", nullptr));
|
||||
#if FMT_USE_NULLPTR
|
||||
EXPECT_EQ("0x0", format("{}", FMT_NULL));
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(FormatterTest, FormatString) {
|
||||
@ -1213,6 +1199,30 @@ TEST(FormatterTest, FormatStringView) {
|
||||
EXPECT_EQ("test", format("{0}", string_view("test")));
|
||||
}
|
||||
|
||||
#ifdef FMT_USE_STD_STRING_VIEW
|
||||
TEST(FormatterTest, FormatStringView) {
|
||||
EXPECT_EQ("test", format("{0}", std::string_view("test")));
|
||||
}
|
||||
#endif
|
||||
|
||||
struct ConvertibleToString {
|
||||
std::string s;
|
||||
ConvertibleToString() : s("foo") {}
|
||||
operator const std::string &() const { return s; }
|
||||
};
|
||||
|
||||
TEST(FormatterTest, FormatConvertibleToString) {
|
||||
EXPECT_EQ("foo", format("{}", ConvertibleToString()));
|
||||
}
|
||||
|
||||
struct ConvertibleToStringView {
|
||||
operator fmt::string_view() const { return "foo"; }
|
||||
};
|
||||
|
||||
TEST(FormatterTest, FormatConvertibleToStringView) {
|
||||
EXPECT_EQ("foo", format("{}", ConvertibleToStringView()));
|
||||
}
|
||||
|
||||
namespace fmt {
|
||||
template <>
|
||||
struct formatter<Date> {
|
||||
@ -1224,7 +1234,7 @@ struct formatter<Date> {
|
||||
return it;
|
||||
}
|
||||
|
||||
auto format(const Date &d, context &ctx) {
|
||||
auto format(const Date &d, context &ctx) -> decltype(ctx.begin()) {
|
||||
format_to(ctx.begin(), "{}-{}-{}", d.year(), d.month(), d.day());
|
||||
return ctx.begin();
|
||||
}
|
||||
@ -1242,7 +1252,7 @@ class Answer {};
|
||||
namespace fmt {
|
||||
template <>
|
||||
struct formatter<Answer> : formatter<int> {
|
||||
auto format(Answer, fmt::context &ctx) {
|
||||
auto format(Answer, fmt::context &ctx) -> decltype(ctx.begin()) {
|
||||
return formatter<int>::format(42, ctx);
|
||||
}
|
||||
};
|
||||
@ -1396,7 +1406,7 @@ TEST(FormatTest, Print) {
|
||||
|
||||
#if FMT_USE_FILE_DESCRIPTORS
|
||||
TEST(FormatTest, PrintColored) {
|
||||
EXPECT_WRITE(stdout, fmt::print_colored(fmt::RED, "Hello, {}!\n", "world"),
|
||||
EXPECT_WRITE(stdout, fmt::print_colored(fmt::red, "Hello, {}!\n", "world"),
|
||||
"\x1b[31mHello, world!\n\x1b[0m");
|
||||
}
|
||||
#endif
|
||||
@ -1423,7 +1433,7 @@ TEST(FormatTest, JoinArg) {
|
||||
EXPECT_EQ(L"(1, 2, 3)", format(L"({})", join(v1, v1 + 3, L", ")));
|
||||
EXPECT_EQ("1, 2, 3", format("{0:{1}}", join(v1, v1 + 3, ", "), 1));
|
||||
|
||||
#if FMT_HAS_GXX_CXX11
|
||||
#if FMT_USE_TRAILING_RETURN && (!FMT_GCC_VERSION || FMT_GCC_VERSION >= 405)
|
||||
EXPECT_EQ("(1, 2, 3)", format("({})", join(v1, ", ")));
|
||||
EXPECT_EQ("(+01.20, +03.40)", format("({:+06.2f})", join(v2, ", ")));
|
||||
#endif
|
||||
@ -1500,6 +1510,12 @@ TEST(LiteralsTest, NamedArg) {
|
||||
fmt::arg(L"third", 99)),
|
||||
udl_a_w);
|
||||
}
|
||||
|
||||
TEST(FormatTest, UdlTemplate) {
|
||||
EXPECT_EQ("foo", "foo"_format());
|
||||
EXPECT_EQ(" 42", "{0:10}"_format(42));
|
||||
EXPECT_EQ("42", fmt::format(FMT_STRING("{}"), 42));
|
||||
}
|
||||
#endif // FMT_USE_USER_DEFINED_LITERALS
|
||||
|
||||
enum TestEnum { A };
|
||||
@ -1508,7 +1524,7 @@ TEST(FormatTest, Enum) {
|
||||
EXPECT_EQ("0", fmt::format("{}", A));
|
||||
}
|
||||
|
||||
#if FMT_USE_STRONG_ENUMS
|
||||
#if FMT_HAS_FEATURE(cxx_strong_enums)
|
||||
enum TestFixedEnum : short { B };
|
||||
|
||||
TEST(FormatTest, FixedEnum) {
|
||||
@ -1516,16 +1532,17 @@ TEST(FormatTest, FixedEnum) {
|
||||
}
|
||||
#endif
|
||||
|
||||
using buffer_range = fmt::back_insert_range<fmt::internal::buffer>;
|
||||
typedef fmt::back_insert_range<fmt::internal::buffer> buffer_range;
|
||||
|
||||
class mock_arg_formatter :
|
||||
class mock_arg_formatter:
|
||||
public fmt::internal::function<void>,
|
||||
public fmt::internal::arg_formatter_base<buffer_range> {
|
||||
private:
|
||||
MOCK_METHOD1(call, void (int value));
|
||||
|
||||
public:
|
||||
using base = fmt::internal::arg_formatter_base<buffer_range>;
|
||||
using range = buffer_range;
|
||||
typedef fmt::internal::arg_formatter_base<buffer_range> base;
|
||||
typedef buffer_range range;
|
||||
|
||||
mock_arg_formatter(fmt::context &ctx, fmt::format_specs &s)
|
||||
: base(fmt::internal::get_container(ctx.begin()), s) {
|
||||
@ -1541,7 +1558,7 @@ class mock_arg_formatter :
|
||||
|
||||
void custom_vformat(fmt::string_view format_str, fmt::format_args args) {
|
||||
fmt::memory_buffer buffer;
|
||||
fmt::do_vformat_to<mock_arg_formatter>(buffer, format_str, args);
|
||||
fmt::vformat_to<mock_arg_formatter>(buffer, format_str, args);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
@ -1567,10 +1584,10 @@ struct variant {
|
||||
namespace fmt {
|
||||
template <>
|
||||
struct formatter<variant> : dynamic_formatter<> {
|
||||
auto format(variant value, context& ctx) {
|
||||
auto format(variant value, context& ctx) -> decltype(ctx.begin()) {
|
||||
if (value.type == variant::INT)
|
||||
return dynamic_formatter::format(42, ctx);
|
||||
return dynamic_formatter::format("foo", ctx);
|
||||
return dynamic_formatter<>::format(42, ctx);
|
||||
return dynamic_formatter<>::format("foo", ctx);
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -1601,14 +1618,9 @@ TEST(FormatTest, DynamicFormatter) {
|
||||
format_error, "precision not allowed for this argument type");
|
||||
}
|
||||
|
||||
TEST(FormatTest, UdlTemplate) {
|
||||
EXPECT_EQ("foo", "foo"_format());
|
||||
EXPECT_EQ(" 42", "{0:10}"_format(42));
|
||||
EXPECT_EQ("42", fmt::format(FMT_STRING("{}"), 42));
|
||||
}
|
||||
|
||||
TEST(FormatTest, ToString) {
|
||||
EXPECT_EQ("42", fmt::to_string(42));
|
||||
EXPECT_EQ("0x1234", fmt::to_string(reinterpret_cast<void*>(0x1234)));
|
||||
}
|
||||
|
||||
TEST(FormatTest, ToWString) {
|
||||
@ -1719,7 +1731,7 @@ FMT_CONSTEXPR test_format_specs_handler parse_test_specs(const char *s) {
|
||||
}
|
||||
|
||||
TEST(FormatTest, ConstexprParseFormatSpecs) {
|
||||
using handler = test_format_specs_handler;
|
||||
typedef test_format_specs_handler handler;
|
||||
static_assert(parse_test_specs("<").align == fmt::ALIGN_LEFT, "");
|
||||
static_assert(parse_test_specs("*^").fill == '*', "");
|
||||
static_assert(parse_test_specs("+").res == handler::PLUS, "");
|
||||
@ -1736,7 +1748,7 @@ TEST(FormatTest, ConstexprParseFormatSpecs) {
|
||||
}
|
||||
|
||||
struct test_context {
|
||||
using char_type = char;
|
||||
typedef char char_type;
|
||||
|
||||
FMT_CONSTEXPR fmt::basic_arg<test_context> next_arg() {
|
||||
return fmt::internal::make_arg<test_context>(11);
|
||||
@ -1760,7 +1772,7 @@ struct test_context {
|
||||
|
||||
FMT_CONSTEXPR fmt::format_specs parse_specs(const char *s) {
|
||||
fmt::format_specs specs;
|
||||
test_context ctx;
|
||||
test_context ctx{};
|
||||
fmt::internal::specs_handler<test_context> h(specs, ctx);
|
||||
parse_format_specs(s, h);
|
||||
return specs;
|
||||
@ -1786,7 +1798,7 @@ TEST(FormatTest, ConstexprSpecsHandler) {
|
||||
FMT_CONSTEXPR fmt::internal::dynamic_format_specs<char>
|
||||
parse_dynamic_specs(const char *s) {
|
||||
fmt::internal::dynamic_format_specs<char> specs;
|
||||
test_context ctx;
|
||||
test_context ctx{};
|
||||
fmt::internal::dynamic_specs_handler<test_context> h(specs, ctx);
|
||||
parse_format_specs(s, h);
|
||||
return specs;
|
||||
@ -1811,13 +1823,13 @@ TEST(FormatTest, ConstexprDynamicSpecsHandler) {
|
||||
|
||||
FMT_CONSTEXPR test_format_specs_handler check_specs(const char *s) {
|
||||
fmt::internal::specs_checker<test_format_specs_handler>
|
||||
checker(test_format_specs_handler(), fmt::internal::DOUBLE);
|
||||
checker(test_format_specs_handler(), fmt::internal::double_type);
|
||||
parse_format_specs(s, checker);
|
||||
return checker;
|
||||
}
|
||||
|
||||
TEST(FormatTest, ConstexprSpecsChecker) {
|
||||
using handler = test_format_specs_handler;
|
||||
typedef test_format_specs_handler handler;
|
||||
static_assert(check_specs("<").align == fmt::ALIGN_LEFT, "");
|
||||
static_assert(check_specs("*^").fill == '*', "");
|
||||
static_assert(check_specs("+").res == handler::PLUS, "");
|
||||
|
||||
@ -1,29 +1,9 @@
|
||||
/*
|
||||
Tests of custom Google Test assertions.
|
||||
|
||||
Copyright (c) 2012-2014, 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.
|
||||
*/
|
||||
// Formatting library for C++ - tests of custom Google Test assertions
|
||||
//
|
||||
// Copyright (c) 2012 - present, Victor Zverovich
|
||||
// All rights reserved.
|
||||
//
|
||||
// For the license information refer to format.h.
|
||||
|
||||
#include "gtest-extra.h"
|
||||
|
||||
|
||||
@ -1,29 +1,9 @@
|
||||
/*
|
||||
Custom Google Test assertions.
|
||||
|
||||
Copyright (c) 2012-2014, 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.
|
||||
*/
|
||||
// Formatting library for C++ - custom Google Test assertions
|
||||
//
|
||||
// Copyright (c) 2012 - present, Victor Zverovich
|
||||
// All rights reserved.
|
||||
//
|
||||
// For the license information refer to format.h.
|
||||
|
||||
#include "gtest-extra.h"
|
||||
|
||||
|
||||
@ -1,29 +1,9 @@
|
||||
/*
|
||||
Custom Google Test assertions.
|
||||
|
||||
Copyright (c) 2012-2014, 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.
|
||||
*/
|
||||
// Formatting library for C++ - custom Google Test assertions
|
||||
//
|
||||
// Copyright (c) 2012 - present, Victor Zverovich
|
||||
// All rights reserved.
|
||||
//
|
||||
// For the license information refer to format.h.
|
||||
|
||||
#ifndef FMT_GTEST_EXTRA_H_
|
||||
#define FMT_GTEST_EXTRA_H_
|
||||
|
||||
@ -1,29 +1,9 @@
|
||||
/*
|
||||
Mock allocator.
|
||||
|
||||
Copyright (c) 2014, 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.
|
||||
*/
|
||||
// Formatting library for C++ - mock allocator
|
||||
//
|
||||
// Copyright (c) 2012 - present, Victor Zverovich
|
||||
// All rights reserved.
|
||||
//
|
||||
// For the license information refer to format.h.
|
||||
|
||||
#ifndef FMT_MOCK_ALLOCATOR_H_
|
||||
#define FMT_MOCK_ALLOCATOR_H_
|
||||
|
||||
@ -1,29 +1,9 @@
|
||||
/*
|
||||
std::ostream support tests
|
||||
|
||||
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.
|
||||
*/
|
||||
// Formatting library for C++ - std::ostream support tests
|
||||
//
|
||||
// Copyright (c) 2012 - present, Victor Zverovich
|
||||
// All rights reserved.
|
||||
//
|
||||
// For the license information refer to format.h.
|
||||
|
||||
#include "fmt/ostream.h"
|
||||
|
||||
@ -53,12 +33,12 @@ std::ostream &operator<<(std::ostream &os, TestEnum) {
|
||||
enum TestEnum2 {A};
|
||||
|
||||
TEST(OStreamTest, Enum) {
|
||||
EXPECT_FALSE(fmt::internal::convert_to_int<TestEnum>::value);
|
||||
EXPECT_FALSE((fmt::internal::convert_to_int<TestEnum, char>::value));
|
||||
EXPECT_EQ("TestEnum", fmt::format("{}", TestEnum()));
|
||||
EXPECT_EQ("0", fmt::format("{}", A));
|
||||
}
|
||||
|
||||
using range = fmt::back_insert_range<fmt::internal::buffer>;
|
||||
typedef fmt::back_insert_range<fmt::internal::buffer> range;
|
||||
|
||||
struct test_arg_formatter: fmt::arg_formatter<range> {
|
||||
test_arg_formatter(fmt::context &ctx, fmt::format_specs &s)
|
||||
|
||||
@ -1,29 +1,9 @@
|
||||
/*
|
||||
Tests of the C++ interface to POSIX functions that require mocks
|
||||
|
||||
Copyright (c) 2012-2015, 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.
|
||||
*/
|
||||
// Tests of the C++ interface to POSIX functions that require mocks
|
||||
//
|
||||
// Copyright (c) 2012 - present, Victor Zverovich
|
||||
// All rights reserved.
|
||||
//
|
||||
// For the license information refer to format.h.
|
||||
|
||||
// Disable bogus MSVC warnings.
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
|
||||
@ -1,29 +1,9 @@
|
||||
/*
|
||||
Mocks of POSIX functions
|
||||
|
||||
Copyright (c) 2012-2015, 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.
|
||||
*/
|
||||
// Formatting library for C++ - mocks of POSIX functions
|
||||
//
|
||||
// Copyright (c) 2012 - present, Victor Zverovich
|
||||
// All rights reserved.
|
||||
//
|
||||
// For the license information refer to format.h.
|
||||
|
||||
#ifndef FMT_POSIX_TEST_H
|
||||
#define FMT_POSIX_TEST_H
|
||||
|
||||
@ -1,29 +1,9 @@
|
||||
/*
|
||||
Tests of the C++ interface to POSIX functions
|
||||
|
||||
Copyright (c) 2015, 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.
|
||||
*/
|
||||
// Formatting library for C++ - tests of the C++ interface to POSIX functions
|
||||
//
|
||||
// Copyright (c) 2012 - present, Victor Zverovich
|
||||
// All rights reserved.
|
||||
//
|
||||
// For the license information refer to format.h.
|
||||
|
||||
#include <cstdlib> // std::exit
|
||||
#include <cstring>
|
||||
|
||||
@ -1,29 +1,9 @@
|
||||
/*
|
||||
printf tests.
|
||||
|
||||
Copyright (c) 2012-2014, 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.
|
||||
*/
|
||||
// Formatting library for C++ - printf tests
|
||||
//
|
||||
// Copyright (c) 2012 - present, Victor Zverovich
|
||||
// All rights reserved.
|
||||
//
|
||||
// For the license information refer to format.h.
|
||||
|
||||
#include <cctype>
|
||||
#include <climits>
|
||||
|
||||
@ -1,29 +1,9 @@
|
||||
/*
|
||||
Test version of FMT_ASSERT
|
||||
|
||||
Copyright (c) 2015, 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.
|
||||
*/
|
||||
// Formatting library for C++ - test version of FMT_ASSERT
|
||||
//
|
||||
// Copyright (c) 2012 - present, Victor Zverovich
|
||||
// All rights reserved.
|
||||
//
|
||||
// For the license information refer to format.h.
|
||||
|
||||
#ifndef FMT_TEST_ASSERT_H
|
||||
#define FMT_TEST_ASSERT_H
|
||||
|
||||
@ -1,29 +1,9 @@
|
||||
/*
|
||||
Test main function.
|
||||
|
||||
Copyright (c) 2012-2014, 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.
|
||||
*/
|
||||
// Formatting library for C++ - test main function.
|
||||
//
|
||||
// Copyright (c) 2012 - present, Victor Zverovich
|
||||
// All rights reserved.
|
||||
//
|
||||
// For the license information refer to format.h.
|
||||
|
||||
#include <cstdlib>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
@ -1,11 +1,9 @@
|
||||
/*
|
||||
Time formatting tests
|
||||
|
||||
Copyright (c) 2012 - 2016, Victor Zverovich
|
||||
All rights reserved.
|
||||
|
||||
For the license information refer to format.h.
|
||||
*/
|
||||
// Formatting library for C++ - time formatting tests
|
||||
//
|
||||
// Copyright (c) 2012 - present, Victor Zverovich
|
||||
// All rights reserved.
|
||||
//
|
||||
// For the license information refer to format.h.
|
||||
|
||||
#ifdef WIN32
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
|
||||
@ -1,29 +1,9 @@
|
||||
/*
|
||||
Utility tests.
|
||||
|
||||
Copyright (c) 2012-2014, 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.
|
||||
*/
|
||||
// Formatting library for C++ - utility tests
|
||||
//
|
||||
// Copyright (c) 2012 - present, Victor Zverovich
|
||||
// All rights reserved.
|
||||
//
|
||||
// For the license information refer to format.h.
|
||||
|
||||
#include "test-assert.h"
|
||||
|
||||
@ -81,7 +61,7 @@ struct formatter<Test, Char> {
|
||||
return ctx.begin();
|
||||
}
|
||||
|
||||
using iterator = std::back_insert_iterator<basic_buffer<Char>>;
|
||||
typedef std::back_insert_iterator<basic_buffer<Char>> iterator;
|
||||
|
||||
auto format(Test, basic_context<iterator, char> &ctx)
|
||||
-> decltype(ctx.begin()) {
|
||||
@ -361,7 +341,7 @@ TEST(MemoryBufferTest, Allocator) {
|
||||
{
|
||||
basic_memory_buffer<char, 10, TestAllocator> buffer2((TestAllocator(&alloc)));
|
||||
EXPECT_EQ(&alloc, buffer2.get_allocator().get());
|
||||
std::size_t size = 2 * fmt::internal::INLINE_BUFFER_SIZE;
|
||||
std::size_t size = 2 * fmt::inline_buffer_size;
|
||||
EXPECT_CALL(alloc, allocate(size)).WillOnce(Return(&mem));
|
||||
buffer2.reserve(size);
|
||||
EXPECT_CALL(alloc, deallocate(&mem, size));
|
||||
@ -372,7 +352,7 @@ TEST(MemoryBufferTest, ExceptionInDeallocate) {
|
||||
typedef AllocatorRef< MockAllocator<char> > TestAllocator;
|
||||
StrictMock< MockAllocator<char> > alloc;
|
||||
basic_memory_buffer<char, 10, TestAllocator> buffer((TestAllocator(&alloc)));
|
||||
std::size_t size = 2 * fmt::internal::INLINE_BUFFER_SIZE;
|
||||
std::size_t size = 2 * fmt::inline_buffer_size;
|
||||
std::vector<char> mem(size);
|
||||
{
|
||||
EXPECT_CALL(alloc, allocate(size)).WillOnce(Return(&mem[0]));
|
||||
@ -436,19 +416,21 @@ TEST(UtilTest, FormatArgs) {
|
||||
}
|
||||
|
||||
struct custom_context {
|
||||
using char_type = char;
|
||||
typedef char char_type;
|
||||
|
||||
template <typename T>
|
||||
struct formatter_type {
|
||||
template <typename ParseContext>
|
||||
auto parse(ParseContext &ctx) -> decltype(ctx.begin()) {
|
||||
return ctx.begin();
|
||||
}
|
||||
struct type {
|
||||
template <typename ParseContext>
|
||||
auto parse(ParseContext &ctx) -> decltype(ctx.begin()) {
|
||||
return ctx.begin();
|
||||
}
|
||||
|
||||
const char *format(const T &, custom_context& ctx) {
|
||||
ctx.called = true;
|
||||
return 0;
|
||||
}
|
||||
const char *format(const T &, custom_context& ctx) {
|
||||
ctx.called = true;
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
bool called;
|
||||
@ -476,12 +458,12 @@ bool operator==(custom_value<Char> lhs, custom_value<Char> rhs) {
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
struct MockVisitor {
|
||||
// Use a unique result type to make sure that there are no undesirable
|
||||
// conversions.
|
||||
struct Result {};
|
||||
// Use a unique result type to make sure that there are no undesirable
|
||||
// conversions.
|
||||
struct Result {};
|
||||
|
||||
template <typename T>
|
||||
struct MockVisitor: fmt::internal::function<Result> {
|
||||
MockVisitor() {
|
||||
ON_CALL(*this, visit(_)).WillByDefault(Return(Result()));
|
||||
}
|
||||
@ -523,12 +505,13 @@ VISIT_TYPE(float, double);
|
||||
#define CHECK_ARG_(Char, expected, value) { \
|
||||
testing::StrictMock<MockVisitor<decltype(expected)>> visitor; \
|
||||
EXPECT_CALL(visitor, visit(expected)); \
|
||||
using iterator = std::back_insert_iterator<basic_buffer<Char>>; \
|
||||
typedef std::back_insert_iterator<basic_buffer<Char>> iterator; \
|
||||
fmt::visit(visitor, make_arg<fmt::basic_context<iterator, Char>>(value)); \
|
||||
}
|
||||
|
||||
#define CHECK_ARG(value) { \
|
||||
typename VisitType<decltype(value)>::Type expected = value; \
|
||||
#define CHECK_ARG(value, typename_) { \
|
||||
typedef decltype(value) value_type; \
|
||||
typename_ VisitType<value_type>::Type expected = value; \
|
||||
CHECK_ARG_(char, expected, value) \
|
||||
CHECK_ARG_(wchar_t, expected, value) \
|
||||
}
|
||||
@ -554,9 +537,9 @@ typename std::enable_if<std::is_floating_point<T>::value, T>::type
|
||||
}
|
||||
|
||||
TYPED_TEST(NumericArgTest, MakeAndVisit) {
|
||||
CHECK_ARG(test_value<TypeParam>());
|
||||
CHECK_ARG(std::numeric_limits<TypeParam>::min());
|
||||
CHECK_ARG(std::numeric_limits<TypeParam>::max());
|
||||
CHECK_ARG(test_value<TypeParam>(), typename);
|
||||
CHECK_ARG(std::numeric_limits<TypeParam>::min(), typename);
|
||||
CHECK_ARG(std::numeric_limits<TypeParam>::max(), typename);
|
||||
}
|
||||
|
||||
TEST(UtilTest, CharArg) {
|
||||
@ -592,22 +575,25 @@ TEST(UtilTest, PointerArg) {
|
||||
const void *cp = 0;
|
||||
CHECK_ARG_(char, cp, p);
|
||||
CHECK_ARG_(wchar_t, cp, p);
|
||||
CHECK_ARG(cp);
|
||||
CHECK_ARG(cp, );
|
||||
}
|
||||
|
||||
TEST(UtilTest, CustomArg) {
|
||||
::Test test;
|
||||
using handle = typename fmt::basic_arg<fmt::context>::handle;
|
||||
using visitor = MockVisitor<handle>;
|
||||
testing::StrictMock<visitor> v;
|
||||
EXPECT_CALL(v, visit(_)).WillOnce(testing::Invoke([&](handle h) {
|
||||
struct check_custom {
|
||||
Result operator()(fmt::basic_arg<fmt::context>::handle h) const {
|
||||
fmt::memory_buffer buffer;
|
||||
fmt::internal::basic_buffer<char> &base = buffer;
|
||||
fmt::context ctx(std::back_inserter(base), "", fmt::format_args());
|
||||
h.format(ctx);
|
||||
EXPECT_EQ("test", std::string(buffer.data(), buffer.size()));
|
||||
return visitor::Result();
|
||||
}));
|
||||
return Result();
|
||||
}
|
||||
};
|
||||
|
||||
TEST(UtilTest, CustomArg) {
|
||||
::Test test;
|
||||
typedef MockVisitor<fmt::basic_arg<fmt::context>::handle> visitor;
|
||||
testing::StrictMock<visitor> v;
|
||||
EXPECT_CALL(v, visit(_)).WillOnce(testing::Invoke(check_custom()));
|
||||
fmt::visit(v, make_arg<fmt::context>(test));
|
||||
}
|
||||
|
||||
@ -841,15 +827,15 @@ TEST(UtilTest, ReportWindowsError) {
|
||||
enum TestEnum2 {};
|
||||
|
||||
TEST(UtilTest, ConvertToInt) {
|
||||
EXPECT_FALSE(fmt::internal::convert_to_int<char>::value);
|
||||
EXPECT_FALSE(fmt::internal::convert_to_int<const char *>::value);
|
||||
EXPECT_TRUE(fmt::internal::convert_to_int<TestEnum2>::value);
|
||||
EXPECT_FALSE((fmt::internal::convert_to_int<char, char>::value));
|
||||
EXPECT_FALSE((fmt::internal::convert_to_int<const char *, char>::value));
|
||||
EXPECT_TRUE((fmt::internal::convert_to_int<TestEnum2, char>::value));
|
||||
}
|
||||
|
||||
#if FMT_USE_ENUM_BASE
|
||||
enum TestEnum : char {TestValue};
|
||||
TEST(UtilTest, IsEnumConvertibleToInt) {
|
||||
EXPECT_TRUE(fmt::internal::convert_to_int<TestEnum>::value);
|
||||
EXPECT_TRUE((fmt::internal::convert_to_int<TestEnum, char>::value));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
32
test/util.cc
32
test/util.cc
@ -1,29 +1,9 @@
|
||||
/*
|
||||
Test utilities.
|
||||
|
||||
Copyright (c) 2012-2014, 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.
|
||||
*/
|
||||
// Formatting library for C++ - test utilities
|
||||
//
|
||||
// Copyright (c) 2012 - present, Victor Zverovich
|
||||
// All rights reserved.
|
||||
//
|
||||
// For the license information refer to format.h.
|
||||
|
||||
#include "util.h"
|
||||
#include <cstring>
|
||||
|
||||
32
test/util.h
32
test/util.h
@ -1,29 +1,9 @@
|
||||
/*
|
||||
Test utilities.
|
||||
|
||||
Copyright (c) 2012-2014, 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.
|
||||
*/
|
||||
// Formatting library for C++ - test utilities
|
||||
//
|
||||
// Copyright (c) 2012 - present, Victor Zverovich
|
||||
// All rights reserved.
|
||||
//
|
||||
// For the license information refer to format.h.
|
||||
|
||||
#include <cstdarg>
|
||||
#include <cstdio>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user