qxLib
string_traits.h
Go to the documentation of this file.
1 /**
2 
3  @file string_traits.h
4  @author Khrapov
5  @date 24.03.2020
6  @copyright (c) Nick Khrapov, 2021. All right reserved.
7 
8 **/
9 #pragma once
10 
13 #include <qx/macros/config.h>
16 
17 #include <cctype>
18 #include <cstdarg>
19 #include <cstring>
20 #include <cwctype>
21 #include <sstream>
22 
23 namespace qx::string_traits
24 {
25 
26 // ------------------------------------------------- usings_char_traits ------------------------------------------------
27 
28 template<class value_t>
30 {
31  using value_type = value_t;
32  using pointer = value_t*;
33  using const_pointer = const value_t*;
34  using reference = value_t&;
35  using const_reference = const value_t&;
36  using difference_type = std::ptrdiff_t;
37  using size_type = size_t;
38  using string_view_type = basic_string_view<value_t>;
39 };
40 
41 
42 
43 // -------------------------------------------------- hash_char_traits -------------------------------------------------
44 
45 template<class value_t, class usings_char_traits_t>
47 {
48  static constexpr typename usings_char_traits_t::size_type hash_function(
49  typename usings_char_traits_t::const_pointer pszStr,
50  size_t nSeed,
51  typename usings_char_traits_t::size_type nLen) noexcept
52  {
53  return djb2a_hash(pszStr, nSeed, nLen);
54  }
55 
56  static constexpr u32 hash_seed() noexcept
57  {
58  return 5712564;
59  }
60 };
61 
62 
63 
64 // ------------------------------------------------- allocation_traits -------------------------------------------------
65 
66 template<class value_t, class usings_char_traits_t, size_t nSmallStringBytes, bool bShrinkToFitWhenSmall>
67  requires(nSmallStringBytes % sizeof(value_t) == 0)
68 struct allocation_traits
69 {
70  static constexpr typename usings_char_traits_t::size_type small_string_size() noexcept
71  {
72  return nSmallStringBytes / sizeof(value_t);
73  }
74 
75  static constexpr bool shrink_to_fit_when_small() noexcept
76  {
77  return bShrinkToFitWhenSmall;
78  }
79 };
80 
81 
82 
83 // -------------------------------------------------- test_char_traits -------------------------------------------------
84 
85 template<class value_t, class usings_char_traits_t>
87 
88 template<class value_t>
90 {
91  static bool is_eng_alpha(value_t ch) noexcept
92  {
93  return (ch >= QX_CHAR_PREFIX(value_t, 'A') && ch <= QX_CHAR_PREFIX(value_t, 'Z'))
94  || (ch >= QX_CHAR_PREFIX(value_t, 'a') && ch <= QX_CHAR_PREFIX(value_t, 'z'));
95  }
96 };
97 
98 template<class usings_char_traits_t>
99 struct test_char_traits<char, usings_char_traits_t> : base_test_char_traits<char>
100 {
101  static bool is_space(typename usings_char_traits_t::value_type ch) noexcept
102  {
103  return std::isspace(static_cast<int>(ch)) != 0;
104  }
105 
106  static bool is_digit(typename usings_char_traits_t::value_type ch) noexcept
107  {
108  return std::isdigit(ch) != 0;
109  }
110 };
111 
112 template<class usings_char_traits_t>
113 struct test_char_traits<wchar_t, usings_char_traits_t> : base_test_char_traits<wchar_t>
114 {
115  static bool is_space(typename usings_char_traits_t::value_type ch) noexcept
116  {
117  return std::iswspace(static_cast<wint_t>(ch)) != 0;
118  }
119 
120  static bool is_digit(typename usings_char_traits_t::value_type ch) noexcept
121  {
122  return std::iswdigit(ch) != 0;
123  }
124 };
125 
126 
127 
128 // ----------------------------------------------- transform_char_traits -----------------------------------------------
129 
130 template<class value_t, class usings_char_traits_t>
132 
133 template<class usings_char_traits_t>
134 struct transform_char_traits<char, usings_char_traits_t>
135 {
136  static typename usings_char_traits_t::value_type to_lower(typename usings_char_traits_t::value_type ch) noexcept
137  {
138  return static_cast<char>(std::tolower(ch));
139  }
140 
141  static typename usings_char_traits_t::value_type to_upper(typename usings_char_traits_t::value_type ch) noexcept
142  {
143  return static_cast<char>(std::toupper(ch));
144  }
145 };
146 
147 template<class usings_char_traits_t>
148 struct transform_char_traits<wchar_t, usings_char_traits_t>
149 {
150  static typename usings_char_traits_t::value_type to_lower(typename usings_char_traits_t::value_type ch) noexcept
151  {
152  return std::towlower(ch);
153  }
154 
155  static typename usings_char_traits_t::value_type to_upper(typename usings_char_traits_t::value_type ch) noexcept
156  {
157  return std::towupper(ch);
158  }
159 };
160 
161 
162 
163 // --------------------------------------------------- length_traits ---------------------------------------------------
164 
165 template<class value_t, class usings_char_traits_t>
167 
168 template<class usings_char_traits_t>
169 struct length_traits<char, usings_char_traits_t>
170 {
171  static constexpr typename usings_char_traits_t::size_type length(
172  typename usings_char_traits_t::const_pointer pszStr) noexcept
173  {
174  if (std::is_constant_evaluated())
175  return static_cast<typename usings_char_traits_t::size_type>(qx::strlen(pszStr));
176  else
177  return static_cast<typename usings_char_traits_t::size_type>(std::strlen(pszStr));
178  }
179 };
180 
181 template<class usings_char_traits_t>
182 struct length_traits<wchar_t, usings_char_traits_t>
183 {
184  static constexpr typename usings_char_traits_t::size_type length(
185  typename usings_char_traits_t::const_pointer pszStr) noexcept
186  {
187  if (std::is_constant_evaluated())
188  return static_cast<typename usings_char_traits_t::size_type>(qx::strlen(pszStr));
189  else
190  return static_cast<typename usings_char_traits_t::size_type>(std::wcslen(pszStr));
191  }
192 };
193 
194 
195 
196 // --------------------------------------------------- compare_traits --------------------------------------------------
197 
198 template<class value_t, class usings_char_traits_t>
200 
201 template<class usings_char_traits_t>
202 struct compare_traits<char, usings_char_traits_t>
203 {
204  static int compare(
205  typename usings_char_traits_t::const_pointer pszFirst,
206  typename usings_char_traits_t::const_pointer pszSecond) noexcept
207  {
208  return std::strcmp(pszFirst, pszSecond);
209  }
210 
211  static int compare_n(
212  typename usings_char_traits_t::const_pointer pszFirst,
213  typename usings_char_traits_t::const_pointer pszSecond,
214  typename usings_char_traits_t::size_type nCount) noexcept
215  {
216  return std::strncmp(pszFirst, pszSecond, nCount);
217  }
218 };
219 
220 template<class usings_char_traits_t>
221 struct compare_traits<wchar_t, usings_char_traits_t>
222 {
223  static int compare(
224  typename usings_char_traits_t::const_pointer pszFirst,
225  typename usings_char_traits_t::const_pointer pszSecond) noexcept
226  {
227  return std::wcscmp(pszFirst, pszSecond);
228  }
229 
230  static int compare_n(
231  typename usings_char_traits_t::const_pointer pszFirst,
232  typename usings_char_traits_t::const_pointer pszSecond,
233  typename usings_char_traits_t::size_type nCount) noexcept
234  {
235  return std::wcsncmp(pszFirst, pszSecond, nCount);
236  }
237 };
238 
239 
240 
241 // ------------------------------------------------ format_string_traits -----------------------------------------------
242 
243 template<class value_t, class usings_char_traits_t>
245 {
246  template<class... args_t>
247  using format_string = QX_FMT_NS::basic_format_string<value_t, args_t...>;
248 };
249 
250 
251 
252 // --------------------------------------------------- format_traits ---------------------------------------------------
253 
254 template<class value_t, class usings_char_traits_t>
256 
257 template<class usings_char_traits_t>
258 struct format_traits<char, usings_char_traits_t>
259 {
260  static constexpr typename usings_char_traits_t::size_type nMemoryBufferSize = 1024;
261 
262  template<class... args_t>
263  static auto make_format_args(args_t&... args)
264  {
265  return QX_FMT_NS::make_format_args(args...);
266  }
267 
268  template<class... args_t>
269  static int sscanf(
270  typename usings_char_traits_t::const_pointer pszString,
271  typename usings_char_traits_t::const_pointer pszFormat,
272  args_t&&... args) noexcept
273  {
274  QX_PUSH_SUPPRESS_ALL_WARNINGS();
275  return std::sscanf(pszString, pszFormat, std::forward<args_t>(args)...);
276  QX_POP_SUPPRESS_WARNINGS();
277  }
278 };
279 
280 template<class usings_char_traits_t>
281 struct format_traits<wchar_t, usings_char_traits_t>
282 {
283  static constexpr typename usings_char_traits_t::size_type nMemoryBufferSize =
284 #if QX_WIN
285  512;
286 #else
287  256;
288 #endif
289 
290  template<class... args_t>
291  static auto make_format_args(args_t&... args)
292  {
293  return QX_FMT_NS::make_wformat_args(args...);
294  }
295 
296  template<class... args_t>
297  static int sscanf(
298  typename usings_char_traits_t::const_pointer pszString,
299  typename usings_char_traits_t::const_pointer pszFormat,
300  args_t&&... args) noexcept
301  {
302  QX_PUSH_SUPPRESS_ALL_WARNINGS();
303  return std::swscanf(pszString, pszFormat, std::forward<args_t>(args)...);
304  QX_POP_SUPPRESS_WARNINGS();
305  }
306 };
307 
308 namespace details
309 {
310 
311 template<
312  class value_t,
313  class usings_traits_t = usings_traits<value_t>,
314  class hash_traits_t = hash_traits<value_t, usings_traits_t>,
315  class allocation_traits_t = allocation_traits<value_t, usings_traits_t, 64, false>,
316  class test_char_traits_t = test_char_traits<value_t, usings_traits_t>,
317  class transform_char_traits_t = transform_char_traits<value_t, usings_traits_t>,
318  class length_traits_t = length_traits<value_t, usings_traits_t>,
319  class compare_traits_t = compare_traits<value_t, usings_traits_t>,
320  class format_string_traits_t = format_string_traits<value_t, usings_traits_t>,
321  class format_traits_t = format_traits<value_t, usings_traits_t>>
322 struct builder
323 {
324  template<class... args_t>
325  struct constructor : public args_t...
326  {
327  };
328 
329  struct type
330  : constructor<
331  usings_traits_t,
332  hash_traits_t,
333  allocation_traits_t,
334  test_char_traits_t,
335  transform_char_traits_t,
336  length_traits_t,
337  compare_traits_t,
338  format_string_traits_t,
339  format_traits_t>
340  {
341  using builder_type = builder;
342  };
343 
344  template<class trait_override_t>
345  using with_usings = builder<
346  value_t,
347  trait_override_t,
348  hash_traits_t,
349  allocation_traits_t,
350  test_char_traits_t,
351  transform_char_traits_t,
352  length_traits_t,
353  compare_traits_t,
354  format_string_traits_t,
355  format_traits_t>;
356 
357  template<class trait_override_t>
358  using with_hash = builder<
359  value_t,
360  usings_traits_t,
361  trait_override_t,
362  allocation_traits_t,
363  test_char_traits_t,
364  transform_char_traits_t,
365  length_traits_t,
366  compare_traits_t,
367  format_string_traits_t,
368  format_traits_t>;
369 
370  template<class trait_override_t>
371  using with_allocation = builder<
372  value_t,
373  usings_traits_t,
374  hash_traits_t,
375  trait_override_t,
376  test_char_traits_t,
377  transform_char_traits_t,
378  length_traits_t,
379  compare_traits_t,
380  format_string_traits_t,
381  format_traits_t>;
382 
383  template<class trait_override_t>
384  using with_test_char = builder<
385  value_t,
386  usings_traits_t,
387  hash_traits_t,
388  allocation_traits_t,
389  trait_override_t,
390  transform_char_traits_t,
391  length_traits_t,
392  compare_traits_t,
393  format_string_traits_t,
394  format_traits_t>;
395 
396  template<class trait_override_t>
398  value_t,
399  usings_traits_t,
400  hash_traits_t,
401  allocation_traits_t,
402  test_char_traits_t,
403  trait_override_t,
404  length_traits_t,
405  compare_traits_t,
406  format_string_traits_t,
407  format_traits_t>;
408 
409  template<class trait_override_t>
410  using with_length = builder<
411  value_t,
412  usings_traits_t,
413  hash_traits_t,
414  allocation_traits_t,
415  test_char_traits_t,
416  transform_char_traits_t,
417  trait_override_t,
418  compare_traits_t,
419  format_string_traits_t,
420  format_traits_t>;
421 
422  template<class trait_override_t>
423  using with_compare = builder<
424  value_t,
425  usings_traits_t,
426  hash_traits_t,
427  allocation_traits_t,
428  test_char_traits_t,
429  transform_char_traits_t,
430  length_traits_t,
431  trait_override_t,
432  format_string_traits_t,
433  format_traits_t>;
434 
435  template<class trait_override_t>
436  using with_format_string = builder<
437  value_t,
438  usings_traits_t,
439  hash_traits_t,
440  allocation_traits_t,
441  test_char_traits_t,
442  transform_char_traits_t,
443  length_traits_t,
444  compare_traits_t,
445  trait_override_t,
446  format_traits_t>;
447 
448  template<class trait_override_t>
449  using with_format = builder<
450  value_t,
451  usings_traits_t,
452  hash_traits_t,
453  allocation_traits_t,
454  test_char_traits_t,
455  transform_char_traits_t,
456  length_traits_t,
457  compare_traits_t,
458  format_string_traits_t,
459  trait_override_t>;
460 };
461 
462 } // namespace details
463 
464 template<class value_t>
465 using default_traits = typename details::builder<value_t>::type;
466 
467 template<class traits_t>
468 struct traits_builder : traits_t::builder_type
469 {
470 };
471 
472 template<class value_t>
473 using small_traits = typename traits_builder<default_traits<value_t>>::template with_allocation<
474  allocation_traits<value_t, usings_traits<value_t>, 32, false>>::type;
475 
476 template<class value_t>
477 using big_traits = typename traits_builder<default_traits<value_t>>::template with_allocation<
478  allocation_traits<value_t, usings_traits<value_t>, 128, false>>::type;
479 
480 template<class value_t>
481 using huge_traits = typename traits_builder<default_traits<value_t>>::template with_allocation<
482  allocation_traits<value_t, usings_traits<value_t>, 256, false>>::type;
483 
484 } // namespace qx::string_traits
requires(same_variadic_args_v< args_t... >) const expr auto coalesce(args_t &&... args)
Coalesce function, C# a ?? b analogue.
Definition: coalesce.inl:57
Static assert macros.
constexpr size_t djb2a_hash(const value_t *pszStr, size_t nSeed, size_t nLen)
djb2a hash
#define QX_CHAR_PREFIX(value_t, ch)
Chose witch of prefixes add to char : L or none.
Definition: string_utils.h:128
constexpr std::size_t strlen(const value_t *psz)
Naive but constexpr string length algorithm, for runtime prefer std::strlen as there are may be a lot...
std::uint32_t u32
0 .. 18 446 744 073 709 551 615
Definition: typedefs.h:23