Commit 4048596250fa8eddbc96b8c49de5a4a8664c67f1

Authored by Daniel Herrera Castro
Committed by Henry Schreiner
1 parent d1f0f483

[precompile] Split StringTools.hpp

CLI11.hpp.in
@@ -46,6 +46,8 @@ namespace {namespace} {{ @@ -46,6 +46,8 @@ namespace {namespace} {{
46 46
47 {string_tools_hpp} 47 {string_tools_hpp}
48 48
  49 +{string_tools_inl_hpp}
  50 +
49 {error_hpp} 51 {error_hpp}
50 52
51 {type_tools_hpp} 53 {type_tools_hpp}
include/CLI/StringTools.hpp
@@ -17,6 +17,8 @@ @@ -17,6 +17,8 @@
17 #include <vector> 17 #include <vector>
18 // [CLI11:public_includes:end] 18 // [CLI11:public_includes:end]
19 19
  20 +#include "Macros.hpp"
  21 +
20 namespace CLI { 22 namespace CLI {
21 23
22 // [CLI11:string_tools_hpp:verbatim] 24 // [CLI11:string_tools_hpp:verbatim]
@@ -43,21 +45,7 @@ namespace detail { @@ -43,21 +45,7 @@ namespace detail {
43 constexpr int expected_max_vector_size{1 << 29}; 45 constexpr int expected_max_vector_size{1 << 29};
44 // Based on http://stackoverflow.com/questions/236129/split-a-string-in-c 46 // Based on http://stackoverflow.com/questions/236129/split-a-string-in-c
45 /// Split a string by a delim 47 /// Split a string by a delim
46 -inline std::vector<std::string> split(const std::string &s, char delim) {  
47 - std::vector<std::string> elems;  
48 - // Check to see if empty string, give consistent result  
49 - if(s.empty()) {  
50 - elems.emplace_back();  
51 - } else {  
52 - std::stringstream ss;  
53 - ss.str(s);  
54 - std::string item;  
55 - while(std::getline(ss, item, delim)) {  
56 - elems.push_back(item);  
57 - }  
58 - }  
59 - return elems;  
60 -} 48 +CLI11_INLINE std::vector<std::string> split(const std::string &s, char delim);
61 49
62 /// Simple function to join a string 50 /// Simple function to join a string
63 template <typename T> std::string join(const T &v, std::string delim = ",") { 51 template <typename T> std::string join(const T &v, std::string delim = ",") {
@@ -106,33 +94,16 @@ template &lt;typename T&gt; std::string rjoin(const T &amp;v, std::string delim = &quot;,&quot;) { @@ -106,33 +94,16 @@ template &lt;typename T&gt; std::string rjoin(const T &amp;v, std::string delim = &quot;,&quot;) {
106 // Based roughly on http://stackoverflow.com/questions/25829143/c-trim-whitespace-from-a-string 94 // Based roughly on http://stackoverflow.com/questions/25829143/c-trim-whitespace-from-a-string
107 95
108 /// Trim whitespace from left of string 96 /// Trim whitespace from left of string
109 -inline std::string &ltrim(std::string &str) {  
110 - auto it = std::find_if(str.begin(), str.end(), [](char ch) { return !std::isspace<char>(ch, std::locale()); });  
111 - str.erase(str.begin(), it);  
112 - return str;  
113 -} 97 +CLI11_INLINE std::string &ltrim(std::string &str);
114 98
115 /// Trim anything from left of string 99 /// Trim anything from left of string
116 -inline std::string &ltrim(std::string &str, const std::string &filter) {  
117 - auto it = std::find_if(str.begin(), str.end(), [&filter](char ch) { return filter.find(ch) == std::string::npos; });  
118 - str.erase(str.begin(), it);  
119 - return str;  
120 -} 100 +CLI11_INLINE std::string &ltrim(std::string &str, const std::string &filter);
121 101
122 /// Trim whitespace from right of string 102 /// Trim whitespace from right of string
123 -inline std::string &rtrim(std::string &str) {  
124 - auto it = std::find_if(str.rbegin(), str.rend(), [](char ch) { return !std::isspace<char>(ch, std::locale()); });  
125 - str.erase(it.base(), str.end());  
126 - return str;  
127 -} 103 +CLI11_INLINE std::string &rtrim(std::string &str);
128 104
129 /// Trim anything from right of string 105 /// Trim anything from right of string
130 -inline std::string &rtrim(std::string &str, const std::string &filter) {  
131 - auto it =  
132 - std::find_if(str.rbegin(), str.rend(), [&filter](char ch) { return filter.find(ch) == std::string::npos; });  
133 - str.erase(it.base(), str.end());  
134 - return str;  
135 -} 106 +CLI11_INLINE std::string &rtrim(std::string &str, const std::string &filter);
136 107
137 /// Trim whitespace from string 108 /// Trim whitespace from string
138 inline std::string &trim(std::string &str) { return ltrim(rtrim(str)); } 109 inline std::string &trim(std::string &str) { return ltrim(rtrim(str)); }
@@ -147,31 +118,13 @@ inline std::string trim_copy(const std::string &amp;str) { @@ -147,31 +118,13 @@ inline std::string trim_copy(const std::string &amp;str) {
147 } 118 }
148 119
149 /// remove quotes at the front and back of a string either '"' or '\'' 120 /// remove quotes at the front and back of a string either '"' or '\''
150 -inline std::string &remove_quotes(std::string &str) {  
151 - if(str.length() > 1 && (str.front() == '"' || str.front() == '\'')) {  
152 - if(str.front() == str.back()) {  
153 - str.pop_back();  
154 - str.erase(str.begin(), str.begin() + 1);  
155 - }  
156 - }  
157 - return str;  
158 -} 121 +CLI11_INLINE std::string &remove_quotes(std::string &str);
159 122
160 /// Add a leader to the beginning of all new lines (nothing is added 123 /// Add a leader to the beginning of all new lines (nothing is added
161 /// at the start of the first line). `"; "` would be for ini files 124 /// at the start of the first line). `"; "` would be for ini files
162 /// 125 ///
163 /// Can't use Regex, or this would be a subs. 126 /// Can't use Regex, or this would be a subs.
164 -inline std::string fix_newlines(const std::string &leader, std::string input) {  
165 - std::string::size_type n = 0;  
166 - while(n != std::string::npos && n < input.size()) {  
167 - n = input.find('\n', n);  
168 - if(n != std::string::npos) {  
169 - input = input.substr(0, n + 1) + leader + input.substr(n + 1);  
170 - n += leader.size();  
171 - }  
172 - }  
173 - return input;  
174 -} 127 +CLI11_INLINE std::string fix_newlines(const std::string &leader, std::string input);
175 128
176 /// Make a copy of the string and then trim it, any filter string can be used (any char in string is filtered) 129 /// Make a copy of the string and then trim it, any filter string can be used (any char in string is filtered)
177 inline std::string trim_copy(const std::string &str, const std::string &filter) { 130 inline std::string trim_copy(const std::string &str, const std::string &filter) {
@@ -179,40 +132,11 @@ inline std::string trim_copy(const std::string &amp;str, const std::string &amp;filter) @@ -179,40 +132,11 @@ inline std::string trim_copy(const std::string &amp;str, const std::string &amp;filter)
179 return trim(s, filter); 132 return trim(s, filter);
180 } 133 }
181 /// Print a two part "help" string 134 /// Print a two part "help" string
182 -inline std::ostream &format_help(std::ostream &out, std::string name, const std::string &description, std::size_t wid) {  
183 - name = " " + name;  
184 - out << std::setw(static_cast<int>(wid)) << std::left << name;  
185 - if(!description.empty()) {  
186 - if(name.length() >= wid)  
187 - out << "\n" << std::setw(static_cast<int>(wid)) << "";  
188 - for(const char c : description) {  
189 - out.put(c);  
190 - if(c == '\n') {  
191 - out << std::setw(static_cast<int>(wid)) << "";  
192 - }  
193 - }  
194 - }  
195 - out << "\n";  
196 - return out;  
197 -} 135 +CLI11_INLINE std::ostream &
  136 +format_help(std::ostream &out, std::string name, const std::string &description, std::size_t wid);
198 137
199 /// Print subcommand aliases 138 /// Print subcommand aliases
200 -inline std::ostream &format_aliases(std::ostream &out, const std::vector<std::string> &aliases, std::size_t wid) {  
201 - if(!aliases.empty()) {  
202 - out << std::setw(static_cast<int>(wid)) << " aliases: ";  
203 - bool front = true;  
204 - for(const auto &alias : aliases) {  
205 - if(!front) {  
206 - out << ", ";  
207 - } else {  
208 - front = false;  
209 - }  
210 - out << detail::fix_newlines(" ", alias);  
211 - }  
212 - out << "\n";  
213 - }  
214 - return out;  
215 -} 139 +CLI11_INLINE std::ostream &format_aliases(std::ostream &out, const std::vector<std::string> &aliases, std::size_t wid);
216 140
217 /// Verify the first character of an option 141 /// Verify the first character of an option
218 /// - is a trigger character, ! has special meaning and new lines would just be annoying to deal with 142 /// - is a trigger character, ! has special meaning and new lines would just be annoying to deal with
@@ -227,16 +151,7 @@ template &lt;typename T&gt; bool valid_later_char(T c) { @@ -227,16 +151,7 @@ template &lt;typename T&gt; bool valid_later_char(T c) {
227 } 151 }
228 152
229 /// Verify an option/subcommand name 153 /// Verify an option/subcommand name
230 -inline bool valid_name_string(const std::string &str) {  
231 - if(str.empty() || !valid_first_char(str[0])) {  
232 - return false;  
233 - }  
234 - auto e = str.end();  
235 - for(auto c = str.begin() + 1; c != e; ++c)  
236 - if(!valid_later_char(*c))  
237 - return false;  
238 - return true;  
239 -} 154 +CLI11_INLINE bool valid_name_string(const std::string &str);
240 155
241 /// Verify an app name 156 /// Verify an app name
242 inline bool valid_alias_name_string(const std::string &str) { 157 inline bool valid_alias_name_string(const std::string &str) {
@@ -270,66 +185,20 @@ inline std::string remove_underscore(std::string str) { @@ -270,66 +185,20 @@ inline std::string remove_underscore(std::string str) {
270 } 185 }
271 186
272 /// Find and replace a substring with another substring 187 /// Find and replace a substring with another substring
273 -inline std::string find_and_replace(std::string str, std::string from, std::string to) {  
274 -  
275 - std::size_t start_pos = 0;  
276 -  
277 - while((start_pos = str.find(from, start_pos)) != std::string::npos) {  
278 - str.replace(start_pos, from.length(), to);  
279 - start_pos += to.length();  
280 - }  
281 -  
282 - return str;  
283 -} 188 +CLI11_INLINE std::string find_and_replace(std::string str, std::string from, std::string to);
284 189
285 /// check if the flag definitions has possible false flags 190 /// check if the flag definitions has possible false flags
286 inline bool has_default_flag_values(const std::string &flags) { 191 inline bool has_default_flag_values(const std::string &flags) {
287 return (flags.find_first_of("{!") != std::string::npos); 192 return (flags.find_first_of("{!") != std::string::npos);
288 } 193 }
289 194
290 -inline void remove_default_flag_values(std::string &flags) {  
291 - auto loc = flags.find_first_of('{', 2);  
292 - while(loc != std::string::npos) {  
293 - auto finish = flags.find_first_of("},", loc + 1);  
294 - if((finish != std::string::npos) && (flags[finish] == '}')) {  
295 - flags.erase(flags.begin() + static_cast<std::ptrdiff_t>(loc),  
296 - flags.begin() + static_cast<std::ptrdiff_t>(finish) + 1);  
297 - }  
298 - loc = flags.find_first_of('{', loc + 1);  
299 - }  
300 - flags.erase(std::remove(flags.begin(), flags.end(), '!'), flags.end());  
301 -} 195 +CLI11_INLINE void remove_default_flag_values(std::string &flags);
302 196
303 /// Check if a string is a member of a list of strings and optionally ignore case or ignore underscores 197 /// Check if a string is a member of a list of strings and optionally ignore case or ignore underscores
304 -inline std::ptrdiff_t find_member(std::string name,  
305 - const std::vector<std::string> names,  
306 - bool ignore_case = false,  
307 - bool ignore_underscore = false) {  
308 - auto it = std::end(names);  
309 - if(ignore_case) {  
310 - if(ignore_underscore) {  
311 - name = detail::to_lower(detail::remove_underscore(name));  
312 - it = std::find_if(std::begin(names), std::end(names), [&name](std::string local_name) {  
313 - return detail::to_lower(detail::remove_underscore(local_name)) == name;  
314 - });  
315 - } else {  
316 - name = detail::to_lower(name);  
317 - it = std::find_if(std::begin(names), std::end(names), [&name](std::string local_name) {  
318 - return detail::to_lower(local_name) == name;  
319 - });  
320 - }  
321 -  
322 - } else if(ignore_underscore) {  
323 - name = detail::remove_underscore(name);  
324 - it = std::find_if(std::begin(names), std::end(names), [&name](std::string local_name) {  
325 - return detail::remove_underscore(local_name) == name;  
326 - });  
327 - } else {  
328 - it = std::find(std::begin(names), std::end(names), name);  
329 - }  
330 -  
331 - return (it != std::end(names)) ? (it - std::begin(names)) : (-1);  
332 -} 198 +CLI11_INLINE std::ptrdiff_t find_member(std::string name,
  199 + const std::vector<std::string> names,
  200 + bool ignore_case = false,
  201 + bool ignore_underscore = false);
333 202
334 /// Find a trigger string and call a modify callable function that takes the current string and starting position of the 203 /// Find a trigger string and call a modify callable function that takes the current string and starting position of the
335 /// trigger and returns the position in the string to search for the next trigger string 204 /// trigger and returns the position in the string to search for the next trigger string
@@ -343,88 +212,23 @@ template &lt;typename Callable&gt; inline std::string find_and_modify(std::string str, @@ -343,88 +212,23 @@ template &lt;typename Callable&gt; inline std::string find_and_modify(std::string str,
343 212
344 /// Split a string '"one two" "three"' into 'one two', 'three' 213 /// Split a string '"one two" "three"' into 'one two', 'three'
345 /// Quote characters can be ` ' or " 214 /// Quote characters can be ` ' or "
346 -inline std::vector<std::string> split_up(std::string str, char delimiter = '\0') {  
347 -  
348 - const std::string delims("\'\"`");  
349 - auto find_ws = [delimiter](char ch) {  
350 - return (delimiter == '\0') ? std::isspace<char>(ch, std::locale()) : (ch == delimiter);  
351 - };  
352 - trim(str);  
353 -  
354 - std::vector<std::string> output;  
355 - bool embeddedQuote = false;  
356 - char keyChar = ' ';  
357 - while(!str.empty()) {  
358 - if(delims.find_first_of(str[0]) != std::string::npos) {  
359 - keyChar = str[0];  
360 - auto end = str.find_first_of(keyChar, 1);  
361 - while((end != std::string::npos) && (str[end - 1] == '\\')) { // deal with escaped quotes  
362 - end = str.find_first_of(keyChar, end + 1);  
363 - embeddedQuote = true;  
364 - }  
365 - if(end != std::string::npos) {  
366 - output.push_back(str.substr(1, end - 1));  
367 - if(end + 2 < str.size()) {  
368 - str = str.substr(end + 2);  
369 - } else {  
370 - str.clear();  
371 - }  
372 -  
373 - } else {  
374 - output.push_back(str.substr(1));  
375 - str = "";  
376 - }  
377 - } else {  
378 - auto it = std::find_if(std::begin(str), std::end(str), find_ws);  
379 - if(it != std::end(str)) {  
380 - std::string value = std::string(str.begin(), it);  
381 - output.push_back(value);  
382 - str = std::string(it + 1, str.end());  
383 - } else {  
384 - output.push_back(str);  
385 - str = "";  
386 - }  
387 - }  
388 - // transform any embedded quotes into the regular character  
389 - if(embeddedQuote) {  
390 - output.back() = find_and_replace(output.back(), std::string("\\") + keyChar, std::string(1, keyChar));  
391 - embeddedQuote = false;  
392 - }  
393 - trim(str);  
394 - }  
395 - return output;  
396 -} 215 +CLI11_INLINE std::vector<std::string> split_up(std::string str, char delimiter = '\0');
397 216
398 /// This function detects an equal or colon followed by an escaped quote after an argument 217 /// This function detects an equal or colon followed by an escaped quote after an argument
399 /// then modifies the string to replace the equality with a space. This is needed 218 /// then modifies the string to replace the equality with a space. This is needed
400 /// to allow the split up function to work properly and is intended to be used with the find_and_modify function 219 /// to allow the split up function to work properly and is intended to be used with the find_and_modify function
401 /// the return value is the offset+1 which is required by the find_and_modify function. 220 /// the return value is the offset+1 which is required by the find_and_modify function.
402 -inline std::size_t escape_detect(std::string &str, std::size_t offset) {  
403 - auto next = str[offset + 1];  
404 - if((next == '\"') || (next == '\'') || (next == '`')) {  
405 - auto astart = str.find_last_of("-/ \"\'`", offset - 1);  
406 - if(astart != std::string::npos) {  
407 - if(str[astart] == ((str[offset] == '=') ? '-' : '/'))  
408 - str[offset] = ' '; // interpret this as a space so the split_up works properly  
409 - }  
410 - }  
411 - return offset + 1;  
412 -} 221 +CLI11_INLINE std::size_t escape_detect(std::string &str, std::size_t offset);
413 222
414 /// Add quotes if the string contains spaces 223 /// Add quotes if the string contains spaces
415 -inline std::string &add_quotes_if_needed(std::string &str) {  
416 - if((str.front() != '"' && str.front() != '\'') || str.front() != str.back()) {  
417 - char quote = str.find('"') < str.find('\'') ? '\'' : '"';  
418 - if(str.find(' ') != std::string::npos) {  
419 - str.insert(0, 1, quote);  
420 - str.append(1, quote);  
421 - }  
422 - }  
423 - return str;  
424 -} 224 +CLI11_INLINE std::string &add_quotes_if_needed(std::string &str);
425 225
426 } // namespace detail 226 } // namespace detail
427 227
428 // [CLI11:string_tools_hpp:end] 228 // [CLI11:string_tools_hpp:end]
429 229
430 } // namespace CLI 230 } // namespace CLI
  231 +
  232 +#ifndef CLI11_COMPILE
  233 +#include "impl/StringTools_inl.hpp"
  234 +#endif
include/CLI/impl/StringTools_inl.hpp 0 → 100644
  1 +// Copyright (c) 2017-2022, 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 +// This include is only needed for IDEs to discover symbols
  10 +#include <CLI/StringTools.hpp>
  11 +
  12 +// [CLI11:public_includes:set]
  13 +#include <string>
  14 +#include <vector>
  15 +// [CLI11:public_includes:end]
  16 +
  17 +namespace CLI {
  18 +// [CLI11:string_tools_inl_hpp:verbatim]
  19 +
  20 +namespace detail {
  21 +CLI11_INLINE std::vector<std::string> split(const std::string &s, char delim) {
  22 + std::vector<std::string> elems;
  23 + // Check to see if empty string, give consistent result
  24 + if(s.empty()) {
  25 + elems.emplace_back();
  26 + } else {
  27 + std::stringstream ss;
  28 + ss.str(s);
  29 + std::string item;
  30 + while(std::getline(ss, item, delim)) {
  31 + elems.push_back(item);
  32 + }
  33 + }
  34 + return elems;
  35 +}
  36 +
  37 +CLI11_INLINE std::string &ltrim(std::string &str) {
  38 + auto it = std::find_if(str.begin(), str.end(), [](char ch) { return !std::isspace<char>(ch, std::locale()); });
  39 + str.erase(str.begin(), it);
  40 + return str;
  41 +}
  42 +
  43 +CLI11_INLINE std::string &ltrim(std::string &str, const std::string &filter) {
  44 + auto it = std::find_if(str.begin(), str.end(), [&filter](char ch) { return filter.find(ch) == std::string::npos; });
  45 + str.erase(str.begin(), it);
  46 + return str;
  47 +}
  48 +
  49 +CLI11_INLINE std::string &rtrim(std::string &str) {
  50 + auto it = std::find_if(str.rbegin(), str.rend(), [](char ch) { return !std::isspace<char>(ch, std::locale()); });
  51 + str.erase(it.base(), str.end());
  52 + return str;
  53 +}
  54 +
  55 +CLI11_INLINE std::string &rtrim(std::string &str, const std::string &filter) {
  56 + auto it =
  57 + std::find_if(str.rbegin(), str.rend(), [&filter](char ch) { return filter.find(ch) == std::string::npos; });
  58 + str.erase(it.base(), str.end());
  59 + return str;
  60 +}
  61 +
  62 +CLI11_INLINE std::string &remove_quotes(std::string &str) {
  63 + if(str.length() > 1 && (str.front() == '"' || str.front() == '\'')) {
  64 + if(str.front() == str.back()) {
  65 + str.pop_back();
  66 + str.erase(str.begin(), str.begin() + 1);
  67 + }
  68 + }
  69 + return str;
  70 +}
  71 +
  72 +CLI11_INLINE std::string fix_newlines(const std::string &leader, std::string input) {
  73 + std::string::size_type n = 0;
  74 + while(n != std::string::npos && n < input.size()) {
  75 + n = input.find('\n', n);
  76 + if(n != std::string::npos) {
  77 + input = input.substr(0, n + 1) + leader + input.substr(n + 1);
  78 + n += leader.size();
  79 + }
  80 + }
  81 + return input;
  82 +}
  83 +
  84 +CLI11_INLINE std::ostream &
  85 +format_help(std::ostream &out, std::string name, const std::string &description, std::size_t wid) {
  86 + name = " " + name;
  87 + out << std::setw(static_cast<int>(wid)) << std::left << name;
  88 + if(!description.empty()) {
  89 + if(name.length() >= wid)
  90 + out << "\n" << std::setw(static_cast<int>(wid)) << "";
  91 + for(const char c : description) {
  92 + out.put(c);
  93 + if(c == '\n') {
  94 + out << std::setw(static_cast<int>(wid)) << "";
  95 + }
  96 + }
  97 + }
  98 + out << "\n";
  99 + return out;
  100 +}
  101 +
  102 +CLI11_INLINE std::ostream &format_aliases(std::ostream &out, const std::vector<std::string> &aliases, std::size_t wid) {
  103 + if(!aliases.empty()) {
  104 + out << std::setw(static_cast<int>(wid)) << " aliases: ";
  105 + bool front = true;
  106 + for(const auto &alias : aliases) {
  107 + if(!front) {
  108 + out << ", ";
  109 + } else {
  110 + front = false;
  111 + }
  112 + out << detail::fix_newlines(" ", alias);
  113 + }
  114 + out << "\n";
  115 + }
  116 + return out;
  117 +}
  118 +
  119 +CLI11_INLINE bool valid_name_string(const std::string &str) {
  120 + if(str.empty() || !valid_first_char(str[0])) {
  121 + return false;
  122 + }
  123 + auto e = str.end();
  124 + for(auto c = str.begin() + 1; c != e; ++c)
  125 + if(!valid_later_char(*c))
  126 + return false;
  127 + return true;
  128 +}
  129 +
  130 +CLI11_INLINE std::string find_and_replace(std::string str, std::string from, std::string to) {
  131 +
  132 + std::size_t start_pos = 0;
  133 +
  134 + while((start_pos = str.find(from, start_pos)) != std::string::npos) {
  135 + str.replace(start_pos, from.length(), to);
  136 + start_pos += to.length();
  137 + }
  138 +
  139 + return str;
  140 +}
  141 +
  142 +CLI11_INLINE void remove_default_flag_values(std::string &flags) {
  143 + auto loc = flags.find_first_of('{', 2);
  144 + while(loc != std::string::npos) {
  145 + auto finish = flags.find_first_of("},", loc + 1);
  146 + if((finish != std::string::npos) && (flags[finish] == '}')) {
  147 + flags.erase(flags.begin() + static_cast<std::ptrdiff_t>(loc),
  148 + flags.begin() + static_cast<std::ptrdiff_t>(finish) + 1);
  149 + }
  150 + loc = flags.find_first_of('{', loc + 1);
  151 + }
  152 + flags.erase(std::remove(flags.begin(), flags.end(), '!'), flags.end());
  153 +}
  154 +
  155 +CLI11_INLINE std::ptrdiff_t find_member(std::string name,
  156 + const std::vector<std::string> names,
  157 + bool ignore_case,
  158 + bool ignore_underscore) {
  159 + auto it = std::end(names);
  160 + if(ignore_case) {
  161 + if(ignore_underscore) {
  162 + name = detail::to_lower(detail::remove_underscore(name));
  163 + it = std::find_if(std::begin(names), std::end(names), [&name](std::string local_name) {
  164 + return detail::to_lower(detail::remove_underscore(local_name)) == name;
  165 + });
  166 + } else {
  167 + name = detail::to_lower(name);
  168 + it = std::find_if(std::begin(names), std::end(names), [&name](std::string local_name) {
  169 + return detail::to_lower(local_name) == name;
  170 + });
  171 + }
  172 +
  173 + } else if(ignore_underscore) {
  174 + name = detail::remove_underscore(name);
  175 + it = std::find_if(std::begin(names), std::end(names), [&name](std::string local_name) {
  176 + return detail::remove_underscore(local_name) == name;
  177 + });
  178 + } else {
  179 + it = std::find(std::begin(names), std::end(names), name);
  180 + }
  181 +
  182 + return (it != std::end(names)) ? (it - std::begin(names)) : (-1);
  183 +}
  184 +
  185 +CLI11_INLINE std::vector<std::string> split_up(std::string str, char delimiter) {
  186 +
  187 + const std::string delims("\'\"`");
  188 + auto find_ws = [delimiter](char ch) {
  189 + return (delimiter == '\0') ? std::isspace<char>(ch, std::locale()) : (ch == delimiter);
  190 + };
  191 + trim(str);
  192 +
  193 + std::vector<std::string> output;
  194 + bool embeddedQuote = false;
  195 + char keyChar = ' ';
  196 + while(!str.empty()) {
  197 + if(delims.find_first_of(str[0]) != std::string::npos) {
  198 + keyChar = str[0];
  199 + auto end = str.find_first_of(keyChar, 1);
  200 + while((end != std::string::npos) && (str[end - 1] == '\\')) { // deal with escaped quotes
  201 + end = str.find_first_of(keyChar, end + 1);
  202 + embeddedQuote = true;
  203 + }
  204 + if(end != std::string::npos) {
  205 + output.push_back(str.substr(1, end - 1));
  206 + if(end + 2 < str.size()) {
  207 + str = str.substr(end + 2);
  208 + } else {
  209 + str.clear();
  210 + }
  211 +
  212 + } else {
  213 + output.push_back(str.substr(1));
  214 + str = "";
  215 + }
  216 + } else {
  217 + auto it = std::find_if(std::begin(str), std::end(str), find_ws);
  218 + if(it != std::end(str)) {
  219 + std::string value = std::string(str.begin(), it);
  220 + output.push_back(value);
  221 + str = std::string(it + 1, str.end());
  222 + } else {
  223 + output.push_back(str);
  224 + str = "";
  225 + }
  226 + }
  227 + // transform any embedded quotes into the regular character
  228 + if(embeddedQuote) {
  229 + output.back() = find_and_replace(output.back(), std::string("\\") + keyChar, std::string(1, keyChar));
  230 + embeddedQuote = false;
  231 + }
  232 + trim(str);
  233 + }
  234 + return output;
  235 +}
  236 +
  237 +CLI11_INLINE std::size_t escape_detect(std::string &str, std::size_t offset) {
  238 + auto next = str[offset + 1];
  239 + if((next == '\"') || (next == '\'') || (next == '`')) {
  240 + auto astart = str.find_last_of("-/ \"\'`", offset - 1);
  241 + if(astart != std::string::npos) {
  242 + if(str[astart] == ((str[offset] == '=') ? '-' : '/'))
  243 + str[offset] = ' '; // interpret this as a space so the split_up works properly
  244 + }
  245 + }
  246 + return offset + 1;
  247 +}
  248 +
  249 +CLI11_INLINE std::string &add_quotes_if_needed(std::string &str) {
  250 + if((str.front() != '"' && str.front() != '\'') || str.front() != str.back()) {
  251 + char quote = str.find('"') < str.find('\'') ? '\'' : '"';
  252 + if(str.find(' ') != std::string::npos) {
  253 + str.insert(0, 1, quote);
  254 + str.append(1, quote);
  255 + }
  256 + }
  257 + return str;
  258 +}
  259 +
  260 +} // namespace detail
  261 +// [CLI11:string_tools_inl_hpp:end]
  262 +} // namespace CLI
src/StringTools.cpp 0 → 100644
  1 +// Copyright (c) 2017-2022, 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 +#include <CLI/impl/StringTools_inl.hpp>