mirror of
https://github.com/fmtlib/fmt.git
synced 2025-12-27 09:18:15 +01:00
Compare commits
31 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5708bf8fcc | ||
|
|
fbd871e433 | ||
|
|
5bce2c0cef | ||
|
|
c75f6dcd30 | ||
|
|
ecd0994c15 | ||
|
|
7859c3493f | ||
|
|
4fca31c497 | ||
|
|
e6df023916 | ||
|
|
1934d9e5d9 | ||
|
|
9270e66700 | ||
|
|
9589bf05de | ||
|
|
aad76bf4c1 | ||
|
|
0bed09caaf | ||
|
|
0e5a4422c2 | ||
|
|
72484cc191 | ||
|
|
80bfa855a2 | ||
|
|
850405f0b0 | ||
|
|
a55df13598 | ||
|
|
baedba07ca | ||
|
|
b9a20d761a | ||
|
|
ba0c3b957f | ||
|
|
4a24a38861 | ||
|
|
5c69ecdd5e | ||
|
|
29732d44bb | ||
|
|
abee8f95ec | ||
|
|
48ba0f2aa2 | ||
|
|
d3a9d03138 | ||
|
|
7aaa693fb3 | ||
|
|
267bed868f | ||
|
|
f0a7da0219 | ||
|
|
5a5c3a3c25 |
3
.github/pull_request_template
vendored
Normal file
3
.github/pull_request_template
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
<!---
|
||||
Please make sure you've followed the guidelines outlined in the CONTRIBUTING.rst 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
|
||||
|
||||
@@ -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
11
CONTRIBUTING.rst
Normal 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!
|
||||
@@ -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>`_)
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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 ()
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
162
fmt/format.h
162
fmt/format.h
@@ -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));
|
||||
|
||||
@@ -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"));
|
||||
}
|
||||
|
||||
46
fmt/posix.h
46
fmt/posix.h
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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__
|
||||
|
||||
@@ -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_
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user