1 /* 2 * Copyright 2019 by its authors. See AUTHORS. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 #ifndef EOLIAN_MONO_MARSHALL_TYPE_IMPL_HH 17 #define EOLIAN_MONO_MARSHALL_TYPE_IMPL_HH 18 19 #include "grammar/generator.hpp" 20 #include "grammar/klass_def.hpp" 21 #include "grammar/case.hpp" 22 #include "helpers.hh" 23 #include "name_helpers.hh" 24 #include "type_match.hh" 25 #include "type_impl.hh" 26 #include "generation_contexts.hh" 27 #include "blacklist.hh" 28 29 namespace eolian_mono { 30 31 namespace eina = efl::eina; 32 33 namespace detail { 34 35 template <typename OutputIterator, typename Context> 36 struct marshall_type_visitor_generate 37 { 38 mutable OutputIterator sink; 39 Context const* context; 40 std::string c_type; 41 bool is_out; 42 bool is_return; 43 bool is_ptr; 44 bool is_special_subtype; 45 46 typedef marshall_type_visitor_generate<OutputIterator, Context> visitor_type; 47 typedef bool result_type; 48 operator ()eolian_mono::detail::marshall_type_visitor_generate49 bool operator()(attributes::regular_type_def const& regular) const 50 { 51 using attributes::regular_type_def; 52 53 struct match 54 { 55 eina::optional<std::string> name; 56 eina::optional<bool> has_own; 57 std::function<attributes::type_def::variant_type()> function; 58 } 59 const match_table[] = 60 { 61 // signed primitives 62 {"string", true, [&] 63 { 64 regular_type_def r = regular; 65 r.base_qualifier.qualifier ^= qualifier_info::is_ref; 66 return replace_base_type(r, "System.String"); 67 }} 68 , {"string", false, [&] 69 { 70 regular_type_def r = regular; 71 r.base_qualifier.qualifier ^= qualifier_info::is_ref; 72 return replace_base_type(r, "System.String"); 73 }} 74 , {"mstring", true, [&] 75 { 76 regular_type_def r = regular; 77 r.base_qualifier.qualifier ^= qualifier_info::is_ref; 78 return replace_base_type(r, "System.String"); 79 }} 80 , {"mstring", false, [&] 81 { 82 regular_type_def r = regular; 83 r.base_qualifier.qualifier ^= qualifier_info::is_ref; 84 return replace_base_type(r, "System.String"); 85 }} 86 , {"stringshare", true, [&] 87 { 88 regular_type_def r = regular; 89 r.base_qualifier.qualifier ^= qualifier_info::is_ref; 90 if (is_special_subtype) 91 return replace_base_type(r, "Eina.Stringshare"); 92 return replace_base_type(r, "System.String"); 93 }} 94 , {"stringshare", false, [&] 95 { 96 regular_type_def r = regular; 97 r.base_qualifier.qualifier ^= qualifier_info::is_ref; 98 if (is_special_subtype) 99 return replace_base_type(r, "Eina.Stringshare"); 100 return replace_base_type(r, "System.String"); 101 }} 102 , {"strbuf", nullptr, [&] 103 { 104 regular_type_def r = regular; 105 r.base_qualifier.qualifier ^= qualifier_info::is_ref; 106 return replace_base_type(r, "Eina.Strbuf"); 107 }} 108 , {"Binbuf", true, [&] 109 { 110 regular_type_def r = regular; 111 r.base_type = "System.IntPtr"; 112 r.namespaces.clear(); 113 return r; 114 }} 115 , {"Binbuf", false, [&] 116 { 117 regular_type_def r = regular; 118 r.base_type = "System.IntPtr"; 119 r.namespaces.clear(); 120 return r; 121 }} 122 , {"binbuf", nullptr, [&] 123 { 124 regular_type_def r = regular; 125 r.base_type = "System.IntPtr"; 126 r.namespaces.clear(); 127 return r; 128 }} 129 , {"event", nullptr, [&] 130 { 131 regular_type_def r = regular; 132 r.base_type = "Efl.Event"; 133 r.namespaces.clear(); 134 return r; 135 }} 136 , {"any_value", true, [&] 137 { 138 regular_type_def r = regular; 139 r.namespaces.clear(); 140 if (is_ptr) 141 r.base_type = "Eina.Value"; 142 else 143 r.base_type = "Eina.ValueNative"; 144 return r; 145 }} 146 , {"any_value", false, [&] 147 { 148 regular_type_def r = regular; 149 r.namespaces.clear(); 150 if (is_ptr) 151 r.base_type = "Eina.Value"; 152 else 153 r.base_type = "Eina.ValueNative"; 154 return r; 155 }} 156 , {"any_value_ref", true, [&] 157 { 158 regular_type_def r = regular; 159 r.namespaces.clear(); 160 r.base_type = "Eina.Value"; 161 return r; 162 }} 163 , {"any_value_ref", false, [&] 164 { 165 regular_type_def r = regular; 166 r.namespaces.clear(); 167 r.base_type = "Eina.Value"; 168 return r; 169 }} 170 , {"void", nullptr, [&] 171 { 172 regular_type_def r = regular; 173 r.namespaces.clear(); 174 if (is_out) // @inout too 175 r.base_type = "System.IntPtr"; 176 else 177 r.base_type = "void"; 178 return r; 179 }} 180 , {"Value_Type", nullptr, [&] 181 { 182 regular_type_def r = regular; 183 r.namespaces.clear(); 184 r.base_type = "Eina.ValueTypeBox"; 185 return r; 186 }} 187 }; 188 189 if (regular.is_struct() && !blacklist::is_struct_blacklisted(regular) && !(bool)(regular.base_qualifier & qualifier_info::is_own)) 190 { 191 if ((is_out || is_return) && is_ptr) 192 return as_generator("System.IntPtr").generate(sink, attributes::unused, *context); 193 return as_generator(string) 194 .generate(sink, name_helpers::type_full_managed_name(regular), *context); 195 } 196 else if (eina::optional<bool> b = type_match::get_match 197 (match_table 198 , [&] (match const& m) 199 { 200 return (!m.name || *m.name == regular.base_type) 201 && (!m.has_own || *m.has_own == (bool)(regular.base_qualifier & qualifier_info::is_own)) 202 ; 203 } 204 , [&] (attributes::type_def::variant_type const& v) 205 { 206 return v.visit(visitor_regular_type_def_printer<OutputIterator, Context>{sink, context}); // we want to keep is_out info 207 })) 208 { 209 return *b; 210 } 211 else if (is_ptr && helpers::need_pointer_conversion(®ular)) 212 { 213 regular_type_def r = regular; 214 r.base_type = "System.IntPtr"; 215 r.namespaces.clear(); 216 return visitor_generate<OutputIterator, Context>{ 217 sink 218 , context 219 , c_type 220 , is_out 221 , is_return 222 , is_ptr 223 , false 224 , is_special_subtype 225 }(r); 226 } 227 else 228 { 229 return visitor_generate<OutputIterator, Context>{ 230 sink 231 , context 232 , c_type 233 , is_out 234 , is_return 235 , is_ptr 236 , false 237 , is_special_subtype 238 }(regular); 239 } 240 } operator ()eolian_mono::detail::marshall_type_visitor_generate241 bool operator()(attributes::klass_name klass_name) const 242 { 243 return visitor_generate<OutputIterator, Context>{ 244 sink 245 , context 246 , c_type 247 , is_out 248 , is_return 249 , is_ptr 250 , false 251 , is_special_subtype 252 }(klass_name); 253 } operator ()eolian_mono::detail::marshall_type_visitor_generate254 bool operator()(attributes::complex_type_def const& complex) const 255 { 256 using attributes::regular_type_def; 257 using attributes::qualifier_info; 258 struct match 259 { 260 eina::optional<std::string> name; 261 eina::optional<bool> has_own; 262 eina::optional<bool> is_const; 263 std::function<attributes::type_def::variant_type()> function; 264 } const matches[] = 265 { 266 {"array", nullptr, nullptr, [&] 267 { 268 return regular_type_def{"System.IntPtr", complex.outer.base_qualifier, {}}; 269 } 270 } 271 ,{"list", nullptr, nullptr, [&] 272 { 273 return regular_type_def{"System.IntPtr", complex.outer.base_qualifier, {}}; 274 } 275 } 276 ,{"hash", nullptr, nullptr, [&] 277 { 278 return regular_type_def{"System.IntPtr", complex.outer.base_qualifier, {}}; 279 } 280 } 281 ,{"iterator", nullptr, nullptr, [&] 282 { 283 return regular_type_def{"System.IntPtr", complex.outer.base_qualifier, {}}; 284 } 285 } 286 ,{"accessor", nullptr, nullptr, [&] 287 { 288 return regular_type_def{"System.IntPtr", complex.outer.base_qualifier, {}}; 289 } 290 } 291 }; 292 293 auto default_match = [&] (attributes::complex_type_def const& complex) 294 { 295 regular_type_def no_pointer_regular = complex.outer; 296 return visitor_type{sink, context, c_type, false, false, false, false}(no_pointer_regular) 297 && as_generator("<" << (type(false, false, true) % ", ") << ">").generate(sink, complex.subtypes, *context); 298 }; 299 300 if(eina::optional<bool> b = type_match::get_match 301 (matches 302 , [&] (match const& m) 303 { 304 return (!m.name || *m.name == complex.outer.base_type) 305 && (!m.has_own || *m.has_own == bool(complex.outer.base_qualifier & qualifier_info::is_own)) 306 && (!m.is_const || *m.is_const == bool(complex.outer.base_qualifier & qualifier_info::is_const)); 307 } 308 , [&] (attributes::type_def::variant_type const& v) 309 { 310 if(v.empty()) 311 return true; 312 else if(attributes::complex_type_def const* complex 313 = eina::get<attributes::complex_type_def>(&v)) 314 return default_match(*complex); 315 else 316 return v.visit(*this); 317 })) 318 { 319 return *b; 320 } 321 322 return visitor_generate<OutputIterator, Context>{ 323 sink 324 , context 325 , c_type 326 , is_out 327 , is_return 328 , is_ptr 329 , false 330 , is_special_subtype 331 }(complex); 332 } 333 }; 334 } } 335 336 #endif 337