* Avoid undefined std::abs(INT_MIN) in integer_parser
When parsing a negative integer into a signed type whose minimum value
equals INTMAX_MIN (e.g. int64_t on typical platforms), integer_parser
computes the limit as std::abs(static_cast<intmax_t>(min())). Negating
INTMAX_MIN cannot be represented in intmax_t, so the std::abs call is
undefined behaviour. UBSan flags this on every negative int64_t parse,
including a trivial one like "-1":
runtime error: negation of -9223372036854775808 cannot be represented
in type 'long'; cast to an unsigned type to negate this value to itself
Build the same unsigned magnitude (|min| == max + 1 for two's-complement)
directly in the unsigned arithmetic type instead. For unsigned T the
expression wraps to 0, which matches the previous std::abs(0) value, so
behaviour for unsigned types is preserved.
* test: cover INT64_MIN parse and run parser tests under UBSan
* test: skip UBSan flags on Windows clang-cl/MinGW builds
* fix: Overwrite m_positional_set in parse_positional()
* feat: Allow append in positionals and fix discrepancy between m_positional and m_positional_set during replace
* feat: Add test for short options parsing
* fix: Update option parsing to allow = with short options
* fix: Fix custom option parsing in case of CXXOPTS_NO_REGEX
Fixes#290.
Checking for overflow should be done before integer overflows.
There are two checks:
(result > limit / base) is used for limits greater than rounded up to base,
e.g. for 65535 it will activate for 65540 and higher.
(result * base > limit - digit) is used for limit+1 to limit+n below
next base rounded number, e.g. 65536 up to 65539.
* Fixes#240: Multiple long option names / aliases
* We now use a vector of long option names instead of a single name
* When specifying an option, you can provide multiple names separated by commas, at most one of which may have a length of 1 (not necessarily the first specified name). The length-1 name is the single-hyphen switch (the "short name").
* Hashing uses the first long name
* Option help currently only uses the first long name.
* Fixes#345, fixes#346, regards #340: Put exceptions in a sub-namespace and renamed them accordingly.
* Also fixed some "loose ends" regarding namespace indentation which were missing in PR #350.
* Dropped `required_option_missing` as it is unused.
Major refactor of the parsing code organisation to improve encapsulation
and not modify the input arguments. The returned result no longer has
pointers into the original option specification.
* Fixes#245:
* Added a new exception type: `option_has_no_value_exception`; throwing it when an option has no value we can cast with `as()`, instead of an `std::domain_error`.
* The `OptionValue` type now holds a pointer to the long option name (in its corresponding key within ParseResults's `m_results` field.