OSSIA
Open Scenario System for Interactive Application
case_insensitive.hpp
1 #pragma once
2 #include <ossia/detail/config.hpp>
3 
5 #include <ossia/detail/hash.hpp>
6 #include <ossia/detail/hash_map.hpp>
7 
8 namespace ossia
9 {
10 static constexpr unsigned char ascii_tolower(unsigned char c) noexcept
11 {
12  constexpr unsigned char A = 'A', Z = 'Z', a = 'a';
13  if(c >= A && c <= Z)
14  return c - (A - a);
15  else
16  return c;
17 }
18 
19 struct ascii_tolower_less
20 {
21  constexpr bool operator()(unsigned char c1, unsigned char c2) const noexcept
22  {
23  return ascii_tolower(c1) < ascii_tolower(c2);
24  }
25 };
26 
27 struct ascii_tolower_equal
28 {
29  constexpr bool operator()(unsigned char c1, unsigned char c2) const noexcept
30  {
31  return ascii_tolower(c1) == ascii_tolower(c2);
32  }
33 };
34 
35 struct case_insensitive_comparator
36 {
37  using is_transparent = std::true_type;
38  bool operator()(std::string_view s1, std::string_view s2) const noexcept
39  {
40  return std::lexicographical_compare(
41  s1.begin(), s1.end(), s2.begin(), s2.end(), ascii_tolower_less{});
42  }
43 };
44 
45 struct case_insensitive_hash
46 {
47  static constexpr int buffer_size = 64;
48  using is_transparent = std::true_type;
49  using is_avalanching = std::true_type;
50 
51  uint64_t operator()(std::string_view s1) const noexcept
52  {
53  namespace wyhash = ankerl::unordered_dense::detail::wyhash;
54 
55  uint64_t res = UINT64_C(0xff51afd7ed558ccd);
56  unsigned char buf[buffer_size + 1];
57  const char* ptr = s1.data();
58  uint64_t remaining = s1.size();
59 
60  while(remaining > 0)
61  {
62  if(remaining >= buffer_size)
63  {
64  for(int i = 0; i < buffer_size; i++)
65  buf[i] = ascii_tolower(ptr[i]);
66  res = wyhash::mix(res, wyhash::hash(buf, buffer_size));
67  remaining -= buffer_size;
68  ptr += buffer_size;
69  }
70  else
71  {
72  [[likely]];
73  for(uint64_t i = 0; i < remaining; i++)
74  buf[i] = ascii_tolower(ptr[i]);
75  res = wyhash::mix(res, wyhash::hash(buf, remaining));
76  remaining = 0;
77  }
78  }
79 
80  return res;
81  }
82 };
83 
84 struct case_insensitive_equal
85 {
86  using is_transparent = std::true_type;
87  constexpr bool operator()(std::string_view s1, std::string_view s2) const noexcept
88  {
89  return std::equal(s1.begin(), s1.end(), s2.begin(), s2.end(), ascii_tolower_equal{});
90  }
91 };
92 
93 template <typename Value>
94 using case_insensitive_string_map
95  = ossia::hash_map<std::string, Value, case_insensitive_hash, case_insensitive_equal>;
96 }
Definition: git_info.h:7