Skip to content

Commit

Permalink
Merge branch 'jarro2783:master' into patch-1
Browse files Browse the repository at this point in the history
  • Loading branch information
amirsojoodi authored Dec 22, 2024
2 parents dfeeffc + 10a7a64 commit 565edd1
Show file tree
Hide file tree
Showing 8 changed files with 15,742 additions and 8,093 deletions.
10 changes: 9 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,20 @@
This is the changelog for `cxxopts`, a C++11 library for parsing command line
options. The project adheres to semantic versioning.

## Unreleased
## 3.2.1

### Bug fixes

* Fix compilation with optional on C++20.

## 3.2

### Bug fixes

* Fix unannotated fallthrough.
* Fix sign conversion with Unicode output.
* Don't initialize regex in static initialiser.
* Fix incorrect integer overflow checks.

### Added

Expand All @@ -19,6 +26,7 @@ options. The project adheres to semantic versioning.

* Change quote output to '' to match Windows.
* Don't split positional arguments by the list delimiter.
* Order help groups by the order they were added.

## 3.1.1

Expand Down
5 changes: 3 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ cmake_minimum_required(VERSION 3.1...3.19)

list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/")
include(cxxopts)
set("PROJECT_DESCRIPTION" "A header-only lightweight C++ command line option parser")
set("PROJECT_HOMEPAGE_URL" "https://github.com/jarro2783/cxxopts")

# Get the version of the library
cxxopts_getversion(VERSION)
Expand All @@ -32,6 +30,9 @@ project(cxxopts
LANGUAGES CXX
)

set("PROJECT_DESCRIPTION" "A header-only lightweight C++ command line option parser")
set("PROJECT_HOMEPAGE_URL" "https://github.com/jarro2783/cxxopts")

# Must include after the project call due to GNUInstallDirs requiring a language be enabled (IE. CXX)
include(GNUInstallDirs)

Expand Down
22 changes: 14 additions & 8 deletions cmake/cxxopts.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,17 @@ endfunction()

# Helper function to ecapsulate install logic
function(cxxopts_install_logic)
if(CMAKE_LIBRARY_ARCHITECTURE)
string(REPLACE "/${CMAKE_LIBRARY_ARCHITECTURE}" "" CMAKE_INSTALL_LIBDIR_ARCHIND "${CMAKE_INSTALL_LIBDIR}")
if(NOT CXXOPTS_USE_UNICODE_HELP)
if(CMAKE_LIBRARY_ARCHITECTURE)
string(REPLACE "/${CMAKE_LIBRARY_ARCHITECTURE}" "" CMAKE_INSTALL_LIBDIR_ARCHIND "${CMAKE_INSTALL_LIBDIR}")
else()
# On some systems (e.g. NixOS), `CMAKE_LIBRARY_ARCHITECTURE` can be empty
set(CMAKE_INSTALL_LIBDIR_ARCHIND "${CMAKE_INSTALL_DATAROOTDIR}")
endif()
if(${CMAKE_VERSION} VERSION_GREATER "3.14")
set(OPTIONAL_ARCH_INDEPENDENT "ARCH_INDEPENDENT")
endif()
else()
# On some systems (e.g. NixOS), `CMAKE_LIBRARY_ARCHITECTURE` can be empty
set(CMAKE_INSTALL_LIBDIR_ARCHIND "${CMAKE_INSTALL_LIBDIR}")
endif()
set(CXXOPTS_CMAKE_DIR "${CMAKE_INSTALL_LIBDIR_ARCHIND}/cmake/cxxopts" CACHE STRING "Installation directory for cmake files, relative to ${CMAKE_INSTALL_PREFIX}.")
Expand All @@ -99,11 +106,6 @@ function(cxxopts_install_logic)
set(targets_export_name cxxopts-targets)
set(PackagingTemplatesDir "${PROJECT_SOURCE_DIR}/packaging")


if(${CMAKE_VERSION} VERSION_GREATER "3.14")
set(OPTIONAL_ARCH_INDEPENDENT "ARCH_INDEPENDENT")
endif()

# Generate the version, config and target files into the build directory.
write_basic_package_version_file(
${version_config}
Expand Down Expand Up @@ -154,6 +156,10 @@ function(cxxopts_install_logic)
set(CPACK_DEBIAN_COMPRESSION_TYPE "xz")

set(PKG_CONFIG_FILE_NAME "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc")
if(CXXOPTS_USE_UNICODE_HELP)
set(PKG_CONFIG_REQUIRES "icu-cu")
set(PKG_CONFIG_EXTRA_CFLAGS "-DCXXOPTS_USE_UNICODE")
endif()
configure_file("${PackagingTemplatesDir}/pkgconfig.pc.in" "${PKG_CONFIG_FILE_NAME}" @ONLY)
install(FILES "${PKG_CONFIG_FILE_NAME}"
DESTINATION "${CMAKE_INSTALL_LIBDIR_ARCHIND}/pkgconfig"
Expand Down
138 changes: 86 additions & 52 deletions include/cxxopts.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ THE SOFTWARE.
#ifndef CXXOPTS_HPP_INCLUDED
#define CXXOPTS_HPP_INCLUDED

#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <exception>
#include <limits>
Expand Down Expand Up @@ -92,7 +94,7 @@ THE SOFTWARE.
#endif

#define CXXOPTS__VERSION_MAJOR 3
#define CXXOPTS__VERSION_MINOR 1
#define CXXOPTS__VERSION_MINOR 2
#define CXXOPTS__VERSION_PATCH 1

#if (__GNUC__ < 10 || (__GNUC__ == 10 && __GNUC_MINOR__ < 1)) && __GNUC__ >= 6
Expand Down Expand Up @@ -972,13 +974,26 @@ integer_parser(const std::string& text, T& value)
throw_or_mimic<exceptions::incorrect_argument_type>(text);
}

const US next = static_cast<US>(result * base + digit);
if (result > next)
US limit = 0;
if (negative)
{
limit = static_cast<US>(std::abs(static_cast<intmax_t>((std::numeric_limits<T>::min)())));
}
else
{
limit = (std::numeric_limits<T>::max)();
}

if (base != 0 && result > limit / base)
{
throw_or_mimic<exceptions::incorrect_argument_type>(text);
}
if (result * base > limit - digit)
{
throw_or_mimic<exceptions::incorrect_argument_type>(text);
}

result = next;
result = static_cast<US>(result * base + digit);
}

detail::check_signed_range<T>(negative, result, text);
Expand Down Expand Up @@ -1048,6 +1063,28 @@ parse_value(const std::string& text, T& value) {
stringstream_parser(text, value);
}

#ifdef CXXOPTS_HAS_OPTIONAL
template <typename T>
void
parse_value(const std::string& text, std::optional<T>& value)
{
T result;
parse_value(text, result);
value = std::move(result);
}
#endif

inline
void parse_value(const std::string& text, char& c)
{
if (text.length() != 1)
{
throw_or_mimic<exceptions::incorrect_argument_type>(text);
}

c = text[0];
}

template <typename T>
void
parse_value(const std::string& text, std::vector<T>& value)
Expand Down Expand Up @@ -1083,28 +1120,6 @@ add_value(const std::string& text, std::vector<T>& value)
value.emplace_back(std::move(v));
}

#ifdef CXXOPTS_HAS_OPTIONAL
template <typename T>
void
parse_value(const std::string& text, std::optional<T>& value)
{
T result;
parse_value(text, result);
value = std::move(result);
}
#endif

inline
void parse_value(const std::string& text, char& c)
{
if (text.length() != 1)
{
throw_or_mimic<exceptions::incorrect_argument_type>(text);
}

c = text[0];
}

template <typename T>
struct type_is_container
{
Expand Down Expand Up @@ -1524,6 +1539,18 @@ CXXOPTS_DIAGNOSTIC_POP
return CXXOPTS_RTTI_CAST<const values::standard_value<T>&>(*m_value).get();
}

#ifdef CXXOPTS_HAS_OPTIONAL
template <typename T>
std::optional<T>
as_optional() const
{
if (m_value == nullptr) {
return std::nullopt;
}
return as<T>();
}
#endif

private:
void
ensure_value(const std::shared_ptr<const OptionDetails>& details)
Expand Down Expand Up @@ -1716,6 +1743,12 @@ CXXOPTS_DIAGNOSTIC_POP
return viter->second.count();
}

bool
contains(const std::string& o) const
{
return static_cast<bool>(count(o));
}

const OptionValue&
operator[](const std::string& option) const
{
Expand All @@ -1736,6 +1769,24 @@ CXXOPTS_DIAGNOSTIC_POP
return viter->second;
}

#ifdef CXXOPTS_HAS_OPTIONAL
template <typename T>
std::optional<T>
as_optional(const std::string& option) const
{
auto iter = m_keys.find(option);
if (iter != m_keys.end())
{
auto viter = m_values.find(iter->second);
if (viter != m_values.end())
{
return viter->second.as_optional<T>();
}
}
return std::nullopt;
}
#endif

const std::vector<KeyValue>&
arguments() const
{
Expand Down Expand Up @@ -2033,6 +2084,7 @@ class Options
std::unordered_set<std::string> m_positional_set{};

//mapping from groups to help options
std::vector<std::string> m_group{};
std::map<std::string, HelpGroupDetails> m_help{};
};

Expand Down Expand Up @@ -2683,6 +2735,12 @@ Options::add_option
}

//add the help details

if (m_help.find(group) == m_help.end())
{
m_group.push_back(group);
}

auto& options = m_help[group];

options.options.emplace_back(HelpOptionDetails{s, l, stringDesc,
Expand Down Expand Up @@ -2814,19 +2872,7 @@ inline
void
Options::generate_all_groups_help(String& result) const
{
std::vector<std::string> all_groups;

std::transform(
m_help.begin(),
m_help.end(),
std::back_inserter(all_groups),
[] (const std::map<std::string, HelpGroupDetails>::value_type& group)
{
return group.first;
}
);

generate_group_help(result, all_groups);
generate_group_help(result, m_group);
}

inline
Expand Down Expand Up @@ -2866,19 +2912,7 @@ inline
std::vector<std::string>
Options::groups() const
{
std::vector<std::string> g;

std::transform(
m_help.begin(),
m_help.end(),
std::back_inserter(g),
[] (const std::map<std::string, HelpGroupDetails>::value_type& pair)
{
return pair.first;
}
);

return g;
return m_group;
}

inline
Expand Down
4 changes: 3 additions & 1 deletion packaging/pkgconfig.pc.in
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,7 @@ includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@

Name: @PROJECT_NAME@
Description: @PROJECT_DESCRIPTION@
URL: @PROJECT_HOMEPAGE_URL@
Version: @PROJECT_VERSION@
Cflags: -I${includedir}
Requires: @PKG_CONFIG_REQUIRES@
Cflags: -I${includedir} @PKG_CONFIG_EXTRA_CFLAGS@
4 changes: 3 additions & 1 deletion src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,6 @@
add_executable(example example.cpp)
target_link_libraries(example cxxopts)

set_property(TARGET example PROPERTY CXX_STANDARD 17)
target_compile_features(example PRIVATE cxx_std_17)
target_compile_options(example PRIVATE
"$<$<CXX_COMPILER_ID:MSVC>:/utf-8;>")
Loading

0 comments on commit 565edd1

Please sign in to comment.