mirror of
https://github.com/fmtlib/fmt.git
synced 2025-07-30 02:37:36 +02:00
Merge pull request #267 from niosHD/update-project-layout
Update project layout
This commit is contained in:
154
CMakeLists.txt
154
CMakeLists.txt
@ -2,6 +2,13 @@ message(STATUS "CMake version: ${CMAKE_VERSION}")
|
|||||||
|
|
||||||
cmake_minimum_required(VERSION 2.8.12)
|
cmake_minimum_required(VERSION 2.8.12)
|
||||||
|
|
||||||
|
# determine if cppformat is built as sub project (using add_subdirectory)
|
||||||
|
# or if it is the master project
|
||||||
|
set(MASTER_PROJECT OFF)
|
||||||
|
if (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
|
||||||
|
set(MASTER_PROJECT ON)
|
||||||
|
endif ()
|
||||||
|
|
||||||
# Set the default CMAKE_BUILD_TYPE to Release.
|
# Set the default CMAKE_BUILD_TYPE to Release.
|
||||||
# This should be done before the project command since the latter can set
|
# This should be done before the project command since the latter can set
|
||||||
# CMAKE_BUILD_TYPE itself (it does so for nmake).
|
# CMAKE_BUILD_TYPE itself (it does so for nmake).
|
||||||
@ -13,50 +20,35 @@ endif ()
|
|||||||
option(FMT_PEDANTIC "Enable extra warnings and expensive tests." OFF)
|
option(FMT_PEDANTIC "Enable extra warnings and expensive tests." OFF)
|
||||||
|
|
||||||
# Options that control generation of various targets.
|
# Options that control generation of various targets.
|
||||||
option(FMT_DOC "Generate the doc target." ON)
|
option(FMT_DOC "Generate the doc target." ${MASTER_PROJECT})
|
||||||
option(FMT_INSTALL "Generate the install target." ON)
|
option(FMT_INSTALL "Generate the install target." ${MASTER_PROJECT})
|
||||||
option(FMT_TEST "Generate the test target." ON)
|
option(FMT_TEST "Generate the test target." ${MASTER_PROJECT})
|
||||||
|
|
||||||
project(FORMAT)
|
project(FORMAT)
|
||||||
|
|
||||||
|
# starting with cmake 3.0 VERSION is part of the project command
|
||||||
|
set(CPPFORMAT_VERSION 2.1.0)
|
||||||
|
if (NOT CPPFORMAT_VERSION MATCHES "^([0-9]+).([0-9]+).([0-9]+)$")
|
||||||
|
message(FATAL_ERROR "Invalid version format ${CPPFORMAT_VERSION}.")
|
||||||
|
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})
|
||||||
|
|
||||||
message(STATUS "Build type: ${CMAKE_BUILD_TYPE}")
|
message(STATUS "Build type: ${CMAKE_BUILD_TYPE}")
|
||||||
|
|
||||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
|
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
|
||||||
|
|
||||||
include(CheckCXXCompilerFlag)
|
|
||||||
check_cxx_compiler_flag(-std=c++11 HAVE_STD_CPP11_FLAG)
|
|
||||||
if (HAVE_STD_CPP11_FLAG)
|
|
||||||
# Check if including cmath works with -std=c++11 and -O3.
|
|
||||||
# It may not in MinGW due to bug http://ehc.ac/p/mingw/bugs/2250/.
|
|
||||||
set(CMAKE_REQUIRED_FLAGS "-std=c++11 -O3")
|
|
||||||
check_cxx_source_compiles("
|
|
||||||
#include <cmath>
|
|
||||||
int main() {}" FMT_CPP11_CMATH)
|
|
||||||
# Check if including <unistd.h> works with -std=c++11.
|
|
||||||
# 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_CPP11_UNISTD_H)
|
|
||||||
if (FMT_CPP11_CMATH AND FMT_CPP11_UNISTD_H)
|
|
||||||
set(CPP11_FLAG -std=c++11)
|
|
||||||
else ()
|
|
||||||
check_cxx_compiler_flag(-std=gnu++11 HAVE_STD_GNUPP11_FLAG)
|
|
||||||
if (HAVE_STD_CPP11_FLAG)
|
|
||||||
set(CPP11_FLAG -std=gnu++11)
|
|
||||||
endif ()
|
|
||||||
endif ()
|
|
||||||
set(CMAKE_REQUIRED_FLAGS )
|
|
||||||
else ()
|
|
||||||
check_cxx_compiler_flag(-std=c++0x HAVE_STD_CPP0X_FLAG)
|
|
||||||
if (HAVE_STD_CPP0X_FLAG)
|
|
||||||
set(CPP11_FLAG -std=c++0x)
|
|
||||||
endif ()
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH}
|
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH}
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/support/cmake")
|
"${CMAKE_CURRENT_SOURCE_DIR}/support/cmake")
|
||||||
|
|
||||||
if (CMAKE_GENERATOR MATCHES "Visual Studio")
|
include(testCxx11)
|
||||||
|
|
||||||
|
if (CMAKE_COMPILER_IS_GNUCXX OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang"))
|
||||||
|
set(PEDANTIC_COMPILE_FLAGS -Wall -Wextra -Wshadow -pedantic)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
if (MASTER_PROJECT AND CMAKE_GENERATOR MATCHES "Visual Studio")
|
||||||
# If Microsoft SDK is installed create script run-msbuild.bat that
|
# If Microsoft SDK is installed create script run-msbuild.bat that
|
||||||
# calls SetEnv.cmd to to set up build environment and runs msbuild.
|
# calls SetEnv.cmd to to set up build environment and runs msbuild.
|
||||||
# It is useful when building Visual Studio projects with the SDK
|
# It is useful when building Visual Studio projects with the SDK
|
||||||
@ -72,63 +64,19 @@ if (CMAKE_GENERATOR MATCHES "Visual Studio")
|
|||||||
${CMAKE_MAKE_PROGRAM} -p:FrameworkPathOverride=\"${netfxpath}\" %*")
|
${CMAKE_MAKE_PROGRAM} -p:FrameworkPathOverride=\"${netfxpath}\" %*")
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
set(FMT_SOURCES format.cc format.h)
|
|
||||||
|
|
||||||
include(CheckSymbolExists)
|
include(CheckSymbolExists)
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
check_symbol_exists(open io.h HAVE_OPEN)
|
check_symbol_exists(open io.h HAVE_OPEN)
|
||||||
else ()
|
else ()
|
||||||
check_symbol_exists(open fcntl.h HAVE_OPEN)
|
check_symbol_exists(open fcntl.h HAVE_OPEN)
|
||||||
endif ()
|
endif ()
|
||||||
if (HAVE_OPEN)
|
|
||||||
add_definitions(-DFMT_USE_FILE_DESCRIPTORS=1)
|
|
||||||
set(FMT_SOURCES ${FMT_SOURCES} posix.cc posix.h)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
if (CPP11_FLAG)
|
|
||||||
set(CMAKE_REQUIRED_FLAGS ${CPP11_FLAG})
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
if (BIICODE)
|
if (BIICODE)
|
||||||
include(support/cmake/biicode.cmake)
|
include(support/cmake/biicode.cmake)
|
||||||
return()
|
return()
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
add_library(cppformat ${FMT_SOURCES})
|
add_subdirectory(cppformat)
|
||||||
if (BUILD_SHARED_LIBS)
|
|
||||||
if (UNIX AND NOT APPLE)
|
|
||||||
# Fix rpmlint warning:
|
|
||||||
# unused-direct-shlib-dependency /usr/lib/libformat.so.1.1.0 /lib/libm.so.6.
|
|
||||||
target_link_libraries(cppformat -Wl,--as-needed)
|
|
||||||
endif ()
|
|
||||||
set(FMT_EXTRA_COMPILE_FLAGS -DFMT_EXPORT)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
if (FMT_PEDANTIC AND
|
|
||||||
(CMAKE_COMPILER_IS_GNUCXX OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang")))
|
|
||||||
set(FMT_EXTRA_COMPILE_FLAGS
|
|
||||||
"${FMT_EXTRA_COMPILE_FLAGS} -Wall -Wextra -Wshadow -pedantic")
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
# If FMT_PEDANTIC is TRUE, then test compilation with both -std=c++11
|
|
||||||
# and the default flags. Otherwise use only the default flags.
|
|
||||||
# The library is distributed in the source form and users have full control
|
|
||||||
# over compile options, so the options used here only matter for testing.
|
|
||||||
if (CPP11_FLAG AND FMT_PEDANTIC)
|
|
||||||
set(FMT_EXTRA_COMPILE_FLAGS "${FMT_EXTRA_COMPILE_FLAGS} ${CPP11_FLAG}")
|
|
||||||
set(FMT_TEST_DEFAULT_FLAGS TRUE)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
set_target_properties(cppformat
|
|
||||||
PROPERTIES COMPILE_FLAGS "${FMT_EXTRA_COMPILE_FLAGS}")
|
|
||||||
|
|
||||||
set(CPPFORMAT_VERSION 2.1.0)
|
|
||||||
if (NOT CPPFORMAT_VERSION MATCHES "^([0-9]+).([0-9]+).([0-9]+)$")
|
|
||||||
message(FATAL_ERROR "Invalid version format ${CPPFORMAT_VERSION}.")
|
|
||||||
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})
|
|
||||||
|
|
||||||
if (FMT_DOC)
|
if (FMT_DOC)
|
||||||
add_subdirectory(doc)
|
add_subdirectory(doc)
|
||||||
@ -139,11 +87,8 @@ if (FMT_TEST)
|
|||||||
add_subdirectory(test)
|
add_subdirectory(test)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
set_target_properties(cppformat PROPERTIES
|
set(gitignore ${PROJECT_SOURCE_DIR}/.gitignore)
|
||||||
VERSION ${CPPFORMAT_VERSION} SOVERSION ${CPACK_PACKAGE_VERSION_MAJOR})
|
if (MASTER_PROJECT AND EXISTS ${gitignore})
|
||||||
|
|
||||||
set(gitignore ${CMAKE_CURRENT_SOURCE_DIR}/.gitignore)
|
|
||||||
if (EXISTS ${gitignore})
|
|
||||||
# Get the list of ignored files from .gitignore.
|
# Get the list of ignored files from .gitignore.
|
||||||
file (STRINGS ${gitignore} lines)
|
file (STRINGS ${gitignore} lines)
|
||||||
LIST(REMOVE_ITEM lines /doc/html)
|
LIST(REMOVE_ITEM lines /doc/html)
|
||||||
@ -159,45 +104,6 @@ if (EXISTS ${gitignore})
|
|||||||
set(CPACK_SOURCE_IGNORE_FILES ${ignored_files})
|
set(CPACK_SOURCE_IGNORE_FILES ${ignored_files})
|
||||||
set(CPACK_SOURCE_PACKAGE_FILE_NAME cppformat-${CPPFORMAT_VERSION})
|
set(CPACK_SOURCE_PACKAGE_FILE_NAME cppformat-${CPPFORMAT_VERSION})
|
||||||
set(CPACK_PACKAGE_NAME cppformat)
|
set(CPACK_PACKAGE_NAME cppformat)
|
||||||
set(CPACK_RESOURCE_FILE_README ${FORMAT_SOURCE_DIR}/README.rst)
|
set(CPACK_RESOURCE_FILE_README ${PROJECT_SOURCE_DIR}/README.rst)
|
||||||
include(CPack)
|
include(CPack)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
# Install targets.
|
|
||||||
if (FMT_INSTALL)
|
|
||||||
include(CMakePackageConfigHelpers)
|
|
||||||
set(config_install_dir lib/cmake/cppformat)
|
|
||||||
set(version_config ${CMAKE_CURRENT_BINARY_DIR}/cppformat-config-version.cmake)
|
|
||||||
set(project_config ${CMAKE_CURRENT_BINARY_DIR}/cppformat-config.cmake)
|
|
||||||
set(targets_export_name cppformat-targets)
|
|
||||||
|
|
||||||
set(FMT_LIB_DIR lib CACHE STRING
|
|
||||||
"Installation directory for libraries, relative to ${CMAKE_INSTALL_PREFIX}.")
|
|
||||||
|
|
||||||
# Add the include directories for both build and install tree.
|
|
||||||
target_include_directories(
|
|
||||||
cppformat PUBLIC
|
|
||||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
|
|
||||||
$<INSTALL_INTERFACE:include>)
|
|
||||||
|
|
||||||
# Generate the version, config and target files into the build directory.
|
|
||||||
write_basic_package_version_file(
|
|
||||||
${version_config}
|
|
||||||
VERSION ${CPPFORMAT_VERSION}
|
|
||||||
COMPATIBILITY AnyNewerVersion)
|
|
||||||
configure_package_config_file(
|
|
||||||
support/cmake/cppformat-config.cmake.in
|
|
||||||
${project_config}
|
|
||||||
INSTALL_DESTINATION ${config_install_dir})
|
|
||||||
export(TARGETS cppformat FILE ${targets_export_name}.cmake)
|
|
||||||
|
|
||||||
# Install version, config and target files.
|
|
||||||
install(
|
|
||||||
FILES ${project_config} ${version_config}
|
|
||||||
DESTINATION ${config_install_dir})
|
|
||||||
install(EXPORT ${targets_export_name} DESTINATION ${config_install_dir})
|
|
||||||
|
|
||||||
# Install the library and the include file.
|
|
||||||
install(TARGETS cppformat EXPORT ${targets_export_name} DESTINATION ${FMT_LIB_DIR})
|
|
||||||
install(FILES format.h DESTINATION include/cppformat)
|
|
||||||
endif ()
|
|
||||||
|
81
cppformat/CMakeLists.txt
Normal file
81
cppformat/CMakeLists.txt
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
#------------------------------------------------------------------------------
|
||||||
|
# define the cppformat library, its includes and the needed defines
|
||||||
|
set(FMT_HEADERS format.h)
|
||||||
|
set(FMT_SOURCES format.cc)
|
||||||
|
if (HAVE_OPEN)
|
||||||
|
set(FMT_HEADERS ${FMT_HEADERS} posix.h)
|
||||||
|
set(FMT_SOURCES ${FMT_SOURCES} posix.cc)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
add_library(cppformat ${FMT_SOURCES} ${FMT_HEADERS})
|
||||||
|
|
||||||
|
target_compile_options(cppformat PUBLIC ${CPP11_FLAG}) # starting with cmake 3.1 the CXX_STANDARD property can be used
|
||||||
|
if (FMT_PEDANTIC)
|
||||||
|
target_compile_options(cppformat PRIVATE ${PEDANTIC_COMPILE_FLAGS})
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
target_include_directories(cppformat INTERFACE
|
||||||
|
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}>
|
||||||
|
$<INSTALL_INTERFACE:include>)
|
||||||
|
|
||||||
|
set_target_properties(cppformat PROPERTIES
|
||||||
|
VERSION ${CPPFORMAT_VERSION} SOVERSION ${CPACK_PACKAGE_VERSION_MAJOR})
|
||||||
|
|
||||||
|
if (BUILD_SHARED_LIBS)
|
||||||
|
if (UNIX AND NOT APPLE)
|
||||||
|
# Fix rpmlint warning:
|
||||||
|
# unused-direct-shlib-dependency /usr/lib/libformat.so.1.1.0 /lib/libm.so.6.
|
||||||
|
target_link_libraries(cppformat -Wl,--as-needed)
|
||||||
|
endif ()
|
||||||
|
target_compile_definitions(cppformat 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(cppformat-header-only INTERFACE)
|
||||||
|
|
||||||
|
target_compile_definitions(cppformat-header-only INTERFACE FMT_HEADER_ONLY=1)
|
||||||
|
|
||||||
|
target_include_directories(cppformat-header-only INTERFACE
|
||||||
|
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}>
|
||||||
|
$<INSTALL_INTERFACE:include>)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
# Install targets.
|
||||||
|
if (FMT_INSTALL)
|
||||||
|
include(CMakePackageConfigHelpers)
|
||||||
|
set(config_install_dir lib/cmake/cppformat)
|
||||||
|
set(version_config ${PROJECT_BINARY_DIR}/cppformat-config-version.cmake)
|
||||||
|
set(project_config ${PROJECT_BINARY_DIR}/cppformat-config.cmake)
|
||||||
|
set(targets_export_name cppformat-targets)
|
||||||
|
|
||||||
|
set (INSTALL_TARGETS cppformat)
|
||||||
|
if (TARGET cppformat-header-only)
|
||||||
|
set(INSTALL_TARGETS ${INSTALL_TARGETS} cppformat-header-only)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
set(FMT_LIB_DIR lib CACHE STRING
|
||||||
|
"Installation directory for libraries, relative to ${CMAKE_INSTALL_PREFIX}.")
|
||||||
|
|
||||||
|
# Generate the version, config and target files into the build directory.
|
||||||
|
write_basic_package_version_file(
|
||||||
|
${version_config}
|
||||||
|
VERSION ${CPPFORMAT_VERSION}
|
||||||
|
COMPATIBILITY AnyNewerVersion)
|
||||||
|
configure_package_config_file(
|
||||||
|
${PROJECT_SOURCE_DIR}/support/cmake/cppformat-config.cmake.in
|
||||||
|
${project_config}
|
||||||
|
INSTALL_DESTINATION ${config_install_dir})
|
||||||
|
export(TARGETS ${INSTALL_TARGETS} FILE ${PROJECT_BINARY_DIR}/${targets_export_name}.cmake)
|
||||||
|
|
||||||
|
# Install version, config and target files.
|
||||||
|
install(
|
||||||
|
FILES ${project_config} ${version_config}
|
||||||
|
DESTINATION ${config_install_dir})
|
||||||
|
install(EXPORT ${targets_export_name} DESTINATION ${config_install_dir})
|
||||||
|
|
||||||
|
# Install the library and the include file.
|
||||||
|
install(TARGETS ${INSTALL_TARGETS} EXPORT ${targets_export_name} DESTINATION ${FMT_LIB_DIR})
|
||||||
|
install(FILES ${FMT_HEADERS} DESTINATION include/cppformat)
|
||||||
|
endif ()
|
3764
cppformat/format.h
Normal file
3764
cppformat/format.h
Normal file
File diff suppressed because it is too large
Load Diff
398
cppformat/posix.h
Normal file
398
cppformat/posix.h
Normal file
@ -0,0 +1,398 @@
|
|||||||
|
/*
|
||||||
|
A C++ interface to POSIX functions.
|
||||||
|
|
||||||
|
Copyright (c) 2014 - 2015, Victor Zverovich
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef FMT_POSIX_H_
|
||||||
|
#define FMT_POSIX_H_
|
||||||
|
|
||||||
|
#ifdef __MINGW32__
|
||||||
|
// Workaround MinGW bug https://sourceforge.net/p/mingw/bugs/2024/.
|
||||||
|
# undef __STRICT_ANSI__
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h> // for O_RDONLY
|
||||||
|
#include <locale.h> // for locale_t
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h> // for strtod_l
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
|
#include "format.h"
|
||||||
|
|
||||||
|
#ifndef FMT_POSIX
|
||||||
|
# if defined(_WIN32) && !defined(__MINGW32__)
|
||||||
|
// Fix warnings about deprecated symbols.
|
||||||
|
# define FMT_POSIX(call) _##call
|
||||||
|
# else
|
||||||
|
# define FMT_POSIX(call) call
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Calls to system functions are wrapped in FMT_SYSTEM for testability.
|
||||||
|
#ifdef FMT_SYSTEM
|
||||||
|
# define FMT_POSIX_CALL(call) FMT_SYSTEM(call)
|
||||||
|
#else
|
||||||
|
# define FMT_SYSTEM(call) call
|
||||||
|
# ifdef _WIN32
|
||||||
|
// Fix warnings about deprecated symbols.
|
||||||
|
# define FMT_POSIX_CALL(call) ::_##call
|
||||||
|
# else
|
||||||
|
# define FMT_POSIX_CALL(call) ::call
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if FMT_GCC_VERSION >= 407
|
||||||
|
# define FMT_UNUSED __attribute__((unused))
|
||||||
|
#else
|
||||||
|
# define FMT_UNUSED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef FMT_USE_STATIC_ASSERT
|
||||||
|
# define FMT_USE_STATIC_ASSERT 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if FMT_USE_STATIC_ASSERT || FMT_HAS_FEATURE(cxx_static_assert) || \
|
||||||
|
(FMT_GCC_VERSION >= 403 && FMT_HAS_GXX_CXX11) || _MSC_VER >= 1600
|
||||||
|
# define FMT_STATIC_ASSERT(cond, message) static_assert(cond, message)
|
||||||
|
#else
|
||||||
|
# define FMT_CONCAT_(a, b) FMT_CONCAT(a, b)
|
||||||
|
# define FMT_STATIC_ASSERT(cond, message) \
|
||||||
|
typedef int FMT_CONCAT_(Assert, __LINE__)[(cond) ? 1 : -1] FMT_UNUSED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Retries the expression while it evaluates to error_result and errno
|
||||||
|
// equals to EINTR.
|
||||||
|
#ifndef _WIN32
|
||||||
|
# define FMT_RETRY_VAL(result, expression, error_result) \
|
||||||
|
do { \
|
||||||
|
result = (expression); \
|
||||||
|
} while (result == error_result && errno == EINTR)
|
||||||
|
#else
|
||||||
|
# define FMT_RETRY_VAL(result, expression, error_result) result = (expression)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define FMT_RETRY(result, expression) FMT_RETRY_VAL(result, expression, -1)
|
||||||
|
|
||||||
|
namespace fmt {
|
||||||
|
|
||||||
|
// An error code.
|
||||||
|
class ErrorCode {
|
||||||
|
private:
|
||||||
|
int value_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit ErrorCode(int value = 0) FMT_NOEXCEPT : value_(value) {}
|
||||||
|
|
||||||
|
int get() const FMT_NOEXCEPT { return value_; }
|
||||||
|
};
|
||||||
|
|
||||||
|
// A buffered file.
|
||||||
|
class BufferedFile {
|
||||||
|
private:
|
||||||
|
FILE *file_;
|
||||||
|
|
||||||
|
friend class File;
|
||||||
|
|
||||||
|
explicit BufferedFile(FILE *f) : file_(f) {}
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Constructs a BufferedFile object which doesn't represent any file.
|
||||||
|
BufferedFile() FMT_NOEXCEPT : file_(0) {}
|
||||||
|
|
||||||
|
// Destroys the object closing the file it represents if any.
|
||||||
|
~BufferedFile() FMT_NOEXCEPT;
|
||||||
|
|
||||||
|
#if !FMT_USE_RVALUE_REFERENCES
|
||||||
|
// Emulate a move constructor and a move assignment operator if rvalue
|
||||||
|
// references are not supported.
|
||||||
|
|
||||||
|
private:
|
||||||
|
// A proxy object to emulate a move constructor.
|
||||||
|
// It is private to make it impossible call operator Proxy directly.
|
||||||
|
struct Proxy {
|
||||||
|
FILE *file;
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
// A "move constructor" for moving from a temporary.
|
||||||
|
BufferedFile(Proxy p) FMT_NOEXCEPT : file_(p.file) {}
|
||||||
|
|
||||||
|
// A "move constructor" for for moving from an lvalue.
|
||||||
|
BufferedFile(BufferedFile &f) FMT_NOEXCEPT : file_(f.file_) {
|
||||||
|
f.file_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A "move assignment operator" for moving from a temporary.
|
||||||
|
BufferedFile &operator=(Proxy p) {
|
||||||
|
close();
|
||||||
|
file_ = p.file;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A "move assignment operator" for moving from an lvalue.
|
||||||
|
BufferedFile &operator=(BufferedFile &other) {
|
||||||
|
close();
|
||||||
|
file_ = other.file_;
|
||||||
|
other.file_ = 0;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns a proxy object for moving from a temporary:
|
||||||
|
// BufferedFile file = BufferedFile(...);
|
||||||
|
operator Proxy() FMT_NOEXCEPT {
|
||||||
|
Proxy p = {file_};
|
||||||
|
file_ = 0;
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
private:
|
||||||
|
FMT_DISALLOW_COPY_AND_ASSIGN(BufferedFile);
|
||||||
|
|
||||||
|
public:
|
||||||
|
BufferedFile(BufferedFile &&other) FMT_NOEXCEPT : file_(other.file_) {
|
||||||
|
other.file_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
BufferedFile& operator=(BufferedFile &&other) {
|
||||||
|
close();
|
||||||
|
file_ = other.file_;
|
||||||
|
other.file_ = 0;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Opens a file.
|
||||||
|
BufferedFile(CStringRef filename, CStringRef mode);
|
||||||
|
|
||||||
|
// Closes the file.
|
||||||
|
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;
|
||||||
|
|
||||||
|
void print(CStringRef format_str, const ArgList &args) {
|
||||||
|
fmt::print(file_, format_str, args);
|
||||||
|
}
|
||||||
|
FMT_VARIADIC(void, print, CStringRef)
|
||||||
|
};
|
||||||
|
|
||||||
|
// A file. Closed file is represented by a File object with descriptor -1.
|
||||||
|
// Methods that are not declared with FMT_NOEXCEPT may throw
|
||||||
|
// fmt::SystemError in case of failure. Note that some errors such as
|
||||||
|
// closing the file multiple times will cause a crash on Windows rather
|
||||||
|
// than an exception. You can get standard behavior by overriding the
|
||||||
|
// invalid parameter handler with _set_invalid_parameter_handler.
|
||||||
|
class File {
|
||||||
|
private:
|
||||||
|
int fd_; // File descriptor.
|
||||||
|
|
||||||
|
// Constructs a File object with a given descriptor.
|
||||||
|
explicit File(int fd) : fd_(fd) {}
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Possible values for the oflag argument to the constructor.
|
||||||
|
enum {
|
||||||
|
RDONLY = FMT_POSIX(O_RDONLY), // Open for reading only.
|
||||||
|
WRONLY = FMT_POSIX(O_WRONLY), // Open for writing only.
|
||||||
|
RDWR = FMT_POSIX(O_RDWR) // Open for reading and writing.
|
||||||
|
};
|
||||||
|
|
||||||
|
// Constructs a File object which doesn't represent any file.
|
||||||
|
File() FMT_NOEXCEPT : fd_(-1) {}
|
||||||
|
|
||||||
|
// Opens a file and constructs a File object representing this file.
|
||||||
|
File(CStringRef path, int oflag);
|
||||||
|
|
||||||
|
#if !FMT_USE_RVALUE_REFERENCES
|
||||||
|
// Emulate a move constructor and a move assignment operator if rvalue
|
||||||
|
// references are not supported.
|
||||||
|
|
||||||
|
private:
|
||||||
|
// A proxy object to emulate a move constructor.
|
||||||
|
// It is private to make it impossible call operator Proxy directly.
|
||||||
|
struct Proxy {
|
||||||
|
int fd;
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
// A "move constructor" for moving from a temporary.
|
||||||
|
File(Proxy p) FMT_NOEXCEPT : fd_(p.fd) {}
|
||||||
|
|
||||||
|
// A "move constructor" for for moving from an lvalue.
|
||||||
|
File(File &other) FMT_NOEXCEPT : fd_(other.fd_) {
|
||||||
|
other.fd_ = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A "move assignment operator" for moving from a temporary.
|
||||||
|
File &operator=(Proxy p) {
|
||||||
|
close();
|
||||||
|
fd_ = p.fd;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A "move assignment operator" for moving from an lvalue.
|
||||||
|
File &operator=(File &other) {
|
||||||
|
close();
|
||||||
|
fd_ = other.fd_;
|
||||||
|
other.fd_ = -1;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns a proxy object for moving from a temporary:
|
||||||
|
// File file = File(...);
|
||||||
|
operator Proxy() FMT_NOEXCEPT {
|
||||||
|
Proxy p = {fd_};
|
||||||
|
fd_ = -1;
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
private:
|
||||||
|
FMT_DISALLOW_COPY_AND_ASSIGN(File);
|
||||||
|
|
||||||
|
public:
|
||||||
|
File(File &&other) FMT_NOEXCEPT : fd_(other.fd_) {
|
||||||
|
other.fd_ = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
File& operator=(File &&other) {
|
||||||
|
close();
|
||||||
|
fd_ = other.fd_;
|
||||||
|
other.fd_ = -1;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Destroys the object closing the file it represents if any.
|
||||||
|
~File() FMT_NOEXCEPT;
|
||||||
|
|
||||||
|
// Returns the file descriptor.
|
||||||
|
int descriptor() const FMT_NOEXCEPT { return fd_; }
|
||||||
|
|
||||||
|
// Closes the file.
|
||||||
|
void close();
|
||||||
|
|
||||||
|
// Returns the file size.
|
||||||
|
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);
|
||||||
|
|
||||||
|
// Attempts to write count bytes from the specified buffer to the file.
|
||||||
|
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);
|
||||||
|
|
||||||
|
// Makes fd be the copy of this file descriptor, closing fd first if
|
||||||
|
// necessary.
|
||||||
|
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;
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
// Creates a BufferedFile object associated with this file and detaches
|
||||||
|
// this File object from the file.
|
||||||
|
BufferedFile fdopen(const char *mode);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Returns the memory page size.
|
||||||
|
long getpagesize();
|
||||||
|
|
||||||
|
#if defined(LC_NUMERIC_MASK) || defined(_MSC_VER)
|
||||||
|
# define FMT_LOCALE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef FMT_LOCALE
|
||||||
|
// A "C" numeric locale.
|
||||||
|
class Locale {
|
||||||
|
private:
|
||||||
|
# ifdef _MSC_VER
|
||||||
|
typedef _locale_t locale_t;
|
||||||
|
|
||||||
|
enum { LC_NUMERIC_MASK = LC_NUMERIC };
|
||||||
|
|
||||||
|
static locale_t newlocale(int category_mask, const char *locale, locale_t) {
|
||||||
|
return _create_locale(category_mask, locale);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void freelocale(locale_t locale) {
|
||||||
|
_free_locale(locale);
|
||||||
|
}
|
||||||
|
|
||||||
|
static double strtod_l(const char *nptr, char **endptr, _locale_t locale) {
|
||||||
|
return _strtod_l(nptr, endptr, locale);
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
|
||||||
|
locale_t locale_;
|
||||||
|
|
||||||
|
FMT_DISALLOW_COPY_AND_ASSIGN(Locale);
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef locale_t Type;
|
||||||
|
|
||||||
|
Locale() : locale_(newlocale(LC_NUMERIC_MASK, "C", NULL)) {
|
||||||
|
if (!locale_)
|
||||||
|
throw fmt::SystemError(errno, "cannot create locale");
|
||||||
|
}
|
||||||
|
~Locale() { freelocale(locale_); }
|
||||||
|
|
||||||
|
Type get() const { return 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;
|
||||||
|
double result = strtod_l(str, &end, locale_);
|
||||||
|
str = end;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#endif // FMT_LOCALE
|
||||||
|
} // namespace fmt
|
||||||
|
|
||||||
|
#if !FMT_USE_RVALUE_REFERENCES
|
||||||
|
namespace std {
|
||||||
|
// For compatibility with C++98.
|
||||||
|
inline fmt::BufferedFile &move(fmt::BufferedFile &f) { return f; }
|
||||||
|
inline fmt::File &move(fmt::File &f) { return f; }
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // FMT_POSIX_H_
|
400
posix.h
400
posix.h
@ -1,398 +1,2 @@
|
|||||||
/*
|
#include "cppformat/posix.h"
|
||||||
A C++ interface to POSIX functions.
|
#warning Including posix.h from the top-level directory is deprecated.
|
||||||
|
|
||||||
Copyright (c) 2014 - 2015, Victor Zverovich
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
1. Redistributions of source code must retain the above copyright notice, this
|
|
||||||
list of conditions and the following disclaimer.
|
|
||||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
this list of conditions and the following disclaimer in the documentation
|
|
||||||
and/or other materials provided with the distribution.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
|
||||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef FMT_POSIX_H_
|
|
||||||
#define FMT_POSIX_H_
|
|
||||||
|
|
||||||
#ifdef __MINGW32__
|
|
||||||
// Workaround MinGW bug https://sourceforge.net/p/mingw/bugs/2024/.
|
|
||||||
# undef __STRICT_ANSI__
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
#include <fcntl.h> // for O_RDONLY
|
|
||||||
#include <locale.h> // for locale_t
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h> // for strtod_l
|
|
||||||
|
|
||||||
#include <cstddef>
|
|
||||||
|
|
||||||
#include "format.h"
|
|
||||||
|
|
||||||
#ifndef FMT_POSIX
|
|
||||||
# if defined(_WIN32) && !defined(__MINGW32__)
|
|
||||||
// Fix warnings about deprecated symbols.
|
|
||||||
# define FMT_POSIX(call) _##call
|
|
||||||
# else
|
|
||||||
# define FMT_POSIX(call) call
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Calls to system functions are wrapped in FMT_SYSTEM for testability.
|
|
||||||
#ifdef FMT_SYSTEM
|
|
||||||
# define FMT_POSIX_CALL(call) FMT_SYSTEM(call)
|
|
||||||
#else
|
|
||||||
# define FMT_SYSTEM(call) call
|
|
||||||
# ifdef _WIN32
|
|
||||||
// Fix warnings about deprecated symbols.
|
|
||||||
# define FMT_POSIX_CALL(call) ::_##call
|
|
||||||
# else
|
|
||||||
# define FMT_POSIX_CALL(call) ::call
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if FMT_GCC_VERSION >= 407
|
|
||||||
# define FMT_UNUSED __attribute__((unused))
|
|
||||||
#else
|
|
||||||
# define FMT_UNUSED
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef FMT_USE_STATIC_ASSERT
|
|
||||||
# define FMT_USE_STATIC_ASSERT 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if FMT_USE_STATIC_ASSERT || FMT_HAS_FEATURE(cxx_static_assert) || \
|
|
||||||
(FMT_GCC_VERSION >= 403 && FMT_HAS_GXX_CXX11) || _MSC_VER >= 1600
|
|
||||||
# define FMT_STATIC_ASSERT(cond, message) static_assert(cond, message)
|
|
||||||
#else
|
|
||||||
# define FMT_CONCAT_(a, b) FMT_CONCAT(a, b)
|
|
||||||
# define FMT_STATIC_ASSERT(cond, message) \
|
|
||||||
typedef int FMT_CONCAT_(Assert, __LINE__)[(cond) ? 1 : -1] FMT_UNUSED
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Retries the expression while it evaluates to error_result and errno
|
|
||||||
// equals to EINTR.
|
|
||||||
#ifndef _WIN32
|
|
||||||
# define FMT_RETRY_VAL(result, expression, error_result) \
|
|
||||||
do { \
|
|
||||||
result = (expression); \
|
|
||||||
} while (result == error_result && errno == EINTR)
|
|
||||||
#else
|
|
||||||
# define FMT_RETRY_VAL(result, expression, error_result) result = (expression)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define FMT_RETRY(result, expression) FMT_RETRY_VAL(result, expression, -1)
|
|
||||||
|
|
||||||
namespace fmt {
|
|
||||||
|
|
||||||
// An error code.
|
|
||||||
class ErrorCode {
|
|
||||||
private:
|
|
||||||
int value_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit ErrorCode(int value = 0) FMT_NOEXCEPT : value_(value) {}
|
|
||||||
|
|
||||||
int get() const FMT_NOEXCEPT { return value_; }
|
|
||||||
};
|
|
||||||
|
|
||||||
// A buffered file.
|
|
||||||
class BufferedFile {
|
|
||||||
private:
|
|
||||||
FILE *file_;
|
|
||||||
|
|
||||||
friend class File;
|
|
||||||
|
|
||||||
explicit BufferedFile(FILE *f) : file_(f) {}
|
|
||||||
|
|
||||||
public:
|
|
||||||
// Constructs a BufferedFile object which doesn't represent any file.
|
|
||||||
BufferedFile() FMT_NOEXCEPT : file_(0) {}
|
|
||||||
|
|
||||||
// Destroys the object closing the file it represents if any.
|
|
||||||
~BufferedFile() FMT_NOEXCEPT;
|
|
||||||
|
|
||||||
#if !FMT_USE_RVALUE_REFERENCES
|
|
||||||
// Emulate a move constructor and a move assignment operator if rvalue
|
|
||||||
// references are not supported.
|
|
||||||
|
|
||||||
private:
|
|
||||||
// A proxy object to emulate a move constructor.
|
|
||||||
// It is private to make it impossible call operator Proxy directly.
|
|
||||||
struct Proxy {
|
|
||||||
FILE *file;
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
// A "move constructor" for moving from a temporary.
|
|
||||||
BufferedFile(Proxy p) FMT_NOEXCEPT : file_(p.file) {}
|
|
||||||
|
|
||||||
// A "move constructor" for for moving from an lvalue.
|
|
||||||
BufferedFile(BufferedFile &f) FMT_NOEXCEPT : file_(f.file_) {
|
|
||||||
f.file_ = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// A "move assignment operator" for moving from a temporary.
|
|
||||||
BufferedFile &operator=(Proxy p) {
|
|
||||||
close();
|
|
||||||
file_ = p.file;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
// A "move assignment operator" for moving from an lvalue.
|
|
||||||
BufferedFile &operator=(BufferedFile &other) {
|
|
||||||
close();
|
|
||||||
file_ = other.file_;
|
|
||||||
other.file_ = 0;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns a proxy object for moving from a temporary:
|
|
||||||
// BufferedFile file = BufferedFile(...);
|
|
||||||
operator Proxy() FMT_NOEXCEPT {
|
|
||||||
Proxy p = {file_};
|
|
||||||
file_ = 0;
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
private:
|
|
||||||
FMT_DISALLOW_COPY_AND_ASSIGN(BufferedFile);
|
|
||||||
|
|
||||||
public:
|
|
||||||
BufferedFile(BufferedFile &&other) FMT_NOEXCEPT : file_(other.file_) {
|
|
||||||
other.file_ = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
BufferedFile& operator=(BufferedFile &&other) {
|
|
||||||
close();
|
|
||||||
file_ = other.file_;
|
|
||||||
other.file_ = 0;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Opens a file.
|
|
||||||
BufferedFile(CStringRef filename, CStringRef mode);
|
|
||||||
|
|
||||||
// Closes the file.
|
|
||||||
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;
|
|
||||||
|
|
||||||
void print(CStringRef format_str, const ArgList &args) {
|
|
||||||
fmt::print(file_, format_str, args);
|
|
||||||
}
|
|
||||||
FMT_VARIADIC(void, print, CStringRef)
|
|
||||||
};
|
|
||||||
|
|
||||||
// A file. Closed file is represented by a File object with descriptor -1.
|
|
||||||
// Methods that are not declared with FMT_NOEXCEPT may throw
|
|
||||||
// fmt::SystemError in case of failure. Note that some errors such as
|
|
||||||
// closing the file multiple times will cause a crash on Windows rather
|
|
||||||
// than an exception. You can get standard behavior by overriding the
|
|
||||||
// invalid parameter handler with _set_invalid_parameter_handler.
|
|
||||||
class File {
|
|
||||||
private:
|
|
||||||
int fd_; // File descriptor.
|
|
||||||
|
|
||||||
// Constructs a File object with a given descriptor.
|
|
||||||
explicit File(int fd) : fd_(fd) {}
|
|
||||||
|
|
||||||
public:
|
|
||||||
// Possible values for the oflag argument to the constructor.
|
|
||||||
enum {
|
|
||||||
RDONLY = FMT_POSIX(O_RDONLY), // Open for reading only.
|
|
||||||
WRONLY = FMT_POSIX(O_WRONLY), // Open for writing only.
|
|
||||||
RDWR = FMT_POSIX(O_RDWR) // Open for reading and writing.
|
|
||||||
};
|
|
||||||
|
|
||||||
// Constructs a File object which doesn't represent any file.
|
|
||||||
File() FMT_NOEXCEPT : fd_(-1) {}
|
|
||||||
|
|
||||||
// Opens a file and constructs a File object representing this file.
|
|
||||||
File(CStringRef path, int oflag);
|
|
||||||
|
|
||||||
#if !FMT_USE_RVALUE_REFERENCES
|
|
||||||
// Emulate a move constructor and a move assignment operator if rvalue
|
|
||||||
// references are not supported.
|
|
||||||
|
|
||||||
private:
|
|
||||||
// A proxy object to emulate a move constructor.
|
|
||||||
// It is private to make it impossible call operator Proxy directly.
|
|
||||||
struct Proxy {
|
|
||||||
int fd;
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
// A "move constructor" for moving from a temporary.
|
|
||||||
File(Proxy p) FMT_NOEXCEPT : fd_(p.fd) {}
|
|
||||||
|
|
||||||
// A "move constructor" for for moving from an lvalue.
|
|
||||||
File(File &other) FMT_NOEXCEPT : fd_(other.fd_) {
|
|
||||||
other.fd_ = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// A "move assignment operator" for moving from a temporary.
|
|
||||||
File &operator=(Proxy p) {
|
|
||||||
close();
|
|
||||||
fd_ = p.fd;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
// A "move assignment operator" for moving from an lvalue.
|
|
||||||
File &operator=(File &other) {
|
|
||||||
close();
|
|
||||||
fd_ = other.fd_;
|
|
||||||
other.fd_ = -1;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns a proxy object for moving from a temporary:
|
|
||||||
// File file = File(...);
|
|
||||||
operator Proxy() FMT_NOEXCEPT {
|
|
||||||
Proxy p = {fd_};
|
|
||||||
fd_ = -1;
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
private:
|
|
||||||
FMT_DISALLOW_COPY_AND_ASSIGN(File);
|
|
||||||
|
|
||||||
public:
|
|
||||||
File(File &&other) FMT_NOEXCEPT : fd_(other.fd_) {
|
|
||||||
other.fd_ = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
File& operator=(File &&other) {
|
|
||||||
close();
|
|
||||||
fd_ = other.fd_;
|
|
||||||
other.fd_ = -1;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Destroys the object closing the file it represents if any.
|
|
||||||
~File() FMT_NOEXCEPT;
|
|
||||||
|
|
||||||
// Returns the file descriptor.
|
|
||||||
int descriptor() const FMT_NOEXCEPT { return fd_; }
|
|
||||||
|
|
||||||
// Closes the file.
|
|
||||||
void close();
|
|
||||||
|
|
||||||
// Returns the file size.
|
|
||||||
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);
|
|
||||||
|
|
||||||
// Attempts to write count bytes from the specified buffer to the file.
|
|
||||||
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);
|
|
||||||
|
|
||||||
// Makes fd be the copy of this file descriptor, closing fd first if
|
|
||||||
// necessary.
|
|
||||||
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;
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
|
|
||||||
// Creates a BufferedFile object associated with this file and detaches
|
|
||||||
// this File object from the file.
|
|
||||||
BufferedFile fdopen(const char *mode);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Returns the memory page size.
|
|
||||||
long getpagesize();
|
|
||||||
|
|
||||||
#if defined(LC_NUMERIC_MASK) || defined(_MSC_VER)
|
|
||||||
# define FMT_LOCALE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef FMT_LOCALE
|
|
||||||
// A "C" numeric locale.
|
|
||||||
class Locale {
|
|
||||||
private:
|
|
||||||
# ifdef _MSC_VER
|
|
||||||
typedef _locale_t locale_t;
|
|
||||||
|
|
||||||
enum { LC_NUMERIC_MASK = LC_NUMERIC };
|
|
||||||
|
|
||||||
static locale_t newlocale(int category_mask, const char *locale, locale_t) {
|
|
||||||
return _create_locale(category_mask, locale);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void freelocale(locale_t locale) {
|
|
||||||
_free_locale(locale);
|
|
||||||
}
|
|
||||||
|
|
||||||
static double strtod_l(const char *nptr, char **endptr, _locale_t locale) {
|
|
||||||
return _strtod_l(nptr, endptr, locale);
|
|
||||||
}
|
|
||||||
# endif
|
|
||||||
|
|
||||||
locale_t locale_;
|
|
||||||
|
|
||||||
FMT_DISALLOW_COPY_AND_ASSIGN(Locale);
|
|
||||||
|
|
||||||
public:
|
|
||||||
typedef locale_t Type;
|
|
||||||
|
|
||||||
Locale() : locale_(newlocale(LC_NUMERIC_MASK, "C", NULL)) {
|
|
||||||
if (!locale_)
|
|
||||||
throw fmt::SystemError(errno, "cannot create locale");
|
|
||||||
}
|
|
||||||
~Locale() { freelocale(locale_); }
|
|
||||||
|
|
||||||
Type get() const { return 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;
|
|
||||||
double result = strtod_l(str, &end, locale_);
|
|
||||||
str = end;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
#endif // FMT_LOCALE
|
|
||||||
} // namespace fmt
|
|
||||||
|
|
||||||
#if !FMT_USE_RVALUE_REFERENCES
|
|
||||||
namespace std {
|
|
||||||
// For compatibility with C++98.
|
|
||||||
inline fmt::BufferedFile &move(fmt::BufferedFile &f) { return f; }
|
|
||||||
inline fmt::File &move(fmt::File &f) { return f; }
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // FMT_POSIX_H_
|
|
||||||
|
@ -24,8 +24,8 @@ else:
|
|||||||
if platform == 'x64':
|
if platform == 'x64':
|
||||||
generator += ' Win64'
|
generator += ' Win64'
|
||||||
cmake_command.append('-G' + generator)
|
cmake_command.append('-G' + generator)
|
||||||
build_command = ['msbuild', '/m:4', '/p:Config=' + config, 'FORMAT.sln']
|
build_command = ['cmake', '--build', '.', '--config', config, '--', '/m:4']
|
||||||
test_command = ['msbuild', 'RUN_TESTS.vcxproj']
|
test_command = ['ctest', '-C', config]
|
||||||
|
|
||||||
check_call(cmake_command)
|
check_call(cmake_command)
|
||||||
check_call(build_command)
|
check_call(build_command)
|
||||||
|
58
support/cmake/testCxx11.cmake
Normal file
58
support/cmake/testCxx11.cmake
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
include(CheckCXXCompilerFlag)
|
||||||
|
|
||||||
|
check_cxx_compiler_flag(-std=c++11 HAVE_STD_CPP11_FLAG)
|
||||||
|
if (HAVE_STD_CPP11_FLAG)
|
||||||
|
# Check if including cmath works with -std=c++11 and -O3.
|
||||||
|
# It may not in MinGW due to bug http://ehc.ac/p/mingw/bugs/2250/.
|
||||||
|
set(CMAKE_REQUIRED_FLAGS "-std=c++11 -O3")
|
||||||
|
check_cxx_source_compiles("
|
||||||
|
#include <cmath>
|
||||||
|
int main() {}" FMT_CPP11_CMATH)
|
||||||
|
# Check if including <unistd.h> works with -std=c++11.
|
||||||
|
# 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_CPP11_UNISTD_H)
|
||||||
|
if (FMT_CPP11_CMATH AND FMT_CPP11_UNISTD_H)
|
||||||
|
set(CPP11_FLAG -std=c++11)
|
||||||
|
else ()
|
||||||
|
check_cxx_compiler_flag(-std=gnu++11 HAVE_STD_GNUPP11_FLAG)
|
||||||
|
if (HAVE_STD_CPP11_FLAG)
|
||||||
|
set(CPP11_FLAG -std=gnu++11)
|
||||||
|
endif ()
|
||||||
|
endif ()
|
||||||
|
set(CMAKE_REQUIRED_FLAGS )
|
||||||
|
else ()
|
||||||
|
check_cxx_compiler_flag(-std=c++0x HAVE_STD_CPP0X_FLAG)
|
||||||
|
if (HAVE_STD_CPP0X_FLAG)
|
||||||
|
set(CPP11_FLAG -std=c++0x)
|
||||||
|
endif ()
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
|
||||||
|
set(CMAKE_REQUIRED_FLAGS ${CPP11_FLAG})
|
||||||
|
# Check if variadic templates are working and not affected by GCC bug 39653:
|
||||||
|
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=39653
|
||||||
|
check_cxx_source_compiles("
|
||||||
|
template <class T, class ...Types>
|
||||||
|
struct S { typedef typename S<Types...>::type type; };
|
||||||
|
int main() {}" SUPPORTS_VARIADIC_TEMPLATES)
|
||||||
|
|
||||||
|
# Check if initializer lists are supported.
|
||||||
|
check_cxx_source_compiles("
|
||||||
|
#include <initializer_list>
|
||||||
|
int main() {}" SUPPORTS_INITIALIZER_LIST)
|
||||||
|
|
||||||
|
# Check if enum bases are available
|
||||||
|
check_cxx_source_compiles("
|
||||||
|
enum C : char {A};
|
||||||
|
int main() {}"
|
||||||
|
SUPPORTS_ENUM_BASE)
|
||||||
|
|
||||||
|
# Check if type traits are available
|
||||||
|
check_cxx_source_compiles("
|
||||||
|
#include <type_traits>
|
||||||
|
class C { void operator=(const C&); };
|
||||||
|
int main() { static_assert(!std::is_copy_assignable<C>::value, \"\"); }"
|
||||||
|
SUPPORTS_TYPE_TRAITS)
|
||||||
|
set(CMAKE_REQUIRED_FLAGS )
|
@ -1,24 +1,17 @@
|
|||||||
set(FMT_GMOCK_DIR ../gmock)
|
#------------------------------------------------------------------------------
|
||||||
|
# Build the google test library
|
||||||
include_directories(.. ${FMT_GMOCK_DIR})
|
|
||||||
|
|
||||||
# Links target with cppformat and any libraries passed as extra arguments.
|
|
||||||
function (target_link_cppformat target)
|
|
||||||
target_link_libraries(${target} cppformat ${ARGN})
|
|
||||||
if (BUILD_SHARED_LIBS)
|
|
||||||
set_target_properties(${target} PROPERTIES COMPILE_FLAGS -DFMT_SHARED)
|
|
||||||
endif ()
|
|
||||||
endfunction ()
|
|
||||||
|
|
||||||
# We compile Google Test ourselves instead of using pre-compiled libraries.
|
# We compile Google Test ourselves instead of using pre-compiled libraries.
|
||||||
# See the Google Test FAQ "Why is it not recommended to install a
|
# See the Google Test FAQ "Why is it not recommended to install a
|
||||||
# pre-compiled copy of Google Test (for example, into /usr/local)?"
|
# pre-compiled copy of Google Test (for example, into /usr/local)?"
|
||||||
# at http://code.google.com/p/googletest/wiki/FAQ for more details.
|
# at http://code.google.com/p/googletest/wiki/FAQ for more details.
|
||||||
|
set(FMT_GMOCK_DIR ../gmock)
|
||||||
add_library(gmock STATIC
|
add_library(gmock STATIC
|
||||||
${FMT_GMOCK_DIR}/gmock-gtest-all.cc ${FMT_GMOCK_DIR}/gmock/gmock.h
|
${FMT_GMOCK_DIR}/gmock-gtest-all.cc ${FMT_GMOCK_DIR}/gmock/gmock.h
|
||||||
${FMT_GMOCK_DIR}/gtest/gtest.h ${FMT_GMOCK_DIR}/gtest/gtest-spi.h)
|
${FMT_GMOCK_DIR}/gtest/gtest.h ${FMT_GMOCK_DIR}/gtest/gtest-spi.h)
|
||||||
target_include_directories(gmock INTERFACE ${FMT_GMOCK_DIR})
|
target_include_directories(gmock PUBLIC ${FMT_GMOCK_DIR})
|
||||||
|
target_compile_options(gmock PUBLIC ${CPP11_FLAG})
|
||||||
|
|
||||||
find_package(Threads)
|
find_package(Threads)
|
||||||
if (Threads_FOUND)
|
if (Threads_FOUND)
|
||||||
target_link_libraries(gmock ${CMAKE_THREAD_LIBS_INIT})
|
target_link_libraries(gmock ${CMAKE_THREAD_LIBS_INIT})
|
||||||
@ -26,20 +19,8 @@ else ()
|
|||||||
target_compile_definitions(gmock PUBLIC GTEST_HAS_PTHREAD=0)
|
target_compile_definitions(gmock PUBLIC GTEST_HAS_PTHREAD=0)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
# Check if variadic templates are working and not affected by GCC bug 39653:
|
if (NOT SUPPORTS_VARIADIC_TEMPLATES OR NOT SUPPORTS_INITIALIZER_LIST)
|
||||||
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=39653
|
target_compile_definitions(gmock PUBLIC GTEST_LANG_CXX11=0)
|
||||||
check_cxx_source_compiles("
|
|
||||||
template <class T, class ...Types>
|
|
||||||
struct S { typedef typename S<Types...>::type type; };
|
|
||||||
int main() {}" FMT_VARIADIC_TEMPLATES)
|
|
||||||
|
|
||||||
# Check if initializer lists are supported.
|
|
||||||
check_cxx_source_compiles("
|
|
||||||
#include <initializer_list>
|
|
||||||
int main() {}" FMT_INITIALIZER_LIST)
|
|
||||||
|
|
||||||
if (NOT FMT_VARIADIC_TEMPLATES OR NOT FMT_INITIALIZER_LIST)
|
|
||||||
add_definitions(-DGTEST_LANG_CXX11=0)
|
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
# Workaround a bug in implementation of variadic templates in MSVC11.
|
# Workaround a bug in implementation of variadic templates in MSVC11.
|
||||||
@ -52,18 +33,32 @@ if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
|||||||
target_compile_definitions(gmock PUBLIC GTEST_USE_OWN_TR1_TUPLE=1)
|
target_compile_definitions(gmock PUBLIC GTEST_USE_OWN_TR1_TUPLE=1)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
# Build the actual library tests
|
||||||
|
|
||||||
set(TEST_MAIN_SRC test-main.cc gtest-extra.cc gtest-extra.h util.cc)
|
set(TEST_MAIN_SRC test-main.cc gtest-extra.cc gtest-extra.h util.cc)
|
||||||
add_library(test-main STATIC ${TEST_MAIN_SRC})
|
add_library(test-main STATIC ${TEST_MAIN_SRC})
|
||||||
target_link_cppformat(test-main gmock)
|
target_compile_definitions(test-main PUBLIC
|
||||||
|
FMT_USE_FILE_DESCRIPTORS=$<BOOL:${HAVE_OPEN}>)
|
||||||
|
target_link_libraries(test-main gmock cppformat)
|
||||||
|
|
||||||
|
# relax pedantic flags for the tests
|
||||||
|
# TODO: fix warnings in tests to make this redundant. (e.g. -Wshadow,...)
|
||||||
|
if (CMAKE_COMPILER_IS_GNUCXX OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang"))
|
||||||
|
set(PEDANTIC_COMPILE_FLAGS -Wall -Wextra -pedantic -Wno-long-long -Wno-variadic-macros)
|
||||||
|
endif ()
|
||||||
|
|
||||||
# Adds a test.
|
# Adds a test.
|
||||||
# Usage: add_fmt_test(name [CUSTOM_LINK] srcs...)
|
# Usage: add_fmt_test(name srcs...)
|
||||||
function(add_fmt_test name)
|
function(add_fmt_test name)
|
||||||
cmake_parse_arguments(add_fmt_test CUSTOM_LINK "" "" ${ARGN})
|
add_executable(${name} ${name}.cc ${ARGN})
|
||||||
add_executable(${name} ${name}.cc ${add_fmt_test_UNPARSED_ARGUMENTS})
|
|
||||||
target_link_libraries(${name} test-main)
|
target_link_libraries(${name} test-main)
|
||||||
if (NOT add_fmt_test_CUSTOM_LINK)
|
# define if certain c++ features can be used
|
||||||
target_link_cppformat(${name})
|
target_compile_definitions(${name} PRIVATE
|
||||||
|
FMT_USE_TYPE_TRAITS=$<BOOL:${SUPPORTS_TYPE_TRAITS}>
|
||||||
|
FMT_USE_ENUM_BASE=$<BOOL:${SUPPORTS_ENUM_BASE}>)
|
||||||
|
if (FMT_PEDANTIC)
|
||||||
|
target_compile_options(${name} PRIVATE ${PEDANTIC_COMPILE_FLAGS})
|
||||||
endif ()
|
endif ()
|
||||||
add_test(NAME ${name} COMMAND ${name})
|
add_test(NAME ${name} COMMAND ${name})
|
||||||
endfunction()
|
endfunction()
|
||||||
@ -71,56 +66,22 @@ endfunction()
|
|||||||
add_fmt_test(assert-test)
|
add_fmt_test(assert-test)
|
||||||
add_fmt_test(gtest-extra-test)
|
add_fmt_test(gtest-extra-test)
|
||||||
add_fmt_test(format-test)
|
add_fmt_test(format-test)
|
||||||
if (FMT_PEDANTIC AND MSVC)
|
add_fmt_test(format-impl-test)
|
||||||
set_target_properties(format-test PROPERTIES COMPILE_FLAGS /W4)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
add_fmt_test(format-impl-test CUSTOM_LINK)
|
|
||||||
add_fmt_test(printf-test)
|
add_fmt_test(printf-test)
|
||||||
foreach (target format-test printf-test)
|
|
||||||
if (FMT_PEDANTIC AND CMAKE_COMPILER_IS_GNUCXX)
|
|
||||||
set_target_properties(${target} PROPERTIES COMPILE_FLAGS
|
|
||||||
"-Wall -Wextra -pedantic -Wno-long-long -Wno-variadic-macros")
|
|
||||||
endif ()
|
|
||||||
if (CPP11_FLAG)
|
|
||||||
set_target_properties(${target} PROPERTIES COMPILE_FLAGS ${CPP11_FLAG})
|
|
||||||
endif ()
|
|
||||||
endforeach ()
|
|
||||||
add_fmt_test(util-test mock-allocator.h)
|
add_fmt_test(util-test mock-allocator.h)
|
||||||
if (CPP11_FLAG)
|
add_fmt_test(macro-test)
|
||||||
set_target_properties(util-test PROPERTIES COMPILE_FLAGS ${CPP11_FLAG})
|
|
||||||
|
# Enable stricter options for one test to make sure that the header is free of
|
||||||
|
# warnings.
|
||||||
|
# TODO: make all tests warning free and add this flag to PEDANTIC_COMPILE_FLAGS
|
||||||
|
if (FMT_PEDANTIC AND MSVC)
|
||||||
|
target_compile_options(format-test PRIVATE /W4)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
check_cxx_source_compiles("
|
|
||||||
enum C : char {A};
|
|
||||||
int main() {}"
|
|
||||||
HAVE_ENUM_BASE)
|
|
||||||
if (HAVE_ENUM_BASE)
|
|
||||||
set_target_properties(util-test
|
|
||||||
PROPERTIES COMPILE_DEFINITIONS "FMT_USE_ENUM_BASE=1")
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
foreach (src ${FMT_SOURCES})
|
|
||||||
set(FMT_TEST_SOURCES ${FMT_TEST_SOURCES} ../${src})
|
|
||||||
endforeach ()
|
|
||||||
|
|
||||||
check_cxx_source_compiles("
|
|
||||||
#include <type_traits>
|
|
||||||
class C { void operator=(const C&); };
|
|
||||||
int main() { static_assert(!std::is_copy_assignable<C>::value, \"\"); }"
|
|
||||||
HAVE_TYPE_TRAITS)
|
|
||||||
if (HAVE_TYPE_TRAITS)
|
|
||||||
foreach (target format-test util-test)
|
|
||||||
set_target_properties(${target}
|
|
||||||
PROPERTIES COMPILE_DEFINITIONS "FMT_USE_TYPE_TRAITS=1")
|
|
||||||
endforeach ()
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
add_executable(macro-test macro-test.cc ${FMT_TEST_SOURCES} ${TEST_MAIN_SRC})
|
|
||||||
target_link_libraries(macro-test gmock)
|
|
||||||
|
|
||||||
if (HAVE_OPEN)
|
if (HAVE_OPEN)
|
||||||
add_executable(posix-mock-test posix-mock-test.cc ../format.cc ${TEST_MAIN_SRC})
|
add_executable(posix-mock-test posix-mock-test.cc ../cppformat/format.cc ${TEST_MAIN_SRC})
|
||||||
|
target_include_directories(posix-mock-test PRIVATE ${PROJECT_SOURCE_DIR})
|
||||||
|
target_compile_definitions(posix-mock-test PRIVATE FMT_USE_FILE_DESCRIPTORS=1)
|
||||||
target_link_libraries(posix-mock-test gmock)
|
target_link_libraries(posix-mock-test gmock)
|
||||||
add_test(NAME posix-mock-test COMMAND posix-mock-test)
|
add_test(NAME posix-mock-test COMMAND posix-mock-test)
|
||||||
add_fmt_test(posix-test)
|
add_fmt_test(posix-test)
|
||||||
@ -128,28 +89,40 @@ endif ()
|
|||||||
|
|
||||||
add_executable(header-only-test
|
add_executable(header-only-test
|
||||||
header-only-test.cc header-only-test2.cc test-main.cc)
|
header-only-test.cc header-only-test2.cc test-main.cc)
|
||||||
set_target_properties(header-only-test
|
|
||||||
PROPERTIES COMPILE_DEFINITIONS "FMT_HEADER_ONLY=1")
|
|
||||||
target_link_libraries(header-only-test gmock)
|
target_link_libraries(header-only-test gmock)
|
||||||
|
if (TARGET cppformat-header-only)
|
||||||
|
target_link_libraries(header-only-test cppformat-header-only)
|
||||||
|
else ()
|
||||||
|
target_include_directories(header-only-test PRIVATE ${PROJECT_SOURCE_DIR})
|
||||||
|
target_compile_definitions(header-only-test PRIVATE FMT_HEADER_ONLY=1)
|
||||||
|
endif ()
|
||||||
|
|
||||||
# Test that the library can be compiled with exceptions disabled.
|
# Test that the library can be compiled with exceptions disabled.
|
||||||
check_cxx_compiler_flag(-fno-exceptions HAVE_FNO_EXCEPTIONS_FLAG)
|
check_cxx_compiler_flag(-fno-exceptions HAVE_FNO_EXCEPTIONS_FLAG)
|
||||||
if (HAVE_FNO_EXCEPTIONS_FLAG)
|
if (HAVE_FNO_EXCEPTIONS_FLAG)
|
||||||
add_library(noexception-test STATIC ../format.cc)
|
add_library(noexception-test ../cppformat/format.cc)
|
||||||
set_target_properties(noexception-test
|
target_compile_options(noexception-test PRIVATE -fno-exceptions)
|
||||||
PROPERTIES COMPILE_FLAGS -fno-exceptions)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
# Test compilation with default flags.
|
|
||||||
if (FMT_TEST_DEFAULT_FLAGS)
|
|
||||||
file(GLOB src RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.cc *.h)
|
|
||||||
foreach (s ${FMT_SOURCES})
|
|
||||||
set(src ${src} ../${s})
|
|
||||||
endforeach ()
|
|
||||||
add_library(testformat STATIC ${src})
|
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
if (FMT_PEDANTIC)
|
if (FMT_PEDANTIC)
|
||||||
|
# syntax test which checks if the library builds in gnu++98 mode
|
||||||
|
file(GLOB test_src *.cc *.h)
|
||||||
|
file(GLOB lib_src ../cppformat/*.cc ../cppformat/*.h)
|
||||||
|
add_library(testformat STATIC ${test_src} ${lib_src})
|
||||||
|
target_include_directories(testformat PRIVATE .. ../gmock)
|
||||||
|
target_compile_definitions(testformat PRIVATE
|
||||||
|
FMT_USE_FILE_DESCRIPTORS=$<BOOL:${HAVE_OPEN}>)
|
||||||
|
check_cxx_compiler_flag(-std=gnu++98 HAVE_STD_GNUPP98_FLAG)
|
||||||
|
if (HAVE_STD_GNUPP98_FLAG)
|
||||||
|
target_compile_options(testformat PRIVATE -std=gnu++98)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
# Test that the library compiles without windows.h.
|
||||||
|
if (CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
||||||
|
add_library(no-windows-h-test ../cppformat/format.cc)
|
||||||
|
target_compile_definitions(no-windows-h-test PRIVATE FMT_USE_WINDOWS_H=0)
|
||||||
|
endif ()
|
||||||
|
|
||||||
add_test(compile-test ${CMAKE_CTEST_COMMAND}
|
add_test(compile-test ${CMAKE_CTEST_COMMAND}
|
||||||
--build-and-test
|
--build-and-test
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/compile-test"
|
"${CMAKE_CURRENT_SOURCE_DIR}/compile-test"
|
||||||
@ -157,8 +130,24 @@ if (FMT_PEDANTIC)
|
|||||||
--build-generator ${CMAKE_GENERATOR}
|
--build-generator ${CMAKE_GENERATOR}
|
||||||
--build-makeprogram ${CMAKE_MAKE_PROGRAM})
|
--build-makeprogram ${CMAKE_MAKE_PROGRAM})
|
||||||
|
|
||||||
# Test that the library compiles without windows.h.
|
# test if the targets are findable from the build directory
|
||||||
add_library(no-windows-h-test ../format.cc)
|
add_test(find-package-test ${CMAKE_CTEST_COMMAND}
|
||||||
set_target_properties(no-windows-h-test
|
-C ${CMAKE_BUILD_TYPE}
|
||||||
PROPERTIES COMPILE_DEFINITIONS "FMT_USE_WINDOWS_H=0")
|
--build-and-test
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/find-package-test"
|
||||||
|
"${CMAKE_CURRENT_BINARY_DIR}/find-package-test"
|
||||||
|
--build-generator ${CMAKE_GENERATOR}
|
||||||
|
--build-makeprogram ${CMAKE_MAKE_PROGRAM}
|
||||||
|
--build-options "-Dcppformat_DIR=${PROJECT_BINARY_DIR}"
|
||||||
|
"-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}")
|
||||||
|
|
||||||
|
# test if the targets are findable when add_subdirectory is used
|
||||||
|
add_test(add_subdirectory-test ${CMAKE_CTEST_COMMAND}
|
||||||
|
-C ${CMAKE_BUILD_TYPE}
|
||||||
|
--build-and-test
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/add_subdirectory-test"
|
||||||
|
"${CMAKE_CURRENT_BINARY_DIR}/add_subdirectory-test"
|
||||||
|
--build-generator ${CMAKE_GENERATOR}
|
||||||
|
--build-makeprogram ${CMAKE_MAKE_PROGRAM}
|
||||||
|
--build-options "-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}")
|
||||||
endif ()
|
endif ()
|
||||||
|
13
test/add_subdirectory-test/CMakeLists.txt
Normal file
13
test/add_subdirectory-test/CMakeLists.txt
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
cmake_minimum_required(VERSION 2.8.12)
|
||||||
|
|
||||||
|
project(cppformat-test)
|
||||||
|
|
||||||
|
add_subdirectory(../.. cppformat)
|
||||||
|
|
||||||
|
add_executable(library-test "main.cpp")
|
||||||
|
target_link_libraries(library-test cppformat)
|
||||||
|
|
||||||
|
if (TARGET cppformat-header-only)
|
||||||
|
add_executable(header-only-test "main.cpp")
|
||||||
|
target_link_libraries(header-only-test cppformat-header-only)
|
||||||
|
endif ()
|
8
test/add_subdirectory-test/main.cpp
Normal file
8
test/add_subdirectory-test/main.cpp
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#include "cppformat/format.h"
|
||||||
|
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
for(int i = 0; i < argc; ++i)
|
||||||
|
fmt::print("{}: {}\n", i, argv[i]);
|
||||||
|
return 0;
|
||||||
|
}
|
@ -25,7 +25,7 @@
|
|||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "format.h"
|
#include "cppformat/format.h"
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
#if GTEST_HAS_DEATH_TEST
|
#if GTEST_HAS_DEATH_TEST
|
||||||
|
@ -5,23 +5,41 @@ cmake_minimum_required(VERSION 2.8)
|
|||||||
include(CheckCXXSourceCompiles)
|
include(CheckCXXSourceCompiles)
|
||||||
set(CMAKE_REQUIRED_INCLUDES ${CMAKE_CURRENT_SOURCE_DIR}/../..)
|
set(CMAKE_REQUIRED_INCLUDES ${CMAKE_CURRENT_SOURCE_DIR}/../..)
|
||||||
|
|
||||||
function (expect_compile_error code)
|
function (generate_source result fragment)
|
||||||
check_cxx_source_compiles("
|
set(${result} "
|
||||||
#include \"format.cc\"
|
#define FMT_HEADER_ONLY 1
|
||||||
#include \"posix.h\"
|
#include \"cppformat/format.h\"
|
||||||
int main() {
|
int main() {
|
||||||
${code}
|
${fragment}
|
||||||
}
|
}
|
||||||
" compiles)
|
" PARENT_SCOPE)
|
||||||
set (does_compile ${compiles})
|
endfunction ()
|
||||||
|
|
||||||
|
function (expect_compile code)
|
||||||
|
generate_source(source "${code}")
|
||||||
|
check_cxx_source_compiles("${source}" compiles)
|
||||||
|
if (NOT compiles)
|
||||||
|
message(FATAL_ERROR "Compile error for: ${code}")
|
||||||
|
endif ()
|
||||||
# Unset the CMake cache variable compiles. Otherwise the compile test will
|
# Unset the CMake cache variable compiles. Otherwise the compile test will
|
||||||
# just use cached information next time it runs.
|
# just use cached information next time it runs.
|
||||||
unset(compiles CACHE)
|
unset(compiles CACHE)
|
||||||
if (does_compile)
|
endfunction ()
|
||||||
|
|
||||||
|
function (expect_compile_error code)
|
||||||
|
generate_source(source "${code}")
|
||||||
|
check_cxx_source_compiles("${source}" compiles)
|
||||||
|
if (compiles)
|
||||||
message(FATAL_ERROR "No compile error for: ${code}")
|
message(FATAL_ERROR "No compile error for: ${code}")
|
||||||
endif ()
|
endif ()
|
||||||
|
# Unset the CMake cache variable compiles. Otherwise the compile test will
|
||||||
|
# just use cached information next time it runs.
|
||||||
|
unset(compiles CACHE)
|
||||||
endfunction ()
|
endfunction ()
|
||||||
|
|
||||||
|
# check if the source file skeleton compiles
|
||||||
|
expect_compile("")
|
||||||
|
|
||||||
# MakeArg doesn't accept [const] volatile char *.
|
# MakeArg doesn't accept [const] volatile char *.
|
||||||
expect_compile_error("volatile char s[] = \"test\"; (fmt::internal::MakeArg<char>)(s);")
|
expect_compile_error("volatile char s[] = \"test\"; (fmt::internal::MakeArg<char>)(s);")
|
||||||
expect_compile_error("const volatile char s[] = \"test\"; (fmt::internal::MakeArg<char>)(s);")
|
expect_compile_error("const volatile char s[] = \"test\"; (fmt::internal::MakeArg<char>)(s);")
|
||||||
|
13
test/find-package-test/CMakeLists.txt
Normal file
13
test/find-package-test/CMakeLists.txt
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
cmake_minimum_required(VERSION 2.8.12)
|
||||||
|
|
||||||
|
project(cppformat-test)
|
||||||
|
|
||||||
|
find_package(cppformat REQUIRED)
|
||||||
|
|
||||||
|
add_executable(library-test "main.cpp")
|
||||||
|
target_link_libraries(library-test cppformat)
|
||||||
|
|
||||||
|
if (TARGET cppformat-header-only)
|
||||||
|
add_executable(header-only-test "main.cpp")
|
||||||
|
target_link_libraries(header-only-test cppformat-header-only)
|
||||||
|
endif ()
|
8
test/find-package-test/main.cpp
Normal file
8
test/find-package-test/main.cpp
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#include "cppformat/format.h"
|
||||||
|
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
for(int i = 0; i < argc; ++i)
|
||||||
|
fmt::print("{}: {}\n", i, argv[i]);
|
||||||
|
return 0;
|
||||||
|
}
|
@ -29,7 +29,7 @@
|
|||||||
#include "test-assert.h"
|
#include "test-assert.h"
|
||||||
|
|
||||||
// Include format.cc instead of format.h to test implementation-specific stuff.
|
// Include format.cc instead of format.h to test implementation-specific stuff.
|
||||||
#include "format.cc"
|
#include "cppformat/format.cc"
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@
|
|||||||
// Test that the library compiles if None is defined to 0 as done by xlib.h.
|
// Test that the library compiles if None is defined to 0 as done by xlib.h.
|
||||||
#define None 0
|
#define None 0
|
||||||
|
|
||||||
#include "format.h"
|
#include "cppformat/format.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "mock-allocator.h"
|
#include "mock-allocator.h"
|
||||||
#include "gtest-extra.h"
|
#include "gtest-extra.h"
|
||||||
|
@ -31,14 +31,14 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
#include "format.h"
|
#include "cppformat/format.h"
|
||||||
|
|
||||||
#ifndef FMT_USE_FILE_DESCRIPTORS
|
#ifndef FMT_USE_FILE_DESCRIPTORS
|
||||||
# define FMT_USE_FILE_DESCRIPTORS 0
|
# define FMT_USE_FILE_DESCRIPTORS 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if FMT_USE_FILE_DESCRIPTORS
|
#if FMT_USE_FILE_DESCRIPTORS
|
||||||
# include "posix.h"
|
# include "cppformat/posix.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define FMT_TEST_THROW_(statement, expected_exception, expected_message, fail) \
|
#define FMT_TEST_THROW_(statement, expected_exception, expected_message, fail) \
|
||||||
|
@ -25,4 +25,4 @@
|
|||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "format.h"
|
#include "cppformat/format.h"
|
||||||
|
@ -25,4 +25,4 @@
|
|||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "format.h"
|
#include "cppformat/format.h"
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
#define FMT_USE_VARIADIC_TEMPLATES 0
|
#define FMT_USE_VARIADIC_TEMPLATES 0
|
||||||
#include "format.h"
|
#include "cppformat/format.h"
|
||||||
|
|
||||||
#define IDENTITY(x) x
|
#define IDENTITY(x) x
|
||||||
|
|
||||||
@ -67,7 +67,7 @@ TEST(UtilTest, NArg) {
|
|||||||
int result;
|
int result;
|
||||||
|
|
||||||
#define MAKE_TEST(func) \
|
#define MAKE_TEST(func) \
|
||||||
void func(const char *format, const fmt::ArgList &args) { \
|
void func(const char *, const fmt::ArgList &args) { \
|
||||||
result = 0; \
|
result = 0; \
|
||||||
for (unsigned i = 0; args[i].type; ++i) \
|
for (unsigned i = 0; args[i].type; ++i) \
|
||||||
result += args[i].int_value; \
|
result += args[i].int_value; \
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
#define _CRT_SECURE_NO_WARNINGS
|
#define _CRT_SECURE_NO_WARNINGS
|
||||||
|
|
||||||
#include "posix-mock.h"
|
#include "posix-mock.h"
|
||||||
#include "posix.cc"
|
#include <cppformat/posix.cc>
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
#include "gtest-extra.h"
|
#include "gtest-extra.h"
|
||||||
#include "posix.h"
|
#include "cppformat/posix.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
#ifdef fileno
|
#ifdef fileno
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
#include <climits>
|
#include <climits>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
#include "format.h"
|
#include "cppformat/format.h"
|
||||||
#include "gtest-extra.h"
|
#include "gtest-extra.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@
|
|||||||
# include <windows.h>
|
# include <windows.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "format.h"
|
#include "cppformat/format.h"
|
||||||
|
|
||||||
#undef max
|
#undef max
|
||||||
|
|
||||||
@ -410,7 +410,7 @@ struct ArgInfo;
|
|||||||
template <> \
|
template <> \
|
||||||
struct ArgInfo<Arg::type_code> { \
|
struct ArgInfo<Arg::type_code> { \
|
||||||
static Type get(const Arg &arg) { return arg.field; } \
|
static Type get(const Arg &arg) { return arg.field; } \
|
||||||
};
|
}
|
||||||
|
|
||||||
ARG_INFO(INT, int, int_value);
|
ARG_INFO(INT, int, int_value);
|
||||||
ARG_INFO(UINT, unsigned, uint_value);
|
ARG_INFO(UINT, unsigned, uint_value);
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "posix.h"
|
#include "cppformat/posix.h"
|
||||||
|
|
||||||
enum {BUFFER_SIZE = 256};
|
enum {BUFFER_SIZE = 256};
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user