Electroneum
utility.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include <cstdint>
4 #include <stdexcept>
5 #include <tuple>
6 #include <type_traits>
7 #include <cstring>
8 #include <functional>
9 #include <string>
10 
11 namespace crow
12 {
13  namespace black_magic
14  {
15 #ifndef CROW_MSVC_WORKAROUND
16  struct OutOfRange
17  {
18  OutOfRange(unsigned /*pos*/, unsigned /*length*/) {}
19  };
20  constexpr unsigned requires_in_range( unsigned i, unsigned len )
21  {
22  return i >= len ? throw OutOfRange(i, len) : i;
23  }
24 
25  class const_str
26  {
27  const char * const begin_;
28  unsigned size_;
29 
30  public:
31  template< unsigned N >
32  constexpr const_str( const char(&arr)[N] ) : begin_(arr), size_(N - 1) {
33  static_assert( N >= 1, "not a string literal");
34  }
35  constexpr char operator[]( unsigned i ) const {
36  return requires_in_range(i, size_), begin_[i];
37  }
38 
39  constexpr operator const char *() const {
40  return begin_;
41  }
42 
43  constexpr const char* begin() const { return begin_; }
44  constexpr const char* end() const { return begin_ + size_; }
45 
46  constexpr unsigned size() const {
47  return size_;
48  }
49  };
50 
51  constexpr unsigned find_closing_tag(const_str s, unsigned p)
52  {
53  return s[p] == '>' ? p : find_closing_tag(s, p+1);
54  }
55 
56  constexpr bool is_valid(const_str s, unsigned i = 0, int f = 0)
57  {
58  return
59  i == s.size()
60  ? f == 0 :
61  f < 0 || f >= 2
62  ? false :
63  s[i] == '<'
64  ? is_valid(s, i+1, f+1) :
65  s[i] == '>'
66  ? is_valid(s, i+1, f-1) :
67  is_valid(s, i+1, f);
68  }
69 
70  constexpr bool is_equ_p(const char* a, const char* b, unsigned n)
71  {
72  return
73  *a == 0 && *b == 0 && n == 0
74  ? true :
75  (*a == 0 || *b == 0)
76  ? false :
77  n == 0
78  ? true :
79  *a != *b
80  ? false :
81  is_equ_p(a+1, b+1, n-1);
82  }
83 
84  constexpr bool is_equ_n(const_str a, unsigned ai, const_str b, unsigned bi, unsigned n)
85  {
86  return
87  ai + n > a.size() || bi + n > b.size()
88  ? false :
89  n == 0
90  ? true :
91  a[ai] != b[bi]
92  ? false :
93  is_equ_n(a,ai+1,b,bi+1,n-1);
94  }
95 
96  constexpr bool is_int(const_str s, unsigned i)
97  {
98  return is_equ_n(s, i, "<int>", 0, 5);
99  }
100 
101  constexpr bool is_uint(const_str s, unsigned i)
102  {
103  return is_equ_n(s, i, "<uint>", 0, 6);
104  }
105 
106  constexpr bool is_float(const_str s, unsigned i)
107  {
108  return is_equ_n(s, i, "<float>", 0, 7) ||
109  is_equ_n(s, i, "<double>", 0, 8);
110  }
111 
112  constexpr bool is_str(const_str s, unsigned i)
113  {
114  return is_equ_n(s, i, "<str>", 0, 5) ||
115  is_equ_n(s, i, "<string>", 0, 8);
116  }
117 
118  constexpr bool is_path(const_str s, unsigned i)
119  {
120  return is_equ_n(s, i, "<path>", 0, 6);
121  }
122 #endif
123  template <typename T>
125  {
126  static const int value = 0;
127  };
128 #define CROW_INTERNAL_PARAMETER_TAG(t, i) \
129 template <> \
130 struct parameter_tag<t> \
131 { \
132  static const int value = i; \
133 }
136  CROW_INTERNAL_PARAMETER_TAG(short, 1);
138  CROW_INTERNAL_PARAMETER_TAG(long long, 1);
139  CROW_INTERNAL_PARAMETER_TAG(unsigned int, 2);
140  CROW_INTERNAL_PARAMETER_TAG(unsigned char, 2);
141  CROW_INTERNAL_PARAMETER_TAG(unsigned short, 2);
142  CROW_INTERNAL_PARAMETER_TAG(unsigned long, 2);
143  CROW_INTERNAL_PARAMETER_TAG(unsigned long long, 2);
144  CROW_INTERNAL_PARAMETER_TAG(double, 3);
145  CROW_INTERNAL_PARAMETER_TAG(std::string, 4);
146 #undef CROW_INTERNAL_PARAMETER_TAG
147  template <typename ... Args>
149 
150  template <>
152  {
153  static const int value = 0;
154  };
155 
156  template <typename Arg, typename ... Args>
158  {
159  static const int sub_value =
160  compute_parameter_tag_from_args_list<Args...>::value;
161  static const int value =
163  ? sub_value* 6 + parameter_tag<typename std::decay<Arg>::type>::value
164  : sub_value;
165  };
166 
167  static inline bool is_parameter_tag_compatible(uint64_t a, uint64_t b)
168  {
169  if (a == 0)
170  return b == 0;
171  if (b == 0)
172  return a == 0;
173  int sa = a%6;
174  int sb = a%6;
175  if (sa == 5) sa = 4;
176  if (sb == 5) sb = 4;
177  if (sa != sb)
178  return false;
179  return is_parameter_tag_compatible(a/6, b/6);
180  }
181 
182  static inline unsigned find_closing_tag_runtime(const char* s, unsigned p)
183  {
184  return
185  s[p] == 0
186  ? throw std::runtime_error("unmatched tag <") :
187  s[p] == '>'
188  ? p : find_closing_tag_runtime(s, p + 1);
189  }
190 
191  static inline uint64_t get_parameter_tag_runtime(const char* s, unsigned p = 0)
192  {
193  return
194  s[p] == 0
195  ? 0 :
196  s[p] == '<' ? (
197  std::strncmp(s+p, "<int>", 5) == 0
199  std::strncmp(s+p, "<uint>", 6) == 0
201  (std::strncmp(s+p, "<float>", 7) == 0 ||
202  std::strncmp(s+p, "<double>", 8) == 0)
204  (std::strncmp(s+p, "<str>", 5) == 0 ||
205  std::strncmp(s+p, "<string>", 8) == 0)
207  std::strncmp(s+p, "<path>", 6) == 0
209  throw std::runtime_error("invalid parameter type")
210  ) :
212  }
213 #ifndef CROW_MSVC_WORKAROUND
214  constexpr uint64_t get_parameter_tag(const_str s, unsigned p = 0)
215  {
216  return
217  p == s.size()
218  ? 0 :
219  s[p] == '<' ? (
220  is_int(s, p)
221  ? get_parameter_tag(s, find_closing_tag(s, p)) * 6 + 1 :
222  is_uint(s, p)
223  ? get_parameter_tag(s, find_closing_tag(s, p)) * 6 + 2 :
224  is_float(s, p)
225  ? get_parameter_tag(s, find_closing_tag(s, p)) * 6 + 3 :
226  is_str(s, p)
227  ? get_parameter_tag(s, find_closing_tag(s, p)) * 6 + 4 :
228  is_path(s, p)
229  ? get_parameter_tag(s, find_closing_tag(s, p)) * 6 + 5 :
230  throw std::runtime_error("invalid parameter type")
231  ) :
232  get_parameter_tag(s, p+1);
233  }
234 #endif
235 
236  template <typename ... T>
237  struct S
238  {
239  template <typename U>
240  using push = S<U, T...>;
241  template <typename U>
242  using push_back = S<T..., U>;
243  template <template<typename ... Args> class U>
244  using rebind = U<T...>;
245  };
246 template <typename F, typename Set>
247  struct CallHelper;
248  template <typename F, typename ...Args>
249  struct CallHelper<F, S<Args...>>
250  {
251  template <typename F1, typename ...Args1, typename =
252  decltype(std::declval<F1>()(std::declval<Args1>()...))
253  >
254  static char __test(int);
255 
256  template <typename ...>
257  static int __test(...);
258 
259  static constexpr bool value = sizeof(__test<F, Args...>(0)) == sizeof(char);
260  };
261 
262 
263  template <int N>
265  {
266  };
267 
268  template <>
270  {
271  using type = int64_t;
272  };
273 
274  template <>
276  {
277  using type = uint64_t;
278  };
279 
280  template <>
282  {
283  using type = double;
284  };
285 
286  template <>
288  {
289  using type = std::string;
290  };
291 
292  template <>
294  {
295  using type = std::string;
296  };
297 
298 
299  template <uint64_t Tag>
300  struct arguments
301  {
302  using subarguments = typename arguments<Tag/6>::type;
303  using type =
304  typename subarguments::template push<typename single_tag_to_type<Tag%6>::type>;
305  };
306 
307  template <>
308  struct arguments<0>
309  {
310  using type = S<>;
311  };
312 
313  template <typename ... T>
315  {
316  using type = typename std::tuple_element<sizeof...(T)-1, std::tuple<T...>>::type;
317  };
318 
319 
320  template <>
322  {
323  };
324 
325 
326  // from http://stackoverflow.com/questions/13072359/c11-compile-time-array-with-logarithmic-evaluation-depth
327  template<class T> using Invoke = typename T::type;
328 
329  template<unsigned...> struct seq{ using type = seq; };
330 
331  template<class S1, class S2> struct concat;
332 
333  template<unsigned... I1, unsigned... I2>
334  struct concat<seq<I1...>, seq<I2...>>
335  : seq<I1..., (sizeof...(I1)+I2)...>{};
336 
337  template<class S1, class S2>
339 
340  template<unsigned N> struct gen_seq;
341  template<unsigned N> using GenSeq = Invoke<gen_seq<N>>;
342 
343  template<unsigned N>
344  struct gen_seq : Concat<GenSeq<N/2>, GenSeq<N - N/2>>{};
345 
346  template<> struct gen_seq<0> : seq<>{};
347  template<> struct gen_seq<1> : seq<0>{};
348 
349  template <typename Seq, typename Tuple>
351 
352  template <unsigned ... N, typename Tuple>
353  struct pop_back_helper<seq<N...>, Tuple>
354  {
355  template <template <typename ... Args> class U>
357  };
358 
359  template <typename ... T>
360  struct pop_back //: public pop_back_helper<typename gen_seq<sizeof...(T)-1>::type, std::tuple<T...>>
361  {
362  template <template <typename ... Args> class U>
363  using rebind = typename pop_back_helper<typename gen_seq<sizeof...(T)-1>::type, std::tuple<T...>>::template rebind<U>;
364  };
365 
366  template <>
367  struct pop_back<>
368  {
369  template <template <typename ... Args> class U>
370  using rebind = U<>;
371  };
372 
373  // from http://stackoverflow.com/questions/2118541/check-if-c0x-parameter-pack-contains-a-type
374  template < typename Tp, typename... List >
375  struct contains : std::true_type {};
376 
377  template < typename Tp, typename Head, typename... Rest >
378  struct contains<Tp, Head, Rest...>
379  : std::conditional< std::is_same<Tp, Head>::value,
380  std::true_type,
381  contains<Tp, Rest...>
382  >::type {};
383 
384  template < typename Tp >
385  struct contains<Tp> : std::false_type {};
386 
387  template <typename T>
389  {
390  };
391 
392  template <typename T>
393  struct promote
394  {
395  using type = T;
396  };
397 
398 #define CROW_INTERNAL_PROMOTE_TYPE(t1, t2) \
399  template<> \
400  struct promote<t1> \
401  { \
402  using type = t2; \
403  }
404 
405  CROW_INTERNAL_PROMOTE_TYPE(char, int64_t);
406  CROW_INTERNAL_PROMOTE_TYPE(short, int64_t);
407  CROW_INTERNAL_PROMOTE_TYPE(int, int64_t);
408  CROW_INTERNAL_PROMOTE_TYPE(long, int64_t);
409  CROW_INTERNAL_PROMOTE_TYPE(long long, int64_t);
410  CROW_INTERNAL_PROMOTE_TYPE(unsigned char, uint64_t);
411  CROW_INTERNAL_PROMOTE_TYPE(unsigned short, uint64_t);
412  CROW_INTERNAL_PROMOTE_TYPE(unsigned int, uint64_t);
413  CROW_INTERNAL_PROMOTE_TYPE(unsigned long, uint64_t);
414  CROW_INTERNAL_PROMOTE_TYPE(unsigned long long, uint64_t);
415  CROW_INTERNAL_PROMOTE_TYPE(float, double);
416 #undef CROW_INTERNAL_PROMOTE_TYPE
417 
418  template <typename T>
419  using promote_t = typename promote<T>::type;
420 
421  } // namespace black_magic
422 
423  namespace detail
424  {
425 
426  template <class T, std::size_t N, class... Args>
428  {
429  static constexpr auto value = N;
430  };
431 
432  template <class T, std::size_t N, class... Args>
434  {
435  static constexpr auto value = N;
436  };
437 
438  template <class T, std::size_t N, class U, class... Args>
440  {
441  static constexpr auto value = get_index_of_element_from_tuple_by_type_impl<T, N + 1, Args...>::value;
442  };
443 
444  } // namespace detail
445 
446  namespace utility
447  {
448  template <class T, class... Args>
449  T& get_element_by_type(std::tuple<Args...>& t)
450  {
451  return std::get<detail::get_index_of_element_from_tuple_by_type_impl<T, 0, Args...>::value>(t);
452  }
453 
454  template<typename T>
456 
457 #ifndef CROW_MSVC_WORKAROUND
458  template<typename T>
459  struct function_traits : public function_traits<decltype(&T::operator())>
460  {
462  static const size_t arity = parent_t::arity;
464  template <size_t i>
465  using arg = typename parent_t::template arg<i>;
466 
467  };
468 #endif
469 
470  template<typename ClassType, typename R, typename ...Args>
471  struct function_traits<R(ClassType::*)(Args...) const>
472  {
473  static const size_t arity = sizeof...(Args);
474 
475  typedef R result_type;
476 
477  template <size_t i>
478  using arg = typename std::tuple_element<i, std::tuple<Args...>>::type;
479  };
480 
481  template<typename ClassType, typename R, typename ...Args>
482  struct function_traits<R(ClassType::*)(Args...)>
483  {
484  static const size_t arity = sizeof...(Args);
485 
486  typedef R result_type;
487 
488  template <size_t i>
489  using arg = typename std::tuple_element<i, std::tuple<Args...>>::type;
490  };
491 
492  template<typename R, typename ...Args>
493  struct function_traits<std::function<R(Args...)>>
494  {
495  static const size_t arity = sizeof...(Args);
496 
497  typedef R result_type;
498 
499  template <size_t i>
500  using arg = typename std::tuple_element<i, std::tuple<Args...>>::type;
501  };
502 
503  std::string base64encode(const char* data, size_t size, const char* key = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/")
504  {
505  std::string ret;
506  ret.resize((size+2) / 3 * 4);
507  auto it = ret.begin();
508  while(size >= 3)
509  {
510  *it++ = key[(((unsigned char)*data)&0xFC)>>2];
511  unsigned char h = (((unsigned char)*data++) & 0x03) << 4;
512  *it++ = key[h|((((unsigned char)*data)&0xF0)>>4)];
513  h = (((unsigned char)*data++) & 0x0F) << 2;
514  *it++ = key[h|((((unsigned char)*data)&0xC0)>>6)];
515  *it++ = key[((unsigned char)*data++)&0x3F];
516 
517  size -= 3;
518  }
519  if (size == 1)
520  {
521  *it++ = key[(((unsigned char)*data)&0xFC)>>2];
522  unsigned char h = (((unsigned char)*data++) & 0x03) << 4;
523  *it++ = key[h];
524  *it++ = '=';
525  *it++ = '=';
526  }
527  else if (size == 2)
528  {
529  *it++ = key[(((unsigned char)*data)&0xFC)>>2];
530  unsigned char h = (((unsigned char)*data++) & 0x03) << 4;
531  *it++ = key[h|((((unsigned char)*data)&0xF0)>>4)];
532  h = (((unsigned char)*data++) & 0x0F) << 2;
533  *it++ = key[h];
534  *it++ = '=';
535  }
536  return ret;
537  }
538 
539  std::string base64encode_urlsafe(const char* data, size_t size)
540  {
541  return base64encode(data, size, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_");
542  }
543 
544 
545  } // namespace utility
546 }
constexpr bool is_float(const_str s, unsigned i)
Definition: utility.h:106
typename std::tuple_element< i, std::tuple< Args... > >::type arg
Definition: utility.h:489
Definition: utility.h:375
const uint32_t T[512]
Definition: groestl_tables.h:34
typename arguments< Tag/6 >::type subarguments
Definition: utility.h:302
Definition: utility.h:25
constexpr bool is_valid(const_str s, unsigned i=0, int f=0)
Definition: utility.h:56
Invoke< concat< S1, S2 > > Concat
Definition: utility.h:338
typename parent_t::result_type result_type
Definition: utility.h:463
const char *const begin_
Definition: utility.h:27
Definition: utility.h:360
std::string base64encode(const char *data, size_t size, const char *key="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/")
Definition: utility.h:503
#define F(w, k)
Definition: sha512-blocks.c:61
T & get_element_by_type(std::tuple< Args... > &t)
Definition: utility.h:449
static unsigned find_closing_tag_runtime(const char *s, unsigned p)
Definition: utility.h:182
constexpr bool is_uint(const_str s, unsigned i)
Definition: utility.h:101
Definition: utility.h:16
typename promote< T >::type promote_t
Definition: utility.h:419
typename pop_back_helper< typename gen_seq< sizeof...(T) -1 >::type, std::tuple< T... > >::template rebind< U > rebind
Definition: utility.h:363
unsigned size_
Definition: utility.h:28
OutOfRange(unsigned, unsigned)
Definition: utility.h:18
Definition: block_queue.cpp:41
static constexpr auto value
Definition: utility.h:429
constexpr bool is_path(const_str s, unsigned i)
Definition: utility.h:118
constexpr unsigned size() const
Definition: utility.h:46
U< typename std::tuple_element< N, Tuple >::type... > rebind
Definition: utility.h:356
Definition: utility.h:237
std::string base64encode_urlsafe(const char *data, size_t size)
Definition: utility.h:539
typename std::tuple_element< i, std::tuple< Args... > >::type arg
Definition: utility.h:478
U< T... > rebind
Definition: utility.h:244
Definition: utility.h:455
Definition: utility.h:247
Definition: utility.h:314
declaration and default definition for the functions used the API
CROW_INTERNAL_PARAMETER_TAG(int, 1)
int64_t type
Definition: utility.h:271
constexpr unsigned find_closing_tag(const_str s, unsigned p)
Definition: utility.h:51
int b
Definition: base.py:1
constexpr bool is_int(const_str s, unsigned i)
Definition: utility.h:96
type
Definition: json.h:74
#define false
Definition: stdbool.h:38
static uint64_t get_parameter_tag_runtime(const char *s, unsigned p=0)
Definition: utility.h:191
Definition: utility.h:329
typename std::tuple_element< i, std::tuple< Args... > >::type arg
Definition: utility.h:500
Definition: utility.h:393
std::string type
Definition: utility.h:295
constexpr bool is_str(const_str s, unsigned i)
Definition: utility.h:112
Invoke< gen_seq< N > > GenSeq
Definition: utility.h:341
Definition: utility.h:331
constexpr unsigned requires_in_range(unsigned i, unsigned len)
Definition: utility.h:20
constexpr uint64_t get_parameter_tag(const_str s, unsigned p=0)
Definition: utility.h:214
U<> rebind
Definition: utility.h:370
constexpr bool is_equ_p(const char *a, const char *b, unsigned n)
Definition: utility.h:70
Definition: utility.h:388
Definition: utility.h:350
T type
Definition: utility.h:395
typename std::tuple_element< sizeof...(T) -1, std::tuple< T... > >::type type
Definition: utility.h:316
constexpr const char * begin() const
Definition: utility.h:43
string a
Definition: MakeCryptoOps.py:15
constexpr const_str(const char(&arr)[N])
Definition: utility.h:32
double type
Definition: utility.h:283
uint64_t type
Definition: utility.h:277
typename T::type Invoke
Definition: utility.h:327
Definition: ci_map.h:7
constexpr char operator[](unsigned i) const
Definition: utility.h:35
Definition: utility.h:264
static const size_t arity
Definition: utility.h:462
typename parent_t::template arg< i > arg
Definition: utility.h:465
CROW_INTERNAL_PROMOTE_TYPE(char, int64_t)
Definition: utility.h:340
static bool is_parameter_tag_compatible(uint64_t a, uint64_t b)
Definition: utility.h:167
std::string type
Definition: utility.h:289
typename subarguments::template push< typename single_tag_to_type< Tag%6 >::type > type
Definition: utility.h:304
#define true
Definition: stdbool.h:37
#define s(x, c)
Definition: aesb.c:46
Definition: utility.h:124
constexpr const char * end() const
Definition: utility.h:44
static const int value
Definition: utility.h:126
Definition: utility.h:300
constexpr bool is_equ_n(const_str a, unsigned ai, const_str b, unsigned bi, unsigned n)
Definition: utility.h:84