OpenMS
Loading...
Searching...
No Matches
StringUtils.h
Go to the documentation of this file.
1// Copyright (c) 2002-present, OpenMS Inc. -- EKU Tuebingen, ETH Zurich, and FU Berlin
2// SPDX-License-Identifier: BSD-3-Clause
3//
4// --------------------------------------------------------------------------
5// $Maintainer: Timo Sachsenberg, Chris Bielow $
6// $Authors: Marc Sturm, Stephan Aiche, Chris Bielow $
7// --------------------------------------------------------------------------
8
9#pragma once
10
11// NOTE: Do NOT include String.h here — String.h includes us. Use std::string directly.
12
15#include <OpenMS/OpenMSConfig.h>
16
17#include <charconv>
18
19#include <algorithm>
20#include <cmath>
21#include <cstdio>
22#include <cstring>
23#include <limits>
24#include <sstream>
25#include <string>
26#include <string_view>
27#include <vector>
28
29namespace OpenMS
30{
31 class DataValue; // forward — DataValue.h includes String.h, so we cannot include it here
32 class ParamValue; // forward — same reason
33
34 // -------------------------------------------------------------------------
35 // QuotingMethod — formerly String::QuotingMethod
36 // -------------------------------------------------------------------------
38 enum class QuotingMethod { NONE, ESCAPE, DOUBLE };
39
40
41 // =========================================================================
42 // StringUtilsHelper — parsing helpers (definitions in StringUtils.cpp)
43 // =========================================================================
44 class OPENMS_DLLAPI StringUtilsHelper
45 {
46 public:
48 static Int32 toInt32(const std::string& s);
50 static Int64 toInt64(const std::string& s);
52 static float toFloat(const std::string& s);
54 static double toDouble(const std::string& s);
55
58 static bool extractDouble(const char*& begin, const char* end, double& target);
59
62 static bool extractInt(const char*& begin, const char* end, int& target);
63 };
64
65
66 // =========================================================================
67 // StringUtils — unified string utility namespace
68 // =========================================================================
69 namespace StringUtils
70 {
71
72 // -----------------------------------------------------------------------
73 // Append numeric value to a string (non-inline; defined in StringUtils.cpp)
74 // -----------------------------------------------------------------------
75
76 OPENMS_DLLAPI void appendToStr(int i, std::string& target);
77 OPENMS_DLLAPI void appendToStr(unsigned int i, std::string& target);
78 OPENMS_DLLAPI void appendToStr(short int i, std::string& target);
79 OPENMS_DLLAPI void appendToStr(short unsigned int i, std::string& target);
80 OPENMS_DLLAPI void appendToStr(long int i, std::string& target);
81 OPENMS_DLLAPI void appendToStr(long unsigned int i, std::string& target);
82 OPENMS_DLLAPI void appendToStr(long long unsigned int i, std::string& target);
83 OPENMS_DLLAPI void appendToStr(long long signed int i, std::string& target);
84
85 OPENMS_DLLAPI void appendToStr(float f, std::string& target);
86 OPENMS_DLLAPI void appendToStrLowP(float f, std::string& target);
87 OPENMS_DLLAPI void appendToStr(double d, std::string& target);
88 OPENMS_DLLAPI void appendToStrLowP(double d, std::string& target);
89 OPENMS_DLLAPI void appendToStr(long double ld, std::string& target);
90 OPENMS_DLLAPI void appendToStrLowP(long double ld, std::string& target);
91
93 OPENMS_DLLAPI void appendToStr(const DataValue& d, bool full_precision, std::string& target);
94
95
96 // -----------------------------------------------------------------------
97 // toStr() — convert a value to a new std::string
98 // -----------------------------------------------------------------------
99
100 inline std::string toStr(int i)
101 { std::string s; appendToStr(i, s); return s; }
102 inline std::string toStr(unsigned int i)
103 { std::string s; appendToStr(i, s); return s; }
104 inline std::string toStr(short int i)
105 { std::string s; appendToStr(i, s); return s; }
106 inline std::string toStr(short unsigned int i)
107 { std::string s; appendToStr(i, s); return s; }
108 inline std::string toStr(long int i)
109 { std::string s; appendToStr(i, s); return s; }
110 inline std::string toStr(long unsigned int i)
111 { std::string s; appendToStr(i, s); return s; }
112 inline std::string toStr(long long unsigned int i)
113 { std::string s; appendToStr(i, s); return s; }
114 inline std::string toStr(long long signed int i)
115 { std::string s; appendToStr(i, s); return s; }
116
118 OPENMS_DLLAPI std::string toStr(float f, bool full_precision = true);
120 OPENMS_DLLAPI std::string toStr(double d, bool full_precision = true);
122 OPENMS_DLLAPI std::string toStr(long double ld, bool full_precision = true);
123
124 inline std::string toStr(char c)
125 { return std::string(1, c); }
126
127 inline std::string toStr(const std::string& s)
128 { return s; }
129
130 inline std::string toStr(const char* s)
131 { return std::string(s); }
132
154 OPENMS_DLLAPI std::string toStr(const DataValue& d, bool full_precision = true);
155
157 OPENMS_DLLAPI std::string toStr(const ParamValue& p, bool full_precision = true);
158
160 inline std::string toStr(std::string_view sv) { return std::string(sv); }
161
162
163 // -----------------------------------------------------------------------
164 // Parse string → numeric
165 // -----------------------------------------------------------------------
166
167 inline Int32 toInt32(const std::string& s) { return StringUtilsHelper::toInt32(s); }
168 inline Int64 toInt64(const std::string& s) { return StringUtilsHelper::toInt64(s); }
169 inline float toFloat(const std::string& s) { return StringUtilsHelper::toFloat(s); }
170 inline double toDouble(const std::string& s) { return StringUtilsHelper::toDouble(s); }
171
172 inline bool extractDouble(const char*& begin, const char* end, double& target)
173 { return StringUtilsHelper::extractDouble(begin, end, target); }
174
175 inline bool extractInt(const char*& begin, const char* end, int& target)
176 { return StringUtilsHelper::extractInt(begin, end, target); }
177
179 inline bool extractDouble(std::string::const_iterator& begin, const std::string::const_iterator& end, double& target)
180 {
181 if (begin == end) return false; // also avoids dereferencing begin below
182 const char* const p_start = &(*begin);
183 const char* p = p_start;
184 // compute the end pointer from the range length -- dereferencing the
185 // past-the-end iterator is UB and asserts under debug iterators
186 const char* const e = p_start + (end - begin);
187 bool ok = StringUtilsHelper::extractDouble(p, e, target);
188 begin += (p - p_start); // advance iterator by number of consumed chars (MSVC iterators cannot be built from a raw pointer)
189 return ok;
190 }
191
192 inline bool extractDouble(std::string::iterator& begin, const std::string::iterator& end, double& target)
193 {
194 if (begin == end) return false; // also avoids dereferencing begin below
195 const char* const p_start = &(*begin);
196 const char* p = p_start;
197 // compute the end pointer from the range length -- dereferencing the
198 // past-the-end iterator is UB and asserts under debug iterators
199 const char* const e = p_start + (end - begin);
200 bool ok = StringUtilsHelper::extractDouble(p, e, target);
201 begin += (p - p_start); // advance iterator by number of consumed chars (MSVC iterators cannot be built from a raw pointer)
202 return ok;
203 }
204
205 inline bool extractInt(std::string::const_iterator& begin, const std::string::const_iterator& end, int& target)
206 {
207 if (begin == end) return false; // also avoids dereferencing begin below
208 const char* const p_start = &(*begin);
209 const char* p = p_start;
210 // compute the end pointer from the range length -- dereferencing the
211 // past-the-end iterator is UB and asserts under debug iterators
212 const char* const e = p_start + (end - begin);
213 bool ok = StringUtilsHelper::extractInt(p, e, target);
214 begin += (p - p_start); // advance iterator by number of consumed chars (MSVC iterators cannot be built from a raw pointer)
215 return ok;
216 }
217
218 inline bool extractInt(std::string::iterator& begin, const std::string::iterator& end, int& target)
219 {
220 if (begin == end) return false; // also avoids dereferencing begin below
221 const char* const p_start = &(*begin);
222 const char* p = p_start;
223 // compute the end pointer from the range length -- dereferencing the
224 // past-the-end iterator is UB and asserts under debug iterators
225 const char* const e = p_start + (end - begin);
226 bool ok = StringUtilsHelper::extractInt(p, e, target);
227 begin += (p - p_start); // advance iterator by number of consumed chars (MSVC iterators cannot be built from a raw pointer)
228 return ok;
229 }
230
231
232 // -----------------------------------------------------------------------
233 // Whitespace scanning (SIMD-accelerated; non-inline)
234 // -----------------------------------------------------------------------
235
237 OPENMS_DLLAPI const char* skipWhitespace(const char* p, const char* p_end);
238
240 inline size_t skipWhitespace(const std::string_view& data)
241 {
242 auto pos = skipWhitespace(data.data(), data.data() + data.size());
243 return static_cast<size_t>(pos - data.data());
244 }
245
247 OPENMS_DLLAPI const char* skipNonWhitespace(const char* p, const char* p_end);
248
250 inline size_t skipNonWhitespace(const std::string_view& data)
251 {
252 auto pos = skipNonWhitespace(data.data(), data.data() + data.size());
253 return static_cast<size_t>(pos - data.data());
254 }
255
256
257 // -----------------------------------------------------------------------
258 // Static factory methods
259 // -----------------------------------------------------------------------
260
262 [[maybe_unused]] OPENMS_DLLAPI std::string number(double d, UInt n);
263
265 [[maybe_unused]] OPENMS_DLLAPI std::string numberLength(double d, UInt n);
266
268 OPENMS_DLLAPI std::string random(UInt length);
269
270
271 // -----------------------------------------------------------------------
272 // Predicates
273 // -----------------------------------------------------------------------
274
275 inline bool hasPrefix(const std::string& s, const std::string& prefix)
276 {
277 if (prefix.size() > s.size()) return false;
278 if (prefix.empty()) return true;
279 return s.compare(0, prefix.size(), prefix) == 0;
280 }
281 inline bool hasPrefix(const std::string& s, char c)
282 { return !s.empty() && s.front() == c; }
283
284 inline bool hasSuffix(const std::string& s, const std::string& sfx)
285 {
286 if (sfx.size() > s.size()) return false;
287 if (sfx.empty()) return true;
288 return s.compare(s.size() - sfx.size(), sfx.size(), sfx) == 0;
289 }
290 inline bool hasSuffix(const std::string& s, char c)
291 { return !s.empty() && s.back() == c; }
292
293 inline bool hasSubstring(const std::string& s, const std::string& sub)
294 {
295 return s.find(sub) != std::string::npos;
296 }
297 inline bool hasSubstring(const std::string& s, char c)
298 { return s.find(c) != std::string::npos; }
299
300 inline bool has(const std::string& s, Byte byte)
301 {
302 return s.find(static_cast<char>(byte)) != std::string::npos;
303 }
304 inline bool has(const std::string& s, char c)
305 { return s.find(c) != std::string::npos; }
306
307
308 // -----------------------------------------------------------------------
309 // Accessors (return new string)
310 // -----------------------------------------------------------------------
311
312 inline std::string prefix(const std::string& s, size_t length)
313 {
314 if (length > s.size())
315 throw Exception::IndexOverflow(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, length, s.size());
316 return s.substr(0, length);
317 }
318
319 inline std::string suffix(const std::string& s, size_t length)
320 {
321 if (length > s.size())
322 throw Exception::IndexOverflow(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, length, s.size());
323 return s.substr(s.size() - length, length);
324 }
325
326 inline std::string prefix(const std::string& s, Int length)
327 {
328 if (length < 0)
329 throw Exception::IndexUnderflow(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, length, 0);
330 return prefix(s, static_cast<size_t>(length));
331 }
332
333 inline std::string suffix(const std::string& s, Int length)
334 {
335 if (length < 0)
336 throw Exception::IndexUnderflow(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, length, 0);
337 return suffix(s, static_cast<size_t>(length));
338 }
339
345 inline std::string prefix(const std::string& s, char delim)
346 {
347 return s.substr(0, s.find(delim)); // find() returns npos if absent -> substr(0, npos) -> whole string
348 }
349
355 inline std::string suffix(const std::string& s, char delim)
356 {
357 size_t pos = s.rfind(delim);
358 return pos == std::string::npos ? s : s.substr(pos + 1);
359 }
360
362 inline std::string substr(const std::string& s, size_t pos = 0, size_t n = std::string::npos)
363 {
364 size_t begin = std::min(pos, s.size());
365 return s.substr(begin, n);
366 }
368 inline std::string substr(std::string_view s, size_t pos = 0, size_t n = std::string::npos)
369 {
370 size_t begin = std::min(pos, s.size());
371 return std::string(s.substr(begin, n));
372 }
373
375 inline bool hasPrefix(std::string_view s, const std::string& prefix)
376 { return s.size() >= prefix.size() && s.substr(0, prefix.size()) == prefix; }
377 inline bool hasSuffix(std::string_view s, const std::string& sfx)
378 { return s.size() >= sfx.size() && s.substr(s.size() - sfx.size()) == sfx; }
379 inline bool hasSubstring(std::string_view s, const std::string& sub)
380 { return s.find(sub) != std::string_view::npos; }
381
383 inline std::string chop(const std::string& s, Size n)
384 {
385 size_t end = (n < s.size()) ? s.size() - n : 0;
386 return std::string(s.begin(), s.begin() + end);
387 }
388
389
390 // -----------------------------------------------------------------------
391 // In-place mutators (all return std::string& for chaining via free fns)
392 // -----------------------------------------------------------------------
393
394 inline std::string& trim(std::string& s)
395 {
396 auto begin = s.begin();
397 while (begin != s.end() && (*begin == ' ' || *begin == '\t' || *begin == '\n' || *begin == '\r'))
398 ++begin;
399 if (begin == s.end()) { s.clear(); return s; }
400 auto end = s.end() - 1;
401 while (end != begin && (*end == ' ' || *end == '\n' || *end == '\t' || *end == '\r'))
402 --end;
403 ++end;
404 if (begin != s.begin() || end != s.end())
405 s.assign(begin, end);
406 return s;
407 }
408
410 inline std::string trimmed(std::string s) { return std::move(trim(s)); }
411
412 inline std::string& toUpper(std::string& s)
413 {
414 std::transform(s.begin(), s.end(), s.begin(), [](unsigned char c){ return std::toupper(c); });
415 return s;
416 }
417
418 inline std::string& toLower(std::string& s)
419 {
420 std::transform(s.begin(), s.end(), s.begin(), [](unsigned char c){ return std::tolower(c); });
421 return s;
422 }
424 inline std::string toUppered(std::string s) { return std::move(toUpper(s)); }
426 inline std::string toLowered(std::string s) { return std::move(toLower(s)); }
427
428 inline std::string& firstToUpper(std::string& s)
429 {
430 if (!s.empty()) s[0] = static_cast<char>(std::toupper(static_cast<unsigned char>(s[0])));
431 return s;
432 }
433
434 inline std::string& reverse(std::string& s)
435 {
436 std::reverse(s.begin(), s.end());
437 return s;
438 }
439
440 inline std::string& simplify(std::string& s)
441 {
442 std::string result;
443 result.reserve(s.size());
444 bool last_ws = false;
445 for (char c : s)
446 {
447 if (c == ' ' || c == '\n' || c == '\t' || c == '\r')
448 {
449 if (!last_ws) result += ' ';
450 last_ws = true;
451 }
452 else
453 {
454 result += c;
455 last_ws = false;
456 }
457 }
458 s.swap(result);
459 return s;
460 }
461
462 inline std::string& fillLeft(std::string& s, char c, UInt size)
463 {
464 if (s.size() < size)
465 s.insert(s.begin(), size - s.size(), c);
466 return s;
467 }
468
469 inline std::string& fillRight(std::string& s, char c, UInt size)
470 {
471 if (s.size() < size)
472 s.append(size - s.size(), c);
473 return s;
474 }
475
476 inline std::string& substitute(std::string& s, char from, char to)
477 {
478 std::replace(s.begin(), s.end(), from, to);
479 return s;
480 }
481
483 inline std::string& substitute(std::string& s, const std::string& from, const std::string& to)
484 {
485 if (from.empty()) return s;
486 std::string result;
487 result.reserve(s.size());
488 size_t start = 0;
489 size_t pos;
490 while ((pos = s.find(from, start)) != std::string::npos)
491 {
492 result.append(s, start, pos - start);
493 result += to;
494 start = pos + from.size();
495 }
496 result.append(s, start, std::string::npos);
497 s.swap(result);
498 return s;
499 }
501 inline std::string substituted(std::string s, char from, char to) { return std::move(substitute(s, from, to)); }
502 inline std::string substituted(std::string s, const std::string& from, const std::string& to) { return std::move(substitute(s, from, to)); }
503
504 inline std::string& remove(std::string& s, char what)
505 {
506 s.erase(std::remove(s.begin(), s.end(), what), s.end());
507 return s;
508 }
509
510 // rvalue-ref overloads so chained/temporary strings can be padded in place
511 inline std::string fillLeft(std::string&& s, char c, UInt size) { fillLeft(s, c, size); return std::move(s); }
512 inline std::string fillRight(std::string&& s, char c, UInt size) { fillRight(s, c, size); return std::move(s); }
513
514 inline std::string& ensureLastChar(std::string& s, char end)
515 {
516 if (s.empty() || s.back() != end) s.push_back(end);
517 return s;
518 }
520 inline std::string ensureLastChar(std::string&& s, char end) { ensureLastChar(s, end); return std::move(s); }
521
522 inline std::string& removeWhitespaces(std::string& s)
523 {
524 // skip unmodified prefix
525 const size_t start = skipNonWhitespace(std::string_view(s.data(), s.size()));
526 auto it = s.cbegin() + start;
527 auto dest = s.begin() + start;
528 auto it_end = s.cend();
529 bool has_spaces = false;
530 while (it != it_end)
531 {
532 const char c = *it;
533 if (c == ' ' || c == '\t' || c == '\n' || c == '\r')
534 {
535 ++it;
536 has_spaces = true;
537 continue;
538 }
539 if (has_spaces) *dest = *it;
540 ++dest;
541 ++it;
542 }
543 if (has_spaces) s.resize(static_cast<size_t>(dest - s.begin()));
544 return s;
545 }
546
547 inline bool isQuoted(const std::string& s, char q)
548 {
549 return s.size() >= 2 && s.front() == q && s.back() == q;
550 }
551
552 inline std::string& quote(std::string& s, char q = '"', QuotingMethod method = QuotingMethod::ESCAPE)
553 {
554 if (method == QuotingMethod::ESCAPE)
555 {
556 substitute(s, std::string("\\"), std::string("\\\\"));
557 substitute(s, std::string(1, q), std::string("\\") + q);
558 }
559 else if (method == QuotingMethod::DOUBLE)
560 {
561 substitute(s, std::string(1, q), std::string(2, q));
562 }
563 s.insert(s.begin(), q);
564 s.push_back(q);
565 return s;
566 }
567
568 inline std::string& unquote(std::string& s, char q = '"', QuotingMethod method = QuotingMethod::ESCAPE)
569 {
570 if (!isQuoted(s, q))
571 throw Exception::ConversionError(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION,
572 "'" + s + "' does not have the expected format of a quoted string");
573 s.erase(s.begin());
574 s.pop_back();
575 if (method == QuotingMethod::ESCAPE)
576 {
577 substitute(s, std::string("\\") + q, std::string(1, q));
578 substitute(s, std::string("\\\\"), std::string("\\"));
579 }
580 else if (method == QuotingMethod::DOUBLE)
581 {
582 substitute(s, std::string(2, q), std::string(1, q));
583 }
584 return s;
585 }
586
587
588 // -----------------------------------------------------------------------
589 // Split / Join
590 // -----------------------------------------------------------------------
591
595 inline bool split(const std::string& s, char splitter,
596 std::vector<std::string>& substrings,
597 bool quote_protect = false)
598 {
599 substrings.clear();
600 if (s.empty()) return false;
601
602 size_t nsplits = static_cast<size_t>(std::count(s.begin(), s.end(), splitter));
603
604 if (!quote_protect && nsplits == 0)
605 {
606 substrings.push_back(s);
607 return false;
608 }
609
610 substrings.reserve(nsplits + 1);
611
612 if (quote_protect)
613 {
614 int quote_count = 0;
615 auto begin = s.cbegin();
616 auto end = s.cbegin();
617 for (; end != s.cend(); ++end)
618 {
619 if (*end == '"') ++quote_count;
620 if ((quote_count % 2 == 0) && (*end == splitter))
621 {
622 std::string block(begin, end);
623 trim(block);
624 bool has_start = block.size() >= 1 && block.front() == '"';
625 bool has_end = block.size() >= 1 && block.back() == '"';
626 if (block.size() >= 2 && (has_start ^ has_end))
627 throw Exception::ConversionError(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION,
628 "Could not dequote string '" + block + "' due to wrongly placed '\"'.");
629 if (block.size() >= 2 && has_start && has_end)
630 block = block.substr(1, block.size() - 2);
631 substrings.push_back(std::move(block));
632 begin = end + 1;
633 }
634 }
635 if (substrings.empty()) { substrings.push_back(s); return false; }
636 std::string block(begin, end);
637 trim(block);
638 bool has_start = block.size() >= 1 && block.front() == '"';
639 bool has_end = block.size() >= 1 && block.back() == '"';
640 if (block.size() >= 2 && (has_start ^ has_end))
641 throw Exception::ConversionError(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION,
642 "Could not dequote string '" + block + "' due to wrongly placed '\"'.");
643 if (block.size() >= 2 && has_start && has_end)
644 block = block.substr(1, block.size() - 2);
645 substrings.push_back(std::move(block));
646 }
647 else
648 {
649 auto begin = s.cbegin();
650 for (auto it = s.cbegin(); it != s.cend(); ++it)
651 {
652 if (*it == splitter)
653 {
654 substrings.emplace_back(begin, it);
655 begin = it + 1;
656 }
657 }
658 substrings.emplace_back(begin, s.cend());
659 }
660 return true;
661 }
662
665 inline bool split(const std::string& s, const std::string& splitter,
666 std::vector<std::string>& substrings)
667 {
668 substrings.clear();
669 if (s.empty()) return false;
670 if (splitter.empty())
671 {
672 substrings.resize(s.size());
673 for (size_t i = 0; i < s.size(); ++i) substrings[i] = std::string(1, s[i]);
674 return true;
675 }
676 size_t len = splitter.size();
677 size_t start = 0;
678 size_t pos = s.find(splitter);
679 while (pos != std::string::npos)
680 {
681 substrings.push_back(s.substr(start, pos - start));
682 start = pos + len;
683 pos = s.find(splitter, start);
684 }
685 substrings.push_back(s.substr(start));
686 return substrings.size() > 1;
687 }
688
691 inline bool split_quoted(const std::string& s, const std::string& splitter,
692 std::vector<std::string>& substrings,
693 char q = '"', QuotingMethod method = QuotingMethod::ESCAPE)
694 {
695 substrings.clear();
696 if (s.empty() || splitter.empty()) return false;
697
698 bool in_quote = false;
699 char targets[2] = {q, splitter[0]};
700 std::string rest = splitter.substr(1);
701 size_t start = 0;
702
703 for (size_t i = 0; i < s.size(); ++i)
704 {
705 if (in_quote)
706 {
707 bool embedded = false;
708 if (method == QuotingMethod::ESCAPE)
709 {
710 for (; i < s.size(); ++i)
711 {
712 if (s[i] == '\\') embedded = !embedded;
713 else if (s[i] == q && !embedded) break;
714 else embedded = false;
715 }
716 }
717 else
718 {
719 for (; i < s.size(); ++i)
720 {
721 if (s[i] == q)
722 {
723 if (method == QuotingMethod::NONE) break;
724 if (i + 1 < s.size() && s[i + 1] == q) embedded = !embedded;
725 else if (!embedded) break;
726 else embedded = false;
727 }
728 }
729 }
730 in_quote = false;
731 }
732 else
733 {
734 i = s.find_first_of(targets, i, 2);
735 if (i == std::string::npos) break;
736 if (s[i] == q) { in_quote = true; }
737 else if (s.compare(i + 1, rest.size(), rest) == 0)
738 {
739 substrings.push_back(s.substr(start, i - start));
740 start = i + splitter.size();
741 i = start - 1;
742 }
743 }
744 }
745 if (in_quote)
746 throw Exception::ConversionError(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION,
747 "unbalanced quotation marks in string '" + s + "'");
748 substrings.push_back(s.substr(start));
749 return substrings.size() > 1;
750 }
751
753 template <class StringIterator>
754 inline void concatenate(std::string& target,
755 StringIterator first, StringIterator last,
756 const std::string& glue = "")
757 {
758 if (first == last) { target.clear(); return; }
759 target = *first;
760 for (auto it = ++first; it != last; ++it)
761 {
762 target += glue;
763 target += *it;
764 }
765 }
766
768 template <class StringIterator>
769 inline std::string concatenate(StringIterator first, StringIterator last,
770 const std::string& glue = "")
771 {
772 std::string result;
773 concatenate(result, first, last, glue);
774 return result;
775 }
776
790 template <typename Container>
791 requires requires(const Container& c) { c.begin(); c.end(); }
792 inline std::string concatenate(const Container& container, const std::string& glue = "")
793 {
794 return concatenate(container.begin(), container.end(), glue);
795 }
796
797 } // namespace StringUtils
798
799
800 // =========================================================================
801 // Legacy StringConversions namespace — thin forwarding layer
802 // Prefer StringUtils:: for new code.
803 // =========================================================================
804 namespace StringConversions
805 {
806 inline void append(int i, std::string& target)
807 { StringUtils::appendToStr(i, target); }
808 inline void append(unsigned int i, std::string& target)
809 { StringUtils::appendToStr(i, target); }
810 inline void append(short int i, std::string& target)
811 { StringUtils::appendToStr(i, target); }
812 inline void append(short unsigned int i, std::string& target)
813 { StringUtils::appendToStr(i, target); }
814 inline void append(long int i, std::string& target)
815 { StringUtils::appendToStr(i, target); }
816 inline void append(long unsigned int i, std::string& target)
817 { StringUtils::appendToStr(i, target); }
818 inline void append(long long unsigned int i, std::string& target)
819 { StringUtils::appendToStr(i, target); }
820 inline void append(long long signed int i, std::string& target)
821 { StringUtils::appendToStr(i, target); }
822 inline void append(float f, std::string& target)
823 { StringUtils::appendToStr(f, target); }
824 inline void append(double d, std::string& target)
825 { StringUtils::appendToStr(d, target); }
826 inline void append(long double ld, std::string& target)
827 { StringUtils::appendToStr(ld, target); }
828 inline void appendLowP(float f, std::string& target)
829 { StringUtils::appendToStrLowP(f, target); }
830 inline void appendLowP(double d, std::string& target)
831 { StringUtils::appendToStrLowP(d, target); }
832 inline void appendLowP(long double ld, std::string& target)
833 { StringUtils::appendToStrLowP(ld, target); }
834 inline void append(const DataValue& d, bool full_precision, std::string& target)
835 { StringUtils::appendToStr(d, full_precision, target); }
836
837 template <typename T>
838 inline std::string toString(const T& i)
839 { return StringUtils::toStr(i); }
840 inline std::string toString(float f, bool fp = true)
841 { return StringUtils::toStr(f, fp); }
842 inline std::string toString(double d, bool fp = true)
843 { return StringUtils::toStr(d, fp); }
844 inline std::string toString(long double ld, bool fp = true)
845 { return StringUtils::toStr(ld, fp); }
846 inline std::string toString(const DataValue& d, bool fp = true)
847 { return StringUtils::toStr(d, fp); }
848 inline std::string toString()
849 { return {}; }
850
851 inline std::string toStringLowP(float f) { return StringUtils::toStr(f, false); }
852 inline std::string toStringLowP(double d) { return StringUtils::toStr(d, false); }
853 inline std::string toStringLowP(long double ld) { return StringUtils::toStr(ld, false); }
854
855 } // namespace StringConversions
856
857} // namespace OpenMS
858
859
860// =============================================================================
861// Global operator+ / operator+= for std::string + numeric types
862//
863// Placing these in the global namespace ensures they are found by unqualified
864// lookup regardless of which OpenMS namespace the caller is in.
865// =============================================================================
866
867inline std::string& operator+=(std::string& s, int i)
868{ OpenMS::StringUtils::appendToStr(i, s); return s; }
869inline std::string& operator+=(std::string& s, unsigned int i)
870{ OpenMS::StringUtils::appendToStr(i, s); return s; }
871inline std::string& operator+=(std::string& s, short int i)
872{ OpenMS::StringUtils::appendToStr(i, s); return s; }
873inline std::string& operator+=(std::string& s, short unsigned int i)
874{ OpenMS::StringUtils::appendToStr(i, s); return s; }
875inline std::string& operator+=(std::string& s, long int i)
876{ OpenMS::StringUtils::appendToStr(i, s); return s; }
877inline std::string& operator+=(std::string& s, long unsigned int i)
878{ OpenMS::StringUtils::appendToStr(i, s); return s; }
879inline std::string& operator+=(std::string& s, long long unsigned int i)
880{ OpenMS::StringUtils::appendToStr(i, s); return s; }
881inline std::string& operator+=(std::string& s, long long signed int i)
882{ OpenMS::StringUtils::appendToStr(i, s); return s; }
883inline std::string& operator+=(std::string& s, float f)
884{ OpenMS::StringUtils::appendToStr(f, s); return s; }
885inline std::string& operator+=(std::string& s, double d)
886{ OpenMS::StringUtils::appendToStr(d, s); return s; }
887inline std::string& operator+=(std::string& s, long double ld)
888{ OpenMS::StringUtils::appendToStr(ld, s); return s; }
889
890// operator+ reuses operator+= on a value-copy, enabling move-from-rvalue
891inline std::string operator+(std::string s, int i)
892{ return std::move(s += i); }
893inline std::string operator+(std::string s, unsigned int i)
894{ return std::move(s += i); }
895inline std::string operator+(std::string s, short int i)
896{ return std::move(s += i); }
897inline std::string operator+(std::string s, short unsigned int i)
898{ return std::move(s += i); }
899inline std::string operator+(std::string s, long int i)
900{ return std::move(s += i); }
901inline std::string operator+(std::string s, long unsigned int i)
902{ return std::move(s += i); }
903inline std::string operator+(std::string s, long long unsigned int i)
904{ return std::move(s += i); }
905inline std::string operator+(std::string s, long long signed int i)
906{ return std::move(s += i); }
907inline std::string operator+(std::string s, float f)
908{ return std::move(s += f); }
909inline std::string operator+(std::string s, double d)
910{ return std::move(s += d); }
911inline std::string operator+(std::string s, long double ld)
912{ return std::move(s += ld); }
std::string & operator+=(std::string &s, int i)
Definition StringUtils.h:867
std::string operator+(std::string s, int i)
Definition StringUtils.h:891
Class to hold strings, numeric values, lists of strings and lists of numeric values.
Definition DataValue.h:33
Invalid conversion exception.
Definition Exception.h:331
Int overflow exception.
Definition Exception.h:211
Int underflow exception.
Definition Exception.h:175
Class to hold strings, numeric values, vectors of strings and vectors of numeric values using the stl...
Definition ParamValue.h:31
Definition StringUtils.h:45
static double toDouble(const std::string &s)
Parse double from string (leading/trailing whitespace allowed)
static Int64 toInt64(const std::string &s)
Parse int64 from string (leading/trailing whitespace allowed)
static bool extractDouble(const char *&begin, const char *end, double &target)
static Int32 toInt32(const std::string &s)
Parse int32 from string (leading/trailing whitespace allowed)
static float toFloat(const std::string &s)
Parse float from string (leading/trailing whitespace allowed)
static bool extractInt(const char *&begin, const char *end, int &target)
OpenMS looks in the< code > OPENMS_THERMO_MANAGED_DIR</code > environment variable first
Definition common-cmake-parameters.doxygen:179
int32_t Int32
Signed integer type (32bit)
Definition Types.h:26
int64_t Int64
Signed integer type (64bit)
Definition Types.h:40
uint8_t Byte
Byte type.
Definition Types.h:81
int Int
Signed integer type.
Definition Types.h:72
unsigned int UInt
Unsigned integer type.
Definition Types.h:64
size_t Size
Size type e.g. used as variable which can hold result of size()
Definition Types.h:97
void append(int i, std::string &target)
Definition StringUtils.h:806
void appendLowP(float f, std::string &target)
Definition StringUtils.h:828
std::string toStringLowP(float f)
Definition StringUtils.h:851
std::string toString()
Definition StringUtils.h:848
float toFloat(const std::string &s)
Definition StringUtils.h:169
void appendToStr(int i, std::string &target)
std::string & fillRight(std::string &s, char c, UInt size)
Definition StringUtils.h:469
Int64 toInt64(const std::string &s)
Definition StringUtils.h:168
std::string substituted(std::string s, char from, char to)
substitute on a copy (for chained/rvalue expressions)
Definition StringUtils.h:501
bool hasPrefix(const std::string &s, const std::string &prefix)
Definition StringUtils.h:275
std::string & toUpper(std::string &s)
Definition StringUtils.h:412
std::string chop(const std::string &s, Size n)
Remove n characters from the end; returns empty string if n >= size.
Definition StringUtils.h:383
std::string & trim(std::string &s)
Definition StringUtils.h:394
std::string & unquote(std::string &s, char q='"', QuotingMethod method = QuotingMethod::ESCAPE)
Definition StringUtils.h:568
bool hasSuffix(const std::string &s, const std::string &sfx)
Definition StringUtils.h:284
bool extractDouble(const char *&begin, const char *end, double &target)
Definition StringUtils.h:172
std::string & fillLeft(std::string &s, char c, UInt size)
Definition StringUtils.h:462
std::string & firstToUpper(std::string &s)
Definition StringUtils.h:428
void appendToStrLowP(float f, std::string &target)
std::string suffix(const std::string &s, size_t length)
Definition StringUtils.h:319
std::string substr(const std::string &s, size_t pos=0, size_t n=std::string::npos)
Wrapper around std::string::substr; clamps pos to [0, size].
Definition StringUtils.h:362
bool extractInt(const char *&begin, const char *end, int &target)
Definition StringUtils.h:175
std::string random(UInt length)
Returns a random string of length characters from [0-9a-zA-Z].
bool isQuoted(const std::string &s, char q)
Definition StringUtils.h:547
std::string toLowered(std::string s)
Returns a lower-cased copy of s (for use in chained/rvalue expressions)
Definition StringUtils.h:426
std::string & removeWhitespaces(std::string &s)
Definition StringUtils.h:522
std::string numberLength(double d, UInt n)
Returns a string for d with at most n characters total (scientific notation if needed)
std::string number(double d, UInt n)
Returns a string with exactly n decimal places for d.
std::string prefix(const std::string &s, size_t length)
Definition StringUtils.h:312
const char * skipNonWhitespace(const char *p, const char *p_end)
Returns pointer to first whitespace character in [p, p_end), or p_end.
bool hasSubstring(const std::string &s, const std::string &sub)
Definition StringUtils.h:293
const char * skipWhitespace(const char *p, const char *p_end)
Returns pointer to first non-whitespace character in [p, p_end), or p_end.
std::string trimmed(std::string s)
Returns a trimmed copy of s (for use in chained/rvalue expressions)
Definition StringUtils.h:410
std::string toStr(int i)
Definition StringUtils.h:100
bool split(const std::string &s, char splitter, std::vector< std::string > &substrings, bool quote_protect=false)
Definition StringUtils.h:595
std::string & ensureLastChar(std::string &s, char end)
Definition StringUtils.h:514
void concatenate(std::string &target, StringIterator first, StringIterator last, const std::string &glue="")
Join elements [first, last) with glue between them, storing result in target.
Definition StringUtils.h:754
std::string & simplify(std::string &s)
Definition StringUtils.h:440
std::string & reverse(std::string &s)
Definition StringUtils.h:434
bool has(const std::string &s, Byte byte)
Definition StringUtils.h:300
double toDouble(const std::string &s)
Definition StringUtils.h:170
std::string & toLower(std::string &s)
Definition StringUtils.h:418
std::string & remove(std::string &s, char what)
Definition StringUtils.h:504
std::string toUppered(std::string s)
Returns an upper-cased copy of s (for use in chained/rvalue expressions)
Definition StringUtils.h:424
Int32 toInt32(const std::string &s)
Definition StringUtils.h:167
bool split_quoted(const std::string &s, const std::string &splitter, std::vector< std::string > &substrings, char q='"', QuotingMethod method = QuotingMethod::ESCAPE)
Definition StringUtils.h:691
std::string & quote(std::string &s, char q='"', QuotingMethod method = QuotingMethod::ESCAPE)
Definition StringUtils.h:552
std::string & substitute(std::string &s, char from, char to)
Definition StringUtils.h:476
Main OpenMS namespace.
Definition openswathalgo/include/OpenMS/OPENSWATHALGO/DATAACCESS/ISpectrumAccess.h:19
QuotingMethod
How to handle embedded quotes when quoting strings.
Definition StringUtils.h:38