cheshirekow  v0.1.0
kwargs.h
Go to the documentation of this file.
1 
6 #ifndef KWARGS_H_
7 #define KWARGS_H_
8 
9 #include <cstdint>
10 
12 namespace kw {
13 
15 template <uint64_t Tag, typename T>
16 struct Arg {
17  T v;
18  Arg(T v) : v(v) {}
19  constexpr bool IsTagged(uint64_t query){ return query == Tag; }
20 };
21 
23 template<uint32_t N>
24 inline constexpr uint64_t Hash(const char (&string)[N]);
25 
27 template <typename T>
28 struct RefWrap {
29  T& v;
30  RefWrap(T& v) : v(v) {}
31 };
32 
34 template <typename T>
35 struct ConstRefWrap {
36  const T& v;
37  ConstRefWrap(const T& v) : v(v) {}
38 };
39 
41 template <typename T>
42 RefWrap<T> Ref(T& v){ return RefWrap<T>(v); }
43 
45 template <typename T>
46 const ConstRefWrap<T> ConstRef(const T& v) { return ConstRefWrap<T>(v); }
47 
50 template <uint64_t Tag>
51 struct Key {
52  template <typename T>
53  Arg<Tag,T> operator=(T v) { return v; }
54 
55  template <typename T>
56  Arg<Tag,T&> operator=(RefWrap<T> vw) { return vw.v; }
57 
58  template <typename T>
60 };
61 
64 template <uint64_t Tag, typename... Args>
65 struct ContainsTag {};
66 
69 template <uint64_t Tag, typename Default, typename... Args>
70 struct TypeOfTagDefault {};
71 
72 template <typename... Args>
73 struct ParamPack;
74 
77 template <uint64_t Tag, bool exists, typename Default, typename... Args>
78 struct GetImpl{};
79 
82 template <uint64_t Tag, typename Default, typename... Args>
83 inline typename TypeOfTagDefault<Tag,Default,Args...>::Result
84  Get(ParamPack<Args...>& pack, Default d) {
85  return
86  GetImpl<Tag,ContainsTag<Tag,Args...>::result,Default,Args...>::Get(pack,d);
87 }
88 
91 template <uint64_t Tag, typename Default, typename... Args>
92 inline typename TypeOfTagDefault<Tag,Default,Args...>::Result
93  Get(ParamPack<Args...>& pack, const Key<Tag>& key, Default d) {
94  return
95  GetImpl<Tag,ContainsTag<Tag,Args...>::result,Default,Args...>::Get(pack,d);
96 }
97 
99 inline uint64_t HashString(const std::string& str, int i,
100  uint64_t hash) {
101  return i == str.size() ? hash :
102  HashString(str, i + 1, ((hash << 5) ^ (hash >> 27)) ^ str[i]);
103 }
104 
105 inline uint64_t HashString(const std::string& str) {
106  return HashString(str, 0, str.size());
107 }
108 
110 template <typename... Args>
111 struct ParamPack{
112 
114  template<uint64_t Tag>
115  constexpr bool Contains(const Key<Tag>& key) {
116  return ContainsTag<Tag, Args...>::result;
117  }
118 
121  template<uint64_t Tag, typename T>
122  typename TypeOfTagDefault<Tag, T, Args...>::Result Get(const Key<Tag>& key,
123  T default_value) {
124  return kw::Get(*this, key, default_value);
125  }
126 
127  template<typename ReturnType>
128  ReturnType GetAs(uint64_t tag, ReturnType default_value) {
129  return default_value;
130  }
131 
132  template<typename ReturnType>
133  ReturnType GetAs(const std::string& tag, ReturnType default_value) {
134  return GetAs(HashString(tag),default_value);
135  }
136 
137  bool Contains(uint64_t tag){ return false; }
138  bool Contains(const std::string& tag){ return Contains(HashString(tag)); }
139 };
140 
141 
142 
144 
147 class Tag {
148  public:
149  template<uint32_t N>
151  constexpr Tag(const char (&string)[N])
152  : m_ptr(string),
153  m_size(N - 1) {
154  }
155 
156  constexpr Tag(const char* string, size_t len)
157  : m_ptr(string),
158  m_size(len) {
159  }
160 
162  constexpr char operator[](uint32_t i) {
163  // if we care about overflow
164  // return n < m_size ? m_ptr[i] : throw std::out_of_range("");
165  return m_ptr[i];
166  }
167 
170  constexpr uint32_t size() {
171  return m_size;
172  }
173 
176  constexpr uint64_t Hash(int i, uint64_t hash) {
177  return i == size() ? hash :
178  Hash(i + 1, ((hash << 5) ^ (hash >> 27)) ^ m_ptr[i]);
179  }
180 
182  constexpr uint64_t Hash(){
183  return Hash(0,size());
184  }
185 
186  private:
187  const char* const m_ptr;
188  const uint32_t m_size;
189 };
190 
192 template<uint32_t N>
193 inline constexpr uint64_t Hash(const char (&string)[N]){
194  return Tag(string).Hash();
195 }
196 
197 } //< namespace kw
198 
199 
200 // ----------------------------------------------------------------------------
201 // Danger!!! Horrible implementation details below!!!
202 // Continue at your own risk!
203 // ----------------------------------------------------------------------------
204 
205 #ifndef DOXYGEN_IGNORE
206 
207 namespace kw {
208 
211 template <typename T, typename ReturnType>
212 ReturnType SafeReturn(T query, ReturnType default_value){
213  return query;
214 }
215 
219 template <typename Head, typename... Tail>
220 struct ParamPack<Head,Tail...>
221  : Head,
222  ParamPack<Tail...> {
223  ParamPack( Head head, Tail... tail )
224  : Head(head),
225  ParamPack<Tail...>(tail...) {}
226 
227  template <uint64_t Tag>
228  constexpr bool Contains(const Key<Tag>& key) const{
229  return ContainsTag<Tag,Head,Tail...>::result;
230  }
231 
232  template<uint64_t Tag, typename T>
233  typename TypeOfTagDefault<Tag,T,Head,Tail...>::Result
234  Get(const Key<Tag>& key, T default_value) {
235  return kw::Get<Tag>(*this, key, default_value);
236  }
237 
238  template<typename ReturnType>
239  ReturnType GetAs(uint64_t tag, ReturnType default_value) {
240  return
241  Head::IsTagged(tag) ?
242  this->Head::v : ParamPack<Tail...>::GetAs(tag, default_value);
243  }
244 
245  template<typename ReturnType>
246  ReturnType GetAs(const std::string& string, ReturnType default_value) {
247  return GetAs(HashString(string),default_value);
248  }
249 
250  bool Contains(uint64_t tag) {
251  return Head::IsTagged(tag) ? true : ParamPack<Tail...>::Contains(tag);
252  }
253 
254  bool Contains(const std::string& tag) {
255  return Contains(HashString(tag));
256  }
257 };
258 
261 template <typename Tail>
262 struct ParamPack<Tail> : Tail {
263  ParamPack( Tail tail ) : Tail(tail) {}
264 
265  template <uint64_t Tag>
266  constexpr bool Contains(const Key<Tag>& key) const{
268  }
269 
270  template<uint64_t Tag, typename T>
272  Get(const Key<Tag>& key, T default_value) {
273  return kw::Get<Tag>(*this, key, default_value);
274  }
275 
276  template<typename ReturnType>
277  ReturnType GetAs(uint64_t tag, ReturnType default_value) {
278  return Tail::IsTagged(tag) ? this->Tail::v : default_value;
279  }
280 
281  template<typename ReturnType>
282  ReturnType GetAs(const std::string& string, ReturnType default_value) {
283  return GetAs(HashString(string), default_value);
284  }
285 
286  bool Contains(uint64_t tag) {
287  return Tail::IsTagged(tag) ? true : false;
288  }
289 
290  bool Contains(const std::string& tag) {
291  return Contains(HashString(tag));
292  }
293 };
294 
296 inline constexpr bool ContainsTagFn(uint64_t tag){
297  return false;
298 }
299 
300 template <uint64_t Tag, typename T, typename... Rest>
301 inline constexpr bool ContainsTagFn(uint64_t tag, Arg<Tag,T> first, Rest... rest){
302  return (tag==Tag) ? true : ContainsTagFn(tag,rest...);
303 }
304 
306 template <uint64_t Tag, typename First, typename... Rest>
307 struct ContainsTag<Tag,First,Rest...> {
308  static const bool result = ContainsTag<Tag, Rest...>::result;
309 };
310 
312 template <uint64_t Tag, typename T, typename... Rest>
313 struct ContainsTag<Tag, Arg<Tag,T>, Rest...> {
314  static const bool result = true;
315 };
316 
318 template <uint64_t Tag>
319 struct ContainsTag<Tag> {
320  static const bool result = false;
321 };
322 
324 template <uint64_t Tag, typename Default, typename Head, typename... Tail>
325 struct TypeOfTagDefault<Tag, Default, Head, Tail...> {
326  typedef typename TypeOfTagDefault<Tag, Default, Tail...>::Result Result;
327 };
328 
330 template <uint64_t Tag, typename Default, typename T, typename... Tail>
331 struct TypeOfTagDefault<Tag, Default, Arg<Tag, T>, Tail...> {
332  typedef T Result;
333 };
334 
336 template <uint64_t Tag, typename Default>
337 struct TypeOfTagDefault<Tag,Default> {
338  typedef Default Result;
339 };
340 
342 template <uint64_t Tag, typename Default, typename... Args>
343 struct GetImpl<Tag,false,Default,Args...>{
344  static inline Default Get(ParamPack<Args...>& pack, Default d) {
345  return d;
346  }
347 };
348 
351 template <uint64_t Tag, typename Default, typename... Args>
352 struct GetImpl<Tag,true,Default,Args...>{
353  static inline typename TypeOfTagDefault<Tag,Default,Args...>::Result Get(
354  ParamPack<Args...>& pack, Default d) {
355  typedef typename TypeOfTagDefault<Tag,Default,Args...>::Result StorageType;
356  return static_cast<Arg<Tag,StorageType>&>(pack).v;
357  }
358 };
359 
360 } //< namespace kw
361 
362 #define TAG(key) kw::Hash(#key)
363 #define KW(key) kw::Key<kw::Hash(#key)>()
364 
365 #endif // DOXYGEN_IGNORE
366 #endif // KWARGS_H_
constexpr bool ContainsTagFn(uint64_t tag)
Function version of ContainsTag.
Definition: kwargs.h:296
provides static member Get() with implementations depending on whether or not Tag is in Args...
Definition: kwargs.h:78
ParamPack(Tail tail)
Definition: kwargs.h:263
TypeOfTagDefault< Tag, Default, Tail...>::Result Result
Definition: kwargs.h:326
Arg(T v)
Definition: kwargs.h:18
constexpr uint32_t size()
return the number of characters in the string, including the terminal null
Definition: kwargs.h:170
TypeOfTagDefault< Tag, T, Tail >::Result Get(const Key< Tag > &key, T default_value)
Definition: kwargs.h:272
T v
Definition: kwargs.h:17
Arg< Tag, T > operator=(T v)
Definition: kwargs.h:53
constexpr string, used to implement tagging with strings
Definition: kwargs.h:147
ReturnType GetAs(const std::string &tag, ReturnType default_value)
Definition: kwargs.h:133
constexpr bool Contains(const Key< Tag > &key) const
Definition: kwargs.h:228
FT_Tag Tag
typedef for 32bit tags (as used in the SFNT format)
Definition: types.h:115
bool Contains(const std::string &tag)
Definition: kwargs.h:290
const char *const m_ptr
Definition: kwargs.h:187
bool Contains(const std::string &tag)
Definition: kwargs.h:138
constexpr uint64_t Hash()
return a hash of the string
Definition: kwargs.h:182
bool Contains(uint64_t tag)
Definition: kwargs.h:250
ReturnType GetAs(uint64_t tag, ReturnType default_value)
Definition: kwargs.h:239
TypeOfTagDefault< Tag, T, Args...>::Result Get(const Key< Tag > &key, T default_value)
return the value associated with Tag, if it exists in the kwargs, otherwise return the default ...
Definition: kwargs.h:122
static Default Get(ParamPack< Args...> &pack, Default d)
Definition: kwargs.h:344
RefWrap< T > Ref(T &v)
forces an argument to be passed by reference
Definition: kwargs.h:42
assignment operator sentinal used as a key for key-values pairs in the kwargs parameter pack ...
Definition: kwargs.h:51
ReturnType GetAs(uint64_t tag, ReturnType default_value)
Definition: kwargs.h:277
Arg< Tag, const T & > operator=(ConstRefWrap< T > vw)
Definition: kwargs.h:59
TypeOfTagDefault< Tag, Default, Args...>::Result Get(ParamPack< Args...> &pack, Default d)
given a parameter pack, retrieves and return sthe parameter tagged with tag, or else returns a defaul...
Definition: kwargs.h:84
constexpr uint64_t Hash(const char(&string)[N])
returns a 64bit hash of string
Definition: kwargs.h:193
signifies that the parameter should be passed by reference
Definition: kwargs.h:28
signifies the parameter should be passed by const reference
Definition: kwargs.h:35
static TypeOfTagDefault< Tag, Default, Args...>::Result Get(ParamPack< Args...> &pack, Default d)
Definition: kwargs.h:353
Arg< Tag, T & > operator=(RefWrap< T > vw)
Definition: kwargs.h:56
ReturnType SafeReturn(T query, ReturnType default_value)
SFINAE to safely iterate over params in a parampack since we cannot use the ?: operator on any old pa...
Definition: kwargs.h:212
constexpr bool Contains(const Key< Tag > &key) const
Definition: kwargs.h:266
ReturnType GetAs(uint64_t tag, ReturnType default_value)
Definition: kwargs.h:128
constexpr bool IsTagged(uint64_t query)
Definition: kwargs.h:19
bool Contains(const std::string &tag)
Definition: kwargs.h:254
uint64_t HashString(const std::string &str, int i, uint64_t hash)
Return an unsigned 64bit hash of string.
Definition: kwargs.h:99
T & v
Definition: kwargs.h:29
ConstRefWrap(const T &v)
Definition: kwargs.h:37
template meta-function contains a static boolean variable 'result' which is true if Tag is in the lis...
Definition: kwargs.h:65
const ConstRefWrap< T > ConstRef(const T &v)
forces an argument to be passed by const reference
Definition: kwargs.h:46
bool Contains(uint64_t tag)
Definition: kwargs.h:286
const Char8_t * str(const Char8_t *s1, const Char8_t *s2)
ReturnType GetAs(const std::string &string, ReturnType default_value)
Definition: kwargs.h:282
const uint32_t m_size
Definition: kwargs.h:188
constexpr Tag(const char(&string)[N])
Construct from a string literal.
Definition: kwargs.h:151
constexpr Tag(const char *string, size_t len)
Definition: kwargs.h:156
constexpr uint64_t Hash(int i, uint64_t hash)
Donald Knuth's hash function TODO: validate or replace this hash function.
Definition: kwargs.h:176
parameter storage for type T within a parameter pack
Definition: kwargs.h:16
RefWrap(T &v)
Definition: kwargs.h:30
bool Contains(uint64_t tag)
Definition: kwargs.h:137
template meta function provides a member typedef Result which evaluates to T if Arg<Tag,T> is in Args... or Default if it is not
Definition: kwargs.h:70
ReturnType GetAs(const std::string &string, ReturnType default_value)
Definition: kwargs.h:246
const T & v
Definition: kwargs.h:36
TypeOfTagDefault< Tag, T, Head, Tail...>::Result Get(const Key< Tag > &key, T default_value)
Definition: kwargs.h:234
constexpr bool Contains(const Key< Tag > &key)
returns true if the numeric tag is a member of the kwargs in Args...
Definition: kwargs.h:115
storage for kwargs parameter pack
Definition: kwargs.h:73
constexpr char operator[](uint32_t i)
return the character at index i
Definition: kwargs.h:162
ParamPack(Head head, Tail...tail)
Definition: kwargs.h:223