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 © Nick Khrapov, 2021. All right reserved.
7 
8 **/
9 #pragma once
10 
13 #include <qx/macros/config.h>
15 
16 #include <cctype>
17 #include <cstdarg>
18 #include <cstring>
19 #include <cwctype>
20 #include <format>
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>
68 
69 template<class usings_char_traits_t>
70 struct allocation_traits<char, usings_char_traits_t>
71 {
72  static constexpr typename usings_char_traits_t::size_type align() noexcept
73  {
74  return 16;
75  }
76 
77  static constexpr typename usings_char_traits_t::size_type small_string_size() noexcept
78  {
79  return 48;
80  }
81 
82  static constexpr bool shrink_to_fit_when_small() noexcept
83  {
84  return false;
85  }
86 };
87 
88 template<class usings_char_traits_t>
89 struct allocation_traits<wchar_t, usings_char_traits_t>
90 {
91  static constexpr typename usings_char_traits_t::size_type align() noexcept
92  {
93  return 16;
94  }
95 
96  static constexpr typename usings_char_traits_t::size_type small_string_size() noexcept
97  {
98 #if QX_MSVC
99  // sizeof(wchar_t) == 2
100  return 24;
101 #else
102  // sizeof(wchar_t) == 4
103  return 12;
104 #endif
105  }
106 
107  static constexpr bool shrink_to_fit_when_small() noexcept
108  {
109  return false;
110  }
111 };
112 
113 template<class value_t, class usings_char_traits_t>
115 
116 template<class usings_char_traits_t>
117 struct small_string_allocation_traits<char, usings_char_traits_t> : public allocation_traits<char, usings_char_traits_t>
118 {
119  static constexpr typename usings_char_traits_t::size_type small_string_size() noexcept
120  {
121  return 16;
122  }
123 };
124 
125 template<class usings_char_traits_t>
126 struct small_string_allocation_traits<wchar_t, usings_char_traits_t>
127  : public allocation_traits<wchar_t, usings_char_traits_t>
128 {
129  static constexpr typename usings_char_traits_t::size_type small_string_size() noexcept
130  {
131 #if QX_MSVC
132  // sizeof(wchar_t) == 2
133  return 8;
134 #else
135  // sizeof(wchar_t) == 4
136  return 4;
137 #endif
138  }
139 };
140 
141 template<class value_t, class usings_char_traits_t>
143 
144 template<class usings_char_traits_t>
145 struct big_string_allocation_traits<char, usings_char_traits_t> : public allocation_traits<char, usings_char_traits_t>
146 {
147  static constexpr typename usings_char_traits_t::size_type align() noexcept
148  {
149  return 128;
150  }
151 
152  static constexpr typename usings_char_traits_t::size_type small_string_size() noexcept
153  {
154  return 240;
155  }
156 };
157 
158 template<class usings_char_traits_t>
159 struct big_string_allocation_traits<wchar_t, usings_char_traits_t>
160  : public allocation_traits<wchar_t, usings_char_traits_t>
161 {
162  static constexpr typename usings_char_traits_t::size_type align() noexcept
163  {
164  return 128;
165  }
166 
167  static constexpr typename usings_char_traits_t::size_type small_string_size() noexcept
168  {
169 #if QX_MSVC
170  // sizeof(wchar_t) == 2
171  return 120;
172 #else
173  // sizeof(wchar_t) == 4
174  return 60;
175 #endif
176  }
177 };
178 
179 
180 
181 // -------------------------------------------------- test_char_traits -------------------------------------------------
182 
183 template<class value_t, class usings_char_traits_t>
185 
186 template<class value_t>
188 {
189  static bool is_eng_alpha(value_t ch) noexcept
190  {
191  return (ch >= QX_CHAR_PREFIX(value_t, 'A') && ch <= QX_CHAR_PREFIX(value_t, 'Z'))
192  || (ch >= QX_CHAR_PREFIX(value_t, 'a') && ch <= QX_CHAR_PREFIX(value_t, 'z'));
193  }
194 };
195 
196 template<class usings_char_traits_t>
197 struct test_char_traits<char, usings_char_traits_t> : base_test_char_traits<char>
198 {
199  static bool is_space(typename usings_char_traits_t::value_type ch) noexcept
200  {
201  return std::isspace(static_cast<int>(ch)) != 0;
202  }
203 
204  static bool is_digit(typename usings_char_traits_t::value_type ch) noexcept
205  {
206  return std::isdigit(ch) != 0;
207  }
208 };
209 
210 template<class usings_char_traits_t>
211 struct test_char_traits<wchar_t, usings_char_traits_t> : base_test_char_traits<wchar_t>
212 {
213  static bool is_space(typename usings_char_traits_t::value_type ch) noexcept
214  {
215  return std::iswspace(static_cast<wint_t>(ch)) != 0;
216  }
217 
218  static bool is_digit(typename usings_char_traits_t::value_type ch) noexcept
219  {
220  return std::iswdigit(ch) != 0;
221  }
222 };
223 
224 
225 
226 // ----------------------------------------------- transform_char_traits -----------------------------------------------
227 
228 template<class value_t, class usings_char_traits_t>
230 
231 template<class usings_char_traits_t>
232 struct transform_char_traits<char, usings_char_traits_t>
233 {
234  static typename usings_char_traits_t::value_type to_lower(typename usings_char_traits_t::value_type ch) noexcept
235  {
236  return static_cast<char>(std::tolower(ch));
237  }
238 
239  static typename usings_char_traits_t::value_type to_upper(typename usings_char_traits_t::value_type ch) noexcept
240  {
241  return static_cast<char>(std::toupper(ch));
242  }
243 };
244 
245 template<class usings_char_traits_t>
246 struct transform_char_traits<wchar_t, usings_char_traits_t>
247 {
248  static typename usings_char_traits_t::value_type to_lower(typename usings_char_traits_t::value_type ch) noexcept
249  {
250  return std::towlower(ch);
251  }
252 
253  static typename usings_char_traits_t::value_type to_upper(typename usings_char_traits_t::value_type ch) noexcept
254  {
255  return std::towupper(ch);
256  }
257 };
258 
259 
260 
261 // --------------------------------------------------- length_traits ---------------------------------------------------
262 
263 template<class value_t, class usings_char_traits_t>
265 
266 template<class usings_char_traits_t>
267 struct length_traits<char, usings_char_traits_t>
268 {
269  static constexpr typename usings_char_traits_t::size_type length(
270  typename usings_char_traits_t::const_pointer pszStr) noexcept
271  {
272  if (std::is_constant_evaluated())
273  return static_cast<typename usings_char_traits_t::size_type>(qx::strlen(pszStr));
274  else
275  return static_cast<typename usings_char_traits_t::size_type>(std::strlen(pszStr));
276  }
277 };
278 
279 template<class usings_char_traits_t>
280 struct length_traits<wchar_t, usings_char_traits_t>
281 {
282  static constexpr typename usings_char_traits_t::size_type length(
283  typename usings_char_traits_t::const_pointer pszStr) noexcept
284  {
285  if (std::is_constant_evaluated())
286  return static_cast<typename usings_char_traits_t::size_type>(qx::strlen(pszStr));
287  else
288  return static_cast<typename usings_char_traits_t::size_type>(std::wcslen(pszStr));
289  }
290 };
291 
292 
293 
294 // --------------------------------------------------- compare_traits --------------------------------------------------
295 
296 template<class value_t, class usings_char_traits_t>
298 
299 template<class usings_char_traits_t>
300 struct compare_traits<char, usings_char_traits_t>
301 {
302  static int compare(
303  typename usings_char_traits_t::const_pointer pszFirst,
304  typename usings_char_traits_t::const_pointer pszSecond) noexcept
305  {
306  return std::strcmp(pszFirst, pszSecond);
307  }
308 
309  static int compare_n(
310  typename usings_char_traits_t::const_pointer pszFirst,
311  typename usings_char_traits_t::const_pointer pszSecond,
312  typename usings_char_traits_t::size_type nCount) noexcept
313  {
314  return std::strncmp(pszFirst, pszSecond, nCount);
315  }
316 };
317 
318 template<class usings_char_traits_t>
319 struct compare_traits<wchar_t, usings_char_traits_t>
320 {
321  static int compare(
322  typename usings_char_traits_t::const_pointer pszFirst,
323  typename usings_char_traits_t::const_pointer pszSecond) noexcept
324  {
325  return std::wcscmp(pszFirst, pszSecond);
326  }
327 
328  static int compare_n(
329  typename usings_char_traits_t::const_pointer pszFirst,
330  typename usings_char_traits_t::const_pointer pszSecond,
331  typename usings_char_traits_t::size_type nCount) noexcept
332  {
333  return std::wcsncmp(pszFirst, pszSecond, nCount);
334  }
335 };
336 
337 
338 
339 // ------------------------------------------------ format_string_traits -----------------------------------------------
340 
341 template<class value_t, class usings_char_traits_t>
343 {
344  template<class... args_t>
345  using format_string = std::basic_format_string<value_t, args_t...>;
346 };
347 
348 
349 
350 // --------------------------------------------------- format_traits ---------------------------------------------------
351 
352 template<class value_t, class usings_char_traits_t>
354 
355 template<class usings_char_traits_t>
356 struct format_traits<char, usings_char_traits_t>
357 {
358  template<class... args_t>
359  static int sscanf(
360  typename usings_char_traits_t::const_pointer pszString,
361  typename usings_char_traits_t::const_pointer pszFormat,
362  args_t&&... args) noexcept
363  {
364  QX_PUSH_SUPPRESS_ALL_WARNINGS();
365  return std::sscanf(pszString, pszFormat, std::forward<args_t>(args)...);
366  QX_POP_SUPPRESS_WARNINGS();
367  }
368 
369  template<class output_it_t, class... args_t>
370  static void format_to(
371  output_it_t itOutput,
372  typename usings_char_traits_t::string_view_type svFormat,
373  args_t&&... args)
374  {
375  std::vformat_to(itOutput, svFormat, std::make_format_args(args...));
376  }
377 };
378 
379 template<class usings_char_traits_t>
380 struct format_traits<wchar_t, usings_char_traits_t>
381 {
382  template<class... args_t>
383  static int sscanf(
384  typename usings_char_traits_t::const_pointer pszString,
385  typename usings_char_traits_t::const_pointer pszFormat,
386  args_t&&... args) noexcept
387  {
388  QX_PUSH_SUPPRESS_ALL_WARNINGS();
389  return std::swscanf(pszString, pszFormat, std::forward<args_t>(args)...);
390  QX_POP_SUPPRESS_WARNINGS();
391  }
392 
393  template<class output_it_t, class... args_t>
394  static void format_to(
395  output_it_t itOutput,
396  typename usings_char_traits_t::string_view_type svFormat,
397  args_t&&... args)
398  {
399  std::vformat_to(itOutput, svFormat, std::make_wformat_args(args...));
400  }
401 };
402 
403 template<class... args_t>
404 struct constructor : public args_t...
405 {
406 };
407 
408 /**
409  @brief Common string traits type. User may use it with user-defined traits to override the required behaviour.
410  @tparam value_t - char type
411 **/
412 template<class value_t>
423 
424 } // namespace qx::string_traits
constexpr size_t djb2a_hash(const value_t *pszStr, size_t nSeed, size_t nLen)
djb2a hash
Definition: string_utils.h:26
#define QX_CHAR_PREFIX(value_t, ch)
Chose witch of prefixes add to char : L or none.
Definition: string_utils.h:261
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...
Definition: string_utils.h:373
std::uint32_t u32
0 .. 18 446 744 073 709 551 615
Definition: typedefs.h:23