qxLib
string_utils.h
Go to the documentation of this file.
1 /**
2 
3  @file string_utils.h
4  @author Khrapov
5  @date 17.10.2020
6  @copyright (c) Nick Khrapov, 2021. All right reserved.
7 
8 **/
9 #pragma once
10 
11 #include <qx/macros/config.h>
12 #include <qx/typedefs.h>
13 
14 namespace qx
15 {
16 
17 /**
18  @brief djb2a hash
19  @tparam value_t - char type
20  @param pszStr - string for hashing
21  @param nSeed - seed for hashing
22  @param nLen - string length
23  @retval - 32bit unsigned value
24 **/
25 template<class value_t>
26 constexpr size_t djb2a_hash(const value_t* pszStr, size_t nSeed, size_t nLen);
27 
28 /**
29  @brief djb2a hash
30  @tparam value_t - char type
31  @param pszStr - string for hashing (zero terminated)
32  @param nSeed - seed for hashing
33  @retval - 32bit unsigned value
34 **/
35 template<class value_t>
36 constexpr size_t djb2a_hash(const value_t* pszStr, size_t nSeed = 0);
37 
38 /**
39  @brief Murmur nHash
40  @details https://en.wikipedia.org/wiki/MurmurHash
41  https://softwareengineering.stackexchange.com/questions/49550/which-hashing-algorithm-is-best-for-uniqueness-and-speed
42  @tparam value_t - char type
43  @param pStr - string for hashing
44  @param nSeed - seed for hashing
45  @param nLen - string length
46  @retval - 32bit unsigned value
47 **/
48 template<class value_t>
49 constexpr size_t murmur_32_hash(const value_t* pStr, size_t nSeed, size_t nLen) noexcept;
50 
51 /**
52  @brief Compares string 1 with string 2
53  @tparam fwd_it_1_t - string 1 iterator type
54  @tparam fwd_it_2_t - string 2 iterator type
55  @param itBegin1 - string 1 begin iterator
56  @param itEnd1 - string 1 end iterator
57  @param itBegin2 - string 2 begin iterator
58  @param itEnd2 - string 2 end iterator
59  @retval - < 0 the first character that does not match has a lower value in str 1 than in str 2
60  0 the contents of both strings are equal
61  > 0 the first character that does not match has a greater value in str 1 than in str 2
62 **/
63 template<class fwd_it_1_t, class fwd_it_2_t>
64 constexpr int iter_strcmp(fwd_it_1_t itBegin1, fwd_it_1_t itEnd1, fwd_it_2_t itBegin2, fwd_it_2_t itEnd2) noexcept;
65 
66 /**
67  @brief Constexpr compare two strings
68  @tparam value_t - char type
69  @param pszLeft - first string (zero terminated)
70  @param pszRight - second string (zero terminated)
71  @retval - < 0 the first character that does not match has a lower value in ptr1 than in ptr2
72  0 the contents of both strings are equal
73  > 0 the first character that does not match has a greater value in ptr1 than in ptr2
74 **/
75 template<class value_t>
76 constexpr int strcmp(const value_t* pszLeft, const value_t* pszRight);
77 
78 namespace details
79 {
80 
81 template<class value_t, size_t N>
82 constexpr const auto& choose_str_prefix(const char (&c)[N], const wchar_t (&w)[N]) noexcept;
83 
84 template<class value_t>
85 constexpr value_t choose_char_prefix(char, wchar_t) noexcept;
86 
87 template<>
88 constexpr char choose_char_prefix<char>(char c, wchar_t) noexcept;
89 
90 template<>
91 constexpr wchar_t choose_char_prefix<wchar_t>(char, wchar_t w) noexcept;
92 
93 } // namespace details
94 
95 } // namespace qx
96 
97 //==============================================================================
98 
99 #define _QX_TO_WCHAR(x) L##x
100 
101 #if QX_MSVC
102  #define _QX_TO_WSTRING(x) __LPREFIX(x)
103 #else
104  #define _QX_TO_WSTRING(x) _QX_TO_WCHAR(x)
105 #endif
106 
107 /**
108  @def QX_TO_WSTRING
109  @brief Convert char* to wchar_t*
110  @param str - string to apply
111 **/
112 #define QX_TO_WSTRING(str) _QX_TO_WSTRING(str)
113 
114 /**
115  @def QX_STR_PREFIX
116  @brief Chose witch of prefixes add to string : L or none
117  @param value_t - char type
118  @param str - string to apply
119 **/
120 #define QX_STR_PREFIX(value_t, str) qx::details::choose_str_prefix<value_t>(str, QX_TO_WSTRING(str))
121 
122 /**
123  @def QX_CHAR_PREFIX
124  @brief Chose witch of prefixes add to char : L or none
125  @param value_t - char type
126  @param ch - string to apply
127 **/
128 #define QX_CHAR_PREFIX(value_t, ch) qx::details::choose_char_prefix<value_t>(ch, _QX_TO_WCHAR(ch))
129 
130 //==============================================================================
131 
132 /*
133  Static string comparisons
134 */
135 #define QX_STATIC_ASSERT_STR_EQ(a, b) static_assert(qx::strcmp((a), (b)) == 0)
136 #define QX_STATIC_ASSERT_STR_NE(a, b) static_assert(qx::strcmp((a), (b)) != 0)
137 #define QX_STATIC_ASSERT_STR_LT(a, b) static_assert(qx::strcmp((a), (b)) < 0)
138 #define QX_STATIC_ASSERT_STR_LE(a, b) static_assert(qx::strcmp((a), (b)) <= 0)
139 #define QX_STATIC_ASSERT_STR_GT(a, b) static_assert(qx::strcmp((a), (b)) > 0)
140 #define QX_STATIC_ASSERT_STR_GE(a, b) static_assert(qx::strcmp((a), (b)) >= 0)
141 
142 //==============================================================================
143 
144 namespace qx
145 {
146 
147 /**
148  @brief Get format specifier for type
149  @tparam value_t - char type
150  @tparam T - target type
151  @retval - format specifier or nullptr
152 **/
153 template<class value_t, class T>
154 constexpr const value_t* get_format_specifier() noexcept;
155 
156 /**
157  @brief Naive but constexpr string length algorithm,
158  for runtime prefer std::strlen as there are may be a lot of optimizations
159  @tparam value_t - char type
160  @param psz - pointer to string zero terminated
161  @retval - string length
162 **/
163 template<class value_t>
164 constexpr std::size_t strlen(const value_t* psz);
165 
166 } // namespace qx
167 
constexpr size_t djb2a_hash(const value_t *pszStr, size_t nSeed, size_t nLen)
djb2a hash
constexpr int iter_strcmp(fwd_it_1_t itBegin1, fwd_it_1_t itEnd1, fwd_it_2_t itBegin2, fwd_it_2_t itEnd2) noexcept
Compares string 1 with string 2.
constexpr size_t murmur_32_hash(const value_t *pStr, size_t nSeed, size_t nLen) noexcept
Murmur nHash.
constexpr int strcmp(const value_t *pszLeft, const value_t *pszRight)
Constexpr compare two strings.