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