From 3785afc5a3f7f27cd11ade8c7371eecd2b02fa81 Mon Sep 17 00:00:00 2001 From: Victor Zverovich Date: Sun, 15 Oct 2017 17:15:01 -0700 Subject: [PATCH] Pass errors to handler instead of throwing (#566) --- .travis.yml | 15 ++++++++++-- fmt/format.h | 49 +++++++++++++++++++++++++-------------- support/cmake/cxx14.cmake | 1 + support/travis-build.py | 6 ++--- 4 files changed, 48 insertions(+), 23 deletions(-) diff --git a/.travis.yml b/.travis.yml index 56a704c5..aa734f7d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,13 +14,24 @@ env: 6pxmyzLHSn1ZR7OX5rfPvwM3tOyZ3H0= matrix: - BUILD=Doc - - BUILD=Debug STANDARD=0x - - BUILD=Release STANDARD=0x + - BUILD=Debug STANDARD=14 + - BUILD=Release STANDARD=14 matrix: exclude: - os: osx env: BUILD=Doc +# Install gcc-6 for extended constexpr support. +addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - g++-6 + +before_install: + - export CXX=g++-6 + script: - support/travis-build.py diff --git a/fmt/format.h b/fmt/format.h index 370b6fc3..7d88a3a2 100644 --- a/fmt/format.h +++ b/fmt/format.h @@ -3100,9 +3100,15 @@ struct precision_handler { } }; +struct error_handler { + void on_error(const char *message) { + FMT_THROW(format_error(message)); + } +}; + // A format specifier handler that sets fields in basic_format_specs. template -class specs_setter { +class specs_setter : public error_handler { public: explicit specs_setter(basic_format_specs &specs): specs_(specs) {} @@ -3316,12 +3322,6 @@ class dynamic_specs_handler : ParseContext &context_; }; -struct error_handler { - void on_error(const char *message) { - FMT_THROW(format_error(message)); - } -}; - template constexpr Iterator parse_arg_id(Iterator it, Handler& handler) { using char_type = typename std::iterator_traits::value_type; @@ -3358,7 +3358,7 @@ constexpr Iterator parse_arg_id(Iterator it, Handler& handler) { // format specifiers. template Iterator parse_format_specs(Iterator it, Handler &handler) { - using char_type = typename Iterator::value_type; + using char_type = typename std::iterator_traits::value_type; // Parse fill and alignment. if (char_type c = *it) { auto p = it + 1; @@ -3382,8 +3382,10 @@ Iterator parse_format_specs(Iterator it, Handler &handler) { handler.on_align(align); if (p != it) { if (c == '}') break; - if (c == '{') - FMT_THROW(format_error("invalid fill character '{'")); + if (c == '{') { + handler.on_error("invalid fill character '{'"); + return it; + } it += 2; handler.on_fill(c); } else ++it; @@ -3423,7 +3425,7 @@ Iterator parse_format_specs(Iterator it, Handler &handler) { if ('0' <= *it && *it <= '9') { handler.on_width(parse_nonnegative_int(it)); } else if (*it == '{') { - struct width_handler : error_handler { + struct width_handler { explicit width_handler(Handler &h) : handler(h) {} void operator()() { handler.on_dynamic_width(auto_id()); } @@ -3432,11 +3434,17 @@ Iterator parse_format_specs(Iterator it, Handler &handler) { handler.on_dynamic_width(id); } + void on_error(const char *message) { + handler.on_error(message); + } + Handler &handler; } wh(handler); it = parse_arg_id(it + 1, wh); - if (*it++ != '}') - FMT_THROW(format_error("invalid format string")); + if (*it++ != '}') { + handler.on_error("invalid format string"); + return it; + } } // Parse precision. @@ -3445,7 +3453,7 @@ Iterator parse_format_specs(Iterator it, Handler &handler) { if ('0' <= *it && *it <= '9') { handler.on_precision(parse_nonnegative_int(it)); } else if (*it == '{') { - struct precision_handler : error_handler { + struct precision_handler { explicit precision_handler(Handler &h) : handler(h) {} void operator()() { handler.on_dynamic_precision(auto_id()); } @@ -3454,13 +3462,20 @@ Iterator parse_format_specs(Iterator it, Handler &handler) { handler.on_dynamic_precision(id); } + void on_error(const char *message) { + handler.on_error(message); + } + Handler &handler; } ph(handler); it = parse_arg_id(it + 1, ph); - if (*it++ != '}') - FMT_THROW(format_error("invalid format string")); + if (*it++ != '}') { + handler.on_error("invalid format string"); + return it; + } } else { - FMT_THROW(format_error("missing precision specifier")); + handler.on_error("missing precision specifier"); + return it; } handler.end_precision(); } diff --git a/support/cmake/cxx14.cmake b/support/cmake/cxx14.cmake index 7b427a37..c86cf508 100644 --- a/support/cmake/cxx14.cmake +++ b/support/cmake/cxx14.cmake @@ -49,6 +49,7 @@ if (CMAKE_CXX_STANDARD) set(CPP14_FLAG ) endif () +message(STATUS "CPP14_FLAG: ${CPP14_FLAG}") set(CMAKE_REQUIRED_FLAGS ${CPP14_FLAG}) # Check if variadic templates are working and not affected by GCC bug 39653: diff --git a/support/travis-build.py b/support/travis-build.py index 91017792..fc61aa72 100755 --- a/support/travis-build.py +++ b/support/travis-build.py @@ -89,10 +89,8 @@ common_cmake_flags = [ '-DCMAKE_INSTALL_PREFIX=' + install_dir, '-DCMAKE_BUILD_TYPE=' + build ] extra_cmake_flags = [] -if standard != '0x': - extra_cmake_flags = [ - '-DCMAKE_CXX_FLAGS=-std=c++' + standard, '-DFMT_USE_CPP11=OFF' - ] +if standard != '14': + extra_cmake_flags = ['-DCMAKE_CXX_FLAGS=-std=c++' + standard] check_call(['cmake', '-DFMT_DOC=OFF', '-DFMT_PEDANTIC=ON', fmt_dir] + common_cmake_flags + extra_cmake_flags, cwd=build_dir)