General Utility Library for C++14  2.11
substring_checks.h
Go to the documentation of this file.
1 
23 #ifndef GUL14_SUBSTRING_CHECKS_H_
24 #define GUL14_SUBSTRING_CHECKS_H_
25 
26 #include "gul14/case_ascii.h"
27 #include "gul14/internal.h"
28 #include "gul14/string_view.h"
29 
30 namespace gul14 {
31 
51 constexpr inline bool contains(string_view haystack, string_view needle) noexcept
52 {
53  return haystack.find(needle) != string_view::npos;
54 }
55 
68 constexpr inline bool contains(string_view haystack, char needle) noexcept
69 {
70  return haystack.find(needle) != string_view::npos;
71 }
72 
85 constexpr inline bool ends_with(string_view str, string_view suffix) noexcept
86 {
87  const auto hsl = str.length();
88  const auto sl = suffix.length();
89 
90  return hsl >= sl && str.compare(hsl - sl, sl, suffix) == 0;
91 }
92 
104 constexpr inline bool ends_with(string_view str, char c) noexcept
105 {
106  return !str.empty() && str.back() == c;
107 }
108 
121 constexpr inline bool starts_with(string_view str, string_view prefix) noexcept
122 {
123  const auto hsl = str.length();
124  const auto hl = prefix.length();
125 
126  return hsl >= hl && string_view{ str.data(), hl }.compare(prefix) == 0;
127 }
128 
140 constexpr inline bool starts_with(string_view str, char c) noexcept
141 {
142  return !str.empty() && str.front() == c;
143 }
144 
145 //
146 // Case insensitive variants following
147 //
148 
165 constexpr inline bool equals_nocase(string_view str1, string_view str2) noexcept
166 {
167  if (str1.size() != str2.size())
168  return false;
169 
170  // Hand-rolled version of std::equal() to maintain constexprness prior to C++20
171  auto it1 = str1.cbegin();
172  auto it2 = str2.cbegin();
173 
174  while (it1 != str1.cend())
175  {
176  if (lowercase_ascii(*it1) != lowercase_ascii(*it2))
177  return false;
178 
179  ++it1;
180  ++it2;
181  }
182 
183  return true;
184 }
185 
207 constexpr inline bool contains_nocase(string_view haystack, string_view needle) noexcept
208 {
209  auto const haysize = haystack.size();
210  auto const needlesize = needle.size();
211  if (haysize < needlesize)
212  return false;
213  for (std::size_t i = 0; i <= haysize - needlesize; ++i) {
214  auto j = needlesize;
215  while (j-- > 0) {
216  if (lowercase_ascii(haystack[j]) != lowercase_ascii(needle[j]))
217  break;
218  }
219  if (j == std::size_t(-1)) {
220  return true;
221  }
222  haystack.remove_prefix(1);
223  }
224  return false;
225 }
226 
241 constexpr inline bool contains_nocase(string_view haystack, char needle) noexcept
242 {
243  needle = lowercase_ascii(needle);
244  while (not haystack.empty()) {
245  if (lowercase_ascii(haystack.front()) == needle)
246  return true;
247  haystack.remove_prefix(1);
248  }
249  return false;
250 }
251 
267 constexpr inline bool ends_with_nocase(string_view str, string_view suffix) noexcept
268 {
269  while (not str.empty()) {
270  if (suffix.empty())
271  return true;
272  if (lowercase_ascii(str.back()) != lowercase_ascii(suffix.back()))
273  return false;
274  str.remove_suffix(1);
275  suffix.remove_suffix(1);
276  }
277  return suffix.empty();
278 }
279 
293 constexpr inline bool ends_with_nocase(string_view str, char c) noexcept
294 {
295  return !str.empty() && lowercase_ascii(str.back()) == lowercase_ascii(c);
296 }
297 
313 constexpr inline bool starts_with_nocase(string_view str, string_view prefix) noexcept
314 {
315  while (not str.empty()) {
316  if (prefix.empty())
317  return true;
318  if (lowercase_ascii(str.front()) != lowercase_ascii(prefix.front()))
319  return false;
320  str.remove_prefix(1);
321  prefix.remove_prefix(1);
322  }
323  return prefix.empty();
324 }
325 
339 constexpr inline bool starts_with_nocase(string_view str, char c) noexcept
340 {
341  return !str.empty() && lowercase_ascii(str.front()) == lowercase_ascii(c);
342 }
343 
345 
346 } // namespace gul14
347 
348 #endif
349 
350 /* vim:set expandtab softtabstop=4 tabstop=4 shiftwidth=4 textwidth=90 cindent: */
Declarations of lowercase_ascii(), lowercase_ascii_inplace(), uppercase_ascii(), and uppercase_ascii_...
constexpr char lowercase_ascii(char c) noexcept
Return the ASCII lowercase equivalent of the given character (or the unchanged character,...
Definition: case_ascii.h:48
constexpr bool equals_nocase(string_view str1, string_view str2) noexcept
Determine whether a string is equal to another one, making no distinction between upper and lower cas...
Definition: substring_checks.h:165
constexpr bool ends_with(string_view str, string_view suffix) noexcept
Determine whether a string ends with another string.
Definition: substring_checks.h:85
constexpr bool contains_nocase(string_view haystack, string_view needle) noexcept
Determine whether a string contains another string.
Definition: substring_checks.h:207
constexpr bool starts_with_nocase(string_view str, string_view prefix) noexcept
Determine whether a string starts with another string.
Definition: substring_checks.h:313
constexpr bool ends_with_nocase(string_view str, string_view suffix) noexcept
Determine whether a string ends with another string.
Definition: substring_checks.h:267
constexpr bool starts_with(string_view str, string_view prefix) noexcept
Determine whether a string starts with another string.
Definition: substring_checks.h:121
constexpr bool contains(string_view haystack, string_view needle) noexcept
Determine whether a string contains another string.
Definition: substring_checks.h:51
Definition of macros used internally by GUL.
Namespace gul14 contains all functions and classes of the General Utility Library.
Definition: doxygen.h:26
Provides a gul14::string_view that is fully compatible with C++17's std::string_view.