SlHelpers
Loading...
Searching...
No Matches
String.h
1// SPDX-License-Identifier: GPL-2.0-only
2
3#pragma once
4
5#include <algorithm>
6#include <charconv>
7#include <cstring>
8#include <cctype>
9#include <functional>
10#include <optional>
11#include <ranges>
12#include <string>
13#include <vector>
14
15namespace SlHelpers {
16
26class GetLine {
27public:
32 GetLine(std::string_view str) noexcept : m_str(str) {}
33
38 std::optional<std::string_view> get() noexcept {
39 if (m_str.empty())
40 return std::nullopt;
41
42 const auto eol = m_str.find('\n');
43 const auto last = eol == std::string_view::npos;
44 auto line = last ? m_str : m_str.substr(0, eol);
45
46 m_str.remove_prefix(last ? m_str.size() : eol + 1);
47
48 return line;
49 }
50private:
51 std::string_view m_str;
52};
53
57class String {
58public:
60 inline static constinit const auto npos = std::string_view::npos;
61 static_assert(std::string_view::npos == std::string::npos);
62
63 String() = delete;
64
66 template <typename I = unsigned>
67 requires std::is_integral_v<I>
68 static std::optional<I> toNum(std::string_view str, int base = 10) noexcept
69 {
70 I num;
71 if (std::from_chars(str.data(), str.data() + str.size(), num, base).ec != std::errc())
72 return std::nullopt;
73 return num;
74 }
75
77 static bool constexpr iEqual(unsigned char a, unsigned char b) noexcept {
78 return std::tolower(a) == std::tolower(b);
79 }
80
87 static constexpr std::string_view::size_type
88 iFind(std::string_view str, std::string_view sub) noexcept {
89 if (str.empty() && sub.empty())
90 return 0;
91 const auto it = std::search(str.begin(), str.end(), sub.begin(), sub.end(), iEqual);
92 if (it == str.end())
93 return npos;
94 return it - str.begin();
95 }
96
103 static constexpr bool
104 iStartsWith(std::string_view str, std::string_view prefix) noexcept {
105 if (str.size() < prefix.size())
106 return false;
107
108 return std::ranges::equal(str | std::views::take(prefix.size()), prefix, iEqual);
109 }
110
117 static constexpr bool
118 iEndsWith(std::string_view str, std::string_view suffix) noexcept {
119 if (str.size() < suffix.size())
120 return false;
121
122 return std::ranges::equal(str | std::views::drop(str.size() - suffix.size()),
123 suffix, iEqual);
124 }
125
135 static std::vector<std::string_view>
136 splitSV(std::string_view str,
137 std::string_view delim,
138 std::optional<char> comment = std::nullopt) noexcept
139 {
140 std::vector<std::string_view> res;
141 std::size_t end = 0;
142
143 do {
144 const auto start = str.find_first_not_of(delim, end);
145 if (start == npos)
146 break;
147
148 end = str.find_first_of(delim, start);
149 const auto len = (end == npos) ? (str.length() - start) : (end - start);
150 auto token = str.substr(start, len);
151 if (comment && token.starts_with(*comment))
152 break;
153
154 res.push_back(token);
155 } while (end != npos);
156
157 return res;
158 }
159
165 template <typename T>
166 static constexpr T trim(const T &line) noexcept
167 {
168 constexpr const std::string_view spaces{" \n\t\r"};
169 const auto pos1 = line.find_first_not_of(spaces);
170 const auto pos2 = line.find_last_not_of(spaces);
171
172 if (pos1 == npos)
173 return {};
174
175 return line.substr(pos1, pos2 - pos1 + 1);
176 }
177
183 static constexpr bool isHex(std::string_view s) noexcept {
184 return std::all_of(s.cbegin(), s.cend(), ::isxdigit);
185 }
186
194 template <std::ranges::input_range Range, typename Output>
195 requires requires(std::ostream &out, Output output,
196 std::ranges::range_reference_t<Range> e) {
197 std::invoke(output, out, e);
198 }
199 static void join(std::ostream &out, Range &&iterable, Output output,
200 std::string_view sep = ", ") {
201 bool first = true;
202 for (auto &&e: iterable) {
203 if (!first)
204 out << sep;
205 first = false;
206
207 std::invoke(output, out, e);
208 }
209 }
210
218 template <std::ranges::input_range Range>
219 static void join(std::ostream &out, Range &&iterable, std::string_view sep = ", ",
220 std::string_view quote = "") {
221 join(out, std::forward<Range>(iterable),
222 [quote](auto &out, const auto &x) { out << quote << x << quote; },
223 sep);
224 }
225
231 struct Hash {
233 using is_transparent = void;
234
239 auto hash(std::string_view sv) const noexcept {
240 return std::hash<std::string_view>{}(sv);
241 }
242
244 size_t operator()(const char *charp) const noexcept { return hash(charp); }
245
247 size_t operator()(std::string_view sv) const noexcept { return hash(sv); }
248
250 size_t operator()(const std::string &s) const noexcept { return hash(s); }
251 };
252
258 struct Eq {
260 using is_transparent = void;
261
268 bool operator()(std::string_view a, std::string_view b) const noexcept {
269 return a == b;
270 }
271 };
272};
273
274}
GetLine(std::string_view str) noexcept
Construct GetLine to parse str.
Definition String.h:32
std::optional< std::string_view > get() noexcept
Read one line.
Definition String.h:38
static constinit const auto npos
A local alias for std::string_view::npos.
Definition String.h:60
static constexpr T trim(const T &line) noexcept
Trim string (remove surrounding whitespace).
Definition String.h:166
static constexpr bool iStartsWith(std::string_view str, std::string_view prefix) noexcept
Like string::starts_with() but ignoring case.
Definition String.h:104
static constexpr bool isHex(std::string_view s) noexcept
Is the string consisting of hex number?
Definition String.h:183
static std::vector< std::string_view > splitSV(std::string_view str, std::string_view delim, std::optional< char > comment=std::nullopt) noexcept
Split str by delim into a vector, ignoring everything after comment.
Definition String.h:136
static constexpr std::string_view::size_type iFind(std::string_view str, std::string_view sub) noexcept
Like string::find() but ignoring case.
Definition String.h:88
static void join(std::ostream &out, Range &&iterable, Output output, std::string_view sep=", ")
Join iterable into out using separator sep, calling output.
Definition String.h:199
static constexpr bool iEndsWith(std::string_view str, std::string_view suffix) noexcept
Like string::ends_with() but ignoring case.
Definition String.h:118
static bool constexpr iEqual(unsigned char a, unsigned char b) noexcept
Compare two characters ignoring case.
Definition String.h:77
static std::optional< I > toNum(std::string_view str, int base=10) noexcept
Convert str to a number.
Definition String.h:68
static void join(std::ostream &out, Range &&iterable, std::string_view sep=", ", std::string_view quote="")
Join iterable into out using separator sep and quoting quote.
Definition String.h:219
Equality test for string and string_view to be used in containers.
Definition String.h:258
bool operator()(std::string_view a, std::string_view b) const noexcept
Compare any kinds of two strings a and b.
Definition String.h:268
void is_transparent
For containers to know this is a transparent eq test.
Definition String.h:260
Hash for string and string_view to be used in hashing containers.
Definition String.h:231
size_t operator()(const std::string &s) const noexcept
Hash string s.
Definition String.h:250
size_t operator()(const char *charp) const noexcept
Hash charp.
Definition String.h:244
size_t operator()(std::string_view sv) const noexcept
Hash string_view sv.
Definition String.h:247
void is_transparent
For containers to know this is a transparent hash.
Definition String.h:233
auto hash(std::string_view sv) const noexcept
Hash any kind of string using std::hash.
Definition String.h:239