diff --git a/CMakeLists.txt b/CMakeLists.txt index 5445b32..6ca682c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -47,18 +47,21 @@ if(MSVC) # make msvc standards compliant... add_compile_options(/permissive-) - macro(get_WIN32_WINNT version) - if(WIN32 AND CMAKE_SYSTEM_VERSION) - set(ver ${CMAKE_SYSTEM_VERSION}) - string(REPLACE "." "" ver ${ver}) - string(REGEX REPLACE "([0-9])" "0\\1" ver ${ver}) - - set(${version} "0x${ver}") - endif() - endmacro() - - get_WIN32_WINNT(ver) - add_definitions(-D_WIN32_WINNT=${ver}) + if(${CMAKE_SYSTEM_VERSION} GREATER_EQUAL 10) # Windows 10 + add_definitions(-D _WIN32_WINNT=0x0A00) + elseif(${CMAKE_SYSTEM_VERSION} EQUAL 6.3) # Windows 8.1 + add_definitions(-D _WIN32_WINNT=0x0603) + elseif(${CMAKE_SYSTEM_VERSION} EQUAL 6.2) # Windows 8 + add_definitions(-D _WIN32_WINNT=0x0602) + elseif(${CMAKE_SYSTEM_VERSION} EQUAL 6.1) # Windows 7 + add_definitions(-D _WIN32_WINNT=0x0601) + elseif(${CMAKE_SYSTEM_VERSION} EQUAL 6.0) # Windows Vista + add_definitions(-D _WIN32_WINNT=0x0600) + else() # Windows XP (5.1) + add_definitions(-D _WIN32_WINNT=0x0501) + endif() + + add_definitions(-DNOMINMAX) endif() add_library(libmcfp INTERFACE) @@ -105,7 +108,7 @@ endif() configure_package_config_file( ${PROJECT_SOURCE_DIR}/cmake/libmcfpConfig.cmake.in - ${PROJECT_SOURCE_DIR}/cmake/libmcfpConfig.cmake + ${CMAKE_CURRENT_BINARY_DIR}/libmcfpConfig.cmake INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/libmcfp PATH_VARS INCLUDE_INSTALL_DIR ) @@ -116,15 +119,17 @@ install(EXPORT libmcfpConfig DESTINATION ${CONFIG_LOC}) install( - FILES cmake/libmcfpConfig.cmake "${version_config}" + FILES ${CMAKE_CURRENT_BINARY_DIR}/libmcfpConfig.cmake "${version_config}" DESTINATION ${CONFIG_LOC}) if(ENABLE_TESTING) enable_testing() + find_package(Boost REQUIRED) + add_executable(libmcfp-unit-test ${PROJECT_SOURCE_DIR}/test/unit-test.cpp) - target_link_libraries(libmcfp-unit-test libmcfp::libmcfp) + target_link_libraries(libmcfp-unit-test libmcfp::libmcfp Boost::boost) if(MSVC) # Specify unwind semantics so that MSVC knowns how to handle exceptions diff --git a/include/mcfp/mcfp.hpp b/include/mcfp/mcfp.hpp index 92021aa..79ec051 100644 --- a/include/mcfp/mcfp.hpp +++ b/include/mcfp/mcfp.hpp @@ -94,7 +94,7 @@ class config_category_impl : public std::error_category } } - bool equivalent(const std::error_code &code, int condition) const noexcept override + bool equivalent(const std::error_code &/*code*/, int /*condition*/) const noexcept override { return false; } @@ -137,9 +137,9 @@ struct is_container_type : std::false_type template struct is_container_type and - std::experimental::is_detected_v and - not std::experimental::is_detected_v>> : std::true_type + is_detected_v and + is_detected_v and + not is_detected_v>> : std::true_type { }; @@ -166,7 +166,7 @@ namespace detail static value_type set_value(std::string_view argument, std::error_code &ec) { value_type value{}; - auto r = charconv::from_chars(argument.begin(), argument.end(), value); + auto r = charconv::from_chars(argument.data(), argument.data() + argument.length(), value); if (r.ec != std::errc()) ec = std::make_error_code(r.ec); return value; @@ -187,7 +187,7 @@ namespace detail { using value_type = std::filesystem::path; - static value_type set_value(std::string_view argument, std::error_code &ec) + static value_type set_value(std::string_view argument, std::error_code &/*ec*/) { return value_type{ argument }; } @@ -203,7 +203,7 @@ namespace detail { using value_type = std::string; - static value_type set_value(std::string_view argument, std::error_code &ec) + static value_type set_value(std::string_view argument, std::error_code &/*ec*/) { return value_type{ argument }; } @@ -249,7 +249,7 @@ namespace detail virtual ~option_base() = default; - virtual void set_value(std::string_view value, std::error_code &ec) + virtual void set_value(std::string_view /*value*/, std::error_code &/*ec*/) { assert(false); } @@ -264,9 +264,9 @@ namespace detail return {}; } - uint32_t width() const + size_t width() const { - uint32_t result = m_name.length(); + size_t result = m_name.length(); if (result <= 1) result = 2; else if (m_short_name != 0) @@ -280,12 +280,12 @@ namespace detail return result + 6; } - void write(std::ostream &os, uint32_t width) const + void write(std::ostream &os, size_t width) const { if (m_hidden) // quick exit return; - uint32_t w2 = 2; + size_t w2 = 2; os << " "; if (m_short_name) { @@ -499,7 +499,7 @@ class config { result = std::any_cast(value); } - catch (const std::bad_cast &ex) + catch (const std::bad_cast &) { ec = make_error_code(config_error::wrong_type_cast); } @@ -516,12 +516,12 @@ class config friend std::ostream &operator<<(std::ostream &os, const config &conf) { - uint32_t terminal_width = get_terminal_width(); + size_t terminal_width = get_terminal_width(); if (not conf.m_usage.empty()) os << conf.m_usage << std::endl; - uint32_t options_width = conf.m_impl->get_option_width(); + size_t options_width = conf.m_impl->get_option_width(); if (options_width > terminal_width / 2) options_width = terminal_width / 2; @@ -848,8 +848,8 @@ class config virtual option_base *get_option(std::string_view name) = 0; virtual option_base *get_option(char short_name) = 0; - virtual uint32_t get_option_width() const = 0; - virtual void write(std::ostream &os, uint32_t width) const = 0; + virtual size_t get_option_width() const = 0; + virtual void write(std::ostream &os, size_t width) const = 0; std::vector m_operands; }; @@ -898,16 +898,16 @@ class config } } - virtual uint32_t get_option_width() const override + virtual size_t get_option_width() const override { return std::apply([](Options const& ...opts) { - uint32_t width = 0; + size_t width = 0; ((width = std::max(width, opts.width())), ...); return width; }, m_options); } - virtual void write(std::ostream &os, uint32_t width) const override + virtual void write(std::ostream &os, size_t width) const override { std::apply([&os,width](Options const& ...opts) { (opts.write(os, width), ...); diff --git a/include/mcfp/text.hpp b/include/mcfp/text.hpp index e9172d3..3fa62ec 100644 --- a/include/mcfp/text.hpp +++ b/include/mcfp/text.hpp @@ -29,11 +29,76 @@ #include #include #include +#include +#include + +#if __has_include() #include +#else +#include +#endif namespace mcfp { +#if (not defined(__cpp_lib_experimental_detect) or (__cpp_lib_experimental_detect < 201505)) and (not defined(_LIBCPP_VERSION) or _LIBCPP_VERSION < 5000) +// This code is copied from: +// https://ld2015.scusa.lsu.edu/cppreference/en/cpp/experimental/is_detected.html + +template< class... > +using void_t = void; + +namespace detail +{ + template class Op, class... Args> + struct detector + { + using value_t = std::false_type; + using type = Default; + }; + + template class Op, class... Args> + struct detector>, Op, Args...> { + // Note that std::void_t is a c++17 feature + using value_t = std::true_type; + using type = Op; + }; +} // namespace detail + +struct nonesuch +{ + nonesuch() = delete; + ~nonesuch() = delete; + nonesuch(nonesuch const&) = delete; + void operator=(nonesuch const&) = delete; +}; + +template class Op, class... Args> +using is_detected = typename detail::detector::value_t; + +template class Op, class... Args> +constexpr inline bool is_detected_v = is_detected::value; + +template class Op, class... Args> +using detected_t = typename detail::detector::type; + +template class Op, class... Args> +using detected_or = detail::detector; + +template class Op, class... Args> +using is_detected_exact = std::is_same>; + +template class Op, class... Args> +constexpr inline bool is_detected_exact_v = is_detected_exact::value; + +#else + +template class Op, class... Args> +constexpr inline bool is_detected_v = std::experimental::is_detected::value; + +#endif + template struct my_charconv { @@ -199,7 +264,7 @@ template using from_chars_function = decltype(std::from_chars(std::declval(), std::declval(), std::declval())); template -using charconv = typename std::conditional_t, std_charconv, my_charconv>; +using charconv = typename std::conditional_t, std_charconv, my_charconv>; // -------------------------------------------------------------------- /// Simplified line breaking code taken from a decent text editor. diff --git a/test/unit-test.cpp b/test/unit-test.cpp index 534b284..c897d0d 100644 --- a/test/unit-test.cpp +++ b/test/unit-test.cpp @@ -365,7 +365,7 @@ BOOST_AUTO_TEST_CASE(t_12) ec = {}; config.parse(argc, argv, ec); - BOOST_CHECK(ec == std::errc()); + BOOST_CHECK(not ec); } // -------------------------------------------------------------------- @@ -407,7 +407,7 @@ verbose config.parse_config_file(is, ec); - BOOST_CHECK(ec == std::errc()); + BOOST_CHECK(not ec); BOOST_CHECK(config.has("aap")); BOOST_CHECK_EQUAL(config.get("aap"), "1"); @@ -487,7 +487,7 @@ BOOST_AUTO_TEST_CASE(file_3) config.parse_config_file("config", "bla-bla.conf", { gTestDir.string() }, ec); - BOOST_CHECK(ec == std::errc()); + BOOST_CHECK(not ec); BOOST_CHECK(config.has("aap")); BOOST_CHECK_EQUAL(config.get("aap"), "aap"); @@ -517,7 +517,7 @@ BOOST_AUTO_TEST_CASE(file_4) config.parse_config_file("config", "unit-test.conf", { gTestDir.string() }, ec); - BOOST_CHECK(ec == std::errc()); + BOOST_CHECK(not ec); BOOST_CHECK(config.has("aap")); BOOST_CHECK_EQUAL(config.get("aap"), "aap");