summaryrefslogtreecommitdiff
path: root/src/bin/eolian_cxx/type_lookup.hh
blob: 1b64bbb20b54b4da500f27197106eff0ef3ae35e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96

#ifndef EOLIAN_CXX_TYPE_LOOKUP_HH
#define EOLIAN_CXX_TYPE_LOOKUP_HH

#include <algorithm>
#include <string>
#include <vector>
#include <cctype>
#include <iterator>
#include <cassert>
#include <cstddef>

#include <Eolian.h>
#include <eolian_database.h>

#include <Eina.hh>

#include "eo_types.hh"
#include "safe_strings.hh"

namespace eolian_cxx {

typedef std::vector<efl::eolian::eolian_type> lookup_table_type;
extern const lookup_table_type type_lookup_table;

inline bool
type_is_complex(Eolian_Type const& type)
{
   return ::eolian_type_type_get(&type) == EOLIAN_TYPE_COMPLEX;
}

inline efl::eolian::eolian_type
type_from_eolian(Eolian_Type const& type)
{
   efl::eolian::eolian_type x;
   x.native = normalize_spaces(safe_str(::eolian_type_c_type_get(&type)));
   x.is_own = ::eolian_type_is_own(&type);
   x.is_const = ::eolian_type_is_const(&type);
   return x;
}

template <typename Iterator>
inline const efl::eolian::eolian_type&
type_find(Iterator first, Iterator last, efl::eolian::eolian_type const& type)
{
   auto res = std::find_if
     (first, last,
      [&type] (efl::eolian::eolian_type const& x)
      {
        return (x.native == type.native && x.is_own == type.is_own);
      });
   return (res != last) ? *res : type;
}

inline efl::eolian::eolian_type_instance
type_lookup(const Eolian_Type* type,
            lookup_table_type const& lut = type_lookup_table)
{
   if (type == NULL) return { efl::eolian::void_type }; // XXX shouldn't
   // assert(type != NULL);

   std::vector<Eolian_Type const*> types;
   types.push_back(type);

   if (::eolian_type_type_get(type) == EOLIAN_TYPE_POINTER && type_is_complex(*eolian_type_base_type_get(type)))
     {
        efl::eina::iterator<Eolian_Type const> end;
        efl::eina::iterator<Eolian_Type const> it
          (::eolian_type_subtypes_get(eolian_type_base_type_get(type)));
        while(it != end)
          {
             if(Eolian_Type const* t = &*it)
               types.push_back(t), ++it;
          }
     }

   efl::eolian::eolian_type_instance v(types.size());
   for (std::size_t i = 0; i != types.size(); ++i)
     {
        v[i] = type_find(lut.begin(), lut.end(), type_from_eolian(*types[i]));
     }

   // Let's degrade to opaque classes when not enough information
   // is available for complex types
   if(v.size() == 1 && type_is_complex(v[0]))
     {
       efl::eolian::eolian_type tmp = v[0];
       return {efl::eolian::type_to_native(tmp)};
     }

   return v;
}

} // namespace eolian_cxx {

#endif // EOLIAN_CXX_TYPE_LOOKUP_HH