6 #ifndef TURI_FLEXIBLE_TYPE_FLEXIBLE_TYPE_CONVERTER_HPP 7 #define TURI_FLEXIBLE_TYPE_FLEXIBLE_TYPE_CONVERTER_HPP 10 #include <unordered_map> 12 #include <type_traits> 13 #include <core/util/code_optimization.hpp> 14 #include <core/data/flexible_type/type_traits.hpp> 15 #include <core/data/flexible_type/flexible_type.hpp> 16 #include <core/data/flexible_type/flexible_type_conversion_utilities.hpp> 25 template <
typename T>
static void convert_from_flexible_type(T& t,
const flexible_type& f);
26 template <
typename T>
static void convert_to_flexible_type(
flexible_type& f, T&& t);
27 template <
typename T>
static flexible_type convert_to_flexible_type(T&& t);
29 namespace flexible_type_internals {
47 static constexpr
int CVTR__FLEXIBLE_TYPE_EXACT = 1;
50 static constexpr
int CVTR__FLOATING_POINT = 2;
51 static constexpr
int CVTR__INTEGER = 3;
54 static constexpr
int CVTR__FLEX_STRING_CONVERTIBLE = 4;
59 static constexpr
int CVTR__FLEX_VEC_CONVERTIBLE_SEQUENCE = 5;
60 static constexpr
int CVTR__FLEX_VEC_CONVERTIBLE_PAIR = 6;
61 static constexpr
int CVTR__FLEX_VEC_CONVERTIBLE_TUPLE = 7;
64 static constexpr
int CVTR__FLEX_DICT_CONVERTIBLE_SEQUENCE = 8;
65 static constexpr
int CVTR__FLEX_DICT_CONVERTIBLE_MAPS = 9;
70 static constexpr
int CVTR__FLEX_LIST_CONVERTIBLE_PAIR = 10;
71 static constexpr
int CVTR__FLEX_LIST_CONVERTIBLE_TUPLE = 11;
72 static constexpr
int CVTR__FLEX_LIST_CONVERTIBLE_SEQUENCE = 12;
75 static constexpr
int CVTR__ENUM = 13;
79 static constexpr
int NUM_CONVERTER_STRUCTS = 14;
91 template <
typename T>
static constexpr
bool matches() {
return false; }
93 template <
typename T>
static inline void get(T& t,
const flexible_type& v) {
94 static_assert(swallow_to_false<T>::value,
"get with bad match.");
99 static_assert(swallow_to_false<T>::value,
"set with bad match.");
113 template <
typename T>
static constexpr
bool matches() {
114 return (std::is_same<T, flexible_type>::value
115 || std::is_same<T, flex_undefined>::value
116 || std::is_same<T, flex_int>::value
117 || std::is_same<T, flex_float>::value
118 || std::is_same<T, flex_string>::value
119 || std::is_same<T, flex_vec>::value
120 || std::is_same<T, flex_list>::value
121 || std::is_same<T, flex_dict>::value
122 || std::is_same<T, flex_image>::value
123 || std::is_same<T, flex_date_time>::value);
137 throw_type_conversion_error(src,
"numeric value");
138 ASSERT_UNREACHABLE();
148 if(UNLIKELY(v != dest)) {
149 throw_type_conversion_error(src,
"integer value");
150 ASSERT_UNREACHABLE();
153 throw_type_conversion_error(src,
"numeric integer value");
154 ASSERT_UNREACHABLE();
164 throw_type_conversion_error(src,
"vector of floats");
165 ASSERT_UNREACHABLE();
175 throw_type_conversion_error(src,
"vector of floats");
176 ASSERT_UNREACHABLE();
181 template <
typename T>
184 std::string errormsg = std::string(
"Expecting ")
194 template <
typename T>
196 dest = std::forward<T>(src);
210 template <
typename T>
static constexpr
bool matches() {
211 return std::is_floating_point<T>::value;
214 template <
typename Float>
217 dest =
static_cast<Float
>(src.get<
flex_float>());
219 dest =
static_cast<Float
>(src.get<
flex_int>());
221 throw_type_conversion_error(src,
"numeric");
222 ASSERT_UNREACHABLE();
226 template <
typename Float>
238 template <
typename T>
static constexpr
bool matches() {
239 return std::is_integral<T>::value || std::is_same<T, bool>::value;
242 template <
typename Integer>
246 if(static_cast<Integer>(v) != v) {
247 throw_type_conversion_error(src,
"integer / convertable float");
248 ASSERT_UNREACHABLE();
250 dest =
static_cast<Integer
>(v);
252 dest =
static_cast<Integer
>(src.get<
flex_int>());
254 throw_type_conversion_error(src,
"integer");
255 ASSERT_UNREACHABLE();
259 template <
typename Integer>
275 template <
typename T>
static constexpr
bool matches() {
276 return is_string<T>::value || std::is_same<T, const char*>::value;
279 template <
typename String>
283 dest.assign(s.begin(), s.end());
286 dest.assign(s.begin(), s.end());
290 static void get(
const char*& dest,
const flexible_type& src) {
294 throw_type_conversion_error(src,
"const char* (reference to temporary).");
295 ASSERT_UNREACHABLE();
299 template <
typename String>
320 template <
typename V>
static constexpr
bool matches() {
321 typedef typename first_nested_type<V>::type U;
323 return (is_sequence_container<V>::value
324 && (std::is_floating_point<U>::value || is_integer_in_4bytes<U>::value));
327 template <
typename Vector>
331 dest.assign(v.begin(), v.end());
334 dest.assign(f.begin(), f.end());
336 throw_type_conversion_error(src,
"flex_vec");
337 ASSERT_UNREACHABLE();
341 template <
typename Vector>
343 dest =
flex_vec(src.begin(), src.end());
358 template <
typename T>
static constexpr
bool matches() {
359 typedef typename first_nested_type<T>::type U1;
360 typedef typename second_nested_type<T>::type U2;
362 return (is_std_pair<T>::value
363 && std::is_floating_point<U1>::value
364 && std::is_floating_point<U2>::value);
367 template <
typename T,
typename U>
368 static void get(std::pair<T, U>& dest,
const flexible_type& src) {
372 throw_type_conversion_error(src,
"2-element flex_list/flex_vec (list size != 2)");
373 ASSERT_UNREACHABLE();
375 convert_from_flexible_type(dest.first, l[0]);
376 convert_from_flexible_type(dest.second, l[1]);
380 throw_type_conversion_error(src,
"2-element flex_list/flex_vec (vector size != 2)");
381 ASSERT_UNREACHABLE();
383 dest.first =
static_cast<T
>(v[0]);
384 dest.second =
static_cast<U
>(v[1]);
386 throw_type_conversion_error(src,
"2-element flex_list/flex_vec");
387 ASSERT_UNREACHABLE();
391 template <
typename T,
typename U>
392 static void set(
flexible_type& dest,
const std::pair<T,U>& src) {
393 if(std::is_floating_point<T>::value && std::is_floating_point<U>::value) {
396 dest =
flex_list{convert_to_flexible_type(src.first), convert_to_flexible_type(src.second)};
407 template <
typename T>
static constexpr
bool matches() {
408 return (is_tuple<T>::value && all_nested_true<std::is_arithmetic, T>::value);
411 template <
typename... Args>
412 static void get(std::tuple<Args...>& dest,
const flexible_type& src) {
413 switch(src.get_type()) {
417 if (d.size() !=
sizeof...(Args)) {
418 std::string errormsg =
419 std::string(
"Expecting a list or vector of length ")
420 + std::to_string(
sizeof...(Args)) +
", but we got a list of length " 421 + std::to_string(d.size());
430 if (d.size() !=
sizeof...(Args)) {
431 std::string errormsg =
432 std::string(
"Expecting a list or vector of length ")
433 + std::to_string(
sizeof...(Args)) +
", but we got a vector of length " 434 + std::to_string(d.size());
442 std::string errormsg =
443 std::string(
"Expecting a list or vector of length ")
444 + std::to_string(
sizeof...(Args)) +
", but we got a " 451 template <
typename... Args>
452 static void set(
flexible_type& dest,
const std::tuple<Args...> & src) {
454 unpack_tuple(v, src);
470 template <>
struct ft_converter<CVTR__FLEX_DICT_CONVERTIBLE_SEQUENCE> {
472 template <
typename T>
static constexpr
bool matches() {
473 typedef typename first_nested_type<T>::type pair_type;
479 template <
typename T,
typename U,
template <
typename...>
class C>
480 static void get(C<std::pair<T, U> >& dest,
const flexible_type& src) {
483 dest.resize(fd.size());
484 for(
size_t i = 0; i < fd.size(); ++i) {
485 convert_from_flexible_type(dest[i].first, fd[i].first);
486 convert_from_flexible_type(dest[i].second, fd[i].second);
490 dest.resize(fl.size());
491 for(
size_t i = 0; i < fl.size(); ++i) {
492 convert_from_flexible_type(dest[i], fl[i]);
495 throw_type_conversion_error(src,
"flex_dict or flex_list of 2-element list/vectors");
496 ASSERT_UNREACHABLE();
500 template <
typename T,
typename U,
template <
typename...>
class C>
501 static void set(
flexible_type& dest,
const C<std::pair<T, U> >& src) {
503 for(
size_t i = 0; i < src.size();++i) {
504 d[i] = std::make_pair(convert_to_flexible_type(src[i].first), convert_to_flexible_type(src[i].second));
517 template <
typename T>
static constexpr
bool matches() {
519 typedef typename first_nested_type<T>::type U1;
520 typedef typename second_nested_type<T>::type U2;
522 return (is_map<T>::value
527 template <
typename T>
529 std::pair<typename T::key_type, typename T::mapped_type> p;
535 for(
size_t i = 0; i < fd.size(); ++i) {
536 convert_from_flexible_type(p.first, fd[i].first);
537 convert_from_flexible_type(p.second, fd[i].second);
538 dest.insert(std::move(p));
542 for(
size_t i = 0; i < l.size(); ++i) {
543 convert_from_flexible_type(p, l[i]);
544 dest.insert(std::move(p));
547 throw_type_conversion_error(src,
"flex_dict / list of 2-element flex_lists/flex_vec");
548 ASSERT_UNREACHABLE();
552 template <
typename T>
555 fd.reserve(src.size());
556 for(
const auto& p : src) {
557 fd.push_back({convert_to_flexible_type(p.first), convert_to_flexible_type(p.second)});
559 dest = std::move(fd);
576 template <
typename T>
static constexpr
bool matches() {
577 typedef typename first_nested_type<T>::type U1;
578 typedef typename second_nested_type<T>::type U2;
580 return (is_std_pair<T>::value
585 template <
typename T,
typename U>
586 static void get(std::pair<T, U>& dest,
const flexible_type& src) {
590 throw_type_conversion_error(src,
"2-element flex_list/flex_vec (list size != 2)");
591 ASSERT_UNREACHABLE();
593 convert_from_flexible_type(dest.first, l[0]);
594 convert_from_flexible_type(dest.second, l[1]);
596 throw_type_conversion_error(src,
"2-element flex_list/flex_vec");
597 ASSERT_UNREACHABLE();
601 template <
typename T,
typename U>
602 static void set(
flexible_type& dest,
const std::pair<T,U>& src) {
603 dest =
flex_list{convert_to_flexible_type(src.first), convert_to_flexible_type(src.second)};
614 template <
typename T>
static constexpr
bool matches() {
615 return (is_tuple<T>::value && all_nested_true<is_flexible_type_convertible, T>::value);
618 template <
typename... Args>
619 static void get(std::tuple<Args...>& dest,
const flexible_type& src) {
620 switch(src.get_type()) {
624 if (d.size() !=
sizeof...(Args)) {
625 std::string errormsg =
626 std::string(
"Expecting a list or vector of length ")
627 + std::to_string(
sizeof...(Args)) +
", but we got a list of length " 628 + std::to_string(d.size());
636 std::string errormsg =
637 std::string(
"Expecting a list or vector of length ")
638 + std::to_string(
sizeof...(Args)) +
", but we got a " 645 template <
typename... Args>
646 static void set(
flexible_type& dest,
const std::tuple<Args...> & src) {
648 unpack_tuple(v, src);
659 template <>
struct ft_converter<CVTR__FLEX_LIST_CONVERTIBLE_SEQUENCE> {
661 template <
typename T>
static constexpr
bool matches() {
663 is_sequence_container<T>::value,
667 template <
typename FlexContainer>
668 static void get(FlexContainer& dest,
const flexible_type& src) {
669 switch(src.get_type()) {
672 dest.resize(fl.size());
673 auto it = dest.begin();
674 for(
size_t i = 0; i < fl.size(); ++i, ++it) {
675 typename FlexContainer::value_type t;
676 convert_from_flexible_type(t, fl[i]);
683 dest.resize(fv.size());
685 auto it = dest.begin();
686 for(
size_t i = 0; i < fv.size(); ++i, ++it) {
687 typename FlexContainer::value_type t;
699 throw_type_conversion_error(src,
"flex_list");
700 ASSERT_UNREACHABLE();
705 template <
typename FlexContainer>
706 static void set(
flexible_type& dest,
const FlexContainer& src) {
709 auto it = src.begin();
710 for(
size_t i = 0; i < fl.size(); ++i, ++it) {
713 typename first_nested_type<FlexContainer>::type v = *it;
714 fl[i] = convert_to_flexible_type(std::move(v));
717 dest = std::move(fl);
742 template <
typename T>
static constexpr
bool matches() {
743 return std::is_enum<T>::value;
746 template <
typename Enum>
749 dest =
static_cast<Enum
>(src.get<
flex_int>());
751 throw_type_conversion_error(src,
"integer / enum.");
752 ASSERT_UNREACHABLE();
756 template <
typename Enum>
769 template <
int idx>
struct ft_resolver {
775 template <
typename T>
static constexpr
bool any_match(
781 template <
typename T>
static constexpr
bool any_match(
783 return ft_resolver<idx - 1>::template any_match<T>();
789 template <
typename T>
static constexpr
bool matches() {
791 && !ft_resolver<idx - 1>::template any_match<T>());
797 template <
typename T>
799 typename std::enable_if<matches<T>()>::type* = NULL) {
803 template <
typename T>
805 typename std::enable_if<!matches<T>()>::type* = NULL) {
806 ft_resolver<idx - 1>::get(t, v);
809 template <
typename T>
811 typename std::enable_if<matches<T>()>::type* = NULL) {
815 template <
typename T>
817 typename std::enable_if<!matches<T>()>::type* = NULL) {
818 ft_resolver<idx - 1>::set(t, std::forward<T>(v));
823 template <>
struct ft_resolver<0> {
824 template <
typename T>
static constexpr
bool any_match() {
return false; }
825 template <
typename T>
static constexpr
bool matches() {
return false; }
826 template <
typename... T>
static void set(T...) {}
827 template <
typename... T>
static void get(T...) {}
836 template <
typename T>
838 static constexpr
bool value = flexible_type_internals::ft_resolver<
839 flexible_type_internals::NUM_CONVERTER_STRUCTS-1>::template any_match<typename base_type<T>::type>();
843 static void convert_from_flexible_type(T& t,
const flexible_type& f) {
846 flexible_type_internals::ft_resolver<flexible_type_internals::NUM_CONVERTER_STRUCTS-1>::get(t, f);
850 static void convert_to_flexible_type(
flexible_type& f, T&& t) {
853 flexible_type_internals::ft_resolver<flexible_type_internals::NUM_CONVERTER_STRUCTS-1>::set(f, std::forward<T>(t));
861 flexible_type_internals::ft_resolver<flexible_type_internals::NUM_CONVERTER_STRUCTS-1>::set(f, std::forward<T>(t));
867 template <
typename T>
872 flexible_type set(
const T& t)
const {
return convert_to_flexible_type(t); }
873 flexible_type set(T&& t)
const {
return convert_to_flexible_type(t); }
876 convert_from_flexible_type(t, f);
883 template <
typename... Args>
std::vector< double > flex_vec
const char * flex_type_enum_to_name(flex_type_enum en)
#define GL_HOT_INLINE_FLATTEN
std::vector< std::pair< flexible_type, flexible_type > > flex_dict
std::vector< flexible_type > flex_list