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 usings_char_traits_t>
187 struct test_char_traits<char, usings_char_traits_t>
188 {
189  static bool is_space(typename usings_char_traits_t::value_type ch) noexcept
190  {
191  return std::isspace(static_cast<int>(ch)) != 0;
192  }
193 
194  static bool is_digit(typename usings_char_traits_t::value_type ch) noexcept
195  {
196  return std::isdigit(ch) != 0;
197  }
198 };
199 
200 template<class usings_char_traits_t>
201 struct test_char_traits<wchar_t, usings_char_traits_t>
202 {
203  static bool is_space(typename usings_char_traits_t::value_type ch) noexcept
204  {
205  return std::iswspace(static_cast<wint_t>(ch)) != 0;
206  }
207 
208  static bool is_digit(typename usings_char_traits_t::value_type ch) noexcept
209  {
210  return std::iswdigit(ch) != 0;
211  }
212 };
213 
214 
215 
216 // ----------------------------------------------- transform_char_traits -----------------------------------------------
217 
218 template<class value_t, class usings_char_traits_t>
220 
221 template<class usings_char_traits_t>
222 struct transform_char_traits<char, usings_char_traits_t>
223 {
224  static typename usings_char_traits_t::value_type to_lower(typename usings_char_traits_t::value_type ch) noexcept
225  {
226  return static_cast<char>(std::tolower(ch));
227  }
228 
229  static typename usings_char_traits_t::value_type to_upper(typename usings_char_traits_t::value_type ch) noexcept
230  {
231  return static_cast<char>(std::toupper(ch));
232  }
233 };
234 
235 template<class usings_char_traits_t>
236 struct transform_char_traits<wchar_t, usings_char_traits_t>
237 {
238  static typename usings_char_traits_t::value_type to_lower(typename usings_char_traits_t::value_type ch) noexcept
239  {
240  return std::towlower(ch);
241  }
242 
243  static typename usings_char_traits_t::value_type to_upper(typename usings_char_traits_t::value_type ch) noexcept
244  {
245  return std::towupper(ch);
246  }
247 };
248 
249 
250 
251 // --------------------------------------------------- length_traits ---------------------------------------------------
252 
253 template<class value_t, class usings_char_traits_t>
255 
256 template<class usings_char_traits_t>
257 struct length_traits<char, usings_char_traits_t>
258 {
259  static constexpr typename usings_char_traits_t::size_type length(
260  typename usings_char_traits_t::const_pointer pszStr) noexcept
261  {
262  if (std::is_constant_evaluated())
263  return static_cast<typename usings_char_traits_t::size_type>(qx::strlen(pszStr));
264  else
265  return static_cast<typename usings_char_traits_t::size_type>(std::strlen(pszStr));
266  }
267 };
268 
269 template<class usings_char_traits_t>
270 struct length_traits<wchar_t, usings_char_traits_t>
271 {
272  static constexpr typename usings_char_traits_t::size_type length(
273  typename usings_char_traits_t::const_pointer pszStr) noexcept
274  {
275  if (std::is_constant_evaluated())
276  return static_cast<typename usings_char_traits_t::size_type>(qx::strlen(pszStr));
277  else
278  return static_cast<typename usings_char_traits_t::size_type>(std::wcslen(pszStr));
279  }
280 };
281 
282 
283 
284 // --------------------------------------------------- compare_traits --------------------------------------------------
285 
286 template<class value_t, class usings_char_traits_t>
288 
289 template<class usings_char_traits_t>
290 struct compare_traits<char, usings_char_traits_t>
291 {
292  static int compare(
293  typename usings_char_traits_t::const_pointer pszFirst,
294  typename usings_char_traits_t::const_pointer pszSecond) noexcept
295  {
296  return std::strcmp(pszFirst, pszSecond);
297  }
298 
299  static int compare_n(
300  typename usings_char_traits_t::const_pointer pszFirst,
301  typename usings_char_traits_t::const_pointer pszSecond,
302  typename usings_char_traits_t::size_type nCount) noexcept
303  {
304  return std::strncmp(pszFirst, pszSecond, nCount);
305  }
306 };
307 
308 template<class usings_char_traits_t>
309 struct compare_traits<wchar_t, usings_char_traits_t>
310 {
311  static int compare(
312  typename usings_char_traits_t::const_pointer pszFirst,
313  typename usings_char_traits_t::const_pointer pszSecond) noexcept
314  {
315  return std::wcscmp(pszFirst, pszSecond);
316  }
317 
318  static int compare_n(
319  typename usings_char_traits_t::const_pointer pszFirst,
320  typename usings_char_traits_t::const_pointer pszSecond,
321  typename usings_char_traits_t::size_type nCount) noexcept
322  {
323  return std::wcsncmp(pszFirst, pszSecond, nCount);
324  }
325 };
326 
327 
328 
329 // ------------------------------------------------ format_string_traits -----------------------------------------------
330 
331 template<class value_t, class usings_char_traits_t>
333 {
334  template<class... args_t>
335  using format_string = std::basic_format_string<value_t, args_t...>;
336 };
337 
338 
339 
340 // --------------------------------------------------- format_traits ---------------------------------------------------
341 
342 template<class value_t, class usings_char_traits_t>
344 
345 template<class usings_char_traits_t>
346 struct format_traits<char, usings_char_traits_t>
347 {
348  template<class... args_t>
349  static int sscanf(
350  typename usings_char_traits_t::const_pointer pszString,
351  typename usings_char_traits_t::const_pointer pszFormat,
352  args_t... args) noexcept
353  {
354  QX_PUSH_SUPPRESS_ALL_WARNINGS();
355  return std::sscanf(pszString, pszFormat, args...);
356  QX_POP_SUPPRESS_WARNINGS();
357  }
358 
359  template<class output_it_t, class... args_t>
360  static void format_to(
361  output_it_t itOutput,
362  typename usings_char_traits_t::string_view_type svFormat,
363  const args_t&... args)
364  {
365  std::vformat_to(itOutput, svFormat, std::make_format_args(args...));
366  }
367 };
368 
369 template<class usings_char_traits_t>
370 struct format_traits<wchar_t, usings_char_traits_t>
371 {
372  template<class... args_t>
373  static int sscanf(
374  typename usings_char_traits_t::const_pointer pszString,
375  typename usings_char_traits_t::const_pointer pszFormat,
376  args_t... args) noexcept
377  {
378  QX_PUSH_SUPPRESS_ALL_WARNINGS();
379  return std::swscanf(pszString, pszFormat, args...);
380  QX_POP_SUPPRESS_WARNINGS();
381  }
382 
383  template<class output_it_t, class... args_t>
384  static void format_to(
385  output_it_t itOutput,
386  typename usings_char_traits_t::string_view_type svFormat,
387  const args_t&... args)
388  {
389  std::vformat_to(itOutput, svFormat, std::make_wformat_args(args...));
390  }
391 };
392 
393 template<class... args_t>
394 struct constructor : public args_t...
395 {
396 };
397 
398 /**
399  @brief Common string traits type. User may use it with user-defined traits to override the required behaviour.
400  @tparam value_t - char type
401 **/
402 template<class value_t>
413 
414 } // 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
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:369
uint32_t u32
0 .. 18 446 744 073 709 551 615
Definition: typedefs.h:24