From 611eb774ca64286b57a685d3ffd9f0a5f2f6c3ad Mon Sep 17 00:00:00 2001 From: vitaut Date: Wed, 29 Jul 2015 07:40:20 -0700 Subject: [PATCH 01/84] Remove Coverity config from Travis The config is now in the coverity_scan branch --- .travis.yml | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/.travis.yml b/.travis.yml index 7ce7536a..f0fbd22d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,12 +10,6 @@ env: Gsnp9ERFnXt+diCfc7Vb72g+7HDn1MCHvw4zfUDdoBh9bxxFlLQRlzZZfwWhzni57lflrt 0QHXafu+oBVOJuNv6WauV3+ZyuWIQRmNGjZFNLvZsXHK/dyad2vGQBPvEkb+8l/aCyTpbr 6pxmyzLHSn1ZR7OX5rfPvwM3tOyZ3H0= - # The next declaration is the encrypted COVERITY_SCAN_TOKEN, created - # via the "travis encrypt" command using the project repo's public key. - - secure: |- - Edkq75sWlKsPhiffnpAYxDm9E9zGg1Hf3rOwSlMZjwS5BmcjU3iteTXfS+cSUbh4YAbgc+ - 3OK+oKtCg7YV0X7AFmz/YOy0Ch8RXM4p0NxV/+OONjno77MsgFVkV41L2wilp5IXbz8nWl - j/HBbZMLPRqtHqEBHMUKGy4VEKq9sBg= matrix: - BUILD=Doc - BUILD=Debug @@ -28,13 +22,3 @@ matrix: script: - support/travis-build.py - -addons: - coverity_scan: - project: - name: "cppformat/cppformat" - description: "Small, safe and fast formatting library for C++" - notification_email: victor.zverovich@gmail.com - build_command_prepend: cmake . - build_command: make -j4 - branch_pattern: coverity_scan From 922fe90ac30bee0f51b1b73c261fa815f70de545 Mon Sep 17 00:00:00 2001 From: vitaut Date: Fri, 31 Jul 2015 08:02:38 -0700 Subject: [PATCH 02/84] Improve integer formatting performance and fix bogus Coverity warning about uncaught exception in format_error_code (via write_int). --- format.h | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/format.h b/format.h index a7c2389b..2a985f16 100644 --- a/format.h +++ b/format.h @@ -1867,6 +1867,27 @@ class BasicWriter { return internal::make_ptr(&buffer_[size], n); } + // Writes an unsigned decimal integer. + template + Char *write_unsigned_decimal(UInt value, unsigned prefix_size = 0) { + unsigned num_digits = internal::count_digits(value); + Char *ptr = get(grow_buffer(prefix_size + num_digits)); + internal::format_decimal(ptr + prefix_size, value, num_digits); + return ptr; + } + + // Writes a decimal integer. + template + void write_decimal(Int value) { + typename internal::IntTraits::MainType abs_value = value; + if (internal::is_negative(value)) { + abs_value = 0 - abs_value; + *write_unsigned_decimal(abs_value, 1) = '-'; + } else { + write_unsigned_decimal(abs_value, 0); + } + } + // Prepare a buffer for integer formatting. CharPtr prepare_int_buffer(unsigned num_digits, const EmptySpec &, const char *prefix, unsigned prefix_size) { @@ -1995,19 +2016,22 @@ class BasicWriter { FMT_VARIADIC_VOID(write, BasicCStringRef) BasicWriter &operator<<(int value) { - return *this << IntFormatSpec(value); + write_decimal(value); + return *this; } BasicWriter &operator<<(unsigned value) { return *this << IntFormatSpec(value); } BasicWriter &operator<<(long value) { - return *this << IntFormatSpec(value); + write_decimal(value); + return *this; } BasicWriter &operator<<(unsigned long value) { return *this << IntFormatSpec(value); } BasicWriter &operator<<(LongLong value) { - return *this << IntFormatSpec(value); + write_decimal(value); + return *this; } /** From d15e0d3e06f2b62ca5a6c56278401d5398e5abed Mon Sep 17 00:00:00 2001 From: vitaut Date: Fri, 31 Jul 2015 08:23:39 -0700 Subject: [PATCH 03/84] Use scoped_ptr instead of raw pointers in tests --- test/posix-mock-test.cc | 18 +++++++++--------- test/posix-test.cc | 9 +++++---- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/test/posix-mock-test.cc b/test/posix-mock-test.cc index c41f5956..a6080fdb 100644 --- a/test/posix-mock-test.cc +++ b/test/posix-mock-test.cc @@ -48,6 +48,8 @@ using fmt::BufferedFile; using fmt::ErrorCode; using fmt::File; +using testing::internal::scoped_ptr; + namespace { int open_count; int close_count; @@ -234,20 +236,19 @@ TEST(UtilTest, GetPageSize) { TEST(FileTest, OpenRetry) { write_file("test", "there must be something here"); - File *f = 0; - EXPECT_RETRY(f = new File("test", File::RDONLY), + scoped_ptr f; + EXPECT_RETRY(f.reset(new File("test", File::RDONLY)), open, "cannot open file test"); #ifndef _WIN32 char c = 0; f->read(&c, 1); #endif - delete f; } TEST(FileTest, CloseNoRetryInDtor) { File read_end, write_end; File::pipe(read_end, write_end); - testing::internal::scoped_ptr f(new File(std::move(read_end))); + scoped_ptr f(new File(std::move(read_end))); int saved_close_count = 0; EXPECT_WRITE(stderr, { close_count = 1; @@ -405,25 +406,24 @@ TEST(FileTest, FdopenNoRetry) { TEST(BufferedFileTest, OpenRetry) { write_file("test", "there must be something here"); - BufferedFile *f = 0; - EXPECT_RETRY(f = new BufferedFile("test", "r"), + scoped_ptr f; + EXPECT_RETRY(f.reset(new BufferedFile("test", "r")), fopen, "cannot open file test"); #ifndef _WIN32 char c = 0; if (fread(&c, 1, 1, f->get()) < 1) throw fmt::SystemError(errno, "fread failed"); #endif - delete f; } TEST(BufferedFileTest, CloseNoRetryInDtor) { File read_end, write_end; File::pipe(read_end, write_end); - BufferedFile *f = new BufferedFile(read_end.fdopen("r")); + scoped_ptr f(new BufferedFile(read_end.fdopen("r"))); int saved_fclose_count = 0; EXPECT_WRITE(stderr, { fclose_count = 1; - delete f; + f.reset(); saved_fclose_count = fclose_count; fclose_count = 0; }, format_system_error(EINTR, "cannot close file") + "\n"); diff --git a/test/posix-test.cc b/test/posix-test.cc index 4a2e678c..e4f75257 100644 --- a/test/posix-test.cc +++ b/test/posix-test.cc @@ -39,6 +39,8 @@ using fmt::BufferedFile; using fmt::ErrorCode; using fmt::File; +using testing::internal::scoped_ptr; + // Checks if the file is open by reading one character from it. bool isopen(int fd) { char buffer; @@ -136,8 +138,7 @@ TEST(BufferedFileTest, CloseFileInDtor) { } TEST(BufferedFileTest, CloseErrorInDtor) { - testing::internal::scoped_ptr f( - new BufferedFile(open_buffered_file())); + scoped_ptr f(new BufferedFile(open_buffered_file())); EXPECT_WRITE(stderr, { // The close function must be called inside EXPECT_WRITE, otherwise // the system may recycle closed file descriptor when redirecting the @@ -261,14 +262,14 @@ TEST(FileTest, CloseFileInDtor) { } TEST(FileTest, CloseErrorInDtor) { - File *f = new File(open_file()); + scoped_ptr f(new File(open_file())); EXPECT_WRITE(stderr, { // The close function must be called inside EXPECT_WRITE, otherwise // the system may recycle closed file descriptor when redirecting the // output in EXPECT_STDERR and the second close will break output // redirection. FMT_POSIX(close(f->descriptor())); - SUPPRESS_ASSERT(delete f); + SUPPRESS_ASSERT(f.reset()); }, format_system_error(EBADF, "cannot close file") + "\n"); } From 7e12c5c9dff76d4bcb6732001b5eea6581305be9 Mon Sep 17 00:00:00 2001 From: vitaut Date: Fri, 31 Jul 2015 08:54:54 -0700 Subject: [PATCH 04/84] Use scoped_ptr instead of raw pointers in tests --- test/gtest-extra-test.cc | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/test/gtest-extra-test.cc b/test/gtest-extra-test.cc index 1d383cbc..4e5db1d5 100644 --- a/test/gtest-extra-test.cc +++ b/test/gtest-extra-test.cc @@ -38,6 +38,8 @@ #include "util.h" +using testing::internal::scoped_ptr; + namespace { // Tests that assertion macros evaluate their arguments exactly once. @@ -350,10 +352,10 @@ TEST(OutputRedirectTest, FlushErrorInCtor) { // Put a character in a file buffer. EXPECT_EQ('x', fputc('x', f.get())); FMT_POSIX(close(write_fd)); - OutputRedirect *redir = 0; - EXPECT_SYSTEM_ERROR_NOASSERT(redir = new OutputRedirect(f.get()), + scoped_ptr redir; + EXPECT_SYSTEM_ERROR_NOASSERT(redir.reset(new OutputRedirect(f.get())), EBADF, "cannot flush stream"); - delete redir; + redir.reset(); write_copy.dup2(write_fd); // "undo" close or dtor will fail } @@ -362,11 +364,10 @@ TEST(OutputRedirectTest, DupErrorInCtor) { int fd = (f.fileno)(); File copy = File::dup(fd); FMT_POSIX(close(fd)); - OutputRedirect *redir = 0; - EXPECT_SYSTEM_ERROR_NOASSERT(redir = new OutputRedirect(f.get()), + scoped_ptr redir; + EXPECT_SYSTEM_ERROR_NOASSERT(redir.reset(new OutputRedirect(f.get())), EBADF, fmt::format("cannot duplicate file descriptor {}", fd)); copy.dup2(fd); // "undo" close or dtor will fail - delete redir; } TEST(OutputRedirectTest, RestoreAndRead) { @@ -405,7 +406,7 @@ TEST(OutputRedirectTest, ErrorInDtor) { int write_fd = write_end.descriptor(); File write_copy = write_end.dup(write_fd); BufferedFile f = write_end.fdopen("w"); - OutputRedirect *redir = new OutputRedirect(f.get()); + scoped_ptr redir(new OutputRedirect(f.get())); // Put a character in a file buffer. EXPECT_EQ('x', fputc('x', f.get())); EXPECT_WRITE(stderr, { @@ -414,7 +415,7 @@ TEST(OutputRedirectTest, ErrorInDtor) { // output in EXPECT_STDERR and the second close will break output // redirection. FMT_POSIX(close(write_fd)); - SUPPRESS_ASSERT(delete redir); + SUPPRESS_ASSERT(redir.reset()); }, format_system_error(EBADF, "cannot flush stream")); write_copy.dup2(write_fd); // "undo" close or dtor of BufferedFile will fail } From 0affb235606e9fc6cb1238b0143fed32463289ef Mon Sep 17 00:00:00 2001 From: Radu Popescu Date: Tue, 4 Aug 2015 12:52:44 +0200 Subject: [PATCH 05/84] fixed #190 Argument shadowing and Clang pedantic support --- CMakeLists.txt | 3 +++ format.cc | 4 ++-- format.h | 4 ++-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b48b183a..8c95fd70 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -99,6 +99,9 @@ if (FMT_PEDANTIC AND CMAKE_COMPILER_IS_GNUCXX) set_target_properties(cppformat PROPERTIES COMPILE_FLAGS "-Wall -Wextra -Wshadow -pedantic") endif () +if (FMT_PEDANTIC AND (CMAKE_CXX_COMPILER_ID MATCHES "Clang")) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_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. diff --git a/format.cc b/format.cc index 6dd52b87..8b0e763c 100644 --- a/format.cc +++ b/format.cc @@ -205,8 +205,8 @@ int safe_strerror( } public: - StrError(int error_code, char *&buffer, std::size_t buffer_size) - : error_code_(error_code), buffer_(buffer), buffer_size_(buffer_size) {} + StrError(int err_code, char *&buf, std::size_t buf_size) + : error_code_(err_code), buffer_(buf), buffer_size_(buf_size) {} int run() { strerror_r(0, 0, ""); // Suppress a warning about unused strerror_r. diff --git a/format.h b/format.h index 2a985f16..d384cfef 100644 --- a/format.h +++ b/format.h @@ -1046,8 +1046,8 @@ struct NamedArg : Arg { BasicStringRef name; template - NamedArg(BasicStringRef name, const T &value) - : name(name), Arg(MakeValue(value)) { + NamedArg(BasicStringRef argname, const T &value) + : name(argname), Arg(MakeValue(value)) { type = static_cast(MakeValue::type(value)); } }; From 5b8d0a7aa9eebcfc33c064aa91e1ea7c59ff61a5 Mon Sep 17 00:00:00 2001 From: vitaut Date: Tue, 4 Aug 2015 07:22:03 -0700 Subject: [PATCH 06/84] Make Coverity happy --- test/format-test.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/format-test.cc b/test/format-test.cc index 4f6597a4..35d96b45 100644 --- a/test/format-test.cc +++ b/test/format-test.cc @@ -1447,12 +1447,14 @@ TEST(FormatterTest, FormatExamples) { const char *filename = "nonexistent"; FILE *ftest = safe_fopen(filename, "r"); + if (ftest) fclose(ftest); int error_code = errno; EXPECT_TRUE(ftest == 0); EXPECT_SYSTEM_ERROR({ FILE *f = safe_fopen(filename, "r"); if (!f) throw fmt::SystemError(errno, "Cannot open file '{}'", filename); + fclose(f); }, error_code, "Cannot open file 'nonexistent'"); } From a8d12ade1c98f0d64d38cb1d4b55026f3f9fe274 Mon Sep 17 00:00:00 2001 From: vitaut Date: Tue, 4 Aug 2015 07:46:15 -0700 Subject: [PATCH 07/84] Append compile flags instead of overwriting --- CMakeLists.txt | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8c95fd70..96dd8416 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -95,12 +95,9 @@ if (BUILD_SHARED_LIBS) # unused-direct-shlib-dependency /usr/lib/libformat.so.1.1.0 /lib/libm.so.6. target_link_libraries(cppformat -Wl,--as-needed) endif () -if (FMT_PEDANTIC AND CMAKE_COMPILER_IS_GNUCXX) - set_target_properties(cppformat PROPERTIES COMPILE_FLAGS - "-Wall -Wextra -Wshadow -pedantic") -endif () -if (FMT_PEDANTIC AND (CMAKE_CXX_COMPILER_ID MATCHES "Clang")) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wshadow -pedantic") +if (FMT_PEDANTIC AND + (CMAKE_COMPILER_IS_GNUCXX OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang"))) + set(FMT_EXTRA_COMPILE_FLAGS "-Wall -Wextra -Wshadow -pedantic") endif () # If FMT_PEDANTIC is TRUE, then test compilation with both -std=c++11 @@ -108,12 +105,15 @@ endif () # 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_target_properties(cppformat PROPERTIES COMPILE_FLAGS ${CPP11_FLAG}) + set(FMT_EXTRA_COMPILE_FLAGS "${FMT_EXTRA_COMPILE_FLAGS} ${CPP11_FLAG}") # Test compilation with default flags. file(GLOB src RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} test/*.cc test/*.h) add_library(testformat STATIC ${FMT_SOURCE_FILES} ${src}) endif () +set_target_properties(cppformat + PROPERTIES COMPILE_FLAGS "${FMT_EXTRA_COMPILE_FLAGS}") + add_subdirectory(doc) include_directories(. gmock) From 7fa17fe77212373353211a238d9f7061f5aef765 Mon Sep 17 00:00:00 2001 From: vitaut Date: Tue, 4 Aug 2015 07:55:33 -0700 Subject: [PATCH 08/84] Fix warnings --- format.cc | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/format.cc b/format.cc index 8b0e763c..3db949db 100644 --- a/format.cc +++ b/format.cc @@ -503,20 +503,20 @@ class PrintfArgFormatter : : BasicArgFormatter, Char>(w, s) {} void visit_char(int value) { - const FormatSpec &spec = this->spec(); + const FormatSpec &fmt_spec = this->spec(); BasicWriter &writer = this->writer(); - if (spec.type_ && spec.type_ != 'c') - writer.write_int(value, spec); + if (fmt_spec.type_ && fmt_spec.type_ != 'c') + writer.write_int(value, fmt_spec); typedef typename BasicWriter::CharPtr CharPtr; CharPtr out = CharPtr(); - if (spec.width_ > 1) { + if (fmt_spec.width_ > 1) { Char fill = ' '; - out = writer.grow_buffer(spec.width_); - if (spec.align_ != ALIGN_LEFT) { - std::fill_n(out, spec.width_ - 1, fill); - out += spec.width_ - 1; + out = writer.grow_buffer(fmt_spec.width_); + if (fmt_spec.align_ != ALIGN_LEFT) { + std::fill_n(out, fmt_spec.width_ - 1, fill); + out += fmt_spec.width_ - 1; } else { - std::fill_n(out + 1, spec.width_ - 1, fill); + std::fill_n(out + 1, fmt_spec.width_ - 1, fill); } } else { out = writer.grow_buffer(1); From ecdc7ec1f1871a47b0a038f1244ba1e621212c0d Mon Sep 17 00:00:00 2001 From: vitaut Date: Tue, 4 Aug 2015 08:01:28 -0700 Subject: [PATCH 09/84] Fix more warnings --- format.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/format.cc b/format.cc index 3db949db..666f69c2 100644 --- a/format.cc +++ b/format.cc @@ -504,14 +504,14 @@ class PrintfArgFormatter : void visit_char(int value) { const FormatSpec &fmt_spec = this->spec(); - BasicWriter &writer = this->writer(); + BasicWriter &w = this->writer(); if (fmt_spec.type_ && fmt_spec.type_ != 'c') - writer.write_int(value, fmt_spec); + w.write_int(value, fmt_spec); typedef typename BasicWriter::CharPtr CharPtr; CharPtr out = CharPtr(); if (fmt_spec.width_ > 1) { Char fill = ' '; - out = writer.grow_buffer(fmt_spec.width_); + out = w.grow_buffer(fmt_spec.width_); if (fmt_spec.align_ != ALIGN_LEFT) { std::fill_n(out, fmt_spec.width_ - 1, fill); out += fmt_spec.width_ - 1; @@ -519,7 +519,7 @@ class PrintfArgFormatter : std::fill_n(out + 1, fmt_spec.width_ - 1, fill); } } else { - out = writer.grow_buffer(1); + out = w.grow_buffer(1); } *out = static_cast(value); } From 58fcf0c0da80b7814da244859f7218a2035eda88 Mon Sep 17 00:00:00 2001 From: vitaut Date: Wed, 5 Aug 2015 07:50:29 -0700 Subject: [PATCH 10/84] Optimize format_decimal --- format.h | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/format.h b/format.h index d384cfef..6b6951ac 100644 --- a/format.h +++ b/format.h @@ -712,24 +712,23 @@ inline unsigned count_digits(uint32_t n) { // Formats a decimal unsigned integer value writing into buffer. template inline void format_decimal(Char *buffer, UInt value, unsigned num_digits) { - --num_digits; + buffer += num_digits; while (value >= 100) { // Integer division is slow so do it for a group of two digits instead // of for every digit. The idea comes from the talk by Alexandrescu // "Three Optimization Tips for C++". See speed-test for a comparison. unsigned index = (value % 100) * 2; value /= 100; - buffer[num_digits] = Data::DIGITS[index + 1]; - buffer[num_digits - 1] = Data::DIGITS[index]; - num_digits -= 2; + *--buffer = Data::DIGITS[index + 1]; + *--buffer = Data::DIGITS[index]; } if (value < 10) { - *buffer = static_cast('0' + value); + *--buffer = static_cast('0' + value); return; } unsigned index = static_cast(value * 2); - buffer[1] = Data::DIGITS[index + 1]; - buffer[0] = Data::DIGITS[index]; + *--buffer = Data::DIGITS[index + 1]; + *--buffer = Data::DIGITS[index]; } #ifndef _WIN32 From 2c6e32f6fffc9c11ba609f9f141e8db832a9ccda Mon Sep 17 00:00:00 2001 From: vitaut Date: Fri, 7 Aug 2015 06:41:07 -0700 Subject: [PATCH 11/84] Simplify appveyor config --- appveyor.yml | 8 ++++---- support/appveyor-build.py | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index dfebef22..2f357641 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,14 +1,14 @@ +configuration: + - Debug + - Release + environment: CTEST_OUTPUT_ON_FAILURE: 1 matrix: - BUILD: msvc - CONFIG: Debug - BUILD: msvc - CONFIG: Release - BUILD: mingw - CONFIG: Debug - BUILD: mingw - CONFIG: Release build_script: - python support/appveyor-build.py diff --git a/support/appveyor-build.py b/support/appveyor-build.py index 9f4e30ce..89821328 100755 --- a/support/appveyor-build.py +++ b/support/appveyor-build.py @@ -5,7 +5,7 @@ import os from subprocess import check_call build = os.environ['BUILD'] -config = os.environ['CONFIG'] +config = os.environ['CONFIGURATION'] path = os.environ['PATH'] cmake_command = ['cmake', '-DFMT_PEDANTIC=ON', '-DCMAKE_BUILD_TYPE=' + config] if build == 'mingw': From 43081b833affae846ad4316dc5e12b51f18f82ff Mon Sep 17 00:00:00 2001 From: vitaut Date: Fri, 7 Aug 2015 07:08:12 -0700 Subject: [PATCH 12/84] Build both on x86 and x64 --- appveyor.yml | 3 ++- support/appveyor-build.py | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 2f357641..ab5ba9f6 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -6,8 +6,9 @@ environment: CTEST_OUTPUT_ON_FAILURE: 1 matrix: - BUILD: msvc + PLATFORM: x86 - BUILD: msvc - - BUILD: mingw + PLATFORM: x64 - BUILD: mingw build_script: diff --git a/support/appveyor-build.py b/support/appveyor-build.py index 89821328..9a0abb18 100755 --- a/support/appveyor-build.py +++ b/support/appveyor-build.py @@ -6,6 +6,7 @@ from subprocess import check_call build = os.environ['BUILD'] config = os.environ['CONFIGURATION'] +platform = os.environ['PLATFORM'] path = os.environ['PATH'] cmake_command = ['cmake', '-DFMT_PEDANTIC=ON', '-DCMAKE_BUILD_TYPE=' + config] if build == 'mingw': @@ -19,6 +20,10 @@ else: # Add MSBuild 14.0 to PATH as described in # http://help.appveyor.com/discussions/problems/2229-v140-not-found-on-vs2105rc. os.environ['PATH'] = r'C:\Program Files (x86)\MSBuild\14.0\Bin;' + path + generator = 'Visual Studio 14 2015' + if platform == 'x64': + generator += ' Win64' + cmake_command.append('-G' + generator) build_command = ['msbuild', '/m:4', '/p:Config=' + config, 'FORMAT.sln'] test_command = ['msbuild', 'RUN_TESTS.vcxproj'] From ca7478144d1597a057c34be2e9957c596492c4ef Mon Sep 17 00:00:00 2001 From: vitaut Date: Fri, 7 Aug 2015 07:08:46 -0700 Subject: [PATCH 13/84] Fix warnings --- format.cc | 7 +++++-- test/util-test.cc | 1 + 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/format.cc b/format.cc index 666f69c2..b70095b7 100644 --- a/format.cc +++ b/format.cc @@ -633,12 +633,15 @@ FMT_FUNC fmt::internal::UTF16ToUTF8::UTF16ToUTF8(fmt::WStringRef s) { } FMT_FUNC int fmt::internal::UTF16ToUTF8::convert(fmt::WStringRef s) { - int length = WideCharToMultiByte(CP_UTF8, 0, s.data(), s.size(), 0, 0, 0, 0); + if (s.size() > INT_MAX) + return ERROR_INVALID_PARAMETER; + int s_size = static_cast(s.size()); + int length = WideCharToMultiByte(CP_UTF8, 0, s.data(), s_size, 0, 0, 0, 0); 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, 0, 0); if (length == 0) return GetLastError(); buffer_[length] = 0; diff --git a/test/util-test.cc b/test/util-test.cc index 2173b1bf..ea0e66f7 100644 --- a/test/util-test.cc +++ b/test/util-test.cc @@ -752,6 +752,7 @@ TEST(UtilTest, UTF8ToUTF16Error) { TEST(UtilTest, UTF16ToUTF8Convert) { fmt::internal::UTF16ToUTF8 u; EXPECT_EQ(ERROR_INVALID_PARAMETER, u.convert(fmt::WStringRef(0, 0))); + EXPECT_EQ(ERROR_INVALID_PARAMETER, u.convert(fmt::WStringRef("foo", INT_MAX + 1u))); } #endif // _WIN32 From 2202541364831babfddb30587b958fbdd43d6061 Mon Sep 17 00:00:00 2001 From: vitaut Date: Fri, 7 Aug 2015 07:12:22 -0700 Subject: [PATCH 14/84] Disable configuration that doesn't work on appveyor --- appveyor.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index ab5ba9f6..8aef24eb 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -5,8 +5,8 @@ configuration: environment: CTEST_OUTPUT_ON_FAILURE: 1 matrix: - - BUILD: msvc - PLATFORM: x86 + #- BUILD: msvc + # PLATFORM: x86 - BUILD: msvc PLATFORM: x64 - BUILD: mingw From a8a2982b9aa9a2629e7e57e7daa5d982cc4264b9 Mon Sep 17 00:00:00 2001 From: vitaut Date: Fri, 7 Aug 2015 07:13:43 -0700 Subject: [PATCH 15/84] Fix test --- test/util-test.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/util-test.cc b/test/util-test.cc index ea0e66f7..a3b17330 100644 --- a/test/util-test.cc +++ b/test/util-test.cc @@ -752,7 +752,7 @@ TEST(UtilTest, UTF8ToUTF16Error) { TEST(UtilTest, UTF16ToUTF8Convert) { fmt::internal::UTF16ToUTF8 u; EXPECT_EQ(ERROR_INVALID_PARAMETER, u.convert(fmt::WStringRef(0, 0))); - EXPECT_EQ(ERROR_INVALID_PARAMETER, u.convert(fmt::WStringRef("foo", INT_MAX + 1u))); + EXPECT_EQ(ERROR_INVALID_PARAMETER, u.convert(fmt::WStringRef(L"foo", INT_MAX + 1u))); } #endif // _WIN32 From cdcdacef9c5f68fadfd7c25231a0c1405f0f8d69 Mon Sep 17 00:00:00 2001 From: vitaut Date: Fri, 7 Aug 2015 07:21:43 -0700 Subject: [PATCH 16/84] Handle undefined $PLATFORM --- support/appveyor-build.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/support/appveyor-build.py b/support/appveyor-build.py index 9a0abb18..4967ae3b 100755 --- a/support/appveyor-build.py +++ b/support/appveyor-build.py @@ -6,7 +6,7 @@ from subprocess import check_call build = os.environ['BUILD'] config = os.environ['CONFIGURATION'] -platform = os.environ['PLATFORM'] +platform = os.environ.get('PLATFORM') path = os.environ['PATH'] cmake_command = ['cmake', '-DFMT_PEDANTIC=ON', '-DCMAKE_BUILD_TYPE=' + config] if build == 'mingw': From c3ba615c653ca61502ddfef6379482b17921f543 Mon Sep 17 00:00:00 2001 From: vitaut Date: Fri, 7 Aug 2015 07:34:58 -0700 Subject: [PATCH 17/84] Fix warnings --- format.cc | 9 ++++++--- test/util-test.cc | 13 +++++++++---- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/format.cc b/format.cc index b70095b7..6c0905b0 100644 --- a/format.cc +++ b/format.cc @@ -612,14 +612,17 @@ FMT_FUNC void fmt::internal::report_unknown_type(char code, const char *type) { #if FMT_USE_WINDOWS_H FMT_FUNC fmt::internal::UTF8ToUTF16::UTF8ToUTF16(fmt::StringRef s) { - int length = MultiByteToWideChar( - CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s.size(), 0, 0); static const char ERROR_MSG[] = "cannot convert string from UTF-8 to UTF-16"; + if (s.size() > INT_MAX) + FMT_THROW(WindowsError(ERROR_INVALID_PARAMETER, ERROR_MSG)); + int s_size = static_cast(s.size()); + int length = MultiByteToWideChar( + CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, 0, 0); if (length == 0) FMT_THROW(WindowsError(GetLastError(), ERROR_MSG)); buffer_.resize(length + 1); length = MultiByteToWideChar( - CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s.size(), &buffer_[0], length); + CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, &buffer_[0], length); if (length == 0) FMT_THROW(WindowsError(GetLastError(), ERROR_MSG)); buffer_[length] = 0; diff --git a/test/util-test.cc b/test/util-test.cc index a3b17330..b92171ab 100644 --- a/test/util-test.cc +++ b/test/util-test.cc @@ -726,12 +726,14 @@ TEST(UtilTest, UTF8ToUTF16) { } template -void check_utf_conversion_error(const char *message) { +void check_utf_conversion_error( + const char *message, + fmt::BasicStringRef str = fmt::BasicStringRef(0, 0)) { fmt::MemoryWriter out; fmt::internal::format_windows_error(out, ERROR_INVALID_PARAMETER, message); fmt::SystemError error(0, ""); try { - Converter(fmt::BasicStringRef(0, 0)); + (Converter)(str); } catch (const fmt::SystemError &e) { error = e; } @@ -745,14 +747,17 @@ TEST(UtilTest, UTF16ToUTF8Error) { } TEST(UtilTest, UTF8ToUTF16Error) { + const char *message = "cannot convert string from UTF-8 to UTF-16"; + check_utf_conversion_error(message); check_utf_conversion_error( - "cannot convert string from UTF-8 to UTF-16"); + message, fmt::StringRef("foo", INT_MAX + 1u)); } TEST(UtilTest, UTF16ToUTF8Convert) { fmt::internal::UTF16ToUTF8 u; EXPECT_EQ(ERROR_INVALID_PARAMETER, u.convert(fmt::WStringRef(0, 0))); - EXPECT_EQ(ERROR_INVALID_PARAMETER, u.convert(fmt::WStringRef(L"foo", INT_MAX + 1u))); + EXPECT_EQ(ERROR_INVALID_PARAMETER, + u.convert(fmt::WStringRef(L"foo", INT_MAX + 1u))); } #endif // _WIN32 From b247d810469e9954df5f75f7b4b2e860f106e27c Mon Sep 17 00:00:00 2001 From: vitaut Date: Fri, 7 Aug 2015 07:39:04 -0700 Subject: [PATCH 18/84] Fix warnings --- test/macro-test.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/macro-test.cc b/test/macro-test.cc index 8a537028..38e85858 100644 --- a/test/macro-test.cc +++ b/test/macro-test.cc @@ -100,7 +100,7 @@ struct S {}; int test_variadic(FMT_GEN(10, GET_TYPE), const fmt::ArgList &args) { \ int result = 0; \ - for (std::size_t i = 0; args[i].type; ++i) \ + for (unsigned i = 0; args[i].type; ++i) \ result += args[i].int_value; \ return result; } From 8c4483d3cb91b2fe884000ad34b7620b8bcb64fc Mon Sep 17 00:00:00 2001 From: vitaut Date: Fri, 7 Aug 2015 07:39:56 -0700 Subject: [PATCH 19/84] Try appveyor config without explicit platform --- appveyor.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 8aef24eb..9e7db412 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -5,8 +5,7 @@ configuration: environment: CTEST_OUTPUT_ON_FAILURE: 1 matrix: - #- BUILD: msvc - # PLATFORM: x86 + - BUILD: msvc - BUILD: msvc PLATFORM: x64 - BUILD: mingw From 32fbc083b79e3cb909416188549a7189936549ae Mon Sep 17 00:00:00 2001 From: vitaut Date: Sat, 8 Aug 2015 18:58:25 -0700 Subject: [PATCH 20/84] Add Touch Surgery to the list of projects using C++ Format --- README.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.rst b/README.rst index 29f43348..f4d23bd2 100644 --- a/README.rst +++ b/README.rst @@ -157,6 +157,8 @@ Projects using this library * `spdlog `_: Super fast C++ logging library +* `Touch Surgery `_: Surgery simulator + * `TrinityCore `_: Open-source MMORPG framework `More... `_ From 11395c4f099da3a9ebaa09eb0e36cce78fd9067f Mon Sep 17 00:00:00 2001 From: jkflying Date: Mon, 17 Aug 2015 13:59:45 +0200 Subject: [PATCH 21/84] Fix warnings Child attribute was being instantiated before parent attribute, gives warnings under GCC 4.9.1 --- format.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/format.h b/format.h index 6b6951ac..4967b81a 100644 --- a/format.h +++ b/format.h @@ -1046,7 +1046,7 @@ struct NamedArg : Arg { template NamedArg(BasicStringRef argname, const T &value) - : name(argname), Arg(MakeValue(value)) { + : Arg(MakeValue(value)), name(argname) { type = static_cast(MakeValue::type(value)); } }; From 2161823559d412f1fc23e9f69ff60b07e9e883fb Mon Sep 17 00:00:00 2001 From: Alex Martin Date: Mon, 17 Aug 2015 18:48:16 +0200 Subject: [PATCH 22/84] add option to disable install --- CMakeLists.txt | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 96dd8416..94f69fd9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,6 +11,7 @@ if (NOT CMAKE_BUILD_TYPE) endif () option(FMT_PEDANTIC "Enable extra warnings and expensive tests." OFF) +option(FMT_INSTALL "Generate install target." ON) project(FORMAT) @@ -216,7 +217,9 @@ if (EXISTS .gitignore) endif () # Install targets. -set(FMT_LIB_DIR lib CACHE STRING - "Installation directory for libraries, relative to ${CMAKE_INSTALL_PREFIX}.") -install(TARGETS cppformat DESTINATION ${FMT_LIB_DIR}) -install(FILES format.h DESTINATION include/cppformat) +if (FMT_INSTALL) + set(FMT_LIB_DIR lib CACHE STRING + "Installation directory for libraries, relative to ${CMAKE_INSTALL_PREFIX}.") + install(TARGETS cppformat DESTINATION ${FMT_LIB_DIR}) + install(FILES format.h DESTINATION include/cppformat) +endif () From 4150fa0f9565eba3ec0f44611355fe6ac41ecd23 Mon Sep 17 00:00:00 2001 From: vitaut Date: Tue, 18 Aug 2015 06:57:31 -0700 Subject: [PATCH 23/84] Fix formatting --- CMakeLists.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 94f69fd9..2507a048 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -218,8 +218,8 @@ endif () # Install targets. if (FMT_INSTALL) - set(FMT_LIB_DIR lib CACHE STRING - "Installation directory for libraries, relative to ${CMAKE_INSTALL_PREFIX}.") - install(TARGETS cppformat DESTINATION ${FMT_LIB_DIR}) - install(FILES format.h DESTINATION include/cppformat) + set(FMT_LIB_DIR lib CACHE STRING + "Installation directory for libraries, relative to ${CMAKE_INSTALL_PREFIX}.") + install(TARGETS cppformat DESTINATION ${FMT_LIB_DIR}) + install(FILES format.h DESTINATION include/cppformat) endif () From 914b97859c309116dac1c93953153e6c96903513 Mon Sep 17 00:00:00 2001 From: Alex Martin Date: Wed, 19 Aug 2015 10:41:37 +0200 Subject: [PATCH 24/84] add CMake option to toggle tests (on by default) --- CMakeLists.txt | 149 +++++++++++++++++++++++++------------------------ 1 file changed, 77 insertions(+), 72 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2507a048..3b5a3361 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,6 +12,7 @@ endif () option(FMT_PEDANTIC "Enable extra warnings and expensive tests." OFF) option(FMT_INSTALL "Generate install target." ON) +option(FMT_TESTS "Generate tests." ON) project(FORMAT) @@ -108,8 +109,10 @@ endif () if (CPP11_FLAG AND FMT_PEDANTIC) set(FMT_EXTRA_COMPILE_FLAGS "${FMT_EXTRA_COMPILE_FLAGS} ${CPP11_FLAG}") # Test compilation with default flags. - file(GLOB src RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} test/*.cc test/*.h) - add_library(testformat STATIC ${FMT_SOURCE_FILES} ${src}) + if (FMT_TESTS) + file(GLOB src RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} test/*.cc test/*.h) + add_library(testformat STATIC ${FMT_SOURCE_FILES} ${src}) + endif () endif () set_target_properties(cppformat @@ -117,79 +120,81 @@ set_target_properties(cppformat add_subdirectory(doc) -include_directories(. gmock) - -# We compile Google Test ourselves instead of using pre-compiled libraries. -# See the Google Test FAQ "Why is it not recommended to install a -# pre-compiled copy of Google Test (for example, into /usr/local)?" -# at http://code.google.com/p/googletest/wiki/FAQ for more details. - -add_library(gmock STATIC - gmock/gmock-gtest-all.cc gmock/gmock/gmock.h - gmock/gtest/gtest.h gmock/gtest/gtest-spi.h) -find_package(Threads) -if (Threads_FOUND) - target_link_libraries(gmock ${CMAKE_THREAD_LIBS_INIT}) -else () - target_compile_definitions(gmock PUBLIC GTEST_HAS_PTHREAD=0) -endif () - -# 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 - struct S { typedef typename S::type type; }; - int main() {}" FMT_VARIADIC_TEMPLATES) - -# Check if initializer lists are supported. -check_cxx_source_compiles(" - #include - int main() {}" FMT_INITIALIZER_LIST) +if (FMT_TESTS) + include_directories(. gmock) -if (NOT FMT_VARIADIC_TEMPLATES OR NOT FMT_INITIALIZER_LIST) - add_definitions(-DGTEST_LANG_CXX11=0) + # We compile Google Test ourselves instead of using pre-compiled libraries. + # See the Google Test FAQ "Why is it not recommended to install a + # pre-compiled copy of Google Test (for example, into /usr/local)?" + # at http://code.google.com/p/googletest/wiki/FAQ for more details. + + add_library(gmock STATIC + gmock/gmock-gtest-all.cc gmock/gmock/gmock.h + gmock/gtest/gtest.h gmock/gtest/gtest-spi.h) + find_package(Threads) + if (Threads_FOUND) + target_link_libraries(gmock ${CMAKE_THREAD_LIBS_INIT}) + else () + target_compile_definitions(gmock PUBLIC GTEST_HAS_PTHREAD=0) + endif () + + # 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 + struct S { typedef typename S::type type; }; + int main() {}" FMT_VARIADIC_TEMPLATES) + + # Check if initializer lists are supported. + check_cxx_source_compiles(" + #include + int main() {}" FMT_INITIALIZER_LIST) + + if (NOT FMT_VARIADIC_TEMPLATES OR NOT FMT_INITIALIZER_LIST) + add_definitions(-DGTEST_LANG_CXX11=0) + endif () + + # This is disabled at the moment because format is compiled without -std=c++11 + # by default. + #check_cxx_source_compiles(" + # void f() noexcept {} + # int main(){ f(); }" FMT_BASIC_NOEXCEPT_SUPPORT) + #if (FMT_BASIC_NOEXCEPT_SUPPORT) + # add_definitions(-DFMT_USE_NOEXCEPT=1) + #endif () + + #check_cxx_source_compiles(" + # struct C{ + # C()=delete; + # C(const C&)=delete; + # C& operator=(const C&)=delete; + # }; + # int main(){}" FMT_DELETED_FUNCTIONS) + #if (FMT_DELETED_FUNCTIONS) + # add_definitions(-DFMT_USE_DELETED_FUNCTIONS=1) + #endif () + + #check_cxx_source_compiles(" + # static_assert(true, \"\"); + # int main(){}" FMT_STATIC_ASSERT) + #if (FMT_STATIC_ASSERT) + # add_definitions(-DFMT_USE_STATIC_ASSERT=1) + #endif () + + # Workaround a bug in implementation of variadic templates in MSVC11. + if (MSVC) + target_compile_definitions(gmock PUBLIC _VARIADIC_MAX=10) + endif () + + # GTest doesn't detect with clang. + if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + target_compile_definitions(gmock PUBLIC GTEST_USE_OWN_TR1_TUPLE=1) + endif () + + enable_testing() + add_subdirectory(test) endif () -# This is disabled at the moment because format is compiled without -std=c++11 -# by default. -#check_cxx_source_compiles(" -# void f() noexcept {} -# int main(){ f(); }" FMT_BASIC_NOEXCEPT_SUPPORT) -#if (FMT_BASIC_NOEXCEPT_SUPPORT) -# add_definitions(-DFMT_USE_NOEXCEPT=1) -#endif () - -#check_cxx_source_compiles(" -# struct C{ -# C()=delete; -# C(const C&)=delete; -# C& operator=(const C&)=delete; -# }; -# int main(){}" FMT_DELETED_FUNCTIONS) -#if (FMT_DELETED_FUNCTIONS) -# add_definitions(-DFMT_USE_DELETED_FUNCTIONS=1) -#endif () - -#check_cxx_source_compiles(" -# static_assert(true, \"\"); -# int main(){}" FMT_STATIC_ASSERT) -#if (FMT_STATIC_ASSERT) -# add_definitions(-DFMT_USE_STATIC_ASSERT=1) -#endif () - -# Workaround a bug in implementation of variadic templates in MSVC11. -if (MSVC) - target_compile_definitions(gmock PUBLIC _VARIADIC_MAX=10) -endif () - -# GTest doesn't detect with clang. -if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") - target_compile_definitions(gmock PUBLIC GTEST_USE_OWN_TR1_TUPLE=1) -endif () - -enable_testing() -add_subdirectory(test) - set(CPACK_PACKAGE_VERSION_MAJOR 1) set(CPACK_PACKAGE_VERSION_MINOR 2) set(CPACK_PACKAGE_VERSION_PATCH 0) From 4274f15f0da920285e489b8954adbf544ea108ca Mon Sep 17 00:00:00 2001 From: vitaut Date: Wed, 19 Aug 2015 07:27:08 -0700 Subject: [PATCH 25/84] Move test-specific stuff to test/CMakeLists.txt --- CMakeLists.txt | 70 --------------------------------------------- test/CMakeLists.txt | 45 +++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 70 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3b5a3361..1aa4b2d6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -121,76 +121,6 @@ set_target_properties(cppformat add_subdirectory(doc) if (FMT_TESTS) - include_directories(. gmock) - - # We compile Google Test ourselves instead of using pre-compiled libraries. - # See the Google Test FAQ "Why is it not recommended to install a - # pre-compiled copy of Google Test (for example, into /usr/local)?" - # at http://code.google.com/p/googletest/wiki/FAQ for more details. - - add_library(gmock STATIC - gmock/gmock-gtest-all.cc gmock/gmock/gmock.h - gmock/gtest/gtest.h gmock/gtest/gtest-spi.h) - find_package(Threads) - if (Threads_FOUND) - target_link_libraries(gmock ${CMAKE_THREAD_LIBS_INIT}) - else () - target_compile_definitions(gmock PUBLIC GTEST_HAS_PTHREAD=0) - endif () - - # 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 - struct S { typedef typename S::type type; }; - int main() {}" FMT_VARIADIC_TEMPLATES) - - # Check if initializer lists are supported. - check_cxx_source_compiles(" - #include - int main() {}" FMT_INITIALIZER_LIST) - - if (NOT FMT_VARIADIC_TEMPLATES OR NOT FMT_INITIALIZER_LIST) - add_definitions(-DGTEST_LANG_CXX11=0) - endif () - - # This is disabled at the moment because format is compiled without -std=c++11 - # by default. - #check_cxx_source_compiles(" - # void f() noexcept {} - # int main(){ f(); }" FMT_BASIC_NOEXCEPT_SUPPORT) - #if (FMT_BASIC_NOEXCEPT_SUPPORT) - # add_definitions(-DFMT_USE_NOEXCEPT=1) - #endif () - - #check_cxx_source_compiles(" - # struct C{ - # C()=delete; - # C(const C&)=delete; - # C& operator=(const C&)=delete; - # }; - # int main(){}" FMT_DELETED_FUNCTIONS) - #if (FMT_DELETED_FUNCTIONS) - # add_definitions(-DFMT_USE_DELETED_FUNCTIONS=1) - #endif () - - #check_cxx_source_compiles(" - # static_assert(true, \"\"); - # int main(){}" FMT_STATIC_ASSERT) - #if (FMT_STATIC_ASSERT) - # add_definitions(-DFMT_USE_STATIC_ASSERT=1) - #endif () - - # Workaround a bug in implementation of variadic templates in MSVC11. - if (MSVC) - target_compile_definitions(gmock PUBLIC _VARIADIC_MAX=10) - endif () - - # GTest doesn't detect with clang. - if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") - target_compile_definitions(gmock PUBLIC GTEST_USE_OWN_TR1_TUPLE=1) - endif () - enable_testing() add_subdirectory(test) endif () diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index b23d4cc4..e7348724 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,3 +1,48 @@ +set(FMT_GMOCK_DIR ../gmock) + +include_directories(.. ${FMT_GMOCK_DIR}) + +# We compile Google Test ourselves instead of using pre-compiled libraries. +# See the Google Test FAQ "Why is it not recommended to install a +# pre-compiled copy of Google Test (for example, into /usr/local)?" +# at http://code.google.com/p/googletest/wiki/FAQ for more details. + +add_library(gmock STATIC + ${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) +find_package(Threads) +if (Threads_FOUND) + target_link_libraries(gmock ${CMAKE_THREAD_LIBS_INIT}) +else () + target_compile_definitions(gmock PUBLIC GTEST_HAS_PTHREAD=0) +endif () + +# 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 + struct S { typedef typename S::type type; }; + int main() {}" FMT_VARIADIC_TEMPLATES) + +# Check if initializer lists are supported. +check_cxx_source_compiles(" + #include + int main() {}" FMT_INITIALIZER_LIST) + +if (NOT FMT_VARIADIC_TEMPLATES OR NOT FMT_INITIALIZER_LIST) + target_compile_definitions(gmock PUBLIC GTEST_LANG_CXX11=0) +endif () + +# Workaround a bug in implementation of variadic templates in MSVC11. +if (MSVC) + target_compile_definitions(gmock PUBLIC _VARIADIC_MAX=10) +endif () + +# GTest doesn't detect with clang. +if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + target_compile_definitions(gmock PUBLIC GTEST_USE_OWN_TR1_TUPLE=1) +endif () + set(TEST_MAIN_SRC test-main.cc gtest-extra.cc gtest-extra.h util.cc) add_library(test-main STATIC ${TEST_MAIN_SRC}) target_link_libraries(test-main cppformat gmock) From d07fd577c3ee44e6e5a1f328f9a24b00f752079e Mon Sep 17 00:00:00 2001 From: vitaut Date: Wed, 19 Aug 2015 07:27:34 -0700 Subject: [PATCH 26/84] FMT_SOURCE_FILES -> FMT_SOURCES --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1aa4b2d6..c866bc43 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -111,7 +111,7 @@ if (CPP11_FLAG AND FMT_PEDANTIC) # Test compilation with default flags. if (FMT_TESTS) file(GLOB src RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} test/*.cc test/*.h) - add_library(testformat STATIC ${FMT_SOURCE_FILES} ${src}) + add_library(testformat STATIC ${FMT_SOURCES} ${src}) endif () endif () From 1bba22667e52f00c0ec3c1c7d708d9abc1d9915b Mon Sep 17 00:00:00 2001 From: vitaut Date: Wed, 19 Aug 2015 07:32:48 -0700 Subject: [PATCH 27/84] Fix build on CMake 2.6 --- test/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index e7348724..843330c9 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -30,7 +30,7 @@ check_cxx_source_compiles(" int main() {}" FMT_INITIALIZER_LIST) if (NOT FMT_VARIADIC_TEMPLATES OR NOT FMT_INITIALIZER_LIST) - target_compile_definitions(gmock PUBLIC GTEST_LANG_CXX11=0) + add_definitions(-DGTEST_LANG_CXX11=0) endif () # Workaround a bug in implementation of variadic templates in MSVC11. From b3714625c08b05a4995eb156cb30f0184580194f Mon Sep 17 00:00:00 2001 From: vitaut Date: Wed, 19 Aug 2015 08:03:17 -0700 Subject: [PATCH 28/84] Fix compilation with FMT_PEDANTIC=ON --- CMakeLists.txt | 6 +----- test/CMakeLists.txt | 31 ++++++++++++++++++++++--------- 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c866bc43..c31d1b7f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -108,11 +108,7 @@ endif () # 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}") - # Test compilation with default flags. - if (FMT_TESTS) - file(GLOB src RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} test/*.cc test/*.h) - add_library(testformat STATIC ${FMT_SOURCES} ${src}) - endif () + set(FMT_TEST_DEFAULT_FLAGS TRUE) endif () set_target_properties(cppformat diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 843330c9..d30c222b 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -59,14 +59,6 @@ function(add_fmt_test name) add_test(NAME ${name} COMMAND ${name}) endfunction() -check_cxx_source_compiles(" - enum C : char {A}; - int main() {}" - HAVE_ENUM_BASE) -if (HAVE_ENUM_BASE) - add_definitions(-DFMT_USE_ENUM_BASE=1) -endif () - add_fmt_test(assert-test) add_fmt_test(gtest-extra-test) add_fmt_test(format-test) @@ -90,6 +82,15 @@ if (CPP11_FLAG) set_target_properties(util-test PROPERTIES COMPILE_FLAGS ${CPP11_FLAG}) 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 () @@ -100,7 +101,10 @@ check_cxx_source_compiles(" int main() { static_assert(!std::is_copy_assignable::value, \"\"); }" HAVE_TYPE_TRAITS) if (HAVE_TYPE_TRAITS) - add_definitions(-DFMT_USE_TYPE_TRAITS=1) + 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}) @@ -127,6 +131,15 @@ if (HAVE_FNO_EXCEPTIONS_FLAG) 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 () + if (FMT_PEDANTIC) add_test(compile-test ${CMAKE_CTEST_COMMAND} --build-and-test From edf5c2600112d392fd1a607b586d26bd11598b0f Mon Sep 17 00:00:00 2001 From: Alex Martin Date: Fri, 21 Aug 2015 19:09:18 +0200 Subject: [PATCH 29/84] add generated "run-msbuild.bat" file to gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 600a6424..faa768a5 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,4 @@ CTestTestfile.cmake CMakeCache.txt CMakeFiles Makefile +run-msbuild.bat From 4807f69ab4ff95e7a31f0907eed6f2a51c6979a0 Mon Sep 17 00:00:00 2001 From: vitaut Date: Wed, 26 Aug 2015 10:13:04 -0700 Subject: [PATCH 30/84] Remove duplicate EXLUDE_SYMBOLS --- doc/build.py | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/build.py b/doc/build.py index 340ce504..e2cea6a3 100755 --- a/doc/build.py +++ b/doc/build.py @@ -43,7 +43,6 @@ def build_docs(): GENERATE_RTF = NO CASE_SENSE_NAMES = NO INPUT = {0}/format.h - EXCLUDE_SYMBOLS = fmt::internal::* QUIET = YES JAVADOC_AUTOBRIEF = YES AUTOLINK_SUPPORT = NO From 06c1859420ed44bdfd602a1d3d0f756eedde0c0a Mon Sep 17 00:00:00 2001 From: Alex Martin Date: Sun, 30 Aug 2015 14:23:54 +0200 Subject: [PATCH 31/84] add CMake option to toggle doxygen documentation --- CMakeLists.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c31d1b7f..b8494b92 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,6 +13,7 @@ endif () option(FMT_PEDANTIC "Enable extra warnings and expensive tests." OFF) option(FMT_INSTALL "Generate install target." ON) option(FMT_TESTS "Generate tests." ON) +option(FMT_DOCS "Generate doxygen documentation." ON) project(FORMAT) @@ -114,7 +115,9 @@ endif () set_target_properties(cppformat PROPERTIES COMPILE_FLAGS "${FMT_EXTRA_COMPILE_FLAGS}") -add_subdirectory(doc) +if (FMT_DOCS) + add_subdirectory(doc) +endif () if (FMT_TESTS) enable_testing() From 75fdfe3e0eb874f9feb7820e602d1ea4bc45439f Mon Sep 17 00:00:00 2001 From: vitaut Date: Mon, 31 Aug 2015 06:49:06 -0700 Subject: [PATCH 32/84] Make options that control target generation more consistent --- CMakeLists.txt | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b8494b92..7957ed89 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,9 +11,11 @@ if (NOT CMAKE_BUILD_TYPE) endif () option(FMT_PEDANTIC "Enable extra warnings and expensive tests." OFF) -option(FMT_INSTALL "Generate install target." ON) -option(FMT_TESTS "Generate tests." ON) -option(FMT_DOCS "Generate doxygen documentation." ON) + +# Options that control generation of various targets. +option(FMT_DOC "Generate the doc target." ON) +option(FMT_INSTALL "Generate the install target." ON) +option(FMT_TEST "Generate the test target." ON) project(FORMAT) @@ -115,11 +117,11 @@ endif () set_target_properties(cppformat PROPERTIES COMPILE_FLAGS "${FMT_EXTRA_COMPILE_FLAGS}") -if (FMT_DOCS) +if (FMT_DOC) add_subdirectory(doc) endif () -if (FMT_TESTS) +if (FMT_TEST) enable_testing() add_subdirectory(test) endif () From 005379ac6f418eff75ecde24e76083dd3e9233fb Mon Sep 17 00:00:00 2001 From: vitaut Date: Mon, 31 Aug 2015 08:21:59 -0700 Subject: [PATCH 33/84] Don't include .buildinfo and .doctrees in the source package Thanks to Dave Johansen. --- CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7957ed89..6a4613e1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -143,7 +143,8 @@ if (EXISTS .gitignore) string(REPLACE "*" ".*" line "${line}") set(ignored_files ${ignored_files} "${line}$" "${line}/") endforeach () - set(ignored_files ${ignored_files} /.git /breathe /format-benchmark sphinx/) + set(ignored_files ${ignored_files} + /.git /breathe /format-benchmark sphinx/ .buildinfo .doctrees) set(CPACK_SOURCE_GENERATOR ZIP) set(CPACK_SOURCE_IGNORE_FILES ${ignored_files}) From d48047e4c01dba3f1c1b8dc87f4fac574855470c Mon Sep 17 00:00:00 2001 From: vitaut Date: Mon, 31 Aug 2015 08:22:25 -0700 Subject: [PATCH 34/84] Break long line --- doc/CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index 2990e8fc..e3cab6aa 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -6,4 +6,5 @@ endif () add_custom_target(doc COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/build.py) -install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html/ DESTINATION share/doc/cppformat) +install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html + DESTINATION share/doc/cppformat) From 59155abbf370e297c0082ff509bbbb6b46904e3e Mon Sep 17 00:00:00 2001 From: vitaut Date: Tue, 8 Sep 2015 08:16:12 -0700 Subject: [PATCH 35/84] Remove extra newline --- format.h | 1 - 1 file changed, 1 deletion(-) diff --git a/format.h b/format.h index 4967b81a..4bc47bfa 100644 --- a/format.h +++ b/format.h @@ -285,7 +285,6 @@ class BasicStringRef { typedef BasicStringRef StringRef; typedef BasicStringRef WStringRef; - /** \rst A reference to a null terminated string. It can be constructed from a C From 79d8f5990696d09180446f87d57190f6e04a3007 Mon Sep 17 00:00:00 2001 From: vitaut Date: Tue, 8 Sep 2015 08:36:20 -0700 Subject: [PATCH 36/84] Implement formatting of objects with (s)printf. --- format.cc | 6 ++++++ test/format-test.cc | 13 ------------- test/printf-test.cc | 4 ++++ test/util.h | 13 +++++++++++++ 4 files changed, 23 insertions(+), 13 deletions(-) diff --git a/format.cc b/format.cc index 6c0905b0..62b54d6d 100644 --- a/format.cc +++ b/format.cc @@ -523,6 +523,12 @@ class PrintfArgFormatter : } *out = static_cast(value); } + + void visit_custom(Arg::CustomValue c) { + BasicFormatter formatter(ArgList(), this->writer()); + const char *format = "}"; + c.format(&formatter, c.value, &format); + } }; } // namespace internal } // namespace fmt diff --git a/test/format-test.cc b/test/format-test.cc index 35d96b45..18498524 100644 --- a/test/format-test.cc +++ b/test/format-test.cc @@ -148,19 +148,6 @@ TEST(CStringRefTest, Ctor) { EXPECT_STREQ("defg", CStringRef(std::string("defg")).c_str()); } -class TestString { - private: - std::string value_; - - public: - explicit TestString(const char *value = "") : value_(value) {} - - friend std::ostream &operator<<(std::ostream &os, const TestString &s) { - os << s.value_; - return os; - } -}; - #if FMT_USE_TYPE_TRAITS TEST(WriterTest, NotCopyConstructible) { EXPECT_FALSE(std::is_copy_constructible >::value); diff --git a/test/printf-test.cc b/test/printf-test.cc index ec29bbe1..e942d6fe 100644 --- a/test/printf-test.cc +++ b/test/printf-test.cc @@ -426,6 +426,10 @@ TEST(PrintfTest, Pointer) { EXPECT_PRINTF(fmt::format("{}", p), "%p", p); } +TEST(PrintfTest, Custom) { + EXPECT_PRINTF("abc", "%s", TestString("abc")); +} + TEST(PrintfTest, Location) { // TODO: test %n } diff --git a/test/util.h b/test/util.h index a0d485eb..0b41fbbb 100644 --- a/test/util.h +++ b/test/util.h @@ -67,3 +67,16 @@ inline FILE *safe_fopen(const char *filename, const char *mode) { return std::fopen(filename, mode); #endif } + +class TestString { + private: + std::string value_; + + public: + explicit TestString(const char *value = "") : value_(value) {} + + friend std::ostream &operator<<(std::ostream &os, const TestString &s) { + os << s.value_; + return os; + } +}; From 42d8f5b9947389acfbab30c76581a7f8f218437c Mon Sep 17 00:00:00 2001 From: Victor Zverovich Date: Wed, 16 Sep 2015 21:33:51 -0700 Subject: [PATCH 37/84] Add redis-cerberus to the list of projects using cppformat --- README.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.rst b/README.rst index f4d23bd2..4b4b2d91 100644 --- a/README.rst +++ b/README.rst @@ -149,6 +149,8 @@ Projects using this library * `readpe `_: Read Portable Executable +* `redis-cerberus `_: A Redis cluster proxy + * `Saddy `_: Small crossplatform 2D graphic engine From a12f49669ce6abf2b6b36397b00c3adbe72e2d60 Mon Sep 17 00:00:00 2001 From: Victor Zverovich Date: Wed, 16 Sep 2015 21:45:27 -0700 Subject: [PATCH 38/84] Add Stellar to the list of projects using C++ Format --- README.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.rst b/README.rst index 4b4b2d91..fb4e38c7 100644 --- a/README.rst +++ b/README.rst @@ -159,6 +159,8 @@ Projects using this library * `spdlog `_: Super fast C++ logging library +* `Stellar `_: Financial platform + * `Touch Surgery `_: Surgery simulator * `TrinityCore `_: Open-source MMORPG framework From ef710dee6c8ae85f9fd6689d391a25aac159cc7c Mon Sep 17 00:00:00 2001 From: vitaut Date: Fri, 18 Sep 2015 16:26:41 -0700 Subject: [PATCH 39/84] Add sprintf overload for wide strings and fix an issue in formatting user-defined objects. Thanks to @ScottLangham --- format.cc | 3 ++- format.h | 7 +++++++ test/printf-test.cc | 4 ++++ test/util.h | 18 ++++++++++++++---- 4 files changed, 27 insertions(+), 5 deletions(-) diff --git a/format.cc b/format.cc index 62b54d6d..a9c978b9 100644 --- a/format.cc +++ b/format.cc @@ -526,7 +526,8 @@ class PrintfArgFormatter : void visit_custom(Arg::CustomValue c) { BasicFormatter formatter(ArgList(), this->writer()); - const char *format = "}"; + const Char format_str[] = {'}', 0}; + const Char *format = format_str; c.format(&formatter, c.value, &format); } }; diff --git a/format.h b/format.h index 4bc47bfa..8260024f 100644 --- a/format.h +++ b/format.h @@ -2706,6 +2706,12 @@ inline std::string sprintf(CStringRef format, ArgList args) { return w.str(); } +inline std::wstring sprintf(WCStringRef format, ArgList args) { + WMemoryWriter w; + printf(w, format, args); + return w.str(); +} + /** \rst Prints formatted data to the file *f*. @@ -2994,6 +3000,7 @@ FMT_VARIADIC(void, print, std::FILE *, CStringRef) FMT_VARIADIC(void, print, std::ostream &, CStringRef) FMT_VARIADIC(void, print_colored, Color, CStringRef) FMT_VARIADIC(std::string, sprintf, CStringRef) +FMT_VARIADIC_W(std::wstring, sprintf, WCStringRef) FMT_VARIADIC(int, printf, CStringRef) FMT_VARIADIC(int, fprintf, std::FILE *, CStringRef) } diff --git a/test/printf-test.cc b/test/printf-test.cc index e942d6fe..041fbad1 100644 --- a/test/printf-test.cc +++ b/test/printf-test.cc @@ -456,3 +456,7 @@ TEST(PrintfTest, PrintfError) { EXPECT_LT(result, 0); } #endif + +TEST(PrintfTest, WideString) { + EXPECT_EQ(L"abc", fmt::sprintf(L"%s", TestWString(L"abc"))); +} diff --git a/test/util.h b/test/util.h index 0b41fbbb..7f42cecd 100644 --- a/test/util.h +++ b/test/util.h @@ -68,15 +68,25 @@ inline FILE *safe_fopen(const char *filename, const char *mode) { #endif } -class TestString { +template +class BasicTestString { private: - std::string value_; + std::basic_string value_; + + static const Char EMPTY[]; public: - explicit TestString(const char *value = "") : value_(value) {} + explicit BasicTestString(const Char *value = EMPTY) : value_(value) {} - friend std::ostream &operator<<(std::ostream &os, const TestString &s) { + friend std::basic_ostream &operator<<( + std::basic_ostream &os, const BasicTestString &s) { os << s.value_; return os; } }; + +template +const Char BasicTestString::EMPTY[] = {0}; + +typedef BasicTestString TestString; +typedef BasicTestString TestWString; From a63a24f2d7d9a425c20857e7089d54a3cf8789d2 Mon Sep 17 00:00:00 2001 From: Dean Moldovan Date: Sun, 27 Sep 2015 02:26:26 +0200 Subject: [PATCH 40/84] Add _format literal --- format.h | 38 ++++++++++++++++++++++++++++++++++++++ test/format-test.cc | 9 +++++++++ 2 files changed, 47 insertions(+) diff --git a/format.h b/format.h index 8260024f..b85ddcb1 100644 --- a/format.h +++ b/format.h @@ -177,6 +177,16 @@ inline uint32_t clzll(uint64_t x) { TypeName& operator=(const TypeName&) #endif +#ifndef FMT_USE_USER_DEFINED_LITERALS +// All compilers which support UDLs also support variadic templates. This +// makes the fmt::literals implementation easier. However, an explicit check +// for variadic templates is added here just in case. +# define FMT_USE_USER_DEFINED_LITERALS \ + FMT_USE_VARIADIC_TEMPLATES && \ + (FMT_HAS_FEATURE(cxx_user_literals) || \ + (FMT_GCC_VERSION >= 407 && FMT_HAS_GXX_CXX11) || _MSC_VER >= 1900) +#endif + #ifndef FMT_ASSERT # define FMT_ASSERT(condition, message) assert((condition) && message) #endif @@ -3005,6 +3015,34 @@ FMT_VARIADIC(int, printf, CStringRef) FMT_VARIADIC(int, fprintf, std::FILE *, CStringRef) } +#if FMT_USE_USER_DEFINED_LITERALS +namespace fmt { +namespace internal { + +template +struct UdlFormat { + const Char *str; + + template + auto operator()(Args && ... args) const + -> decltype(format(str, std::forward(args)...)) { + return format(str, std::forward(args)...); + } +}; + +} // namespace internal + +inline namespace literals { + +inline internal::UdlFormat +operator"" _format(const char *s, std::size_t) { return {s}; } +inline internal::UdlFormat +operator"" _format(const wchar_t *s, std::size_t) { return {s}; } + +} // inline namespace literals +} // namespace fmt +#endif // FMT_USE_USER_DEFINED_LITERALS + // Restore warnings. #if FMT_GCC_VERSION >= 406 # pragma GCC diagnostic pop diff --git a/test/format-test.cc b/test/format-test.cc index 18498524..b95c499a 100644 --- a/test/format-test.cc +++ b/test/format-test.cc @@ -1602,3 +1602,12 @@ TEST(FormatTest, MaxArgs) { fmt::format("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 'a', 'b', 'c', 'd', 'e')); } + +#if FMT_USE_USER_DEFINED_LITERALS +using namespace fmt::literals; + +TEST(LiteralsTest, Format) { + EXPECT_EQ(format("{}c{}", "ab", 1), "{}c{}"_format("ab", 1)); + EXPECT_EQ(format(L"{}c{}", L"ab", 1), L"{}c{}"_format(L"ab", 1)); +} +#endif // FMT_USE_USER_DEFINED_LITERALS From bc6010cc211e20942948ae9bce4939dc1eea590f Mon Sep 17 00:00:00 2001 From: Dean Moldovan Date: Sun, 27 Sep 2015 04:09:37 +0200 Subject: [PATCH 41/84] Add _a literal for named arguments --- format.h | 15 +++++++++++++++ test/format-test.cc | 13 +++++++++++++ 2 files changed, 28 insertions(+) diff --git a/format.h b/format.h index b85ddcb1..e5e91537 100644 --- a/format.h +++ b/format.h @@ -3030,6 +3030,16 @@ struct UdlFormat { } }; +template +struct UdlArg { + const Char *str; + + template + NamedArg operator=(T &&value) const { + return {str, std::forward(value)}; + } +}; + } // namespace internal inline namespace literals { @@ -3039,6 +3049,11 @@ operator"" _format(const char *s, std::size_t) { return {s}; } inline internal::UdlFormat operator"" _format(const wchar_t *s, std::size_t) { return {s}; } +inline internal::UdlArg +operator"" _a(const char *s, std::size_t) { return {s}; } +inline internal::UdlArg +operator"" _a(const wchar_t *s, std::size_t) { return {s}; } + } // inline namespace literals } // namespace fmt #endif // FMT_USE_USER_DEFINED_LITERALS diff --git a/test/format-test.cc b/test/format-test.cc index b95c499a..c189f990 100644 --- a/test/format-test.cc +++ b/test/format-test.cc @@ -1610,4 +1610,17 @@ TEST(LiteralsTest, Format) { EXPECT_EQ(format("{}c{}", "ab", 1), "{}c{}"_format("ab", 1)); EXPECT_EQ(format(L"{}c{}", L"ab", 1), L"{}c{}"_format(L"ab", 1)); } + +TEST(LiteralsTest, NamedArg) { + EXPECT_EQ(format("{first}{second}{first}{third}", + fmt::arg("first", "abra"), fmt::arg("second", "cad"), + fmt::arg("third", 99)), + format("{first}{second}{first}{third}", + "first"_a="abra", "second"_a="cad", "third"_a=99)); + EXPECT_EQ(format(L"{first}{second}{first}{third}", + fmt::arg(L"first", L"abra"), fmt::arg(L"second", L"cad"), + fmt::arg(L"third", 99)), + format(L"{first}{second}{first}{third}", + L"first"_a=L"abra", L"second"_a=L"cad", L"third"_a=99)); +} #endif // FMT_USE_USER_DEFINED_LITERALS From c0813c59f303152dcec3af9a702bc92d551e5248 Mon Sep 17 00:00:00 2001 From: Dean Moldovan Date: Fri, 9 Oct 2015 11:55:36 +0200 Subject: [PATCH 42/84] Work around UDL macro stringification bug on some versions of GCC See bug report: https://gcc.gnu.org/ml/gcc-bugs/2015-04/msg02027.html --- test/format-test.cc | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/test/format-test.cc b/test/format-test.cc index c189f990..3fceab88 100644 --- a/test/format-test.cc +++ b/test/format-test.cc @@ -1604,23 +1604,31 @@ TEST(FormatTest, MaxArgs) { } #if FMT_USE_USER_DEFINED_LITERALS +// Passing user-defined literals directly to EXPECT_EQ causes problems +// with macro argument stringification (#) on some versions of GCC. +// Workaround: Assing the UDL result to a variable before the macro. + using namespace fmt::literals; TEST(LiteralsTest, Format) { - EXPECT_EQ(format("{}c{}", "ab", 1), "{}c{}"_format("ab", 1)); - EXPECT_EQ(format(L"{}c{}", L"ab", 1), L"{}c{}"_format(L"ab", 1)); + auto udl_format = "{}c{}"_format("ab", 1); + EXPECT_EQ(format("{}c{}", "ab", 1), udl_format); + auto udl_format_w = L"{}c{}"_format(L"ab", 1); + EXPECT_EQ(format(L"{}c{}", L"ab", 1), udl_format_w); } TEST(LiteralsTest, NamedArg) { + auto udl_a = format("{first}{second}{first}{third}", + "first"_a="abra", "second"_a="cad", "third"_a=99); EXPECT_EQ(format("{first}{second}{first}{third}", fmt::arg("first", "abra"), fmt::arg("second", "cad"), fmt::arg("third", 99)), - format("{first}{second}{first}{third}", - "first"_a="abra", "second"_a="cad", "third"_a=99)); + udl_a); + auto udl_a_w = format(L"{first}{second}{first}{third}", + L"first"_a=L"abra", L"second"_a=L"cad", L"third"_a=99); EXPECT_EQ(format(L"{first}{second}{first}{third}", fmt::arg(L"first", L"abra"), fmt::arg(L"second", L"cad"), fmt::arg(L"third", 99)), - format(L"{first}{second}{first}{third}", - L"first"_a=L"abra", L"second"_a=L"cad", L"third"_a=99)); + udl_a_w); } #endif // FMT_USE_USER_DEFINED_LITERALS From 47e26cdc3730348502562f55aa7d160c70df7304 Mon Sep 17 00:00:00 2001 From: Dean Moldovan Date: Sun, 11 Oct 2015 02:34:20 +0200 Subject: [PATCH 43/84] Document user-defined literals --- doc/index.rst | 43 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 40 insertions(+), 3 deletions(-) diff --git a/doc/index.rst b/doc/index.rst index 2166b253..a890776b 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -65,6 +65,34 @@ The Format API also supports positional arguments useful for localization: fmt::print("I'd rather be {1} than {0}.", "right", "happy"); +Named arguments can be created with ``fmt::arg``. This makes it easier to track +what goes where when multiple values are being inserted: + +.. code:: c++ + + fmt::print("Hello, {name}! The answer is {number}. Goodbye, {name}.", + fmt::arg("name", "World"), fmt::arg("number", 42)); + +If your compiler supports C++11 user-defined literals, the suffix ``_a`` offers +an alternative, slightly terser syntax for named arguments: + +.. code:: c++ + + fmt::print("Hello, {name}! The answer is {number}. Goodbye, {name}.", + "name"_a="World", "number"_a=42); + +The ``_format`` suffix may be used to format string literals similar to Python: + +.. code:: c++ + + std::string message = "{0}{1}{0}"_format("abra", "cad"); + +Other than the placement of the format string on the left of the operator, +``_format`` is functionally identical to ``fmt::format``. In order to use the +literal operators, they must be made visible with the directive +``using namespace fmt::literals;``. Note that this brings in only ``_a`` and +``_format`` but nothing else from the ``fmt`` namespace. + .. _write-api: Write API @@ -128,13 +156,22 @@ compilers where it has been tested and known to work: * Mac OS X with GCC 4.2.1 and Clang 4.2, 5.1.0 -* 64-bit Windows with Visual C++ 2010 and - `2013 `_ +* 64-bit Windows with Visual C++ 2010, 2013 and + `2015 `_ * 32-bit Windows with Visual C++ 2010 Although the library uses C++11 features when available, it also works with older -compilers and standard library implementations. +compilers and standard library implementations. The only thing to keep in mind +for C++98 portability: + +* Variadic templates: minimum GCC 4.4, Clang 2.9 or VS2013. This feature allow + the Format API to accept an unlimited number of arguments. With older compilers + the maximum is 15. + +* User-defined literals: minimum GCC 4.7, Clang 3.1 or VS2015. The suffixes + ``_format`` and ``_a`` are functionally equivalent to the functions + ``fmt::format`` and ``fmt::arg``. The output of all formatting functions is consistent across platforms. In particular, formatting a floating-point infinity always gives ``inf`` while the output From 358ae822bba1393df45a11a7a97d7a37a11246be Mon Sep 17 00:00:00 2001 From: Dean Moldovan Date: Tue, 13 Oct 2015 00:35:22 +0200 Subject: [PATCH 44/84] Update Sphinx with C++11 literals fix and add fmt::literals API docs --- doc/api.rst | 4 ++++ doc/build.py | 6 ++++-- doc/index.rst | 2 +- format.h | 20 ++++++++++++++++++++ 4 files changed, 29 insertions(+), 3 deletions(-) diff --git a/doc/api.rst b/doc/api.rst index 7e1855a7..ecd442a1 100644 --- a/doc/api.rst +++ b/doc/api.rst @@ -26,6 +26,8 @@ arguments in the resulting string. .. doxygenfunction:: format(CStringRef, ArgList) +.. doxygenfunction:: operator""_format(const char *, std::size_t) + .. _print: .. doxygenfunction:: print(CStringRef, ArgList) @@ -74,6 +76,8 @@ Utilities .. doxygenfunction:: fmt::arg(StringRef, const T&) +.. doxygenfunction:: operator""_a(const char *, std::size_t) + .. doxygendefine:: FMT_CAPTURE .. doxygendefine:: FMT_VARIADIC diff --git a/doc/build.py b/doc/build.py index e2cea6a3..e4c66533 100755 --- a/doc/build.py +++ b/doc/build.py @@ -30,7 +30,8 @@ def build_docs(): activate_this_file = os.path.join(virtualenv_dir, 'bin', 'activate_this.py') execfile(activate_this_file, dict(__file__=activate_this_file)) # Install Sphinx and Breathe. - pip_install('sphinx==1.3.1') + pip_install('sphinx-doc/sphinx', + '4d2c17e043d9e8197fa5cd0db34212af3bb17069') pip_install('michaeljones/breathe', '511b0887293e7c6b12310bb61b3659068f48f0f4') # Build docs. @@ -53,7 +54,8 @@ def build_docs(): ALIASES += "endrst=\endverbatim" PREDEFINED = _WIN32=1 \ FMT_USE_VARIADIC_TEMPLATES=1 \ - FMT_USE_RVALUE_REFERENCES=1 + FMT_USE_RVALUE_REFERENCES=1 \ + FMT_USE_USER_DEFINED_LITERALS=1 EXCLUDE_SYMBOLS = fmt::internal::* StringValue write_str '''.format(os.path.dirname(doc_dir))) if p.returncode != 0: diff --git a/doc/index.rst b/doc/index.rst index a890776b..35c56f04 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -165,7 +165,7 @@ Although the library uses C++11 features when available, it also works with olde compilers and standard library implementations. The only thing to keep in mind for C++98 portability: -* Variadic templates: minimum GCC 4.4, Clang 2.9 or VS2013. This feature allow +* Variadic templates: minimum GCC 4.4, Clang 2.9 or VS2013. This feature allows the Format API to accept an unlimited number of arguments. With older compilers the maximum is 15. diff --git a/format.h b/format.h index e5e91537..d25eab34 100644 --- a/format.h +++ b/format.h @@ -3044,11 +3044,31 @@ struct UdlArg { inline namespace literals { +/** + \rst + C++11 literal equivalent of :func:`fmt::format`. + + **Example**:: + + using namespace fmt::literals; + std::string message = "The answer is {}"_format(42); + \endrst + */ inline internal::UdlFormat operator"" _format(const char *s, std::size_t) { return {s}; } inline internal::UdlFormat operator"" _format(const wchar_t *s, std::size_t) { return {s}; } +/** + \rst + C++11 literal equivalent of :func:`fmt::arg`. + + **Example**:: + + using namespace fmt::literals; + print("Elapsed time: {s:.2f} seconds", "s"_a=1.23); + \endrst + */ inline internal::UdlArg operator"" _a(const char *s, std::size_t) { return {s}; } inline internal::UdlArg From 7732688b80259cac3e27be3cda5b5db5ef32012f Mon Sep 17 00:00:00 2001 From: vitaut Date: Tue, 13 Oct 2015 08:24:16 -0700 Subject: [PATCH 45/84] If Sphinx is already installed but version doesn't match, reinstall it --- doc/build.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/doc/build.py b/doc/build.py index e4c66533..a0f841c9 100755 --- a/doc/build.py +++ b/doc/build.py @@ -5,14 +5,16 @@ from __future__ import print_function import os, shutil, tempfile from subprocess import check_call, CalledProcessError, Popen, PIPE -def pip_install(package, commit=None): +def pip_install(package, commit=None, **kwargs): "Install package using pip." if commit: + check_version = kwargs.get('check_version', '') cmd = ['pip', 'show', package.split('/')[1]] p = Popen(cmd, stdout=PIPE, stderr=PIPE) stdout, stderr = p.communicate() - if stdout: - return # Already installed + if stdout and check_version in stdout: + print('{} already installed'.format(package)) + return elif p.returncode != 0: # Old versions of pip such as the one installed on Travis don't support # the show command - continue installation in this case. @@ -31,7 +33,8 @@ def build_docs(): execfile(activate_this_file, dict(__file__=activate_this_file)) # Install Sphinx and Breathe. pip_install('sphinx-doc/sphinx', - '4d2c17e043d9e8197fa5cd0db34212af3bb17069') + '4d2c17e043d9e8197fa5cd0db34212af3bb17069', + check_version='1.4a0.dev-20151013') pip_install('michaeljones/breathe', '511b0887293e7c6b12310bb61b3659068f48f0f4') # Build docs. From 5bc908623c0d06d496c568a33854b95135b42ab6 Mon Sep 17 00:00:00 2001 From: vitaut Date: Tue, 13 Oct 2015 08:45:49 -0700 Subject: [PATCH 46/84] Add diagnostics to the documentation build script --- doc/build.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/doc/build.py b/doc/build.py index a0f841c9..214f01ab 100755 --- a/doc/build.py +++ b/doc/build.py @@ -3,7 +3,7 @@ from __future__ import print_function import os, shutil, tempfile -from subprocess import check_call, CalledProcessError, Popen, PIPE +from subprocess import check_call, check_output, CalledProcessError, Popen, PIPE def pip_install(package, commit=None, **kwargs): "Install package using pip." @@ -15,13 +15,14 @@ def pip_install(package, commit=None, **kwargs): if stdout and check_version in stdout: print('{} already installed'.format(package)) return - elif p.returncode != 0: + if p.returncode != 0: # Old versions of pip such as the one installed on Travis don't support # the show command - continue installation in this case. # Otherwise throw CalledProcessError. if p.returncode > 1 and 'No command by the name pip show' not in stderr: raise CalledProcessError(p.returncode, cmd) package = 'git+git://github.com/{0}.git@{1}'.format(package, commit) + print('Installing {}'.format(package)) check_call(['pip', 'install', '-q', package]) def build_docs(): @@ -37,6 +38,7 @@ def build_docs(): check_version='1.4a0.dev-20151013') pip_install('michaeljones/breathe', '511b0887293e7c6b12310bb61b3659068f48f0f4') + print(check_output(['sphinx-build', '--version'])) # Build docs. cmd = ['doxygen', '-'] p = Popen(cmd, stdin=PIPE) From bdbac0b78f06ee06572e0336798df730158cd455 Mon Sep 17 00:00:00 2001 From: vitaut Date: Tue, 13 Oct 2015 08:55:05 -0700 Subject: [PATCH 47/84] More diagnostics --- doc/build.py | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/build.py b/doc/build.py index 214f01ab..c94344b9 100755 --- a/doc/build.py +++ b/doc/build.py @@ -39,6 +39,7 @@ def build_docs(): pip_install('michaeljones/breathe', '511b0887293e7c6b12310bb61b3659068f48f0f4') print(check_output(['sphinx-build', '--version'])) + print('PATH:', os.environ['PATH']) # Build docs. cmd = ['doxygen', '-'] p = Popen(cmd, stdin=PIPE) From 08bcf61fb210dc7023e1a4461b9150140b94fc1b Mon Sep 17 00:00:00 2001 From: vitaut Date: Wed, 14 Oct 2015 06:27:41 -0700 Subject: [PATCH 48/84] Add --upgrade option to pip --- doc/build.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/build.py b/doc/build.py index c94344b9..412d407b 100755 --- a/doc/build.py +++ b/doc/build.py @@ -23,7 +23,7 @@ def pip_install(package, commit=None, **kwargs): raise CalledProcessError(p.returncode, cmd) package = 'git+git://github.com/{0}.git@{1}'.format(package, commit) print('Installing {}'.format(package)) - check_call(['pip', 'install', '-q', package]) + check_call(['pip', 'install', '--upgrade', '--quiet', package]) def build_docs(): # Create virtualenv. From 6dae7f3ba6e3d0bb0ec55c629bbacddc2aa41188 Mon Sep 17 00:00:00 2001 From: vitaut Date: Wed, 14 Oct 2015 06:39:07 -0700 Subject: [PATCH 49/84] Add more diagnostics --- doc/build.py | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/build.py b/doc/build.py index 412d407b..33a79baa 100755 --- a/doc/build.py +++ b/doc/build.py @@ -40,6 +40,7 @@ def build_docs(): '511b0887293e7c6b12310bb61b3659068f48f0f4') print(check_output(['sphinx-build', '--version'])) print('PATH:', os.environ['PATH']) + print(check_output(['which', 'sphinx-build'])) # Build docs. cmd = ['doxygen', '-'] p = Popen(cmd, stdin=PIPE) From d6ecf3ae61afa54278afeabd45fb0e4c14790b04 Mon Sep 17 00:00:00 2001 From: vitaut Date: Wed, 14 Oct 2015 06:43:30 -0700 Subject: [PATCH 50/84] Add more diagnostics --- doc/build.py | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/build.py b/doc/build.py index 33a79baa..33538c62 100755 --- a/doc/build.py +++ b/doc/build.py @@ -41,6 +41,7 @@ def build_docs(): print(check_output(['sphinx-build', '--version'])) print('PATH:', os.environ['PATH']) print(check_output(['which', 'sphinx-build'])) + print(check_output(['cat', '/home/travis/build/cppformat/cppformat/virtualenv/bin/sphinx-build'])) # Build docs. cmd = ['doxygen', '-'] p = Popen(cmd, stdin=PIPE) From f4d38ce3ea837d745c765605f6e473c29365e3a5 Mon Sep 17 00:00:00 2001 From: vitaut Date: Wed, 14 Oct 2015 06:52:07 -0700 Subject: [PATCH 51/84] Add more diagnostics --- doc/build.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/build.py b/doc/build.py index 33538c62..fc446086 100755 --- a/doc/build.py +++ b/doc/build.py @@ -23,7 +23,7 @@ def pip_install(package, commit=None, **kwargs): raise CalledProcessError(p.returncode, cmd) package = 'git+git://github.com/{0}.git@{1}'.format(package, commit) print('Installing {}'.format(package)) - check_call(['pip', 'install', '--upgrade', '--quiet', package]) + check_call(['pip', 'install', '--upgrade', package]) def build_docs(): # Create virtualenv. @@ -42,6 +42,8 @@ def build_docs(): print('PATH:', os.environ['PATH']) print(check_output(['which', 'sphinx-build'])) print(check_output(['cat', '/home/travis/build/cppformat/cppformat/virtualenv/bin/sphinx-build'])) + import sphinx + print(sphinx.__version__) # Build docs. cmd = ['doxygen', '-'] p = Popen(cmd, stdin=PIPE) From 95fa85cf049098e1a6ee1241ad45268e195d0fe2 Mon Sep 17 00:00:00 2001 From: vitaut Date: Wed, 14 Oct 2015 07:06:13 -0700 Subject: [PATCH 52/84] Try uninstalling older version of sphinx --- doc/build.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/build.py b/doc/build.py index fc446086..68558e09 100755 --- a/doc/build.py +++ b/doc/build.py @@ -21,6 +21,8 @@ def pip_install(package, commit=None, **kwargs): # Otherwise throw CalledProcessError. if p.returncode > 1 and 'No command by the name pip show' not in stderr: raise CalledProcessError(p.returncode, cmd) + else: + check_call('pip', 'uninstall', '-y', 'sphinx') package = 'git+git://github.com/{0}.git@{1}'.format(package, commit) print('Installing {}'.format(package)) check_call(['pip', 'install', '--upgrade', package]) From a08bc864fbc2b095d444c5411a36097cced49a12 Mon Sep 17 00:00:00 2001 From: vitaut Date: Wed, 14 Oct 2015 07:13:23 -0700 Subject: [PATCH 53/84] Add more diagnostics --- doc/build.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/build.py b/doc/build.py index 68558e09..7c1e649c 100755 --- a/doc/build.py +++ b/doc/build.py @@ -22,7 +22,8 @@ def pip_install(package, commit=None, **kwargs): if p.returncode > 1 and 'No command by the name pip show' not in stderr: raise CalledProcessError(p.returncode, cmd) else: - check_call('pip', 'uninstall', '-y', 'sphinx') + print('Uninstalling {}'.format(package)) + check_call('pip', 'uninstall', '-y', package) package = 'git+git://github.com/{0}.git@{1}'.format(package, commit) print('Installing {}'.format(package)) check_call(['pip', 'install', '--upgrade', package]) @@ -40,6 +41,7 @@ def build_docs(): check_version='1.4a0.dev-20151013') pip_install('michaeljones/breathe', '511b0887293e7c6b12310bb61b3659068f48f0f4') + print(check_output(['pip', '--version'])) print(check_output(['sphinx-build', '--version'])) print('PATH:', os.environ['PATH']) print(check_output(['which', 'sphinx-build'])) From 13c633223ee8f4001049623de87c806ffc7f3b11 Mon Sep 17 00:00:00 2001 From: vitaut Date: Wed, 14 Oct 2015 08:17:39 -0700 Subject: [PATCH 54/84] Upgrade pip on Travis --- doc/build.py | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/doc/build.py b/doc/build.py index 7c1e649c..235e9afc 100755 --- a/doc/build.py +++ b/doc/build.py @@ -2,28 +2,22 @@ # Build the documentation. from __future__ import print_function -import os, shutil, tempfile +import os, pip, shutil, tempfile from subprocess import check_call, check_output, CalledProcessError, Popen, PIPE +from distutils.version import LooseVersion def pip_install(package, commit=None, **kwargs): "Install package using pip." + if LooseVersion(pip.__version__) < LooseVersion('1.5.4'): + # Upgrade pip because installation of sphinx with pip 1.1 available on Travis + # is broken (see #207) and it doesn't support the show command. + check_call(['pip', 'install', '--upgrade', 'pip']) if commit: check_version = kwargs.get('check_version', '') - cmd = ['pip', 'show', package.split('/')[1]] - p = Popen(cmd, stdout=PIPE, stderr=PIPE) - stdout, stderr = p.communicate() - if stdout and check_version in stdout: + output = check_output(['pip', 'show', package.split('/')[1]]) + if check_version in output: print('{} already installed'.format(package)) return - if p.returncode != 0: - # Old versions of pip such as the one installed on Travis don't support - # the show command - continue installation in this case. - # Otherwise throw CalledProcessError. - if p.returncode > 1 and 'No command by the name pip show' not in stderr: - raise CalledProcessError(p.returncode, cmd) - else: - print('Uninstalling {}'.format(package)) - check_call('pip', 'uninstall', '-y', package) package = 'git+git://github.com/{0}.git@{1}'.format(package, commit) print('Installing {}'.format(package)) check_call(['pip', 'install', '--upgrade', package]) From ee6f4e7aecd74ca94be2dea48c48d9fe8d3deb23 Mon Sep 17 00:00:00 2001 From: vitaut Date: Wed, 14 Oct 2015 08:31:54 -0700 Subject: [PATCH 55/84] Check pip version once and skip pip show for now --- doc/build.py | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/doc/build.py b/doc/build.py index 235e9afc..1d405974 100755 --- a/doc/build.py +++ b/doc/build.py @@ -8,16 +8,12 @@ from distutils.version import LooseVersion def pip_install(package, commit=None, **kwargs): "Install package using pip." - if LooseVersion(pip.__version__) < LooseVersion('1.5.4'): - # Upgrade pip because installation of sphinx with pip 1.1 available on Travis - # is broken (see #207) and it doesn't support the show command. - check_call(['pip', 'install', '--upgrade', 'pip']) if commit: check_version = kwargs.get('check_version', '') - output = check_output(['pip', 'show', package.split('/')[1]]) - if check_version in output: - print('{} already installed'.format(package)) - return + #output = check_output(['pip', 'show', package.split('/')[1]]) + #if check_version in output: + # print('{} already installed'.format(package)) + # return package = 'git+git://github.com/{0}.git@{1}'.format(package, commit) print('Installing {}'.format(package)) check_call(['pip', 'install', '--upgrade', package]) @@ -29,6 +25,10 @@ def build_docs(): check_call(['virtualenv', virtualenv_dir]) activate_this_file = os.path.join(virtualenv_dir, 'bin', 'activate_this.py') execfile(activate_this_file, dict(__file__=activate_this_file)) + # Upgrade pip because installation of sphinx with pip 1.1 available on Travis + # is broken (see #207) and it doesn't support the show command. + if LooseVersion(pip.__version__) < LooseVersion('1.5.4'): + check_call(['pip', 'install', '--upgrade', 'pip']) # Install Sphinx and Breathe. pip_install('sphinx-doc/sphinx', '4d2c17e043d9e8197fa5cd0db34212af3bb17069', @@ -39,7 +39,6 @@ def build_docs(): print(check_output(['sphinx-build', '--version'])) print('PATH:', os.environ['PATH']) print(check_output(['which', 'sphinx-build'])) - print(check_output(['cat', '/home/travis/build/cppformat/cppformat/virtualenv/bin/sphinx-build'])) import sphinx print(sphinx.__version__) # Build docs. From e61f4d2bf6cdcfb69ec91fef555ffde1af7af010 Mon Sep 17 00:00:00 2001 From: vitaut Date: Wed, 14 Oct 2015 08:36:58 -0700 Subject: [PATCH 56/84] Upgrade to pip 1.5.4 --- doc/build.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/build.py b/doc/build.py index 1d405974..926575ed 100755 --- a/doc/build.py +++ b/doc/build.py @@ -28,7 +28,7 @@ def build_docs(): # Upgrade pip because installation of sphinx with pip 1.1 available on Travis # is broken (see #207) and it doesn't support the show command. if LooseVersion(pip.__version__) < LooseVersion('1.5.4'): - check_call(['pip', 'install', '--upgrade', 'pip']) + check_call(['pip', 'install', '--upgrade', 'pip==1.5.4']) # Install Sphinx and Breathe. pip_install('sphinx-doc/sphinx', '4d2c17e043d9e8197fa5cd0db34212af3bb17069', From e854c7d47e12e5c58afed680fe0a016d537066fa Mon Sep 17 00:00:00 2001 From: vitaut Date: Thu, 15 Oct 2015 06:41:16 -0700 Subject: [PATCH 57/84] Check if pip is updated --- doc/build.py | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/build.py b/doc/build.py index 926575ed..eab739fd 100755 --- a/doc/build.py +++ b/doc/build.py @@ -28,6 +28,7 @@ def build_docs(): # Upgrade pip because installation of sphinx with pip 1.1 available on Travis # is broken (see #207) and it doesn't support the show command. if LooseVersion(pip.__version__) < LooseVersion('1.5.4'): + print("Updating pip") check_call(['pip', 'install', '--upgrade', 'pip==1.5.4']) # Install Sphinx and Breathe. pip_install('sphinx-doc/sphinx', From a5b296a484bc4f4765453a19ac179f9261834fd0 Mon Sep 17 00:00:00 2001 From: vitaut Date: Thu, 15 Oct 2015 07:08:26 -0700 Subject: [PATCH 58/84] More diagnostics --- doc/build.py | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/build.py b/doc/build.py index eab739fd..68ec9cd0 100755 --- a/doc/build.py +++ b/doc/build.py @@ -27,6 +27,7 @@ def build_docs(): execfile(activate_this_file, dict(__file__=activate_this_file)) # Upgrade pip because installation of sphinx with pip 1.1 available on Travis # is broken (see #207) and it doesn't support the show command. + print('pip version: {} {}'.format(pip.__version__, LooseVersion(pip.__version__) < LooseVersion('1.5.4'))) if LooseVersion(pip.__version__) < LooseVersion('1.5.4'): print("Updating pip") check_call(['pip', 'install', '--upgrade', 'pip==1.5.4']) From 238d6dc506a06c0d9b390bd1629860a486e5b208 Mon Sep 17 00:00:00 2001 From: vitaut Date: Thu, 15 Oct 2015 07:14:57 -0700 Subject: [PATCH 59/84] Try importing pip after activating virtualenv --- doc/build.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/build.py b/doc/build.py index 68ec9cd0..4b741b10 100755 --- a/doc/build.py +++ b/doc/build.py @@ -2,7 +2,7 @@ # Build the documentation. from __future__ import print_function -import os, pip, shutil, tempfile +import os, shutil, tempfile from subprocess import check_call, check_output, CalledProcessError, Popen, PIPE from distutils.version import LooseVersion @@ -27,6 +27,7 @@ def build_docs(): execfile(activate_this_file, dict(__file__=activate_this_file)) # Upgrade pip because installation of sphinx with pip 1.1 available on Travis # is broken (see #207) and it doesn't support the show command. + import pip print('pip version: {} {}'.format(pip.__version__, LooseVersion(pip.__version__) < LooseVersion('1.5.4'))) if LooseVersion(pip.__version__) < LooseVersion('1.5.4'): print("Updating pip") From a257d811d84bf2ba35c319709d0829ef9ee82659 Mon Sep 17 00:00:00 2001 From: vitaut Date: Thu, 15 Oct 2015 07:20:52 -0700 Subject: [PATCH 60/84] Check if pip has __version__ --- doc/build.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/build.py b/doc/build.py index 4b741b10..41964bb7 100755 --- a/doc/build.py +++ b/doc/build.py @@ -28,8 +28,8 @@ def build_docs(): # Upgrade pip because installation of sphinx with pip 1.1 available on Travis # is broken (see #207) and it doesn't support the show command. import pip - print('pip version: {} {}'.format(pip.__version__, LooseVersion(pip.__version__) < LooseVersion('1.5.4'))) - if LooseVersion(pip.__version__) < LooseVersion('1.5.4'): + if not '__version__' in dir(pip) or \ + LooseVersion(pip.__version__) < LooseVersion('1.5.4'): print("Updating pip") check_call(['pip', 'install', '--upgrade', 'pip==1.5.4']) # Install Sphinx and Breathe. From 39265a428873c83de548f09e9eeaab55ad15ef25 Mon Sep 17 00:00:00 2001 From: vitaut Date: Thu, 15 Oct 2015 07:40:34 -0700 Subject: [PATCH 61/84] Try the latest version of pip --- doc/build.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/build.py b/doc/build.py index 41964bb7..6a38cde2 100755 --- a/doc/build.py +++ b/doc/build.py @@ -31,7 +31,7 @@ def build_docs(): if not '__version__' in dir(pip) or \ LooseVersion(pip.__version__) < LooseVersion('1.5.4'): print("Updating pip") - check_call(['pip', 'install', '--upgrade', 'pip==1.5.4']) + check_call(['pip', 'install', '--upgrade', 'pip']) # Install Sphinx and Breathe. pip_install('sphinx-doc/sphinx', '4d2c17e043d9e8197fa5cd0db34212af3bb17069', From 2a4f98f4746a1c2cf13b9c07983c7157ca3e0c4e Mon Sep 17 00:00:00 2001 From: vitaut Date: Thu, 15 Oct 2015 07:54:41 -0700 Subject: [PATCH 62/84] Diagnose sphinx-build failure on Travis --- doc/build.py | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/build.py b/doc/build.py index 6a38cde2..5d86664a 100755 --- a/doc/build.py +++ b/doc/build.py @@ -39,6 +39,7 @@ def build_docs(): pip_install('michaeljones/breathe', '511b0887293e7c6b12310bb61b3659068f48f0f4') print(check_output(['pip', '--version'])) + print(check_output(['pip', 'show', 'sphinx-rtd-theme'])) print(check_output(['sphinx-build', '--version'])) print('PATH:', os.environ['PATH']) print(check_output(['which', 'sphinx-build'])) From 1554c9c6e5cd5a02abf5aa6084ad38ab221456b5 Mon Sep 17 00:00:00 2001 From: vitaut Date: Thu, 15 Oct 2015 08:09:19 -0700 Subject: [PATCH 63/84] Diagnose sphinx-build failure on Travis --- doc/build.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/doc/build.py b/doc/build.py index 5d86664a..bd69714d 100755 --- a/doc/build.py +++ b/doc/build.py @@ -2,7 +2,7 @@ # Build the documentation. from __future__ import print_function -import os, shutil, tempfile +import os, pkg_resources, shutil, tempfile from subprocess import check_call, check_output, CalledProcessError, Popen, PIPE from distutils.version import LooseVersion @@ -27,9 +27,9 @@ def build_docs(): execfile(activate_this_file, dict(__file__=activate_this_file)) # Upgrade pip because installation of sphinx with pip 1.1 available on Travis # is broken (see #207) and it doesn't support the show command. - import pip - if not '__version__' in dir(pip) or \ - LooseVersion(pip.__version__) < LooseVersion('1.5.4'): + pip_version = pkg_resources.get_distribution('pip').version + print('pip version: ' + pip_version) + if LooseVersion(pip_version) < LooseVersion('1.5.4'): print("Updating pip") check_call(['pip', 'install', '--upgrade', 'pip']) # Install Sphinx and Breathe. @@ -39,6 +39,7 @@ def build_docs(): pip_install('michaeljones/breathe', '511b0887293e7c6b12310bb61b3659068f48f0f4') print(check_output(['pip', '--version'])) + print('sphinx-rtd-theme version: ' + pkg_resources.get_distribution("sphinx-rtd-theme").version) print(check_output(['pip', 'show', 'sphinx-rtd-theme'])) print(check_output(['sphinx-build', '--version'])) print('PATH:', os.environ['PATH']) From 9daa774b5b165bf09a8cfbe764143c78370cc7b8 Mon Sep 17 00:00:00 2001 From: vitaut Date: Thu, 15 Oct 2015 08:13:32 -0700 Subject: [PATCH 64/84] Import pkg_resources after activating virtualenv --- doc/build.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/build.py b/doc/build.py index bd69714d..c59391b1 100755 --- a/doc/build.py +++ b/doc/build.py @@ -2,7 +2,7 @@ # Build the documentation. from __future__ import print_function -import os, pkg_resources, shutil, tempfile +import os, shutil, tempfile from subprocess import check_call, check_output, CalledProcessError, Popen, PIPE from distutils.version import LooseVersion @@ -27,6 +27,7 @@ def build_docs(): execfile(activate_this_file, dict(__file__=activate_this_file)) # Upgrade pip because installation of sphinx with pip 1.1 available on Travis # is broken (see #207) and it doesn't support the show command. + import pkg_resources pip_version = pkg_resources.get_distribution('pip').version print('pip version: ' + pip_version) if LooseVersion(pip_version) < LooseVersion('1.5.4'): From 694bfb5309a7a1b19f25c0600cf808916045cd53 Mon Sep 17 00:00:00 2001 From: vitaut Date: Thu, 15 Oct 2015 08:19:33 -0700 Subject: [PATCH 65/84] sphinx-rtd-theme -> sphinx_rtd_theme --- doc/build.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/build.py b/doc/build.py index c59391b1..ce3867cc 100755 --- a/doc/build.py +++ b/doc/build.py @@ -40,7 +40,7 @@ def build_docs(): pip_install('michaeljones/breathe', '511b0887293e7c6b12310bb61b3659068f48f0f4') print(check_output(['pip', '--version'])) - print('sphinx-rtd-theme version: ' + pkg_resources.get_distribution("sphinx-rtd-theme").version) + print('sphinx-rtd-theme version: ' + pkg_resources.get_distribution("sphinx_rtd_theme").version) print(check_output(['pip', 'show', 'sphinx-rtd-theme'])) print(check_output(['sphinx-build', '--version'])) print('PATH:', os.environ['PATH']) From d57c6204cdb54c2ee693e08a602f17d59566d6f4 Mon Sep 17 00:00:00 2001 From: vitaut Date: Thu, 15 Oct 2015 08:26:44 -0700 Subject: [PATCH 66/84] Try installing the stupid sphinx-rtd-theme explicitly --- doc/build.py | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/build.py b/doc/build.py index ce3867cc..b0547f22 100755 --- a/doc/build.py +++ b/doc/build.py @@ -34,6 +34,7 @@ def build_docs(): print("Updating pip") check_call(['pip', 'install', '--upgrade', 'pip']) # Install Sphinx and Breathe. + check_call(['pip', 'install', 'sphinx-rtd-theme==0.1.8']) pip_install('sphinx-doc/sphinx', '4d2c17e043d9e8197fa5cd0db34212af3bb17069', check_version='1.4a0.dev-20151013') From 221eeda912ec1eca1fcf7500172aed44459ad8fb Mon Sep 17 00:00:00 2001 From: vitaut Date: Thu, 15 Oct 2015 08:30:16 -0700 Subject: [PATCH 67/84] Remove diagnostics which is not working --- doc/build.py | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/build.py b/doc/build.py index b0547f22..b485645e 100755 --- a/doc/build.py +++ b/doc/build.py @@ -41,7 +41,6 @@ def build_docs(): pip_install('michaeljones/breathe', '511b0887293e7c6b12310bb61b3659068f48f0f4') print(check_output(['pip', '--version'])) - print('sphinx-rtd-theme version: ' + pkg_resources.get_distribution("sphinx_rtd_theme").version) print(check_output(['pip', 'show', 'sphinx-rtd-theme'])) print(check_output(['sphinx-build', '--version'])) print('PATH:', os.environ['PATH']) From 2cca51c7448f6e7f9ceb47373a6e8e0db3457cd8 Mon Sep 17 00:00:00 2001 From: Richard Maxwell Date: Fri, 9 Oct 2015 08:55:05 +1300 Subject: [PATCH 68/84] Issue 205: Make iostream support optional. --- format.cc | 2 ++ format.h | 12 +++++++++++- test/format-test.cc | 2 ++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/format.cc b/format.cc index a9c978b9..84b81f88 100644 --- a/format.cc +++ b/format.cc @@ -1252,11 +1252,13 @@ FMT_FUNC void fmt::print(CStringRef format_str, ArgList args) { print(stdout, format_str, args); } +#ifndef FMT_NO_STREAM_LIBRARIES FMT_FUNC void fmt::print(std::ostream &os, CStringRef format_str, ArgList args) { MemoryWriter w; w.write(format_str, args); os.write(w.data(), w.size()); } +#endif FMT_FUNC void fmt::print_colored(Color c, CStringRef format, ArgList args) { char escape[] = "\x1b[30m"; diff --git a/format.h b/format.h index d25eab34..ecb61fa5 100644 --- a/format.h +++ b/format.h @@ -38,9 +38,12 @@ #include #include #include -#include #include +#ifndef FMT_NO_STREAM_LIBRARIES +# include +#endif + #if _SECURE_SCL # include #endif @@ -2685,6 +2688,8 @@ void print(std::FILE *f, CStringRef format_str, ArgList args); */ void print(CStringRef format_str, ArgList args); + +#ifndef FMT_NO_STREAM_LIBRARIES /** \rst Prints formatted data to the stream *os*. @@ -2695,6 +2700,7 @@ void print(CStringRef format_str, ArgList args); \endrst */ void print(std::ostream &os, CStringRef format_str, ArgList args); +#endif template void printf(BasicWriter &w, BasicCStringRef format, ArgList args) { @@ -3007,7 +3013,11 @@ FMT_VARIADIC(std::string, format, CStringRef) FMT_VARIADIC_W(std::wstring, format, WCStringRef) FMT_VARIADIC(void, print, CStringRef) FMT_VARIADIC(void, print, std::FILE *, CStringRef) + +#ifndef FMT_NO_STREAM_LIBRARIES FMT_VARIADIC(void, print, std::ostream &, CStringRef) +#endif + FMT_VARIADIC(void, print_colored, Color, CStringRef) FMT_VARIADIC(std::string, sprintf, CStringRef) FMT_VARIADIC_W(std::wstring, sprintf, WCStringRef) diff --git a/test/format-test.cc b/test/format-test.cc index 3fceab88..e9b522a2 100644 --- a/test/format-test.cc +++ b/test/format-test.cc @@ -1539,6 +1539,7 @@ TEST(FormatIntTest, FormatDec) { EXPECT_EQ("42", format_decimal(42ull)); } +#ifndef FMT_NO_STREAM_LIBRARIES TEST(FormatTest, Print) { #if FMT_USE_FILE_DESCRIPTORS EXPECT_WRITE(stdout, fmt::print("Don't {}!", "panic"), "Don't panic!"); @@ -1549,6 +1550,7 @@ TEST(FormatTest, Print) { fmt::print(os, "Don't {}!", "panic"); EXPECT_EQ("Don't panic!", os.str()); } +#endif #if FMT_USE_FILE_DESCRIPTORS TEST(FormatTest, PrintColored) { From 884c55741fd6e630a9ab89762b5703f0c975458e Mon Sep 17 00:00:00 2001 From: vitaut Date: Fri, 16 Oct 2015 07:00:19 -0700 Subject: [PATCH 69/84] Install a version of sphinx without sphinx-rtd-theme because the latter breaks the sphinx-build --- doc/build.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/doc/build.py b/doc/build.py index b485645e..09488549 100755 --- a/doc/build.py +++ b/doc/build.py @@ -34,9 +34,8 @@ def build_docs(): print("Updating pip") check_call(['pip', 'install', '--upgrade', 'pip']) # Install Sphinx and Breathe. - check_call(['pip', 'install', 'sphinx-rtd-theme==0.1.8']) - pip_install('sphinx-doc/sphinx', - '4d2c17e043d9e8197fa5cd0db34212af3bb17069', + pip_install('cppformat/sphinx', + '12dde8afdb0a7bb5576e2656692c3478c69d8cc3', check_version='1.4a0.dev-20151013') pip_install('michaeljones/breathe', '511b0887293e7c6b12310bb61b3659068f48f0f4') From 418cd1c82aca938cdba4e0d7f8f21f2af9e11263 Mon Sep 17 00:00:00 2001 From: vitaut Date: Fri, 16 Oct 2015 07:03:45 -0700 Subject: [PATCH 70/84] Pip show no more --- doc/build.py | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/build.py b/doc/build.py index 09488549..8a115aa9 100755 --- a/doc/build.py +++ b/doc/build.py @@ -40,7 +40,6 @@ def build_docs(): pip_install('michaeljones/breathe', '511b0887293e7c6b12310bb61b3659068f48f0f4') print(check_output(['pip', '--version'])) - print(check_output(['pip', 'show', 'sphinx-rtd-theme'])) print(check_output(['sphinx-build', '--version'])) print('PATH:', os.environ['PATH']) print(check_output(['which', 'sphinx-build'])) From ee1fdc575b136c279e53a6fb3da192f987b46509 Mon Sep 17 00:00:00 2001 From: vitaut Date: Fri, 16 Oct 2015 07:18:04 -0700 Subject: [PATCH 71/84] Print alabaster version --- doc/build.py | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/build.py b/doc/build.py index 8a115aa9..fbc6b714 100755 --- a/doc/build.py +++ b/doc/build.py @@ -40,6 +40,7 @@ def build_docs(): pip_install('michaeljones/breathe', '511b0887293e7c6b12310bb61b3659068f48f0f4') print(check_output(['pip', '--version'])) + print(check_output(['pip', 'show', 'alabaster'])) print(check_output(['sphinx-build', '--version'])) print('PATH:', os.environ['PATH']) print(check_output(['which', 'sphinx-build'])) From 2d921c96e0f1c5245700b1af1cba3c3bc1c89b34 Mon Sep 17 00:00:00 2001 From: vitaut Date: Fri, 16 Oct 2015 07:34:38 -0700 Subject: [PATCH 72/84] Update sphinx --- doc/build.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/build.py b/doc/build.py index fbc6b714..c28df576 100755 --- a/doc/build.py +++ b/doc/build.py @@ -35,7 +35,7 @@ def build_docs(): check_call(['pip', 'install', '--upgrade', 'pip']) # Install Sphinx and Breathe. pip_install('cppformat/sphinx', - '12dde8afdb0a7bb5576e2656692c3478c69d8cc3', + 'bb0bdaa6c99a9a9834ab689be9d859d01f876452', check_version='1.4a0.dev-20151013') pip_install('michaeljones/breathe', '511b0887293e7c6b12310bb61b3659068f48f0f4') From aaa8b1e0aa5e14765dfa57484e5a2eba8db2184a Mon Sep 17 00:00:00 2001 From: vitaut Date: Fri, 16 Oct 2015 08:07:44 -0700 Subject: [PATCH 73/84] Upgrade distribute if it is 0.6.24 or lower because installation of sphinx with distribute 0.6.24 available on Travis is broken. --- doc/build.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/doc/build.py b/doc/build.py index c28df576..95264412 100755 --- a/doc/build.py +++ b/doc/build.py @@ -27,15 +27,24 @@ def build_docs(): execfile(activate_this_file, dict(__file__=activate_this_file)) # Upgrade pip because installation of sphinx with pip 1.1 available on Travis # is broken (see #207) and it doesn't support the show command. - import pkg_resources - pip_version = pkg_resources.get_distribution('pip').version - print('pip version: ' + pip_version) + from pkg_resources import get_distribution, DistributionNotFound + pip_version = get_distribution('pip').version if LooseVersion(pip_version) < LooseVersion('1.5.4'): print("Updating pip") check_call(['pip', 'install', '--upgrade', 'pip']) + # Upgrade distribute because installation of sphinx with distribute 0.6.24 + # available on Travis is broken (see #207). + try: + distribute_version = get_distribution('distribute').version + print('distribute version: ' + distribute_version) + if LooseVersion(distribute_version) <= LooseVersion('0.6.24'): + print("Updating distribute") + check_call(['pip', 'install', '--upgrade', 'distribute']) + except DistributionNotFound: + pass # Install Sphinx and Breathe. pip_install('cppformat/sphinx', - 'bb0bdaa6c99a9a9834ab689be9d859d01f876452', + '12dde8afdb0a7bb5576e2656692c3478c69d8cc3', check_version='1.4a0.dev-20151013') pip_install('michaeljones/breathe', '511b0887293e7c6b12310bb61b3659068f48f0f4') From 79d7aacff31641d21f3a30aade03aa4ea48c055c Mon Sep 17 00:00:00 2001 From: vitaut Date: Fri, 16 Oct 2015 08:13:54 -0700 Subject: [PATCH 74/84] Remove diagnostics --- doc/build.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/doc/build.py b/doc/build.py index 95264412..9f752889 100755 --- a/doc/build.py +++ b/doc/build.py @@ -36,7 +36,6 @@ def build_docs(): # available on Travis is broken (see #207). try: distribute_version = get_distribution('distribute').version - print('distribute version: ' + distribute_version) if LooseVersion(distribute_version) <= LooseVersion('0.6.24'): print("Updating distribute") check_call(['pip', 'install', '--upgrade', 'distribute']) @@ -48,13 +47,6 @@ def build_docs(): check_version='1.4a0.dev-20151013') pip_install('michaeljones/breathe', '511b0887293e7c6b12310bb61b3659068f48f0f4') - print(check_output(['pip', '--version'])) - print(check_output(['pip', 'show', 'alabaster'])) - print(check_output(['sphinx-build', '--version'])) - print('PATH:', os.environ['PATH']) - print(check_output(['which', 'sphinx-build'])) - import sphinx - print(sphinx.__version__) # Build docs. cmd = ['doxygen', '-'] p = Popen(cmd, stdin=PIPE) From a596b8724bf422b945fdf3bb2ba76acfcd32c1b3 Mon Sep 17 00:00:00 2001 From: vitaut Date: Fri, 16 Oct 2015 08:28:58 -0700 Subject: [PATCH 75/84] Improve error message when less is not installed --- doc/build.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/doc/build.py b/doc/build.py index 9f752889..481623cb 100755 --- a/doc/build.py +++ b/doc/build.py @@ -2,7 +2,7 @@ # Build the documentation. from __future__ import print_function -import os, shutil, tempfile +import errno, os, shutil, sys, tempfile from subprocess import check_call, check_output, CalledProcessError, Popen, PIPE from distutils.version import LooseVersion @@ -76,10 +76,16 @@ def build_docs(): check_call(['sphinx-build', '-D', 'breathe_projects.format=' + os.path.join(os.getcwd(), 'doxyxml'), '-b', 'html', doc_dir, 'html']) - check_call(['lessc', '--clean-css', - '--include-path=' + os.path.join(doc_dir, 'bootstrap'), - os.path.join(doc_dir, 'cppformat.less'), - 'html/_static/cppformat.css']) + try: + check_call(['lessc', '--clean-css', + '--include-path=' + os.path.join(doc_dir, 'bootstrap'), + os.path.join(doc_dir, 'cppformat.less'), + 'html/_static/cppformat.css']) + except OSError, e: + if e.errno != errno.ENOENT: + raise + print('lessc not found; make sure that Less (http://lesscss.org/) is installed') + sys.exit(1) return 'html' if __name__ == '__main__': From 5898720c282e24be6e05b31592204b3515812759 Mon Sep 17 00:00:00 2001 From: vitaut Date: Sat, 17 Oct 2015 08:05:58 -0700 Subject: [PATCH 76/84] Make documentation build script compatible with Python 3 --- doc/build.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/doc/build.py b/doc/build.py index 481623cb..d4266c6b 100755 --- a/doc/build.py +++ b/doc/build.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python # Build the documentation. from __future__ import print_function @@ -24,7 +24,8 @@ def build_docs(): virtualenv_dir = 'virtualenv' check_call(['virtualenv', virtualenv_dir]) activate_this_file = os.path.join(virtualenv_dir, 'bin', 'activate_this.py') - execfile(activate_this_file, dict(__file__=activate_this_file)) + with open(activate_this_file) as f: + exec(f.read(), dict(__file__=activate_this_file)) # Upgrade pip because installation of sphinx with pip 1.1 available on Travis # is broken (see #207) and it doesn't support the show command. from pkg_resources import get_distribution, DistributionNotFound @@ -70,7 +71,7 @@ def build_docs(): FMT_USE_RVALUE_REFERENCES=1 \ FMT_USE_USER_DEFINED_LITERALS=1 EXCLUDE_SYMBOLS = fmt::internal::* StringValue write_str - '''.format(os.path.dirname(doc_dir))) + '''.format(os.path.dirname(doc_dir)).encode('UTF-8')) if p.returncode != 0: raise CalledProcessError(p.returncode, cmd) check_call(['sphinx-build', '-D', @@ -81,7 +82,7 @@ def build_docs(): '--include-path=' + os.path.join(doc_dir, 'bootstrap'), os.path.join(doc_dir, 'cppformat.less'), 'html/_static/cppformat.css']) - except OSError, e: + except OSError as e: if e.errno != errno.ENOENT: raise print('lessc not found; make sure that Less (http://lesscss.org/) is installed') From 826edabae10fd14aae12c4d29049e4c7b0f2fc3e Mon Sep 17 00:00:00 2001 From: vitaut Date: Sat, 17 Oct 2015 08:17:32 -0700 Subject: [PATCH 77/84] Add building the documentation section --- doc/usage.rst | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/doc/usage.rst b/doc/usage.rst index ea3e43be..3d900ff6 100644 --- a/doc/usage.rst +++ b/doc/usage.rst @@ -54,6 +54,23 @@ To build a `shared library`__ set the ``BUILD_SHARED_LIBS`` CMake variable to __ http://en.wikipedia.org/wiki/Library_%28computing%29#Shared_libraries +Building the documentation +========================== + +To build the documentation you need the following software installed on your +system: + +* [Python](https://www.python.org/) with pip and virtualenv +* [Doxygen](http://www.stack.nl/~dimitri/doxygen/) +* [Less](http://lesscss.org/) with less-plugin-clean-css + +First generate makefiles or project files using CMake as described in +previous section. Then compile the ``doc`` target/project, for example:: + + make doc + +This will generate HTML documenation in ``doc/html``. + Android NDK =========== From 6d9712c7fdef4751d33ee2a3f0b83cec5ffb2ef0 Mon Sep 17 00:00:00 2001 From: vitaut Date: Sat, 17 Oct 2015 08:21:23 -0700 Subject: [PATCH 78/84] Fix links --- doc/usage.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/usage.rst b/doc/usage.rst index 3d900ff6..abd74eee 100644 --- a/doc/usage.rst +++ b/doc/usage.rst @@ -60,9 +60,9 @@ Building the documentation To build the documentation you need the following software installed on your system: -* [Python](https://www.python.org/) with pip and virtualenv -* [Doxygen](http://www.stack.nl/~dimitri/doxygen/) -* [Less](http://lesscss.org/) with less-plugin-clean-css +* `Python `_ with pip and virtualenv +* `Doxygen `_ +* `Less `_ with less-plugin-clean-css First generate makefiles or project files using CMake as described in previous section. Then compile the ``doc`` target/project, for example:: From 044ef900bceb9b17d08444cdfc59a20e9267edab Mon Sep 17 00:00:00 2001 From: vitaut Date: Sat, 17 Oct 2015 08:34:58 -0700 Subject: [PATCH 79/84] Grammar --- doc/usage.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/usage.rst b/doc/usage.rst index abd74eee..bee62ed2 100644 --- a/doc/usage.rst +++ b/doc/usage.rst @@ -65,11 +65,11 @@ system: * `Less `_ with less-plugin-clean-css First generate makefiles or project files using CMake as described in -previous section. Then compile the ``doc`` target/project, for example:: +the previous section. Then compile the ``doc`` target/project, for example:: make doc -This will generate HTML documenation in ``doc/html``. +This will generate the HTML documenation in ``doc/html``. Android NDK =========== From caa8f76a88f644881b73d944ad73afeab7e2dabe Mon Sep 17 00:00:00 2001 From: vitaut Date: Sat, 17 Oct 2015 17:35:51 -0700 Subject: [PATCH 80/84] Make content wider on medium-size devices (#210) --- doc/cppformat.less | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/doc/cppformat.less b/doc/cppformat.less index 44772375..f3e78a65 100644 --- a/doc/cppformat.less +++ b/doc/cppformat.less @@ -13,11 +13,6 @@ html { background-color: darken(@header-bg, 10%); } -.navbar-content { - .make-md-column-offset(2); - .make-md-column(8); -} - .jumbotron { #gradient > .vertical(@header-bg; darken(@header-bg, 2%); 50%; 50%); background-size: 100% 4px; @@ -32,9 +27,11 @@ div.sphinxsidebar { } // Keep content not too wide for better readability. -.content { - .make-md-column-offset(2); - .make-md-column(8); +.navbar-content, .content { + .make-md-column-offset(1); + .make-md-column(10); + .make-lg-column-offset(2); + .make-lg-column(8); } .footer { From 9608a98b01995eb5258841aafc19371f112470e7 Mon Sep 17 00:00:00 2001 From: Dean Moldovan Date: Sun, 11 Oct 2015 04:07:38 +0200 Subject: [PATCH 81/84] Fix shared library build on OS X --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6a4613e1..1fb4a707 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -95,7 +95,7 @@ if (BIICODE) endif () add_library(cppformat ${FMT_SOURCES}) -if (BUILD_SHARED_LIBS) +if (BUILD_SHARED_LIBS AND 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) From 77b32006a3cdfb6d4a8154cb1a92f23602660207 Mon Sep 17 00:00:00 2001 From: vitaut Date: Sun, 18 Oct 2015 06:42:24 -0700 Subject: [PATCH 82/84] Workaround a bug in MSVC when _CRTDBG_MAP_ALLOC is defined --- format.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/format.h b/format.h index d25eab34..e1340e7c 100644 --- a/format.h +++ b/format.h @@ -458,9 +458,9 @@ class MemoryBuffer : private Allocator, public Buffer { private: T data_[SIZE]; - // Free memory allocated by the buffer. - void free() { - if (this->ptr_ != data_) this->deallocate(this->ptr_, this->capacity_); + // Deallocate memory allocated by the buffer. + void deallocate() { + if (this->ptr_ != data_) Allocator::deallocate(this->ptr_, this->capacity_); } protected: @@ -469,7 +469,7 @@ class MemoryBuffer : private Allocator, public Buffer { public: explicit MemoryBuffer(const Allocator &alloc = Allocator()) : Allocator(alloc), Buffer(data_, SIZE) {} - ~MemoryBuffer() { free(); } + ~MemoryBuffer() { deallocate(); } #if FMT_USE_RVALUE_REFERENCES private: @@ -486,7 +486,7 @@ class MemoryBuffer : private Allocator, public Buffer { } else { this->ptr_ = other.ptr_; // Set pointer to the inline array so that delete is not called - // when freeing. + // when deallocating. other.ptr_ = other.data_; } } @@ -498,7 +498,7 @@ class MemoryBuffer : private Allocator, public Buffer { MemoryBuffer &operator=(MemoryBuffer &&other) { assert(this != &other); - free(); + deallocate(); move(other); return *this; } @@ -524,7 +524,7 @@ void MemoryBuffer::grow(std::size_t size) { // the buffer already uses the new storage and will deallocate it in case // of exception. if (old_ptr != data_) - this->deallocate(old_ptr, old_capacity); + Allocator::deallocate(old_ptr, old_capacity); } // A fixed-size buffer. From b2714f83cc41ed84aff460161fbfa81f3d5e8882 Mon Sep 17 00:00:00 2001 From: vitaut Date: Sun, 18 Oct 2015 08:50:35 -0700 Subject: [PATCH 83/84] FMT_NO_STREAM_LIBRARIES -> FMT_USE_IOSTREAMS for consistency with similar macros and removed unnecessary checks. --- format.cc | 2 -- format.h | 40 ++++++++++++++++++++-------------------- test/format-test.cc | 2 -- 3 files changed, 20 insertions(+), 24 deletions(-) diff --git a/format.cc b/format.cc index 84b81f88..a9c978b9 100644 --- a/format.cc +++ b/format.cc @@ -1252,13 +1252,11 @@ FMT_FUNC void fmt::print(CStringRef format_str, ArgList args) { print(stdout, format_str, args); } -#ifndef FMT_NO_STREAM_LIBRARIES FMT_FUNC void fmt::print(std::ostream &os, CStringRef format_str, ArgList args) { MemoryWriter w; w.write(format_str, args); os.write(w.data(), w.size()); } -#endif FMT_FUNC void fmt::print_colored(Color c, CStringRef format, ArgList args) { char escape[] = "\x1b[30m"; diff --git a/format.h b/format.h index 144f585e..2f714001 100644 --- a/format.h +++ b/format.h @@ -40,7 +40,11 @@ #include #include -#ifndef FMT_NO_STREAM_LIBRARIES +#ifndef FMT_USE_IOSTREAMS +# define FMT_USE_IOSTREAMS 1 +#endif + +#if FMT_USE_IOSTREAMS # include #endif @@ -2688,20 +2692,6 @@ void print(std::FILE *f, CStringRef format_str, ArgList args); */ void print(CStringRef format_str, ArgList args); - -#ifndef FMT_NO_STREAM_LIBRARIES -/** - \rst - Prints formatted data to the stream *os*. - - **Example**:: - - print(cerr, "Don't {}!", "panic"); - \endrst - */ -void print(std::ostream &os, CStringRef format_str, ArgList args); -#endif - template void printf(BasicWriter &w, BasicCStringRef format, ArgList args) { internal::PrintfFormatter(args).format(w, format); @@ -3014,16 +3004,26 @@ FMT_VARIADIC_W(std::wstring, format, WCStringRef) FMT_VARIADIC(void, print, CStringRef) FMT_VARIADIC(void, print, std::FILE *, CStringRef) -#ifndef FMT_NO_STREAM_LIBRARIES -FMT_VARIADIC(void, print, std::ostream &, CStringRef) -#endif - FMT_VARIADIC(void, print_colored, Color, CStringRef) FMT_VARIADIC(std::string, sprintf, CStringRef) FMT_VARIADIC_W(std::wstring, sprintf, WCStringRef) FMT_VARIADIC(int, printf, CStringRef) FMT_VARIADIC(int, fprintf, std::FILE *, CStringRef) -} + +#if FMT_USE_IOSTREAMS +/** + \rst + Prints formatted data to the stream *os*. + + **Example**:: + + print(cerr, "Don't {}!", "panic"); + \endrst + */ +void print(std::ostream &os, CStringRef format_str, ArgList args); +FMT_VARIADIC(void, print, std::ostream &, CStringRef) +#endif +} // namespace fmt #if FMT_USE_USER_DEFINED_LITERALS namespace fmt { diff --git a/test/format-test.cc b/test/format-test.cc index e9b522a2..3fceab88 100644 --- a/test/format-test.cc +++ b/test/format-test.cc @@ -1539,7 +1539,6 @@ TEST(FormatIntTest, FormatDec) { EXPECT_EQ("42", format_decimal(42ull)); } -#ifndef FMT_NO_STREAM_LIBRARIES TEST(FormatTest, Print) { #if FMT_USE_FILE_DESCRIPTORS EXPECT_WRITE(stdout, fmt::print("Don't {}!", "panic"), "Don't panic!"); @@ -1550,7 +1549,6 @@ TEST(FormatTest, Print) { fmt::print(os, "Don't {}!", "panic"); EXPECT_EQ("Don't panic!", os.str()); } -#endif #if FMT_USE_FILE_DESCRIPTORS TEST(FormatTest, PrintColored) { From e81c0aef39ab3127b265c5fcc2c20a857f28b474 Mon Sep 17 00:00:00 2001 From: vitaut Date: Sun, 18 Oct 2015 09:16:10 -0700 Subject: [PATCH 84/84] Fix bogus coverity warnings. --- test/test-main.cc | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/test/test-main.cc b/test/test-main.cc index 9f5426ee..350044da 100644 --- a/test/test-main.cc +++ b/test/test-main.cc @@ -25,6 +25,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include #include #ifdef _WIN32 @@ -52,5 +53,10 @@ int main(int argc, char **argv) { _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG); _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); + try { + return RUN_ALL_TESTS(); + } catch (...) { + // Catch all exceptions to make Coverity happy. + } + return EXIT_FAILURE; }