libfly  6.2.2
C++20 utility library for Linux, macOS, and Windows
classifier.hpp
1 #pragma once
2 
3 #include "fly/types/string/concepts.hpp"
4 #include "fly/types/string/detail/traits.hpp"
5 #include "fly/types/string/literals.hpp"
6 
7 #include <string>
8 
9 namespace fly::detail {
10 
17 template <fly::StandardCharacter CharType>
19 {
21  using size_type = typename traits::size_type;
22  using view_type = typename traits::view_type;
23  using int_type = typename traits::int_type;
24 
25 public:
36  template <fly::StandardStringLike T>
37  static constexpr size_type size(T &&value);
38 
46  template <std::size_t N>
47  static constexpr size_type size(const CharType (&value)[N]);
48 
61  static constexpr bool is_alpha(CharType ch);
62 
75  static constexpr bool is_upper(CharType ch);
76 
89  static constexpr bool is_lower(CharType ch);
90 
103  static constexpr CharType to_upper(CharType ch);
104 
117  static constexpr CharType to_lower(CharType ch);
118 
130  static constexpr bool is_digit(CharType ch);
131 
143  static constexpr bool is_x_digit(CharType ch);
144 
157  static constexpr bool is_space(CharType ch);
158 
159 private:
168  static constexpr CharType unify_az_characters(CharType ch);
169 
170  static constexpr const auto s_null_terminator = FLY_CHR(CharType, '\0');
171  static constexpr const auto s_zero = FLY_CHR(CharType, '0');
172  static constexpr const auto s_upper_a = FLY_CHR(CharType, 'A');
173  static constexpr const auto s_upper_z = FLY_CHR(CharType, 'Z');
174  static constexpr const auto s_upper_f = FLY_CHR(CharType, 'F');
175  static constexpr const auto s_lower_a = FLY_CHR(CharType, 'a');
176  static constexpr const auto s_lower_z = FLY_CHR(CharType, 'z');
177  static constexpr const auto s_space = FLY_CHR(CharType, ' ');
178  static constexpr const auto s_form_feed = FLY_CHR(CharType, '\f');
179  static constexpr const auto s_line_feed = FLY_CHR(CharType, '\n');
180  static constexpr const auto s_carriage_return = FLY_CHR(CharType, '\r');
181  static constexpr const auto s_horizontal_tab = FLY_CHR(CharType, '\t');
182  static constexpr const auto s_vertical_tab = FLY_CHR(CharType, '\v');
183 
184  static constexpr const auto s_case_bit = static_cast<int_type>(0x20);
185  static constexpr const auto s_case_mask = static_cast<int_type>(~s_case_bit);
186 };
187 
188 //==================================================================================================
189 template <fly::StandardCharacter CharType>
190 template <fly::StandardStringLike T>
191 constexpr auto BasicClassifier<CharType>::size(T &&value) -> size_type
192 {
193  using U = std::remove_cvref_t<T>;
194 
195  if constexpr (std::is_array_v<U> || std::is_pointer_v<U>)
196  {
197  return std::char_traits<CharType>::length(std::forward<T>(value));
198  }
199  else
200  {
201  return value.size();
202  }
203 }
204 
205 //==================================================================================================
206 template <fly::StandardCharacter CharType>
207 template <std::size_t N>
208 constexpr auto BasicClassifier<CharType>::size(const CharType (&value)[N]) -> size_type
209 {
210  static_assert(N > 0, "Character arrays must have non-zero size");
211  return N - ((value[N - 1] == s_null_terminator) ? 1 : 0);
212 }
213 
214 //==================================================================================================
215 template <fly::StandardCharacter CharType>
216 constexpr bool BasicClassifier<CharType>::is_alpha(CharType ch)
217 {
218  return is_upper(unify_az_characters(ch));
219 }
220 
221 //==================================================================================================
222 template <fly::StandardCharacter CharType>
223 constexpr bool BasicClassifier<CharType>::is_upper(CharType ch)
224 {
225  return (ch >= s_upper_a) && (ch <= s_upper_z);
226 }
227 
228 //==================================================================================================
229 template <fly::StandardCharacter CharType>
230 constexpr bool BasicClassifier<CharType>::is_lower(CharType ch)
231 {
232  return (ch >= s_lower_a) && (ch <= s_lower_z);
233 }
234 
235 //==================================================================================================
236 template <fly::StandardCharacter CharType>
237 constexpr CharType BasicClassifier<CharType>::to_upper(CharType ch)
238 {
239  if (is_lower(ch))
240  {
241  ch = static_cast<CharType>(static_cast<int_type>(ch) & s_case_mask);
242  }
243 
244  return ch;
245 }
246 
247 //==================================================================================================
248 template <fly::StandardCharacter CharType>
249 constexpr CharType BasicClassifier<CharType>::to_lower(CharType ch)
250 {
251  if (is_upper(ch))
252  {
253  ch = static_cast<CharType>(static_cast<int_type>(ch) | s_case_bit);
254  }
255 
256  return ch;
257 }
258 
259 //==================================================================================================
260 template <fly::StandardCharacter CharType>
261 constexpr bool BasicClassifier<CharType>::is_digit(CharType ch)
262 {
263  return (ch ^ s_zero) < 10;
264 }
265 
266 //==================================================================================================
267 template <fly::StandardCharacter CharType>
268 constexpr bool BasicClassifier<CharType>::is_x_digit(CharType ch)
269 {
270  const auto alpha = unify_az_characters(ch);
271  return is_digit(ch) || ((alpha >= s_upper_a) && (alpha <= s_upper_f));
272 }
273 
274 //==================================================================================================
275 template <fly::StandardCharacter CharType>
276 constexpr bool BasicClassifier<CharType>::is_space(CharType ch)
277 {
278  return (ch == s_space) || (ch == s_form_feed) || (ch == s_line_feed) ||
279  (ch == s_carriage_return) || (ch == s_horizontal_tab) || (ch == s_vertical_tab);
280 }
281 
282 //==================================================================================================
283 template <fly::StandardCharacter CharType>
284 constexpr CharType BasicClassifier<CharType>::unify_az_characters(CharType ch)
285 {
286  return static_cast<CharType>(static_cast<int_type>(ch) & s_case_mask);
287 }
288 
289 } // namespace fly::detail
Definition: classifier.hpp:19
static constexpr bool is_digit(CharType ch)
Definition: classifier.hpp:261
static constexpr bool is_lower(CharType ch)
Definition: classifier.hpp:230
static constexpr bool is_space(CharType ch)
Definition: classifier.hpp:276
static constexpr CharType to_upper(CharType ch)
Definition: classifier.hpp:237
static constexpr CharType to_lower(CharType ch)
Definition: classifier.hpp:249
static constexpr bool is_alpha(CharType ch)
Definition: classifier.hpp:216
static constexpr bool is_x_digit(CharType ch)
Definition: classifier.hpp:268
static constexpr size_type size(T &&value)
static constexpr size_type size(const CharType(&value)[N])
static constexpr bool is_upper(CharType ch)
Definition: classifier.hpp:223
Definition: traits.hpp:18