Merge branch 'master' into add-option-chars

This commit is contained in:
jarro2783 2022-09-29 06:56:20 +10:00 committed by GitHub
commit e3e4b7fbd8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 91 additions and 64 deletions

View File

@ -2,43 +2,70 @@ name: CMake
on: on:
push: push:
branches: [ master ] branches: [ master, main ]
pull_request: pull_request:
branches: [ master ] branches: [ master, main ]
workflow_dispatch: workflow_dispatch:
env: env:
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.) # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
BUILD_TYPE: Release BUILD_TYPE: Release
jobs:
build:
# The CMake configure and build commands are platform agnostic and should work equally
# well on Windows or Mac. You can convert this to a matrix build if you need
# cross-platform coverage.
# See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix
runs-on: ${{matrix.os}}
defaults:
run:
shell: bash
jobs:
build-ubuntu:
strategy: strategy:
matrix: matrix:
os: [ubuntu-18.04] os: [ ubuntu-18.04, ubuntu-20.04, ubuntu-22.04 ]
compiler: [g++-7, g++-9, g++-10, clang++] compiler: [ g++-9, g++-10, clang++ ]
include:
- os: ubuntu-18.04
compiler: g++-7
name: Build and Test on Ubuntu
runs-on: ${{matrix.os}}
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- name: Configure CMake
run: cmake -S "${{github.workspace}}" -B "${{github.workspace}}/build" -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_CXX_COMPILER=${{matrix.compiler}}
- name: Build
run: cmake --build "${{github.workspace}}/build" --config $BUILD_TYPE
- name: Test
working-directory: ${{github.workspace}}/build/test
run: ctest -C $BUILD_TYPE --output-on-failure
- name: Configure CMake build-macos:
# Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make. name: Build and Test on MacOS
# See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type strategy:
run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_CXX_COMPILER=${{matrix.compiler}} matrix:
os: [ macos-11, macos-12 ]
runs-on: ${{matrix.os}}
steps:
- uses: actions/checkout@v3
- name: Configure CMake
run: cmake -S "${{github.workspace}}" -B "${{github.workspace}}/build" -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
- name: Show compile commands
run: cat build/compile_commands.json
- name: Build
run: cmake --build "${{github.workspace}}/build" --config $BUILD_TYPE
- name: Test
working-directory: ${{github.workspace}}/build/test
shell: bash
run: ctest -C $BUILD_TYPE --output-on-failure
- name: Build build-windows:
# Build your program with the given configuration name: Build and Test on Windows
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} runs-on: windows-latest
steps:
- name: Test - uses: actions/checkout@v3
working-directory: ${{github.workspace}}/build - uses: ilammy/msvc-dev-cmd@v1
# Execute tests defined by the CMake configuration. - name: Configure CMake
# See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail run: cmake -S "${{github.workspace}}" -B "${{github.workspace}}/build" -DCMAKE_BUILD_TYPE=$BUILD_TYPE -T "ClangCl"
run: ctest -C ${{env.BUILD_TYPE}} - name: Build
run: cmake --build "${{github.workspace}}/build" --config $BUILD_TYPE
- name: Test
working-directory: ${{github.workspace}}/build/test
run: cd $BUILD_TYPE && ./link_test && ./options_test

View File

@ -139,10 +139,13 @@ options.add_options()
("server", "The server to execute on", cxxopts::value<std::string>()) ("server", "The server to execute on", cxxopts::value<std::string>())
("filenames", "The filename(s) to process", cxxopts::value<std::vector<std::string>>()); ("filenames", "The filename(s) to process", cxxopts::value<std::vector<std::string>>());
options.parse_positional({"script", "server", "filenames"}) options.parse_positional({"script", "server", "filenames"});
// Parse options the usual way
options.parse(argc, argv);
``` ```
Then parsing a set of arguments like: For example, parsing the following arguments:
~~~ ~~~
my_script.py my_server.com file1.txt file2.txt file3.txt my_script.py my_server.com file1.txt file2.txt file3.txt
~~~ ~~~

View File

@ -1,6 +1,6 @@
/* /*
Copyright (c) 2014, 2015, 2016, 2017 Jarryd Beck Copyright (c) 2014-2022 Jarryd Beck
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
@ -27,12 +27,10 @@ THE SOFTWARE.
#ifndef CXXOPTS_HPP_INCLUDED #ifndef CXXOPTS_HPP_INCLUDED
#define CXXOPTS_HPP_INCLUDED #define CXXOPTS_HPP_INCLUDED
#include <cassert>
#include <cctype>
#include <cstring> #include <cstring>
#include <exception> #include <exception>
#include <limits> #include <limits>
#include <list> #include <initializer_list>
#include <map> #include <map>
#include <memory> #include <memory>
#include <sstream> #include <sstream>
@ -195,9 +193,9 @@ stringAppend(String&s, String a)
inline inline
String& String&
stringAppend(String& s, size_t n, UChar32 c) stringAppend(String& s, std::size_t n, UChar32 c)
{ {
for (size_t i = 0; i != n; ++i) for (std::size_t i = 0; i != n; ++i)
{ {
s.append(c); s.append(c);
} }
@ -219,7 +217,7 @@ stringAppend(String& s, Iterator begin, Iterator end)
} }
inline inline
size_t std::size_t
stringLength(const String& s) stringLength(const String& s)
{ {
return s.length(); return s.length();
@ -277,7 +275,7 @@ toLocalString(T&& t)
} }
inline inline
size_t std::size_t
stringLength(const String& s) stringLength(const String& s)
{ {
return s.length(); return s.length();
@ -292,7 +290,7 @@ stringAppend(String&s, const String& a)
inline inline
String& String&
stringAppend(String& s, size_t n, char c) stringAppend(String& s, std::size_t n, char c)
{ {
return s.append(n, c); return s.append(n, c);
} }
@ -681,7 +679,8 @@ inline OptionNames split_option_names(const std::string &text)
"abcdefghijklmnopqrstuvwxyz" "abcdefghijklmnopqrstuvwxyz"
"0123456789" "0123456789"
"_-.?"; "_-.?";
if (!std::isalnum(text[token_start_pos]) ||
if (!std::isalnum(text[token_start_pos], std::locale::classic()) ||
text.find_first_not_of(option_name_valid_chars, token_start_pos) < next_delimiter_pos) { text.find_first_not_of(option_name_valid_chars, token_start_pos) < next_delimiter_pos) {
throw_or_mimic<exceptions::invalid_option_format>(text); throw_or_mimic<exceptions::invalid_option_format>(text);
} }
@ -700,11 +699,11 @@ inline ArguDesc ParseArgument(const char *arg, bool &matched)
if (strncmp(pdata, "--", 2) == 0) if (strncmp(pdata, "--", 2) == 0)
{ {
pdata += 2; pdata += 2;
if (isalnum(*pdata)) if (isalnum(*pdata, std::locale::classic()))
{ {
argu_desc.arg_name.push_back(*pdata); argu_desc.arg_name.push_back(*pdata);
pdata += 1; pdata += 1;
while (isalnum(*pdata) || *pdata == '-' || *pdata == '_') while (isalnum(*pdata, std::locale::classic()) || *pdata == '-' || *pdata == '_')
{ {
argu_desc.arg_name.push_back(*pdata); argu_desc.arg_name.push_back(*pdata);
pdata += 1; pdata += 1;
@ -732,7 +731,7 @@ inline ArguDesc ParseArgument(const char *arg, bool &matched)
{ {
pdata += 1; pdata += 1;
argu_desc.grouping = true; argu_desc.grouping = true;
while (isalnum(*pdata)) while (isalnum(*pdata, std::locale::classic()))
{ {
argu_desc.arg_name.push_back(*pdata); argu_desc.arg_name.push_back(*pdata);
pdata += 1; pdata += 1;
@ -1355,7 +1354,7 @@ class OptionDetails
return m_long; return m_long;
} }
size_t std::size_t
hash() const hash() const
{ {
return m_hash; return m_hash;
@ -1368,7 +1367,7 @@ class OptionDetails
std::shared_ptr<const Value> m_value{}; std::shared_ptr<const Value> m_value{};
int m_count; int m_count;
size_t m_hash{}; std::size_t m_hash{};
}; };
struct HelpOptionDetails struct HelpOptionDetails
@ -1429,7 +1428,7 @@ CXXOPTS_IGNORE_WARNING("-Wnull-dereference")
#endif #endif
CXXOPTS_NODISCARD CXXOPTS_NODISCARD
size_t std::size_t
count() const noexcept count() const noexcept
{ {
return m_count; return m_count;
@ -1474,7 +1473,7 @@ CXXOPTS_DIAGNOSTIC_POP
// Holding this pointer is safe, since OptionValue's only exist in key-value pairs, // Holding this pointer is safe, since OptionValue's only exist in key-value pairs,
// where the key has the string we point to. // where the key has the string we point to.
std::shared_ptr<Value> m_value{}; std::shared_ptr<Value> m_value{};
size_t m_count = 0; std::size_t m_count = 0;
bool m_default = false; bool m_default = false;
}; };
@ -1515,8 +1514,8 @@ class KeyValue
std::string m_value; std::string m_value;
}; };
using ParsedHashMap = std::unordered_map<size_t, OptionValue>; using ParsedHashMap = std::unordered_map<std::size_t, OptionValue>;
using NameHashMap = std::unordered_map<std::string, size_t>; using NameHashMap = std::unordered_map<std::string, std::size_t>;
class ParseResult class ParseResult
{ {
@ -1610,7 +1609,7 @@ class ParseResult
return Iterator(this, true); return Iterator(this, true);
} }
size_t std::size_t
count(const std::string& o) const count(const std::string& o) const
{ {
auto iter = m_keys.find(o); auto iter = m_keys.find(o);
@ -1820,7 +1819,7 @@ class Options
} }
Options& Options&
set_width(size_t width) set_width(std::size_t width)
{ {
m_width = width; m_width = width;
return *this; return *this;
@ -1938,7 +1937,7 @@ class Options
std::string m_positional_help{}; std::string m_positional_help{};
bool m_show_positional; bool m_show_positional;
bool m_allow_unrecognised; bool m_allow_unrecognised;
size_t m_width; std::size_t m_width;
bool m_tab_expansion; bool m_tab_expansion;
std::shared_ptr<OptionMap> m_options; std::shared_ptr<OptionMap> m_options;
@ -1974,8 +1973,8 @@ class OptionAdder
}; };
namespace { namespace {
constexpr size_t OPTION_LONGEST = 30; constexpr std::size_t OPTION_LONGEST = 30;
constexpr size_t OPTION_DESC_GAP = 2; constexpr std::size_t OPTION_DESC_GAP = 2;
String String
format_option format_option
@ -2027,8 +2026,8 @@ String
format_description format_description
( (
const HelpOptionDetails& o, const HelpOptionDetails& o,
size_t start, std::size_t start,
size_t allowed, std::size_t allowed,
bool tab_expansion bool tab_expansion
) )
{ {
@ -2051,7 +2050,7 @@ format_description
if (tab_expansion) if (tab_expansion)
{ {
String desc2; String desc2;
auto size = size_t{ 0 }; auto size = std::size_t{ 0 };
for (auto c = std::begin(desc); c != std::end(desc); ++c) for (auto c = std::begin(desc); c != std::end(desc); ++c)
{ {
if (*c == '\n') if (*c == '\n')
@ -2081,7 +2080,7 @@ format_description
auto startLine = current; auto startLine = current;
auto lastSpace = current; auto lastSpace = current;
auto size = size_t{}; auto size = std::size_t{};
bool appendNewLine; bool appendNewLine;
bool onlyWhiteSpace = true; bool onlyWhiteSpace = true;
@ -2089,13 +2088,11 @@ format_description
while (current != std::end(desc)) while (current != std::end(desc))
{ {
appendNewLine = false; appendNewLine = false;
if (*previous == ' ' || *previous == '\t')
if (std::isblank(*previous))
{ {
lastSpace = current; lastSpace = current;
} }
if (*current != ' ' && *current != '\t')
if (!std::isblank(*current))
{ {
onlyWhiteSpace = false; onlyWhiteSpace = false;
} }
@ -2621,7 +2618,7 @@ Options::help_one_group(const std::string& g) const
OptionHelp format; OptionHelp format;
size_t longest = 0; std::size_t longest = 0;
String result; String result;
@ -2646,7 +2643,7 @@ Options::help_one_group(const std::string& g) const
longest = (std::min)(longest, OPTION_LONGEST); longest = (std::min)(longest, OPTION_LONGEST);
//widest allowed description -- min 10 chars for helptext/line //widest allowed description -- min 10 chars for helptext/line
size_t allowed = 10; std::size_t allowed = 10;
if (m_width > allowed + longest + OPTION_DESC_GAP) if (m_width > allowed + longest + OPTION_DESC_GAP)
{ {
allowed = m_width - longest - OPTION_DESC_GAP; allowed = m_width - longest - OPTION_DESC_GAP;
@ -2693,7 +2690,7 @@ Options::generate_group_help
const std::vector<std::string>& print_groups const std::vector<std::string>& print_groups
) const ) const
{ {
for (size_t i = 0; i != print_groups.size(); ++i) for (std::size_t i = 0; i != print_groups.size(); ++i)
{ {
const String& group_help_text = help_one_group(print_groups[i]); const String& group_help_text = help_one_group(print_groups[i]);
if (empty(group_help_text)) if (empty(group_help_text))