Line | Branch | Exec | Source |
---|---|---|---|
1 | // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- | ||
2 | // vi: set et ts=4 sw=4 sts=4: | ||
3 | // | ||
4 | // SPDX-FileCopyrightInfo: Copyright © DuMux Project contributors, see AUTHORS.md in root folder | ||
5 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
6 | // | ||
7 | |||
8 | /*! | ||
9 | * \file | ||
10 | * \ingroup Core | ||
11 | * \brief Helpers for working with strings | ||
12 | */ | ||
13 | |||
14 | #ifndef DUMUX_COMMON_STRING_UTILITIES_HH | ||
15 | #define DUMUX_COMMON_STRING_UTILITIES_HH | ||
16 | |||
17 | #include <vector> | ||
18 | #include <string> | ||
19 | #include <string_view> | ||
20 | #include <tuple> | ||
21 | |||
22 | namespace Dumux { | ||
23 | |||
24 | /* | ||
25 | * \brief Tokenize a string splitting at a given delimiter | ||
26 | * \ingroup Core | ||
27 | * \param str a string to be tokenized | ||
28 | * \param delim a set of delimiter characters separating the tokens | ||
29 | * \note this works without copying the original string, make sure that string | ||
30 | * does not go out of scope! | ||
31 | * \note The delimiter characters cannot appear within any of the tokens | ||
32 | * | ||
33 | * Examples: | ||
34 | * - tokenize("bla&foo&&&bar", "&") -> {"bla", "foo", "bar"} | ||
35 | * - tokenize(" a b ", " ") -> {"a", "b"} | ||
36 | * - tokenize(str, " \n\t") -> split at whitespace (and removes all whitespace) | ||
37 | */ | ||
38 | 31 | std::vector<std::string_view> tokenize(std::string_view str, std::string_view delim) | |
39 | { | ||
40 | 213 | const auto token = [&](std::size_t pos){ | |
41 | 182 | const auto start = str.find_first_not_of(delim, pos); | |
42 | 182 | const auto end = str.find_first_of(delim, start); | |
43 | 364 | return std::make_pair(start, end); | |
44 | 213 | }; | |
45 | |||
46 | 31 | std::vector<std::string_view> tokens; | |
47 |
2/2✓ Branch 3 taken 60 times.
✓ Branch 4 taken 31 times.
|
273 | for (auto [start, end] = token(0); start != end; std::tie(start, end) = token(end)) |
48 |
2/6✓ Branch 1 taken 60 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 60 times.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
|
60 | tokens.emplace_back(str.substr(start, end-start)); |
49 | 31 | return tokens; | |
50 | } | ||
51 | |||
52 | /* | ||
53 | * \brief Split a string at a given separator string | ||
54 | * \ingroup Core | ||
55 | * \param str a string to be split | ||
56 | * \param delim a set of delimiter characters separating the tokens | ||
57 | * \param removeEmpty if empty string between two separator should be removed from the result | ||
58 | * \note this works without copying the original string, make sure that string | ||
59 | * does not go out of scope! | ||
60 | * | ||
61 | * Examples: | ||
62 | * - split("| Hello | world |", "|") -> {"", " Hello ", " world ", ""} | ||
63 | * - split("| Hello | world |", "|", true) -> {" Hello ", " world "} | ||
64 | * - split("blafoobla", "foo") -> {"bla", "bla"} | ||
65 | * - split("blafoobla", "bla") -> {"", "foo", ""} | ||
66 | * - split("blafoobla", "bla", true) -> {"foo"} | ||
67 | */ | ||
68 | 92 | std::vector<std::string_view> split(std::string_view str, std::string_view delim, bool removeEmpty = false) | |
69 | { | ||
70 | 92 | const auto token = [&](std::size_t pos){ | |
71 | ✗ | const auto end = str.find(delim, pos); | |
72 | 279 | return std::make_pair(pos, end); | |
73 | 279 | }; | |
74 | |||
75 | 92 | std::vector<std::string_view> split; | |
76 |
2/2✓ Branch 1 taken 187 times.
✓ Branch 2 taken 92 times.
|
653 | for (auto [start, end] = token(0); start != std::string::npos; std::tie(start, end) = token(start)) |
77 | { | ||
78 |
5/6✓ Branch 1 taken 187 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 184 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 2 times.
|
187 | if (auto&& sub = str.substr(start, end-start); !removeEmpty || !sub.empty()) |
79 |
1/2✓ Branch 1 taken 185 times.
✗ Branch 2 not taken.
|
185 | split.emplace_back(std::move(sub)); |
80 | |||
81 | // skip to after the delimiter | ||
82 |
2/2✓ Branch 0 taken 95 times.
✓ Branch 1 taken 92 times.
|
187 | start = (end != std::string::npos) ? end + delim.size() : end; |
83 | } | ||
84 | 92 | return split; | |
85 | } | ||
86 | |||
87 | } // end namespace Dumux | ||
88 | |||
89 | #endif | ||
90 |