MADARA  3.4.1
KnowledgeCast.h
Go to the documentation of this file.
1 
56 #ifndef _MADARA_KNOWLEDGE_KNOWLEDGE_CAST_H_
57 #define _MADARA_KNOWLEDGE_KNOWLEDGE_CAST_H_
58 
59 #include <string>
60 #include <cstring>
61 #include <type_traits>
62 #include <stdbool.h>
65 
66 namespace madara
67 {
68 namespace knowledge
69 {
70 template<class T>
71 struct type
72 {
73  type() = default;
74  using self = T;
75 };
76 
79 template<class O>
80 inline auto knowledge_cast(type<O>, const KnowledgeRecord& in) ->
81  typename std::enable_if<
82  std::is_constructible<O, const KnowledgeRecord&>::value, O>::type
83 {
84  return O{in};
85 }
86 
88 template<class O>
89 inline auto knowledge_cast(type<O>, const KnowledgeRecord& in)
91 {
92  return static_cast<O>(in.to_double());
93 }
94 
96 template<class O>
97 inline auto knowledge_cast(type<O>, const KnowledgeRecord& in)
98  -> utility::enable_if_<std::is_integral<O>::value || std::is_enum<O>::value,
99  O>
100 {
101  return static_cast<O>(in.to_integer());
102 }
103 
106 {
107  return in.is_true();
108 }
109 
112 {
113  return in.to_string();
114 }
115 
117 inline std::vector<int64_t> knowledge_cast(
118  type<std::vector<int64_t>>, const KnowledgeRecord& in)
119 {
120  return in.to_integers();
121 }
122 
124 template<typename T>
125 inline auto knowledge_cast(type<std::vector<T>>, const KnowledgeRecord& in) ->
126  typename std::enable_if<std::is_integral<T>::value, std::vector<T>>::type
127 {
128  auto vec = in.to_integers();
129  return {std::begin(vec), std::end(vec)};
130 }
131 
133 inline std::vector<double> knowledge_cast(
134  type<std::vector<double>>, const KnowledgeRecord& in)
135 {
136  return in.to_doubles();
137 }
138 
140 template<typename T>
141 inline auto knowledge_cast(type<std::vector<T>>, const KnowledgeRecord& in) ->
142  typename std::enable_if<std::is_floating_point<T>::value,
143  std::vector<T>>::type
144 {
145  auto vec = in.to_doubles();
146  return {std::begin(vec), std::end(vec)};
147 }
148 
151 namespace impl
152 {
153 template<typename T>
154 inline auto get_size(const T& c) -> decltype(c.size())
155 {
156  return c.size();
157 }
158 
159 template<typename T, size_t N>
160 inline size_t get_size(const T (&arr)[N])
161 {
162  (void)arr;
163  return N;
164 }
165 
166 template<typename T>
167 inline auto share_array(const KnowledgeRecord& in) ->
168  typename std::enable_if<std::is_integral<typename std::decay<decltype(
169  *std::begin(std::declval<T&>()))>::type>::value,
170  decltype(in.share_integers())>::type
171 {
172  return in.share_integers();
173 }
174 
175 template<typename T>
176 inline auto to_array(const KnowledgeRecord& in) ->
177  typename std::enable_if<std::is_integral<typename std::decay<decltype(
178  *std::begin(std::declval<T&>()))>::type>::value,
179  decltype(in.to_integers())>::type
180 {
181  return in.to_integers();
182 }
183 
184 template<typename T>
185 inline auto share_array(const KnowledgeRecord& in) ->
186  typename std::enable_if<std::is_floating_point<typename std::decay<decltype(
187  *std::begin(std::declval<T&>()))>::type>::value,
188  decltype(in.share_doubles())>::type
189 {
190  return in.share_doubles();
191 }
192 
193 template<typename T>
194 inline auto to_array(const KnowledgeRecord& in) ->
195  typename std::enable_if<std::is_floating_point<typename std::decay<decltype(
196  *std::begin(std::declval<T&>()))>::type>::value,
197  decltype(in.to_doubles())>::type
198 {
199  return in.to_doubles();
200 }
201 
202 template<typename T>
204 {
205  T* ptr;
206  size_t len;
207 
208  T* begin() const
209  {
210  return ptr;
211  }
212  const T* cbegin() const
213  {
214  return ptr;
215  }
216  T* end() const
217  {
218  return ptr + len;
219  }
220  const T* cend() const
221  {
222  return ptr + len;
223  }
224 
225  T& operator[](size_t i) const
226  {
227  return ptr[i];
228  }
229 
230  size_t size() const
231  {
232  return len;
233  }
234 };
235 
236 template<typename T>
237 simple_span<T> make_span(T* ptr, size_t size)
238 {
239  return {ptr, size};
240 }
241 
242 template<typename T>
243 struct is_basic_string : std::false_type
244 {
245 };
246 
247 template<typename CharT, typename Traits, typename Allocator>
248 struct is_basic_string<std::basic_string<CharT, Traits, Allocator>>
249  : std::true_type
250 {
251 };
252 } // namespace impl
253 
255 template<typename CharT, typename Traits, typename Allocator>
256 inline std::basic_string<CharT, Traits, Allocator>& knowledge_cast(
257  const KnowledgeRecord& in, std::basic_string<CharT, Traits, Allocator>& out)
258 {
259  static_assert(std::is_same<std::string,
260  std::basic_string<CharT, Traits, Allocator>>::value,
261  "knowledge_cast only supports std::string, "
262  "not other std::basic_string types");
263  return (out = knowledge_cast(type<std::string>{}, in));
264 }
265 
268 // template<typename T>
269 // inline auto knowledge_cast(const KnowledgeRecord& in, T* out, size_t size)
270 // -> decltype(
271 // knowledge_cast(in, std::declval<impl::simple_span<T>&>()),
272 // (T*)nullptr)
273 //{
274 // auto span = impl::make_span(out, size);
275 // knowledge_cast(in, span);
276 // return out;
277 //}
278 
282 {
283  return in;
284 }
285 
287 template<typename T>
288 inline auto knowledge_cast(const KnowledgeRecord& in)
289  -> decltype(knowledge_cast(type<T>{}, in))
290 {
291  return knowledge_cast(type<T>{}, in);
292 }
293 
297 template<class O>
298 inline auto knowledge_cast(O&& in) ->
299  typename std::decay<decltype(KnowledgeRecord{std::forward<O>(in)})>::type
300 {
301  return KnowledgeRecord{std::forward<O>(in)};
302 }
303 
306 template<typename T>
307 inline auto knowledge_cast(const T& in) -> typename std::enable_if<
308  std::is_integral<typename std::decay<decltype(in[0])>::type>::value &&
309  !std::is_same<typename std::decay<decltype(in[0])>::type,
310  char>::value &&
311  !std::is_same<typename std::decay<decltype(in[0])>::type,
312  unsigned char>::value &&
313  !std::is_same<T, std::vector<int64_t>>::value,
314  typename std::decay<decltype(KnowledgeRecord{
315  tags::integers, std::begin(in), std::end(in)})>::type>::type
316 {
317  return KnowledgeRecord{tags::integers, std::begin(in), std::end(in)};
318 }
319 
321 template<typename T>
322 inline auto knowledge_cast(const T& in) -> typename std::enable_if<
323  std::is_floating_point<typename std::decay<decltype(in[0])>::type>::value &&
324  !std::is_same<T, std::vector<double>>::value,
325  typename std::decay<decltype(KnowledgeRecord{
326  tags::doubles, std::begin(in), std::end(in)})>::type>::type
327 {
328  return KnowledgeRecord{tags::doubles, std::begin(in), std::end(in)};
329 }
330 
332 template<typename T>
333 inline auto knowledge_cast(const T& in) -> typename std::enable_if<
334  std::is_same<typename std::decay<decltype(in[0])>::type, char>::value &&
335  !std::is_same<T, std::string>::value,
336  typename std::decay<decltype(KnowledgeRecord{
337  tags::string, std::begin(in), std::end(in)})>::type>::type
338 {
339  return KnowledgeRecord{tags::string, std::begin(in), std::end(in)};
340 }
341 
343 template<typename T>
344 inline auto knowledge_cast(const T& in) -> typename std::enable_if<
345  std::is_same<typename std::decay<decltype(in[0])>::type,
346  unsigned char>::value &&
347  !std::is_same<T, std::vector<unsigned char>>::value,
348  typename std::decay<decltype(KnowledgeRecord{
349  tags::binary, std::begin(in), std::end(in)})>::type>::type
350 {
351  return KnowledgeRecord{tags::binary, std::begin(in), std::end(in)};
352 }
353 
354 template<typename T>
355 inline auto knowledge_cast(const KnowledgeRecord& in, T&& out)
356  -> decltype(*out = knowledge_cast(
358 {
359  return (*out = knowledge_cast(
360  type<typename utility::decay_<T>::container_type::value_type>{}, in));
361 }
362 
363 template<typename Container>
364 inline void knowledge_cast(
365  const KnowledgeRecord& in, std::back_insert_iterator<Container> iter)
366 {
367  using out_type = typename Container::value_type;
368  iter = knowledge_cast(type<out_type>{}, in);
369 }
370 
373 {
374  return in;
375 }
376 
378 inline const KnowledgeRecord& knowledge_cast(const KnowledgeRecord& in)
379 {
380  return in;
381 }
382 
385  const KnowledgeRecord& in, KnowledgeRecord& out)
386 {
387  return out = in;
388 }
389 
392 #define MADARA_KNOWLEDGE_COMPARE_OP(op) \
393  template<typename T, typename std::enable_if< \
394  !std::is_convertible<T, KnowledgeRecord>::value && \
395  std::is_fundamental<T>::value, \
396  void*>::type = nullptr> \
397  inline auto operator op(const KnowledgeRecord& l, const T& r) \
398  ->decltype(knowledge_cast<T>(l) op r) \
399  { \
400  return knowledge_cast<T>(l) op r; \
401  } \
402  \
403  template<typename T, typename std::enable_if< \
404  !std::is_convertible<T, KnowledgeRecord>::value && \
405  std::is_fundamental<T>::value, \
406  void*>::type = nullptr> \
407  inline auto operator op(const T& l, const KnowledgeRecord& r) \
408  ->decltype(l op knowledge_cast<T>(r)) \
409  { \
410  return l op knowledge_cast<T>(r); \
411  } \
412  \
413  inline bool operator op(const KnowledgeRecord& l, std::nullptr_t) \
414  { \
415  return l op 0; \
416  } \
417  \
418  inline bool operator op(const KnowledgeRecord& l, const char* r) \
419  { \
420  auto s = l.share_string(); \
421  if (s) \
422  { \
423  return s->compare(r) op 0; \
424  } \
425  else \
426  { \
427  return l.to_string().compare(r) op 0; \
428  } \
429  } \
430  \
431  inline bool operator op(const char* l, const KnowledgeRecord& r) \
432  { \
433  auto s = r.share_string(); \
434  if (s) \
435  { \
436  return std::strcmp(l, s->c_str()) op 0; \
437  } \
438  else \
439  { \
440  return std::strcmp(l, r.to_string().c_str()) op 0; \
441  } \
442  } \
443  \
444  inline bool operator op(const KnowledgeRecord& l, const std::string& r) \
445  { \
446  auto s = l.share_string(); \
447  if (s) \
448  { \
449  return s->compare(r) op 0; \
450  } \
451  else \
452  { \
453  return l.to_string().compare(r) op 0; \
454  } \
455  } \
456  \
457  inline bool operator op(const std::string& l, const KnowledgeRecord& r) \
458  { \
459  auto s = r.share_string(); \
460  if (s) \
461  { \
462  return l.compare(*s) op 0; \
463  } \
464  else \
465  { \
466  return l.compare(r.to_string()) op 0; \
467  } \
468  }
469 
476 
479 #define MADARA_KNOWLEDGE_BINARY_OP(op) \
480  template<typename T, typename std::enable_if< \
481  !std::is_convertible<T, KnowledgeRecord>::value && \
482  std::is_fundamental<T>::value, \
483  void*>::type = nullptr> \
484  inline auto operator op(const KnowledgeRecord& l, const T& r) \
485  ->decltype(l op knowledge_cast(r)) \
486  { \
487  return l op knowledge_cast(r); \
488  } \
489  \
490  template<typename T, typename std::enable_if< \
491  !std::is_convertible<T, KnowledgeRecord>::value && \
492  std::is_fundamental<T>::value, \
493  void*>::type = nullptr> \
494  inline auto operator op(const T& l, const KnowledgeRecord& r) \
495  ->decltype(knowledge_cast(l) op r) \
496  { \
497  return knowledge_cast(l) op r; \
498  }
499 
505 
508 #define MADARA_KNOWLEDGE_COMPOSITE_OP(op) \
509  template<typename T, typename std::enable_if< \
510  !std::is_convertible<T, KnowledgeRecord>::value && \
511  std::is_fundamental<T>::value, \
512  void*>::type = nullptr> \
513  inline auto operator op(KnowledgeRecord& l, const T& r) \
514  ->decltype(l op knowledge_cast(r)) \
515  { \
516  return l op knowledge_cast(r); \
517  }
518 
524 
525 template<typename OutputIterator>
526 size_t KnowledgeRecord::get_history_range(
527  OutputIterator out, size_t index, size_t count) const
528 {
529  return for_history_range(
530  [&out](const KnowledgeRecord& rec) {
531  knowledge_cast(rec, *out);
532  ++out;
533  },
534  index, count);
535 }
536 
537 } // namespace knowledge
538 } // namespace madara
539 
540 #endif
#define MADARA_KNOWLEDGE_COMPOSITE_OP(op)
Generates composite assignment operators for KnowledgeRecords, in combination with types that can be ...
#define MADARA_KNOWLEDGE_COMPARE_OP(op)
Generates comparison operators for KnowledgeRecords, in combination with types that can be knowledge_...
#define MADARA_KNOWLEDGE_BINARY_OP(op)
Generates binary math operators for KnowledgeRecords, in combination with types that can be knowledge...
This class encapsulates an entry in a KnowledgeBase.
std::string to_string(const std::string &delimiter=", ") const
converts the value to a string.
std::vector< Integer > to_integers(void) const
converts the value to a vector of integers
bool is_true(void) const
Checks to see if the record is true.
std::vector< double > to_doubles(void) const
converts the value to a vector of doubles
auto to_array(const KnowledgeRecord &in) -> typename std::enable_if< std::is_integral< typename std::decay< decltype(*std::begin(std::declval< T & >()))>::type >::value, decltype(in.to_integers())>::type
auto share_array(const KnowledgeRecord &in) -> typename std::enable_if< std::is_integral< typename std::decay< decltype(*std::begin(std::declval< T & >()))>::type >::value, decltype(in.share_integers())>::type
simple_span< T > make_span(T *ptr, size_t size)
auto get_size(const T &c) -> decltype(c.size())
constexpr doubles_t doubles
constexpr integers_t integers
constexpr string_t string
constexpr binary_t binary
Provides functions and classes for the distributed knowledge base.
auto knowledge_cast(type< O >, const KnowledgeRecord &in) -> typename std::enable_if< std::is_constructible< O, const KnowledgeRecord & >::value, O >::type
By default, call constructor of target class; for other semantics, define specializations.
Definition: KnowledgeCast.h:80
typename std::enable_if< Pred, T >::type enable_if_
Less verbose synonym for std::enable_if.
Definition: StlHelper.h:74
constexpr bool is_same()
Less verbose equivalent for std::is_same.
Definition: StlHelper.h:102
constexpr bool is_integral()
Less verbose equivalent for std::is_integral.
Definition: StlHelper.h:138
typename std::decay< T >::type decay_
Less verbose synonym for std::decay.
Definition: StlHelper.h:78
constexpr bool is_floating_point()
Less verbose equivalent for std::is_floating_point.
Definition: StlHelper.h:145
Copyright(c) 2020 Galois.