CLI11 2.7.2
C++11 Command Line Interface Parser
Loading...
Searching...
No Matches
TypeTools_inl.hpp
1// Copyright (c) 2017-2026, University of Cincinnati, developed by Henry Schreiner
2// under NSF AWARD 1414736 and by the respective contributors.
3// All rights reserved.
4//
5// SPDX-License-Identifier: BSD-3-Clause
6
7#pragma once
8
9// IWYU pragma: private, include "CLI/CLI.hpp"
10
11// This include is only needed for IDEs to discover symbols
12#include "../TypeTools.hpp"
13
14#include "../StringTools.hpp"
15
16// [CLI11:public_includes:set]
17#include <cerrno>
18#include <cstdint>
19#include <cstdlib>
20#include <limits>
21#include <sstream>
22#include <string>
23#include <utility>
24#include <vector>
25// [CLI11:public_includes:end]
26
27namespace CLI {
28// [CLI11:type_tools_inl_hpp:verbatim]
29
30namespace detail {
31
32CLI11_INLINE std::int64_t to_flag_value(std::string val) noexcept {
33 static const std::string trueString("true");
34 static const std::string falseString("false");
35 if(val == trueString) {
36 return 1;
37 }
38 if(val == falseString) {
39 return -1;
40 }
41 val = detail::to_lower(std::move(val));
42 std::int64_t ret = 0;
43 if(val.size() == 1) {
44 if(val[0] >= '1' && val[0] <= '9') {
45 return (static_cast<std::int64_t>(val[0]) - '0');
46 }
47 switch(val[0]) {
48 case '0':
49 case 'f':
50 case 'n':
51 case '-':
52 ret = -1;
53 break;
54 case 't':
55 case 'y':
56 case '+':
57 ret = 1;
58 break;
59 default:
60 errno = EINVAL;
61 return -1;
62 }
63 return ret;
64 }
65 if(val == trueString || val == "on" || val == "yes" || val == "enable") {
66 ret = 1;
67 } else if(val == falseString || val == "off" || val == "no" || val == "disable") {
68 ret = -1;
69 } else {
70 char *loc_ptr{nullptr};
71 ret = std::strtoll(val.c_str(), &loc_ptr, 0);
72 if(loc_ptr != (val.c_str() + val.size()) && errno == 0) {
73 errno = EINVAL;
74 }
75 }
76 return ret;
77}
78
79CLI11_INLINE std::string sum_string_vector(const std::vector<std::string> &values) {
80 // First try a pure integer sum so that large integral totals (>= 1e16, or beyond the 2^53 mantissa of
81 // double) are preserved exactly and rendered as a plain integer rather than scientific notation
82 std::int64_t ival{0};
83 bool int_sum{true};
84 for(const auto &arg : values) {
85 std::int64_t tv{0};
86 if(!integral_conversion(arg, tv)) {
87 int_sum = false;
88 break;
89 }
90 // detect signed overflow before performing the addition since signed overflow is undefined behavior
91 if((tv > 0 && ival > (std::numeric_limits<std::int64_t>::max)() - tv) ||
92 (tv < 0 && ival < (std::numeric_limits<std::int64_t>::min)() - tv)) {
93 int_sum = false;
94 break;
95 }
96 ival += tv;
97 }
98 if(int_sum) {
99 return std::to_string(ival);
100 }
101
102 double val{0.0};
103 bool fail{false};
104 std::string output;
105 for(const auto &arg : values) {
106 double tv{0.0};
107 auto comp = lexical_cast(arg, tv);
108 if(!comp) {
109 errno = 0;
110 auto fv = detail::to_flag_value(arg);
111 fail = (errno != 0);
112 if(fail) {
113 break;
114 }
115 tv = static_cast<double>(fv);
116 }
117 val += tv;
118 }
119 if(fail) {
120 for(const auto &arg : values) {
121 output.append(arg);
122 }
123 } else {
124 std::ostringstream out;
125 out.precision(16);
126 out << val;
127 output = out.str();
128 }
129 return output;
130}
131
132} // namespace detail
133// [CLI11:type_tools_inl_hpp:end]
134} // namespace CLI