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_STRUCT_FIELDS_HH 17 #define EOLIAN_MONO_STRUCT_FIELDS_HH 18 19 #include "grammar/generator.hpp" 20 #include "grammar/klass_def.hpp" 21 #include "grammar/indentation.hpp" 22 #include "grammar/list.hpp" 23 #include "grammar/alternative.hpp" 24 #include "name_helpers.hh" 25 #include "type.hh" 26 #include "using_decl.hh" 27 #include "documentation.hh" 28 29 namespace eolian_mono { 30 31 struct field_argument_name_generator 32 { 33 template<typename OutputIterator, typename Context> generateeolian_mono::field_argument_name_generator34 bool generate(OutputIterator sink, attributes::struct_field_def const& field, Context const& context) const 35 { 36 if (!as_generator(name_helpers::to_field_name(field.name)) 37 .generate(sink, attributes::unused, context)) 38 return false; 39 return true; 40 } 41 } const field_argument_name {}; 42 43 struct field_argument_decl_generator 44 { 45 template<typename OutputIterator, typename Context> generateeolian_mono::field_argument_decl_generator46 bool generate(OutputIterator sink, attributes::struct_field_def const& field, Context const& context) const 47 { 48 if (!as_generator(type << " " << string) 49 .generate(sink, std::make_tuple(field.type, name_helpers::to_field_name(field.name)), context)) 50 return false; 51 return true; 52 } 53 } const field_argument_decl {}; 54 55 struct field_argument_default_generator 56 { 57 template<typename OutputIterator, typename Context> generateeolian_mono::field_argument_default_generator58 bool generate(OutputIterator sink, attributes::struct_field_def const& field, Context const& context) const 59 { 60 if (!as_generator(type << " " << string << " = default(" << type << ")") 61 .generate(sink, std::make_tuple(field.type, name_helpers::to_field_name(field.name), field.type), context)) 62 return false; 63 return true; 64 } 65 } const field_argument_default {}; 66 67 struct field_argument_assignment_generator 68 { 69 template<typename OutputIterator, typename Context> generateeolian_mono::field_argument_assignment_generator70 bool generate(OutputIterator sink, attributes::struct_field_def const& field, Context const& context) const 71 { 72 auto field_name = to_field_name(field.name); 73 // FIXME Replace need_struct_conversion(regular) with need_struct_conversion(type) 74 auto regular = efl::eina::get<attributes::regular_type_def>(&field.type.original_type); 75 auto klass = efl::eina::get<attributes::klass_name>(&field.type.original_type); 76 auto complex = efl::eina::get<attributes::complex_type_def>(&field.type.original_type); 77 78 if (klass) 79 { 80 if (!as_generator( 81 "this." << string << " = " << string << "?.NativeHandle ?? System.IntPtr.Zero;\n") 82 .generate(sink, std::make_tuple(field_name, field_name), context)) 83 return false; 84 } 85 else if ((complex && (complex->outer.base_type == "array"))) 86 { 87 if (!as_generator( 88 "this." << string << " = Efl.Eo.Globals.IListToNativeArray(" << string << ", " << (field.type.has_own ? "true" : "false") << ");\n") 89 .generate(sink, std::make_tuple(field_name, field_name), context)) 90 return false; 91 } 92 else if ((complex && (complex->outer.base_type == "list"))) 93 { 94 if (!as_generator( 95 "this." << string << " = Efl.Eo.Globals.IListToNativeList(" << string << ", " << (field.type.has_own ? "true" : "false") << ");\n") 96 .generate(sink, std::make_tuple(field_name, field_name), context)) 97 return false; 98 } 99 else if ((complex && (complex->outer.base_type == "iterator"))) 100 { 101 if (!as_generator( 102 "this." << string << " = Efl.Eo.Globals.IEnumerableToIterator(" << string << ", " << (field.type.has_own ? "true" : "false") << ");\n") 103 .generate(sink, std::make_tuple(field_name, field_name), context)) 104 return false; 105 } 106 else if ((complex && (complex->outer.base_type == "accessor"))) 107 { 108 if (!as_generator( 109 "this." << string << " = Efl.Eo.Globals.IEnumerableToAccessor(" << string << ", " << (field.type.has_own ? "true" : "false") << ");\n") 110 .generate(sink, std::make_tuple(field_name, field_name), context)) 111 return false; 112 } 113 else if ((complex && (complex->outer.base_type == "hash")) 114 || field.type.c_type == "Eina_Binbuf *" || field.type.c_type == "const Eina_Binbuf *") 115 { 116 // Always assumes pointer 117 if (!as_generator( 118 "this." << string << " = " << string << ".Handle;\n") 119 .generate(sink, std::make_tuple(field_name, field_name), context)) 120 return false; 121 } 122 else if (field.type.is_ptr && helpers::need_pointer_conversion(regular) && !helpers::need_struct_conversion(regular)) 123 { 124 if (!as_generator( 125 "this." << string << " = Eina.PrimitiveConversion.ManagedToPointerAlloc(" << string << ");\n") 126 .generate(sink, std::make_tuple(field_name, field_name), context)) 127 return false; 128 } 129 else if (helpers::need_struct_conversion(regular)) 130 { 131 if (!as_generator( 132 "this." << string << " = " << string << ";\n") 133 .generate(sink, std::make_tuple(field_name, field_name), context)) 134 return false; 135 } 136 else if (regular && (regular->base_type == "string" || regular->base_type == "mstring")) 137 { 138 if (!as_generator( 139 "this." << string << " = Eina.MemoryNative.StrDup(" << string << ");\n") 140 .generate(sink, std::make_tuple(field_name, field_name), context)) 141 return false; 142 } 143 else if (regular && regular->base_type == "stringshare") 144 { 145 if (!as_generator( 146 "this." << string << " = Eina.MemoryNative.AddStringshare(" << string << ");\n") 147 .generate(sink, std::make_tuple(field_name, field_name), context)) 148 return false; 149 } 150 else if (field.type.c_type == "Eina_Slice" || field.type.c_type == "const Eina_Slice" 151 || field.type.c_type == "Eina_Rw_Slice" || field.type.c_type == "const Eina_Rw_Slice") 152 { 153 if (!as_generator( 154 "this." << string << " = " << string << ";\n") 155 .generate(sink, std::make_tuple(field_name, field_name), context)) 156 return false; 157 } 158 else if (field.type.c_type == "Eina_Value" || field.type.c_type == "const Eina_Value") 159 { 160 if (!as_generator( 161 "this." << string << " = " << string << ".GetNative();\n" 162 ).generate(sink, std::make_tuple(field_name, field_name), context)) 163 return false; 164 } 165 else if (field.type.c_type == "Eina_Value *" || field.type.c_type == "const Eina_Value *") 166 { 167 if (!as_generator( 168 "this." << string << " = " << string << "?.NativeHandle ?? System.IntPtr.Zero;\n" 169 ).generate(sink, std::make_tuple(field_name, field_name), context)) 170 return false; 171 } 172 else if (!field.type.is_ptr && regular && regular->base_type == "bool") 173 { 174 if (!as_generator( 175 "this." << string << " = " << string << " ? (byte)1 : (byte)0;\n") 176 .generate(sink, std::make_tuple(field_name, field_name), context)) 177 return false; 178 } 179 else if (!field.type.is_ptr && regular && regular->base_type == "char") 180 { 181 if (!as_generator( 182 "this." << string << " = (byte)" << string << ";\n") 183 .generate(sink, std::make_tuple(field_name, field_name), context)) 184 return false; 185 } 186 else // primitives and enums 187 { 188 if (!as_generator( 189 "this." << string << " = " << string << ";\n") 190 .generate(sink, std::make_tuple(field_name, field_name), context)) 191 return false; 192 } 193 return true; 194 } 195 } const field_argument_assignment {}; 196 197 struct field_argument_docs_generator 198 { 199 template<typename OutputIterator, typename Context> generateeolian_mono::field_argument_docs_generator200 bool generate(OutputIterator sink, attributes::struct_field_def const& field, Context const& context) const 201 { 202 if (!as_generator(current_indentation(context) << "/// <param name=\"" << string << "\">" << documentation_string << "</param>") 203 .generate(sink, std::make_tuple(name_helpers::to_field_name(field.name), field.documentation.summary), context)) 204 return false; 205 return true; 206 } 207 } const field_argument_docs {}; 208 209 } 210 211 namespace efl { namespace eolian { namespace grammar { 212 213 template<> 214 struct is_eager_generator< ::eolian_mono::field_argument_name_generator> : std::true_type {}; 215 template<> 216 struct is_generator< ::eolian_mono::field_argument_name_generator> : std::true_type {}; 217 218 template<> 219 struct is_eager_generator< ::eolian_mono::field_argument_decl_generator> : std::true_type {}; 220 template<> 221 struct is_generator< ::eolian_mono::field_argument_decl_generator> : std::true_type {}; 222 223 template<> 224 struct is_eager_generator< ::eolian_mono::field_argument_default_generator> : std::true_type {}; 225 template<> 226 struct is_generator< ::eolian_mono::field_argument_default_generator> : std::true_type {}; 227 228 template<> 229 struct is_eager_generator< ::eolian_mono::field_argument_assignment_generator> : std::true_type {}; 230 template<> 231 struct is_generator< ::eolian_mono::field_argument_assignment_generator> : std::true_type {}; 232 233 template<> 234 struct is_eager_generator< ::eolian_mono::field_argument_docs_generator> : std::true_type {}; 235 template<> 236 struct is_generator< ::eolian_mono::field_argument_docs_generator> : std::true_type {}; 237 238 namespace type_traits { 239 240 template <> 241 struct attributes_needed< ::eolian_mono::field_argument_name_generator> : std::integral_constant<int, 1> {}; 242 243 template <> 244 struct attributes_needed< ::eolian_mono::field_argument_decl_generator> : std::integral_constant<int, 1> {}; 245 246 template <> 247 struct attributes_needed< ::eolian_mono::field_argument_default_generator> : std::integral_constant<int, 1> {}; 248 249 template <> 250 struct attributes_needed< ::eolian_mono::field_argument_assignment_generator> : std::integral_constant<int, 1> {}; 251 252 template <> 253 struct attributes_needed< ::eolian_mono::field_argument_docs_generator> : std::integral_constant<int, 1> {}; 254 255 } 256 257 } } } 258 259 #endif 260 261