Compare commits

..

31 Commits
3.0.1 ... 3.0.2

Author SHA1 Message Date
Jonathan Müller
5708bf8fcc Update changelog 2017-06-14 18:05:24 +02:00
Rich E
fbd871e433 added FMT_API declarations where needed when using FMT_EXPORT from a separate dll
(cherry picked from commit ad6d78f2a8)
2017-06-09 13:33:59 +02:00
Andreas Schönle
5bce2c0cef Allow compiling and using as DLL in windows (#502)
* fix warnings and errors in test compiles with BUILD_SHARED_LIBS

* did requested changes and added one change to allow all tests to succeed
in windows DLL

(cherry picked from commit 79f11dbaa7)
2017-06-09 12:42:32 +02:00
Tomek Rozen
c75f6dcd30 Changing ArgArray template argument from unsigned to size_t
Each instantiation of ArgArray template uses sizeof operator, which
returns a std::size_t value. GCC 7.1 warns about invalid conversion
(error: conversion to ‘unsigned int’ from ‘long unsigned
int’ may alter its value [-Werror=conversion]).

(cherry picked from commit e14bac62a0)
2017-06-08 12:08:50 +02:00
Victor Zverovich
ecd0994c15 Use Ubuntu Trusty on Travis for a new CMake
(cherry picked from commit 0284a2893a)
2017-06-08 12:08:50 +02:00
Victor Zverovich
7859c3493f Fix handling of implicit conversion to integral types larger than int (#507)
(cherry picked from commit 07ed421521)
2017-06-08 12:08:50 +02:00
Victor Zverovich
4fca31c497 Don't define WIN32_LEAN_AND_MEAN in header-only mode
(cherry picked from commit c56d345985)
2017-06-08 12:08:50 +02:00
Jonathan Müller
e6df023916 Workaround MSVC lookup issue in ArgFormatterBase
Fixes #505.

(cherry picked from commit 52aabbe7ef)
2017-06-08 12:08:50 +02:00
Quentin Buathier
1934d9e5d9 Don't include the world with WIN32_LEAN_AND_MEAN (#503)
(cherry picked from commit 4423490d0b)
2017-06-08 12:08:50 +02:00
Victor Zverovich
9270e66700 Remove redundant include (#479)
(cherry picked from commit cc736e7611)
2017-06-08 11:33:01 +02:00
Victor Zverovich
9589bf05de Fix error on MinGW
(cherry picked from commit db0d54f855)
2017-06-08 11:32:49 +02:00
Victor Zverovich
aad76bf4c1 Document which header defines formatting functions
(cherry picked from commit e208fbff52)
2017-06-08 11:32:39 +02:00
Magnus Bjerke Vik
0bed09caaf Fix Android not being detected with latest NDK toolchain (#458)
When using the NDK 13b toolchain standalone or with CMake, ANDROID is not defined,
but __ANDROID__ is defined instead.

(cherry picked from commit bc6af7548b)
2017-06-08 11:29:36 +02:00
Victor Zverovich
0e5a4422c2 Workaround an nvcc bug
(cherry picked from commit 9e9ad57f58)
2017-06-08 11:29:32 +02:00
Calum Robinson
72484cc191 Fix missing intrinsic when included from C++/CLI
Managed C++ code doesn't have the _BitScanReverse* intrinsics, we must use the fallback code for count_digits etc.

(cherry picked from commit a2596d685d)
2017-06-08 11:29:27 +02:00
Eric Fiselier
80bfa855a2 Don't export the -std=c++11 flag from the fmt target
(cherry picked from commit b9aaa507fc)
2017-06-08 11:29:16 +02:00
Victor Zverovich
850405f0b0 Fix test compilation for FreeBSD (#433)
(cherry picked from commit fac5546321)
2017-06-08 11:28:48 +02:00
Victor Zverovich
a55df13598 Fix collision with global convert function (#425)
(cherry picked from commit 796beaaddb)
2017-06-08 11:28:43 +02:00
Victor Zverovich
baedba07ca Fix signbit detection (#423)
(cherry picked from commit def687462c)
2017-06-08 11:28:39 +02:00
Victor Zverovich
b9a20d761a Add version macro FMT_VERSION (#411)
(cherry picked from commit f5b1c16e2c)

# Conflicts:
#	CMakeLists.txt
2017-06-08 11:27:51 +02:00
Victor Zverovich
ba0c3b957f Fix warnings on C++98
(cherry picked from commit cfd00af37a)
2017-06-08 11:27:11 +02:00
Victor Zverovich
4a24a38861 Fix warnings
(cherry picked from commit 6274401919)

# Conflicts:
#	fmt/printf.h
#	test/string-test.cc
2017-06-08 11:26:18 +02:00
Jonathan Müller
5c69ecdd5e Create pull_request_template
(cherry picked from commit 8cef95f7c3)
2017-06-08 11:23:13 +02:00
Victor Zverovich
29732d44bb Add CONTRIBUTING file
(cherry picked from commit 922ae4896b)
2017-06-08 11:23:09 +02:00
Chen Hayat
abee8f95ec Fix Klockwork compilation warning
(cherry picked from commit 05ba3e7888)
2017-06-08 11:23:04 +02:00
Victor Zverovich
48ba0f2aa2 FMT_NULLPTR -> FMT_NULL and improve formatting
(cherry picked from commit 1daddec151)

# Conflicts:
#	fmt/printf.h
#	fmt/string.h
#	fmt/time.h
2017-06-08 11:22:50 +02:00
Jonathan Müller
d3a9d03138 Fix missing '>'
(cherry picked from commit d8867a2b07)
2017-06-08 11:21:55 +02:00
Jonathan Müller
7aaa693fb3 Add extern templates for format_float
Fixes #413.

(cherry picked from commit 6c0125785b)
2017-06-08 11:21:49 +02:00
alabuzhev
267bed868f Using FMT_NULLPTR instead of literal 0
(cherry picked from commit 49ccb2e449)
2017-06-08 11:21:41 +02:00
Victor Zverovich
f0a7da0219 argument index -> argument id
(cherry picked from commit 7ce7def515)
2017-06-08 11:18:34 +02:00
Lectem
5a5c3a3c25 fix newer clang warnings
(cherry picked from commit 8f455c10b0)
2017-06-08 11:17:45 +02:00
20 changed files with 286 additions and 129 deletions

3
.github/pull_request_template vendored Normal file
View File

@@ -0,0 +1,3 @@
<!---
Please make sure you've followed the guidelines outlined in the CONTRIBUTING.rst file.
--->

View File

@@ -1,4 +1,5 @@
language: cpp
dist: trusty
sudo: required # the doc target uses sudo to install dependencies
os:
@@ -22,12 +23,5 @@ matrix:
- os: osx
env: BUILD=Doc
addons:
apt:
sources:
- kubuntu-backports # cmake 2.8.12
packages:
- cmake
script:
- support/travis-build.py

View File

@@ -9,12 +9,22 @@ if (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
set(MASTER_PROJECT ON)
endif ()
# Joins arguments and places the results in ${result_var}.
function(join result_var)
set(result )
foreach (arg ${ARGN})
set(result "${result}${arg}")
endforeach ()
set(${result_var} "${result}" PARENT_SCOPE)
endfunction()
# Set the default CMAKE_BUILD_TYPE to Release.
# This should be done before the project command since the latter can set
# CMAKE_BUILD_TYPE itself (it does so for nmake).
if (NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release CACHE STRING
"Choose the type of build, options are: None(CMAKE_CXX_FLAGS or CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel.")
join(doc "Choose the type of build, options are: None(CMAKE_CXX_FLAGS or "
"CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel.")
set(CMAKE_BUILD_TYPE Release CACHE STRING ${doc})
endif ()
option(FMT_PEDANTIC "Enable extra warnings and expensive tests." OFF)
@@ -28,13 +38,17 @@ option(FMT_USE_CPP11 "Enable the addition of C++11 compiler flags." ON)
project(FMT)
# Starting with cmake 3.0 VERSION is part of the project command.
set(FMT_VERSION 3.0.1)
if (NOT FMT_VERSION MATCHES "^([0-9]+).([0-9]+).([0-9]+)$")
message(FATAL_ERROR "Invalid version format ${FMT_VERSION}.")
file(READ fmt/format.h format_h)
if (NOT format_h MATCHES "FMT_VERSION ([0-9]+)([0-9][0-9])([0-9][0-9])")
message(FATAL_ERROR "Cannot get FMT_VERSION from format.h.")
endif ()
set(CPACK_PACKAGE_VERSION_MAJOR ${CMAKE_MATCH_1})
set(CPACK_PACKAGE_VERSION_MINOR ${CMAKE_MATCH_2})
set(CPACK_PACKAGE_VERSION_PATCH ${CMAKE_MATCH_3})
# Use math to skip leading zeros if any.
math(EXPR CPACK_PACKAGE_VERSION_MAJOR ${CMAKE_MATCH_1})
math(EXPR CPACK_PACKAGE_VERSION_MINOR ${CMAKE_MATCH_2})
math(EXPR CPACK_PACKAGE_VERSION_PATCH ${CMAKE_MATCH_3})
join(FMT_VERSION ${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.
${CPACK_PACKAGE_VERSION_PATCH})
message(STATUS "Version: ${FMT_VERSION}")
message(STATUS "Build type: ${CMAKE_BUILD_TYPE}")

11
CONTRIBUTING.rst Normal file
View File

@@ -0,0 +1,11 @@
Contributing to fmt
===================
All C++ code must adhere to `Google C++ Style Guide
<https://google.github.io/styleguide/cppguide.html>`_ with the following
exceptions:
* Exceptions are permitted
* snake_case should be used instead of UpperCamelCase for function names
Thanks for contributing!

View File

@@ -1,3 +1,38 @@
3.0.2 - TBD
-----------
* Added ``FMT_VERSION`` macro (`#411 <https://github.com/fmtlib/fmt/issues/411>`_).
* Used ``FMT_NULL`` instead of literal ``0`` (`#409 <https://github.com/fmtlib/fmt/pull/409>`_). Thanks `@alabuzhev (Alex Alabuzhev) <https://github.com/alabuzhev>`_.
* Added extern templates for ``format_float`` (`#413 <https://github.com/fmtlib/fmt/issues/413>`_).
* Fixed implicit conversion issue (`#507 <https://github.com/fmtlib/fmt/issues/507>`_).
* Fixed signbit detection (`#423 <https://github.com/fmtlib/fmt/issues/423>`_).
* Fixed naming collision (`#425 <https://github.com/fmtlib/fmt/issues/425>`_).
* Fixed missing intrinsic for C++/CLI (`#457 <https://github.com/fmtlib/fmt/pull/457>`_). Thanks `@calumr (Calum Robinson) <https://github.com/calumr>`_
* Fixed Android detection (`#458 <https://github.com/fmtlib/fmt/pull/458>`_). Thanks `@Gachapen (Magnus Bjerke Vik) <https://github.com/Gachapen>`_.
* Use lean ``windows.h`` if not in header-only mode (`#503 <https://github.com/fmtlib/fmt/pull/503>`_). Thanks `@Quentin01 (Quentin Buathier) <https://github.com/Quentin01>`_.
* Fixed issue with CMake exporting C++11 flag (`#445 <https://github.com/fmtlib/fmt/pull/455>`_). Thanks `@EricWF (Eric) <https://github.com/EricWF>`_.
* Fixed issue with nvcc and MSVC compiler bug and MinGW (`#505 <https://github.com/fmtlib/fmt/issues/505>`_).
* Fixed DLL issues (`#469 <https://github.com/fmtlib/fmt/pull/469>`_ and `#502 <https://github.com/fmtlib/fmt/pull/502>`_). Thanks `@richardeakin (Richard Eakin) <https://github.com/richardeakin>`_ and `@AndreasSchoenle (Andreas Schönle) <https://github.com/AndreasSchoenle>`_.
* Fixed test compilation under FreeBSD (`#433 <https://github.com/fmtlib/fmt/issues/433>`_).
* Fixed various warnings (`#403 <https://github.com/fmtlib/fmt/pull/403>`_, `#410 <https://github.com/fmtlib/fmt/pull/410>`_ and `#510 <https://github.com/fmtlib/fmt/pull/510>`_). Thanks `@Lecetem <https://github.com/Lectem>`_, `@chenhayat (Chen Hayat) <https://github.com/chenhayat>`_ and `@trozen <https://github.com/trozen>`_.
* Removed redundant include (`#479 <https://github.com/fmtlib/fmt/issues/479>`_).
* Fixed documentation issues.
3.0.1 - 2016-11-01
------------------
* Fixed handling of thousands seperator (`#353 <https://github.com/fmtlib/fmt/issues/353>`_)

View File

@@ -11,8 +11,8 @@ namespace is usually omitted in examples.
Format API
==========
The following functions use :ref:`format string syntax <syntax>` similar
to the one used by Python's `str.format
The following functions defined in ``fmt/format.h`` use :ref:`format string
syntax <syntax>` similar to the one used by Python's `str.format
<http://docs.python.org/3/library/stdtypes.html#str.format>`_ function.
They take *format_str* and *args* as arguments.

View File

@@ -51,7 +51,7 @@ described in the next section.
A *format_spec* field can also include nested replacement fields in certain
positions within it. These nested replacement fields can contain only an
argument index; format specifications are not allowed. This allows the
argument id; format specifications are not allowed. This allows the
formatting of a value to be dynamically specified.
See the :ref:`formatexamples` section for some examples.

View File

@@ -15,7 +15,9 @@ if (FMT_CPPFORMAT)
endif ()
# Starting with cmake 3.1 the CXX_STANDARD property can be used instead.
target_compile_options(fmt PUBLIC ${CPP11_FLAG})
# Note: Don't make -std=c++11 public or interface, since it breaks projects
# that use C++14.
target_compile_options(fmt PRIVATE ${CPP11_FLAG})
if (FMT_PEDANTIC)
target_compile_options(fmt PRIVATE ${PEDANTIC_COMPILE_FLAGS})
endif ()

View File

@@ -41,6 +41,9 @@
#endif
#if FMT_USE_WINDOWS_H
# if !defined(FMT_HEADER_ONLY) && !defined(WIN32_LEAN_AND_MEAN)
# define WIN32_LEAN_AND_MEAN
# endif
# if defined(NOMINMAX) || defined(FMT_WIN_MINMAX)
# include <windows.h>
# else
@@ -80,9 +83,9 @@ static inline fmt::internal::Null<> strerror_s(char *, std::size_t, ...) {
namespace fmt {
FMT_FUNC internal::RuntimeError::~RuntimeError() throw() {}
FMT_FUNC FormatError::~FormatError() throw() {}
FMT_FUNC SystemError::~SystemError() throw() {}
FMT_FUNC internal::RuntimeError::~RuntimeError() FMT_DTOR_NOEXCEPT {}
FMT_FUNC FormatError::~FormatError() FMT_DTOR_NOEXCEPT {}
FMT_FUNC SystemError::~SystemError() FMT_DTOR_NOEXCEPT {}
namespace {
@@ -191,7 +194,8 @@ int safe_strerror(
: error_code_(err_code), buffer_(buf), buffer_size_(buf_size) {}
int run() {
strerror_r(0, 0, ""); // Suppress a warning about unused strerror_r.
// Suppress a warning about unused strerror_r.
strerror_r(0, FMT_NULL, "");
return handle(strerror_r(error_code_, buffer_, buffer_size_));
}
};
@@ -525,7 +529,7 @@ FMT_FUNC fmt::internal::UTF8ToUTF16::UTF8ToUTF16(fmt::StringRef s) {
FMT_THROW(WindowsError(ERROR_INVALID_PARAMETER, ERROR_MSG));
int s_size = static_cast<int>(s.size());
int length = MultiByteToWideChar(
CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, 0, 0);
CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, FMT_NULL, 0);
if (length == 0)
FMT_THROW(WindowsError(GetLastError(), ERROR_MSG));
buffer_.resize(length + 1);
@@ -547,12 +551,13 @@ FMT_FUNC int fmt::internal::UTF16ToUTF8::convert(fmt::WStringRef s) {
if (s.size() > INT_MAX)
return ERROR_INVALID_PARAMETER;
int s_size = static_cast<int>(s.size());
int length = WideCharToMultiByte(CP_UTF8, 0, s.data(), s_size, 0, 0, 0, 0);
int length = WideCharToMultiByte(
CP_UTF8, 0, s.data(), s_size, FMT_NULL, 0, FMT_NULL, FMT_NULL);
if (length == 0)
return GetLastError();
buffer_.resize(length + 1);
length = WideCharToMultiByte(
CP_UTF8, 0, s.data(), s_size, &buffer_[0], length, 0, 0);
CP_UTF8, 0, s.data(), s_size, &buffer_[0], length, FMT_NULL, FMT_NULL);
if (length == 0)
return GetLastError();
buffer_[length] = 0;
@@ -576,9 +581,10 @@ FMT_FUNC void fmt::internal::format_windows_error(
buffer.resize(INLINE_BUFFER_SIZE);
for (;;) {
wchar_t *system_message = &buffer[0];
int result = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
0, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
system_message, static_cast<uint32_t>(buffer.size()), 0);
int result = FormatMessageW(
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
FMT_NULL, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
system_message, static_cast<uint32_t>(buffer.size()), FMT_NULL);
if (result != 0) {
UTF16ToUTF8 utf8_message;
if (utf8_message.convert(system_message) == ERROR_SUCCESS) {
@@ -623,7 +629,7 @@ void fmt::internal::ArgMap<Char>::init(const ArgList &args) {
if (!map_.empty())
return;
typedef internal::NamedArg<Char> NamedArg;
const NamedArg *named_arg = 0;
const NamedArg *named_arg = FMT_NULL;
bool use_values =
args.type(ArgList::MAX_PACKED_ARGS - 1) == internal::Arg::NONE;
if (use_values) {
@@ -905,14 +911,14 @@ template void fmt::internal::FixedBuffer<char>::grow(std::size_t);
template void fmt::internal::ArgMap<char>::init(const fmt::ArgList &args);
template void fmt::internal::PrintfFormatter<char>::format(
template FMT_API void fmt::internal::PrintfFormatter<char>::format(
BasicWriter<char> &writer, CStringRef format);
template int fmt::internal::CharTraits<char>::format_float(
template FMT_API int fmt::internal::CharTraits<char>::format_float(
char *buffer, std::size_t size, const char *format,
unsigned width, int precision, double value);
template int fmt::internal::CharTraits<char>::format_float(
template FMT_API int fmt::internal::CharTraits<char>::format_float(
char *buffer, std::size_t size, const char *format,
unsigned width, int precision, long double value);
@@ -922,14 +928,14 @@ template void fmt::internal::FixedBuffer<wchar_t>::grow(std::size_t);
template void fmt::internal::ArgMap<wchar_t>::init(const fmt::ArgList &args);
template void fmt::internal::PrintfFormatter<wchar_t>::format(
template FMT_API void fmt::internal::PrintfFormatter<wchar_t>::format(
BasicWriter<wchar_t> &writer, WCStringRef format);
template int fmt::internal::CharTraits<wchar_t>::format_float(
template FMT_API int fmt::internal::CharTraits<wchar_t>::format_float(
wchar_t *buffer, std::size_t size, const wchar_t *format,
unsigned width, int precision, double value);
template int fmt::internal::CharTraits<wchar_t>::format_float(
template int FMT_API fmt::internal::CharTraits<wchar_t>::format_float(
wchar_t *buffer, std::size_t size, const wchar_t *format,
unsigned width, int precision, long double value);

View File

@@ -38,7 +38,10 @@
#include <stdexcept>
#include <string>
#include <vector>
#include <utility>
#include <utility> // for std::pair
// The fmt library version in the form major * 10000 + minor * 100 + patch.
#define FMT_VERSION 30002
#ifdef _SECURE_SCL
# define FMT_SECURE_SCL _SECURE_SCL
@@ -152,10 +155,6 @@ typedef __int64 intmax_t;
# endif
#endif
#if FMT_USE_RVALUE_REFERENCES
# include <utility> // for std::move
#endif
// Check if exceptions are disabled.
#if defined(__GNUC__) && !defined(__EXCEPTIONS)
# define FMT_EXCEPTIONS 0
@@ -180,22 +179,32 @@ typedef __int64 intmax_t;
# define FMT_USE_NOEXCEPT 0
#endif
#ifndef FMT_NOEXCEPT
# if FMT_EXCEPTIONS
# if FMT_USE_NOEXCEPT || FMT_HAS_FEATURE(cxx_noexcept) || \
#if FMT_USE_NOEXCEPT || FMT_HAS_FEATURE(cxx_noexcept) || \
(FMT_GCC_VERSION >= 408 && FMT_HAS_GXX_CXX11) || \
FMT_MSC_VER >= 1900
# define FMT_NOEXCEPT noexcept
# else
# define FMT_NOEXCEPT throw()
# endif
# define FMT_DETECTED_NOEXCEPT noexcept
#else
# define FMT_DETECTED_NOEXCEPT throw()
#endif
#ifndef FMT_NOEXCEPT
# if FMT_EXCEPTIONS
# define FMT_NOEXCEPT FMT_DETECTED_NOEXCEPT
# else
# define FMT_NOEXCEPT
# endif
#endif
// This is needed because GCC still uses throw() in its headers when exceptions
// are disabled.
#if FMT_GCC_VERSION
# define FMT_DTOR_NOEXCEPT FMT_DETECTED_NOEXCEPT
#else
# define FMT_DTOR_NOEXCEPT FMT_NOEXCEPT
#endif
#ifndef FMT_OVERRIDE
# if FMT_USE_OVERRIDE || FMT_HAS_FEATURE(cxx_override) || \
# if (defined(FMT_USE_OVERRIDE) && FMT_USE_OVERRIDE) || FMT_HAS_FEATURE(cxx_override) || \
(FMT_GCC_VERSION >= 408 && FMT_HAS_GXX_CXX11) || \
FMT_MSC_VER >= 1900
# define FMT_OVERRIDE override
@@ -204,6 +213,15 @@ typedef __int64 intmax_t;
# endif
#endif
#ifndef FMT_NULL
# if FMT_HAS_FEATURE(cxx_nullptr) || \
(FMT_GCC_VERSION >= 408 && FMT_HAS_GXX_CXX11) || \
FMT_MSC_VER >= 1600
# define FMT_NULL nullptr
# else
# define FMT_NULL NULL
# endif
#endif
// A macro to disallow the copy constructor and operator= functions
// This should be used in the private: declarations for a class
@@ -236,6 +254,21 @@ typedef __int64 intmax_t;
(!defined(FMT_ICC_VERSION) || FMT_ICC_VERSION >= 1500)
#endif
#ifndef FMT_USE_EXTERN_TEMPLATES
// Clang doesn't have a feature check for extern templates so we check
// for variadic templates which were introduced in the same version.
// For GCC according to cppreference.com they were introduced in 3.3.
# define FMT_USE_EXTERN_TEMPLATES \
((__clang__ && FMT_USE_VARIADIC_TEMPLATES) || \
(FMT_GCC_VERSION >= 303 && FMT_HAS_GXX_CXX11))
#endif
#ifdef FMT_HEADER_ONLY
// If header only do not use extern templates.
# undef FMT_USE_EXTERN_TEMPLATES
# define FMT_USE_EXTERN_TEMPLATES 0
#endif
#ifndef FMT_ASSERT
# define FMT_ASSERT(condition, message) assert((condition) && message)
#endif
@@ -252,7 +285,7 @@ typedef __int64 intmax_t;
// otherwise support __builtin_clz and __builtin_clzll, so
// only define FMT_BUILTIN_CLZ using the MSVC intrinsics
// if the clz and clzll builtins are not available.
#if FMT_MSC_VER && !defined(FMT_BUILTIN_CLZLL)
#if FMT_MSC_VER && !defined(FMT_BUILTIN_CLZLL) && !defined(_MANAGED)
# include <intrin.h> // _BitScanReverse, _BitScanReverse64
namespace fmt {
@@ -360,8 +393,10 @@ class numeric_limits<fmt::internal::DummyInt> :
// Portable version of signbit.
static bool isnegative(double x) {
using namespace fmt::internal;
if (const_check(sizeof(signbit(x)) == sizeof(int)))
if (const_check(sizeof(signbit(x)) == sizeof(bool) ||
sizeof(signbit(x)) == sizeof(int))) {
return signbit(x) != 0;
}
if (x < 0) return true;
if (!isnotanumber(x)) return false;
int dec = 0, sign = 0;
@@ -547,7 +582,8 @@ class FormatError : public std::runtime_error {
public:
explicit FormatError(CStringRef message)
: std::runtime_error(message.c_str()) {}
~FormatError() throw();
FormatError(const FormatError &ferr) : std::runtime_error(ferr) {}
FMT_API ~FormatError() FMT_DTOR_NOEXCEPT;
};
namespace internal {
@@ -605,7 +641,7 @@ class Buffer {
std::size_t size_;
std::size_t capacity_;
Buffer(T *ptr = 0, std::size_t capacity = 0)
Buffer(T *ptr = FMT_NULL, std::size_t capacity = 0)
: ptr_(ptr), size_(0), capacity_(capacity) {}
/**
@@ -663,7 +699,8 @@ class Buffer {
template <typename T>
template <typename U>
void Buffer<T>::append(const U *begin, const U *end) {
std::size_t new_size = size_ + internal::to_unsigned(end - begin);
FMT_ASSERT(end >= begin, "negative value");
std::size_t new_size = size_ + (end - begin);
if (new_size > capacity_)
grow(new_size);
std::uninitialized_copy(begin, end,
@@ -735,7 +772,7 @@ void MemoryBuffer<T, SIZE, Allocator>::grow(std::size_t size) {
std::size_t new_capacity = this->capacity_ + this->capacity_ / 2;
if (size > new_capacity)
new_capacity = size;
T *new_ptr = this->allocate(new_capacity);
T *new_ptr = this->allocate(new_capacity, FMT_NULL);
// The following code doesn't throw, so the raw pointer above doesn't leak.
std::uninitialized_copy(this->ptr_, this->ptr_ + this->size_,
make_ptr(new_ptr, new_capacity));
@@ -757,7 +794,7 @@ class FixedBuffer : public fmt::Buffer<Char> {
FixedBuffer(Char *array, std::size_t size) : fmt::Buffer<Char>(array, size) {}
protected:
FMT_API void grow(std::size_t size);
FMT_API void grow(std::size_t size) FMT_OVERRIDE;
};
template <typename Char>
@@ -789,6 +826,15 @@ class CharTraits<char> : public BasicCharTraits<char> {
const char *format, unsigned width, int precision, T value);
};
#if FMT_USE_EXTERN_TEMPLATES
extern template int CharTraits<char>::format_float<double>
(char *buffer, std::size_t size,
const char* format, unsigned width, int precision, double value);
extern template int CharTraits<char>::format_float<long double>
(char *buffer, std::size_t size,
const char* format, unsigned width, int precision, long double value);
#endif
template <>
class CharTraits<wchar_t> : public BasicCharTraits<wchar_t> {
public:
@@ -800,6 +846,15 @@ class CharTraits<wchar_t> : public BasicCharTraits<wchar_t> {
const wchar_t *format, unsigned width, int precision, T value);
};
#if FMT_USE_EXTERN_TEMPLATES
extern template int CharTraits<wchar_t>::format_float<double>
(wchar_t *buffer, std::size_t size,
const wchar_t* format, unsigned width, int precision, double value);
extern template int CharTraits<wchar_t>::format_float<long double>
(wchar_t *buffer, std::size_t size,
const wchar_t* format, unsigned width, int precision, long double value);
#endif
// Checks if a number is negative - used to avoid warnings.
template <bool IsSigned>
struct SignChecker {
@@ -846,13 +901,7 @@ struct FMT_API BasicData {
static const char DIGITS[];
};
#ifndef FMT_USE_EXTERN_TEMPLATES
// Clang doesn't have a feature check for extern templates so we check
// for variadic templates which were introduced in the same version.
# define FMT_USE_EXTERN_TEMPLATES (__clang__ && FMT_USE_VARIADIC_TEMPLATES)
#endif
#if FMT_USE_EXTERN_TEMPLATES && !defined(FMT_HEADER_ONLY)
#if FMT_USE_EXTERN_TEMPLATES
extern template struct BasicData<void>;
#endif
@@ -950,7 +999,8 @@ inline void format_decimal(Char *buffer, UInt value, unsigned num_digits,
template <typename UInt, typename Char>
inline void format_decimal(Char *buffer, UInt value, unsigned num_digits) {
return format_decimal(buffer, value, num_digits, NoThousandsSep());
format_decimal(buffer, value, num_digits, NoThousandsSep());
return;
}
#ifndef _WIN32
@@ -1100,7 +1150,9 @@ struct ConvertToIntImpl2<T, true> {
template<typename T>
struct ConvertToInt {
enum { enable_conversion = sizeof(convert(get<T>())) == sizeof(Yes) };
enum {
enable_conversion = sizeof(fmt::internal::convert(get<T>())) == sizeof(Yes)
};
enum { value = ConvertToIntImpl2<T, enable_conversion>::value };
};
@@ -1287,14 +1339,9 @@ class MakeValue : public Arg {
}
template <typename T>
MakeValue(const T &value,
typename EnableIf<ConvertToInt<T>::value, int>::type = 0) {
int_value = value;
}
template <typename T>
static uint64_t type(const T &) {
return ConvertToInt<T>::value ? Arg::INT : Arg::CUSTOM;
static typename EnableIf<Not<ConvertToInt<T>::value>::value, uint64_t>::type
type(const T &) {
return Arg::CUSTOM;
}
// Additional template param `Char_` is needed here because make_type always
@@ -1332,7 +1379,8 @@ struct NamedArg : Arg {
class RuntimeError : public std::runtime_error {
protected:
RuntimeError() : std::runtime_error("") {}
~RuntimeError() throw();
RuntimeError(const RuntimeError &rerr) : std::runtime_error(rerr) {}
FMT_API ~RuntimeError() FMT_DTOR_NOEXCEPT;
};
template <typename Char>
@@ -1802,14 +1850,14 @@ class ArgMap {
public:
FMT_API void init(const ArgList &args);
const internal::Arg* find(const fmt::BasicStringRef<Char> &name) const {
const internal::Arg *find(const fmt::BasicStringRef<Char> &name) const {
// The list is unsorted, so just return the first matching name.
for (typename MapType::const_iterator it = map_.begin(), end = map_.end();
it != end; ++it) {
if (it->first == name)
return &it->second;
}
return 0;
return FMT_NULL;
}
};
@@ -1827,6 +1875,9 @@ class ArgFormatterBase : public ArgVisitor<Impl, void> {
writer_.write_int(reinterpret_cast<uintptr_t>(p), spec_);
}
// workaround MSVC two-phase lookup issue
typedef internal::Arg Arg;
protected:
BasicWriter<Char> &writer() { return writer_; }
FormatSpec &spec() { return spec_; }
@@ -1838,7 +1889,7 @@ class ArgFormatterBase : public ArgVisitor<Impl, void> {
}
void write(const char *value) {
Arg::StringValue<char> str = {value, value != 0 ? std::strlen(value) : 0};
Arg::StringValue<char> str = {value, value ? std::strlen(value) : 0};
writer_.write_str(str, spec_);
}
@@ -1853,8 +1904,10 @@ class ArgFormatterBase : public ArgVisitor<Impl, void> {
void visit_any_double(T value) { writer_.write_double(value, spec_); }
void visit_bool(bool value) {
if (spec_.type_)
return visit_any_int(value);
if (spec_.type_) {
visit_any_int(value);
return;
}
write(value);
}
@@ -1894,13 +1947,14 @@ class ArgFormatterBase : public ArgVisitor<Impl, void> {
write(value);
}
void visit_string(Arg::StringValue<char> value) {
// Qualification with "internal" here and below is a workaround for nvcc.
void visit_string(internal::Arg::StringValue<char> value) {
writer_.write_str(value, spec_);
}
using ArgVisitor<Impl, void>::visit_wstring;
void visit_wstring(Arg::StringValue<Char> value) {
void visit_wstring(internal::Arg::StringValue<Char> value) {
writer_.write_str(value, spec_);
}
@@ -2104,10 +2158,10 @@ inline uint64_t make_type(const T &arg) {
return MakeValue< BasicFormatter<char> >::type(arg);
}
template <unsigned N, bool/*IsPacked*/= (N < ArgList::MAX_PACKED_ARGS)>
template <std::size_t N, bool/*IsPacked*/= (N < ArgList::MAX_PACKED_ARGS)>
struct ArgArray;
template <unsigned N>
template <std::size_t N>
struct ArgArray<N, true/*IsPacked*/> {
typedef Value Type[N > 0 ? N : 1];
@@ -2125,7 +2179,7 @@ struct ArgArray<N, true/*IsPacked*/> {
}
};
template <unsigned N>
template <std::size_t N>
struct ArgArray<N, false/*IsPacked*/> {
typedef Arg Type[N + 1]; // +1 for the list end Arg::NONE
@@ -2265,7 +2319,7 @@ inline uint64_t make_type(FMT_GEN15(FMT_ARG_TYPE_DEFAULT)) {
*/
class SystemError : public internal::RuntimeError {
private:
void init(int err_code, CStringRef format_str, ArgList args);
FMT_API void init(int err_code, CStringRef format_str, ArgList args);
protected:
int error_code_;
@@ -2305,7 +2359,7 @@ class SystemError : public internal::RuntimeError {
}
FMT_VARIADIC_CTOR(SystemError, init, int, CStringRef)
~SystemError() throw();
FMT_API ~SystemError() FMT_DTOR_NOEXCEPT;
int error_code() const { return error_code_; }
};
@@ -2802,7 +2856,7 @@ void BasicWriter<Char>::write_int(T value, Spec spec) {
case 'n': {
unsigned num_digits = internal::count_digits(abs_value);
fmt::StringRef sep = "";
#ifndef ANDROID
#if !(defined(ANDROID) || defined(__ANDROID__))
sep = internal::thousands_sep(std::localeconv());
#endif
unsigned size = static_cast<unsigned>(
@@ -2921,7 +2975,7 @@ void BasicWriter<Char>::write_double(T value, const FormatSpec &spec) {
// Format using snprintf.
Char fill = internal::CharTraits<Char>::cast(spec.fill());
unsigned n = 0;
Char *start = 0;
Char *start = FMT_NULL;
for (;;) {
std::size_t buffer_size = buffer_.capacity() - offset;
#if FMT_MSC_VER
@@ -3583,7 +3637,7 @@ inline internal::Arg BasicFormatter<Char, AF>::get_arg(
template <typename Char, typename AF>
inline internal::Arg BasicFormatter<Char, AF>::parse_arg_index(const Char *&s) {
const char *error = 0;
const char *error = FMT_NULL;
internal::Arg arg = *s < '0' || *s > '9' ?
next_arg(error) : get_arg(internal::parse_nonnegative_int(s), error);
if (error) {
@@ -3601,7 +3655,7 @@ inline internal::Arg BasicFormatter<Char, AF>::parse_arg_name(const Char *&s) {
do {
c = *++s;
} while (internal::is_name_start(c) || ('0' <= c && c <= '9'));
const char *error = 0;
const char *error = FMT_NULL;
internal::Arg arg = get_arg(BasicStringRef<Char>(start, s - start), error);
if (error)
FMT_THROW(FormatError(error));

View File

@@ -21,6 +21,9 @@
#ifndef _WIN32
# include <unistd.h>
#else
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
# endif
# include <windows.h>
# include <io.h>
@@ -79,7 +82,7 @@ void fmt::BufferedFile::close() {
if (!file_)
return;
int result = FMT_SYSTEM(fclose(file_));
file_ = 0;
file_ = FMT_NULL;
if (result != 0)
FMT_THROW(SystemError(errno, "cannot close file"));
}

View File

@@ -107,10 +107,10 @@ class BufferedFile {
public:
// Constructs a BufferedFile object which doesn't represent any file.
BufferedFile() FMT_NOEXCEPT : file_(0) {}
BufferedFile() FMT_NOEXCEPT : file_(FMT_NULL) {}
// Destroys the object closing the file it represents if any.
~BufferedFile() FMT_NOEXCEPT;
FMT_API ~BufferedFile() FMT_NOEXCEPT;
#if !FMT_USE_RVALUE_REFERENCES
// Emulate a move constructor and a move assignment operator if rvalue
@@ -129,7 +129,7 @@ public:
// A "move constructor" for moving from an lvalue.
BufferedFile(BufferedFile &f) FMT_NOEXCEPT : file_(f.file_) {
f.file_ = 0;
f.file_ = FMT_NULL;
}
// A "move assignment operator" for moving from a temporary.
@@ -143,7 +143,7 @@ public:
BufferedFile &operator=(BufferedFile &other) {
close();
file_ = other.file_;
other.file_ = 0;
other.file_ = FMT_NULL;
return *this;
}
@@ -151,7 +151,7 @@ public:
// BufferedFile file = BufferedFile(...);
operator Proxy() FMT_NOEXCEPT {
Proxy p = {file_};
file_ = 0;
file_ = FMT_NULL;
return p;
}
@@ -161,29 +161,29 @@ public:
public:
BufferedFile(BufferedFile &&other) FMT_NOEXCEPT : file_(other.file_) {
other.file_ = 0;
other.file_ = FMT_NULL;
}
BufferedFile& operator=(BufferedFile &&other) {
close();
file_ = other.file_;
other.file_ = 0;
other.file_ = FMT_NULL;
return *this;
}
#endif
// Opens a file.
BufferedFile(CStringRef filename, CStringRef mode);
FMT_API BufferedFile(CStringRef filename, CStringRef mode);
// Closes the file.
void close();
FMT_API void close();
// Returns the pointer to a FILE object representing this file.
FILE *get() const FMT_NOEXCEPT { return file_; }
// We place parentheses around fileno to workaround a bug in some versions
// of MinGW that define fileno as a macro.
int (fileno)() const;
FMT_API int (fileno)() const;
void print(CStringRef format_str, const ArgList &args) {
fmt::print(file_, format_str, args);
@@ -216,7 +216,7 @@ class File {
File() FMT_NOEXCEPT : fd_(-1) {}
// Opens a file and constructs a File object representing this file.
File(CStringRef path, int oflag);
FMT_API File(CStringRef path, int oflag);
#if !FMT_USE_RVALUE_REFERENCES
// Emulate a move constructor and a move assignment operator if rvalue
@@ -279,43 +279,43 @@ class File {
#endif
// Destroys the object closing the file it represents if any.
~File() FMT_NOEXCEPT;
FMT_API ~File() FMT_NOEXCEPT;
// Returns the file descriptor.
int descriptor() const FMT_NOEXCEPT { return fd_; }
// Closes the file.
void close();
FMT_API void close();
// Returns the file size. The size has signed type for consistency with
// stat::st_size.
LongLong size() const;
FMT_API LongLong size() const;
// Attempts to read count bytes from the file into the specified buffer.
std::size_t read(void *buffer, std::size_t count);
FMT_API std::size_t read(void *buffer, std::size_t count);
// Attempts to write count bytes from the specified buffer to the file.
std::size_t write(const void *buffer, std::size_t count);
FMT_API std::size_t write(const void *buffer, std::size_t count);
// Duplicates a file descriptor with the dup function and returns
// the duplicate as a file object.
static File dup(int fd);
FMT_API static File dup(int fd);
// Makes fd be the copy of this file descriptor, closing fd first if
// necessary.
void dup2(int fd);
FMT_API void dup2(int fd);
// Makes fd be the copy of this file descriptor, closing fd first if
// necessary.
void dup2(int fd, ErrorCode &ec) FMT_NOEXCEPT;
FMT_API void dup2(int fd, ErrorCode &ec) FMT_NOEXCEPT;
// Creates a pipe setting up read_end and write_end file objects for reading
// and writing respectively.
static void pipe(File &read_end, File &write_end);
FMT_API static void pipe(File &read_end, File &write_end);
// Creates a BufferedFile object associated with this file and detaches
// this File object from the file.
BufferedFile fdopen(const char *mode);
FMT_API BufferedFile fdopen(const char *mode);
};
// Returns the memory page size.
@@ -355,7 +355,7 @@ class Locale {
public:
typedef locale_t Type;
Locale() : locale_(newlocale(LC_NUMERIC_MASK, "C", NULL)) {
Locale() : locale_(newlocale(LC_NUMERIC_MASK, "C", FMT_NULL)) {
if (!locale_)
FMT_THROW(fmt::SystemError(errno, "cannot create locale"));
}
@@ -366,7 +366,7 @@ class Locale {
// Converts string to floating-point number and advances str past the end
// of the parsed input.
double strtod(const char *&str) const {
char *end = 0;
char *end = FMT_NULL;
double result = strtod_l(str, &end, locale_);
str = end;
return result;

View File

@@ -20,7 +20,14 @@ if (FMT_USE_CPP11)
check_cxx_source_compiles("
#include <unistd.h>
int main() {}" FMT_CPP11_UNISTD_H)
if (FMT_CPP11_CMATH AND FMT_CPP11_UNISTD_H)
# Check if snprintf works with -std=c++11. It may not in MinGW.
check_cxx_source_compiles("
#include <stdio.h>
int main() {
char buffer[10];
snprintf(buffer, 10, \"foo\");
}" FMT_CPP11_SNPRINTF)
if (FMT_CPP11_CMATH AND FMT_CPP11_UNISTD_H AND FMT_CPP11_SNPRINTF)
set(CPP11_FLAG -std=c++11)
else ()
check_cxx_compiler_flag(-std=gnu++11 HAVE_STD_GNUPP11_FLAG)

View File

@@ -26,6 +26,7 @@
*/
#define FMT_NOEXCEPT
#undef FMT_SHARED
#include "test-assert.h"
// Include format.cc instead of format.h to test implementation-specific stuff.

View File

@@ -250,7 +250,7 @@ TEST(WriterTest, Allocator) {
std::size_t size =
static_cast<std::size_t>(1.5 * fmt::internal::INLINE_BUFFER_SIZE);
std::vector<char> mem(size);
EXPECT_CALL(alloc, allocate(size)).WillOnce(testing::Return(&mem[0]));
EXPECT_CALL(alloc, allocate(size, 0)).WillOnce(testing::Return(&mem[0]));
for (int i = 0; i < fmt::internal::INLINE_BUFFER_SIZE + 1; ++i)
w << '*';
EXPECT_CALL(alloc, deallocate(&mem[0], size));
@@ -1225,7 +1225,7 @@ TEST(FormatterTest, FormatOct) {
TEST(FormatterTest, FormatIntLocale) {
ScopedMock<LocaleMock> mock;
lconv lc = {};
lconv lc = lconv();
char sep[] = "--";
lc.thousands_sep = sep;
EXPECT_CALL(mock, localeconv()).Times(3).WillRepeatedly(testing::Return(&lc));
@@ -1234,6 +1234,16 @@ TEST(FormatterTest, FormatIntLocale) {
EXPECT_EQ("1--234--567", format("{:n}", 1234567));
}
struct ConvertibleToLongLong {
operator fmt::LongLong() const {
return fmt::LongLong(1) << 32;
}
};
TEST(FormatterTest, FormatConvertibleToLongLong) {
EXPECT_EQ("100000000", format("{:x}", ConvertibleToLongLong()));
}
TEST(FormatterTest, FormatFloat) {
EXPECT_EQ("392.500000", format("{0:f}", 392.5f));
}
@@ -1653,3 +1663,11 @@ FMT_VARIADIC(void, custom_format, const char *)
TEST(FormatTest, CustomArgFormatter) {
custom_format("{}", 42);
}
void convert(int);
// Check if there is no collision with convert function in the global namespace.
TEST(FormatTest, ConvertCollision) {
fmt::format("{}", 42);
}

View File

@@ -2823,7 +2823,11 @@ inline int IsATTY(int /* fd */) { return 0; }
inline int IsATTY(int fd) { return _isatty(fd); }
# endif // GTEST_OS_WINDOWS_MOBILE
inline int StrCaseCmp(const char* s1, const char* s2) {
return _stricmp(s1, s2);
# if _EMULATE_GLIBC
return strcasecmp(s1, s2);
# else
return _stricmp(s1, s2);
# endif
}
inline char* StrDup(const char* src) { return _strdup(src); }
# endif // __BORLANDC__

View File

@@ -36,8 +36,8 @@ class MockAllocator {
MockAllocator() {}
MockAllocator(const MockAllocator &) {}
typedef T value_type;
MOCK_METHOD1_T(allocate, T* (std::size_t n));
MOCK_METHOD2_T(deallocate, void (T* p, std::size_t n));
MOCK_METHOD2_T(allocate, T *(std::size_t n, const T *h));
MOCK_METHOD2_T(deallocate, void (T *p, std::size_t n));
};
template <typename Allocator>
@@ -78,8 +78,10 @@ class AllocatorRef {
Allocator *get() const { return alloc_; }
value_type* allocate(std::size_t n) { return alloc_->allocate(n); }
void deallocate(value_type* p, std::size_t n) { alloc_->deallocate(p, n); }
value_type *allocate(std::size_t n, const value_type *h) {
return alloc_->allocate(n, h);
}
void deallocate(value_type *p, std::size_t n) { alloc_->deallocate(p, n); }
};
#endif // FMT_MOCK_ALLOCATOR_H_

View File

@@ -502,7 +502,7 @@ LocaleType newlocale(int category_mask, const char *locale, LocaleType base) {
return LocaleMock::instance->newlocale(category_mask, locale, base);
}
#ifdef __APPLE__
#if defined(__APPLE__) || defined(__FreeBSD__)
typedef int FreeLocaleResult;
#else
typedef void FreeLocaleResult;

View File

@@ -6,6 +6,9 @@
For the license information refer to format.h.
*/
#ifdef WIN32
#define _CRT_SECURE_NO_WARNINGS
#endif
#include "gmock/gmock.h"
#include "fmt/time.h"

View File

@@ -83,8 +83,8 @@ void CheckForwarding(
// Check if value_type is properly defined.
AllocatorRef< MockAllocator<int> >::value_type *ptr = &mem;
// Check forwarding.
EXPECT_CALL(alloc, allocate(42)).WillOnce(Return(ptr));
ref.allocate(42);
EXPECT_CALL(alloc, allocate(42, 0)).WillOnce(Return(ptr));
ref.allocate(42, 0);
EXPECT_CALL(alloc, deallocate(ptr, 42));
ref.deallocate(ptr, 42);
}
@@ -339,7 +339,7 @@ TEST(MemoryBufferTest, Grow) {
EXPECT_EQ(10u, buffer.capacity());
int mem[20];
mem[7] = 0xdead;
EXPECT_CALL(alloc, allocate(20)).WillOnce(Return(mem));
EXPECT_CALL(alloc, allocate(20, 0)).WillOnce(Return(mem));
buffer.grow(20);
EXPECT_EQ(20u, buffer.capacity());
// Check if size elements have been copied
@@ -360,7 +360,7 @@ TEST(MemoryBufferTest, Allocator) {
MemoryBuffer<char, 10, TestAllocator> buffer2((TestAllocator(&alloc)));
EXPECT_EQ(&alloc, buffer2.get_allocator().get());
std::size_t size = 2 * fmt::internal::INLINE_BUFFER_SIZE;
EXPECT_CALL(alloc, allocate(size)).WillOnce(Return(&mem));
EXPECT_CALL(alloc, allocate(size, 0)).WillOnce(Return(&mem));
buffer2.reserve(size);
EXPECT_CALL(alloc, deallocate(&mem, size));
}
@@ -373,13 +373,13 @@ TEST(MemoryBufferTest, ExceptionInDeallocate) {
std::size_t size = 2 * fmt::internal::INLINE_BUFFER_SIZE;
std::vector<char> mem(size);
{
EXPECT_CALL(alloc, allocate(size)).WillOnce(Return(&mem[0]));
EXPECT_CALL(alloc, allocate(size, 0)).WillOnce(Return(&mem[0]));
buffer.resize(size);
std::fill(&buffer[0], &buffer[0] + size, 'x');
}
std::vector<char> mem2(2 * size);
{
EXPECT_CALL(alloc, allocate(2 * size)).WillOnce(Return(&mem2[0]));
EXPECT_CALL(alloc, allocate(2 * size, 0)).WillOnce(Return(&mem2[0]));
std::exception e;
EXPECT_CALL(alloc, deallocate(&mem[0], size)).WillOnce(testing::Throw(e));
EXPECT_THROW(buffer.reserve(2 * size), std::exception);