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 <string>
12#include <vector>
13
14namespace SlHelpers {
15
25class GetLine {
26public:
31 GetLine(std::string_view str) noexcept : m_str(str) {}
32
37 std::optional<std::string_view> get() noexcept {
38 if (m_str.empty())
39 return std::nullopt;
40
41 const auto eol = m_str.find('\n');
42 const auto last = eol == std::string_view::npos;
43 auto line = last ? m_str : m_str.substr(0, eol);
44
45 m_str.remove_prefix(last ? m_str.size() : eol + 1);
46
47 return line;
48 }
49private:
50 std::string_view m_str;
51};
52
56class String {
57public:
59 inline static constinit const auto npos = std::string_view::npos;
60 static_assert(std::string_view::npos == std::string::npos);
61
62 String() = delete;
63
65 template <typename I = unsigned>
66 requires std::is_integral_v<I>
67 static std::optional<I> toNum(std::string_view str, int base = 10) noexcept
68 {
69 I num;
70 if (std::from_chars(str.data(), str.data() + str.size(), num, base).ec != std::errc())
71 return std::nullopt;
72 return num;
73 }
74
81 static constexpr std::string_view::size_type
82 iFind(std::string_view str, std::string_view sub) noexcept {
83 if (str.empty() && sub.empty())
84 return 0;
85 const auto it = std::search(str.begin(), str.end(), sub.begin(), sub.end(),
86 [](char ch1, char ch2) {
87 return std::tolower(static_cast<unsigned char>(ch1)) ==
88 std::tolower(static_cast<unsigned char>(ch2));
89 });
90 if (it == str.end())
91 return npos;
92 return it - str.begin();
93 }
94
102 [[deprecated]] static std::vector<std::string>
103 split(std::string str, const std::string &delim,
104 const std::optional<char> &comment = std::nullopt) noexcept {
105 std::vector<std::string> res;
106
107 auto tok = ::strtok(str.data(), delim.c_str());
108 while (tok) {
109 if (comment && tok[0] == *comment)
110 break;
111 res.push_back(tok);
112 tok = ::strtok(nullptr, delim.c_str());
113 }
114
115 return res;
116 }
117
127 static std::vector<std::string_view>
128 splitSV(std::string_view str,
129 std::string_view delim,
130 std::optional<char> comment = std::nullopt) noexcept
131 {
132 std::vector<std::string_view> res;
133 std::size_t end = 0;
134
135 do {
136 const auto start = str.find_first_not_of(delim, end);
137 if (start == npos)
138 break;
139
140 end = str.find_first_of(delim, start);
141 const auto len = (end == npos) ? (str.length() - start) : (end - start);
142 auto token = str.substr(start, len);
143 if (comment && !token.empty() && token[0] == *comment)
144 break;
145
146 res.push_back(token);
147 } while (end != npos);
148
149 return res;
150 }
151
157 template <typename T>
158 static constexpr T trim(const T &line) noexcept
159 {
160 constexpr const std::string_view spaces{" \n\t\r"};
161 const auto pos1 = line.find_first_not_of(spaces);
162 const auto pos2 = line.find_last_not_of(spaces);
163
164 if (pos1 == npos)
165 return {};
166
167 return line.substr(pos1, pos2 - pos1 + 1);
168 }
169
175 static constexpr bool isHex(std::string_view s) noexcept {
176 return std::all_of(s.cbegin(), s.cend(), ::isxdigit);
177 }
178
186 template <std::ranges::input_range Range, typename Output>
187 requires requires(std::ostream &out, Output output,
188 std::ranges::range_reference_t<Range> e) {
189 std::invoke(output, out, e);
190 }
191 static void join(std::ostream &out, Range &&iterable, Output output,
192 std::string_view sep = ", ") {
193 bool first = true;
194 for (auto &&e: iterable) {
195 if (!first)
196 out << sep;
197 first = false;
198
199 std::invoke(output, out, e);
200 }
201 }
202
210 template <std::ranges::input_range Range>
211 static void join(std::ostream &out, Range &&iterable, std::string_view sep = ", ",
212 std::string_view quote = "") {
213 join(out, std::forward<Range>(iterable),
214 [quote](auto &out, const auto &x) { out << quote << x << quote; },
215 sep);
216 }
217
223 struct Hash {
225 using is_transparent = void;
226
231 auto hash(std::string_view sv) const noexcept {
232 return std::hash<std::string_view>{}(sv);
233 }
234
236 size_t operator()(const char *charp) const noexcept { return hash(charp); }
237
239 size_t operator()(std::string_view sv) const noexcept { return hash(sv); }
240
242 size_t operator()(const std::string &s) const noexcept { return hash(s); }
243 };
244
250 struct Eq {
252 using is_transparent = void;
253
260 bool operator()(std::string_view a, std::string_view b) const noexcept {
261 return a == b;
262 }
263 };
264};
265
266}
GetLine(std::string_view str) noexcept
Construct GetLine to parse str.
Definition String.h:31
std::optional< std::string_view > get() noexcept
Read one line.
Definition String.h:37
static std::optional< I > toNum(std::string_view str, int base=10) noexcept
Convert str to a number.
Definition String.h:67
static constinit const auto npos
A local alias for std::string_view::npos.
Definition String.h:59
static constexpr T trim(const T &line) noexcept
Trim string (remove surrounding whitespace).
Definition String.h:158
static constexpr bool isHex(std::string_view s) noexcept
Is the string consisting of hex number?
Definition String.h:175
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:128
static std::vector< std::string > split(std::string str, const std::string &delim, const std::optional< char > &comment=std::nullopt) noexcept
Split a string into vector of strings, DO NOT USE THIS.
Definition String.h:103
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:82
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:191
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:211
Equality test for string and string_view to be used in containers.
Definition String.h:250
bool operator()(std::string_view a, std::string_view b) const noexcept
Compare any kinds of two strings a and b.
Definition String.h:260
void is_transparent
For containers to know this is a transparent eq test.
Definition String.h:252
Hash for string and string_view to be used in hashing containers.
Definition String.h:223
size_t operator()(const std::string &s) const noexcept
Hash string s.
Definition String.h:242
size_t operator()(const char *charp) const noexcept
Hash charp.
Definition String.h:236
size_t operator()(std::string_view sv) const noexcept
Hash string_view sv.
Definition String.h:239
void is_transparent
For containers to know this is a transparent hash.
Definition String.h:225
auto hash(std::string_view sv) const noexcept
Hash any kind of string using std::hash.
Definition String.h:231