SlHelpers
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 
15 namespace SlHelpers {
16 
26 class GetLine {
27 public:
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  }
50 private:
51  std::string_view m_str;
52 };
53 
57 class String {
58 public:
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 
131  static void eraseAllOf(std::string &s, std::string_view what) {
132  std::erase_if(s, [what](char c) {
133  return what.find(c) != std::string_view::npos;
134  });
135  }
136 
143  static void replaceAll(std::string &s, std::string_view from, std::string_view to) {
144  for (size_t pos = 0; (pos = s.find(from, pos)) != std::string::npos;
145  pos += to.size())
146  s.replace(pos, from.size(), to);
147  }
148 
158  static std::vector<std::string_view>
159  splitSV(std::string_view str,
160  std::string_view delim,
161  std::optional<char> comment = std::nullopt) noexcept
162  {
163  std::vector<std::string_view> res;
164  std::size_t end = 0;
165 
166  do {
167  const auto start = str.find_first_not_of(delim, end);
168  if (start == npos)
169  break;
170 
171  end = str.find_first_of(delim, start);
172  const auto len = (end == npos) ? (str.length() - start) : (end - start);
173  auto token = str.substr(start, len);
174  if (comment && token.starts_with(*comment))
175  break;
176 
177  res.push_back(token);
178  } while (end != npos);
179 
180  return res;
181  }
182 
188  template <typename T>
189  static constexpr T trim(const T &line) noexcept
190  {
191  constexpr const std::string_view spaces{" \n\t\r"};
192  const auto pos1 = line.find_first_not_of(spaces);
193  const auto pos2 = line.find_last_not_of(spaces);
194 
195  if (pos1 == npos)
196  return {};
197 
198  return line.substr(pos1, pos2 - pos1 + 1);
199  }
200 
206  static constexpr bool isHex(std::string_view s) noexcept {
207  return std::all_of(s.cbegin(), s.cend(), ::isxdigit);
208  }
209 
217  template <std::ranges::input_range Range, typename Output>
218  requires requires(std::ostream &out, Output output,
219  std::ranges::range_reference_t<Range> e) {
220  std::invoke(output, out, e);
221  }
222  static void join(std::ostream &out, Range &&iterable, Output output,
223  std::string_view sep = ", ") {
224  bool first = true;
225  for (auto &&e: iterable) {
226  if (!first)
227  out << sep;
228  first = false;
229 
230  std::invoke(output, out, e);
231  }
232  }
233 
241  template <std::ranges::input_range Range>
242  static void join(std::ostream &out, Range &&iterable, std::string_view sep = ", ",
243  std::string_view quote = "") {
244  join(out, std::forward<Range>(iterable),
245  [quote](auto &out, const auto &x) { out << quote << x << quote; },
246  sep);
247  }
248 
254  struct Hash {
256  using is_transparent = void;
257 
262  auto hash(std::string_view sv) const noexcept {
263  return std::hash<std::string_view>{}(sv);
264  }
265 
267  size_t operator()(const char *charp) const noexcept { return hash(charp); }
268 
270  size_t operator()(std::string_view sv) const noexcept { return hash(sv); }
271 
273  size_t operator()(const std::string &s) const noexcept { return hash(s); }
274  };
275 
281  struct Eq {
283  using is_transparent = void;
284 
291  bool operator()(std::string_view a, std::string_view b) const noexcept {
292  return a == b;
293  }
294  };
295 };
296 
297 }
static constexpr T trim(const T &line) noexcept
Trim string (remove surrounding whitespace)
Definition: String.h:189
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:159
Equality test for string and string_view to be used in containers.
Definition: String.h:281
requires requires(std::ostream &out, Output output, std::ranges::range_reference_t< Range > e)
Join iterable into out using separator sep, calling output.
Definition: String.h:218
Hash for string and string_view to be used in hashing containers.
Definition: String.h:254
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:242
static constexpr bool iStartsWith(std::string_view str, std::string_view prefix) noexcept
Like string::starts_with() but ignoring case.
Definition: String.h:104
requires static std::is_integral_v< I > std::optional< I > toNum(std::string_view str, int base=10) noexcept
Convert str to a number.
Definition: String.h:68
static constexpr bool isHex(std::string_view s) noexcept
Is the string consisting of hex number?
Definition: String.h:206
size_t operator()(const std::string &s) const noexcept
Hash string s.
Definition: String.h:273
GetLine(std::string_view str) noexcept
Construct GetLine to parse str.
Definition: String.h:32
Various helpers on strings.
Definition: String.h:57
static bool constexpr iEqual(unsigned char a, unsigned char b) noexcept
Compare two characters ignoring case.
Definition: String.h:77
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
auto hash(std::string_view sv) const noexcept
Hash any kind of string using std::hash.
Definition: String.h:262
void is_transparent
For containers to know this is a transparent hash.
Definition: String.h:256
Parses a string view into lines.
Definition: String.h:26
static constinit const auto npos
A local alias for std::string_view::npos.
Definition: String.h:60
static void replaceAll(std::string &s, std::string_view from, std::string_view to)
Replace all occurrences of from in s with to.
Definition: String.h:143
void is_transparent
For containers to know this is a transparent eq test.
Definition: String.h:283
bool operator()(std::string_view a, std::string_view b) const noexcept
Compare any kinds of two strings a and b.
Definition: String.h:291
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 void eraseAllOf(std::string &s, std::string_view what)
Erase any of characters in what from s.
Definition: String.h:131
size_t operator()(const char *charp) const noexcept
Hash charp.
Definition: String.h:267
size_t operator()(std::string_view sv) const noexcept
Hash string_view sv.
Definition: String.h:270
Definition: Color.h:8