From 49a9983799f1696cfdcddc73a148c24c6612b21e Mon Sep 17 00:00:00 2001 From: Sandu Liviu Catalin Date: Sun, 22 May 2016 23:37:55 +0300 Subject: [PATCH] Update the format library to the latest version. --- cbp/Module.cbp | 2 + cbp/Sandbox.cbp | 1 + external/Common/posix.cc | 2 +- external/CppFormat/ChangeLog.rst | 335 ------------ external/CppFormat/LICENSE.rst | 2 +- external/CppFormat/README.rst | 409 --------------- external/CppFormat/format.cc | 127 ++--- external/CppFormat/ostream.cc | 61 +++ include/{ => fmt}/format.h | 639 +++++++++++++---------- include/fmt/ostream.h | 133 +++++ {external/Common => include/fmt}/posix.h | 6 +- include/fmt/stringf.h | 36 ++ include/fmt/timef.h | 64 +++ 13 files changed, 711 insertions(+), 1106 deletions(-) delete mode 100644 external/CppFormat/ChangeLog.rst delete mode 100644 external/CppFormat/README.rst create mode 100644 external/CppFormat/ostream.cc rename include/{ => fmt}/format.h (92%) create mode 100644 include/fmt/ostream.h rename {external/Common => include/fmt}/posix.h (98%) create mode 100644 include/fmt/stringf.h create mode 100644 include/fmt/timef.h diff --git a/cbp/Module.cbp b/cbp/Module.cbp index d3129f45..6d86b588 100644 --- a/cbp/Module.cbp +++ b/cbp/Module.cbp @@ -392,6 +392,7 @@ + @@ -400,6 +401,7 @@ + diff --git a/cbp/Sandbox.cbp b/cbp/Sandbox.cbp index 03159ddc..df0eac9b 100644 --- a/cbp/Sandbox.cbp +++ b/cbp/Sandbox.cbp @@ -154,6 +154,7 @@ + diff --git a/external/Common/posix.cc b/external/Common/posix.cc index c6c2ae2c..1ec746a4 100644 --- a/external/Common/posix.cc +++ b/external/Common/posix.cc @@ -1,7 +1,7 @@ /* A C++ interface to POSIX functions. - Copyright (c) 2014 - 2015, Victor Zverovich + Copyright (c) 2014 - 2016, Victor Zverovich All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/external/CppFormat/ChangeLog.rst b/external/CppFormat/ChangeLog.rst deleted file mode 100644 index 89d5af8e..00000000 --- a/external/CppFormat/ChangeLog.rst +++ /dev/null @@ -1,335 +0,0 @@ -1.1.0 - 2015-03-06 ------------------- - -* Added ``BasicArrayWriter``, a class template that provides operations for - formatting and writing data into a fixed-size array - (`#105 `_ and - `#122 `_): - - .. code:: c++ - - char buffer[100]; - fmt::ArrayWriter w(buffer); - w.write("The answer is {}", 42); - -* Added `0 A.D. `_ and `PenUltima Online (POL) - `_ to the list of notable projects using C++ Format. - -* C++ Format now uses MSVC intrinsics for better formatting performance - (`#115 `_, - `#116 `_, - `#118 `_ and - `#121 `_). - Previously these optimizations where only used on GCC and Clang. - Thanks to `@CarterLi `_ and - `@objectx `_. - -* CMake install target (`#119 `_). - Thanks to `@TrentHouliston `_. - - You can now install C++ Format with ``make install`` command. - -* Improved `Biicode `_ support - (`#98 `_ and - `#104 `_). Thanks to - `@MariadeAnton `_ and - `@franramirez688 `_. - -* Improved support for bulding with `Android NDK - `_ - (`#107 `_). - Thanks to `@newnon `_. - - The `android-ndk-example `_ - repository provides and example of using C++ Format with Android NDK: - - .. image:: https://raw.githubusercontent.com/cppformat/android-ndk-example/ - master/screenshot.png - -* Improved documentation of ``SystemError`` and ``WindowsError`` - (`#54 `_). - -* Various code improvements - (`#110 `_, - `#111 `_ - `#112 `_). - Thanks to `@CarterLi `_. - -* Improved compile-time errors when formatting wide into narrow strings - (`#117 `_). - -* Fixed ``BasicWriter::write`` without formatting arguments when C++11 support - is disabled (`#109 `_). - -* Fixed header-only build on OS X with GCC 4.9 - (`#124 `_). - -* Fixed packaging issues (`#94 `_). - -* Fixed warnings in GCC, MSVC and Xcode/Clang - (`#95 `_, - `#96 `_ and - `#114 `_). - -* Added `changelog `_ - (`#103 `_). - -1.0.0 - 2015-02-05 ------------------- - -* Add support for a header-only configuration when ``FMT_HEADER_ONLY`` is - defined before including ``format.h``: - - .. code:: c++ - - #define FMT_HEADER_ONLY - #include "format.h" - -* Compute string length in the constructor of ``BasicStringRef`` - instead of the ``size`` method - (`#79 `_). - This eliminates size computation for string literals on reasonable optimizing - compilers. - -* Fix formatting of types with overloaded ``operator <<`` for ``std::wostream`` - (`#86 `_): - - .. code:: c++ - - fmt::format(L"The date is {0}", Date(2012, 12, 9)); - -* Fix linkage of tests on Arch Linux - (`#89 `_). - -* Allow precision specifier for non-float arguments - (`#90 `_): - - .. code:: c++ - - fmt::print("{:.3}\n", "Carpet"); // prints "Car" - -* Fix build on Android NDK - (`#93 `_) - -* Improvements to documentation build procedure. - -* Remove ``FMT_SHARED`` CMake variable in favor of standard `BUILD_SHARED_LIBS - `_. - -* Fix error handling in ``fmt::fprintf``. - -* Fix a number of warnings. - -0.12.0 - 2014-10-25 -------------------- - -* [Breaking] Improved separation between formatting and buffer management. - ``Writer`` is now a base class that cannot be instantiated directly. - The new ``MemoryWriter`` class implements the default buffer management - with small allocations done on stack. So ``fmt::Writer`` should be replaced - with ``fmt::MemoryWriter`` in variable declarations. - - Old code: - - .. code:: c++ - - fmt::Writer w; - - New code: - - .. code:: c++ - - fmt::MemoryWriter w; - - If you pass ``fmt::Writer`` by reference, you can continue to do so: - - .. code:: c++ - - void f(fmt::Writer &w); - - This doesn't affect the formatting API. - -* Support for custom memory allocators - (`#69 `_) - -* Formatting functions now accept `signed char` and `unsigned char` strings as - arguments (`#73 `_): - - .. code:: c++ - - auto s = format("GLSL version: {}", glGetString(GL_VERSION)); - -* Reduced code bloat. According to the new `benchmark results - `_, - cppformat is close to ``printf`` and by the order of magnitude better than - Boost Format in terms of compiled code size. - -* Improved appearance of the documentation on mobile by using the `Sphinx - Bootstrap theme `_: - - .. |old| image:: https://cloud.githubusercontent.com/assets/576385/4792130/ - cd256436-5de3-11e4-9a62-c077d0c2b003.png - - .. |new| image:: https://cloud.githubusercontent.com/assets/576385/4792131/ - cd29896c-5de3-11e4-8f59-cac952942bf0.png - - +-------+-------+ - | Old | New | - +-------+-------+ - | |old| | |new| | - +-------+-------+ - -0.11.0 - 2014-08-21 -------------------- - -* Safe printf implementation with a POSIX extension for positional arguments: - - .. code:: c++ - - fmt::printf("Elapsed time: %.2f seconds", 1.23); - fmt::printf("%1$s, %3$d %2$s", weekday, month, day); - -* Arguments of ``char`` type can now be formatted as integers - (Issue `#55 `_): - - .. code:: c++ - - fmt::format("0x{0:02X}", 'a'); - -* Deprecated parts of the API removed. - -* The library is now built and tested on MinGW with Appveyor in addition to - existing test platforms Linux/GCC, OS X/Clang, Windows/MSVC. - -0.10.0 - 2014-07-01 -------------------- - -**Improved API** - -* All formatting methods are now implemented as variadic functions instead - of using ``operator<<`` for feeding arbitrary arguments into a temporary - formatter object. This works both with C++11 where variadic templates are - used and with older standards where variadic functions are emulated by - providing lightweight wrapper functions defined with the ``FMT_VARIADIC`` - macro. You can use this macro for defining your own portable variadic - functions: - - .. code:: c++ - - void report_error(const char *format, const fmt::ArgList &args) { - fmt::print("Error: {}"); - fmt::print(format, args); - } - FMT_VARIADIC(void, report_error, const char *) - - report_error("file not found: {}", path); - - Apart from a more natural syntax, this also improves performance as there - is no need to construct temporary formatter objects and control arguments' - lifetimes. Because the wrapper functions are very ligthweight, this doesn't - cause code bloat even in pre-C++11 mode. - -* Simplified common case of formatting an ``std::string``. Now it requires a - single function call: - - .. code:: c++ - - std::string s = format("The answer is {}.", 42); - - Previously it required 2 function calls: - - .. code:: c++ - - std::string s = str(Format("The answer is {}.") << 42); - - Instead of unsafe ``c_str`` function, ``fmt::Writer`` should be used directly - to bypass creation of ``std::string``: - - .. code:: c++ - - fmt::Writer w; - w.write("The answer is {}.", 42); - w.c_str(); // returns a C string - - This doesn't do dynamic memory allocation for small strings and is less error - prone as the lifetime of the string is the same as for ``std::string::c_str`` - which is well understood (hopefully). - -* Improved consistency in naming functions that are a part of the public API. - Now all public functions are lowercase following the standard library - conventions. Previously it was a combination of lowercase and - CapitalizedWords. - Issue `#50 `_. - -* Old functions are marked as deprecated and will be removed in the next - release. - -**Other Changes** - -* Experimental support for printf format specifications (work in progress): - - .. code:: c++ - - fmt::printf("The answer is %d.", 42); - std::string s = fmt::sprintf("Look, a %s!", "string"); - -* Support for hexadecimal floating point format specifiers ``a`` and ``A``: - - .. code:: c++ - - print("{:a}", -42.0); // Prints -0x1.5p+5 - print("{:A}", -42.0); // Prints -0X1.5P+5 - -* CMake option ``FMT_SHARED`` that specifies whether to build format as a - shared library (off by default). - -0.9.0 - 2014-05-13 ------------------- - -* More efficient implementation of variadic formatting functions. - -* ``Writer::Format`` now has a variadic overload: - - .. code:: c++ - - Writer out; - out.Format("Look, I'm {}!", "variadic"); - -* For efficiency and consistency with other overloads, variadic overload of - the ``Format`` function now returns ``Writer`` instead of ``std::string``. - Use the ``str`` function to convert it to ``std::string``: - - .. code:: c++ - - std::string s = str(Format("Look, I'm {}!", "variadic")); - -* Replaced formatter actions with output sinks: ``NoAction`` -> ``NullSink``, - ``Write`` -> ``FileSink``, ``ColorWriter`` -> ``ANSITerminalSink``. - This improves naming consistency and shouldn't affect client code unless - these classes are used directly which should be rarely needed. - -* Added ``ThrowSystemError`` function that formats a message and throws - ``SystemError`` containing the formatted message and system-specific error - description. For example, the following code - - .. code:: c++ - - FILE *f = fopen(filename, "r"); - if (!f) - ThrowSystemError(errno, "Failed to open file '{}'") << filename; - - will throw ``SystemError`` exception with description - "Failed to open file '': No such file or directory" if file - doesn't exist. - -* Support for AppVeyor continuous integration platform. - -* ``Format`` now throws ``SystemError`` in case of I/O errors. - -* Improve test infrastructure. Print functions are now tested by redirecting - the output to a pipe. - -0.8.0 - 2014-04-14 ------------------- - -* Initial release diff --git a/external/CppFormat/LICENSE.rst b/external/CppFormat/LICENSE.rst index b1c96ca0..eb6be650 100644 --- a/external/CppFormat/LICENSE.rst +++ b/external/CppFormat/LICENSE.rst @@ -1,4 +1,4 @@ -Copyright (c) 2012 - 2015, Victor Zverovich +Copyright (c) 2012 - 2016, Victor Zverovich All rights reserved. diff --git a/external/CppFormat/README.rst b/external/CppFormat/README.rst deleted file mode 100644 index 29f43348..00000000 --- a/external/CppFormat/README.rst +++ /dev/null @@ -1,409 +0,0 @@ -C++ Format -========== - -.. image:: https://travis-ci.org/cppformat/cppformat.png?branch=master - :target: https://travis-ci.org/cppformat/cppformat - -.. image:: https://ci.appveyor.com/api/projects/status/qk0bhyhqp1ekpat8 - :target: https://ci.appveyor.com/project/vitaut/cppformat - -.. image:: https://webapi.biicode.com/v1/badges/vitaut/vitaut/cppformat/master?dummy - :target: https://www.biicode.com/vitaut/cppformat - -.. image:: https://badges.gitter.im/Join%20Chat.svg - :alt: Join the chat at https://gitter.im/cppformat/cppformat - :target: https://gitter.im/cppformat/cppformat?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge - -C++ Format is an open-source formatting library for C++. -It can be used as a safe alternative to printf or as a fast -alternative to IOStreams. - -`Documentation `_ - -Features --------- - -* Two APIs: faster concatenation-based write API and slower (but still - very fast) replacement-based format API with positional arguments for - localization. -* Write API similar to the one used by IOStreams but stateless allowing - faster implementation. -* Format API with `format string syntax - `_ - similar to the one used by `str.format - `_ in Python. -* Safe `printf implementation - `_ - including the POSIX extension for positional arguments. -* Support for user-defined types. -* High speed: performance of the format API is close to that of - glibc's `printf `_ - and better than performance of IOStreams. See `Speed tests`_ and - `Fast integer to string conversion in C++ - `_. -* Small code size both in terms of source code (format consists of a single - header file and a single source file) and compiled code. - See `Compile time and code bloat`_. -* Reliability: the library has an extensive set of `unit tests - `_. -* Safety: the library is fully type safe, errors in format strings are - reported using exceptions, automatic memory management prevents buffer - overflow errors. -* Ease of use: small self-contained code base, no external dependencies, - permissive BSD `license - `_ -* `Portability `_ with consistent output - across platforms and support for older compilers. -* Clean warning-free codebase even on high warning levels - (-Wall -Wextra -pedantic). -* Support for wide strings. -* Optional header-only configuration enabled with the ``FMT_HEADER_ONLY`` macro. - -See the `documentation `_ for more details. - -Examples --------- - -This prints ``Hello, world!`` to stdout: - -.. code:: c++ - - fmt::print("Hello, {}!", "world"); // uses Python-like format string syntax - fmt::printf("Hello, %s!", "world"); // uses printf format string syntax - -Arguments can be accessed by position and arguments' indices can be repeated: - -.. code:: c++ - - std::string s = fmt::format("{0}{1}{0}", "abra", "cad"); - // s == "abracadabra" - -C++ Format can be used as a safe portable replacement for ``itoa``: - -.. code:: c++ - - fmt::MemoryWriter w; - w << 42; // replaces itoa(42, buffer, 10) - w << fmt::hex(42); // replaces itoa(42, buffer, 16) - // access the string using w.str() or w.c_str() - -An object of any user-defined type for which there is an overloaded -:code:`std::ostream` insertion operator (``operator<<``) can be formatted: - -.. code:: c++ - - class Date { - int year_, month_, day_; - public: - Date(int year, int month, int day) : year_(year), month_(month), day_(day) {} - - 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)); - // s == "The date is 2012-12-9" - -You can use the `FMT_VARIADIC -`_ -macro to create your own functions similar to `format -`_ and -`print `_ -which take arbitrary arguments: - -.. code:: c++ - - // Prints formatted error message. - void report_error(const char *format, fmt::ArgList args) { - fmt::print("Error: "); - fmt::print(format, args); - } - FMT_VARIADIC(void, report_error, const char *) - - report_error("file not found: {}", path); - -Note that you only need to define one function that takes ``fmt::ArgList`` -argument. ``FMT_VARIADIC`` automatically defines necessary wrappers that -accept variable number of arguments. - -Projects using this library ---------------------------- - -* `0 A.D. `_: A free, open-source, cross-platform real-time strategy game - -* `AMPL/MP `_: - An open-source library for mathematical programming - -* `HarpyWar/pvpgn `_: - Player vs Player Gaming Network with tweaks - -* `KBEngine `_: An open-source MMOG server engine - -* `Lifeline `_: A 2D game - -* `PenUltima Online (POL) `_: - An MMO server, compatible with most Ultima Online clients - -* `quasardb `_: A distributed, high-performance, associative database - -* `readpe `_: Read Portable Executable - -* `Saddy `_: - Small crossplatform 2D graphic engine - -* `Salesforce Analytics Cloud `_: - Business intelligence software - -* `spdlog `_: Super fast C++ logging library - -* `TrinityCore `_: Open-source MMORPG framework - -`More... `_ - -If you are aware of other projects using this library, please let me know -by `email `_ or by submitting an -`issue `_. - -Motivation ----------- - -So why yet another formatting library? - -There are plenty of methods for doing this task, from standard ones like -the printf family of function and IOStreams to Boost Format library and -FastFormat. The reason for creating a new library is that every existing -solution that I found either had serious issues or didn't provide -all the features I needed. - -Printf -~~~~~~ - -The good thing about printf is that it is pretty fast and readily available -being a part of the C standard library. The main drawback is that it -doesn't support user-defined types. Printf also has safety issues although -they are mostly solved with `__attribute__ ((format (printf, ...)) -`_ in GCC. -There is a POSIX extension that adds positional arguments required for -`i18n `_ -to printf but it is not a part of C99 and may not be available on some -platforms. - -IOStreams -~~~~~~~~~ - -The main issue with IOStreams is best illustrated with an example: - -.. code:: c++ - - std::cout << std::setprecision(2) << std::fixed << 1.23456 << "\n"; - -which is a lot of typing compared to printf: - -.. code:: c++ - - printf("%.2f\n", 1.23456); - -Matthew Wilson, the author of FastFormat, referred to this situation with -IOStreams as "chevron hell". IOStreams doesn't support positional arguments -by design. - -The good part is that IOStreams supports user-defined types and is safe -although error reporting is awkward. - -Boost Format library -~~~~~~~~~~~~~~~~~~~~ - -This is a very powerful library which supports both printf-like format -strings and positional arguments. The main its drawback is performance. -According to various benchmarks it is much slower than other methods -considered here. Boost Format also has excessive build times and severe -code bloat issues (see `Benchmarks`_). - -FastFormat -~~~~~~~~~~ - -This is an interesting library which is fast, safe and has positional -arguments. However it has significant limitations, citing its author: - - Three features that have no hope of being accommodated within the - current design are: - - * Leading zeros (or any other non-space padding) - * Octal/hexadecimal encoding - * Runtime width/alignment specification - -It is also quite big and has a heavy dependency, STLSoft, which might be -too restrictive for using it in some projects. - -Loki SafeFormat -~~~~~~~~~~~~~~~ - -SafeFormat is a formatting library which uses printf-like format strings -and is type safe. It doesn't support user-defined types or positional -arguments. It makes unconventional use of ``operator()`` for passing -format arguments. - -Tinyformat -~~~~~~~~~~ - -This library supports printf-like format strings and is very small and -fast. Unfortunately it doesn't support positional arguments and wrapping -it in C++98 is somewhat difficult. Also its performance and code compactness -are limited by IOStreams. - -Boost Spirit.Karma -~~~~~~~~~~~~~~~~~~ - -This is not really a formatting library but I decided to include it here -for completeness. As IOStreams it suffers from the problem of mixing -verbatim text with arguments. The library is pretty fast, but slower -on integer formatting than ``fmt::Writer`` on Karma's own benchmark, -see `Fast integer to string conversion in C++ -`_. - -Benchmarks ----------- - -Speed tests -~~~~~~~~~~~ - -The following speed tests results were generated by building -``tinyformat_test.cpp`` on Ubuntu GNU/Linux 14.04.1 with -``g++-4.8.2 -O3 -DSPEED_TEST -DHAVE_FORMAT``, and taking the best of three -runs. In the test, the format string ``"%0.10f:%04d:%+g:%s:%p:%c:%%\n"`` or -equivalent is filled 2000000 times with output sent to ``/dev/null``; for -further details see the `source -`_. - -================= ============= =========== -Library Method Run Time, s -================= ============= =========== -EGLIBC 2.19 printf 1.30 -libstdc++ 4.8.2 std::ostream 1.85 -C++ Format 1.0 fmt::print 1.42 -tinyformat 2.0.1 tfm::printf 2.25 -Boost Format 1.54 boost::format 9.94 -================= ============= =========== - -As you can see ``boost::format`` is much slower than the alternative methods; this -is confirmed by `other tests `_. -Tinyformat is quite good coming close to IOStreams. Unfortunately tinyformat -cannot be faster than the IOStreams because it uses them internally. -Performance of cppformat is close to that of printf, being `faster than printf on integer -formatting `_, -but slower on floating-point formatting which dominates this benchmark. - -Compile time and code bloat -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The script `bloat-test.py -`_ -from `format-benchmark `_ -tests compile time and code bloat for nontrivial projects. -It generates 100 translation units and uses ``printf()`` or its alternative -five times in each to simulate a medium sized project. The resulting -executable size and compile time (g++-4.8.1, Ubuntu GNU/Linux 13.10, -best of three) is shown in the following tables. - -**Optimized build (-O3)** - -============ =============== ==================== ================== -Method Compile Time, s Executable size, KiB Stripped size, KiB -============ =============== ==================== ================== -printf 2.6 41 30 -IOStreams 19.4 92 70 -C++ Format 46.8 46 34 -tinyformat 64.6 418 386 -Boost Format 222.8 990 923 -============ =============== ==================== ================== - -As you can see, C++ Format has two times less overhead in terms of resulting -code size compared to IOStreams and comes pretty close to ``printf``. -Boost Format has by far the largest overheads. - -**Non-optimized build** - -============ =============== ==================== ================== -Method Compile Time, s Executable size, KiB Stripped size, KiB -============ =============== ==================== ================== -printf 2.1 41 30 -IOStreams 19.7 86 62 -C++ Format 47.9 108 86 -tinyformat 27.7 234 190 -Boost Format 122.6 884 763 -============ =============== ==================== ================== - -``libc``, ``libstdc++`` and ``libformat`` are all linked as shared -libraries to compare formatting function overhead only. Boost Format -and tinyformat are header-only libraries so they don't provide any -linkage options. - -Running the tests -~~~~~~~~~~~~~~~~~ - -Please refer to `Building the library`__ for the instructions on how to build -the library and run the unit tests. - -__ http://cppformat.github.io/latest/usage.html#building-the-library - -Benchmarks reside in a separate repository, -`format-benchmarks `_, -so to run the benchmarks you first need to clone this repository and -generate Makefiles with CMake:: - - $ git clone --recursive https://github.com/cppformat/format-benchmark.git - $ cd format-benchmark - $ cmake . - -Then you can run the speed test:: - - $ make speed-test - -or the bloat test:: - - $ make bloat-test - -License -------- - -C++ Format is distributed under the BSD `license -`_. - -The `Format String Syntax -`_ -section in the documentation is based on the one from Python `string module -documentation `_ -adapted for the current library. For this reason the documentation is -distributed under the Python Software Foundation license available in -`doc/python-license.txt -`_. -It only applies if you distribute the documentation of C++ Format. - -Links ------ - -`API changes/compatibility report `_ - -Acknowledgments ---------------- - -The benchmark section of this readme file and the performance tests are taken -from the excellent `tinyformat `_ library -written by Chris Foster. Boost Format library is acknowledged transitively -since it had some influence on tinyformat. -Some ideas used in the implementation are borrowed from `Loki -`_ SafeFormat and `Diagnostic API -`_ in -`Clang `_. -Format string syntax and the documentation are based on Python's `str.format -`_. -Thanks `Doug Turnbull `_ for his valuable -comments and contribution to the design of the type-safe API and -`Gregory Czajkowski `_ for implementing binary -formatting. Thanks `Ruslan Baratov `_ for comprehensive -`comparison of integer formatting algorithms `_ -and useful comments regarding performance, `Boris Kaul `_ for -`C++ counting digits benchmark `_. -Thanks to `CarterLi `_ for contributing various -improvements to the code. diff --git a/external/CppFormat/format.cc b/external/CppFormat/format.cc index daccd68f..886cb9b6 100644 --- a/external/CppFormat/format.cc +++ b/external/CppFormat/format.cc @@ -1,7 +1,7 @@ /* Formatting library for C++ - Copyright (c) 2012 - 2015, Victor Zverovich + Copyright (c) 2012 - 2016, Victor Zverovich All rights reserved. Redistribution and use in source and binary forms, with or without @@ -60,12 +60,6 @@ using fmt::internal::Arg; # define FMT_CATCH(x) if (false) #endif -#ifdef FMT_HEADER_ONLY -# define FMT_FUNC inline -#else -# define FMT_FUNC -#endif - #ifdef _MSC_VER # pragma warning(push) # pragma warning(disable: 4127) // conditional expression is constant @@ -129,7 +123,7 @@ struct IntChecker { const char RESET_COLOR[] = "\x1b[0m"; -typedef void (*FormatFunc)(fmt::Writer &, int, fmt::StringRef); +typedef void (*FormatFunc)(Writer &, int, StringRef); // Portable thread-safe version of strerror. // Sets buffer to point to a string describing the error code. @@ -169,7 +163,7 @@ int safe_strerror( } // Handle the case when strerror_r is not available. - int handle(fmt::internal::Null<>) { + int handle(internal::Null<>) { return fallback(strerror_s(buffer_, buffer_size_, error_code_)); } @@ -181,7 +175,7 @@ int safe_strerror( } // Fallback to strerror if strerror_r and strerror_s are not available. - int fallback(fmt::internal::Null<>) { + int fallback(internal::Null<>) { errno = 0; buffer_ = strerror(error_code_); return errno; @@ -199,8 +193,8 @@ int safe_strerror( return StrError(error_code, buffer, buffer_size).run(); } -void format_error_code(fmt::Writer &out, int error_code, - fmt::StringRef message) FMT_NOEXCEPT { +void format_error_code(Writer &out, int error_code, + StringRef message) FMT_NOEXCEPT { // Report error code making sure that the output fits into // INLINE_BUFFER_SIZE to avoid dynamic memory allocation and potential // bad_alloc. @@ -209,22 +203,22 @@ void format_error_code(fmt::Writer &out, int error_code, static const char ERROR_STR[] = "error "; // Subtract 2 to account for terminating null characters in SEP and ERROR_STR. std::size_t error_code_size = sizeof(SEP) + sizeof(ERROR_STR) - 2; - typedef fmt::internal::IntTraits::MainType MainType; + typedef internal::IntTraits::MainType MainType; MainType abs_value = static_cast(error_code); if (internal::is_negative(error_code)) { abs_value = 0 - abs_value; ++error_code_size; } - error_code_size += fmt::internal::count_digits(abs_value); - if (message.size() <= fmt::internal::INLINE_BUFFER_SIZE - error_code_size) + error_code_size += internal::count_digits(abs_value); + if (message.size() <= internal::INLINE_BUFFER_SIZE - error_code_size) out << message << SEP; out << ERROR_STR << error_code; - assert(out.size() <= fmt::internal::INLINE_BUFFER_SIZE); + assert(out.size() <= internal::INLINE_BUFFER_SIZE); } -void report_error(FormatFunc func, - int error_code, fmt::StringRef message) FMT_NOEXCEPT { - fmt::MemoryWriter full_message; +void report_error(FormatFunc func, int error_code, + StringRef message) FMT_NOEXCEPT { + MemoryWriter full_message; func(full_message, error_code, message); // Use Writer::data instead of Writer::c_str to avoid potential memory // allocation. @@ -233,7 +227,7 @@ void report_error(FormatFunc func, } // IsZeroInt::visit(arg) returns true iff arg is a zero integer. -class IsZeroInt : public fmt::internal::ArgVisitor { +class IsZeroInt : public ArgVisitor { public: template bool visit_any_int(T value) { return value == 0; } @@ -241,44 +235,43 @@ class IsZeroInt : public fmt::internal::ArgVisitor { // Checks if an argument is a valid printf width specifier and sets // left alignment if it is negative. -class WidthHandler : public fmt::internal::ArgVisitor { +class WidthHandler : public ArgVisitor { private: - fmt::FormatSpec &spec_; + FormatSpec &spec_; FMT_DISALLOW_COPY_AND_ASSIGN(WidthHandler); public: - explicit WidthHandler(fmt::FormatSpec &spec) : spec_(spec) {} + explicit WidthHandler(FormatSpec &spec) : spec_(spec) {} void report_unhandled_arg() { - FMT_THROW(fmt::FormatError("width is not integer")); + FMT_THROW(FormatError("width is not integer")); } template unsigned visit_any_int(T value) { - typedef typename fmt::internal::IntTraits::MainType UnsignedType; + typedef typename internal::IntTraits::MainType UnsignedType; UnsignedType width = static_cast(value); - if (fmt::internal::is_negative(value)) { - spec_.align_ = fmt::ALIGN_LEFT; + if (internal::is_negative(value)) { + spec_.align_ = ALIGN_LEFT; width = 0 - width; } if (width > INT_MAX) - FMT_THROW(fmt::FormatError("number is too big")); + FMT_THROW(FormatError("number is too big")); return static_cast(width); } }; -class PrecisionHandler : - public fmt::internal::ArgVisitor { +class PrecisionHandler : public ArgVisitor { public: void report_unhandled_arg() { - FMT_THROW(fmt::FormatError("precision is not integer")); + FMT_THROW(FormatError("precision is not integer")); } template int visit_any_int(T value) { if (!IntChecker::is_signed>::fits_in_int(value)) - FMT_THROW(fmt::FormatError("number is too big")); + FMT_THROW(FormatError("number is too big")); return static_cast(value); } }; @@ -298,15 +291,15 @@ struct is_same { // corresponding signed or unsigned type depending on the type specifier: // 'd' and 'i' - signed, other - unsigned) template -class ArgConverter : public fmt::internal::ArgVisitor, void> { +class ArgConverter : public ArgVisitor, void> { private: - fmt::internal::Arg &arg_; + internal::Arg &arg_; wchar_t type_; FMT_DISALLOW_COPY_AND_ASSIGN(ArgConverter); public: - ArgConverter(fmt::internal::Arg &arg, wchar_t type) + ArgConverter(internal::Arg &arg, wchar_t type) : arg_(arg), type_(type) {} void visit_bool(bool value) { @@ -317,8 +310,8 @@ class ArgConverter : public fmt::internal::ArgVisitor, void> { template void visit_any_int(U value) { bool is_signed = type_ == 'd' || type_ == 'i'; - using fmt::internal::Arg; - typedef typename fmt::internal::Conditional< + using internal::Arg; + typedef typename internal::Conditional< is_same::value, U, T>::type TargetType; if (sizeof(TargetType) <= sizeof(int)) { // Extra casts are used to silence warnings. @@ -327,7 +320,7 @@ class ArgConverter : public fmt::internal::ArgVisitor, void> { arg_.int_value = static_cast(static_cast(value)); } else { arg_.type = Arg::UINT; - typedef typename fmt::internal::MakeUnsigned::Type Unsigned; + typedef typename internal::MakeUnsigned::Type Unsigned; arg_.uint_value = static_cast(static_cast(value)); } } else { @@ -336,51 +329,43 @@ class ArgConverter : public fmt::internal::ArgVisitor, void> { // glibc's printf doesn't sign extend arguments of smaller types: // std::printf("%lld", -42); // prints "4294967254" // but we don't have to do the same because it's a UB. - arg_.long_long_value = static_cast(value); + arg_.long_long_value = static_cast(value); } else { arg_.type = Arg::ULONG_LONG; arg_.ulong_long_value = - static_cast::Type>(value); + static_cast::Type>(value); } } } }; // Converts an integer argument to char for printf. -class CharConverter : public fmt::internal::ArgVisitor { +class CharConverter : public ArgVisitor { private: - fmt::internal::Arg &arg_; + internal::Arg &arg_; FMT_DISALLOW_COPY_AND_ASSIGN(CharConverter); public: - explicit CharConverter(fmt::internal::Arg &arg) : arg_(arg) {} + explicit CharConverter(internal::Arg &arg) : arg_(arg) {} template void visit_any_int(T value) { - arg_.type = Arg::CHAR; + arg_.type = internal::Arg::CHAR; arg_.int_value = static_cast(value); } }; - -// Write the content of w to os. -void write(std::ostream &os, fmt::Writer &w) { - const char *data = w.data(); - typedef internal::MakeUnsigned::Type UnsignedStreamSize; - UnsignedStreamSize size = w.size(); - UnsignedStreamSize max_size = - internal::to_unsigned((std::numeric_limits::max)()); - do { - UnsignedStreamSize n = size <= max_size ? size : max_size; - os.write(data, static_cast(n)); - data += n; - size -= n; - } while (size != 0); -} } // namespace namespace internal { +// This method is used to preserve binary compatibility with fmt 3.0. +// It can be removed in 4.0. +FMT_FUNC void format_system_error( + Writer &out, int error_code, StringRef message) FMT_NOEXCEPT { + fmt::format_system_error(out, error_code, message); +} + template class PrintfArgFormatter : public ArgFormatterBase, Char> { @@ -456,7 +441,7 @@ FMT_FUNC void fmt::SystemError::init( int err_code, CStringRef format_str, ArgList args) { error_code_ = err_code; MemoryWriter w; - internal::format_system_error(w, err_code, format(format_str, args)); + format_system_error(w, err_code, format(format_str, args)); std::runtime_error &base = *this; base = std::runtime_error(w.str()); } @@ -614,12 +599,12 @@ FMT_FUNC void fmt::internal::format_windows_error( #endif // FMT_USE_WINDOWS_H -FMT_FUNC void fmt::internal::format_system_error( +FMT_FUNC void fmt::format_system_error( fmt::Writer &out, int error_code, fmt::StringRef message) FMT_NOEXCEPT { FMT_TRY { - MemoryBuffer buffer; - buffer.resize(INLINE_BUFFER_SIZE); + internal::MemoryBuffer buffer; + buffer.resize(internal::INLINE_BUFFER_SIZE); for (;;) { char *system_message = &buffer[0]; int result = safe_strerror(error_code, system_message, buffer.size()); @@ -876,7 +861,7 @@ void fmt::internal::PrintfFormatter::format( FMT_FUNC void fmt::report_system_error( int error_code, fmt::StringRef message) FMT_NOEXCEPT { // 'fmt::' is for bcc32. - fmt::report_error(internal::format_system_error, error_code, message); + fmt::report_error(format_system_error, error_code, message); } #if FMT_USE_WINDOWS_H @@ -897,13 +882,6 @@ FMT_FUNC void fmt::print(CStringRef format_str, ArgList args) { print(stdout, format_str, args); } -FMT_FUNC void fmt::print(std::ostream &os, CStringRef format_str, - ArgList args) { - MemoryWriter w; - w.write(format_str, args); - write(os, w); -} - FMT_FUNC void fmt::print_colored(Color c, CStringRef format, ArgList args) { char escape[] = "\x1b[30m"; escape[3] = static_cast('0' + c); @@ -919,13 +897,6 @@ FMT_FUNC int fmt::fprintf(std::FILE *f, CStringRef format, ArgList args) { return std::fwrite(w.data(), 1, size, f) < size ? -1 : static_cast(size); } -FMT_FUNC int fmt::fprintf(std::ostream &os, CStringRef format, ArgList args) { - MemoryWriter w; - printf(w, format, args); - write(os, w); - return static_cast(w.size()); -} - #ifndef FMT_HEADER_ONLY template struct fmt::internal::BasicData; diff --git a/external/CppFormat/ostream.cc b/external/CppFormat/ostream.cc new file mode 100644 index 00000000..0ba30347 --- /dev/null +++ b/external/CppFormat/ostream.cc @@ -0,0 +1,61 @@ +/* + Formatting library for C++ - std::ostream support + + Copyright (c) 2012 - 2016, Victor Zverovich + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "ostream.h" + +namespace fmt { + +namespace { +// Write the content of w to os. +void write(std::ostream &os, Writer &w) { + const char *data = w.data(); + typedef internal::MakeUnsigned::Type UnsignedStreamSize; + UnsignedStreamSize size = w.size(); + UnsignedStreamSize max_size = + internal::to_unsigned((std::numeric_limits::max)()); + do { + UnsignedStreamSize n = size <= max_size ? size : max_size; + os.write(data, static_cast(n)); + data += n; + size -= n; + } while (size != 0); +} +} + +FMT_FUNC void print(std::ostream &os, CStringRef format_str, ArgList args) { + MemoryWriter w; + w.write(format_str, args); + write(os, w); +} + +FMT_FUNC int fprintf(std::ostream &os, CStringRef format, ArgList args) { + MemoryWriter w; + printf(w, format, args); + write(os, w); + return static_cast(w.size()); +} +} // namespace fmt diff --git a/include/format.h b/include/fmt/format.h similarity index 92% rename from include/format.h rename to include/fmt/format.h index 67f02f22..ab675f35 100644 --- a/include/format.h +++ b/include/fmt/format.h @@ -1,7 +1,7 @@ /* Formatting library for C++ - Copyright (c) 2012 - 2015, Victor Zverovich + Copyright (c) 2012 - 2016, Victor Zverovich All rights reserved. Redistribution and use in source and binary forms, with or without @@ -29,6 +29,7 @@ #define FMT_FORMAT_H_ #include +#include #include #include #include @@ -39,14 +40,6 @@ #include #include -#ifndef FMT_USE_IOSTREAMS -# define FMT_USE_IOSTREAMS 1 -#endif - -#if FMT_USE_IOSTREAMS -# include -#endif - #ifdef _SECURE_SCL # define FMT_SECURE_SCL _SECURE_SCL #else @@ -57,7 +50,13 @@ # include #endif -#if defined(_MSC_VER) && _MSC_VER <= 1500 +#ifdef _MSC_VER +# define FMT_MSC_VER _MSC_VER +#else +# define FMT_MSC_VER 0 +#endif + +#if FMT_MSC_VER && FMT_MSC_VER <= 1500 typedef unsigned __int32 uint32_t; typedef unsigned __int64 uint64_t; typedef __int64 intmax_t; @@ -98,7 +97,13 @@ typedef __int64 intmax_t; # define FMT_GCC_EXTENSION #endif -#if defined(__clang__) && !defined(__INTEL_COMPILER) +#if defined(__INTEL_COMPILER) +# define FMT_ICC_VERSION __INTEL_COMPILER +#elif defined(__ICL) +# define FMT_ICC_VERSION __ICL +#endif + +#if defined(__clang__) && !defined(FMT_ICC_VERSION) # pragma clang diagnostic push # pragma clang diagnostic ignored "-Wdocumentation" #endif @@ -131,7 +136,7 @@ typedef __int64 intmax_t; // since version 2013. # define FMT_USE_VARIADIC_TEMPLATES \ (FMT_HAS_FEATURE(cxx_variadic_templates) || \ - (FMT_GCC_VERSION >= 404 && FMT_HAS_GXX_CXX11) || _MSC_VER >= 1800) + (FMT_GCC_VERSION >= 404 && FMT_HAS_GXX_CXX11) || FMT_MSC_VER >= 1800) #endif #ifndef FMT_USE_RVALUE_REFERENCES @@ -142,7 +147,7 @@ typedef __int64 intmax_t; # else # define FMT_USE_RVALUE_REFERENCES \ (FMT_HAS_FEATURE(cxx_rvalue_references) || \ - (FMT_GCC_VERSION >= 403 && FMT_HAS_GXX_CXX11) || _MSC_VER >= 1600) + (FMT_GCC_VERSION >= 403 && FMT_HAS_GXX_CXX11) || FMT_MSC_VER >= 1600) # endif #endif @@ -154,7 +159,7 @@ typedef __int64 intmax_t; #if defined(__GNUC__) && !defined(__EXCEPTIONS) # define FMT_EXCEPTIONS 0 #endif -#if defined(_MSC_VER) && !_HAS_EXCEPTIONS +#if FMT_MSC_VER && !_HAS_EXCEPTIONS # define FMT_EXCEPTIONS 0 #endif #ifndef FMT_EXCEPTIONS @@ -169,7 +174,7 @@ typedef __int64 intmax_t; # endif #endif -// Define FMT_USE_NOEXCEPT to make C++ Format use noexcept (C++11 feature). +// Define FMT_USE_NOEXCEPT to make fmt use noexcept (C++11 feature). #ifndef FMT_USE_NOEXCEPT # define FMT_USE_NOEXCEPT 0 #endif @@ -178,7 +183,7 @@ typedef __int64 intmax_t; # if FMT_EXCEPTIONS # if FMT_USE_NOEXCEPT || FMT_HAS_FEATURE(cxx_noexcept) || \ (FMT_GCC_VERSION >= 408 && FMT_HAS_GXX_CXX11) || \ - _MSC_VER >= 1900 + FMT_MSC_VER >= 1900 # define FMT_NOEXCEPT noexcept # else # define FMT_NOEXCEPT throw() @@ -195,7 +200,7 @@ typedef __int64 intmax_t; #endif #if FMT_USE_DELETED_FUNCTIONS || FMT_HAS_FEATURE(cxx_deleted_functions) || \ - (FMT_GCC_VERSION >= 404 && FMT_HAS_GXX_CXX11) || _MSC_VER >= 1800 + (FMT_GCC_VERSION >= 404 && FMT_HAS_GXX_CXX11) || FMT_MSC_VER >= 1800 # define FMT_DELETED_OR_UNDEFINED = delete # define FMT_DISALLOW_COPY_AND_ASSIGN(TypeName) \ TypeName(const TypeName&) = delete; \ @@ -211,10 +216,12 @@ typedef __int64 intmax_t; // All compilers which support UDLs also support variadic templates. This // makes the fmt::literals implementation easier. However, an explicit check // for variadic templates is added here just in case. +// For Intel's compiler both it and the system gcc/msc must support UDLs. # define FMT_USE_USER_DEFINED_LITERALS \ FMT_USE_VARIADIC_TEMPLATES && FMT_USE_RVALUE_REFERENCES && \ (FMT_HAS_FEATURE(cxx_user_literals) || \ - (FMT_GCC_VERSION >= 407 && FMT_HAS_GXX_CXX11) || _MSC_VER >= 1900) + (FMT_GCC_VERSION >= 407 && FMT_HAS_GXX_CXX11) || FMT_MSC_VER >= 1900) && \ + (!defined(FMT_ICC_VERSION) || FMT_ICC_VERSION >= 1500) #endif #ifndef FMT_ASSERT @@ -234,7 +241,7 @@ typedef __int64 intmax_t; // otherwise support __builtin_clz and __builtin_clzll, so // only define FMT_BUILTIN_CLZ using the MSVC intrinsics // if the clz and clzll builtins are not available. -#if defined(_MSC_VER) && !defined(FMT_BUILTIN_CLZLL) +#if FMT_MSC_VER && !defined(FMT_BUILTIN_CLZLL) # include // _BitScanReverse, _BitScanReverse64 namespace fmt { @@ -371,18 +378,13 @@ class BasicWriter; typedef BasicWriter Writer; typedef BasicWriter WWriter; -namespace internal { template -class BasicArgFormatter; -} +class ArgFormatter; template > + typename ArgFormatter = fmt::ArgFormatter > class BasicFormatter; -template -void format(BasicFormatter &f, const Char *&format_str, const T &value); - /** \rst A string reference. It can be constructed from a C string or ``std::string``. @@ -834,6 +836,16 @@ struct FMT_API BasicData { static const char DIGITS[]; }; +#ifndef FMT_USE_EXTERN_TEMPLATES +// Clang doesn't have a feature check for extern templates so we check +// for variadic templates which were introduced in the same version. +# define FMT_USE_EXTERN_TEMPLATES (__clang__ && FMT_USE_VARIADIC_TEMPLATES) +#endif + +#if FMT_USE_EXTERN_TEMPLATES +extern template struct BasicData; +#endif + typedef BasicData<> Data; #ifdef FMT_BUILTIN_CLZLL @@ -871,9 +883,56 @@ inline unsigned count_digits(uint32_t n) { } #endif +// A functor that doesn't add a thousands separator. +struct NoThousandsSep { + template + void operator()(Char *) {} +}; + +// A functor that adds a thousands separator. +class ThousandsSep { + private: + fmt::StringRef sep_; + + // Index of a decimal digit with the least significant digit having index 0. + unsigned digit_index_; + + public: + explicit ThousandsSep(fmt::StringRef sep) : sep_(sep), digit_index_(0) {} + + template + void operator()(Char *&buffer) { + if (++digit_index_ % 3 != 0) + return; + buffer -= sep_.size(); + std::uninitialized_copy(sep_.data(), sep_.data() + sep_.size(), + internal::make_ptr(buffer, sep_.size())); + } +}; + +// Returns the thousands separator for the current locale. +// On android the lconv structure is stubbed using an empty structure. +// The test is for the size only, not for the presense of +// thousands_sep in std::lconv, because if one would add thousands_sep +// at some point, the size of structure would be at least sizeof(char*). +template= sizeof(char*))> +struct Locale { + static fmt::StringRef thousands_sep() { return ""; } +}; + +template +struct Locale { + static fmt::StringRef thousands_sep() { + return static_cast(std::localeconv())->thousands_sep; + } +}; + // Formats a decimal unsigned integer value writing into buffer. -template -inline void format_decimal(Char *buffer, UInt value, unsigned num_digits) { +// thousands_sep is a functor that is called after writing each char to +// add a thousands separator if necessary. +template +inline void format_decimal(Char *buffer, UInt value, unsigned num_digits, + ThousandsSep thousands_sep) { buffer += num_digits; while (value >= 100) { // Integer division is slow so do it for a group of two digits instead @@ -882,7 +941,9 @@ inline void format_decimal(Char *buffer, UInt value, unsigned num_digits) { unsigned index = static_cast((value % 100) * 2); value /= 100; *--buffer = Data::DIGITS[index + 1]; + thousands_sep(buffer); *--buffer = Data::DIGITS[index]; + thousands_sep(buffer); } if (value < 10) { *--buffer = static_cast('0' + value); @@ -893,6 +954,11 @@ inline void format_decimal(Char *buffer, UInt value, unsigned num_digits) { *--buffer = Data::DIGITS[index]; } +template +inline void format_decimal(Char *buffer, UInt value, unsigned num_digits) { + return format_decimal(buffer, value, num_digits, NoThousandsSep()); +} + #ifndef _WIN32 # define FMT_USE_WINDOWS_H 0 #elif !defined(FMT_USE_WINDOWS_H) @@ -940,9 +1006,6 @@ FMT_API void format_windows_error(fmt::Writer &out, int error_code, fmt::StringRef message) FMT_NOEXCEPT; #endif -FMT_API void format_system_error(fmt::Writer &out, int error_code, - fmt::StringRef message) FMT_NOEXCEPT; - // A formatting argument value. struct Value { template @@ -1013,33 +1076,16 @@ struct WCharHelper { typedef char Yes[1]; typedef char No[2]; -// These are non-members to workaround an overload resolution bug in bcc32. -Yes &convert(fmt::ULongLong); -Yes &convert(std::ostream &); -No &convert(...); - template T &get(); -struct DummyStream : std::ostream { - DummyStream(); // Suppress a bogus warning in MSVC. - // Hide all operator<< overloads from std::ostream. - void operator<<(Null<>); -}; - -No &operator<<(std::ostream &, int); +// These are non-members to workaround an overload resolution bug in bcc32. +Yes &convert(fmt::ULongLong); +No &convert(...); template struct ConvertToIntImpl { - enum { value = false }; -}; - -template -struct ConvertToIntImpl { - // Convert to int only if T doesn't have an overloaded operator<<. - enum { - value = sizeof(convert(get() << get())) == sizeof(No) - }; + enum { value = ENABLE_CONVERSION }; }; template @@ -1110,7 +1156,7 @@ class MakeValue : public Arg { // characters and strings into narrow strings as in // fmt::format("{}", L"test"); // To fix this, use a wide format string: fmt::format(L"{}", L"test"). -#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED) +#if !FMT_MSC_VER || defined(_NATIVE_WCHAR_T_DEFINED) MakeValue(typename WCharHelper::Unsupported); #endif MakeValue(typename WCharHelper::Unsupported); @@ -1269,123 +1315,6 @@ struct NamedArg : Arg { : Arg(MakeArg< BasicFormatter >(value)), name(argname) {} }; -#define FMT_DISPATCH(call) static_cast(this)->call - -// An argument visitor. -// To use ArgVisitor define a subclass that implements some or all of the -// visit methods with the same signatures as the methods in ArgVisitor, -// for example, visit_int(int). -// Specify the subclass name as the Impl template parameter. Then calling -// ArgVisitor::visit for some argument will dispatch to a visit method -// specific to the argument type. For example, if the argument type is -// double then visit_double(double) method of a subclass will be called. -// If the subclass doesn't contain a method with this signature, then -// a corresponding method of ArgVisitor will be called. -// -// Example: -// class MyArgVisitor : public ArgVisitor { -// public: -// void visit_int(int value) { print("{}", value); } -// void visit_double(double value) { print("{}", value ); } -// }; -// -// ArgVisitor uses the curiously recurring template pattern: -// http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern -template -class ArgVisitor { - public: - void report_unhandled_arg() {} - - Result visit_unhandled_arg() { - FMT_DISPATCH(report_unhandled_arg()); - return Result(); - } - - Result visit_int(int value) { - return FMT_DISPATCH(visit_any_int(value)); - } - Result visit_long_long(LongLong value) { - return FMT_DISPATCH(visit_any_int(value)); - } - Result visit_uint(unsigned value) { - return FMT_DISPATCH(visit_any_int(value)); - } - Result visit_ulong_long(ULongLong value) { - return FMT_DISPATCH(visit_any_int(value)); - } - Result visit_bool(bool value) { - return FMT_DISPATCH(visit_any_int(value)); - } - Result visit_char(int value) { - return FMT_DISPATCH(visit_any_int(value)); - } - template - Result visit_any_int(T) { - return FMT_DISPATCH(visit_unhandled_arg()); - } - - Result visit_double(double value) { - return FMT_DISPATCH(visit_any_double(value)); - } - Result visit_long_double(long double value) { - return FMT_DISPATCH(visit_any_double(value)); - } - template - Result visit_any_double(T) { - return FMT_DISPATCH(visit_unhandled_arg()); - } - - Result visit_cstring(const char *) { - return FMT_DISPATCH(visit_unhandled_arg()); - } - Result visit_string(Arg::StringValue) { - return FMT_DISPATCH(visit_unhandled_arg()); - } - Result visit_wstring(Arg::StringValue) { - return FMT_DISPATCH(visit_unhandled_arg()); - } - Result visit_pointer(const void *) { - return FMT_DISPATCH(visit_unhandled_arg()); - } - Result visit_custom(Arg::CustomValue) { - return FMT_DISPATCH(visit_unhandled_arg()); - } - - Result visit(const Arg &arg) { - switch (arg.type) { - default: - FMT_ASSERT(false, "invalid argument type"); - return Result(); - case Arg::INT: - return FMT_DISPATCH(visit_int(arg.int_value)); - case Arg::UINT: - return FMT_DISPATCH(visit_uint(arg.uint_value)); - case Arg::LONG_LONG: - return FMT_DISPATCH(visit_long_long(arg.long_long_value)); - case Arg::ULONG_LONG: - return FMT_DISPATCH(visit_ulong_long(arg.ulong_long_value)); - case Arg::BOOL: - return FMT_DISPATCH(visit_bool(arg.int_value != 0)); - case Arg::CHAR: - return FMT_DISPATCH(visit_char(arg.int_value)); - case Arg::DOUBLE: - return FMT_DISPATCH(visit_double(arg.double_value)); - case Arg::LONG_DOUBLE: - return FMT_DISPATCH(visit_long_double(arg.long_double_value)); - case Arg::CSTRING: - return FMT_DISPATCH(visit_cstring(arg.string.value)); - case Arg::STRING: - return FMT_DISPATCH(visit_string(arg.string)); - case Arg::WSTRING: - return FMT_DISPATCH(visit_wstring(arg.wstring)); - case Arg::POINTER: - return FMT_DISPATCH(visit_pointer(arg.pointer)); - case Arg::CUSTOM: - return FMT_DISPATCH(visit_custom(arg.custom)); - } - } -}; - class RuntimeError : public std::runtime_error { protected: RuntimeError() : std::runtime_error("") {} @@ -1462,6 +1391,165 @@ class ArgList { } }; +#define FMT_DISPATCH(call) static_cast(this)->call + +/** + \rst + An argument visitor based on the `curiously recurring template pattern + `_. + + To use `~fmt::ArgVisitor` define a subclass that implements some or all of the + visit methods with the same signatures as the methods in `~fmt::ArgVisitor`, + for example, `~fmt::ArgVisitor::visit_int()`. + Pass the subclass as the *Impl* template parameter. Then calling + `~fmt::ArgVisitor::visit` for some argument will dispatch to a visit method + specific to the argument type. For example, if the argument type is + ``double`` then the `~fmt::ArgVisitor::visit_double()` method of a subclass + will be called. If the subclass doesn't contain a method with this signature, + then a corresponding method of `~fmt::ArgVisitor` will be called. + + **Example**:: + + class MyArgVisitor : public fmt::ArgVisitor { + public: + void visit_int(int value) { fmt::print("{}", value); } + void visit_double(double value) { fmt::print("{}", value ); } + }; + \endrst + */ +template +class ArgVisitor { + private: + typedef internal::Arg Arg; + + public: + void report_unhandled_arg() {} + + Result visit_unhandled_arg() { + FMT_DISPATCH(report_unhandled_arg()); + return Result(); + } + + /** Visits an ``int`` argument. **/ + Result visit_int(int value) { + return FMT_DISPATCH(visit_any_int(value)); + } + + /** Visits a ``long long`` argument. **/ + Result visit_long_long(LongLong value) { + return FMT_DISPATCH(visit_any_int(value)); + } + + /** Visits an ``unsigned`` argument. **/ + Result visit_uint(unsigned value) { + return FMT_DISPATCH(visit_any_int(value)); + } + + /** Visits an ``unsigned long long`` argument. **/ + Result visit_ulong_long(ULongLong value) { + return FMT_DISPATCH(visit_any_int(value)); + } + + /** Visits a ``bool`` argument. **/ + Result visit_bool(bool value) { + return FMT_DISPATCH(visit_any_int(value)); + } + + /** Visits a ``char`` or ``wchar_t`` argument. **/ + Result visit_char(int value) { + return FMT_DISPATCH(visit_any_int(value)); + } + + /** Visits an argument of any integral type. **/ + template + Result visit_any_int(T) { + return FMT_DISPATCH(visit_unhandled_arg()); + } + + /** Visits a ``double`` argument. **/ + Result visit_double(double value) { + return FMT_DISPATCH(visit_any_double(value)); + } + + /** Visits a ``long double`` argument. **/ + Result visit_long_double(long double value) { + return FMT_DISPATCH(visit_any_double(value)); + } + + /** Visits a ``double`` or ``long double`` argument. **/ + template + Result visit_any_double(T) { + return FMT_DISPATCH(visit_unhandled_arg()); + } + + /** Visits a null-terminated C string (``const char *``) argument. **/ + Result visit_cstring(const char *) { + return FMT_DISPATCH(visit_unhandled_arg()); + } + + /** Visits a string argument. **/ + Result visit_string(Arg::StringValue) { + return FMT_DISPATCH(visit_unhandled_arg()); + } + + /** Visits a wide string argument. **/ + Result visit_wstring(Arg::StringValue) { + return FMT_DISPATCH(visit_unhandled_arg()); + } + + /** Visits a pointer argument. **/ + Result visit_pointer(const void *) { + return FMT_DISPATCH(visit_unhandled_arg()); + } + + /** Visits an argument of a custom (user-defined) type. **/ + Result visit_custom(Arg::CustomValue) { + return FMT_DISPATCH(visit_unhandled_arg()); + } + + /** + \rst + Visits an argument dispatching to the appropriate visit method based on + the argument type. For example, if the argument type is ``double`` then + the `~fmt::ArgVisitor::visit_double()` method of the *Impl* class will be + called. + \endrst + */ + Result visit(const Arg &arg) { + switch (arg.type) { + default: + FMT_ASSERT(false, "invalid argument type"); + return Result(); + case Arg::INT: + return FMT_DISPATCH(visit_int(arg.int_value)); + case Arg::UINT: + return FMT_DISPATCH(visit_uint(arg.uint_value)); + case Arg::LONG_LONG: + return FMT_DISPATCH(visit_long_long(arg.long_long_value)); + case Arg::ULONG_LONG: + return FMT_DISPATCH(visit_ulong_long(arg.ulong_long_value)); + case Arg::BOOL: + return FMT_DISPATCH(visit_bool(arg.int_value != 0)); + case Arg::CHAR: + return FMT_DISPATCH(visit_char(arg.int_value)); + case Arg::DOUBLE: + return FMT_DISPATCH(visit_double(arg.double_value)); + case Arg::LONG_DOUBLE: + return FMT_DISPATCH(visit_long_double(arg.long_double_value)); + case Arg::CSTRING: + return FMT_DISPATCH(visit_cstring(arg.string.value)); + case Arg::STRING: + return FMT_DISPATCH(visit_string(arg.string)); + case Arg::WSTRING: + return FMT_DISPATCH(visit_wstring(arg.wstring)); + case Arg::POINTER: + return FMT_DISPATCH(visit_pointer(arg.pointer)); + case Arg::CUSTOM: + return FMT_DISPATCH(visit_custom(arg.custom)); + } + } +}; + enum Alignment { ALIGN_DEFAULT, ALIGN_LEFT, ALIGN_RIGHT, ALIGN_CENTER, ALIGN_NUMERIC }; @@ -1688,7 +1776,8 @@ namespace internal { template class ArgMap { private: - typedef std::vector, internal::Arg> > MapType; + typedef std::vector< + std::pair, internal::Arg> > MapType; typedef typename MapType::value_type Pair; MapType map_; @@ -1805,24 +1894,6 @@ class ArgFormatterBase : public ArgVisitor { } }; -// An argument formatter. -template -class BasicArgFormatter : - public ArgFormatterBase, Char> { - private: - BasicFormatter &formatter_; - const Char *format_; - - public: - BasicArgFormatter(BasicFormatter &f, FormatSpec &s, const Char *fmt) - : ArgFormatterBase, Char>(f.writer(), s), - formatter_(f), format_(fmt) {} - - void visit_custom(Arg::CustomValue c) { - c.format(&formatter_, c.value, &format_); - } -}; - class FormatterBase { private: ArgList args_; @@ -1890,6 +1961,59 @@ class PrintfFormatter : private FormatterBase { }; } // namespace internal +/** + \rst + An argument formatter based on the `curiously recurring template pattern + `_. + + To use `~fmt::BasicArgFormatter` define a subclass that implements some or + all of the visit methods with the same signatures as the methods in + `~fmt::ArgVisitor`, for example, `~fmt::ArgVisitor::visit_int()`. + Pass the subclass as the *Impl* template parameter. When a formatting + function processes an argument, it will dispatch to a visit method + specific to the argument type. For example, if the argument type is + ``double`` then the `~fmt::ArgVisitor::visit_double()` method of a subclass + will be called. If the subclass doesn't contain a method with this signature, + then a corresponding method of `~fmt::BasicArgFormatter` or its superclass + will be called. + \endrst + */ +template +class BasicArgFormatter : public internal::ArgFormatterBase { + private: + BasicFormatter &formatter_; + const Char *format_; + + public: + /** + \rst + Constructs an argument formatter object. + *formatter* is a reference to the main formatter object, *spec* contains + format specifier information for standard argument types, and *fmt* points + to the part of the format string being parsed for custom argument types. + \endrst + */ + BasicArgFormatter(BasicFormatter &formatter, + FormatSpec &spec, const Char *fmt) + : internal::ArgFormatterBase(formatter.writer(), spec), + formatter_(formatter), format_(fmt) {} + + /** Formats argument of a custom (user-defined) type. */ + void visit_custom(internal::Arg::CustomValue c) { + c.format(&formatter_, c.value, &format_); + } +}; + +/** The default argument formatter. */ +template +class ArgFormatter : public BasicArgFormatter, Char> { + public: + /** Constructs an argument formatter object. */ + ArgFormatter(BasicFormatter &formatter, + FormatSpec &spec, const Char *fmt) + : BasicArgFormatter, Char>(formatter, spec, fmt) {} +}; + /** This template formats data and writes the output to a writer. */ template class BasicFormatter : private internal::FormatterBase { @@ -1972,11 +2096,15 @@ struct ArgArray { template static Value make(const T &value) { +#ifdef __clang__ Value result = MakeValue(value); // Workaround a bug in Apple LLVM version 4.2 (clang-425.0.28) of clang: - // https://github.com/cppformat/cppformat/issues/276 + // https://github.com/fmtlib/fmt/issues/276 (void)result.custom.format; return result; +#else + return MakeValue(value); +#endif } }; @@ -2014,38 +2142,6 @@ inline uint64_t make_type(FMT_GEN15(FMT_ARG_TYPE_DEFAULT)) { (t12.type << 48) | (t13.type << 52) | (t14.type << 56); } #endif - -template -class FormatBuf : public std::basic_streambuf { - private: - typedef typename std::basic_streambuf::int_type int_type; - typedef typename std::basic_streambuf::traits_type traits_type; - - Buffer &buffer_; - Char *start_; - - public: - FormatBuf(Buffer &buffer) : buffer_(buffer), start_(&buffer[0]) { - this->setp(start_, start_ + buffer_.capacity()); - } - - int_type overflow(int_type ch = traits_type::eof()) { - if (!traits_type::eq_int_type(ch, traits_type::eof())) { - size_t size = this->size(); - buffer_.resize(size); - buffer_.reserve(size * 2); - - start_ = &buffer_[0]; - start_[size] = traits_type::to_char_type(ch); - this->setp(start_+ size + 1, start_ + size * 2); - } - return ch; - } - - size_t size() const { - return to_unsigned(this->pptr() - start_); - } -}; } // namespace internal # define FMT_MAKE_TEMPLATE_ARG(n) typename T##n @@ -2164,17 +2260,10 @@ class SystemError : public internal::RuntimeError { public: /** \rst - Constructs a :class:`fmt::SystemError` object with the description - of the form - - .. parsed-literal:: - **: ** - - where ** is the formatted message and ** is - the system message corresponding to the error code. - *error_code* is a system error code as given by ``errno``. - If *error_code* is not a valid error code such as -1, the system message - may look like "Unknown error -1" and is platform-dependent. + Constructs a :class:`fmt::SystemError` object with a description + formatted with `fmt::format_system_error`. *message* and additional + arguments passed into the constructor are formatted similarly to + `fmt::format`. **Example**:: @@ -2195,6 +2284,25 @@ class SystemError : public internal::RuntimeError { int error_code() const { return error_code_; } }; +/** + \rst + Formats an error returned by an operating system or a language runtime, + for example a file opening error, and writes it to *out* in the following + form: + + .. parsed-literal:: + **: ** + + where ** is the passed message and ** is + the system message corresponding to the error code. + *error_code* is a system error code as given by ``errno``. + If *error_code* is not a valid error code such as -1, the system message + may look like "Unknown error -1" and is platform-dependent. + \endrst + */ +FMT_API void format_system_error(fmt::Writer &out, int error_code, + fmt::StringRef message) FMT_NOEXCEPT; + /** \rst This template provides operations for formatting and writing data into @@ -2482,6 +2590,8 @@ class BasicWriter { } void clear() FMT_NOEXCEPT { buffer_.clear(); } + + Buffer &buffer() FMT_NOEXCEPT { return buffer_; } }; template @@ -2627,9 +2737,8 @@ void BasicWriter::write_int(T value, Spec spec) { switch (spec.type()) { case 0: case 'd': { unsigned num_digits = internal::count_digits(abs_value); - CharPtr p = prepare_int_buffer( - num_digits, spec, prefix, prefix_size) + 1 - num_digits; - internal::format_decimal(get(p), abs_value, num_digits); + CharPtr p = prepare_int_buffer(num_digits, spec, prefix, prefix_size) + 1; + internal::format_decimal(get(p), abs_value, 0); break; } case 'x': case 'X': { @@ -2684,6 +2793,15 @@ void BasicWriter::write_int(T value, Spec spec) { } while ((n >>= 3) != 0); break; } + case 'n': { + unsigned num_digits = internal::count_digits(abs_value); + fmt::StringRef sep = internal::Locale::thousands_sep(); + unsigned size = static_cast( + num_digits + sep.size() * (num_digits - 1) / 3); + CharPtr p = prepare_int_buffer(size, spec, prefix, prefix_size) + 1; + internal::format_decimal(get(p), abs_value, 0, internal::ThousandsSep(sep)); + break; + } default: internal::report_unknown_type( spec.type(), spec.flag(CHAR_FLAG) ? "char" : "integer"); @@ -2704,7 +2822,7 @@ void BasicWriter::write_double(T value, const FormatSpec &spec) { case 'e': case 'f': case 'g': case 'a': break; case 'F': -#ifdef _MSC_VER +#if FMT_MSC_VER // MSVC's printf doesn't support 'F'. type = 'f'; #endif @@ -2797,7 +2915,7 @@ void BasicWriter::write_double(T value, const FormatSpec &spec) { Char *start = 0; for (;;) { std::size_t buffer_size = buffer_.capacity() - offset; -#ifdef _MSC_VER +#if FMT_MSC_VER // MSVC's vsnprintf_s doesn't work with zero size, so reserve // space for at least one extra character to make the size non-zero. // Note that the buffer's capacity will increase by more than 1. @@ -2964,20 +3082,6 @@ class BasicArrayWriter : public BasicWriter { typedef BasicArrayWriter ArrayWriter; typedef BasicArrayWriter WArrayWriter; -// Formats a value. -template -void format(BasicFormatter &f, const Char *&format_str, const T &value) { - internal::MemoryBuffer buffer; - - internal::FormatBuf format_buf(buffer); - std::basic_ostream output(&format_buf); - output << value; - - BasicStringRef str(&buffer[0], format_buf.size()); - typedef internal::MakeArg< BasicFormatter > MakeArg; - format_str = f.format(format_str, MakeArg(str)); -} - // Reports a system error without throwing an exception. // Can be used to report errors from destructors. FMT_API void report_system_error(int error_code, @@ -3407,32 +3511,6 @@ FMT_VARIADIC_W(std::wstring, sprintf, WCStringRef) FMT_VARIADIC(int, printf, CStringRef) FMT_VARIADIC(int, fprintf, std::FILE *, CStringRef) -#if FMT_USE_IOSTREAMS -/** - \rst - Prints formatted data to the stream *os*. - - **Example**:: - - print(cerr, "Don't {}!", "panic"); - \endrst - */ -FMT_API void print(std::ostream &os, CStringRef format_str, ArgList args); -FMT_VARIADIC(void, print, std::ostream &, CStringRef) - -/** - \rst - Prints formatted data to the stream *os*. - - **Example**:: - - fprintf(cerr, "Don't %s!", "panic"); - \endrst - */ -FMT_API int fprintf(std::ostream &os, CStringRef format_str, ArgList args); -FMT_VARIADIC(int, fprintf, std::ostream &, CStringRef) -#endif - namespace internal { template inline bool is_name_start(Char c) { @@ -3782,12 +3860,15 @@ operator"" _a(const wchar_t *s, std::size_t) { return {s}; } # pragma GCC diagnostic pop #endif -#if defined(__clang__) && !defined(__INTEL_COMPILER) +#if defined(__clang__) && !defined(FMT_ICC_VERSION) # pragma clang diagnostic pop #endif #ifdef FMT_HEADER_ONLY +# define FMT_FUNC inline # include "format.cc" +#else +# define FMT_FUNC #endif #endif // FMT_FORMAT_H_ diff --git a/include/fmt/ostream.h b/include/fmt/ostream.h new file mode 100644 index 00000000..458d31de --- /dev/null +++ b/include/fmt/ostream.h @@ -0,0 +1,133 @@ +/* + Formatting library for C++ - std::ostream support + + Copyright (c) 2012 - 2016, Victor Zverovich + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef FMT_OSTREAM_H_ +#define FMT_OSTREAM_H_ + +#include "format.h" +#include + +namespace fmt { + +namespace internal { + +template +class FormatBuf : public std::basic_streambuf { + private: + typedef typename std::basic_streambuf::int_type int_type; + typedef typename std::basic_streambuf::traits_type traits_type; + + Buffer &buffer_; + Char *start_; + + public: + FormatBuf(Buffer &buffer) : buffer_(buffer), start_(&buffer[0]) { + this->setp(start_, start_ + buffer_.capacity()); + } + + int_type overflow(int_type ch = traits_type::eof()) { + if (!traits_type::eq_int_type(ch, traits_type::eof())) { + size_t buf_size = size(); + buffer_.resize(buf_size); + buffer_.reserve(buf_size * 2); + + start_ = &buffer_[0]; + start_[buf_size] = traits_type::to_char_type(ch); + this->setp(start_+ buf_size + 1, start_ + buf_size * 2); + } + return ch; + } + + size_t size() const { + return to_unsigned(this->pptr() - start_); + } +}; + +Yes &convert(std::ostream &); + +struct DummyStream : std::ostream { + DummyStream(); // Suppress a bogus warning in MSVC. + // Hide all operator<< overloads from std::ostream. + void operator<<(Null<>); +}; + +No &operator<<(std::ostream &, int); + +template +struct ConvertToIntImpl { + // Convert to int only if T doesn't have an overloaded operator<<. + enum { + value = sizeof(convert(get() << get())) == sizeof(No) + }; +}; +} // namespace internal + +// Formats a value. +template +void format(BasicFormatter &f, + const Char *&format_str, const T &value) { + internal::MemoryBuffer buffer; + + internal::FormatBuf format_buf(buffer); + std::basic_ostream output(&format_buf); + output << value; + + BasicStringRef str(&buffer[0], format_buf.size()); + typedef internal::MakeArg< BasicFormatter > MakeArg; + format_str = f.format(format_str, MakeArg(str)); +} + +/** + \rst + Prints formatted data to the stream *os*. + + **Example**:: + + print(cerr, "Don't {}!", "panic"); + \endrst + */ +FMT_API void print(std::ostream &os, CStringRef format_str, ArgList args); +FMT_VARIADIC(void, print, std::ostream &, CStringRef) + +/** + \rst + Prints formatted data to the stream *os*. + + **Example**:: + + fprintf(cerr, "Don't %s!", "panic"); + \endrst + */ +FMT_API int fprintf(std::ostream &os, CStringRef format_str, ArgList args); +FMT_VARIADIC(int, fprintf, std::ostream &, CStringRef) +} // namespace fmt + +#ifdef FMT_HEADER_ONLY +# include "ostream.cc" +#endif + +#endif // FMT_OSTREAM_H_ diff --git a/external/Common/posix.h b/include/fmt/posix.h similarity index 98% rename from external/Common/posix.h rename to include/fmt/posix.h index bfbd3851..ab6d12e8 100644 --- a/external/Common/posix.h +++ b/include/fmt/posix.h @@ -1,7 +1,7 @@ /* A C++ interface to POSIX functions. - Copyright (c) 2014 - 2015, Victor Zverovich + Copyright (c) 2014 - 2016, Victor Zverovich All rights reserved. Redistribution and use in source and binary forms, with or without @@ -145,7 +145,7 @@ public: // A "move constructor" for moving from a temporary. BufferedFile(Proxy p) FMT_NOEXCEPT : file_(p.file) {} - // A "move constructor" for for moving from an lvalue. + // A "move constructor" for moving from an lvalue. BufferedFile(BufferedFile &f) FMT_NOEXCEPT : file_(f.file_) { f.file_ = 0; } @@ -251,7 +251,7 @@ class File { // A "move constructor" for moving from a temporary. File(Proxy p) FMT_NOEXCEPT : fd_(p.fd) {} - // A "move constructor" for for moving from an lvalue. + // A "move constructor" for moving from an lvalue. File(File &other) FMT_NOEXCEPT : fd_(other.fd_) { other.fd_ = -1; } diff --git a/include/fmt/stringf.h b/include/fmt/stringf.h new file mode 100644 index 00000000..31c7e9d9 --- /dev/null +++ b/include/fmt/stringf.h @@ -0,0 +1,36 @@ +/* + Formatting library for C++ - string utilities + + Copyright (c) 2012 - 2016, Victor Zverovich + All rights reserved. + + For the license information refer to format.h. + */ + +#ifndef FMT_STRING_H_ +#define FMT_STRING_H_ + +#include "format.h" + +namespace fmt { + +/** + \rst + Converts *value* to ``std::string`` using the default format for type *T*. + + **Example**:: + + #include "fmt/string.h" + + std::string answer = fmt::to_string(42); + \endrst + */ +template +std::string to_string(const T &value) { + fmt::MemoryWriter w; + w << value; + return w.str(); +} +} + +#endif // FMT_STRING_H_ diff --git a/include/fmt/timef.h b/include/fmt/timef.h new file mode 100644 index 00000000..863382c0 --- /dev/null +++ b/include/fmt/timef.h @@ -0,0 +1,64 @@ +/* + Formatting library for C++ - time formatting + + Copyright (c) 2012 - 2016, Victor Zverovich + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef FMT_TIME_H_ +#define FMT_TIME_H_ + +#include "fmt/format.h" +#include + +namespace fmt { +template +void format(BasicFormatter &f, + const char *&format_str, const std::tm &tm) { + if (*format_str == ':') + ++format_str; + const char *end = format_str; + while (*end && *end != '}') + ++end; + if (*end != '}') + FMT_THROW(FormatError("missing '}' in format string")); + internal::MemoryBuffer format; + format.append(format_str, end + 1); + format[format.size() - 1] = '\0'; + Buffer &buffer = f.writer().buffer(); + std::size_t start = buffer.size(); + for (;;) { + std::size_t size = buffer.capacity() - start; + std::size_t count = std::strftime(&buffer[start], size, &format[0], &tm); + if (count != 0) { + buffer.resize(start + count); + break; + } + const std::size_t MIN_GROWTH = 10; + buffer.reserve(buffer.capacity() + size > MIN_GROWTH ? size : MIN_GROWTH); + } + format_str = end + 1; +} +} + +#endif // FMT_TIME_H_