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