Compare commits

...

52 Commits
5.0.0 ... 5.1.0

Author SHA1 Message Date
c2ce7e4f07 Update version 2018-07-05 06:22:54 -07:00
434eb9167e Update README.rst 2018-07-04 18:07:17 -07:00
09d94162f9 Update changelog 2018-07-04 17:47:46 -07:00
e6362642cf Fix pedantic conversion warning 2018-07-04 17:45:28 -07:00
f0110e8125 Update changelog and CI 2018-07-04 17:43:07 -07:00
479ee2a8c6 Fix MSVC build, take 2 2018-07-04 14:24:07 -07:00
e928b6724c Fix MSVC 2013 build 2018-07-04 12:33:15 -07:00
ec218a3ad1 Fix redefinition warning for RESET_COLOR 2018-07-04 07:52:19 -07:00
c04fb91b03 Fix handling of user-defined types in format_to (#793) 2018-07-04 07:40:56 -07:00
323b92bffe Force linking of inline functions into the library (#795) 2018-07-03 19:10:23 -07:00
c6d9730ddb Fix sign conversion warnings (#790) 2018-06-27 14:31:20 +02:00
2e95823ef7 Move new color support to format.h and mark old as deprecated 2018-06-24 06:39:22 -07:00
ab2d88ca8e Make format_to work with basic_memory_buffer (#776) 2018-06-23 08:29:26 -07:00
3abd036c47 Fix compilation on gcc 4 2018-06-23 07:18:59 -07:00
c2f3805488 Add vformat_to_n (#769) 2018-06-23 07:03:00 -07:00
ce500635c7 Renamed enum color to colors.
Added enum colors conversion to rgb struct.
Added colors_test.cpp.

Removed print_colored.
Renamed enum colors back to color.

Removed unnecessary inline keyword.
Removed print_rgb.
2018-06-23 06:14:44 -07:00
0508bbc7ae Add wchar_t overload of format_to_n (#764) 2018-06-13 08:24:32 +02:00
c2fbadb9cf Fixed issue #779 2018-06-12 07:39:44 +02:00
47268ecd80 Fixed GCC version test 2018-06-10 20:35:38 +02:00
9ff3b6af2e Fix handling of compile-time strings when including ostream.h (#768) 2018-06-10 19:05:27 +02:00
e3707ef14b Document that file should be in wide-oriented mode for wide print 2018-06-09 09:12:49 +02:00
45fa4ee949 Merge branch 'master' of github.com:fmtlib/fmt 2018-06-08 21:43:56 +02:00
9c07b37fff Using enum class now.
Renamed from hex to color.
Changed colr names to snake case.
2018-06-08 21:40:35 +02:00
5b5886a993 Fixed line length. 2018-06-08 19:48:41 +02:00
d2bfee13e2 Added quotes for strings in ranges and tuple likes. 2018-06-08 19:48:41 +02:00
aff6e45e14 Added support for rgb color output. 2018-06-07 22:49:16 +02:00
1b8a7f8fa0 Fix postincrement in truncating and counting iterators 2018-06-07 20:20:36 +02:00
4bc26f0a7b Merge branch 'master' of github.com:fmtlib/fmt 2018-06-07 18:42:30 +02:00
fc6e0fe992 Fix FP formatting to a non-back_insert_iterator with sign & numeric alignment (#756) 2018-06-07 18:41:40 +02:00
cd5b5670ba Make is_range and is_tuple_like public API, fix #751 2018-06-06 21:49:14 +02:00
6322b47e60 Minor cleanup 2018-06-06 16:51:35 +02:00
691a7a91a1 Add more compilers to CI and increase FMT_PEDANTIC warning levels (#736)
* Add a _lot_ more warnings to FMT_PEDANTIC
Fix these warnings

* Add more compilers to CI
Fix (some) of the compiler errors with them

* Enable -Werror on CI
Increase warning level on MSVC when compiling with FMT_PEDANTIC

* Add VS 2013 and 2015 to Appveyor

* Fix Appveyor tests
Formatting

* Implement requested changes
Fix some of the MSVC warnings
Implement C++11 integer_sequence

* Reintroduce appveyor-build.py

* Remove ranges-test from tests

* Remove (some) explicit warning suppressions
Fix C++ standard setting in CI

* Remove (some) explicit warning suppressions
Fix C++ standard setting in CI

* Fix test builds with C++11

* Enable pedantic warnings on tests

* Fix warnings from edits to master

* Cleanups

* Add C++11 support to ranges.h
Re-enable ranges-test
Fix a Visual Studio error about function not returning a value in printf.h
Fix a bug in .travis.yml
2018-06-06 15:57:59 +02:00
dd1a5ef7f9 Let requests close the file 2018-06-05 16:58:02 +02:00
d5c462596b Fix formatting of more than 15 named arguments (#754) 2018-06-05 08:32:28 +02:00
47d147b65d Simplify the nvcc warning fix 2018-06-04 21:27:20 +02:00
911a75114b Fix nvcc warnings (#752) 2018-06-04 21:00:28 +02:00
94b476283c Fix docs 2018-06-04 19:56:22 +02:00
252f11f85d Fix a bogus MSVC warning about unreachable code, take 2 2018-06-04 18:17:55 +02:00
81d5663825 Fix more bogus MSVC warnings about unreachable code (#748) 2018-06-04 06:10:52 +02:00
68f0ac8271 Fix a bogus MSVC warning about unreachable code 2018-06-03 08:03:56 +02:00
b60a5c5d49 Improve floating-point formatting 2018-05-28 20:16:30 -07:00
8dc2360b11 Fix a comment 2018-05-28 17:21:39 -07:00
4e4b8570e5 Implement simple version of Grisu 2018-05-28 11:25:07 -07:00
4027557958 Fix tests on 64-bit MSVC 2018-05-27 11:38:53 -07:00
5c32aa411c Workaround a bug in MSVC 2018-05-27 11:18:27 -07:00
468c243ca8 Add a function to get cached power of 10 2018-05-27 10:57:26 -07:00
2f257b7291 Implement normalization and simplify power table 2018-05-27 08:04:30 -07:00
6a5bb6e268 Move Android.mk to support and update 2018-05-27 06:20:54 -07:00
e282d963fe Bump version 2018-05-26 09:46:59 -07:00
e2cd521b8f Fix incorrect call to on_align in '{:}=' (#750) 2018-05-26 09:23:09 -07:00
fba352a92a Don't use UDL templates on Intel C++ compiler (#742) 2018-05-26 08:07:45 -07:00
6dcc526d5b Update release script 2018-05-26 07:02:49 -07:00
45 changed files with 1551 additions and 813 deletions

View File

@ -1,10 +1,12 @@
language: cpp
dist: trusty
sudo: required # the doc target uses sudo to install dependencies
sudo: false
os: linux
git:
depth: 1
os:
- linux
- osx
env:
global:
@ -12,18 +14,81 @@ env:
a1eovNn4uol9won7ghr67eD3/59oeESN+G9bWE+ecI1V6yRseG9whniGhIpC/YfMW/Qz5I
5sxSmFjaw9bxCISNwUIrL1O5x2AmRYTnFcXk4dFsUvlZg+WeF/aKyBYCNRM8C2ndbBmtAO
o1F2EwFbiso0EmtzhAPs19ujiVxkLn4=
matrix:
- BUILD=Doc
- BUILD=Debug STANDARD=14
- BUILD=Release STANDARD=14
matrix:
exclude:
- os: osx
env: BUILD=Doc
include:
# Documentation
- env: BUILD=Doc
sudo: required
# g++ 6 on Linux with C++14
- env: COMPILER=g++-6 BUILD=Debug STANDARD=14
compiler: gcc
addons:
apt:
update: true
sources:
- ubuntu-toolchain-r-test
packages:
- g++-6
- env: COMPILER=g++-6 BUILD=Release STANDARD=14
compiler: gcc
addons:
apt:
update: true
sources:
- ubuntu-toolchain-r-test
packages:
- g++-6
# Apple clang on OS X with C++14
- env: BUILD=Debug STANDARD=14
compiler: clang
os: osx
- env: BUILD=Release STANDARD=14
compiler: clang
os: osx
# clang 6.0 on Linux with C++14
- env: COMPILER=clang++-6.0 BUILD=Debug STANDARD=14
compiler: clang
addons:
apt:
update: true
packages:
- clang-6.0
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-trusty
- llvm-toolchain-trusty-6.0
# clang 4.0 on Linux with C++14
- env: COMPILER=clang++-4.0 BUILD=Debug STANDARD=11
compiler: clang
addons:
apt:
update: true
packages:
- clang-4.0
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-trusty
- llvm-toolchain-trusty-4.0
# g++ 4.8 on Linux with C++11
- env: COMPILER=g++-4.8 BUILD=Debug STANDARD=11
compiler: gcc
# g++ 4.4 on Linux with C++11
- env: COMPILER=g++-4.4 BUILD=Debug STANDARD=11
compiler: gcc
addons:
apt:
update: true
packages:
- g++-4.4
sources:
- ubuntu-toolchain-r-test
# Android
- language: android
android:
addons:
apt:
update: true
components:
- tools
- platform-tools
@ -51,17 +116,14 @@ matrix:
after_success:
- cd ${TRAVIS_BUILD_DIR}
- tree ./libs
allow_failures:
# Errors
- env: COMPILER=g++-4.4 BUILD=Debug STANDARD=11
compiler: gcc
# Install gcc-6 for extended constexpr support.
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-6
before_install:
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then export CXX=g++-6; fi
before_script:
- if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then export CXX=${COMPILER}; fi
- if [[ "${BUILD}" != "Doc" ]]; then ${CXX} --version; fi
script:
- support/travis-build.py

View File

@ -1,6 +1,6 @@
message(STATUS "CMake version: ${CMAKE_VERSION}")
cmake_minimum_required(VERSION 2.8.12)
cmake_minimum_required(VERSION 3.1.0)
# Determine if fmt is built as a subproject (using add_subdirectory)
# or if it is the master project.
@ -28,12 +28,12 @@ if (NOT CMAKE_BUILD_TYPE)
endif ()
option(FMT_PEDANTIC "Enable extra warnings and expensive tests." OFF)
option(FMT_WERROR "Halt the compilation with an error on compiler warnings." OFF)
# Options that control generation of various targets.
option(FMT_DOC "Generate the doc target." ${MASTER_PROJECT})
option(FMT_INSTALL "Generate the install target." ${MASTER_PROJECT})
option(FMT_TEST "Generate the test target." ${MASTER_PROJECT})
option(FMT_USE_CPP14 "Enable the addition of C++14 compiler flags." ON)
project(FMT)
@ -58,9 +58,62 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH}
"${CMAKE_CURRENT_SOURCE_DIR}/support/cmake")
include(cxx14)
include(CheckCXXCompilerFlag)
if (CMAKE_COMPILER_IS_GNUCXX OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang"))
set(PEDANTIC_COMPILE_FLAGS -Wall -Wextra -Wshadow -pedantic)
if (CMAKE_CXX_COMPILER_ID MATCHES "GNU")
set(PEDANTIC_COMPILE_FLAGS -pedantic-errors -Wall -Wextra -pedantic
-Wold-style-cast -Wfloat-equal -Wlogical-op -Wundef
-Wredundant-decls -Wshadow -Wwrite-strings -Wpointer-arith
-Wcast-qual -Wformat=2 -Wmissing-include-dirs
-Wcast-align -Wnon-virtual-dtor
-Wctor-dtor-privacy -Wdisabled-optimization
-Winvalid-pch -Wmissing-declarations -Woverloaded-virtual
-Wno-ctor-dtor-privacy -Wno-dangling-else -Wno-float-equal
-Wno-format-nonliteral -Wno-sign-conversion -Wno-shadow)
if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.6)
set(PEDANTIC_COMPILE_FLAGS ${PEDANTIC_COMPILE_FLAGS} -Wnoexcept)
endif ()
if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.0)
set(PEDANTIC_COMPILE_FLAGS ${PEDANTIC_COMPILE_FLAGS} -Wdouble-promotion
-Wtrampolines -Wzero-as-null-pointer-constant -Wuseless-cast
-Wvector-operation-performance -Wsized-deallocation)
endif ()
if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 6.0)
set(PEDANTIC_COMPILE_FLAGS ${PEDANTIC_COMPILE_FLAGS} -Wshift-overflow=2
-Wnull-dereference -Wduplicated-cond)
endif ()
set(WERROR_FLAG -Werror)
endif ()
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
set(PEDANTIC_COMPILE_FLAGS -Weverything -Wpedantic
-Wno-weak-vtables -Wno-padded -Wno-gnu-statement-expression
-Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-reserved-id-macro
-Wno-global-constructors -Wno-disabled-macro-expansion
-Wno-switch-enum -Wno-documentation-unknown-command
-Wno-gnu-string-literal-operator-template -Wno-unused-member-function
-Wno-format-nonliteral -Wno-missing-noreturn -Wno-undefined-func-template
-Wno-shadow -Wno-sign-conversion -Wno-used-but-marked-unused
-Wno-covered-switch-default -Wno-missing-variable-declarations
-Wno-double-promotion)
set(WERROR_FLAG -Werror)
check_cxx_compiler_flag(-Wno-zero-as-null-pointer-constant HAS_NULLPTR_WARNING)
if (HAS_NULLPTR_WARNING)
set(PEDANTIC_COMPILE_FLAGS ${PEDANTIC_COMPILE_FLAGS} -Wno-zero-as-null-pointer-constant)
endif ()
check_cxx_compiler_flag(-Wno-gnu-string-literal-operator-template HAS_GNU_UDL_WARNING)
if (HAS_GNU_UDL_WARNING)
set(PEDANTIC_COMPILE_FLAGS ${PEDANTIC_COMPILE_FLAGS} -Wno-gnu-string-literal-operator-template)
endif ()
endif ()
if (MSVC)
set(PEDANTIC_COMPILE_FLAGS /W3)
set(WERROR_FLAG /WX)
endif ()
if (MASTER_PROJECT AND CMAKE_GENERATOR MATCHES "Visual Studio")
@ -106,9 +159,9 @@ endif ()
add_library(fmt ${FMT_SOURCES} ${FMT_HEADERS} README.rst ChangeLog.rst)
add_library(fmt::fmt ALIAS fmt)
# Starting with CMake 3.1 the CXX_STANDARD property can be used instead.
# Don't export -std since it may break projects that use other standards.
target_compile_options(fmt PRIVATE ${CPP14_FLAG})
if (FMT_WERROR)
target_compile_options(fmt PRIVATE ${WERROR_FLAG})
endif ()
if (FMT_PEDANTIC)
target_compile_options(fmt PRIVATE ${PEDANTIC_COMPILE_FLAGS})
endif ()
@ -130,17 +183,14 @@ if (BUILD_SHARED_LIBS)
target_compile_definitions(fmt PRIVATE FMT_EXPORT INTERFACE FMT_SHARED)
endif ()
# Additionally define a header-only library when CMake is new enough.
if (CMAKE_VERSION VERSION_GREATER 3.1.0 OR CMAKE_VERSION VERSION_EQUAL 3.1.0)
add_library(fmt-header-only INTERFACE)
add_library(fmt::fmt-header-only ALIAS fmt-header-only)
add_library(fmt-header-only INTERFACE)
add_library(fmt::fmt-header-only ALIAS fmt-header-only)
target_compile_definitions(fmt-header-only INTERFACE FMT_HEADER_ONLY=1)
target_compile_definitions(fmt-header-only INTERFACE FMT_HEADER_ONLY=1)
target_include_directories(fmt-header-only INTERFACE
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>)
endif ()
target_include_directories(fmt-header-only INTERFACE
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>)
# Install targets.
if (FMT_INSTALL)

View File

@ -1,3 +1,86 @@
5.1.0 - 2018-07-05
------------------
* Added experimental support for RGB color output enabled with
the ``FMT_EXTENDED_COLORS`` macro:
.. code:: c++
#define FMT_EXTENDED_COLORS
#define FMT_HEADER_ONLY // or compile fmt with FMT_EXTENDED_COLORS defined
#include <fmt/format.h>
fmt::print(fmt::color::steel_blue, "Some beautiful text");
The old API (the ``print_colored`` and ``vprint_colored`` functions and the
``color`` enum) is now deprecated.
(`#762 <https://github.com/fmtlib/fmt/issues/762>`_
`#767 <https://github.com/fmtlib/fmt/pull/767>`_).
Thanks `@Remotion (Remo) <https://github.com/Remotion>`_.
* Added quotes to strings in ranges and tuples
(`#766 <https://github.com/fmtlib/fmt/pull/766>`_).
Thanks `@Remotion (Remo) <https://github.com/Remotion>`_.
* Made ``format_to`` work with ``basic_memory_buffer``
(`#776 <https://github.com/fmtlib/fmt/issues/776>`_).
* Added ``vformat_to_n`` and ``wchar_t`` overload of ``format_to_n``
(`#764 <https://github.com/fmtlib/fmt/issues/764>`_,
`#769 <https://github.com/fmtlib/fmt/issues/769>`_).
* Made ``is_range`` and ``is_tuple_like`` part of public (experimental) API
to allow specialization for user-defined types
(`#751 <https://github.com/fmtlib/fmt/issues/751>`_,
`#759 <https://github.com/fmtlib/fmt/pull/759>`_).
Thanks `@drrlvn (Dror Levin) <https://github.com/drrlvn>`_.
* Added more compilers to continuous integration and increased ``FMT_PEDANTIC``
warning levels
(`#736 <https://github.com/fmtlib/fmt/pull/736>`_).
Thanks `@eliaskosunen (Elias Kosunen) <https://github.com/eliaskosunen>`_.
* Fixed compilation with MSVC 2013.
* Fixed handling of user-defined types in ``format_to``
(`#793 <https://github.com/fmtlib/fmt/issues/793>`_).
* Forced linking of inline ``vformat`` functions into the library
(`#795 <https://github.com/fmtlib/fmt/issues/795>`_).
* Fixed incorrect call to on_align in ``'{:}='``
(`#750 <https://github.com/fmtlib/fmt/issues/750>`_).
* Fixed floating-point formatting to a non-back_insert_iterator with sign &
numeric alignment specified
(`#756 <https://github.com/fmtlib/fmt/issues/756>`_).
* Fixed formatting to an array with ``format_to_n``
(`#778 <https://github.com/fmtlib/fmt/issues/778>`_).
* Fixed formatting of more than 15 named arguments
(`#754 <https://github.com/fmtlib/fmt/issues/754>`_).
* Fixed handling of compile-time strings when including ``fmt/ostream.h``.
(`#768 <https://github.com/fmtlib/fmt/issues/768>`_).
* Fixed various compiler warnings and errors
(`#742 <https://github.com/fmtlib/fmt/issues/742>`_,
`#748 <https://github.com/fmtlib/fmt/issues/748>`_,
`#752 <https://github.com/fmtlib/fmt/issues/752>`_,
`#770 <https://github.com/fmtlib/fmt/issues/770>`_,
`#775 <https://github.com/fmtlib/fmt/pull/775>`_,
`#779 <https://github.com/fmtlib/fmt/issues/779>`_,
`#780 <https://github.com/fmtlib/fmt/pull/780>`_,
`#790 <https://github.com/fmtlib/fmt/pull/790>`_,
`#792 <https://github.com/fmtlib/fmt/pull/792>`_,
`#800 <https://github.com/fmtlib/fmt/pull/800>`_).
Thanks `@Remotion (Remo) <https://github.com/Remotion>`_,
`@gabime (Gabi Melman) <https://github.com/gabime>`_,
`@foonathan (Jonathan Müller) <https://github.com/foonathan>`_,
`@Dark-Passenger (Dhruv Paranjape) <https://github.com/Dark-Passenger>`_, and
`@0x8000-0000 (Sign Bit) <https://github.com/0x8000-0000>`_.
5.0.0 - 2018-05-21
------------------
@ -134,8 +217,8 @@
vreport_error(format, fmt::make_format_args(args...));
}
* Added the ``make_printf_args`` function for capturing ``printf`` arguments (
`#687 <https://github.com/fmtlib/fmt/issues/687>`_,
* Added the ``make_printf_args`` function for capturing ``printf`` arguments
(`#687 <https://github.com/fmtlib/fmt/issues/687>`_,
`#694 <https://github.com/fmtlib/fmt/pull/694>`_).
Thanks `@Kronuz (Germán Méndez Bravo) <https://github.com/Kronuz>`_.
@ -207,8 +290,8 @@
* Disallowed formatting of multibyte strings into a wide character target
(`#606 <https://github.com/fmtlib/fmt/pull/606>`_).
* Improved documentation (
`#515 <https://github.com/fmtlib/fmt/pull/515>`_,
* Improved documentation
(`#515 <https://github.com/fmtlib/fmt/pull/515>`_,
`#614 <https://github.com/fmtlib/fmt/issues/614>`_,
`#617 <https://github.com/fmtlib/fmt/pull/617>`_,
`#661 <https://github.com/fmtlib/fmt/pull/661>`_,
@ -257,8 +340,8 @@
(`#626 <https://github.com/fmtlib/fmt/pull/626>`_).
Thanks `@aroig (Abdó Roig-Maranges) <https://github.com/aroig>`_.
* Fixed various compiler warnings (
`#640 <https://github.com/fmtlib/fmt/pull/640>`_,
* Fixed various compiler warnings
(`#640 <https://github.com/fmtlib/fmt/pull/640>`_,
`#656 <https://github.com/fmtlib/fmt/pull/656>`_,
`#679 <https://github.com/fmtlib/fmt/pull/679>`_,
`#681 <https://github.com/fmtlib/fmt/pull/681>`_,
@ -1184,8 +1267,8 @@ Fixes
`@Jopie64 (Johan) <https://github.com/Jopie64>`_.
* Fixed portability issues (mostly causing test failures) on ARM, ppc64, ppc64le,
s390x and SunOS 5.11 i386 (
`#138 <https://github.com/fmtlib/fmt/issues/138>`_,
s390x and SunOS 5.11 i386
(`#138 <https://github.com/fmtlib/fmt/issues/138>`_,
`#179 <https://github.com/fmtlib/fmt/issues/179>`_,
`#180 <https://github.com/fmtlib/fmt/issues/180>`_,
`#202 <https://github.com/fmtlib/fmt/issues/202>`_,

View File

@ -81,19 +81,19 @@ Format strings can be checked at compile time:
// test.cc
#include <fmt/format.h>
std::string s = fmt::format(fmt("{2}"), 42);
std::string s = format(fmt("{2}"), 42);
.. code::
$ g++ -Iinclude test.cc -std=c++14
$ c++ -Iinclude -std=c++14 test.cc
...
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
test.cc:3:17: note: in instantiation of function template specialization 'fmt::v5::format<S, int>' requested here
std::string s = format(fmt("{2}"), 42);
^
include/fmt/core.h:778: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])'
include/fmt/format.h:2226:16: note: in call to '&checker.context_->on_error(&"argument index out of range"[0])'
context_.on_error("argument index out of range");
^

View File

@ -49,6 +49,9 @@ arguments in the resulting string.
.. doxygenfunction:: print(std::FILE *, string_view, const Args&...)
.. doxygenfunction:: vprint(std::FILE *, string_view, format_args)
.. doxygenfunction:: print(std::FILE *, wstring_view, const Args&...)
.. doxygenfunction:: vprint(std::FILE *, wstring_view, wformat_args)
Named arguments
---------------

View File

@ -6,7 +6,7 @@ import errno, os, shutil, sys, tempfile
from subprocess import check_call, check_output, CalledProcessError, Popen, PIPE
from distutils.version import LooseVersion
versions = ['1.0.0', '1.1.0', '2.0.0', '3.0.2', '4.0.0', '4.1.0', '5.0.0']
versions = ['1.0.0', '1.1.0', '2.0.0', '3.0.2', '4.0.0', '4.1.0', '5.0.0', '5.1.0']
def pip_install(package, commit=None, **kwargs):
"Install package using pip."
@ -56,7 +56,7 @@ def create_build_env(dirname='virtualenv'):
pip_install('sphinx-doc/sphinx', '12b83372ac9316e8cbe86e7fed889296a4cc29ee',
min_version='1.4.1.dev20160531')
pip_install('michaeljones/breathe',
'6b1c5bb7a1866f15fc328b8716258354b10c1daa',
'129222318f7c8f865d2631e7da7b033567e7f56a',
min_version='4.2.0')
def build_docs(version='dev', **kwargs):

View File

@ -16,7 +16,7 @@
#include <type_traits>
// The fmt library version in the form major * 10000 + minor * 100 + patch.
#define FMT_VERSION 50000
#define FMT_VERSION 50100
#ifdef __has_feature
# define FMT_HAS_FEATURE(x) __has_feature(x)
@ -30,6 +30,12 @@
# define FMT_HAS_INCLUDE(x) 0
#endif
#ifdef __has_cpp_attribute
# define FMT_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x)
#else
# define FMT_HAS_CPP_ATTRIBUTE(x) 0
#endif
#if defined(__GNUC__) && !defined(__clang__)
# define FMT_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
#else
@ -95,6 +101,12 @@
# define FMT_USE_NULLPTR 0
#endif
#if FMT_HAS_CPP_ATTRIBUTE(noreturn)
# define FMT_NORETURN [[noreturn]]
#else
# define FMT_NORETURN
#endif
// Check if exceptions are disabled.
#if defined(__GNUC__) && !defined(__EXCEPTIONS)
# define FMT_EXCEPTIONS 0
@ -187,10 +199,19 @@
FMT_BEGIN_NAMESPACE
// An implementation of declval for pre-C++11 compilers such as gcc 4.
namespace internal {
// An implementation of declval for pre-C++11 compilers such as gcc 4.
template <typename T>
typename std::add_rvalue_reference<T>::type declval() FMT_NOEXCEPT;
// Casts nonnegative integer to unsigned.
template <typename Int>
FMT_CONSTEXPR typename std::make_unsigned<Int>::type to_unsigned(Int value) {
FMT_ASSERT(value >= 0, "negative value");
return static_cast<typename std::make_unsigned<Int>::type>(value);
}
}
/**
@ -218,15 +239,15 @@ class basic_string_view {
#else
struct type {
const char *data() const { return FMT_NULL; }
size_t size() const { return 0; };
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
: data_(s), size_(size) {}
FMT_CONSTEXPR basic_string_view(const Char *s, size_t count) FMT_NOEXCEPT
: data_(s), size_(count) {}
/**
\rst
@ -262,8 +283,8 @@ class basic_string_view {
// Lexicographically compare this string reference to other.
int compare(basic_string_view other) const {
size_t size = size_ < other.size_ ? size_ : other.size_;
int result = std::char_traits<Char>::compare(data_, other.data_, size);
size_t str_size = size_ < other.size_ ? size_ : other.size_;
int result = std::char_traits<Char>::compare(data_, other.data_, str_size);
if (result == 0)
result = size_ == other.size_ ? 0 : (size_ < other.size_ ? -1 : 1);
return result;
@ -315,13 +336,13 @@ class basic_buffer {
std::size_t capacity_;
protected:
basic_buffer(T *p = FMT_NULL, std::size_t size = 0, std::size_t capacity = 0)
FMT_NOEXCEPT: ptr_(p), size_(size), capacity_(capacity) {}
basic_buffer(T *p = FMT_NULL, std::size_t sz = 0, std::size_t cap = 0)
FMT_NOEXCEPT: ptr_(p), size_(sz), capacity_(cap) {}
/** Sets the buffer data and capacity. */
void set(T *data, std::size_t capacity) FMT_NOEXCEPT {
ptr_ = data;
capacity_ = capacity;
void set(T *buf_data, std::size_t buf_capacity) FMT_NOEXCEPT {
ptr_ = buf_data;
capacity_ = buf_capacity;
}
/** Increases the buffer capacity to hold at least *capacity* elements. */
@ -357,9 +378,9 @@ class basic_buffer {
}
/** Reserves space to store at least *capacity* elements. */
void reserve(std::size_t capacity) {
if (capacity > capacity_)
grow(capacity);
void reserve(std::size_t new_capacity) {
if (new_capacity > capacity_)
grow(new_capacity);
}
void push_back(const T &value) {
@ -428,7 +449,7 @@ template <typename T, typename Char>
struct is_named_arg<named_arg<T, Char>> : std::true_type {};
enum type {
none_type, name_arg_type,
none_type, named_arg_type,
// Integer types should go first,
int_type, uint_type, long_long_type, ulong_long_type, bool_type, char_type,
last_integer_type = char_type,
@ -438,12 +459,12 @@ enum type {
};
FMT_CONSTEXPR bool is_integral(type t) {
FMT_ASSERT(t != internal::name_arg_type, "invalid argument type");
FMT_ASSERT(t != internal::named_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::name_arg_type, "invalid argument type");
FMT_ASSERT(t != internal::named_arg_type, "invalid argument type");
return t > internal::none_type && t <= internal::last_numeric_type;
}
@ -550,11 +571,17 @@ FMT_CONSTEXPR basic_format_arg<Context> make_arg(const T &value);
return static_cast<ValueType>(val); \
}
#define FMT_MAKE_VALUE_SAME(TAG, Type) \
template <typename C> \
FMT_CONSTEXPR typed_value<C, TAG> make_value(Type val) { \
return val; \
}
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)
FMT_MAKE_VALUE_SAME(int_type, int)
FMT_MAKE_VALUE_SAME(uint_type, 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.
@ -568,8 +595,8 @@ FMT_MAKE_VALUE(
(sizeof(unsigned long) == sizeof(unsigned) ? uint_type : ulong_long_type),
unsigned long, ulong_type)
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_SAME(long_long_type, long long)
FMT_MAKE_VALUE_SAME(ulong_long_type, 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)
@ -583,8 +610,8 @@ inline typed_value<C, char_type> make_value(wchar_t val) {
#endif
FMT_MAKE_VALUE(double_type, float, double)
FMT_MAKE_VALUE(double_type, double, double)
FMT_MAKE_VALUE(long_double_type, long double, long double)
FMT_MAKE_VALUE_SAME(double_type, double)
FMT_MAKE_VALUE_SAME(long_double_type, 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).
@ -594,18 +621,17 @@ FMT_MAKE_VALUE(cstring_type, const typename C::char_type*,
const typename C::char_type*)
FMT_MAKE_VALUE(cstring_type, signed char*, const signed char*)
FMT_MAKE_VALUE(cstring_type, const signed char*, const signed char*)
FMT_MAKE_VALUE_SAME(cstring_type, 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_SAME(cstring_type, const unsigned char*)
FMT_MAKE_VALUE_SAME(string_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*)
FMT_MAKE_VALUE_SAME(pointer_type, const void*)
#if FMT_USE_NULLPTR
FMT_MAKE_VALUE(pointer_type, std::nullptr_t, const void*)
@ -637,7 +663,7 @@ inline typename std::enable_if<
make_value(const T &val) { return val; }
template <typename C, typename T>
typed_value<C, name_arg_type>
typed_value<C, named_arg_type>
make_value(const named_arg<T, typename C::char_type> &val) {
basic_format_arg<C> arg = make_arg<C>(val.value);
std::memcpy(val.data, &arg, sizeof(arg));
@ -732,7 +758,7 @@ class basic_parse_context : private ErrorHandler {
// Advances the begin iterator to ``it``.
FMT_CONSTEXPR void advance_to(iterator it) {
format_str_.remove_prefix(it - begin());
format_str_.remove_prefix(internal::to_unsigned(it - begin()));
}
// Returns the next argument index.
@ -788,7 +814,7 @@ class arg_map {
basic_format_arg<Context> find(basic_string_view<char_type> name) const {
// The list is unsorted, so just return the first matching name.
for (auto it = map_, end = map_ + size_; it != end; ++it) {
for (entry *it = map_, *end = map_ + size_; it != end; ++it) {
if (it->name == name)
return it->arg;
}
@ -811,8 +837,8 @@ class context_base {
typedef basic_format_arg<Context> format_arg;
context_base(OutputIt out, basic_string_view<char_type> format_str,
basic_format_args<Context> args)
: parse_context_(format_str), out_(out), args_(args) {}
basic_format_args<Context> ctx_args)
: parse_context_(format_str), out_(out), args_(ctx_args) {}
// Returns the argument with specified index.
format_arg do_get_arg(unsigned arg_id) {
@ -892,8 +918,8 @@ class basic_format_context :
stored in the object so make sure they have appropriate lifetimes.
*/
basic_format_context(OutputIt out, basic_string_view<char_type> format_str,
basic_format_args<basic_format_context> args)
: base(out, format_str, args) {}
basic_format_args<basic_format_context> ctx_args)
: base(out, format_str, ctx_args) {}
format_arg next_arg() {
return this->do_get_arg(this->parse_context().next_arg_id());
@ -922,10 +948,10 @@ struct get_type {
};
template <typename Context>
FMT_CONSTEXPR uint64_t get_types() { return 0; }
FMT_CONSTEXPR unsigned long long get_types() { return 0; }
template <typename Context, typename Arg, typename... Args>
FMT_CONSTEXPR uint64_t get_types() {
FMT_CONSTEXPR unsigned long long get_types() {
return get_type<Context, Arg>::value | (get_types<Context, Args...>() << 4);
}
@ -969,26 +995,32 @@ class format_arg_store {
internal::value<Context>, basic_format_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)];
static const size_t DATA_SIZE =
NUM_ARGS + (IS_PACKED && NUM_ARGS != 0 ? 0 : 1);
value_type data_[DATA_SIZE];
friend class basic_format_args<Context>;
static FMT_CONSTEXPR uint64_t get_types() {
return IS_PACKED ? internal::get_types<Context, Args...>()
: -static_cast<int64_t>(NUM_ARGS);
static FMT_CONSTEXPR long long get_types() {
return IS_PACKED ?
static_cast<long long>(internal::get_types<Context, Args...>()) :
-static_cast<long long>(NUM_ARGS);
}
public:
#if FMT_USE_CONSTEXPR
static constexpr uint64_t TYPES = get_types();
static constexpr long long TYPES = get_types();
#else
static const uint64_t TYPES;
static const long long TYPES;
#endif
#if FMT_GCC_VERSION && FMT_GCC_VERSION <= 405
// Workaround an array initialization bug in gcc 4.5 and earlier.
#if (FMT_GCC_VERSION && FMT_GCC_VERSION <= 405) || \
(FMT_MSC_VER && FMT_MSC_VER <= 1800)
// Workaround array initialization issues in gcc <= 4.5 and MSVC <= 2013.
format_arg_store(const Args &... args) {
data_ = {internal::make_arg<IS_PACKED, Context>(args)...};
value_type init[DATA_SIZE] =
{internal::make_arg<IS_PACKED, Context>(args)...};
std::memcpy(data_, init, sizeof(init));
}
#else
format_arg_store(const Args &... args)
@ -998,7 +1030,7 @@ class format_arg_store {
#if !FMT_USE_CONSTEXPR
template <typename Context, typename ...Args>
const uint64_t format_arg_store<Context, Args...>::TYPES = get_types();
const long long format_arg_store<Context, Args...>::TYPES = get_types();
#endif
/**
@ -1030,7 +1062,7 @@ class basic_format_args {
private:
// To reduce compiled code size per formatting function call, types of first
// max_packed_args arguments are passed in the types_ field.
uint64_t types_;
unsigned long long types_;
union {
// If the number of arguments is less than max_packed_args, the argument
// values are stored in values_, otherwise they are stored in args_.
@ -1043,7 +1075,7 @@ class basic_format_args {
typename internal::type type(unsigned index) const {
unsigned shift = index * 4;
uint64_t mask = 0xf;
unsigned long long mask = 0xf;
return static_cast<typename internal::type>(
(types_ & (mask << shift)) >> shift);
}
@ -1054,9 +1086,9 @@ class basic_format_args {
void set_data(const format_arg *args) { args_ = args; }
format_arg do_get(size_type index) const {
int64_t signed_types = static_cast<int64_t>(types_);
long long signed_types = static_cast<long long>(types_);
if (signed_types < 0) {
uint64_t num_args = -signed_types;
unsigned long long num_args = static_cast<unsigned long long>(-signed_types);
return index < num_args ? args_[index] : format_arg();
}
format_arg arg;
@ -1080,22 +1112,22 @@ class basic_format_args {
*/
template <typename... Args>
basic_format_args(const format_arg_store<Context, Args...> &store)
: types_(store.TYPES) {
: types_(static_cast<unsigned long long>(store.TYPES)) {
set_data(store.data_);
}
/** Returns the argument at specified index. */
format_arg get(size_type index) const {
format_arg arg = do_get(index);
return arg.type_ == internal::name_arg_type ?
return arg.type_ == internal::named_arg_type ?
arg.value_.as_named_arg().template deserialize<Context>() : arg;
}
unsigned max_size() const {
int64_t signed_types = static_cast<int64_t>(types_);
long long signed_types = static_cast<long long>(types_);
return static_cast<unsigned>(
signed_types < 0 ?
-signed_types : static_cast<int64_t>(internal::max_packed_args));
-signed_types : static_cast<long long>(internal::max_packed_args));
}
};
@ -1163,28 +1195,22 @@ inline internal::named_arg<T, wchar_t> arg(wstring_view name, const T &arg) {
template <typename S, typename T, typename Char>
void arg(S, internal::named_arg<T, Char>) FMT_DELETED;
#ifndef FMT_EXTENDED_COLORS
// color and (v)print_colored are deprecated.
enum color { black, red, green, yellow, blue, magenta, cyan, white };
FMT_API void vprint_colored(color c, string_view format, format_args args);
FMT_API void vprint_colored(color c, wstring_view format, wformat_args args);
/**
Formats a string and prints it to stdout using ANSI escape sequences to
specify color (experimental).
Example:
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,
const Args & ... args) {
vprint_colored(c, format_str, make_format_args(args...));
}
template <typename... Args>
inline void print_colored(color c, wstring_view format_str,
const Args & ... args) {
vprint_colored(c, format_str, make_format_args<wformat_context>(args...));
}
#endif
format_context::iterator vformat_to(
internal::buffer &buf, string_view format_str, format_args args);
@ -1267,6 +1293,10 @@ inline void print(std::FILE *f, string_view format_str, const Args & ... args) {
format_arg_store<format_context, Args...> as(args...);
vprint(f, format_str, as);
}
/**
Prints formatted data to the file *f* which should be in wide-oriented mode set
via ``fwide(f, 1)`` or ``_setmode(_fileno(f), _O_U8TEXT)`` on Windows.
*/
template <typename... Args>
inline void print(std::FILE *f, wstring_view format_str, const Args & ... args) {
format_arg_store<wformat_context, Args...> as(args...);

View File

@ -45,12 +45,6 @@
# define FMT_CATCH(x) if (false)
#endif
#ifdef __GNUC__
// Disable the warning about declaration shadowing because it affects too
// many valid cases.
# pragma GCC diagnostic ignored "-Wshadow"
#endif
#ifdef _MSC_VER
# pragma warning(push)
# pragma warning(disable: 4127) // conditional expression is constant
@ -71,9 +65,6 @@ inline fmt::internal::null<> strerror_s(char *, std::size_t, ...) {
FMT_BEGIN_NAMESPACE
FMT_FUNC format_error::~format_error() throw() {}
FMT_FUNC system_error::~system_error() FMT_DTOR_NOEXCEPT {}
namespace {
#ifndef _MSC_VER
@ -95,9 +86,6 @@ inline int fmt_snprintf(char *buffer, size_t size, const char *format, ...) {
# define FMT_SWPRINTF swprintf
#endif // defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT)
const char RESET_COLOR[] = "\x1b[0m";
const wchar_t WRESET_COLOR[] = L"\x1b[0m";
typedef void (*FormatFunc)(internal::buffer &, int, string_view);
// Portable thread-safe version of strerror.
@ -232,30 +220,19 @@ FMT_FUNC void system_error::init(
namespace internal {
template <typename T>
int char_traits<char>::format_float(
char *buffer, std::size_t size, const char *format,
unsigned width, int precision, T value) {
if (width == 0) {
return precision < 0 ?
FMT_SNPRINTF(buffer, size, format, value) :
FMT_SNPRINTF(buffer, size, format, precision, value);
}
char *buffer, std::size_t size, const char *format, int precision, T value) {
return precision < 0 ?
FMT_SNPRINTF(buffer, size, format, width, value) :
FMT_SNPRINTF(buffer, size, format, width, precision, value);
FMT_SNPRINTF(buffer, size, format, value) :
FMT_SNPRINTF(buffer, size, format, precision, value);
}
template <typename T>
int char_traits<wchar_t>::format_float(
wchar_t *buffer, std::size_t size, const wchar_t *format,
unsigned width, int precision, T value) {
if (width == 0) {
return precision < 0 ?
FMT_SWPRINTF(buffer, size, format, value) :
FMT_SWPRINTF(buffer, size, format, precision, value);
}
wchar_t *buffer, std::size_t size, const wchar_t *format, int precision,
T value) {
return precision < 0 ?
FMT_SWPRINTF(buffer, size, format, width, value) :
FMT_SWPRINTF(buffer, size, format, width, precision, value);
FMT_SWPRINTF(buffer, size, format, value) :
FMT_SWPRINTF(buffer, size, format, precision, value);
}
template <typename T>
@ -294,35 +271,28 @@ const uint64_t basic_data<T>::POWERS_OF_10_64[] = {
// These are generated by support/compute-powers.py.
template <typename T>
const uint64_t basic_data<T>::POW10_SIGNIFICANDS[] = {
0xfa8fd5a0081c0288ull, 0xbaaee17fa23ebf76ull, 0x8b16fb203055ac76ull,
0xcf42894a5dce35eaull, 0x9a6bb0aa55653b2dull, 0xe61acf033d1a45dfull,
0xab70fe17c79ac6caull, 0xff77b1fcbebcdc4full, 0xbe5691ef416bd60cull,
0x8dd01fad907ffc3cull, 0xd3515c2831559a83ull, 0x9d71ac8fada6c9b5ull,
0xea9c227723ee8bcbull, 0xaecc49914078536dull, 0x823c12795db6ce57ull,
0xc21094364dfb5637ull, 0x9096ea6f3848984full, 0xd77485cb25823ac7ull,
0xa086cfcd97bf97f4ull, 0xef340a98172aace5ull, 0xb23867fb2a35b28eull,
0x84c8d4dfd2c63f3bull, 0xc5dd44271ad3cdbaull, 0x936b9fcebb25c996ull,
0xdbac6c247d62a584ull, 0xa3ab66580d5fdaf6ull, 0xf3e2f893dec3f126ull,
0xb5b5ada8aaff80b8ull, 0x87625f056c7c4a8bull, 0xc9bcff6034c13053ull,
0x964e858c91ba2655ull, 0xdff9772470297ebdull, 0xa6dfbd9fb8e5b88full,
0xf8a95fcf88747d94ull, 0xb94470938fa89bcfull, 0x8a08f0f8bf0f156bull,
0xcdb02555653131b6ull, 0x993fe2c6d07b7facull, 0xe45c10c42a2b3b06ull,
0xaa242499697392d3ull, 0xfd87b5f28300ca0eull, 0xbce5086492111aebull,
0x8cbccc096f5088ccull, 0xd1b71758e219652cull, 0x9c40000000000000ull,
0xe8d4a51000000000ull, 0xad78ebc5ac620000ull, 0x813f3978f8940984ull,
0xc097ce7bc90715b3ull, 0x8f7e32ce7bea5c70ull, 0xd5d238a4abe98068ull,
0x9f4f2726179a2245ull, 0xed63a231d4c4fb27ull, 0xb0de65388cc8ada8ull,
0x83c7088e1aab65dbull, 0xc45d1df942711d9aull, 0x924d692ca61be758ull,
0xda01ee641a708deaull, 0xa26da3999aef774aull, 0xf209787bb47d6b85ull,
0xb454e4a179dd1877ull, 0x865b86925b9bc5c2ull, 0xc83553c5c8965d3dull,
0x952ab45cfa97a0b3ull, 0xde469fbd99a05fe3ull, 0xa59bc234db398c25ull,
0xf6c69a72a3989f5cull, 0xb7dcbf5354e9beceull, 0x88fcf317f22241e2ull,
0xcc20ce9bd35c78a5ull, 0x98165af37b2153dfull, 0xe2a0b5dc971f303aull,
0xa8d9d1535ce3b396ull, 0xfb9b7cd9a4a7443cull, 0xbb764c4ca7a44410ull,
0x8bab8eefb6409c1aull, 0xd01fef10a657842cull, 0x9b10a4e5e9913129ull,
0xe7109bfba19c0c9dull, 0xac2820d9623bf429ull, 0x80444b5e7aa7cf85ull,
0xbf21e44003acdd2dull, 0x8e679c2f5e44ff8full, 0xd433179d9c8cb841ull,
0x9e19db92b4e31ba9ull, 0xeb96bf6ebadf77d9ull, 0xaf87023b9bf0ee6bull
0xfa8fd5a0081c0288, 0xbaaee17fa23ebf76, 0x8b16fb203055ac76, 0xcf42894a5dce35ea,
0x9a6bb0aa55653b2d, 0xe61acf033d1a45df, 0xab70fe17c79ac6ca, 0xff77b1fcbebcdc4f,
0xbe5691ef416bd60c, 0x8dd01fad907ffc3c, 0xd3515c2831559a83, 0x9d71ac8fada6c9b5,
0xea9c227723ee8bcb, 0xaecc49914078536d, 0x823c12795db6ce57, 0xc21094364dfb5637,
0x9096ea6f3848984f, 0xd77485cb25823ac7, 0xa086cfcd97bf97f4, 0xef340a98172aace5,
0xb23867fb2a35b28e, 0x84c8d4dfd2c63f3b, 0xc5dd44271ad3cdba, 0x936b9fcebb25c996,
0xdbac6c247d62a584, 0xa3ab66580d5fdaf6, 0xf3e2f893dec3f126, 0xb5b5ada8aaff80b8,
0x87625f056c7c4a8b, 0xc9bcff6034c13053, 0x964e858c91ba2655, 0xdff9772470297ebd,
0xa6dfbd9fb8e5b88f, 0xf8a95fcf88747d94, 0xb94470938fa89bcf, 0x8a08f0f8bf0f156b,
0xcdb02555653131b6, 0x993fe2c6d07b7fac, 0xe45c10c42a2b3b06, 0xaa242499697392d3,
0xfd87b5f28300ca0e, 0xbce5086492111aeb, 0x8cbccc096f5088cc, 0xd1b71758e219652c,
0x9c40000000000000, 0xe8d4a51000000000, 0xad78ebc5ac620000, 0x813f3978f8940984,
0xc097ce7bc90715b3, 0x8f7e32ce7bea5c70, 0xd5d238a4abe98068, 0x9f4f2726179a2245,
0xed63a231d4c4fb27, 0xb0de65388cc8ada8, 0x83c7088e1aab65db, 0xc45d1df942711d9a,
0x924d692ca61be758, 0xda01ee641a708dea, 0xa26da3999aef774a, 0xf209787bb47d6b85,
0xb454e4a179dd1877, 0x865b86925b9bc5c2, 0xc83553c5c8965d3d, 0x952ab45cfa97a0b3,
0xde469fbd99a05fe3, 0xa59bc234db398c25, 0xf6c69a72a3989f5c, 0xb7dcbf5354e9bece,
0x88fcf317f22241e2, 0xcc20ce9bd35c78a5, 0x98165af37b2153df, 0xe2a0b5dc971f303a,
0xa8d9d1535ce3b396, 0xfb9b7cd9a4a7443c, 0xbb764c4ca7a44410, 0x8bab8eefb6409c1a,
0xd01fef10a657842c, 0x9b10a4e5e9913129, 0xe7109bfba19c0c9d, 0xac2820d9623bf429,
0x80444b5e7aa7cf85, 0xbf21e44003acdd2d, 0x8e679c2f5e44ff8f, 0xd433179d9c8cb841,
0x9e19db92b4e31ba9, 0xeb96bf6ebadf77d9, 0xaf87023b9bf0ee6b
};
// Binary exponents of pow(10, k), for k = -348, -340, ..., 340, corresponding
@ -339,6 +309,9 @@ const int16_t basic_data<T>::POW10_EXPONENTS[] = {
827, 853, 880, 907, 933, 960, 986, 1013, 1039, 1066
};
template <typename T> const char basic_data<T>::RESET_COLOR[] = "\x1b[0m";
template <typename T> const wchar_t basic_data<T>::WRESET_COLOR[] = L"\x1b[0m";
FMT_FUNC fp operator*(fp x, fp y) {
// Multiply 32-bit parts of significands.
uint64_t mask = (1ULL << 32) - 1;
@ -349,6 +322,19 @@ FMT_FUNC fp operator*(fp x, fp y) {
uint64_t mid = (bd >> 32) + (ad & mask) + (bc & mask) + (1U << 31);
return fp(ac + (ad >> 32) + (bc >> 32) + (mid >> 32), x.e + y.e + 64);
}
FMT_FUNC fp get_cached_power(int min_exponent, int &pow10_exponent) {
const double one_over_log2_10 = 0.30102999566398114; // 1 / log2(10)
int index = static_cast<int>(std::ceil(
(min_exponent + fp::significand_size - 1) * one_over_log2_10));
// Decimal exponent of the first (smallest) cached power of 10.
const int first_dec_exp = -348;
// Difference between two consecutive decimal exponents in cached powers of 10.
const int dec_exp_step = 8;
index = (index - first_dec_exp - 1) / dec_exp_step + 1;
pow10_exponent = first_dec_exp + index * dec_exp_step;
return fp(data::POW10_SIGNIFICANDS[index], data::POW10_EXPONENTS[index]);
}
} // namespace internal
#if FMT_USE_WINDOWS_H
@ -513,12 +499,13 @@ FMT_FUNC void vprint(wstring_view format_str, wformat_args args) {
vprint(stdout, format_str, args);
}
#ifndef FMT_EXTENDED_COLORS
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);
vprint(format, args);
std::fputs(RESET_COLOR, stdout);
std::fputs(internal::data::RESET_COLOR, stdout);
}
FMT_FUNC void vprint_colored(color c, wstring_view format, wformat_args args) {
@ -526,8 +513,45 @@ FMT_FUNC void vprint_colored(color c, wstring_view format, wformat_args args) {
escape[3] = static_cast<wchar_t>('0' + c);
std::fputws(escape, stdout);
vprint(format, args);
std::fputws(WRESET_COLOR, stdout);
std::fputws(internal::data::WRESET_COLOR, stdout);
}
#else
namespace internal {
FMT_CONSTEXPR void to_esc(uint8_t c, char out[], int offset) {
out[offset + 0] = static_cast<char>('0' + c / 100);
out[offset + 1] = static_cast<char>('0' + c / 10 % 10);
out[offset + 2] = static_cast<char>('0' + c % 10);
}
} // namespace internal
FMT_FUNC void vprint_rgb(rgb fd, string_view format, format_args args) {
char escape_fd[] = "\x1b[38;2;000;000;000m";
internal::to_esc(fd.r, escape_fd, 7);
internal::to_esc(fd.g, escape_fd, 11);
internal::to_esc(fd.b, escape_fd, 15);
std::fputs(escape_fd, stdout);
vprint(format, args);
std::fputs(internal::data::RESET_COLOR, stdout);
}
FMT_FUNC void vprint_rgb(rgb fd, rgb bg, string_view format, format_args args) {
char escape_fd[] = "\x1b[38;2;000;000;000m"; // foreground color
char escape_bg[] = "\x1b[48;2;000;000;000m"; // background color
internal::to_esc(fd.r, escape_fd, 7);
internal::to_esc(fd.g, escape_fd, 11);
internal::to_esc(fd.b, escape_fd, 15);
internal::to_esc(bg.r, escape_bg, 7);
internal::to_esc(bg.g, escape_bg, 11);
internal::to_esc(bg.b, escape_bg, 15);
std::fputs(escape_fd, stdout);
std::fputs(escape_bg, stdout);
vprint(format, args);
std::fputs(internal::data::RESET_COLOR, stdout);
}
#endif
FMT_FUNC locale locale_provider::locale() { return fmt::locale(); }

File diff suppressed because it is too large Load Diff

View File

@ -53,8 +53,7 @@ struct test_stream : std::basic_ostream<Char> {
void operator<<(null);
};
// Checks if T has an overloaded operator<< which is a free function (not a
// member of std::ostream).
// Checks if T has a user-defined operator<< (e.g. not a member of std::ostream).
template <typename T, typename Char>
class is_streamable {
private:
@ -69,7 +68,9 @@ class is_streamable {
typedef decltype(test<T>(0)) result;
public:
static const bool value = result::value;
// std::string operator<< is not considered user-defined because we handle strings
// specially.
static const bool value = result::value && !std::is_same<T, std::string>::value;
};
// Disable conversion to int if T has an overloaded operator<< which is a free

View File

@ -49,8 +49,7 @@ class printf_precision_handler: public function<int> {
}
template <typename T>
typename std::enable_if<!std::is_integral<T>::value, int>::type
operator()(T) {
typename std::enable_if<!std::is_integral<T>::value, int>::type operator()(T) {
FMT_THROW(format_error("precision is not integer"));
return 0;
}
@ -251,25 +250,33 @@ class printf_arg_formatter:
: base(back_insert_range<internal::basic_buffer<char_type>>(buffer), spec),
context_(ctx) {}
using base::operator();
/** Formats an argument of type ``bool``. */
iterator operator()(bool value) {
format_specs &fmt_spec = this->spec();
if (fmt_spec.type_ != 's')
return (*this)(value ? 1 : 0);
fmt_spec.type_ = 0;
this->write(value);
template <typename T>
typename std::enable_if<std::is_integral<T>::value, iterator>::type
operator()(T value) {
// MSVC2013 fails to compile separate overloads for bool and char_type so
// use std::is_same instead.
if (std::is_same<T, bool>::value) {
format_specs &fmt_spec = this->spec();
if (fmt_spec.type_ != 's')
return base::operator()(value ? 1 : 0);
fmt_spec.type_ = 0;
this->write(value != 0);
} else if (std::is_same<T, char_type>::value) {
format_specs &fmt_spec = this->spec();
if (fmt_spec.type_ && fmt_spec.type_ != 'c')
return (*this)(static_cast<int>(value));
fmt_spec.flags_ = 0;
fmt_spec.align_ = ALIGN_RIGHT;
return base::operator()(value);
} else {
return base::operator()(value);
}
return this->out();
}
/** Formats a character. */
iterator operator()(char_type value) {
format_specs &fmt_spec = this->spec();
if (fmt_spec.type_ && fmt_spec.type_ != 'c')
return (*this)(static_cast<int>(value));
fmt_spec.flags_ = 0;
fmt_spec.align_ = ALIGN_RIGHT;
template <typename T>
typename std::enable_if<std::is_floating_point<T>::value, iterator>::type
operator()(T value) {
return base::operator()(value);
}
@ -295,6 +302,14 @@ class printf_arg_formatter:
return this->out();
}
iterator operator()(basic_string_view<char_type> value) {
return base::operator()(value);
}
iterator operator()(monostate value) {
return base::operator()(value);
}
/** Formats a pointer. */
iterator operator()(const void *value) {
if (value)

View File

@ -93,18 +93,14 @@ struct conditional_helper {};
template <typename T, typename _ = void>
struct is_range_ : std::false_type {};
#if !FMT_MSC_VER || FMT_MSC_VER > 1800
template <typename T>
struct is_range_<T,typename std::conditional<
false,
conditional_helper<decltype(internal::declval<T>().begin()),
decltype(internal::declval<T>().end())>,
void>::type> : std::true_type {};
template <typename T>
struct is_range {
static FMT_CONSTEXPR_DECL const bool value =
is_range_<T>::value && !is_like_std_string<T>::value;
};
struct is_range_<T, typename std::conditional<
false,
conditional_helper<decltype(internal::declval<T>().begin()),
decltype(internal::declval<T>().end())>,
void>::type> : std::true_type {};
#endif
/// tuple_size and tuple_element check.
template <typename T>
@ -121,23 +117,38 @@ class is_tuple_like_ {
!std::is_void<decltype(check<T>(FMT_NULL))>::value;
};
template <typename T>
struct is_tuple_like {
static FMT_CONSTEXPR_DECL const bool value =
is_tuple_like_<T>::value && !is_range_<T>::value;
};
} // namespace internal
#if FMT_HAS_FEATURE(__cpp_lib_integer_sequence) || FMT_MSC_VER >= 1900
# define FMT_USE_INTEGER_SEQUENCE 1
// Check for integer_sequence
#if defined(__cpp_lib_integer_sequence) || FMT_MSC_VER >= 1900
template <typename T, T... N>
using integer_sequence = std::integer_sequence<T, N...>;
template <std::size_t... N>
using index_sequence = std::index_sequence<N...>;
template <std::size_t N>
using make_index_sequence = std::make_index_sequence<N>;
#else
# define FMT_USE_INTEGER_SEQUENCE 0
template <typename T, T... N>
struct integer_sequence {
typedef T value_type;
static FMT_CONSTEXPR std::size_t size() {
return sizeof...(N);
}
};
template <std::size_t... N>
using index_sequence = integer_sequence<std::size_t, N...>;
template <typename T, std::size_t N, T... Ns>
struct make_integer_sequence : make_integer_sequence<T, N - 1, N - 1, Ns...> {};
template <typename T, T... Ns>
struct make_integer_sequence<T, 0, Ns...> : integer_sequence<T, Ns...> {};
template <std::size_t N>
using make_index_sequence = make_integer_sequence<std::size_t, N>;
#endif
#if FMT_USE_INTEGER_SEQUENCE
namespace internal {
template <size_t... Is, class Tuple, class F>
void for_each(std::index_sequence<Is...>, Tuple &&tup, F &&f) noexcept {
template <class Tuple, class F, size_t... Is>
void for_each(index_sequence<Is...>, Tuple &&tup, F &&f) FMT_NOEXCEPT {
using std::get;
// using free function get<I>(T) now.
const int _[] = {0, ((void)f(get<Is>(tup)), 0)...};
@ -145,7 +156,7 @@ void for_each(std::index_sequence<Is...>, Tuple &&tup, F &&f) noexcept {
}
template <class T>
FMT_CONSTEXPR std::make_index_sequence<std::tuple_size<T>::value>
FMT_CONSTEXPR make_index_sequence<std::tuple_size<T>::value>
get_indexes(T const &) { return {}; }
template <class Tuple, class F>
@ -153,13 +164,72 @@ void for_each(Tuple &&tup, F &&f) {
const auto indexes = get_indexes(tup);
for_each(indexes, std::forward<Tuple>(tup), std::forward<F>(f));
}
template<typename Arg>
FMT_CONSTEXPR const char* format_str_quoted(bool add_space, const Arg&,
typename std::enable_if<
!is_like_std_string<typename std::decay<Arg>::type>::value>::type* = nullptr) {
return add_space ? " {}" : "{}";
}
template<typename Arg>
FMT_CONSTEXPR const char* format_str_quoted(bool add_space, const Arg&,
typename std::enable_if<
is_like_std_string<typename std::decay<Arg>::type>::value>::type* = nullptr) {
return add_space ? " \"{}\"" : "\"{}\"";
}
FMT_CONSTEXPR const char* format_str_quoted(bool add_space, const char*) {
return add_space ? " \"{}\"" : "\"{}\"";
}
FMT_CONSTEXPR const wchar_t* format_str_quoted(bool add_space, const wchar_t*) {
return add_space ? L" \"{}\"" : L"\"{}\"";
}
FMT_CONSTEXPR const char* format_str_quoted(bool add_space, const char) {
return add_space ? " '{}'" : "'{}'";
}
FMT_CONSTEXPR const wchar_t* format_str_quoted(bool add_space, const wchar_t) {
return add_space ? L" '{}'" : L"'{}'";
}
} // namespace internal
template <typename T>
struct is_tuple_like {
static FMT_CONSTEXPR_DECL const bool value =
internal::is_tuple_like_<T>::value && !internal::is_range_<T>::value;
};
template <typename TupleT, typename Char>
struct formatter<TupleT, Char,
typename std::enable_if<fmt::internal::is_tuple_like<TupleT>::value>::type> {
typename std::enable_if<fmt::is_tuple_like<TupleT>::value>::type> {
private:
// C++11 generic lambda for format()
template <typename FormatContext>
struct format_each {
template <typename T>
void operator()(const T& v) {
if (i > 0) {
if (formatting.add_prepostfix_space) {
*out++ = ' ';
}
internal::copy(formatting.delimiter, out);
}
format_to(out,
internal::format_str_quoted(
(formatting.add_delimiter_spaces && i > 0), v),
v);
++i;
}
fmt::formatting_tuple<Char> formatting;
formatting_tuple<Char>& formatting;
std::size_t& i;
typename std::add_lvalue_reference<decltype(std::declval<FormatContext>().out())>::type out;
};
public:
formatting_tuple<Char> formatting;
template <typename ParseContext>
FMT_CONSTEXPR auto parse(ParseContext &ctx) -> decltype(ctx.begin()) {
@ -171,20 +241,8 @@ struct formatter<TupleT, Char,
auto out = ctx.out();
std::size_t i = 0;
internal::copy(formatting.prefix, out);
internal::for_each(values, [&](const auto &v) {
if (i > 0) {
if (formatting.add_prepostfix_space) {
*out++ = ' ';
}
internal::copy(formatting.delimiter, out);
}
if (formatting.add_delimiter_spaces && i > 0) {
format_to(out, " {}", v);
} else {
format_to(out, "{}", v);
}
++i;
});
internal::for_each(values, format_each<FormatContext>{formatting, i, out});
if (formatting.add_prepostfix_space) {
*out++ = ' ';
}
@ -193,13 +251,18 @@ struct formatter<TupleT, Char,
return ctx.out();
}
};
#endif // FMT_USE_INTEGER_SEQUENCE
template <typename T>
struct is_range {
static FMT_CONSTEXPR_DECL const bool value =
internal::is_range_<T>::value && !internal::is_like_std_string<T>::value;
};
template <typename RangeT, typename Char>
struct formatter< RangeT, Char,
typename std::enable_if<fmt::internal::is_range<RangeT>::value>::type> {
struct formatter<RangeT, Char,
typename std::enable_if<fmt::is_range<RangeT>::value>::type> {
fmt::formatting_range<Char> formatting;
formatting_range<Char> formatting;
template <typename ParseContext>
FMT_CONSTEXPR auto parse(ParseContext &ctx) -> decltype(ctx.begin()) {
@ -219,11 +282,10 @@ struct formatter< RangeT, Char,
}
internal::copy(formatting.delimiter, out);
}
if (formatting.add_delimiter_spaces && i > 0) {
format_to(out, " {}", *it);
} else {
format_to(out, "{}", *it);
}
format_to(out,
internal::format_str_quoted(
(formatting.add_delimiter_spaces && i > 0), *it),
*it);
if (++i > formatting.range_length_limit) {
format_to(out, " ... <other elements>");
break;

View File

@ -54,7 +54,6 @@ inline std::tm localtime(std::time_t time) {
return lt.tm_;
// Too big time values may be unsupported.
FMT_THROW(format_error("time_t value out of range"));
return std::tm();
}
// Thread-safe replacement for std::gmtime
@ -90,7 +89,6 @@ inline std::tm gmtime(std::time_t time) {
return gt.tm_;
// Too big time values may be unsupported.
FMT_THROW(format_error("time_t value out of range"));
return std::tm();
}
namespace internal {

View File

@ -8,6 +8,11 @@
#include "fmt/format-inl.h"
FMT_BEGIN_NAMESPACE
namespace internal {
// Force linking of inline functions into the library.
std::string (*vformat_ref)(string_view, format_args) = vformat;
std::wstring (*vformat_wref)(wstring_view, wformat_args) = vformat;
}
template struct internal::basic_data<void>;
@ -21,12 +26,12 @@ template void internal::arg_map<format_context>::init(
const basic_format_args<format_context> &args);
template FMT_API int internal::char_traits<char>::format_float(
char *buffer, std::size_t size, const char *format,
unsigned width, int precision, double value);
char *buffer, std::size_t size, const char *format, int precision,
double value);
template FMT_API int internal::char_traits<char>::format_float(
char *buffer, std::size_t size, const char *format,
unsigned width, int precision, long double value);
char *buffer, std::size_t size, const char *format, int precision,
long double value);
// Explicit instantiations for wchar_t.
@ -39,9 +44,9 @@ template void internal::arg_map<wformat_context>::init(
template FMT_API int internal::char_traits<wchar_t>::format_float(
wchar_t *buffer, std::size_t size, const wchar_t *format,
unsigned width, int precision, double value);
int precision, double value);
template FMT_API int internal::char_traits<wchar_t>::format_float(
wchar_t *buffer, std::size_t size, const wchar_t *format,
unsigned width, int precision, long double value);
int precision, long double value);
FMT_END_NAMESPACE

View File

@ -6,7 +6,7 @@
// For the license information refer to format.h.
// Disable bogus MSVC warnings.
#ifndef _CRT_SECURE_NO_WARNINGS
#if !defined(_CRT_SECURE_NO_WARNINGS) && defined(_MSC_VER)
# define _CRT_SECURE_NO_WARNINGS
#endif

View File

@ -4,7 +4,7 @@ include $(CLEAR_VARS)
LOCAL_MODULE := fmt_static
LOCAL_MODULE_FILENAME := libfmt
LOCAL_SRC_FILES := fmt/format.cc
LOCAL_SRC_FILES := ../src/format.cc
LOCAL_C_INCLUDES := $(LOCAL_PATH)
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)

13
support/appveyor-build.py Executable file → Normal file
View File

@ -6,9 +6,11 @@ from subprocess import check_call
build = os.environ['BUILD']
config = os.environ['CONFIGURATION']
platform = os.environ.get('PLATFORM')
platform = os.environ['PLATFORM']
path = os.environ['PATH']
cmake_command = ['cmake', '-DFMT_PEDANTIC=ON', '-DCMAKE_BUILD_TYPE=' + config]
image = os.environ['APPVEYOR_BUILD_WORKER_IMAGE']
jobid = os.environ['APPVEYOR_JOB_ID']
cmake_command = ['cmake', '-DFMT_PEDANTIC=ON', '-DCMAKE_BUILD_TYPE=' + config, '..']
if build == 'mingw':
cmake_command.append('-GMinGW Makefiles')
build_command = ['mingw32-make', '-j4']
@ -21,7 +23,12 @@ else:
# Add MSBuild 14.0 to PATH as described in
# http://help.appveyor.com/discussions/problems/2229-v140-not-found-on-vs2105rc.
os.environ['PATH'] = r'C:\Program Files (x86)\MSBuild\15.0\Bin;' + path
generator = 'Visual Studio 15 2017'
if image == 'Visual Studio 2013':
generator = 'Visual Studio 12 2013'
elif image == 'Visual Studio 2015':
generator = 'Visual Studio 14 2015'
elif image == 'Visual Studio 2017':
generator = 'Visual Studio 15 2017'
if platform == 'x64':
generator += ' Win64'
cmake_command.append('-G' + generator)

View File

@ -2,21 +2,28 @@ configuration:
- Debug
- Release
image: Visual Studio 2017
clone_depth: 1
platform:
- Win32
- x64
image:
- Visual Studio 2013
- Visual Studio 2015
- Visual Studio 2017
environment:
CTEST_OUTPUT_ON_FAILURE: 1
matrix:
- BUILD: msvc
- BUILD: msvc
PLATFORM: x64
MSVC_DEFAULT_OPTIONS: ON
BUILD: msvc
before_build:
# Workaround for CMake not wanting sh.exe on PATH for MinGW.
- set PATH=%PATH:C:\Program Files\Git\usr\bin;=%
- mkdir build
- cd build
build_script:
- python support/appveyor-build.py
- python ../support/appveyor-build.py
on_failure:
- appveyor PushArtifact Testing/Temporary/LastTest.log

View File

@ -1,67 +1,52 @@
# C++14 feature support detection
if (NOT FMT_USE_CPP14)
return()
endif ()
include(CheckCXXSourceCompiles)
include(CheckCXXCompilerFlag)
if (FMT_USE_CPP14)
check_cxx_compiler_flag(-std=c++14 HAVE_STD_CPP14_FLAG)
if (HAVE_STD_CPP14_FLAG)
# Check if including cmath works with -std=c++14 and -O3.
# It may not in MinGW due to bug http://ehc.ac/p/mingw/bugs/2250/.
set(CMAKE_REQUIRED_FLAGS "-std=c++14 -O3")
check_cxx_source_compiles("
#include <cmath>
int main() {}" FMT_CPP14_CMATH)
# Check if including <unistd.h> works with -std=c++14.
# It may not in MinGW due to bug http://sourceforge.net/p/mingw/bugs/2024/.
check_cxx_source_compiles("
#include <unistd.h>
int main() {}" FMT_CPP14_UNISTD_H)
# Check if snprintf works with -std=c++14. It may not in MinGW.
check_cxx_source_compiles("
#include <stdio.h>
int main() {
char buffer[10];
snprintf(buffer, 10, \"foo\");
}" FMT_CPP14_SNPRINTF)
if (FMT_CPP14_CMATH AND FMT_CPP14_UNISTD_H AND FMT_CPP14_SNPRINTF)
set(CPP14_FLAG -std=c++14)
else ()
check_cxx_compiler_flag(-std=gnu++14 HAVE_STD_GNUPP14_FLAG)
if (HAVE_STD_CPP14_FLAG)
set(CPP14_FLAG -std=gnu++14)
endif ()
endif ()
set(CMAKE_REQUIRED_FLAGS )
else ()
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 ()
if (NOT CMAKE_CXX_STANDARD)
set(CMAKE_CXX_STANDARD 11)
endif()
message(STATUS "CXX_STANDARD: ${CMAKE_CXX_STANDARD}")
if (CMAKE_CXX_STANDARD EQUAL 20)
check_cxx_compiler_flag(-std=c++20 has_std_20_flag)
check_cxx_compiler_flag(-std=c++2a has_std_2a_flag)
if (has_std_20_flag)
set(CXX_STANDARD_FLAG -std=c++20)
elseif (has_std_2a_flag)
set(CXX_STANDARD_FLAG -std=c++2a)
endif ()
elseif (CMAKE_CXX_STANDARD EQUAL 17)
check_cxx_compiler_flag(-std=c++17 has_std_17_flag)
check_cxx_compiler_flag(-std=c++1z has_std_1z_flag)
if (has_std_17_flag)
set(CXX_STANDARD_FLAG -std=c++17)
elseif (has_std_1z_flag)
set(CXX_STANDARD_FLAG -std=c++1z)
endif ()
elseif (CMAKE_CXX_STANDARD EQUAL 14)
check_cxx_compiler_flag(-std=c++14 has_std_14_flag)
check_cxx_compiler_flag(-std=c++1y has_std_1y_flag)
if (has_std_14_flag)
set(CXX_STANDARD_FLAG -std=c++14)
elseif (has_std_1y_flag)
set(CXX_STANDARD_FLAG -std=c++1y)
endif ()
elseif (CMAKE_CXX_STANDARD EQUAL 11)
check_cxx_compiler_flag(-std=c++11 has_std_11_flag)
check_cxx_compiler_flag(-std=c++0x has_std_0x_flag)
if (has_std_11_flag)
set(CXX_STANDARD_FLAG -std=c++11)
elseif (has_std_0x_flag)
set(CXX_STANDARD_FLAG -std=c++0x)
endif ()
endif ()
if (CMAKE_CXX_STANDARD)
# Don't use -std compiler flag if CMAKE_CXX_STANDARD is specified.
set(CPP14_FLAG )
endif ()
message(STATUS "CPP14_FLAG: ${CPP14_FLAG}")
set(CMAKE_REQUIRED_FLAGS ${CPP14_FLAG})
set(CMAKE_REQUIRED_FLAGS ${CXX_STANDARD_FLAG})
# Check if variadic templates are working and not affected by GCC bug 39653:
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=39653
@ -69,17 +54,26 @@ check_cxx_source_compiles("
template <class T, class ...Types>
struct S { typedef typename S<Types...>::type type; };
int main() {}" SUPPORTS_VARIADIC_TEMPLATES)
if (NOT SUPPORTS_VARIADIC_TEMPLATES)
set (SUPPORTS_VARIADIC_TEMPLATES OFF)
endif ()
# Check if initializer lists are supported.
check_cxx_source_compiles("
#include <initializer_list>
int main() {}" SUPPORTS_INITIALIZER_LIST)
if (NOT SUPPORTS_INITIALIZER_LIST)
set (SUPPORTS_INITIALIZER_LIST OFF)
endif ()
# Check if enum bases are available
check_cxx_source_compiles("
enum C : char {A};
int main() {}"
SUPPORTS_ENUM_BASE)
if (NOT SUPPORTS_ENUM_BASE)
set (SUPPORTS_ENUM_BASE OFF)
endif ()
# Check if type traits are available
check_cxx_source_compiles("
@ -87,11 +81,17 @@ check_cxx_source_compiles("
class C { void operator=(const C&); };
int main() { static_assert(!std::is_copy_assignable<C>::value, \"\"); }"
SUPPORTS_TYPE_TRAITS)
if (NOT SUPPORTS_TYPE_TRAITS)
set (SUPPORTS_TYPE_TRAITS OFF)
endif ()
# Check if user-defined literals are available
check_cxx_source_compiles("
void operator\"\" _udl(long double);
int main() {}"
SUPPORTS_USER_DEFINED_LITERALS)
if (NOT SUPPORTS_USER_DEFINED_LITERALS)
set (SUPPORTS_USER_DEFINED_LITERALS OFF)
endif ()
set(CMAKE_REQUIRED_FLAGS )

View File

@ -39,12 +39,15 @@ for i, exp in enumerate(range(min_exponent, max_exponent + 1, step)):
print('Significands:', end='')
for i, fp in enumerate(powers):
if i % 3 == 0:
if i % 4 == 0:
print(end='\n ')
print(' {:0<#16x}ull'.format(fp.f, ), end=',')
print(' {:0<#16x}'.format(fp.f, ), end=',')
print('\n\nExponents:', end='')
for i, fp in enumerate(powers):
if i % 11 == 0:
print(end='\n ')
print(' {:5}'.format(fp.e), end=',')
print('\n\nMax exponent difference:',
max([x.e - powers[i - 1].e for i, x in enumerate(powers)][1:]))

View File

@ -152,7 +152,9 @@ def update_site(env):
if os.path.exists(html_dir):
shutil.rmtree(html_dir)
include_dir = env.fmt_repo.dir
if LooseVersion(version) >= LooseVersion('3.0.0'):
if LooseVersion(version) >= LooseVersion('5.0.0'):
include_dir = os.path.join(include_dir, 'include', 'fmt')
elif LooseVersion(version) >= LooseVersion('3.0.0'):
include_dir = os.path.join(include_dir, 'fmt')
import build
build.build_docs(version, doc_dir=target_doc_dir,
@ -243,12 +245,11 @@ def release(args):
id = r.json()['id']
uploads_url = 'https://uploads.github.com/repos/fmtlib/fmt/releases'
package = 'fmt-{}.zip'.format(version)
with open('build/fmt/' + package, 'rb') as f:
r = requests.post(
'{}/{}/assets?name={}'.format(uploads_url, id, package),
params=params, files={package: f})
if r.status_code != 201:
raise Exception('Failed to upload an asset ' + str(r))
r = requests.post(
'{}/{}/assets?name={}'.format(uploads_url, id, package),
params=params, files={package: open('build/fmt/' + package, 'rb')})
if r.status_code != 201:
raise Exception('Failed to upload an asset ' + str(r))
if __name__ == '__main__':

View File

@ -2,8 +2,8 @@
# Build the project on Travis CI.
from __future__ import print_function
import errno, os, re, shutil, subprocess, sys, tempfile, urllib
from subprocess import call, check_call, check_output, Popen, PIPE, STDOUT
import errno, os, shutil, subprocess, sys, urllib
from subprocess import call, check_call, Popen, PIPE, STDOUT
def rmtree_if_exists(dir):
try:
@ -85,14 +85,12 @@ test_build_dir = os.path.join(fmt_dir, "_build_test")
# Configure library.
makedirs_if_not_exist(build_dir)
common_cmake_flags = [
'-DCMAKE_INSTALL_PREFIX=' + install_dir, '-DCMAKE_BUILD_TYPE=' + build
cmake_flags = [
'-DCMAKE_INSTALL_PREFIX=' + install_dir, '-DCMAKE_BUILD_TYPE=' + build,
'-DCMAKE_CXX_STANDARD=' + standard
]
extra_cmake_flags = []
if standard != '14':
extra_cmake_flags = ['-DCMAKE_CXX_FLAGS=-std=c++' + standard]
check_call(['cmake', '-DFMT_DOC=OFF', '-DFMT_PEDANTIC=ON', fmt_dir] +
common_cmake_flags + extra_cmake_flags, cwd=build_dir)
check_call(['cmake', '-DFMT_DOC=OFF', '-DFMT_PEDANTIC=ON', '-DFMT_WERROR=ON', fmt_dir] +
cmake_flags, cwd=build_dir)
# Build library.
check_call(['make', '-j4'], cwd=build_dir)
@ -101,7 +99,7 @@ check_call(['make', '-j4'], cwd=build_dir)
env = os.environ.copy()
env['CTEST_OUTPUT_ON_FAILURE'] = '1'
if call(['make', 'test'], env=env, cwd=build_dir):
with open('Testing/Temporary/LastTest.log', 'r') as f:
with open(os.path.join(build_dir, 'Testing', 'Temporary', 'LastTest.log'), 'r') as f:
print(f.read())
sys.exit(-1)
@ -110,7 +108,6 @@ check_call(['make', 'install'], cwd=build_dir)
# Test installation.
makedirs_if_not_exist(test_build_dir)
check_call(['cmake', '-DCMAKE_CXX_FLAGS=-std=c++' + standard,
os.path.join(fmt_dir, "test", "find-package-test")] +
common_cmake_flags, cwd=test_build_dir)
check_call(['cmake', os.path.join(fmt_dir, "test", "find-package-test")] +
cmake_flags, cwd=test_build_dir)
check_call(['make', '-j4'], cwd=test_build_dir)

View File

@ -7,9 +7,8 @@
# at http://code.google.com/p/googletest/wiki/FAQ for more details.
add_library(gmock STATIC
gmock-gtest-all.cc gmock/gmock.h gtest/gtest.h gtest/gtest-spi.h)
target_compile_options(gmock PUBLIC ${CPP14_FLAG})
target_compile_definitions(gmock PUBLIC GTEST_HAS_STD_WSTRING=1)
target_include_directories(gmock PUBLIC .)
target_include_directories(gmock SYSTEM PUBLIC . gmock gtest)
find_package(Threads)
if (Threads_FOUND)
@ -43,6 +42,7 @@ set(TEST_MAIN_SRC test-main.cc gtest-extra.cc gtest-extra.h util.cc)
add_library(test-main STATIC ${TEST_MAIN_SRC})
target_compile_definitions(test-main PUBLIC
FMT_USE_FILE_DESCRIPTORS=$<BOOL:${HAVE_OPEN}>)
target_include_directories(test-main SYSTEM PUBLIC gtest gmock)
target_link_libraries(test-main gmock fmt)
include(CheckCXXCompilerFlag)
@ -57,7 +57,7 @@ endif ()
# Use less strict pedantic flags for the tests because GMock doesn't compile
# cleanly with -pedantic and -std=c++98.
if (CMAKE_COMPILER_IS_GNUCXX OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang"))
set(PEDANTIC_COMPILE_FLAGS -Wall -Wextra -Wno-long-long -Wno-variadic-macros)
#set(PEDANTIC_COMPILE_FLAGS -Wall -Wextra -Wno-long-long -Wno-variadic-macros)
endif ()
function(add_fmt_executable name)
@ -80,6 +80,7 @@ function(add_fmt_test name)
if (FMT_PEDANTIC)
target_compile_options(${name} PRIVATE ${PEDANTIC_COMPILE_FLAGS})
endif ()
target_include_directories(${name} SYSTEM PUBLIC gtest gmock)
add_test(NAME ${name} COMMAND ${name})
endfunction()
@ -94,12 +95,6 @@ add_fmt_test(util-test mock-allocator.h)
add_fmt_test(custom-formatter-test)
add_fmt_test(ranges-test)
# Enable stricter options for one test to make sure that the header is free of
# warnings.
if (FMT_PEDANTIC AND MSVC)
target_compile_options(format-test PRIVATE /W4)
endif ()
if (HAVE_OPEN)
add_fmt_executable(posix-mock-test
posix-mock-test.cc ../src/format.cc ${TEST_MAIN_SRC})
@ -107,6 +102,10 @@ if (HAVE_OPEN)
posix-mock-test PRIVATE ${PROJECT_SOURCE_DIR}/include)
target_compile_definitions(posix-mock-test PRIVATE FMT_USE_FILE_DESCRIPTORS=1)
target_link_libraries(posix-mock-test gmock)
target_include_directories(posix-mock-test SYSTEM PUBLIC gtest gmock)
if (FMT_PEDANTIC)
target_compile_options(posix-mock-test PRIVATE ${PEDANTIC_COMPILE_FLAGS})
endif ()
add_test(NAME posix-mock-test COMMAND posix-mock-test)
add_fmt_test(posix-test)
endif ()
@ -114,6 +113,7 @@ endif ()
add_fmt_executable(header-only-test
header-only-test.cc header-only-test2.cc test-main.cc)
target_link_libraries(header-only-test gmock)
target_include_directories(header-only-test SYSTEM PUBLIC gtest gmock)
if (TARGET fmt-header-only)
target_link_libraries(header-only-test fmt-header-only)
else ()
@ -126,20 +126,28 @@ endif ()
check_cxx_compiler_flag(-fno-exceptions HAVE_FNO_EXCEPTIONS_FLAG)
if (HAVE_FNO_EXCEPTIONS_FLAG)
add_library(noexception-test ../src/format.cc)
target_compile_options(noexception-test PUBLIC ${CPP14_FLAG})
target_include_directories(
noexception-test PRIVATE ${PROJECT_SOURCE_DIR}/include)
target_compile_options(noexception-test PRIVATE -fno-exceptions)
if (FMT_PEDANTIC)
target_compile_options(noexception-test PRIVATE ${PEDANTIC_COMPILE_FLAGS})
endif ()
target_include_directories(noexception-test SYSTEM PUBLIC gtest gmock)
endif ()
message(STATUS "FMT_PEDANTIC: ${FMT_PEDANTIC}")
if (FMT_PEDANTIC)
# Test that the library compiles without windows.h.
if (CMAKE_SYSTEM_NAME STREQUAL "Windows")
add_library(no-windows-h-test ../src/format.cc)
target_compile_options(no-windows-h-test PUBLIC ${CPP14_FLAG})
target_include_directories(
no-windows-h-test PRIVATE ${PROJECT_SOURCE_DIR}/include)
target_compile_definitions(no-windows-h-test PRIVATE FMT_USE_WINDOWS_H=0)
if (FMT_PEDANTIC)
target_compile_options(no-windows-h-test PRIVATE ${PEDANTIC_COMPILE_FLAGS})
endif ()
target_include_directories(no-windows-h-test SYSTEM PUBLIC gtest gmock)
endif ()
add_test(compile-test ${CMAKE_CTEST_COMMAND}
@ -148,9 +156,11 @@ if (FMT_PEDANTIC)
"${CMAKE_CURRENT_BINARY_DIR}/compile-test"
--build-generator ${CMAKE_GENERATOR}
--build-makeprogram ${CMAKE_MAKE_PROGRAM}
--build-options
--build-options
"-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}"
"-DCPP14_FLAG=${CPP14_FLAG}"
"-DCMAKE_CXX_STANDARD=${CMAKE_CXX_STANDARD}"
"-DCXX_STANDARD_FLAG=${CXX_STANDARD_FLAG}"
"-DPEDANTIC_COMPILE_FLAGS=${PEDANTIC_COMPILE_FLAGS}"
"-DSUPPORTS_USER_DEFINED_LITERALS=${SUPPORTS_USER_DEFINED_LITERALS}")
# test if the targets are findable from the build directory
@ -163,8 +173,9 @@ if (FMT_PEDANTIC)
--build-makeprogram ${CMAKE_MAKE_PROGRAM}
--build-options
"-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}"
"-DCPP14_FLAG=${CPP14_FLAG}"
"-DCMAKE_CXX_STANDARD=${CMAKE_CXX_STANDARD}"
"-DFMT_DIR=${PROJECT_BINARY_DIR}"
"-DPEDANTIC_COMPILE_FLAGS=${PEDANTIC_COMPILE_FLAGS}"
"-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}")
# test if the targets are findable when add_subdirectory is used
@ -177,6 +188,7 @@ if (FMT_PEDANTIC)
--build-makeprogram ${CMAKE_MAKE_PROGRAM}
--build-options
"-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}"
"-DCPP14_FLAG=${CPP14_FLAG}"
"-DCMAKE_CXX_STANDARD=${CMAKE_CXX_STANDARD}"
"-DPEDANTIC_COMPILE_FLAGS=${PEDANTIC_COMPILE_FLAGS}"
"-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}")
endif ()

View File

@ -1,15 +1,17 @@
cmake_minimum_required(VERSION 2.8.12)
cmake_minimum_required(VERSION 3.1.0)
project(fmt-test)
add_subdirectory(../.. fmt)
add_executable(library-test "main.cc")
target_compile_options(library-test PUBLIC ${CPP14_FLAG})
target_link_libraries(library-test fmt::fmt)
target_compile_options(library-test PRIVATE ${PEDANTIC_COMPILE_FLAGS})
target_include_directories(library-test PUBLIC SYSTEM .)
if (TARGET fmt::fmt-header-only)
add_executable(header-only-test "main.cc")
target_compile_options(header-only-test PUBLIC ${CPP14_FLAG})
target_link_libraries(header-only-test fmt::fmt-header-only)
target_compile_options(header-only-test PRIVATE ${PEDANTIC_COMPILE_FLAGS})
target_include_directories(header-only-test PUBLIC SYSTEM .)
endif ()

View File

@ -6,7 +6,7 @@
// For the license information refer to format.h.
#include "fmt/core.h"
#include "gtest/gtest.h"
#include "gtest.h"
#if GTEST_HAS_DEATH_TEST
# define EXPECT_DEBUG_DEATH_IF_SUPPORTED(statement, regex) \

View File

@ -1,10 +1,12 @@
# Test if compile errors are produced where necessary.
cmake_minimum_required(VERSION 2.8)
cmake_minimum_required(VERSION 3.1.0)
include(CheckCXXSourceCompiles)
include(CheckCXXCompilerFlag)
set(CMAKE_REQUIRED_INCLUDES ${CMAKE_CURRENT_SOURCE_DIR}/../../include)
set(CMAKE_REQUIRED_FLAGS ${CPP14_FLAG})
set(CMAKE_REQUIRED_FLAGS ${CXX_STANDARD_FLAG} ${PEDANTIC_COMPILE_FLAGS})
function (generate_source result fragment)
set(${result} "

View File

@ -8,6 +8,9 @@
#include "fmt/format.h"
#include "gtest-extra.h"
// MSVC 2013 is known to be broken.
#if !FMT_MSC_VER || FMT_MSC_VER > 1800
// A custom argument formatter that doesn't print `-` for floating-point values
// rounded to 0.
class custom_arg_formatter :
@ -22,7 +25,8 @@ class custom_arg_formatter :
using base::operator();
iterator operator()(double value) {
if (round(value * pow(10, spec().precision())) == 0)
// Comparing a float to 0.0 is safe
if (round(value * pow(10, spec().precision())) == 0.0)
value = 0;
return base::operator()(value);
}
@ -44,3 +48,4 @@ std::string custom_format(const char *format_str, const Args & ... args) {
TEST(CustomFormatterTest, Format) {
EXPECT_EQ("0.00", custom_format("{:.2f}", -.00001));
}
#endif

View File

@ -1,15 +1,17 @@
cmake_minimum_required(VERSION 2.8.12)
cmake_minimum_required(VERSION 3.1.0)
project(fmt-test)
find_package(FMT REQUIRED)
add_executable(library-test main.cc)
target_compile_options(library-test PUBLIC ${CPP14_FLAG})
target_link_libraries(library-test fmt::fmt)
target_compile_options(library-test PRIVATE ${PEDANTIC_COMPILE_FLAGS})
target_include_directories(library-test PUBLIC SYSTEM .)
if (TARGET fmt::fmt-header-only)
add_executable(header-only-test main.cc)
target_compile_options(header-only-test PUBLIC ${CPP14_FLAG})
target_link_libraries(header-only-test fmt::fmt-header-only)
target_compile_options(header-only-test PRIVATE ${PEDANTIC_COMPILE_FLAGS})
target_include_directories(header-only-test PUBLIC SYSTEM .)
endif ()

View File

@ -5,6 +5,7 @@
//
// For the license information refer to format.h.
#define FMT_EXTENDED_COLORS
#define FMT_NOEXCEPT
#undef FMT_SHARED
#include "test-assert.h"
@ -16,7 +17,7 @@
#include <algorithm>
#include <cstring>
#include "gmock/gmock.h"
#include "gmock.h"
#include "gtest-extra.h"
#include "util.h"
@ -30,9 +31,8 @@ struct ValueExtractor: fmt::internal::function<T> {
}
template <typename U>
T operator()(U) {
FMT_NORETURN T operator()(U) {
throw std::runtime_error(fmt::format("invalid type {}", typeid(U).name()));
return T();
}
};
@ -53,9 +53,9 @@ TEST(FormatTest, FormatNegativeNaN) {
}
TEST(FormatTest, StrError) {
char *message = 0;
char *message = nullptr;
char buffer[BUFFER_SIZE];
EXPECT_ASSERT(fmt::safe_strerror(EDOM, message = 0, 0), "invalid buffer");
EXPECT_ASSERT(fmt::safe_strerror(EDOM, message = nullptr, 0), "invalid buffer");
EXPECT_ASSERT(fmt::safe_strerror(EDOM, message = buffer, 0),
"invalid buffer");
buffer[0] = 'x';
@ -117,3 +117,10 @@ TEST(FormatTest, FormatErrorCode) {
EXPECT_EQ(msg, to_string(buffer));
}
}
TEST(ColorsTest, Colors) {
EXPECT_WRITE(stdout, fmt::print(fmt::rgb(255,20,30), "rgb(255,20,30)"),
"\x1b[38;2;255;020;030mrgb(255,20,30)\x1b[0m");
EXPECT_WRITE(stdout, fmt::print(fmt::color::blue,"blue"),
"\x1b[38;2;000;000;255mblue\x1b[0m");
}

View File

@ -14,16 +14,11 @@
#include <memory>
#include <stdint.h>
#include "gmock/gmock.h"
// Test that the library compiles if None is defined to 0 as done by xlib.h.
#define None 0
#include "fmt/format.h"
#include "util.h"
#include "mock-allocator.h"
#include "gmock.h"
#include "gtest-extra.h"
#include "mock-allocator.h"
#include "util.h"
#undef min
#undef max
@ -232,6 +227,18 @@ TEST(FormatToTest, Format) {
EXPECT_EQ("part1part2", s);
}
TEST(FormatToTest, FormatToNonbackInsertIteratorWithSignAndNumericAlignment) {
char buffer[16] = {};
fmt::format_to(buffer, "{: =+}", 42.0);
EXPECT_STREQ("+42", buffer);
}
TEST(FormatToTest, FormatToMemoryBuffer) {
fmt::basic_memory_buffer<char, 100> buffer;
fmt::format_to(buffer, "{}", "foo");
EXPECT_EQ("foo", to_string(buffer));
}
TEST(FormatterTest, Escape) {
EXPECT_EQ("{", format("{{"));
EXPECT_EQ("before {", format("before {{"));
@ -321,6 +328,11 @@ TEST(FormatterTest, NamedArg) {
EXPECT_EQ(" -42", format("{0:{width}}", -42, fmt::arg("width", 4)));
EXPECT_EQ("st", format("{0:.{precision}}", "str", fmt::arg("precision", 2)));
EXPECT_EQ("1 2", format("{} {two}", 1, fmt::arg("two", 2)));
EXPECT_EQ("42", format("{c}",
fmt::arg("a", 0), fmt::arg("b", 0), fmt::arg("c", 42), fmt::arg("d", 0),
fmt::arg("e", 0), fmt::arg("f", 0), fmt::arg("g", 0), fmt::arg("h", 0),
fmt::arg("i", 0), fmt::arg("j", 0), fmt::arg("k", 0), fmt::arg("l", 0),
fmt::arg("m", 0), fmt::arg("n", 0), fmt::arg("o", 0), fmt::arg("p", 0)));
}
TEST(FormatterTest, AutoArgIndex) {
@ -435,6 +447,7 @@ TEST(FormatterTest, Fill) {
EXPECT_EQ("c****", format("{0:*<5}", 'c'));
EXPECT_EQ("abc**", format("{0:*<5}", "abc"));
EXPECT_EQ("**0xface", format("{0:*>8}", reinterpret_cast<void*>(0xface)));
EXPECT_EQ("foo=", format("{:}=", "foo"));
}
TEST(FormatterTest, PlusSign) {
@ -1024,7 +1037,7 @@ TEST(FormatterTest, FormatCString) {
EXPECT_EQ("test", format("{0:s}", "test"));
char nonconst[] = "nonconst";
EXPECT_EQ("nonconst", format("{0}", nonconst));
EXPECT_THROW_MSG(format("{0}", reinterpret_cast<const char*>(0)),
EXPECT_THROW_MSG(format("{0}", static_cast<const char*>(nullptr)),
format_error, "string pointer is null");
}
@ -1046,7 +1059,7 @@ TEST(FormatterTest, FormatUCharString) {
TEST(FormatterTest, FormatPointer) {
check_unknown_types(reinterpret_cast<void*>(0x1234), "p", "pointer");
EXPECT_EQ("0x0", format("{0}", reinterpret_cast<void*>(0)));
EXPECT_EQ("0x0", format("{0}", static_cast<void*>(nullptr)));
EXPECT_EQ("0x1234", format("{0}", reinterpret_cast<void*>(0x1234)));
EXPECT_EQ("0x1234", format("{0:p}", reinterpret_cast<void*>(0x1234)));
EXPECT_EQ("0x" + std::string(sizeof(void*) * CHAR_BIT / 4, 'f'),
@ -1109,7 +1122,8 @@ class Answer {};
FMT_BEGIN_NAMESPACE
template <>
struct formatter<Answer> : formatter<int> {
auto format(Answer, fmt::format_context &ctx) -> decltype(ctx.out()) {
template <typename FormatContext>
auto format(Answer, FormatContext &ctx) -> decltype(ctx.out()) {
return formatter<int>::format(42, ctx);
}
};
@ -1120,6 +1134,13 @@ TEST(FormatterTest, CustomFormat) {
EXPECT_EQ("0042", format("{:04}", Answer()));
}
TEST(FormatterTest, CustomFormatTo) {
char buf[10] = {};
auto end = fmt::format_to(buf, "{}", Answer());
EXPECT_EQ(end, buf + 2);
EXPECT_STREQ(buf, "42");
}
TEST(FormatterTest, WideFormatString) {
EXPECT_EQ(L"42", format(L"{}", 42));
EXPECT_EQ(L"4.2", format(L"{}", 4.2));
@ -1148,7 +1169,7 @@ TEST(FormatterTest, FormatExamples) {
FILE *ftest = safe_fopen(filename, "r");
if (ftest) fclose(ftest);
int error_code = errno;
EXPECT_TRUE(ftest == 0);
EXPECT_TRUE(ftest == nullptr);
EXPECT_SYSTEM_ERROR({
FILE *f = safe_fopen(filename, "r");
if (!f)
@ -1259,13 +1280,6 @@ TEST(FormatTest, Print) {
#endif
}
#if FMT_USE_FILE_DESCRIPTORS
TEST(FormatTest, PrintColored) {
EXPECT_WRITE(stdout, fmt::print_colored(fmt::red, "Hello, {}!\n", "world"),
"\x1b[31mHello, world!\n\x1b[0m");
}
#endif
TEST(FormatTest, Variadic) {
EXPECT_EQ("abc1", format("{}c{}", "ab", 1));
EXPECT_EQ(L"abc1", format(L"{}c{}", L"ab", 1));
@ -1309,7 +1323,7 @@ TEST(StrTest, Convert) {
EXPECT_EQ("2012-12-9", s);
}
std::string vformat_message(int id, const char *format, fmt::format_args args) {
static std::string vformat_message(int id, const char *format, fmt::format_args args) {
fmt::memory_buffer buffer;
format_to(buffer, "[{}] ", id);
vformat_to(buffer, format, args);
@ -1409,19 +1423,25 @@ class mock_arg_formatter:
EXPECT_CALL(*this, call(42));
}
using base::operator();
iterator operator()(int value) {
template <typename T>
typename std::enable_if<std::is_integral<T>::value, iterator>::type
operator()(T value) {
call(value);
return base::operator()(value);
}
template <typename T>
typename std::enable_if<!std::is_integral<T>::value, iterator>::type
operator()(T value) {
return base::operator()(value);
}
iterator operator()(fmt::basic_format_arg<fmt::format_context>::handle) {
return base::operator()(fmt::monostate());
}
};
void custom_vformat(fmt::string_view format_str, fmt::format_args args) {
static void custom_vformat(fmt::string_view format_str, fmt::format_args args) {
fmt::memory_buffer buffer;
fmt::vformat_to<mock_arg_formatter>(buffer, format_str, args);
}
@ -1518,6 +1538,15 @@ TEST(FormatTest, FormatToN) {
EXPECT_EQ("foox", fmt::string_view(buffer, 4));
}
TEST(FormatTest, WideFormatToN) {
wchar_t buffer[4];
buffer[3] = L'x';
auto result = fmt::format_to_n(buffer, 3, L"{}", 12345);
EXPECT_EQ(5u, result.size);
EXPECT_EQ(buffer + 3, result.out);
EXPECT_EQ(L"123x", fmt::wstring_view(buffer, 4));
}
#if FMT_USE_CONSTEXPR
struct test_arg_id_handler {
enum result { NONE, EMPTY, INDEX, NAME, ERROR };
@ -1794,12 +1823,14 @@ FMT_CONSTEXPR bool test_error(const char *fmt, const char *expected_error) {
return equal(actual_error, expected_error);
}
#define EXPECT_ERROR_NOARGS(fmt, error) \
static_assert(test_error(fmt, error), "")
#define EXPECT_ERROR(fmt, error, ...) \
static_assert(test_error<__VA_ARGS__>(fmt, error), "")
TEST(FormatTest, FormatStringErrors) {
EXPECT_ERROR("foo", nullptr);
EXPECT_ERROR("}", "unmatched '}' in format string");
EXPECT_ERROR_NOARGS("foo", nullptr);
EXPECT_ERROR_NOARGS("}", "unmatched '}' in format string");
EXPECT_ERROR("{0:s", "unknown format specifier", Date);
#ifndef _MSC_VER
// This causes an internal compiler error in MSVC2017.
@ -1807,7 +1838,7 @@ TEST(FormatTest, FormatStringErrors) {
EXPECT_ERROR("{:{<}", "invalid fill character '{'", int);
EXPECT_ERROR("{:10000000000}", "number is too big", int);
EXPECT_ERROR("{:.10000000000}", "number is too big", int);
EXPECT_ERROR("{:x}", "argument index out of range");
EXPECT_ERROR_NOARGS("{:x}", "argument index out of range");
EXPECT_ERROR("{:=}", "format specifier requires numeric argument",
const char *);
EXPECT_ERROR("{:+}", "format specifier requires numeric argument",
@ -1834,15 +1865,15 @@ TEST(FormatTest, FormatStringErrors) {
EXPECT_ERROR("{:s}", "invalid type specifier", void *);
#endif
EXPECT_ERROR("{foo", "missing '}' in format string", int);
EXPECT_ERROR("{10000000000}", "number is too big");
EXPECT_ERROR("{0x}", "invalid format string");
EXPECT_ERROR("{-}", "invalid format string");
EXPECT_ERROR_NOARGS("{10000000000}", "number is too big");
EXPECT_ERROR_NOARGS("{0x}", "invalid format string");
EXPECT_ERROR_NOARGS("{-}", "invalid format string");
EXPECT_ERROR("{:{0x}}", "invalid format string", int);
EXPECT_ERROR("{:{-}}", "invalid format string", int);
EXPECT_ERROR("{:.{0x}}", "invalid format string", int);
EXPECT_ERROR("{:.{-}}", "invalid format string", int);
EXPECT_ERROR("{:.x}", "missing precision specifier", int);
EXPECT_ERROR("{}", "argument index out of range");
EXPECT_ERROR_NOARGS("{}", "argument index out of range");
EXPECT_ERROR("{1}", "argument index out of range", int);
EXPECT_ERROR("{1}{}",
"cannot switch from manual to automatic argument indexing",

View File

@ -36,7 +36,7 @@
// This line ensures that gtest.h can be compiled on its own, even
// when it's fused.
#include "gtest/gtest.h"
#include "gtest.h"
// The following lines pull in the real gtest *.cc files.
// Copyright 2005, Google Inc.

View File

@ -235,7 +235,7 @@
// Most of the types needed for porting Google Mock are also required
// for Google Test and are defined in gtest-port.h.
#include "gtest/gtest.h"
#include "gtest.h"
// To avoid conditional compilation everywhere, we make it
// gmock-port.h's responsibility to #include the header implementing

View File

@ -340,10 +340,10 @@ TEST(OutputRedirectTest, FlushErrorInCtor) {
// Put a character in a file buffer.
EXPECT_EQ('x', fputc('x', f.get()));
FMT_POSIX(close(write_fd));
scoped_ptr<OutputRedirect> redir;
scoped_ptr<OutputRedirect> redir{nullptr};
EXPECT_SYSTEM_ERROR_NOASSERT(redir.reset(new OutputRedirect(f.get())),
EBADF, "cannot flush stream");
redir.reset();
redir.reset(nullptr);
write_copy.dup2(write_fd); // "undo" close or dtor will fail
}
@ -352,7 +352,7 @@ TEST(OutputRedirectTest, DupErrorInCtor) {
int fd = (f.fileno)();
file copy = file::dup(fd);
FMT_POSIX(close(fd));
scoped_ptr<OutputRedirect> redir;
scoped_ptr<OutputRedirect> redir{nullptr};
EXPECT_SYSTEM_ERROR_NOASSERT(redir.reset(new OutputRedirect(f.get())),
EBADF, fmt::format("cannot duplicate file descriptor {}", fd));
copy.dup2(fd); // "undo" close or dtor will fail
@ -403,7 +403,7 @@ TEST(OutputRedirectTest, ErrorInDtor) {
// output in EXPECT_STDERR and the second close will break output
// redirection.
FMT_POSIX(close(write_fd));
SUPPRESS_ASSERT(redir.reset());
SUPPRESS_ASSERT(redir.reset(nullptr));
}, format_system_error(EBADF, "cannot flush stream"));
write_copy.dup2(write_fd); // "undo" close or dtor of buffered_file will fail
}

View File

@ -75,7 +75,7 @@ std::string read(file &f, std::size_t count) {
do {
n = f.read(&buffer[offset], count - offset);
// We can't read more than size_t bytes since count has type size_t.
offset += static_cast<std::size_t>(n);
offset += n;
} while (offset < count && n != 0);
buffer.resize(offset);
return buffer;

View File

@ -9,7 +9,7 @@
#define FMT_GTEST_EXTRA_H_
#include <string>
#include <gmock/gmock.h>
#include "gmock.h"
#include "fmt/core.h"
@ -155,7 +155,7 @@ std::string read(fmt::file &f, std::size_t count);
template <typename Mock>
struct ScopedMock : testing::StrictMock<Mock> {
ScopedMock() { Mock::instance = this; }
~ScopedMock() { Mock::instance = 0; }
~ScopedMock() { Mock::instance = nullptr; }
};
#endif // FMT_GTEST_EXTRA_H_

View File

@ -8,7 +8,7 @@
#ifndef FMT_MOCK_ALLOCATOR_H_
#define FMT_MOCK_ALLOCATOR_H_
#include "gmock/gmock.h"
#include "gmock.h"
template <typename T>
class MockAllocator {
@ -28,7 +28,7 @@ class AllocatorRef {
public:
typedef typename Allocator::value_type value_type;
explicit AllocatorRef(Allocator *alloc = 0) : alloc_(alloc) {}
explicit AllocatorRef(Allocator *alloc = nullptr) : alloc_(alloc) {}
AllocatorRef(const AllocatorRef &other) : alloc_(other.alloc_) {}
@ -41,7 +41,7 @@ class AllocatorRef {
private:
void move(AllocatorRef &other) {
alloc_ = other.alloc_;
other.alloc_ = 0;
other.alloc_ = nullptr;
}
public:

View File

@ -8,29 +8,29 @@
#include "fmt/ostream.h"
#include <sstream>
#include "gmock/gmock.h"
#include "gmock.h"
#include "gtest-extra.h"
#include "util.h"
using fmt::format;
using fmt::format_error;
std::ostream &operator<<(std::ostream &os, const Date &d) {
static std::ostream &operator<<(std::ostream &os, const Date &d) {
os << d.year() << '-' << d.month() << '-' << d.day();
return os;
}
std::wostream &operator<<(std::wostream &os, const Date &d) {
static std::wostream &operator<<(std::wostream &os, const Date &d) {
os << d.year() << L'-' << d.month() << L'-' << d.day();
return os;
}
enum TestEnum {};
std::ostream &operator<<(std::ostream &os, TestEnum) {
static std::ostream &operator<<(std::ostream &os, TestEnum) {
return os << "TestEnum";
}
std::wostream &operator<<(std::wostream &os, TestEnum) {
static std::wostream &operator<<(std::wostream &os, TestEnum) {
return os << L"TestEnum";
}
@ -95,7 +95,7 @@ TEST(OStreamTest, FormatSpecs) {
}
struct EmptyTest {};
std::ostream &operator<<(std::ostream &os, EmptyTest) {
static std::ostream &operator<<(std::ostream &os, EmptyTest) {
return os << "";
}
@ -145,7 +145,7 @@ TEST(OStreamTest, WriteToOStreamMaxSize) {
} os(streambuf);
testing::InSequence sequence;
const char *data = 0;
const char *data = nullptr;
std::size_t size = max_size;
do {
typedef std::make_unsigned<std::streamsize>::type ustreamsize;
@ -154,7 +154,7 @@ TEST(OStreamTest, WriteToOStreamMaxSize) {
EXPECT_CALL(streambuf, xsputn(data, static_cast<std::streamsize>(n)))
.WillOnce(testing::Return(max_streamsize));
data += n;
size -= static_cast<std::size_t>(n);
size -= n;
} while (size != 0);
fmt::internal::write(os, buffer);
}
@ -163,3 +163,9 @@ TEST(OStreamTest, Join) {
int v[3] = {1, 2, 3};
EXPECT_EQ("1, 2, 3", fmt::format("{}", fmt::join(v, v + 3, ", ")));
}
#if FMT_USE_CONSTEXPR
TEST(OStreamTest, ConstexprString) {
EXPECT_EQ("42", format(fmt("{}"), std::string("42")));
}
#endif

View File

@ -6,7 +6,9 @@
// For the license information refer to format.h.
// Disable bogus MSVC warnings.
#define _CRT_SECURE_NO_WARNINGS
#ifdef _MSC_VER
# define _CRT_SECURE_NO_WARNINGS
#endif
#include "posix-mock.h"
#include "../src/posix.cc"
@ -21,7 +23,7 @@
# undef ERROR
#endif
#include "gmock/gmock.h"
#include "gmock.h"
#include "gtest-extra.h"
#include "util.h"
@ -131,7 +133,7 @@ int test::dup2(int fildes, int fildes2) {
}
FILE *test::fdopen(int fildes, const char *mode) {
EMULATE_EINTR(fdopen, 0);
EMULATE_EINTR(fdopen, nullptr);
return ::FMT_POSIX(fdopen(fildes, mode));
}
@ -160,7 +162,7 @@ int test::pipe(int *pfds, unsigned psize, int textmode) {
#endif
FILE *test::fopen(const char *filename, const char *mode) {
EMULATE_EINTR(fopen, 0);
EMULATE_EINTR(fopen, nullptr);
return ::fopen(filename, mode);
}
@ -193,7 +195,7 @@ int (test::fileno)(FILE *stream) {
# define EXPECT_EQ_POSIX(expected, actual)
#endif
void write_file(fmt::cstring_view filename, fmt::string_view content) {
static void write_file(fmt::cstring_view filename, fmt::string_view content) {
fmt::buffered_file f(filename, "w");
f.print("{}", content);
}
@ -214,7 +216,7 @@ TEST(UtilTest, GetPageSize) {
TEST(FileTest, OpenRetry) {
write_file("test", "there must be something here");
scoped_ptr<file> f;
scoped_ptr<file> f{nullptr};
EXPECT_RETRY(f.reset(new file("test", file::RDONLY)),
open, "cannot open file test");
#ifndef _WIN32
@ -230,7 +232,7 @@ TEST(FileTest, CloseNoRetryInDtor) {
int saved_close_count = 0;
EXPECT_WRITE(stderr, {
close_count = 1;
f.reset();
f.reset(nullptr);
saved_close_count = close_count;
close_count = 0;
}, format_system_error(EINTR, "cannot close file") + "\n");
@ -383,7 +385,7 @@ TEST(FileTest, FdopenNoRetry) {
TEST(BufferedFileTest, OpenRetry) {
write_file("test", "there must be something here");
scoped_ptr<buffered_file> f;
scoped_ptr<buffered_file> f{nullptr};
EXPECT_RETRY(f.reset(new buffered_file("test", "r")),
fopen, "cannot open file test");
#ifndef _WIN32
@ -400,7 +402,7 @@ TEST(BufferedFileTest, CloseNoRetryInDtor) {
int saved_fclose_count = 0;
EXPECT_WRITE(stderr, {
fclose_count = 1;
f.reset();
f.reset(nullptr);
saved_fclose_count = fclose_count;
fclose_count = 0;
}, format_system_error(EINTR, "cannot close file") + "\n");
@ -436,8 +438,9 @@ TEST(ScopedMock, Scope) {
ScopedMock<TestMock> mock;
EXPECT_EQ(&mock, TestMock::instance);
TestMock &copy = mock;
static_cast<void>(copy);
}
EXPECT_EQ(0, TestMock::instance);
EXPECT_EQ(nullptr, TestMock::instance);
}
#ifdef FMT_LOCALE
@ -472,7 +475,13 @@ double _strtod_l(const char *nptr, char **endptr, _locale_t locale) {
# pragma warning(pop)
#endif
LocaleType newlocale(int category_mask, const char *locale, LocaleType base) {
#if defined(__THROW) && FMT_GCC_VERSION > 0 && FMT_GCC_VERSION <= 408
#define FMT_LOCALE_THROW __THROW
#else
#define FMT_LOCALE_THROW
#endif
LocaleType newlocale(int category_mask, const char *locale, LocaleType base) FMT_LOCALE_THROW {
return LocaleMock::instance->newlocale(category_mask, locale, base);
}
@ -482,15 +491,17 @@ typedef int FreeLocaleResult;
typedef void FreeLocaleResult;
#endif
FreeLocaleResult freelocale(LocaleType locale) {
FreeLocaleResult freelocale(LocaleType locale) FMT_LOCALE_THROW {
LocaleMock::instance->freelocale(locale);
return FreeLocaleResult();
}
double strtod_l(const char *nptr, char **endptr, LocaleType locale) {
double strtod_l(const char *nptr, char **endptr, LocaleType locale) FMT_LOCALE_THROW {
return LocaleMock::instance->strtod_l(nptr, endptr, locale);
}
#undef FMT_LOCALE_THROW
TEST(LocaleTest, LocaleMock) {
ScopedMock<LocaleMock> mock;
LocaleType locale = reinterpret_cast<LocaleType>(11);
@ -504,7 +515,7 @@ TEST(LocaleTest, Locale) {
#endif
ScopedMock<LocaleMock> mock;
LocaleType impl = reinterpret_cast<LocaleType>(42);
EXPECT_CALL(mock, newlocale(LC_NUMERIC_MASK, StrEq("C"), 0))
EXPECT_CALL(mock, newlocale(LC_NUMERIC_MASK, StrEq("C"), nullptr))
.WillOnce(Return(impl));
EXPECT_CALL(mock, freelocale(impl));
fmt::Locale locale;

View File

@ -23,12 +23,12 @@ using fmt::file;
using testing::internal::scoped_ptr;
// Checks if the file is open by reading one character from it.
bool isopen(int fd) {
static bool isopen(int fd) {
char buffer;
return FMT_POSIX(read(fd, &buffer, 1)) == 1;
}
bool isclosed(int fd) {
static bool isclosed(int fd) {
char buffer;
std::streamsize result = 0;
SUPPRESS_ASSERT(result = FMT_POSIX(read(fd, &buffer, 1)));
@ -36,7 +36,7 @@ bool isclosed(int fd) {
}
// Opens a file for reading.
file open_file() {
static file open_file() {
file read_end, write_end;
file::pipe(read_end, write_end);
write_end.write(FILE_CONTENT, std::strlen(FILE_CONTENT));
@ -45,7 +45,7 @@ file open_file() {
}
// Attempts to write a string to a file.
void write(file &f, fmt::string_view s) {
static void write(file &f, fmt::string_view s) {
std::size_t num_chars_left = s.size();
const char *ptr = s.data();
do {
@ -53,32 +53,32 @@ void write(file &f, fmt::string_view s) {
ptr += count;
// We can't write more than size_t bytes since num_chars_left
// has type size_t.
num_chars_left -= static_cast<std::size_t>(count);
num_chars_left -= count;
} while (num_chars_left != 0);
}
TEST(BufferedFileTest, DefaultCtor) {
buffered_file f;
EXPECT_TRUE(f.get() == 0);
EXPECT_TRUE(f.get() == nullptr);
}
TEST(BufferedFileTest, MoveCtor) {
buffered_file bf = open_buffered_file();
FILE *fp = bf.get();
EXPECT_TRUE(fp != 0);
EXPECT_TRUE(fp != nullptr);
buffered_file bf2(std::move(bf));
EXPECT_EQ(fp, bf2.get());
EXPECT_TRUE(bf.get() == 0);
EXPECT_TRUE(bf.get() == nullptr);
}
TEST(BufferedFileTest, MoveAssignment) {
buffered_file bf = open_buffered_file();
FILE *fp = bf.get();
EXPECT_TRUE(fp != 0);
EXPECT_TRUE(fp != nullptr);
buffered_file bf2;
bf2 = std::move(bf);
EXPECT_EQ(fp, bf2.get());
EXPECT_TRUE(bf.get() == 0);
EXPECT_TRUE(bf.get() == nullptr);
}
TEST(BufferedFileTest, MoveAssignmentClosesFile) {
@ -90,13 +90,13 @@ TEST(BufferedFileTest, MoveAssignmentClosesFile) {
}
TEST(BufferedFileTest, MoveFromTemporaryInCtor) {
FILE *fp = 0;
FILE *fp = nullptr;
buffered_file f(open_buffered_file(&fp));
EXPECT_EQ(fp, f.get());
}
TEST(BufferedFileTest, MoveFromTemporaryInAssignment) {
FILE *fp = 0;
FILE *fp = nullptr;
buffered_file f;
f = open_buffered_file(&fp);
EXPECT_EQ(fp, f.get());
@ -126,7 +126,7 @@ TEST(BufferedFileTest, CloseErrorInDtor) {
// output in EXPECT_STDERR and the second close will break output
// redirection.
FMT_POSIX(close(f->fileno()));
SUPPRESS_ASSERT(f.reset());
SUPPRESS_ASSERT(f.reset(nullptr));
}, format_system_error(EBADF, "cannot close file") + "\n");
}
@ -134,7 +134,7 @@ TEST(BufferedFileTest, Close) {
buffered_file f = open_buffered_file();
int fd = f.fileno();
f.close();
EXPECT_TRUE(f.get() == 0);
EXPECT_TRUE(f.get() == nullptr);
EXPECT_TRUE(isclosed(fd));
}
@ -142,7 +142,7 @@ TEST(BufferedFileTest, CloseError) {
buffered_file f = open_buffered_file();
FMT_POSIX(close(f.fileno()));
EXPECT_SYSTEM_ERROR_NOASSERT(f.close(), EBADF, "cannot close file");
EXPECT_TRUE(f.get() == 0);
EXPECT_TRUE(f.get() == nullptr);
}
TEST(BufferedFileTest, Fileno) {
@ -153,7 +153,7 @@ TEST(BufferedFileTest, Fileno) {
EXPECT_DEATH_IF_SUPPORTED({
try {
f.fileno();
} catch (fmt::system_error) {
} catch (const fmt::system_error&) {
std::exit(1);
}
}, "");
@ -209,7 +209,7 @@ TEST(FileTest, MoveAssignmentClosesFile) {
EXPECT_TRUE(isclosed(old_fd));
}
file OpenBufferedFile(int &fd) {
static file OpenBufferedFile(int &fd) {
file f = open_file();
fd = f.descriptor();
return f;
@ -253,7 +253,7 @@ TEST(FileTest, CloseErrorInDtor) {
// output in EXPECT_STDERR and the second close will break output
// redirection.
FMT_POSIX(close(f->descriptor()));
SUPPRESS_ASSERT(f.reset());
SUPPRESS_ASSERT(f.reset(nullptr));
}, format_system_error(EBADF, "cannot close file") + "\n");
}

View File

@ -20,13 +20,13 @@ using fmt::format_error;
const unsigned BIG_NUM = INT_MAX + 1u;
// Makes format string argument positional.
std::string make_positional(fmt::string_view format) {
static std::string make_positional(fmt::string_view format) {
std::string s(format.data(), format.size());
s.replace(s.find('%'), 1, "%1$");
return s;
}
std::wstring make_positional(fmt::wstring_view format) {
static std::wstring make_positional(fmt::wstring_view format) {
std::wstring s(format.data(), format.size());
s.replace(s.find(L'%'), 1, L"%1$");
return s;
@ -410,7 +410,7 @@ TEST(PrintfTest, Inf) {
double inf = std::numeric_limits<double>::infinity();
for (const char* type = "fega"; *type; ++type) {
EXPECT_PRINTF("inf", fmt::format("%{}", *type), inf);
char upper = std::toupper(*type);
char upper = static_cast<char>(std::toupper(*type));
EXPECT_PRINTF("INF", fmt::format("%{}", upper), inf);
}
}
@ -426,11 +426,11 @@ TEST(PrintfTest, Char) {
TEST(PrintfTest, String) {
EXPECT_PRINTF("abc", "%s", "abc");
const char *null_str = 0;
const char *null_str = nullptr;
EXPECT_PRINTF("(null)", "%s", null_str);
EXPECT_PRINTF(" (null)", "%10s", null_str);
EXPECT_PRINTF(L"abc", L"%s", L"abc");
const wchar_t *null_wstr = 0;
const wchar_t *null_wstr = nullptr;
EXPECT_PRINTF(L"(null)", L"%s", null_wstr);
EXPECT_PRINTF(L" (null)", L"%10s", null_wstr);
}
@ -439,22 +439,22 @@ TEST(PrintfTest, Pointer) {
int n;
void *p = &n;
EXPECT_PRINTF(fmt::format("{}", p), "%p", p);
p = 0;
p = nullptr;
EXPECT_PRINTF("(nil)", "%p", p);
EXPECT_PRINTF(" (nil)", "%10p", p);
const char *s = "test";
EXPECT_PRINTF(fmt::format("{:p}", s), "%p", s);
const char *null_str = 0;
const char *null_str = nullptr;
EXPECT_PRINTF("(nil)", "%p", null_str);
p = &n;
EXPECT_PRINTF(fmt::format(L"{}", p), L"%p", p);
p = 0;
p = nullptr;
EXPECT_PRINTF(L"(nil)", L"%p", p);
EXPECT_PRINTF(L" (nil)", L"%10p", p);
const wchar_t *w = L"test";
EXPECT_PRINTF(fmt::format(L"{:p}", w), L"%p", w);
const wchar_t *null_wstr = 0;
const wchar_t *null_wstr = nullptr;
EXPECT_PRINTF(L"(nil)", L"%p", null_wstr);
}

View File

@ -11,7 +11,11 @@
#include "fmt/ranges.h"
#include "gtest/gtest.h"
/// Check if 'if constexpr' is supported.
#if (__cplusplus > 201402L) || \
(defined(_MSVC_LANG) && _MSVC_LANG > 201402L && _MSC_VER >= 1910)
#include "gtest.h"
#include <vector>
#include <array>
@ -30,10 +34,9 @@ TEST(RangesTest, FormatVector2) {
EXPECT_EQ("{{1, 2}, {3, 5}, {7, 11}}", ivf);
}
#if FMT_USE_INTEGER_SEQUENCE
TEST(RangesTest, FormatMap) {
std::map<std::string, int32_t> simap{{"one", 1}, {"two", 2}};
EXPECT_EQ("{(one, 1), (two, 2)}", fmt::format("{}", simap));
EXPECT_EQ("{(\"one\", 1), (\"two\", 2)}", fmt::format("{}", simap));
}
TEST(RangesTest, FormatPair) {
@ -42,15 +45,11 @@ TEST(RangesTest, FormatPair) {
}
TEST(RangesTest, FormatTuple) {
std::tuple<int64_t, float, std::string> tu1{42, 3.14159265358979f,
"this is tuple"};
EXPECT_EQ("(42, 3.14159, this is tuple)", fmt::format("{}", tu1));
std::tuple<int64_t, float, std::string, char> tu1{42, 3.14159265358979f,
"this is tuple", 'i'};
EXPECT_EQ("(42, 3.14159, \"this is tuple\", 'i')", fmt::format("{}", tu1));
}
/// Check if 'if constexpr' is supported.
#if (__cplusplus > 201402L) || \
(defined(_MSVC_LANG) && _MSVC_LANG > 201402L && _MSC_VER >= 1910)
struct my_struct {
int32_t i;
std::string str; // can throw
@ -82,9 +81,8 @@ struct tuple_element<N, my_struct> {
TEST(RangesTest, FormatStruct) {
my_struct mst{13, "my struct"};
EXPECT_EQ("(13, my struct)", fmt::format("{}", mst));
EXPECT_EQ("(13, \"my struct\")", fmt::format("{}", mst));
}
#endif // (__cplusplus > 201402L) || (defined(_MSVC_LANG) && _MSVC_LANG >
// 201402L && _MSC_VER >= 1910)
#endif // FMT_USE_INTEGER_SEQUENCE

View File

@ -6,7 +6,7 @@
// For the license information refer to format.h.
#include <cstdlib>
#include <gtest/gtest.h>
#include "gtest.h"
#ifdef _WIN32
# include <windows.h>

View File

@ -9,7 +9,7 @@
#define _CRT_SECURE_NO_WARNINGS
#endif
#include "gmock/gmock.h"
#include "gmock.h"
#include "fmt/time.h"
TEST(TimeTest, Format) {
@ -26,7 +26,7 @@ TEST(TimeTest, GrowBuffer) {
for (int i = 0; i < 30; ++i)
s += "%c";
s += "}\n";
std::time_t t = std::time(0);
std::time_t t = std::time(nullptr);
fmt::format(s, *std::localtime(&t));
}
@ -34,7 +34,7 @@ TEST(TimeTest, EmptyResult) {
EXPECT_EQ("", fmt::format("{}", std::tm()));
}
bool EqualTime(const std::tm &lhs, const std::tm &rhs) {
static bool EqualTime(const std::tm &lhs, const std::tm &rhs) {
return lhs.tm_sec == rhs.tm_sec &&
lhs.tm_min == rhs.tm_min &&
lhs.tm_hour == rhs.tm_hour &&
@ -47,13 +47,13 @@ bool EqualTime(const std::tm &lhs, const std::tm &rhs) {
}
TEST(TimeTest, LocalTime) {
std::time_t t = std::time(0);
std::time_t t = std::time(nullptr);
std::tm tm = *std::localtime(&t);
EXPECT_TRUE(EqualTime(tm, fmt::localtime(t)));
}
TEST(TimeTest, GMTime) {
std::time_t t = std::time(0);
std::time_t t = std::time(nullptr);
std::tm tm = *std::gmtime(&t);
EXPECT_TRUE(EqualTime(tm, fmt::gmtime(t)));
}

View File

@ -17,7 +17,7 @@
# include <type_traits>
#endif
#include "gmock/gmock.h"
#include "gmock.h"
#include "gtest-extra.h"
#include "mock-allocator.h"
#include "util.h"
@ -71,8 +71,8 @@ struct formatter<Test, Char> {
};
FMT_END_NAMESPACE
void CheckForwarding(
MockAllocator<int> &alloc, AllocatorRef< MockAllocator<int> > &ref) {
static void CheckForwarding(
MockAllocator<int> &alloc, AllocatorRef<MockAllocator<int>> &ref) {
int mem;
// Check if value_type is properly defined.
AllocatorRef< MockAllocator<int> >::value_type *ptr = &mem;
@ -92,7 +92,7 @@ TEST(AllocatorTest, AllocatorRef) {
TestAllocatorRef ref2(ref);
CheckForwarding(alloc, ref2);
TestAllocatorRef ref3;
EXPECT_EQ(0, ref3.get());
EXPECT_EQ(nullptr, ref3.get());
ref3 = ref;
CheckForwarding(alloc, ref3);
}
@ -112,7 +112,7 @@ TEST(BufferTest, Nonmoveable) {
// A test buffer with a dummy grow method.
template <typename T>
struct TestBuffer : basic_buffer<T> {
void grow(std::size_t capacity) { this->set(0, capacity); }
void grow(std::size_t capacity) { this->set(nullptr, capacity); }
};
template <typename T>
@ -132,23 +132,23 @@ struct MockBuffer : basic_buffer<T> {
TEST(BufferTest, Ctor) {
{
MockBuffer<int> buffer;
EXPECT_EQ(0, &buffer[0]);
EXPECT_EQ(0u, buffer.size());
EXPECT_EQ(0u, buffer.capacity());
EXPECT_EQ(nullptr, &buffer[0]);
EXPECT_EQ(static_cast<size_t>(0), buffer.size());
EXPECT_EQ(static_cast<size_t>(0), buffer.capacity());
}
{
int dummy;
MockBuffer<int> buffer(&dummy);
EXPECT_EQ(&dummy, &buffer[0]);
EXPECT_EQ(0u, buffer.size());
EXPECT_EQ(0u, buffer.capacity());
EXPECT_EQ(static_cast<size_t>(0), buffer.size());
EXPECT_EQ(static_cast<size_t>(0), buffer.capacity());
}
{
int dummy;
std::size_t capacity = std::numeric_limits<std::size_t>::max();
MockBuffer<int> buffer(&dummy, capacity);
EXPECT_EQ(&dummy, &buffer[0]);
EXPECT_EQ(0u, buffer.size());
EXPECT_EQ(static_cast<size_t>(0), buffer.size());
EXPECT_EQ(capacity, buffer.capacity());
}
}
@ -201,7 +201,7 @@ TEST(BufferTest, Clear) {
TestBuffer<char> buffer;
buffer.resize(20);
buffer.resize(0);
EXPECT_EQ(0u, buffer.size());
EXPECT_EQ(static_cast<size_t>(0), buffer.size());
EXPECT_EQ(20u, buffer.capacity());
}
@ -231,7 +231,7 @@ TEST(BufferTest, AppendAllocatesEnoughStorage) {
TEST(MemoryBufferTest, Ctor) {
basic_memory_buffer<char, 123> buffer;
EXPECT_EQ(0u, buffer.size());
EXPECT_EQ(static_cast<size_t>(0), buffer.size());
EXPECT_EQ(123u, buffer.capacity());
}
@ -239,7 +239,7 @@ TEST(MemoryBufferTest, Ctor) {
typedef AllocatorRef< std::allocator<char> > TestAllocator;
void check_move_buffer(const char *str,
static void check_move_buffer(const char *str,
basic_memory_buffer<char, 5, TestAllocator> &buffer) {
std::allocator<char> *alloc = buffer.get_allocator().get();
basic_memory_buffer<char, 5, TestAllocator> buffer2(std::move(buffer));
@ -248,7 +248,7 @@ void check_move_buffer(const char *str,
EXPECT_EQ(str, std::string(&buffer2[0], buffer2.size()));
EXPECT_EQ(5u, buffer2.capacity());
// Move should transfer allocator.
EXPECT_EQ(0, buffer.get_allocator().get());
EXPECT_EQ(nullptr, buffer.get_allocator().get());
EXPECT_EQ(alloc, buffer2.get_allocator().get());
}
@ -273,7 +273,7 @@ TEST(MemoryBufferTest, MoveCtor) {
EXPECT_GT(buffer2.capacity(), 5u);
}
void check_move_assign_buffer(
static void check_move_assign_buffer(
const char *str, basic_memory_buffer<char, 5> &buffer) {
basic_memory_buffer<char, 5> buffer2;
buffer2 = std::move(buffer);
@ -335,7 +335,7 @@ TEST(MemoryBufferTest, Grow) {
TEST(MemoryBufferTest, Allocator) {
typedef AllocatorRef< MockAllocator<char> > TestAllocator;
basic_memory_buffer<char, 10, TestAllocator> buffer;
EXPECT_EQ(0, buffer.get_allocator().get());
EXPECT_EQ(nullptr, buffer.get_allocator().get());
StrictMock< MockAllocator<char> > alloc;
char mem;
{
@ -376,7 +376,7 @@ TEST(MemoryBufferTest, ExceptionInDeallocate) {
TEST(FixedBufferTest, Ctor) {
char array[10] = "garbage";
fmt::basic_fixed_buffer<char> buffer(array, sizeof(array));
EXPECT_EQ(0u, buffer.size());
EXPECT_EQ(static_cast<size_t>(0), buffer.size());
EXPECT_EQ(10u, buffer.capacity());
EXPECT_EQ(array, buffer.data());
}
@ -384,7 +384,7 @@ TEST(FixedBufferTest, Ctor) {
TEST(FixedBufferTest, CompileTimeSizeCtor) {
char array[10] = "garbage";
fmt::basic_fixed_buffer<char> buffer(array);
EXPECT_EQ(0u, buffer.size());
EXPECT_EQ(static_cast<size_t>(0), buffer.size());
EXPECT_EQ(10u, buffer.capacity());
EXPECT_EQ(array, buffer.data());
}
@ -402,7 +402,7 @@ struct uint32_pair {
TEST(UtilTest, BitCast) {
auto s = fmt::internal::bit_cast<uint32_pair>(uint64_t{42});
EXPECT_EQ(fmt::internal::bit_cast<uint64_t>(s), 42u);
EXPECT_EQ(fmt::internal::bit_cast<uint64_t>(s), 42ull);
s = fmt::internal::bit_cast<uint32_pair>(uint64_t(~0ull));
EXPECT_EQ(fmt::internal::bit_cast<uint64_t>(s), ~0ull);
}
@ -439,7 +439,7 @@ struct custom_context {
const char *format(const T &, custom_context& ctx) {
ctx.called = true;
return 0;
return nullptr;
}
};
};
@ -583,8 +583,8 @@ TEST(UtilTest, WStringArg) {
}
TEST(UtilTest, PointerArg) {
void *p = 0;
const void *cp = 0;
void *p = nullptr;
const void *cp = nullptr;
CHECK_ARG_(char, cp, p);
CHECK_ARG_(wchar_t, cp, p);
CHECK_ARG(cp, );
@ -765,14 +765,14 @@ TEST(UtilTest, FormatSystemError) {
try {
std::allocator<char> alloc;
alloc.deallocate(alloc.allocate(max_size), max_size);
} catch (std::bad_alloc) {
} catch (const std::bad_alloc&) {
throws_on_alloc = true;
}
if (!throws_on_alloc) {
fmt::print("warning: std::allocator allocates {} chars", max_size);
return;
}
fmt::format_system_error(message, EDOM, fmt::string_view(0, max_size));
fmt::format_system_error(message, EDOM, fmt::string_view(nullptr, max_size));
EXPECT_EQ(fmt::format("error {}", EDOM), to_string(message));
}
@ -822,7 +822,8 @@ TEST(UtilTest, FormatLongWindowsError) {
const int provisioning_not_allowed = 0x80284013L /*TBS_E_PROVISIONING_NOT_ALLOWED*/;
if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 0,
provisioning_not_allowed, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
static_cast<DWORD>(provisioning_not_allowed),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
reinterpret_cast<LPWSTR>(&message), 0, 0) == 0) {
return;
}
@ -867,7 +868,7 @@ TEST(UtilTest, IsEnumConvertibleToInt) {
#endif
TEST(UtilTest, ParseNonnegativeInt) {
if (std::numeric_limits<int>::max() != (1 << 31)) {
if (std::numeric_limits<int>::max() != static_cast<int>(static_cast<unsigned>(1) << 31)) {
fmt::print("Skipping parse_nonnegative_int test\n");
return;
}
@ -881,17 +882,67 @@ TEST(UtilTest, ParseNonnegativeInt) {
fmt::format_error, "number is too big");
}
TEST(UtilTest, FPSubtract) {
auto r = fp(123, 1) - fp(102, 1);
EXPECT_EQ(r.f, 21u);
EXPECT_EQ(r.e, 1);
template <bool is_iec559>
void test_construct_from_double() {
fmt::print("warning: double is not IEC559, skipping FP tests\n");
}
TEST(UtilTest, FPMultiply) {
auto r = fp(123ULL << 32, 4) * fp(56ULL << 32, 7);
EXPECT_EQ(r.f, 123u * 56u);
EXPECT_EQ(r.e, 4 + 7 + 64);
r = fp(123ULL << 32, 4) * fp(567ULL << 31, 8);
EXPECT_EQ(r.f, (123 * 567 + 1u) / 2);
EXPECT_EQ(r.e, 4 + 8 + 64);
template <>
void test_construct_from_double<true>() {
auto v = fp(1.23);
EXPECT_EQ(v.f, 0x13ae147ae147aeu);
EXPECT_EQ(v.e, -52);
}
TEST(FPTest, ConstructFromDouble) {
test_construct_from_double<std::numeric_limits<double>::is_iec559>();
}
TEST(FPTest, Normalize) {
auto v = fp(0xbeef, 42);
v.normalize();
EXPECT_EQ(0xbeef000000000000, v.f);
EXPECT_EQ(-6, v.e);
}
TEST(FPTest, Subtract) {
auto v = fp(123, 1) - fp(102, 1);
EXPECT_EQ(v.f, 21u);
EXPECT_EQ(v.e, 1);
}
TEST(FPTest, Multiply) {
auto v = fp(123ULL << 32, 4) * fp(56ULL << 32, 7);
EXPECT_EQ(v.f, 123u * 56u);
EXPECT_EQ(v.e, 4 + 7 + 64);
v = fp(123ULL << 32, 4) * fp(567ULL << 31, 8);
EXPECT_EQ(v.f, (123 * 567 + 1u) / 2);
EXPECT_EQ(v.e, 4 + 8 + 64);
}
TEST(FPTest, GetCachedPower) {
typedef std::numeric_limits<double> limits;
for (auto exp = limits::min_exponent; exp <= limits::max_exponent; ++exp) {
int dec_exp = 0;
auto fp = fmt::internal::get_cached_power(exp, dec_exp);
EXPECT_LE(exp, fp.e);
int dec_exp_step = 8;
EXPECT_LE(fp.e, exp + dec_exp_step * log2(10));
EXPECT_DOUBLE_EQ(pow(10, dec_exp), ldexp(fp.f, fp.e));
}
}
TEST(IteratorTest, CountingIterator) {
fmt::internal::counting_iterator<char> it;
auto prev = it++;
EXPECT_EQ(prev.count(), 0);
EXPECT_EQ(it.count(), 1);
}
TEST(IteratorTest, TruncatingIterator) {
char *p = FMT_NULL;
fmt::internal::truncating_iterator<char*> it(p, 3);
auto prev = it++;
EXPECT_EQ(prev.base(), p);
EXPECT_EQ(it.base(), p + 1);
}

View File

@ -35,7 +35,7 @@ std::string get_system_error(int error_code);
extern const char *const FILE_CONTENT;
// Opens a buffered file for reading.
fmt::buffered_file open_buffered_file(FILE **fp = 0);
fmt::buffered_file open_buffered_file(FILE **fp = nullptr);
inline FILE *safe_fopen(const char *filename, const char *mode) {
#if defined(_WIN32) && !defined(__MINGW32__)