FINAL CUT
fkey_hashmap.h
1 /***********************************************************************
2 * fkey_hashmap.h - Key sequence hash map access *
3 * *
4 * This file is part of the FINAL CUT widget toolkit *
5 * *
6 * Copyright 2015-2023 Markus Gans *
7 * *
8 * FINAL CUT is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU Lesser General Public License as *
10 * published by the Free Software Foundation; either version 3 of *
11 * the License, or (at your option) any later version. *
12 * *
13 * FINAL CUT is distributed in the hope that it will be useful, but *
14 * WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU Lesser General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU Lesser General Public *
19 * License along with this program. If not, see *
20 * <http://www.gnu.org/licenses/>. *
21 ***********************************************************************/
22 
23 #ifndef FKEYHASHMAP_H
24 #define FKEYHASHMAP_H
25 
26 #if !defined (USE_FINAL_H) && !defined (COMPILE_FINAL_CUT)
27  #error "Only <final/final.h> can be included directly."
28 #endif
29 
30 #include <algorithm>
31 #include <memory>
32 #include <string>
33 #include <unordered_map>
34 
35 #include "final/fc.h"
36 #include "final/input/fkey_map.h"
37 
38 namespace finalcut
39 {
40 
41 namespace fkeyhashmap
42 {
43 
44 namespace internal
45 {
46 
47 struct Const
48 {
49  static auto getMaxHashSize() -> std::size_t
50  {
51  static const auto size = std::max( FKeyMap::getKeyMap().size()
52  , FKeyMap::getKeyCapMap().size() ) * 2;
53  return size;
54  }
55 };
56 
57 //----------------------------------------------------------------------
58 template <typename BufferT>
60 {
61  KeySequence (const char* s, uInt8 l)
62  : string(s)
63  , length(l)
64  { }
65 
66  explicit KeySequence (const BufferT& buf)
67  : buffer(&buf)
68  { }
69 
70  const char* string{nullptr};
71  const uInt8 length{0};
72  const BufferT* buffer{nullptr};
73 };
74 
75 //----------------------------------------------------------------------
76 template <typename IterT>
77 constexpr auto hash_function (IterT iter, const IterT end) -> std::size_t
78 {
79  std::size_t sum = 0;
80 
81  while ( iter != end )
82  {
83  sum += std::size_t(*iter);
84  ++iter;
85  sum += ( iter != end ) ? std::size_t(*iter) << 8 : 0;
86  }
87 
88  return sum % Const::getMaxHashSize();
89 }
90 
91 //----------------------------------------------------------------------
92 template <typename BufferT>
93 constexpr auto hash_function (const BufferT& buf) -> std::size_t
94 {
95  return hash_function (std::begin(buf), std::end(buf));
96 }
97 
98 //----------------------------------------------------------------------
99 template <typename BufferT>
101 {
102  auto operator () (const KeySequence<BufferT>& key) const noexcept -> std::size_t
103  {
104  if ( key.string && ! key.buffer )
105  return hash_function (key.string, key.string + key.length);
106 
107  if ( key.buffer )
108  return hash_function (*key.buffer);
109 
110  return hash_function(std::string("unknown"));
111  }
112 };
113 
114 //----------------------------------------------------------------------
115 template <typename BufferT>
117 {
118  auto operator () ( const KeySequence<BufferT>& lhs
119  , const KeySequence<BufferT>& rhs) const noexcept -> bool
120  {
121  if ( lhs.string && ! lhs.buffer && rhs.string && ! rhs.buffer )
122  {
123  return lhs.length == rhs.length
124  && std::memcmp(lhs.string, rhs.string, rhs.length) == 0;
125  }
126 
127  if ( ! lhs.string && lhs.buffer && rhs.string && ! rhs.buffer )
128  {
129  return lhs.buffer->getSize() == rhs.length
130  && lhs.buffer->strncmp_front(rhs.string, rhs.length);
131  }
132 
133  if ( lhs.string && ! lhs.buffer && ! rhs.string && rhs.buffer )
134  {
135  return lhs.length == rhs.buffer->getSize()
136  && rhs.buffer->strncmp_front(lhs.string, lhs.length);
137  }
138 
139  return false;
140  }
141 };
142 
143 //----------------------------------------------------------------------
144 // Using-declaration
145 template <typename BufferT>
146 using HashMap = std::unordered_map<KeySequence<BufferT>
147  , FKey
150 
151 //----------------------------------------------------------------------
152 template <typename BufferT>
153 auto createKeyCapMap() -> HashMap<BufferT>
154 {
155  const auto& fkey_cap_table = FKeyMap::getKeyCapMap();
156  HashMap<BufferT> fkey_cap_map;
157  fkey_cap_map.reserve(fkey_cap_table.size());
158 
159  for (const auto& item : fkey_cap_table)
160  if ( item.string && item.length != 0 )
161  fkey_cap_map[{item.string, item.length}] = item.num;
162 
163  return fkey_cap_map;
164 }
165 
166 //----------------------------------------------------------------------
167 template <typename BufferT, typename IterT>
168 auto createKeyCapMap (IterT begin, IterT end) -> HashMap<BufferT>
169 {
170  HashMap<BufferT> fkey_cap_map;
171  fkey_cap_map.reserve(std::size_t(end - begin));
172  auto iter = begin;
173 
174  while ( iter != end )
175  {
176  if ( iter->string && iter->length != 0 )
177  fkey_cap_map[{iter->string, iter->length}] = iter->num;
178 
179  ++iter;
180  }
181 
182  return fkey_cap_map;
183 }
184 
185 //----------------------------------------------------------------------
186 template <typename BufferT>
187 auto createKeyMap() -> HashMap<BufferT>
188 {
189  auto& fkey_table = FKeyMap::getKeyMap();
190  HashMap<BufferT> fkey_map;
191  fkey_map.reserve(fkey_table.size());
192 
193  for (auto& item : fkey_table)
194  if ( item.length != 0 ) // Note: item.string is an array and always allocated
195  fkey_map[{item.string.data(), item.length}] = item.num;
196 
197  return fkey_map;
198 }
199 
200 } // namespace internal
201 
202 //----------------------------------------------------------------------
203 template <typename BufferT>
204 auto getKeyCapMap() -> internal::HashMap<BufferT>&
205 {
206  using HashMapType = internal::HashMap<BufferT>;
207  static const auto& fkey_cap_map = std::make_unique<HashMapType>(internal::createKeyCapMap<BufferT>());
208  return *fkey_cap_map;
209 }
210 
211 //----------------------------------------------------------------------
212 template <typename BufferT, typename IterT>
213 void setKeyCapMap (IterT begin, IterT end)
214 {
215  getKeyCapMap<BufferT>() = internal::createKeyCapMap<BufferT>(begin, end);
216 }
217 
218 //----------------------------------------------------------------------
219 template <typename BufferT>
220 auto getKeyMap() -> internal::HashMap<BufferT>&
221 {
222  using HashMapType = internal::HashMap<BufferT>;
223  static const auto& fkey_map = std::make_unique<HashMapType>(internal::createKeyMap<BufferT>());
224  return *fkey_map;
225 }
226 
227 //----------------------------------------------------------------------
228 template <typename BufferT>
229 auto getTermcapKey (const BufferT& char_rbuf) -> FKey
230 {
231  auto& hashmap = getKeyCapMap<BufferT>();
232  auto iter = hashmap.find(internal::KeySequence<BufferT>(char_rbuf));
233 
234  if ( iter != hashmap.end() ) // found
235  return iter->second;
236 
237  return FKey::None;
238 }
239 
240 //----------------------------------------------------------------------
241 template <typename BufferT>
242 auto getKnownKey (const BufferT& char_rbuf) -> FKey
243 {
244  auto& hashmap = getKeyMap<BufferT>();
245  auto iter = hashmap.find(internal::KeySequence<BufferT>(char_rbuf));
246 
247  if ( iter != hashmap.end() ) // found
248  return iter->second;
249 
250  return FKey::None;
251 }
252 
253 } // namespace fkeyhashmap
254 
255 } // namespace finalcut
256 
257 #endif // FKEYHASHMAP_H
Definition: class_template.cpp:25
Definition: fkey_hashmap.h:47