diff --git a/src/bin/eolian_mono/eolian/mono/events.hh b/src/bin/eolian_mono/eolian/mono/events.hh index 2acfcbb4b5..7405f8c2e1 100644 --- a/src/bin/eolian_mono/eolian/mono/events.hh +++ b/src/bin/eolian_mono/eolian/mono/events.hh @@ -1,606 +1,619 @@ /* * Copyright 2019 by its authors. See AUTHORS. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef EOLIAN_MONO_EVENTS_HH #define EOLIAN_MONO_EVENTS_HH #include #include #include "grammar/generator.hpp" #include "grammar/klass_def.hpp" #include "type_match.hh" #include "name_helpers.hh" #include "using_decl.hh" namespace eolian_mono { namespace eina = efl::eina; template struct unpack_event_args_visitor { mutable OutputIterator sink; Context const* context; attributes::type_def const& type; typedef unpack_event_args_visitor visitor_type; typedef bool result_type; bool operator()(grammar::attributes::regular_type_def const& regular) const { std::string const& arg = "info"; std::string arg_type = name_helpers::type_full_managed_name(regular); if (regular.is_struct()) { // Structs are usually passed by pointer to events, like having a ptr<> modifier // Uses implicit conversion from IntPtr return as_generator( " info" ).generate(sink, attributes::unused, *context); } else if (type.is_ptr) { return as_generator("(" + arg_type + ")Marshal.PtrToStructure(" + arg + ", typeof(" + arg_type + "))") .generate(sink, attributes::unused, *context); } using attributes::regular_type_def; struct match { eina::optional name; std::function function; } /// Sizes taken from https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/sizeof const match_table [] = { {"bool", [&arg] { return "Marshal.ReadByte(" + arg + ") != 0"; }} , {"ubyte", [&arg] { return "Marshal.ReadByte(" + arg + ")"; }} , {"byte", [&arg] { return "(sbyte) Marshal.ReadByte(" + arg + ")"; }} , {"char", [&arg] { return "(char) Marshal.ReadByte(" + arg + ")"; }} , {"short", [&arg] { return "Marshal.ReadInt16(" + arg + ")"; }} , {"ushort", [&arg] { return "(ushort) Marshal.ReadInt16(" + arg + ")"; }} , {"int", [&arg] { return "Marshal.ReadInt32(" + arg + ")"; }} , {"uint", [&arg] { return "(uint) Marshal.ReadInt32(" + arg + ")"; }} , {"long", [&arg] { return "Marshal.ReadInt64(" + arg + ")"; }} , {"ulong", [&arg] { return "(ulong) Marshal.ReadInt64(" + arg + ")"; }} , {"llong", [&arg] { return "(long) Marshal.ReadInt64(" + arg + ")"; }} , {"ullong", [&arg] { return "(ulong) Marshal.ReadInt64(" + arg + ")"; }} , {"int8", [&arg] { return "(sbyte)Marshal.ReadByte(" + arg + ")"; }} , {"uint8", [&arg] { return "Marshal.ReadByte(" + arg + ")"; }} , {"int16", [&arg] { return "Marshal.ReadInt16(" + arg + ")"; }} , {"uint16", [&arg] { return "(ushort)Marshal.ReadInt16(" + arg + ")"; }} , {"int32", [&arg] { return "Marshal.ReadInt32(" + arg + ")"; }} , {"uint32", [&arg] { return "(uint) Marshal.ReadInt32(" + arg + ")"; }} // We don't support int128 as csharp has no similar datatype. , {"int64", [&arg] { return "Marshal.ReadInt64(" + arg + ")"; }} , {"uint64", [&arg] { return "(ulong) Marshal.ReadInt64(" + arg + ")"; }} , {"float", [&arg] { return "Eina.PrimitiveConversion.PointerToManaged(" + arg + ")"; }} , {"double", [&arg] { return "Eina.PrimitiveConversion.PointerToManaged(" + arg + ")"; }} , {"string", [&arg] { return "Eina.StringConversion.NativeUtf8ToManagedString(" + arg + ")"; }} , {"stringshare", [&arg] { return "Eina.StringConversion.NativeUtf8ToManagedString(" + arg + ")"; }} , {"Eina.Error", [&arg] { return "(Eina.Error)Marshal.PtrToStructure(" + arg + ", typeof(Eina.Error))"; }} }; std::string full_type_name = name_helpers::type_full_eolian_name(regular); auto filter_func = [®ular, &full_type_name] (match const& m) { return (!m.name || *m.name == regular.base_type || *m.name == full_type_name); }; auto accept_func = [&](std::string const& conversion) { return as_generator(conversion).generate(sink, attributes::unused, *context); }; if (eina::optional b = type_match::get_match(match_table, filter_func, accept_func)) return *b; else { // Type defined in Eo is passed here. (e.g. enum type defined in Eo) // Uses conversion from IntPtr with type casting to the given type. return as_generator( " (" << arg_type << ")info" ).generate(sink, attributes::unused, *context); } } bool operator()(grammar::attributes::klass_name const& cls) const { return as_generator("(Efl.Eo.Globals.CreateWrapperFor(info) as " + name_helpers::klass_full_concrete_name(cls) + ")").generate(sink, attributes::unused, *context); } bool operator()(attributes::complex_type_def const& types) const { if (types.outer.base_type == "iterator") return as_generator("Efl.Eo.Globals.IteratorTo" << eolian_mono::type << "(info)").generate(sink, type, *context); else if (types.outer.base_type == "accessor") return as_generator("Efl.Eo.Globals.AccessorTo" << eolian_mono::type << "(info)").generate(sink, type, *context); + else if (types.outer.base_type == "array") + return as_generator("Efl.Eo.Globals.NativeArrayTo" << eolian_mono::type << "(info)").generate(sink, type, *context); + else if (types.outer.base_type == "list") + return as_generator("Efl.Eo.Globals.NativeListTo" << eolian_mono::type << "(info)").generate(sink, type, *context); else return as_generator("new " << eolian_mono::type << "(info, false, false)").generate(sink, type, *context); } }; template struct pack_event_info_and_call_visitor { mutable OutputIterator sink; Context const* context; attributes::type_def const& type; std::string library_name; std::string evt_c_name; typedef pack_event_info_and_call_visitor visitor_type; typedef bool result_type; bool operator()(grammar::attributes::regular_type_def const& regular) const { std::string arg_type = name_helpers::type_full_managed_name(regular); auto const& indent = current_indentation(*context); if (regular.is_struct()) { return as_generator( indent.inc() << "Contract.Requires(e != null, nameof(e));\n" << indent.inc() << "IntPtr info = Marshal.AllocHGlobal(Marshal.SizeOf(e.arg));\n" << indent.inc() << "CallNativeEventCallback(" + library_name + ", \"_" + evt_c_name + "\", info, " << "(p) => Marshal.FreeHGlobal(p));\n" ).generate(sink, attributes::unused, *context); } using attributes::regular_type_def; struct match { eina::optional name; std::function function; }; std::string full_type_name = name_helpers::type_full_eolian_name(regular); auto filter_func = [®ular, &full_type_name] (match const& m) { return (!m.name || *m.name == regular.base_type || *m.name == full_type_name); }; match const str_table[] = { {"string", [] { return "e.arg"; }} , {"stringshare", [] { return "e.arg"; }} }; auto str_accept_func = [&](std::string const& conversion) { return as_generator( indent.inc() << "Contract.Requires(e != null, nameof(e));\n" << indent.inc() << "IntPtr info = Eina.StringConversion.ManagedStringToNativeUtf8Alloc(" << conversion << ");\n" << indent.inc() << "CallNativeEventCallback(" + library_name + ", \"_" + evt_c_name + "\", info, " << "(p) => Eina.MemoryNative.Free(p));\n" ).generate(sink, attributes::unused, *context); }; if (eina::optional b = type_match::get_match(str_table, filter_func, str_accept_func)) return *b; match const value_table [] = { {"bool", [] { return "e.arg ? (byte) 1 : (byte) 0"; }} , {"Eina.Error", [] { return "(int)e.arg"; }} , {nullptr, [] { return "e.arg"; }} }; auto value_accept_func = [&](std::string const& conversion) { return as_generator( indent.inc() << "Contract.Requires(e != null, nameof(e));\n" << indent.inc() << "IntPtr info = Eina.PrimitiveConversion.ManagedToPointerAlloc(" << conversion << ");\n" << indent.inc() << "CallNativeEventCallback(" + library_name + ", \"_" + evt_c_name + "\", info, " << "(p) => Marshal.FreeHGlobal(p));\n" ).generate(sink, attributes::unused, *context); }; if (eina::optional b = type_match::get_match(value_table, filter_func, value_accept_func)) return *b; return value_accept_func("e.args"); } bool operator()(grammar::attributes::klass_name const&) const { auto const& indent = current_indentation(*context); return as_generator( indent.inc() << "Contract.Requires(e != null, nameof(e));\n" << indent.inc() << "IntPtr info = e.arg.NativeHandle;\n" - << indent.inc() << "CallNativeEventCallback(" << library_name << ", \"_" << evt_c_name << "\", IntPtr.Zero, null);\n" + << indent.inc() << "CallNativeEventCallback(" << library_name << ", \"_" << evt_c_name << "\", info, null);\n" ).generate(sink, attributes::unused, *context); } bool operator()(attributes::complex_type_def const& type) const { auto const& indent = current_indentation(*context); - if ((type.outer.base_type == "iterator") || (type.outer.base_type == "accessor")) - return true; - - return as_generator( - indent.inc() << "Contract.Requires(e != null, nameof(e));\n" - << indent.inc() << "IntPtr info = e.arg.Handle;\n" - << indent.inc() << "CallNativeEventCallback(" << library_name << ", \"_" << evt_c_name << "\", IntPtr.Zero, null);\n" + bool is_own = type.outer.base_qualifier & attributes::qualifier_info::is_own; + std::string info_variable; + + if (type.outer.base_type == "iterator") + info_variable = std::string("IntPtr info = Efl.Eo.Globals.IEnumerableToIterator(e.arg, ") + (is_own ? "true" : "false") + ");\n"; + else if (type.outer.base_type == "accessor") + info_variable = std::string("IntPtr info = Efl.Eo.Globals.IEnumerableToAccessor(e.arg, ") + (is_own ? "true" : "false") + ");\n"; + else if (type.outer.base_type == "array") + info_variable = std::string("IntPtr info = Efl.Eo.Globals.IListToNativeArray(e.arg, ") + (is_own ? "true" : "false") + ");\n"; + else if (type.outer.base_type == "list") + info_variable = std::string("IntPtr info = Efl.Eo.Globals.IListToNativeList(e.arg, ") + (is_own ? "true" : "false") + ");\n"; + else + info_variable = "IntPtr info = e.arg.Handle;\n"; + return as_generator(indent.inc() << "Contract.Requires(e != null, nameof(e));\n" + << indent.inc() << info_variable + << indent.inc() << "CallNativeEventCallback(" << library_name << ", \"_" << evt_c_name << "\", info, null);\n" ).generate(sink, attributes::unused, *context); } }; /* * Generates a struct wrapping the argument of a given event. */ struct event_argument_wrapper_generator { template bool generate(OutputIterator sink, attributes::event_def const& evt, Context const& context) const { efl::eina::optional etype = evt.type; if (!etype.is_engaged()) return true; if (blacklist::is_event_blacklisted(evt, context)) return true; std::string evt_name = name_helpers::managed_event_name(evt.name); if (!as_generator(scope_tab << "/// Event argument wrapper for event .\n" ).generate(sink, nullptr, context)) return false; std::string since; if (!evt.is_beta) { since = evt.documentation.since; if (since.empty()) { auto unit = (const Eolian_Unit*) context_find_tag(context).state; attributes::klass_def klass(get_klass(evt.klass, unit), unit); since = klass.documentation.since; } if (!since.empty()) { if (!as_generator( scope_tab << lit("/// Since EFL ") << evt.documentation.since << ".\n" ).generate(sink, nullptr, context)) return false; } else { EINA_CXX_DOM_LOG_ERR(eolian_mono::domain) << "Event " << evt.name << " of class " << evt.klass.eolian_name << " is stable but has no 'Since' information."; // We do not bail out here because there are some cases of this happening upstream. } } if (!as_generator(scope_tab << lit("/// \n") << scope_tab << "[Efl.Eo.BindingEntity]\n" << scope_tab << "public class " << name_helpers::managed_event_args_short_name(evt) << " : EventArgs {\n" << scope_tab(2) << "/// Actual event payload.\n" ).generate(sink, nullptr, context)) return false; if (since != "") { if (!as_generator(scope_tab(2) << "/// Since EFL " << since << ".\n").generate(sink, nullptr, context)) return false; } if (!as_generator(scope_tab(2) << "/// \n" << scope_tab(2) << "/// " << documentation_string << "\n" << scope_tab(2) << "public " << type << " arg { get; set; }\n" << scope_tab << "}\n\n" ).generate(sink, std::make_tuple(evt.documentation.summary, *etype), context)) return false; return true; } } const event_argument_wrapper {}; /* * Generates an event declaration as a C# Interface member. * In regular/abstract classes they are declared directly in their * implementation in event_definition_generator. */ struct event_declaration_generator { template bool generate(OutputIterator sink, attributes::event_def const& evt, Context const& context) const { std::string wrapper_args_type; std::string evt_name = name_helpers::managed_event_name(evt.name); if (blacklist::is_event_blacklisted(evt, context)) return true; if (evt.type.is_engaged()) wrapper_args_type = "<" + name_helpers::managed_event_args_name(evt) + ">"; if (!as_generator(documentation(2)) .generate(sink, evt, context)) return false; if (evt.type.is_engaged()) if (!as_generator( scope_tab(2) << "/// \n" ).generate(sink, evt, context)) return false; if (!as_generator( scope_tab(2) << "event EventHandler" << wrapper_args_type << " " << evt_name << ";\n" ).generate(sink, evt, context)) return false; return true; } } const event_declaration {}; struct event_definition_generator { attributes::klass_def const& klass; attributes::klass_def const& leaf_klass; bool is_inherited_event; template bool generate(OutputIterator sink, attributes::event_def const& evt, Context const& context) const { if (blacklist::is_event_blacklisted(evt, context)) return true; auto library_name = context_find_tag(context).actual_library_name(klass.filename); std::string managed_evt_name = name_helpers::managed_event_name(evt.name); auto const& indent = current_indentation(context); bool is_unique = helpers::is_unique_event(evt, leaf_klass); bool use_explicit_impl = is_inherited_event && !is_unique; // The name of the public event that goes in the public API. std::string wrapper_evt_name; if (use_explicit_impl) wrapper_evt_name = name_helpers::translate_inherited_event_name(evt, klass); else wrapper_evt_name = managed_evt_name; std::string klass_name; if (is_inherited_event) klass_name = name_helpers::klass_full_interface_name(klass); else klass_name = name_helpers::klass_concrete_name(klass); std::string wrapper_args_type = "EventArgs"; std::string wrapper_args_template = ""; std::string event_args = "EventArgs args = EventArgs.Empty;\n"; std::string event_native_call; efl::eina::optional etype = evt.type; if (!etype.is_engaged()) { auto event_call_site_sink = std::back_inserter(event_native_call); if (!as_generator(indent.inc().inc().inc() << "CallNativeEventCallback(" << library_name << ", \"_" << utils::to_uppercase(evt.c_name) << "\", IntPtr.Zero, null);\n") .generate(event_call_site_sink, attributes::unused, context)) return false; } else { wrapper_args_type = name_helpers::managed_event_args_name(evt); wrapper_args_template = "<" + wrapper_args_type + ">"; std::string arg_initializer; auto arg_initializer_sink = std::back_inserter(arg_initializer); auto event_call_site_sink = std::back_inserter(event_native_call); auto sub_context = change_indentation(indent.inc().inc(), context); if (!as_generator(", info => new " << wrapper_args_type << "{ " << "arg = ").generate(arg_initializer_sink, attributes::unused, context)) return false; if (!(*etype).original_type.visit(unpack_event_args_visitor{arg_initializer_sink, &sub_context, *etype})) return false; if (!(*etype).original_type.visit(pack_event_info_and_call_visitor{event_call_site_sink, &sub_context, *etype, library_name, utils::to_uppercase(evt.c_name)})) return false; arg_initializer += " }"; event_args = arg_initializer; } if(!as_generator(documentation(2)).generate(sink, evt, context)) return false; if (etype.is_engaged()) if (!as_generator( scope_tab(2) << "/// \n" ).generate(sink, evt, context)) return false; // Visible event declaration. Either a regular class member or an explicit interface implementation. if (klass.type == attributes::class_type::interface_ || klass.type == attributes::class_type::mixin) { // Public event implementation. if (!as_generator( scope_tab(2) << (!use_explicit_impl ? "public " : " ") << "event EventHandler" << wrapper_args_template << " " << (use_explicit_impl ? (klass_name + ".") : "") << managed_evt_name << "\n" ).generate(sink, attributes::unused, context)) return false; } else // For inheritable classes event handling. { // We may have inherited an event with the same name as this concrete event, thus // the concrete event would "hide" the interface one, requiring the new keyword. std::string visibility = "public "; if (!is_unique) visibility += "new "; if (!as_generator( scope_tab(2) << visibility << "event EventHandler" << wrapper_args_template << " " << wrapper_evt_name << "\n" ).generate(sink, attributes::unused, context)) return false; } if (!generate_event_add_remove(sink, evt, event_args, context)) return false; if (!generate_event_trigger(sink, evt, wrapper_evt_name, wrapper_args_type, event_native_call, context)) return false; return true; } template bool generate_event_trigger(OutputIterator sink , attributes::event_def const &evt , std::string const& event_name , std::string const& event_args_type , std::string const& event_native_call , Context const& context) const { auto library_name = context_find_tag(context).actual_library_name(klass.filename); std::string upper_c_name = utils::to_uppercase(evt.c_name); bool is_concrete = context_find_tag(context).current_wrapper_kind == class_context::concrete; if (!as_generator( scope_tab(2) << "/// Method to raise event "<< event_name << ".\n" ).generate(sink, nullptr, context)) return false; if (!evt.is_beta) { std::string since = evt.documentation.since; if (since.empty()) { auto unit = (const Eolian_Unit*) context_find_tag(context).state; attributes::klass_def klass(get_klass(evt.klass, unit), unit); since = klass.documentation.since; } if (!since.empty()) { if (!as_generator( scope_tab(2) << "/// Since EFL " << evt.documentation.since << ".\n" ).generate(sink, nullptr, context)) return false; } else { EINA_CXX_DOM_LOG_ERR(eolian_mono::domain) << "Event " << evt.name << " of class " << evt.klass.eolian_name << " is stable but has no 'Since' information."; // We do not bail out here because there are some cases of this happening upstream. } } // Close summary if (!as_generator(scope_tab(2) << "/// \n").generate(sink, nullptr, context)) return false; if (evt.type.is_engaged()) { if (!as_generator(scope_tab(2) << "/// Event to raise.\n" ).generate(sink, nullptr, context)) return false; } if (!as_generator( scope_tab(2) << (is_concrete ? "public" : "protected virtual") << " void On" << event_name << "(" << (!evt.type.is_engaged() ? "" : event_args_type + " e") << ")\n" << scope_tab(2) << "{\n" << event_native_call << scope_tab(2) << "}\n\n" ).generate(sink, nullptr, context)) return false; return true; } template bool generate_event_add_remove(OutputIterator sink , attributes::event_def const &evt , std::string const& event_args , Context const& context) const { std::string upper_c_name = utils::to_uppercase(evt.c_name); auto unit = (const Eolian_Unit*) context_find_tag(context).state; attributes::klass_def klass(get_klass(evt.klass, unit), unit); auto library_name = context_find_tag(context).actual_library_name(klass.filename); return as_generator( scope_tab(2) << "{\n" << scope_tab(2) << scope_tab << "add\n" << scope_tab(2) << scope_tab << "{\n"//evt.type.is_engaged() << scope_tab(2) << scope_tab << scope_tab << "Efl.EventCb callerCb = GetInternalEventCallback(value" << (evt.type.is_engaged() ? event_args : "") << ");\n" << scope_tab(2) << scope_tab << scope_tab << "string key = \"_" << upper_c_name << "\";\n" << scope_tab(2) << scope_tab << scope_tab << "AddNativeEventHandler(" << library_name << ", key, callerCb, value);\n" << scope_tab(2) << scope_tab << "}\n\n" << scope_tab(2) << scope_tab << "remove\n" << scope_tab(2) << scope_tab << "{\n" << scope_tab(2) << scope_tab << scope_tab << "string key = \"_" << upper_c_name << "\";\n" << scope_tab(2) << scope_tab << scope_tab << "RemoveNativeEventHandler(" << library_name << ", key, value);\n" << scope_tab(2) << scope_tab << "}\n" << scope_tab(2) << "}\n\n" ).generate(sink, attributes::unused, context); } }; struct event_definition_parameterized { event_definition_generator operator()(attributes::klass_def const& klass, attributes::klass_def const& leaf_klass) const { bool is_inherited_event = klass != leaf_klass; return {klass, leaf_klass, is_inherited_event}; } } const event_definition; } namespace efl { namespace eolian { namespace grammar { template <> struct is_eager_generator : std::true_type {}; template <> struct is_generator : std::true_type {}; template <> struct is_eager_generator : std::true_type {}; template <> struct is_generator : std::true_type {}; template <> struct is_eager_generator : std::true_type {}; template <> struct is_generator : std::true_type {}; template <> struct is_generator : std::true_type {}; namespace type_traits { template <> struct attributes_needed : std::integral_constant {}; template <> struct attributes_needed : std::integral_constant {}; template <> struct attributes_needed : std::integral_constant {}; template <> struct attributes_needed : std::integral_constant {}; } } } } #endif diff --git a/src/bin/eolian_mono/eolian/mono/parameter.hh b/src/bin/eolian_mono/eolian/mono/parameter.hh index 91b29afdc1..824dc0c927 100644 --- a/src/bin/eolian_mono/eolian/mono/parameter.hh +++ b/src/bin/eolian_mono/eolian/mono/parameter.hh @@ -1,1645 +1,1677 @@ /* * Copyright 2019 by its authors. See AUTHORS. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef EOLIAN_MONO_PARAMETER_HH #define EOLIAN_MONO_PARAMETER_HH #include "grammar/generator.hpp" #include "grammar/klass_def.hpp" #include "grammar/attribute_reorder.hpp" #include "grammar/case.hpp" #include "helpers.hh" #include "marshall_type.hh" #include "type.hh" #include "using_decl.hh" #include "name_helpers.hh" using namespace eolian_mono::name_helpers; namespace eolian_mono { struct parameter_generator; struct marshall_parameter_generator; struct argument_generator; struct argument_invocation_generator; struct native_argument_invocation_generator; struct native_convert_in_variable_generator; struct convert_in_variable_generator; struct native_convert_out_variable_generator; struct convert_out_variable_generator; struct convert_out_assign_generator; struct native_convert_in_ptr_assign_generator; struct convert_in_ptr_assign_generator; struct native_convert_out_assign_parameterized; struct native_convert_out_assign_generator; struct convert_return_generator; struct convert_return_variable_generator; struct native_convert_return_generator; struct native_convert_return_parameterized; struct native_convert_return_variable_generator; struct convert_function_pointer_generator; struct native_convert_function_pointer_generator; struct constructor_param_generator; struct constructor_invocation_generator; struct constructor_parameter_name_generator; struct constructor_parameter_name_paremeterized; } namespace efl { namespace eolian { namespace grammar { template <> struct is_eager_generator< ::eolian_mono::parameter_generator> : std::true_type {}; template <> struct is_generator< ::eolian_mono::parameter_generator> : std::true_type {}; namespace type_traits { template <> struct attributes_needed< ::eolian_mono::parameter_generator> : std::integral_constant {}; } template <> struct is_eager_generator< ::eolian_mono::marshall_parameter_generator> : std::true_type {}; template <> struct is_generator< ::eolian_mono::marshall_parameter_generator> : std::true_type {}; namespace type_traits { template <> struct attributes_needed< ::eolian_mono::marshall_parameter_generator> : std::integral_constant {}; } template <> struct is_eager_generator< ::eolian_mono::argument_generator> : std::true_type {}; template <> struct is_generator< ::eolian_mono::argument_generator> : std::true_type {}; namespace type_traits { template <> struct attributes_needed< ::eolian_mono::argument_generator> : std::integral_constant {}; } template <> struct is_eager_generator< ::eolian_mono::argument_invocation_generator> : std::true_type {}; template <> struct is_generator< ::eolian_mono::argument_invocation_generator> : std::true_type {}; namespace type_traits { template <> struct attributes_needed< ::eolian_mono::argument_invocation_generator> : std::integral_constant {}; } template <> struct is_eager_generator< ::eolian_mono::native_argument_invocation_generator> : std::true_type {}; template <> struct is_generator< ::eolian_mono::native_argument_invocation_generator> : std::true_type {}; namespace type_traits { template <> struct attributes_needed< ::eolian_mono::native_argument_invocation_generator> : std::integral_constant {}; } template <> struct is_eager_generator< ::eolian_mono::native_convert_in_variable_generator> : std::true_type {}; template <> struct is_generator< ::eolian_mono::native_convert_in_variable_generator> : std::true_type {}; namespace type_traits { template <> struct attributes_needed< ::eolian_mono::native_convert_in_variable_generator> : std::integral_constant {}; } template <> struct is_eager_generator< ::eolian_mono::convert_in_variable_generator> : std::true_type {}; template <> struct is_generator< ::eolian_mono::convert_in_variable_generator> : std::true_type {}; namespace type_traits { template <> struct attributes_needed< ::eolian_mono::convert_in_variable_generator> : std::integral_constant {}; } template <> struct is_eager_generator< ::eolian_mono::convert_out_variable_generator> : std::true_type {}; template <> struct is_generator< ::eolian_mono::convert_out_variable_generator> : std::true_type {}; namespace type_traits { template <> struct attributes_needed< ::eolian_mono::convert_out_variable_generator> : std::integral_constant {}; } template <> struct is_eager_generator< ::eolian_mono::native_convert_out_variable_generator> : std::true_type {}; template <> struct is_generator< ::eolian_mono::native_convert_out_variable_generator> : std::true_type {}; namespace type_traits { template <> struct attributes_needed< ::eolian_mono::native_convert_out_variable_generator> : std::integral_constant {}; } template <> struct is_eager_generator< ::eolian_mono::convert_out_assign_generator> : std::true_type {}; template <> struct is_generator< ::eolian_mono::convert_out_assign_generator> : std::true_type {}; namespace type_traits { template <> struct attributes_needed< ::eolian_mono::convert_out_assign_generator> : std::integral_constant {}; } template <> struct is_eager_generator< ::eolian_mono::native_convert_in_ptr_assign_generator> : std::true_type {}; template <> struct is_generator< ::eolian_mono::native_convert_in_ptr_assign_generator> : std::true_type {}; namespace type_traits { template <> struct attributes_needed< ::eolian_mono::native_convert_in_ptr_assign_generator> : std::integral_constant {}; } template <> struct is_eager_generator< ::eolian_mono::convert_in_ptr_assign_generator> : std::true_type {}; template <> struct is_generator< ::eolian_mono::convert_in_ptr_assign_generator> : std::true_type {}; namespace type_traits { template <> struct attributes_needed< ::eolian_mono::convert_in_ptr_assign_generator> : std::integral_constant {}; } template <> struct is_eager_generator< ::eolian_mono::convert_return_variable_generator> : std::true_type {}; template <> struct is_generator< ::eolian_mono::convert_return_variable_generator> : std::true_type {}; namespace type_traits { template <> struct attributes_needed< ::eolian_mono::convert_return_variable_generator> : std::integral_constant {}; } template <> struct is_eager_generator< ::eolian_mono::convert_return_generator> : std::true_type {}; template <> struct is_generator< ::eolian_mono::convert_return_generator> : std::true_type {}; namespace type_traits { template <> struct attributes_needed< ::eolian_mono::convert_return_generator> : std::integral_constant {}; } template <> struct is_eager_generator< ::eolian_mono::native_convert_out_assign_generator> : std::true_type {}; template <> struct is_generator< ::eolian_mono::native_convert_out_assign_generator> : std::true_type {}; template <> struct is_generator< ::eolian_mono::native_convert_out_assign_parameterized> : std::true_type {}; namespace type_traits { template <> struct attributes_needed< ::eolian_mono::native_convert_out_assign_generator> : std::integral_constant {}; } template <> struct is_eager_generator< ::eolian_mono::native_convert_return_variable_generator> : std::true_type {}; template <> struct is_generator< ::eolian_mono::native_convert_return_variable_generator> : std::true_type {}; namespace type_traits { template <> struct attributes_needed< ::eolian_mono::native_convert_return_variable_generator> : std::integral_constant {}; } template <> struct is_eager_generator< ::eolian_mono::native_convert_return_generator> : std::true_type {}; template <> struct is_generator< ::eolian_mono::native_convert_return_generator> : std::true_type {}; template <> struct is_generator< ::eolian_mono::native_convert_return_parameterized> : std::true_type {}; namespace type_traits { template <> struct attributes_needed< ::eolian_mono::native_convert_return_generator> : std::integral_constant {}; } template <> struct is_eager_generator< ::eolian_mono::convert_function_pointer_generator> : std::true_type {}; template <> struct is_generator< ::eolian_mono::convert_function_pointer_generator> : std::true_type {}; namespace type_traits { template <> struct attributes_needed< ::eolian_mono::convert_function_pointer_generator> : std::integral_constant {}; } template <> struct is_eager_generator< ::eolian_mono::native_convert_function_pointer_generator> : std::true_type {}; template <> struct is_generator< ::eolian_mono::native_convert_function_pointer_generator> : std::true_type {}; namespace type_traits { template <> struct attributes_needed< ::eolian_mono::native_convert_function_pointer_generator> : std::integral_constant {}; } template <> struct is_eager_generator< ::eolian_mono::constructor_param_generator> : std::true_type {}; template <> struct is_generator< ::eolian_mono::constructor_param_generator> : std::true_type {}; namespace type_traits { template <> struct attributes_needed< ::eolian_mono::constructor_param_generator> : std::integral_constant {}; } template <> struct is_eager_generator< ::eolian_mono::constructor_invocation_generator> : std::true_type {}; template <> struct is_generator< ::eolian_mono::constructor_invocation_generator> : std::true_type {}; namespace type_traits { template <> struct attributes_needed< ::eolian_mono::constructor_invocation_generator> : std::integral_constant {}; } template <> struct is_eager_generator< ::eolian_mono::constructor_parameter_name_generator> : std::true_type {}; template <> struct is_generator< ::eolian_mono::constructor_parameter_name_generator> : std::true_type {}; template <> struct is_generator< ::eolian_mono::constructor_parameter_name_paremeterized> : std::true_type {}; namespace type_traits { template <> struct attributes_needed< ::eolian_mono::constructor_parameter_name_generator> : std::integral_constant {}; } } } } namespace eolian_mono { namespace attributes = efl::eolian::grammar::attributes; // Helper function to query parameter attributes const static bool WANT_OWN = true; const static bool WANT_OUT = true; inline bool param_is_acceptable(attributes::parameter_def const ¶m, std::string c_type, bool want_own, bool want_out) { return (param.type.c_type == c_type) && ((param.direction != attributes::parameter_direction::in) == want_out) && (param.type.has_own == want_own); } inline bool param_should_use_out_var(attributes::parameter_def const& param, bool native) { if (param.direction == attributes::parameter_direction::in) return false; if ((native && param_is_acceptable(param, "const char *", !WANT_OWN, WANT_OUT)) || (native && param_is_acceptable(param, "Eina_Stringshare *", !WANT_OWN, WANT_OUT)) || param_is_acceptable(param, "Eina_Binbuf *", !WANT_OWN, WANT_OUT) || param_is_acceptable(param, "Eina_Binbuf *", WANT_OWN, WANT_OUT) || param_is_acceptable(param, "const Eina_Binbuf *", !WANT_OWN, WANT_OUT) || param_is_acceptable(param, "const Eina_Binbuf *", WANT_OWN, WANT_OUT) || param_is_acceptable(param, "Eina_Array *", !WANT_OWN, WANT_OUT) || param_is_acceptable(param, "Eina_Array *", WANT_OWN, WANT_OUT) || param_is_acceptable(param, "const Eina_Array *", !WANT_OWN, WANT_OUT) || param_is_acceptable(param, "const Eina_Array *", WANT_OWN, WANT_OUT) || param_is_acceptable(param, "Eina_List *", !WANT_OWN, WANT_OUT) || param_is_acceptable(param, "Eina_List *", WANT_OWN, WANT_OUT) || param_is_acceptable(param, "const Eina_List *", !WANT_OWN, WANT_OUT) || param_is_acceptable(param, "const Eina_List *", WANT_OWN, WANT_OUT) || param_is_acceptable(param, "Eina_Accessor *", !WANT_OWN, WANT_OUT) || param_is_acceptable(param, "Eina_Accessor *", WANT_OWN, WANT_OUT) || param_is_acceptable(param, "const Eina_Accessor *", !WANT_OWN, WANT_OUT) || param_is_acceptable(param, "const Eina_Accessor *", WANT_OWN, WANT_OUT) || param_is_acceptable(param, "Eina_Hash *", !WANT_OWN, WANT_OUT) || param_is_acceptable(param, "Eina_Hash *", WANT_OWN, WANT_OUT) || param_is_acceptable(param, "const Eina_Hash *", !WANT_OWN, WANT_OUT) || param_is_acceptable(param, "const Eina_Hash *", WANT_OWN, WANT_OUT) || param_is_acceptable(param, "Eina_Iterator *", !WANT_OWN, WANT_OUT) || param_is_acceptable(param, "Eina_Iterator *", WANT_OWN, WANT_OUT) || param_is_acceptable(param, "const Eina_Iterator *", !WANT_OWN, WANT_OUT) || param_is_acceptable(param, "const Eina_Iterator *", WANT_OWN, WANT_OUT) || param_is_acceptable(param, "Eina_Value", WANT_OWN, WANT_OUT) || param_is_acceptable(param, "Eina_Value", !WANT_OWN, WANT_OUT) ) return true; auto regular = efl::eina::get(¶m.type.original_type); if (helpers::need_struct_conversion(regular)) return true; if (param.type.is_ptr && helpers::need_pointer_conversion(regular)) return true; return false; } inline bool param_should_use_in_var(attributes::parameter_def const& param, bool /*native*/) { if (param.direction != attributes::parameter_direction::in) return false; if (param_is_acceptable(param, "Eina_Binbuf *", !WANT_OWN, !WANT_OUT) || param_is_acceptable(param, "Eina_Binbuf *", WANT_OWN, !WANT_OUT) || param_is_acceptable(param, "const Eina_Binbuf *", !WANT_OWN, !WANT_OUT) || param_is_acceptable(param, "const Eina_Binbuf *", WANT_OWN, !WANT_OUT) || param_is_acceptable(param, "Eina_Array *", !WANT_OWN, !WANT_OUT) || param_is_acceptable(param, "Eina_Array *", WANT_OWN, !WANT_OUT) || param_is_acceptable(param, "const Eina_Array *", !WANT_OWN, !WANT_OUT) || param_is_acceptable(param, "const Eina_Array *", WANT_OWN, !WANT_OUT) || param_is_acceptable(param, "Eina_List *", !WANT_OWN, !WANT_OUT) || param_is_acceptable(param, "Eina_List *", WANT_OWN, !WANT_OUT) || param_is_acceptable(param, "const Eina_List *", !WANT_OWN, !WANT_OUT) || param_is_acceptable(param, "const Eina_List *", WANT_OWN, !WANT_OUT) || param_is_acceptable(param, "Eina_Accessor *", !WANT_OWN, !WANT_OUT) || param_is_acceptable(param, "Eina_Accessor *", WANT_OWN, !WANT_OUT) || param_is_acceptable(param, "const Eina_Accessor *", !WANT_OWN, !WANT_OUT) || param_is_acceptable(param, "const Eina_Accessor *", WANT_OWN, !WANT_OUT) || param_is_acceptable(param, "Eina_Hash *", !WANT_OWN, !WANT_OUT) || param_is_acceptable(param, "Eina_Hash *", WANT_OWN, !WANT_OUT) || param_is_acceptable(param, "const Eina_Hash *", !WANT_OWN, !WANT_OUT) || param_is_acceptable(param, "const Eina_Hash *", WANT_OWN, !WANT_OUT) || param_is_acceptable(param, "Eina_Iterator *", !WANT_OWN, !WANT_OUT) || param_is_acceptable(param, "Eina_Iterator *", WANT_OWN, !WANT_OUT) || param_is_acceptable(param, "const Eina_Iterator *", !WANT_OWN, !WANT_OUT) || param_is_acceptable(param, "const Eina_Iterator *", WANT_OWN, !WANT_OUT) || param_is_acceptable(param, "Eina_Value", WANT_OWN, !WANT_OUT) || param_is_acceptable(param, "Eina_Value", !WANT_OWN, !WANT_OUT) ) return true; auto regular = efl::eina::get(¶m.type.original_type); if (helpers::need_struct_conversion(regular)) return true; if (param.type.is_ptr && helpers::need_pointer_conversion(regular)) return true; return false; } inline std::string out_variable_name(std::string const& param_name) { return "_out_" + escape_keyword(param_name); } inline std::string in_variable_name(std::string const& param_name) { return "_in_" + escape_keyword(param_name); } inline std::string direction_modifier(attributes::parameter_def const& param) { if (param.direction == attributes::parameter_direction::inout) { return "ref "; } else if (param.direction != attributes::parameter_direction::in) { if (param.type.c_type == "Eina_Slice" || param.type.c_type == "Eina_Rw_Slice") return "ref "; else return "out "; } else if (param.direction == attributes::parameter_direction::in && param.type.is_ptr) { auto regular = efl::eina::get(¶m.type.original_type); if (helpers::need_struct_conversion(regular)) return "ref "; // Don't add ref on Marshal if it is ptr } return ""; } std::string marshall_direction_modifier(attributes::parameter_def const& param) { if (param.direction == attributes::parameter_direction::in && param.type.is_ptr) { auto regular = efl::eina::get(¶m.type.original_type); if (helpers::need_struct_conversion(regular) && param.type.has_own) return " "; // Don't add ref on Marshal if it is ptr } return direction_modifier(param); } struct is_fp_visitor { typedef is_fp_visitor visitor_type; typedef bool result_type; bool operator()(grammar::attributes::regular_type_def const &type) const { return type.is_function_ptr(); } template bool operator()(T const &) const { return false; } }; struct type_name_visitor { typedef type_name_visitor visitor_type; typedef std::string result_type; std::string operator()(grammar::attributes::regular_type_def const &type) const { return name_helpers::type_full_eolian_name(type); } template std::string operator()(T const &) const { return ""; } }; struct parameter_generator { template bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const { std::string param_name = escape_keyword(param.param_name); return as_generator( direction_modifier(param) << type << " " << string ).generate(sink, std::make_tuple(param, param_name), context); } } const parameter {}; struct marshall_parameter_generator { template bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const { std::string param_name = escape_keyword(param.param_name); if (!param.type.original_type.visit(is_fp_visitor{})) return as_generator( marshall_direction_modifier(param) << marshall_type << " " << string ).generate(sink, std::make_tuple(param, param_name), context); return as_generator( "IntPtr " << param_name << "_data, " << type << "Internal " << param_name << ", Eina.Callbacks.EinaFreeCb " << param_name << "_free_cb" ).generate(sink, param, context); } } const marshall_parameter {}; // FIXME This seems to be used only in the else branch of the native function definition. Is it really needed? struct argument_generator { bool generate_direction; argument_generator () : generate_direction(true) {} argument_generator (bool r) : generate_direction(r) {} template bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const { std::string param_name = escape_keyword(param.param_name); std::string direction = marshall_direction_modifier(param); if (generate_direction && !param.type.original_type.visit(is_fp_visitor{})) return as_generator(direction << param_name).generate(sink, attributes::unused, context); if (!generate_direction && !param.type.original_type.visit(is_fp_visitor{})) return as_generator(param_name).generate(sink, attributes::unused, context); else return as_generator (param_name << "_data, " << param_name << ", " << param_name << "_free_cb" ).generate(sink, attributes::unused, context); } argument_generator operator ()(bool r) const { return {r}; } } const argument {}; struct native_argument_invocation_generator { template bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const { std::string arg = direction_modifier(param); if (param_should_use_out_var(param, true)) arg += out_variable_name(param.param_name); else if (param_should_use_in_var(param, true)) arg += in_variable_name(param.param_name); else if (param.type.original_type.visit(is_fp_visitor{})) { arg += escape_keyword(param.param_name) + "_wrapper.ManagedCb"; } else // FIXME Wrap data and C function pointers into some kind of structure. arg += escape_keyword(param.param_name); return as_generator(arg).generate(sink, attributes::unused, context); } } const native_argument_invocation {}; // Generates the correct parameter name when invoking a function struct argument_invocation_generator { constexpr argument_invocation_generator(bool conversion_vars) : use_conversion_vars(conversion_vars) {} template bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const { std::string arg = marshall_direction_modifier(param); if (use_conversion_vars && param_should_use_out_var(param, false)) arg += out_variable_name(param.param_name); else if (use_conversion_vars && param_should_use_in_var(param, false)) arg += in_variable_name(param.param_name); else if (param.type.original_type.visit(is_fp_visitor{})) { std::string param_name = escape_keyword(param.param_name); return as_generator("GCHandle.ToIntPtr(" << param_name << "_handle), " << type << "Wrapper.Cb, Efl.Eo.Globals.free_gchandle") .generate(sink, param.type, context); } else arg += escape_keyword(param.param_name); return as_generator(arg).generate(sink, attributes::unused, context); } bool const use_conversion_vars; } const argument_invocation {true}; argument_invocation_generator const argument_invocation_no_conversion {false}; struct native_convert_in_variable_generator { template bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const { if (param.direction != attributes::parameter_direction::in) return true; auto regular = efl::eina::get(¶m.type.original_type); if (param.type.is_ptr && helpers::need_pointer_conversion(regular) && !helpers::need_struct_conversion(param, regular)) { return as_generator( "var " << string << " = Eina.PrimitiveConversion.PointerToManaged<" << type << ">(" << escape_keyword(param.param_name) << ");\n" ).generate(sink, std::make_tuple(in_variable_name(param.param_name), param.type), context); } else if (helpers::need_struct_conversion(regular)) { return as_generator( type << " " << string << " = " << escape_keyword(param.param_name) << ";\n" ).generate(sink, std::make_tuple(param.type, in_variable_name(param.param_name)), context); } else if (param.type.c_type == "Eina_Binbuf *" || param.type.c_type == "const Eina_Binbuf *") { return as_generator( "var " << string << " = new Eina.Binbuf(" << escape_keyword(param.param_name) << ", " << (param.type.has_own ? "true" : "false") << ");\n" ).generate(sink, in_variable_name(param.param_name), context); } else if (param.type.c_type == "Eina_Hash *" || param.type.c_type == "const Eina_Hash *") { attributes::complex_type_def const* complex = efl::eina::get(¶m.type.original_type); if (!complex || complex->subtypes.size() != 2) return false; return as_generator( "var " << string << " = new " << type << "(" << escape_keyword(param.param_name) << ", " << (param.type.has_own ? "true" : "false") << ", " << (complex->subtypes.front().has_own ? "true" : "false") << ", " << (complex->subtypes.back().has_own ? "true" : "false") << ");\n" ).generate(sink, std::make_tuple(in_variable_name(param.param_name), param.type), context); } - else if (param.type.c_type == "Eina_Array *" || param.type.c_type == "const Eina_Array *" - || param.type.c_type == "Eina_List *" || param.type.c_type == "const Eina_List *" - ) + else if (param.type.c_type == "Eina_List *" || param.type.c_type == "const Eina_List *") { attributes::complex_type_def const* complex = efl::eina::get(¶m.type.original_type); if (!complex) return false; return as_generator( - "var " << string << " = new " << type << "(" << escape_keyword(param.param_name) - << ", " << (param.type.has_own ? "true" : "false") - << ", " << (complex->subtypes.front().is_value_type || complex->subtypes.front().has_own ? "true" : "false") + "var " << string << " = Efl.Eo.Globals.NativeListTo" << type << "(" << escape_keyword(param.param_name) << ");\n" ).generate(sink, std::make_tuple(in_variable_name(param.param_name), param.type), context); } + else if (param.type.c_type == "Eina_Array *" || param.type.c_type == "const Eina_Array *") + { + attributes::complex_type_def const* complex = efl::eina::get(¶m.type.original_type); + if (!complex) + return false; + return as_generator( + "var " << string << " = Efl.Eo.Globals.NativeArrayTo" << type << "(" << escape_keyword(param.param_name) + << ");\n" + ).generate(sink, std::make_tuple(in_variable_name(param.param_name), param.type), context); + } + else if (param.type.c_type == "Eina_Iterator *" || param.type.c_type == "const Eina_Iterator *") { attributes::complex_type_def const* complex = efl::eina::get(¶m.type.original_type); if (!complex) return false; return as_generator( "var " << string << " = Efl.Eo.Globals.IteratorTo" << type << "(" << escape_keyword(param.param_name) << ");\n" ).generate(sink, std::make_tuple(in_variable_name(param.param_name), param.type), context); } else if (param.type.c_type == "Eina_Accessor *" || param.type.c_type == "const Eina_Accessor *") { attributes::complex_type_def const* complex = efl::eina::get(¶m.type.original_type); if (!complex) return false; return as_generator( "var " << string << " = Efl.Eo.Globals.AccessorTo" << type << "(" << escape_keyword(param.param_name) << ");\n" ).generate(sink, std::make_tuple(in_variable_name(param.param_name), param.type), context); } else if (param.type.c_type == "Eina_Value") { return as_generator( "var " << string << " = new " << type << "(" << string << ");\n" ).generate(sink, std::make_tuple(in_variable_name(param.param_name), param.type, param.param_name), context); } return true; } } const native_convert_in_variable {}; struct convert_in_variable_generator { template bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const { if (param.direction != attributes::parameter_direction::in) return true; auto regular = efl::eina::get(¶m.type.original_type); if (param.type.is_ptr && helpers::need_pointer_conversion(regular) && !helpers::need_struct_conversion(param, regular)) { return as_generator( "var " << string << " = Eina.PrimitiveConversion.ManagedToPointerAlloc(" << escape_keyword(param.param_name) << ");\n" ).generate(sink, in_variable_name(param.param_name), context); } else if (helpers::need_struct_conversion(regular)) { return as_generator( marshall_type << " " << string << " = " << escape_keyword(param.param_name) << ";\n" ).generate(sink, std::make_tuple(param.type, in_variable_name(param.param_name)), context); } else if (param.type.c_type == "Eina_Binbuf *" || param.type.c_type == "const Eina_Binbuf *") { if (!as_generator( "Contract.Requires(" << string << " != null, nameof(" << string << "));\n" << scope_tab(2) << "var " << string << " = " << string << ".Handle;\n" ).generate(sink, std::make_tuple(escape_keyword(param.param_name), escape_keyword(param.param_name), in_variable_name(param.param_name), escape_keyword(param.param_name)), context)) return false; if (param.type.has_own) { return as_generator( escape_keyword(param.param_name) << ".Own = false;\n" ).generate(sink, attributes::unused, context); } } else if (param.type.c_type == "Eina_Hash *" || param.type.c_type == "const Eina_Hash *") { attributes::complex_type_def const* complex = efl::eina::get(¶m.type.original_type); if (!complex || complex->subtypes.size() != 2) return false; if (!as_generator( "Contract.Requires(" << string << " != null, nameof(" << string << "));\n" << scope_tab(2) << "var " << string << " = " << string << ".Handle;\n" ).generate(sink, std::make_tuple(escape_keyword(param.param_name), escape_keyword(param.param_name), in_variable_name(param.param_name), escape_keyword(param.param_name)), context)) return false; if (param.type.has_own && !as_generator( escape_keyword(param.param_name) << ".SetOwn(false);\n" ).generate(sink, attributes::unused, context)) return false; if (complex->subtypes.front().has_own && !as_generator( escape_keyword(param.param_name) << ".SetOwnKey(false);\n" ).generate(sink, attributes::unused, context)) return false; if (complex->subtypes.back().has_own && !as_generator( escape_keyword(param.param_name) << ".SetOwnValue(false);\n" << escape_keyword(param.param_name) << ".UnSetFreeCb();\n" ).generate(sink, attributes::unused, context)) return false; } - else if (param.type.c_type == "Eina_Array *" || param.type.c_type == "const Eina_Array *" - || param.type.c_type == "Eina_List *" || param.type.c_type == "const Eina_List *" - ) + else if (param.type.c_type == "Eina_Array *" || param.type.c_type == "const Eina_Array *") { attributes::complex_type_def const* complex = efl::eina::get(¶m.type.original_type); if (!complex) return false; if (!as_generator( - "Contract.Requires(" << string << " != null, nameof(" << string << "));\n" - << "var " << string << " = " << string << ".Handle;\n" - ).generate(sink, std::make_tuple(escape_keyword(param.param_name), escape_keyword(param.param_name), - in_variable_name(param.param_name), escape_keyword(param.param_name)) - , context)) + "var " << string << " = " << "Efl.Eo.Globals.IListToNativeArray(" << escape_keyword(param.param_name) << ", " << (param.type.has_own ? "true" : "false") << ");\n" + ).generate(sink, in_variable_name(param.param_name), context)) return false; - if (param.type.has_own && !as_generator( - escape_keyword(param.param_name) << ".Own = false;\n" - ).generate(sink, attributes::unused, context)) + } + else if (param.type.c_type == "Eina_List *" || param.type.c_type == "const Eina_List *") + { + attributes::complex_type_def const* complex = efl::eina::get(¶m.type.original_type); + if (!complex) return false; - - if ((param.type.has_own && (complex->subtypes.front().is_value_type || complex->subtypes.front().has_own)) - && !as_generator( - escape_keyword(param.param_name) << ".OwnContent = false;\n" - ).generate(sink, attributes::unused, context)) + auto var_name = in_variable_name(param.param_name); + if (!as_generator( + "var " << string << " = " << "Efl.Eo.Globals.IListToNativeList(" << escape_keyword(param.param_name) << ", " << (param.type.has_own ? "true" : "false") << ");\n" + ).generate(sink, var_name, context)) return false; } else if (param.type.c_type == "Eina_Iterator *" || param.type.c_type == "const Eina_Iterator *") { attributes::complex_type_def const* complex = efl::eina::get(¶m.type.original_type); if (!complex) return false; auto var_name = in_variable_name(param.param_name); if (!as_generator( "var " << string << " = Efl.Eo.Globals.IEnumerableToIterator(" << escape_keyword(param.param_name) << ", " << (param.type.has_own ? "true" : "false")<< ");\n" ).generate(sink, var_name, context)) return false; } else if (param.type.c_type == "Eina_Accessor *" || param.type.c_type == "const Eina_Accessor *") { attributes::complex_type_def const* complex = efl::eina::get(¶m.type.original_type); if (!complex) return false; auto var_name = in_variable_name(param.param_name); if (!as_generator( "var " << string << " = Efl.Eo.Globals.IEnumerableToAccessor(" << escape_keyword(param.param_name) << ", " << (param.type.has_own ? "true" : "false")<< ");\n" ).generate(sink, var_name, context)) return false; } else if (param.type.c_type == "Eina_Value") { return as_generator( "Contract.Requires(" << string << " != null, nameof(" << string << "));\n" "var " << string << " = " << string << ".GetNative();\n" ).generate(sink, std::make_tuple(param.param_name, param.param_name, in_variable_name(param.param_name), param.param_name), context); } return true; } } const convert_in_variable {}; /* Some types require an intermediate variable to be filled as out parameter in the marshalled function */ struct convert_out_variable_generator { template bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const { if (param.direction == attributes::parameter_direction::in) return true; auto regular = efl::eina::get(¶m.type.original_type); if (param.type.is_ptr && helpers::need_pointer_conversion(regular) && !helpers::need_struct_conversion(regular)) { return as_generator( "System.IntPtr " << string << " = System.IntPtr.Zero;\n" ).generate(sink, out_variable_name(param.param_name), context); } else if (helpers::need_struct_conversion(regular)) { return as_generator( "var " << string << " = new " << marshall_type << "();\n" ).generate(sink, std::make_tuple(out_variable_name(param.param_name), param), context); } else if (param_is_acceptable(param, "Eina_Binbuf *", WANT_OWN, WANT_OUT) || param_is_acceptable(param, "Eina_Binbuf *", !WANT_OWN, WANT_OUT) || param_is_acceptable(param, "const Eina_Binbuf *", WANT_OWN, WANT_OUT) || param_is_acceptable(param, "const Eina_Binbuf *", !WANT_OWN, WANT_OUT) ) { return as_generator( "System.IntPtr " << string << " = System.IntPtr.Zero;\n" ).generate(sink, out_variable_name(param.param_name), context); } else if (param_is_acceptable(param, "Eina_Array *", WANT_OWN, WANT_OUT) || param_is_acceptable(param, "Eina_Array *", !WANT_OWN, WANT_OUT) || param_is_acceptable(param, "const Eina_Array *", WANT_OWN, WANT_OUT) || param_is_acceptable(param, "const Eina_Array *", !WANT_OWN, WANT_OUT) || param_is_acceptable(param, "Eina_List *", WANT_OWN, WANT_OUT) || param_is_acceptable(param, "Eina_List *", !WANT_OWN, WANT_OUT) || param_is_acceptable(param, "const Eina_List *", WANT_OWN, WANT_OUT) || param_is_acceptable(param, "const Eina_List *", !WANT_OWN, WANT_OUT) || param_is_acceptable(param, "Eina_Accessor *", WANT_OWN, WANT_OUT) || param_is_acceptable(param, "Eina_Accessor *", !WANT_OWN, WANT_OUT) || param_is_acceptable(param, "const Eina_Accessor *", WANT_OWN, WANT_OUT) || param_is_acceptable(param, "const Eina_Accessor *", !WANT_OWN, WANT_OUT) || param_is_acceptable(param, "Eina_Hash *", WANT_OWN, WANT_OUT) || param_is_acceptable(param, "Eina_Hash *", !WANT_OWN, WANT_OUT) || param_is_acceptable(param, "const Eina_Hash *", WANT_OWN, WANT_OUT) || param_is_acceptable(param, "const Eina_Hash *", !WANT_OWN, WANT_OUT) || param_is_acceptable(param, "Eina_Iterator *", WANT_OWN, WANT_OUT) || param_is_acceptable(param, "Eina_Iterator *", !WANT_OWN, WANT_OUT) || param_is_acceptable(param, "const Eina_Iterator *", WANT_OWN, WANT_OUT) || param_is_acceptable(param, "const Eina_Iterator *", !WANT_OWN, WANT_OUT) ) { return as_generator( "System.IntPtr " << string << " = System.IntPtr.Zero;\n" ).generate(sink, out_variable_name(param.param_name), context); } else if (param_is_acceptable(param, "Eina_Value", WANT_OWN, WANT_OUT) || param_is_acceptable(param, "Eina_Value", !WANT_OWN, WANT_OUT)) { return as_generator( marshall_type << " " << string << ";\n" ).generate(sink, std::make_tuple(param.type, out_variable_name(param.param_name)), context); } return true; } } const convert_out_variable {}; struct native_convert_out_variable_generator { template bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const { if (param.direction == attributes::parameter_direction::in) return true; auto regular = efl::eina::get(¶m.type.original_type); if (param.type.is_ptr && helpers::need_pointer_conversion(regular) && !helpers::need_struct_conversion(regular)) { return as_generator( type << " " << string << " = default(" << type << ");\n" ).generate(sink, std::make_tuple(param, out_variable_name(param.param_name), param), context); } else if (helpers::need_struct_conversion(regular) || param_is_acceptable(param, "const char *", !WANT_OWN, WANT_OUT) || param_is_acceptable(param, "Eina_Stringshare *", !WANT_OWN, WANT_OUT)) { return as_generator( type << " " << string << " = default(" << type << ");\n" ).generate(sink, std::make_tuple(param, out_variable_name(param.param_name), param), context); } else if (param_is_acceptable(param, "Eina_Binbuf *", WANT_OWN, WANT_OUT) || param_is_acceptable(param, "Eina_Binbuf *", !WANT_OWN, WANT_OUT) || param_is_acceptable(param, "const Eina_Binbuf *", WANT_OWN, WANT_OUT) || param_is_acceptable(param, "const Eina_Binbuf *", !WANT_OWN, WANT_OUT) ) { return as_generator( "Eina.Binbuf " << string << " = default(Eina.Binbuf);\n" ).generate(sink, out_variable_name(param.param_name), context); } else if (param_is_acceptable(param, "Eina_Array *", WANT_OWN, WANT_OUT) || param_is_acceptable(param, "Eina_Array *", !WANT_OWN, WANT_OUT) || param_is_acceptable(param, "const Eina_Array *", WANT_OWN, WANT_OUT) || param_is_acceptable(param, "const Eina_Array *", !WANT_OWN, WANT_OUT) || param_is_acceptable(param, "Eina_List *", WANT_OWN, WANT_OUT) || param_is_acceptable(param, "Eina_List *", !WANT_OWN, WANT_OUT) || param_is_acceptable(param, "const Eina_List *", WANT_OWN, WANT_OUT) || param_is_acceptable(param, "const Eina_List *", !WANT_OWN, WANT_OUT) || param_is_acceptable(param, "Eina_Accessor *", WANT_OWN, WANT_OUT) || param_is_acceptable(param, "Eina_Accessor *", !WANT_OWN, WANT_OUT) || param_is_acceptable(param, "const Eina_Accessor *", WANT_OWN, WANT_OUT) || param_is_acceptable(param, "const Eina_Accessor *", !WANT_OWN, WANT_OUT) || param_is_acceptable(param, "Eina_Hash *", WANT_OWN, WANT_OUT) || param_is_acceptable(param, "Eina_Hash *", !WANT_OWN, WANT_OUT) || param_is_acceptable(param, "const Eina_Hash *", WANT_OWN, WANT_OUT) || param_is_acceptable(param, "const Eina_Hash *", !WANT_OWN, WANT_OUT) || param_is_acceptable(param, "Eina_Iterator *", WANT_OWN, WANT_OUT) || param_is_acceptable(param, "Eina_Iterator *", !WANT_OWN, WANT_OUT) || param_is_acceptable(param, "const Eina_Iterator *", WANT_OWN, WANT_OUT) || param_is_acceptable(param, "const Eina_Iterator *", !WANT_OWN, WANT_OUT) ) { attributes::complex_type_def const* complex = efl::eina::get(¶m.type.original_type); if (!complex) return false; return as_generator( type << " " << string << " = default(" << type << ");\n" ).generate(sink, std::make_tuple(param.type, out_variable_name(param.param_name), param.type), context); } else if (param_is_acceptable(param, "Eina_Value", WANT_OWN, WANT_OUT) || param_is_acceptable(param, "Eina_Value", !WANT_OWN, WANT_OUT)) { return as_generator( string << " = default(" << marshall_type << ");\n" << type << " " << string << " = null;\n" ).generate(sink, std::make_tuple(param.param_name, param, param, out_variable_name(param.param_name)), context); } else if (param.direction == attributes::parameter_direction::out) { // Assign a default value to the out variable in case we end up in the catch clause. return as_generator( string << " = default(" << type << ");" ).generate(sink, std::make_tuple(escape_keyword(param.param_name), param), context); } return true; } } const native_convert_out_variable {}; /* Assign the Managed out variables from the marshalled intermediate ones if needed. */ struct convert_out_assign_generator { template bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const { if (param.direction == attributes::parameter_direction::in) return true; auto regular = efl::eina::get(¶m.type.original_type); if (param.type.is_ptr && helpers::need_pointer_conversion(regular) && !helpers::need_struct_conversion_in_return(param.type, param.direction)) { bool ret = as_generator( string << " = Eina.PrimitiveConversion.PointerToManaged<" << type << ">(" << out_variable_name(param.param_name) << ");\n" ).generate(sink, std::make_tuple(escape_keyword(param.param_name), param.type), context); if (param.type.has_own) ret = ret && as_generator(scope_tab << scope_tab << "Marshal.FreeHGlobal(" << out_variable_name(param.param_name) << ");\n" ).generate(sink, attributes::unused, context); return ret; } else if (helpers::need_struct_conversion(regular)) { return as_generator( string << " = " << out_variable_name(param.param_name) << ";\n" ).generate(sink, escape_keyword(param.param_name), context); } else if (param_is_acceptable(param, "Eina_Binbuf *", WANT_OWN, WANT_OUT) || param_is_acceptable(param, "Eina_Binbuf *", !WANT_OWN, WANT_OUT) || param_is_acceptable(param, "const Eina_Binbuf *", WANT_OWN, WANT_OUT) || param_is_acceptable(param, "const Eina_Binbuf *", !WANT_OWN, WANT_OUT) ) { return as_generator( string << " = new Eina.Binbuf(" << string << ", " << (param.type.has_own ? "true" : "false") << ");\n" ).generate(sink, std::make_tuple(escape_keyword(param.param_name), out_variable_name(param.param_name)), context); } else if (param_is_acceptable(param, "Eina_Hash *", WANT_OWN, WANT_OUT) || param_is_acceptable(param, "Eina_Hash *", !WANT_OWN, WANT_OUT) || param_is_acceptable(param, "const Eina_Hash *", WANT_OWN, WANT_OUT) || param_is_acceptable(param, "const Eina_Hash *", !WANT_OWN, WANT_OUT) ) { attributes::complex_type_def const* complex = efl::eina::get(¶m.type.original_type); if (!complex || complex->subtypes.size() != 2) return false; return as_generator( string << " = new " << type << "(" << string << ", " << (param.type.has_own ? "true" : "false") << ", " << (complex->subtypes.front().has_own ? "true" : "false") << ", " << (complex->subtypes.back().has_own ? "true" : "false") << ");\n" ).generate(sink, std::make_tuple(escape_keyword(param.param_name), param.type, out_variable_name(param.param_name)), context); } else if (param_is_acceptable(param, "Eina_Array *", WANT_OWN, WANT_OUT) || param_is_acceptable(param, "Eina_Array *", !WANT_OWN, WANT_OUT) || param_is_acceptable(param, "const Eina_Array *", WANT_OWN, WANT_OUT) || param_is_acceptable(param, "const Eina_Array *", !WANT_OWN, WANT_OUT) - || param_is_acceptable(param, "Eina_List *", WANT_OWN, WANT_OUT) + ) + { + attributes::complex_type_def const* complex = efl::eina::get(¶m.type.original_type); + if (!complex) + return false; + return as_generator( + string << " = Efl.Eo.Globals.NativeArrayTo" << type << "(" << string + << ");\n" + ).generate(sink, std::make_tuple(escape_keyword(param.param_name), param.type, out_variable_name(param.param_name)), context); + } + else if (param_is_acceptable(param, "Eina_List *", WANT_OWN, WANT_OUT) || param_is_acceptable(param, "Eina_List *", !WANT_OWN, WANT_OUT) || param_is_acceptable(param, "const Eina_List *", WANT_OWN, WANT_OUT) || param_is_acceptable(param, "const Eina_List *", !WANT_OWN, WANT_OUT) ) { attributes::complex_type_def const* complex = efl::eina::get(¶m.type.original_type); if (!complex) return false; return as_generator( - string << " = new " << type << "(" << string - << ", " << (param.type.has_own ? "true" : "false") - << ", " << (param.type.has_own && (complex->subtypes.front().is_value_type || complex->subtypes.front().has_own) ? "true" : "false") + string << " = Efl.Eo.Globals.NativeListTo" << type << "(" << string << ");\n" ).generate(sink, std::make_tuple(escape_keyword(param.param_name), param.type, out_variable_name(param.param_name)), context); } else if (param_is_acceptable(param, "Eina_Accessor *", WANT_OWN, WANT_OUT) || param_is_acceptable(param, "Eina_Accessor *", !WANT_OWN, WANT_OUT) || param_is_acceptable(param, "const Eina_Accessor *", WANT_OWN, WANT_OUT) || param_is_acceptable(param, "const Eina_Accessor *", !WANT_OWN, WANT_OUT) ) { attributes::complex_type_def const* complex = efl::eina::get(¶m.type.original_type); if (!complex) return false; return as_generator( string << " = Efl.Eo.Globals.AccessorTo" << type << "(" << string << ");\n" ).generate(sink, std::make_tuple(escape_keyword(param.param_name), param.type, out_variable_name(param.param_name)), context); } else if (param_is_acceptable(param, "Eina_Iterator *", WANT_OWN, WANT_OUT) || param_is_acceptable(param, "Eina_Iterator *", !WANT_OWN, WANT_OUT) || param_is_acceptable(param, "const Eina_Iterator *", WANT_OWN, WANT_OUT) || param_is_acceptable(param, "const Eina_Iterator *", !WANT_OWN, WANT_OUT) ) { attributes::complex_type_def const* complex = efl::eina::get(¶m.type.original_type); if (!complex) return false; return as_generator( string << " = Efl.Eo.Globals.IteratorTo" << type << "(" << string << ");\n" ).generate(sink, std::make_tuple(escape_keyword(param.param_name), param.type, out_variable_name(param.param_name)), context); } else if (param_is_acceptable(param, "Eina_Value", WANT_OWN, WANT_OUT) || param_is_acceptable(param, "Eina_Value", !WANT_OWN, WANT_OUT)) { return as_generator( string << " = new " << type << "(" << string << ");\n" ).generate(sink, std::make_tuple(param.param_name, param.type, out_variable_name(param.param_name)), context); } return true; } } const convert_out_assign {}; struct native_convert_in_ptr_assign_generator { template bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const { auto regular = efl::eina::get(¶m.type.original_type); if (param_should_use_in_var(param, true) && param.type.is_ptr && !param.type.has_own && helpers::need_struct_conversion(regular)) { return as_generator( string << " = " << in_variable_name(param.param_name) << ";\n" ).generate(sink, escape_keyword(param.param_name), context); } return true; } } const native_convert_in_ptr_assign {}; struct convert_in_ptr_assign_generator { template bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const { auto regular = efl::eina::get(¶m.type.original_type); if (param_should_use_in_var(param, true) && param.type.is_ptr && !param.type.has_own && helpers::need_struct_conversion(regular)) { return as_generator( string << " = " << in_variable_name(param.param_name) << ";\n" ).generate(sink, escape_keyword(param.param_name), context); } + else if (param_is_acceptable(param, "Eina_Array *", WANT_OWN, !WANT_OUT) + || param_is_acceptable(param, "Eina_Array *", !WANT_OWN, !WANT_OUT) + || param_is_acceptable(param, "const Eina_Array *", WANT_OWN, !WANT_OUT) + || param_is_acceptable(param, "const Eina_Array *", !WANT_OWN, !WANT_OUT) + ) + { + return as_generator( + scope_tab(2) << lit("Efl.Eo.Globals.UpdateListFromNativeArray(") << escape_keyword(param.param_name) << ", " << in_variable_name(param.param_name) << ");\n" + ).generate(sink, attributes::unused, context); + } + return true; } } const convert_in_ptr_assign {}; struct convert_return_variable_generator { template bool generate(OutputIterator sink, attributes::type_def const& ret_type, Context const& context) const { if (ret_type.c_type != "void") return as_generator("var _ret_var = ").generate(sink, attributes::unused, context); return true; } } const convert_return_variable {}; /* Converts the intermediate return variable to the proper API type */ struct convert_return_generator { template bool generate(OutputIterator sink, attributes::type_def const& ret_type, Context const& context) const { auto regular = efl::eina::get(&ret_type.original_type); if (ret_type.is_ptr && helpers::need_pointer_conversion(regular) && !helpers::need_struct_conversion_in_return(ret_type, attributes::parameter_direction::unknown)) { return as_generator( "var __ret_tmp = Eina.PrimitiveConversion.PointerToManaged<" << type << ">(_ret_var);\n" << scope_tab << scope_tab << (ret_type.has_own ? ("Marshal.FreeHGlobal(_ret_var);\n"): "\n") << scope_tab << scope_tab << "return __ret_tmp;\n" ).generate(sink, ret_type, context); } else if (helpers::need_struct_conversion(regular)) { return as_generator( "return _ret_var;" ).generate(sink, nullptr, context); } else if (ret_type.c_type == "Eina_Binbuf *" || ret_type.c_type == "const Eina_Binbuf *") { if (!as_generator("var _binbuf_ret = new Eina.Binbuf(_ret_var, " << std::string{ret_type.has_own ? "true" : "false"} << ");\n" << scope_tab << scope_tab << "return _binbuf_ret;\n") .generate(sink, attributes::unused, context)) return false; } else if (ret_type.c_type == "Eina_Hash *" || ret_type.c_type == "const Eina_Hash *") { attributes::complex_type_def const* complex = efl::eina::get(&ret_type.original_type); if (!complex || complex->subtypes.size() != 2) return false; if (!as_generator("return new " << type << "(_ret_var, " << std::string{ret_type.has_own ? "true" : "false"} << ", " << (complex->subtypes.front().has_own ? "true" : "false") << ", " << (complex->subtypes.back().has_own ? "true" : "false") << ");\n") .generate(sink, ret_type, context)) return false; } - else if (ret_type.c_type == "Eina_Array *" || ret_type.c_type == "const Eina_Array *" - || ret_type.c_type == "Eina_List *" || ret_type.c_type == "const Eina_List *" - ) + else if (ret_type.c_type == "Eina_Array *" || ret_type.c_type == "const Eina_Array *") { attributes::complex_type_def const* complex = efl::eina::get(&ret_type.original_type); if (!complex) return false; - if (!as_generator("return new " << type << "(_ret_var, " << std::string{ret_type.has_own ? "true" : "false"} - << ", " << (ret_type.has_own && (complex->subtypes.front().is_value_type || complex->subtypes.front().has_own) ? "true" : "false") - << ");\n") - .generate(sink, ret_type, context)) + + if (!as_generator("return Efl.Eo.Globals.NativeArrayTo" << type << "(_ret_var);") + .generate(sink, ret_type, context)) + return false; + } + else if (ret_type.c_type == "Eina_List *" || ret_type.c_type == "const Eina_List *") + { + attributes::complex_type_def const* complex = efl::eina::get(&ret_type.original_type); + if (!complex) + return false; + if (!as_generator("return Efl.Eo.Globals.NativeListTo" << type << "(_ret_var);") + .generate(sink, ret_type, context)) return false; } else if (ret_type.c_type == "Eina_Accessor *" || ret_type.c_type == "const Eina_Accessor *") { attributes::complex_type_def const* complex = efl::eina::get(&ret_type.original_type); if (!complex) return false; if (!as_generator("return Efl.Eo.Globals.AccessorTo" << type << "(_ret_var);") .generate(sink, ret_type, context)) return false; } else if (ret_type.c_type == "Eina_Iterator *" || ret_type.c_type == "const Eina_Iterator *") { attributes::complex_type_def const* complex = efl::eina::get(&ret_type.original_type); if (!complex) return false; if (!as_generator("return Efl.Eo.Globals.IteratorTo" << type << "(_ret_var);") .generate(sink, ret_type, context)) return false; } else if (ret_type.c_type != "void") { return as_generator("return _ret_var;").generate(sink, ret_type, context); } return true; } } const convert_return {}; // Native (virtual wrappers) generators struct native_convert_out_assign_generator { attributes::klass_def const* klass; template bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const { EINA_CXX_DOM_LOG_DBG(eolian_mono::domain) << "native_convert_out_assign_generator: " << param.param_name << std::endl; if (param.direction == attributes::parameter_direction::in) return true; auto regular = efl::eina::get(¶m.type.original_type); if (param.type.is_ptr && helpers::need_pointer_conversion(regular) && !helpers::need_struct_conversion_in_return(param.type, param.direction)) { return as_generator( string << " = Eina.PrimitiveConversion.ManagedToPointerAlloc(" << string << ");\n" ).generate(sink, std::make_tuple(escape_keyword(param.param_name), out_variable_name(param.param_name)), context); } else if (helpers::need_struct_conversion(regular)) { return as_generator( string << " = " << string << ";\n" ).generate(sink, std::make_tuple(escape_keyword(param.param_name), out_variable_name(param.param_name)), context); } else if (param_is_acceptable(param, "Eina_Stringshare *", !WANT_OWN, WANT_OUT)) { if (klass == nullptr) { EINA_CXX_DOM_LOG_ERR(eolian_mono::domain) << "Null class found when trying to assign out stringshare from native wrapper." << std::endl; return false; } return as_generator( string << "= " << string << ";\n" ).generate(sink, std::make_tuple(escape_keyword(param.param_name), out_variable_name(param.param_name)), context); } else if (param_is_acceptable(param, "const char *", !WANT_OWN, WANT_OUT)) { if (klass == nullptr) { EINA_CXX_DOM_LOG_ERR(eolian_mono::domain) << "Null class found when trying to assign out string from native wrapper." << std::endl; return false; } return as_generator( string << " = " << string << ";\n" ).generate(sink, std::make_tuple(escape_keyword(param.param_name), out_variable_name(param.param_name)), context); } else if (param_is_acceptable(param, "Eina_Binbuf *", WANT_OWN, WANT_OUT) || param_is_acceptable(param, "Eina_Binbuf *", !WANT_OWN, WANT_OUT) || param_is_acceptable(param, "const Eina_Binbuf *", WANT_OWN, WANT_OUT) || param_is_acceptable(param, "const Eina_Binbuf *", !WANT_OWN, WANT_OUT) ) { if (!as_generator( string << " = " << string << ".Handle;\n" ).generate(sink, std::make_tuple(escape_keyword(param.param_name), out_variable_name(param.param_name)), context)) return false; if (param.type.has_own) return as_generator( string << ".Own = false;\n" ).generate(sink, out_variable_name(param.param_name), context); } else if (param_is_acceptable(param, "Eina_Hash *", WANT_OWN, WANT_OUT) || param_is_acceptable(param, "Eina_Hash *", !WANT_OWN, WANT_OUT) || param_is_acceptable(param, "const Eina_Hash *", WANT_OWN, WANT_OUT) || param_is_acceptable(param, "const Eina_Hash *", !WANT_OWN, WANT_OUT) ) { attributes::complex_type_def const* complex = efl::eina::get(¶m.type.original_type); if (!complex || complex->subtypes.size() != 2) return false; auto outvar = out_variable_name(param.param_name); if (!as_generator( string << " = " << string << ".Handle;\n" ).generate(sink, std::make_tuple(escape_keyword(param.param_name), outvar), context)) return false; if (param.type.has_own && !as_generator( string << ".SetOwn(false);\n" ).generate(sink, outvar, context)) return false; if (complex->subtypes.front().has_own && !as_generator( string << ".SetOwnKey(false);\n" ).generate(sink, outvar, context)) return false; if (complex->subtypes.back().has_own && !as_generator( string << ".SetOwnValue(false);\n" << string << ".UnSetFreeCb();\n" ).generate(sink, std::make_tuple(outvar, outvar), context)) return false; } else if (param_is_acceptable(param, "Eina_Array *", WANT_OWN, WANT_OUT) || param_is_acceptable(param, "Eina_Array *", !WANT_OWN, WANT_OUT) || param_is_acceptable(param, "const Eina_Array *", WANT_OWN, WANT_OUT) - || param_is_acceptable(param, "const Eina_Array *", !WANT_OWN, WANT_OUT) - || param_is_acceptable(param, "Eina_List *", WANT_OWN, WANT_OUT) - || param_is_acceptable(param, "Eina_List *", !WANT_OWN, WANT_OUT) - || param_is_acceptable(param, "const Eina_List *", WANT_OWN, WANT_OUT) - || param_is_acceptable(param, "const Eina_List *", !WANT_OWN, WANT_OUT) - ) + || param_is_acceptable(param, "const Eina_Array *", !WANT_OWN, WANT_OUT)) { attributes::complex_type_def const* complex = efl::eina::get(¶m.type.original_type); if (!complex) return false; auto outvar = out_variable_name(param.param_name); if (!as_generator( - string << " = " << string << ".Handle;\n" + string << " = Efl.Eo.Globals.IListToNativeArray(" << string << ", " << (param.type.has_own ? "true" : "false")<< ");\n" ).generate(sink, std::make_tuple(escape_keyword(param.param_name), outvar), context)) return false; - if (param.type.has_own && !as_generator( - string << ".Own = false;\n" - ).generate(sink, outvar, context)) + } + else if (param_is_acceptable(param, "Eina_List *", WANT_OWN, WANT_OUT) + || param_is_acceptable(param, "Eina_List *", !WANT_OWN, WANT_OUT) + || param_is_acceptable(param, "const Eina_List *", WANT_OWN, WANT_OUT) + || param_is_acceptable(param, "const Eina_List *", !WANT_OWN, WANT_OUT)) + { + attributes::complex_type_def const* complex = efl::eina::get(¶m.type.original_type); + if (!complex) return false; - if ((param.type.has_own && (complex->subtypes.front().is_value_type && complex->subtypes.front().has_own)) - && !as_generator( - string << ".OwnContent = false;\n" - ).generate(sink, outvar, context)) + auto outvar = out_variable_name(param.param_name); + if (!as_generator( + string << " = Efl.Eo.Globals.IListToNativeList(" << string << ", " << (param.type.has_own ? "true" : "false")<<");\n" + ).generate(sink, std::make_tuple(escape_keyword(param.param_name), outvar), context)) return false; } else if (param_is_acceptable(param, "Eina_Accessor *", WANT_OWN, WANT_OUT) || param_is_acceptable(param, "Eina_Accessor *", !WANT_OWN, WANT_OUT) || param_is_acceptable(param, "const Eina_Accessor *", WANT_OWN, WANT_OUT) || param_is_acceptable(param, "const Eina_Accessor *", !WANT_OWN, WANT_OUT) ) { attributes::complex_type_def const* complex = efl::eina::get(¶m.type.original_type); if (!complex) return false; auto outvar = out_variable_name(param.param_name); if (!as_generator( string << " = Efl.Eo.Globals.IEnumerableToAccessor(" << string << ", " << (param.type.has_own ? "true" : "false")<< ");\n" ).generate(sink, std::make_tuple(escape_keyword(param.param_name), outvar), context)) return false; } else if (param_is_acceptable(param, "Eina_Iterator *", WANT_OWN, WANT_OUT) || param_is_acceptable(param, "Eina_Iterator *", !WANT_OWN, WANT_OUT) || param_is_acceptable(param, "const Eina_Iterator *", WANT_OWN, WANT_OUT) || param_is_acceptable(param, "const Eina_Iterator *", !WANT_OWN, WANT_OUT) ) { attributes::complex_type_def const* complex = efl::eina::get(¶m.type.original_type); if (!complex) return false; auto outvar = out_variable_name(param.param_name); if (!as_generator( string << " = Efl.Eo.Globals.IEnumerableToIterator(" << string << ", " << (param.type.has_own ? "true" : "false")<< ");\n" ).generate(sink, std::make_tuple(escape_keyword(param.param_name), outvar), context)) return false; } return true; } }; struct native_convert_return_variable_generator { template bool generate(OutputIterator sink, attributes::type_def const& ret_type, Context const& context) const { if (ret_type.c_type == "Eina_Accessor *" || ret_type.c_type == "const Eina_Accessor *" || ret_type.c_type == "Eina_Iterator *" || ret_type.c_type == "const Eina_Iterator *") return as_generator( type << " _ret_var = null;" ).generate(sink, ret_type, context); else if (ret_type.c_type != "void") return as_generator( type << " _ret_var = default(" << type << ");" ).generate(sink, std::make_tuple(ret_type, ret_type), context); return true; } } const native_convert_return_variable {}; struct native_convert_return_generator { attributes::klass_def const* klass; template bool generate(OutputIterator sink, attributes::type_def const& ret_type, Context const& context) const { auto regular = efl::eina::get(&ret_type.original_type); if (ret_type.is_ptr && helpers::need_pointer_conversion(regular) && !helpers::need_struct_conversion_in_return(ret_type, attributes::parameter_direction::unknown) ) { return as_generator( "return Eina.PrimitiveConversion.ManagedToPointerAlloc(_ret_var);" ).generate(sink, attributes::unused, context); } else if (helpers::need_struct_conversion(regular)) { return as_generator( "return _ret_var;" ).generate(sink, nullptr, context); } else if (ret_type.c_type == "const char *") { if(!ret_type.has_own) { if (klass == nullptr) { EINA_CXX_DOM_LOG_ERR(eolian_mono::domain) << "Null class found when trying to return string from native wrapper." << std::endl; return false; } return as_generator( "return _ret_var;" ).generate(sink, attributes::unused, context); } else { return as_generator("return _ret_var;" ).generate(sink, attributes::unused, context); } } else if (ret_type.c_type == "Eina_Stringshare *") { // Correct check for string? if (!ret_type.has_own) { if (klass == nullptr) { EINA_CXX_DOM_LOG_ERR(eolian_mono::domain) << "Null class found when trying to return stringshare from native wrapper." << std::endl; return false; } return as_generator( "return _ret_var;" ).generate(sink, attributes::unused, context); } else { return as_generator("return _ret_var;") .generate(sink, attributes::unused, context); } } else if (ret_type.c_type == "Eina_Binbuf *" || ret_type.c_type == "const Eina_Binbuf *") { if (ret_type.has_own && !as_generator("_ret_var.Own = false; ") .generate(sink, attributes::unused, context)) return false; return as_generator("return _ret_var.Handle;") .generate(sink, attributes::unused, context); } else if (ret_type.c_type == "Eina_Hash *" || ret_type.c_type == "const Eina_Hash *") { attributes::complex_type_def const* complex = efl::eina::get(&ret_type.original_type); if (!complex || complex->subtypes.size() != 2) return false; if (ret_type.has_own && !as_generator("_ret_var.SetOwn(false); ") .generate(sink, attributes::unused, context)) return false; if (complex->subtypes.front().has_own && !as_generator("_ret_var.SetOwnKey(false); ") .generate(sink, attributes::unused, context)) return false; if (complex->subtypes.back().has_own && !as_generator("_ret_var.SetOwnValue(false); _ret_var.UnSetFreeCb(); ") .generate(sink, attributes::unused, context)) return false; return as_generator("return _ret_var.Handle;") .generate(sink, attributes::unused, context); } - else if (ret_type.c_type == "Eina_Array *" || ret_type.c_type == "const Eina_Array *" - || ret_type.c_type == "Eina_List *" || ret_type.c_type == "const Eina_List *" - ) + else if (ret_type.c_type == "Eina_Array *" || ret_type.c_type == "const Eina_Array *") { attributes::complex_type_def const* complex = efl::eina::get(&ret_type.original_type); if (!complex) return false; - if (ret_type.has_own && !as_generator("_ret_var.Own = false; ") - .generate(sink, attributes::unused, context)) + + return as_generator(lit("return Efl.Eo.Globals.IListToNativeArray(_ret_var, ") << (ret_type.has_own ? "true" : "false") << ");") + .generate(sink, attributes::unused, context); + } + else if (ret_type.c_type == "Eina_List *" || ret_type.c_type == "const Eina_List *") + { + attributes::complex_type_def const* complex = efl::eina::get(&ret_type.original_type); + if (!complex) return false; - return as_generator("return _ret_var.Handle;") + return as_generator(lit("return Efl.Eo.Globals.IListToNativeList(_ret_var, ") << (ret_type.has_own ? "true" : "false") << ");") .generate(sink, attributes::unused, context); } else if (ret_type.c_type == "Eina_Accessor *" || ret_type.c_type == "const Eina_Accessor *") { return as_generator(lit("return Efl.Eo.Globals.IEnumerableToAccessor(_ret_var, ") << (ret_type.has_own ? "true" : "false") << ");") .generate(sink, attributes::unused, context); } else if (ret_type.c_type == "Eina_Iterator *" || ret_type.c_type == "const Eina_Iterator *") { return as_generator(lit("return Efl.Eo.Globals.IEnumerableToIterator(_ret_var, ") << (ret_type.has_own ? "true" : "false") << ");") .generate(sink, attributes::unused, context); } else if (ret_type.c_type != "void") return as_generator("return _ret_var;").generate(sink, ret_type, context); return true; } }; struct native_convert_out_assign_parameterized { native_convert_out_assign_generator const operator()(attributes::klass_def const &klass) const { return {&klass}; } } const native_convert_out_assign; struct native_convert_return_parameterized { native_convert_return_generator const operator()(attributes::klass_def const &klass) const { return {&klass}; } } const native_convert_return; struct convert_function_pointer_generator { template bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const { if (param.direction != attributes::parameter_direction::in) return true; if (!param.type.original_type.visit(is_fp_visitor{})) return true; std::string param_name = escape_keyword(param.param_name); // Allocate GCHandle in "param_name"_handle for param; if (!as_generator( "GCHandle " << param_name << "_handle = GCHandle.Alloc(" << param_name << ");\n" ).generate(sink, attributes::unused, context)) return false; return true; } } const convert_function_pointer {}; struct native_convert_function_pointer_generator { template bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const { if (param.direction != attributes::parameter_direction::in) return true; if (!param.type.original_type.visit(is_fp_visitor{})) return true; // Getting the type through C api std::string type_name = param.type.original_type.visit(type_name_visitor{}); const Eolian_Typedecl *tpd = ::eolian_unit_alias_by_name_get(param.unit, type_name.c_str()); if (!tpd) { EINA_LOG_ERR("Failed to get typedecl for c type [%s]", param.type.c_type.c_str()); return false; } if (eolian_typedecl_type_get(tpd) != EOLIAN_TYPEDECL_FUNCTION_POINTER) return true; const Eolian_Function *fd = eolian_typedecl_function_pointer_get(tpd); if (!fd) { EINA_LOG_ERR("Failed to get function pointer info for c type [%s]", param.type.c_type.c_str()); return false; } attributes::function_def f(fd, EOLIAN_FUNCTION_POINTER, tpd, param.unit); std::string param_name = escape_keyword(param.param_name); // Allocate GCHandle in "param_name"_handle for param; if (!as_generator( scope_tab << type << "Wrapper " << param_name << "_wrapper = new " << type << "Wrapper(" << param_name << ", " << param_name << "_data, " << param_name << "_free_cb);\n" ).generate(sink, std::make_tuple(param.type, param.type), context)) return false; // FIXME What about calling the free function? return true; } } const native_convert_function_pointer {}; struct constructor_parameter_name_generator { template bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const { auto target_name = name_helpers::constructor_managed_name(ctor.name); // Only multi-valued constructing methods get their actual parameter names if (ctor.function.parameters.size() > 1) target_name += '_' + param.param_name; auto name = name_helpers::managed_name(target_name); name[0] = std::tolower(name[0]); return as_generator(string).generate(sink, name, context); } attributes::constructor_def const& ctor; }; struct constructor_parameter_name_parameterized { constructor_parameter_name_generator const operator()(attributes::constructor_def const& ctor) const { return {ctor}; } } const constructor_parameter_name; // Generates the parameters for the given constructor // If the constructor receives multiple parameters, they get the name // of the constructor plus the name of the parameter (e.g. DefineParentData, DefineIndex) struct constructor_param_generator { template bool generate(OutputIterator sink, attributes::constructor_def const& ctor, Context const& context) const { auto params = ctor.function.parameters; if (!as_generator( efl::eolian::grammar::attribute_reorder<1, -1> (type(false, ctor.is_optional) << " " << constructor_parameter_name(ctor) << (ctor.is_optional ? " = null" : "")) % ", " ).generate(sink, params, context)) return false; // } return true; } } const constructor_param; // Generates the invocation of the given parameter struct constructor_invocation_generator { template bool generate(OutputIterator sink, attributes::constructor_def const& ctor, Context const& context) const { auto params = ctor.function.parameters; if (!as_generator( scope_tab << "if (" << (efl::eolian::grammar::attribute_reorder<-1> ("Efl.Eo.Globals.ParamHelperCheck(" << constructor_parameter_name(ctor) << ")") % " || ") << ")\n" << scope_tab(2) << scope_tab << "{\n" << scope_tab(2) << scope_tab << scope_tab << name_helpers::managed_method_name(ctor.function) << "(" ).generate(sink, params, context)) return false; size_t idx = 0; for (auto&& param : params) { idx++; if (!as_generator( "Efl.Eo.Globals.GetParamHelper(" << constructor_parameter_name(ctor) << ")" << ((idx < params.size()) ? ", " : "") ).generate(sink, param, context)) return false; } if (!as_generator( ");\n" << scope_tab(2) << scope_tab << "}\n").generate(sink, attributes::unused, context)) return false; return true; } } const constructor_invocation; } #endif diff --git a/src/bin/eolian_mono/eolian/mono/struct_definition.hh b/src/bin/eolian_mono/eolian/mono/struct_definition.hh index 24d0ff34ca..176b5518d7 100644 --- a/src/bin/eolian_mono/eolian/mono/struct_definition.hh +++ b/src/bin/eolian_mono/eolian/mono/struct_definition.hh @@ -1,831 +1,850 @@ /* * Copyright 2019 by its authors. See AUTHORS. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef EOLIAN_MONO_STRUCT_DEFINITION_HH #define EOLIAN_MONO_STRUCT_DEFINITION_HH #include "grammar/generator.hpp" #include "grammar/klass_def.hpp" #include "grammar/indentation.hpp" #include "grammar/list.hpp" #include "grammar/alternative.hpp" #include "grammar/attribute_reorder.hpp" #include "name_helpers.hh" #include "helpers.hh" #include "type.hh" #include "using_decl.hh" #include "documentation.hh" #include "struct_fields.hh" #include "blacklist.hh" #include "culture_info.hh" namespace eolian_mono { inline std::string binding_struct_name(attributes::struct_def const& struct_) { return name_helpers::typedecl_managed_name(struct_); } inline std::string struct_internal_decl_name() { return "NativeStruct"; } inline std::string binding_struct_internal_name(attributes::struct_def const& struct_) { return binding_struct_name(struct_) + "." + struct_internal_decl_name(); } // Conversors generation // struct to_internal_field_convert_generator { template bool generate(OutputIterator sink, attributes::struct_field_def const& field, Context const& context) const { auto const& indent = current_indentation(context); auto field_name = name_helpers::to_field_name(field.name); // FIXME Replace need_struct_conversion(regular) with need_struct_conversion(type) auto regular = efl::eina::get(&field.type.original_type); auto klass = efl::eina::get(&field.type.original_type); auto complex = efl::eina::get(&field.type.original_type); if (klass) { if (!as_generator( indent << scope_tab << scope_tab << "_internal_struct." << string << " = _external_struct." << string << "?.NativeHandle ?? System.IntPtr.Zero;\n") .generate(sink, std::make_tuple(field_name, field_name), context)) return false; } + else if ((complex && (complex->outer.base_type == "array"))) + { + if (!as_generator( + indent << scope_tab << scope_tab << "_internal_struct." << string << " = Efl.Eo.Globals.IListToNativeArray(_external_struct." << string << ", " << (field.type.has_own ? "true" : "false") << ");\n") + .generate(sink, std::make_tuple(field_name, field_name), context)) + return false; + } + else if ((complex && (complex->outer.base_type == "list"))) + { + if (!as_generator( + indent << scope_tab << scope_tab << "_internal_struct." << string << " = Efl.Eo.Globals.IListToNativeList(_external_struct." << string << ", " << (field.type.has_own ? "true" : "false") << ");\n") + .generate(sink, std::make_tuple(field_name, field_name), context)) + return false; + } else if ((complex && (complex->outer.base_type == "iterator"))) { if (!as_generator( indent << scope_tab << scope_tab << "_internal_struct." << string << " = Efl.Eo.Globals.IEnumerableToIterator(_external_struct." << string << ", " << (field.type.has_own ? "true" : "false") << ");\n") .generate(sink, std::make_tuple(field_name, field_name), context)) return false; } - else if ((complex && (complex->outer.base_type == "array" - || complex->outer.base_type == "list" - || complex->outer.base_type == "hash")) + else if ((complex && (complex->outer.base_type == "hash")) || field.type.c_type == "Eina_Binbuf *" || field.type.c_type == "const Eina_Binbuf *") { // Always assumes pointer if (!as_generator( indent << scope_tab << scope_tab << "_internal_struct." << string << " = _external_struct." << string << ".Handle;\n") .generate(sink, std::make_tuple(field_name, field_name), context)) return false; } else if (field.type.is_ptr && helpers::need_pointer_conversion(regular) && !helpers::need_struct_conversion(regular)) { if (!as_generator( indent << scope_tab << scope_tab << "_internal_struct." << string << " = Eina.PrimitiveConversion.ManagedToPointerAlloc(_external_struct." << string << ");\n") .generate(sink, std::make_tuple(field_name, field_name), context)) return false; } else if (helpers::need_struct_conversion(regular)) { if (!as_generator( indent << scope_tab << scope_tab << "_internal_struct." << string << " = _external_struct." << string << ";\n") .generate(sink, std::make_tuple(field_name, field_name), context)) return false; } else if (regular && (regular->base_type == "string" || regular->base_type == "mstring")) { if (!as_generator( indent << scope_tab << scope_tab << "_internal_struct." << string << " = Eina.MemoryNative.StrDup(_external_struct." << string << ");\n") .generate(sink, std::make_tuple(field_name, field_name), context)) return false; } else if (regular && regular->base_type == "stringshare") { if (!as_generator( indent << scope_tab << scope_tab << "_internal_struct." << string << " = Eina.MemoryNative.AddStringshare(_external_struct." << string << ");\n") .generate(sink, std::make_tuple(field_name, field_name), context)) return false; } else if (field.type.c_type == "Eina_Slice" || field.type.c_type == "const Eina_Slice" || field.type.c_type == "Eina_Rw_Slice" || field.type.c_type == "const Eina_Rw_Slice") { if (!as_generator( "\n" << indent << scope_tab << scope_tab << "_internal_struct." << field_name << ".Len = _external_struct." << field_name << ".Len;\n" << indent << scope_tab << scope_tab << "_internal_struct." << field_name << ".Mem = _external_struct." << field_name << ".Mem;\n") .generate(sink, attributes::unused, context)) return false; } else if (field.type.c_type == "Eina_Value" || field.type.c_type == "const Eina_Value") { if (!as_generator( indent << scope_tab << scope_tab << "_internal_struct." << string << " = _external_struct." << string << ".GetNative();\n" ).generate(sink, std::make_tuple(field_name, field_name), context)) return false; } else if (field.type.c_type == "Eina_Value *" || field.type.c_type == "const Eina_Value *") { if (!as_generator( indent << scope_tab << scope_tab << "_internal_struct." << string << " = _external_struct." << string << "?.NativeHandle ?? System.IntPtr.Zero;\n" ).generate(sink, std::make_tuple(field_name, field_name), context)) return false; } else if (!field.type.is_ptr && regular && regular->base_type == "bool") { if (!as_generator( indent << scope_tab << scope_tab << "_internal_struct." << string << " = _external_struct." << string << " ? (byte)1 : (byte)0;\n") .generate(sink, std::make_tuple(field_name, field_name), context)) return false; } else if (!field.type.is_ptr && regular && regular->base_type == "char") { if (!as_generator( indent << scope_tab << scope_tab << "_internal_struct." << string << " = (byte)_external_struct." << string << ";\n") .generate(sink, std::make_tuple(field_name, field_name), context)) return false; } else // primitives and enums { if (!as_generator( indent << scope_tab << scope_tab << "_internal_struct." << string << " = _external_struct." << string << ";\n") .generate(sink, std::make_tuple(field_name, field_name), context)) return false; } return true; } } const to_internal_field_convert {}; struct to_external_field_convert_generator { template bool generate(OutputIterator sink, attributes::struct_field_def const& field, Context const& context) const { auto const& indent = current_indentation(context); auto field_name = name_helpers::to_field_name(field.name); auto regular = efl::eina::get(&field.type.original_type); auto klass = efl::eina::get(&field.type.original_type); auto complex = efl::eina::get(&field.type.original_type); if (klass) { auto interface_name = name_helpers::klass_full_interface_name(*klass); auto concrete_name = name_helpers::klass_full_concrete_name(*klass); if (!as_generator( "\n" << indent << scope_tab << scope_tab << "_external_struct." << string << " = (" << concrete_name << ") Efl.Eo.Globals.CreateWrapperFor(_internal_struct." << string << ");\n" ).generate(sink, std::make_tuple(field_name, field_name), context)) return false; } else if (field.type.c_type == "Eina_Binbuf *" || field.type.c_type == "const Eina_Binbuf *") { if (!as_generator( indent << scope_tab << scope_tab << "_external_struct." << string << " = new " << type << "(_internal_struct." << string << ", false);\n") .generate(sink, std::make_tuple(field_name, field.type, field_name), context)) return false; } - else if (complex && (complex->outer.base_type == "array" - || complex->outer.base_type == "list")) + else if (complex && (complex->outer.base_type == "array")) + { + // Always assumes pointer + if (!as_generator( + indent << scope_tab << scope_tab << "_external_struct." << string << " = Efl.Eo.Globals.NativeArrayTo" << type << "(_internal_struct." << string << ");\n") + .generate(sink, std::make_tuple(field_name, field.type, field_name), context)) + return false; + } + else if (complex && (complex->outer.base_type == "list")) { // Always assumes pointer if (!as_generator( - indent << scope_tab << scope_tab << "_external_struct." << string << " = new " << type << "(_internal_struct." << string << ", false, false);\n") + indent << scope_tab << scope_tab << "_external_struct." << string << " = Efl.Eo.Globals.NativeListTo" << type << "(_internal_struct." << string << ");\n") .generate(sink, std::make_tuple(field_name, field.type, field_name), context)) return false; } else if (complex && complex->outer.base_type == "hash") { if (!as_generator( indent << scope_tab << scope_tab << "_external_struct." << string << " = new " << type << "(_internal_struct." << string << ", false, false, false);\n") .generate(sink, std::make_tuple(field_name, field.type, field_name), context)) return false; } else if (complex && complex->outer.base_type == "iterator") { if (!as_generator( indent << scope_tab << scope_tab << "_external_struct." << string << " = Efl.Eo.Globals.IteratorTo" << type << "(_internal_struct." << string << ");\n") .generate(sink, std::make_tuple(field_name, field.type, field_name), context)) return false; } else if (field.type.is_ptr && helpers::need_pointer_conversion(regular) && !helpers::need_struct_conversion(regular)) { if (!as_generator( indent << scope_tab << scope_tab << "_external_struct." << string << " = Eina.PrimitiveConversion.PointerToManaged<" << type << ">(_internal_struct." << string << ");\n") .generate(sink, std::make_tuple(field_name, field.type, field_name), context)) return false; } else if (helpers::need_struct_conversion(regular)) { if (!as_generator( indent << scope_tab << scope_tab << "_external_struct." << string << " = _internal_struct." << string << ";\n") .generate(sink, std::make_tuple(field_name, field_name), context)) return false; } else if (regular && (regular->base_type == "string" || regular->base_type == "mstring" || regular->base_type == "stringshare")) { if (!as_generator( indent << scope_tab << scope_tab << "_external_struct." << string << " = Eina.StringConversion.NativeUtf8ToManagedString(_internal_struct." << string << ");\n") .generate(sink, std::make_tuple(field_name, field_name), context)) return false; } else if (field.type.c_type == "Eina_Slice" || field.type.c_type == "const Eina_Slice" || field.type.c_type == "Eina_Rw_Slice" || field.type.c_type == "const Eina_Rw_Slice") { if (!as_generator( "\n" << indent << scope_tab << scope_tab << "_external_struct." << field_name << ".Len = _internal_struct." << field_name << ".Len;\n" << indent << scope_tab << scope_tab << "_external_struct." << field_name << ".Mem = _internal_struct." << field_name << ".Mem;\n") .generate(sink, attributes::unused, context)) return false; } else if (field.type.c_type == "Eina_Value" || field.type.c_type == "const Eina_Value") { if (!as_generator( indent << scope_tab << scope_tab << "_external_struct." << string << " = new Eina.Value(_internal_struct." << string << ");\n" ).generate(sink, std::make_tuple(field_name, field_name), context)) return false; } else if (field.type.c_type == "Eina_Value *" || field.type.c_type == "const Eina_Value *") { if (!as_generator( indent << scope_tab << scope_tab << "_external_struct." << string << " = new Eina.Value(_internal_struct." << string << ", Eina.Ownership.Unmanaged);\n" ).generate(sink, std::make_tuple(field_name, field_name), context)) return false; } else if (!field.type.is_ptr && regular && regular->base_type == "bool") { if (!as_generator( indent << scope_tab << scope_tab << "_external_struct." << string << " = _internal_struct." << string << " != 0;\n" ).generate(sink, std::make_tuple(field_name, field_name), context)) return false; } else if (!field.type.is_ptr && regular && regular->base_type == "char") { if (!as_generator( indent << scope_tab << scope_tab << "_external_struct." << string << " = (char)_internal_struct." << string << ";\n" ).generate(sink, std::make_tuple(field_name, field_name), context)) return false; } else // primitives and enums { if (!as_generator( indent << scope_tab << scope_tab << "_external_struct." << string << " = _internal_struct." << string << ";\n") .generate(sink, std::make_tuple(field_name, field_name), context)) return false; } return true; } } const to_external_field_convert {}; // Internal Struct // struct struct_internal_definition_generator { template bool generate(OutputIterator sink, attributes::struct_def const& struct_, Context const& context) const { auto const& indent = current_indentation(context); if (!as_generator ( "#pragma warning disable CS1591\n\n" << indent << "/// Internal wrapper for struct " << string << ".\n" << indent << "[StructLayout(LayoutKind.Sequential)]\n" << indent << "internal struct " << string << "\n" << indent << "{\n" ) .generate(sink, std::make_tuple<>(binding_struct_name(struct_), struct_internal_decl_name()), context)) return false; // iterate struct fields for (auto const& field : struct_.fields) { auto field_name = name_helpers::to_field_name(field.name); auto klass = efl::eina::get(&field.type.original_type); auto regular = efl::eina::get(&field.type.original_type); if (klass || (regular && (regular->base_type == "string" || regular->base_type == "mstring" || regular->base_type == "stringshare" || regular->base_type == "any_value_ref"))) { if (!as_generator(indent << scope_tab << "/// Internal wrapper for field " << field_name << "\n" << indent << scope_tab << "public System.IntPtr " << field_name << ";\n") .generate(sink, nullptr, context)) return false; } else if (regular && !(regular->base_qualifier & efl::eolian::grammar::attributes::qualifier_info::is_ref) && regular->base_type == "bool") { if (!as_generator(indent << scope_tab << "/// Internal wrapper for field " << field_name << "\n" << indent << scope_tab << "public System.Byte " << field_name << ";\n") .generate(sink, nullptr, context)) return false; } else if (regular && !(regular->base_qualifier & efl::eolian::grammar::attributes::qualifier_info::is_ref) && regular->base_type == "char") { if (!as_generator(indent << scope_tab << "/// Internal wrapper for field " << field_name << "\n" << indent << scope_tab << "public System.Byte " << field_name << ";\n") .generate(sink, nullptr, context)) return false; } else if (!as_generator(indent << scope_tab << eolian_mono::marshall_annotation(false) << "\n" << indent << scope_tab << "public " << eolian_mono::marshall_type(false) << " " << string << ";\n") .generate(sink, std::make_tuple(field.type, field.type, field_name), context)) return false; } // Check whether this is an extern struct without declared fields in .eo file and generate a // placeholder field if positive. // Mono's JIT is picky when generating function pointer for delegates with empty structs, leading to // those 'mini-amd64.c condition fields not met' crashes. if (struct_.fields.size() == 0) { if (!as_generator(indent << scope_tab << "internal IntPtr field;\n").generate(sink, nullptr, context)) return false; } auto external_name = binding_struct_name(struct_); auto internal_name = binding_struct_internal_name(struct_); // to internal if (!as_generator( indent << scope_tab << "/// Implicit conversion to the internal/marshalling representation.\n" << indent << scope_tab << "public static implicit operator " << string << "(" << string << " _external_struct)\n" << indent << scope_tab << "{\n" << indent << scope_tab << scope_tab << "var _internal_struct = new " << string << "();\n" ).generate(sink, std::make_tuple(internal_name, external_name, internal_name), context)) return false; for (auto const& field : struct_.fields) { if (!to_internal_field_convert.generate(sink, field, context)) return false; } if (!as_generator(indent << scope_tab << scope_tab << "return _internal_struct;\n" << indent << scope_tab << "}\n\n").generate(sink, nullptr, context)) return false; // to managed if (!as_generator( indent << scope_tab << "/// Implicit conversion to the managed representation.\n" << indent << scope_tab << "public static implicit operator " << string << "(" << string << " _internal_struct)\n" << indent << scope_tab << "{\n" << indent << scope_tab << scope_tab << "var _external_struct = new " << string << "();\n" ).generate(sink, std::make_tuple(external_name, internal_name, external_name), context)) return false; for (auto const& field : struct_.fields) { if (!to_external_field_convert.generate(sink, field, context)) return false; } if (!as_generator(indent << scope_tab << scope_tab << "return _external_struct;\n" << indent << scope_tab << "}\n").generate(sink, nullptr, context)) return false; // close internal class if(!as_generator(indent << "}\n" << "#pragma warning restore CS1591\n" ).generate(sink, attributes::unused, context)) return false; return true; } } const struct_internal_definition {}; // Managed Struct // struct struct_definition_generator { /** * Generates an implicit operator for packing only if the struct has more * than one attribute. Then operator will receive a tuple with the same of * each attribute's type in the same order they were declared. * * Remarks: due to the MCS compiler's limitations, no operator is generated * for structs with more than 4 fields. */ template bool generate_implicit_operator(attributes::struct_def const& struct_ , OutputIterator sink , Context const& context) const { if (struct_.fields.size() <= 1 || struct_.fields.size() > 4) return true; auto struct_name = binding_struct_name(struct_); auto const& indent = current_indentation(context).inc(); if (!as_generator( indent << scope_tab << "/// Packs tuple into " << struct_name << " object.\n" << indent << scope_tab << "///Since EFL 1.24.\n" << indent << scope_tab << "///\n" ).generate(sink, attributes::unused, context)) return false; if (!as_generator( indent << scope_tab << "public static implicit operator " << struct_name << "(\n" << indent << scope_tab << scope_tab << "(\n" << ((indent << scope_tab << scope_tab << " " << field_argument_decl) % ",\n") << "\n" << indent << scope_tab << scope_tab << ") tuple)\n" << indent << scope_tab << "{\n" ).generate(sink, struct_.fields, context)) return false; // object constructor if (!as_generator( indent << scope_tab << scope_tab << "return new " << struct_name << "{\n" ).generate(sink, attributes::unused, context)) return false; for (const auto& field: struct_.fields) { auto field_name = name_helpers::to_field_name(field.name); if (!as_generator( indent << scope_tab << scope_tab << scope_tab << field_name << " = tuple." << field_name << ",\n" ).generate(sink, attributes::unused, context)) return false; } if (!as_generator( indent << scope_tab << scope_tab << "};\n" << indent << scope_tab << "}\n" ).generate(sink, attributes::unused, context)) return false; return true; } template bool generate_deconstruct_method(OutputIterator sink, attributes::struct_def const& struct_, Context const& context) const { auto const& indent = current_indentation(context).inc(); auto struct_name = binding_struct_name(struct_); if (!as_generator( indent << scope_tab << "/// Unpacks " << struct_name << " into tuple.\n" << indent << scope_tab << "/// Since EFL 1.24.\n" << indent << scope_tab << "/// \n" << indent << scope_tab << "public void Deconstruct(\n" ).generate(sink, attributes::unused, context)) return false; // parameters { auto i = 0u; for (auto const& field : struct_.fields) { auto field_name = name_helpers::to_field_name(field.name); auto suffix = i == struct_.fields.size() - 1 ? "\n" : ",\n"; if (!as_generator( indent << scope_tab << scope_tab << "out " << type << " " << field_name << suffix ).generate(sink, std::make_tuple(field.type), context)) return false; ++i; } } if (!as_generator( indent << scope_tab << ")\n" << indent << scope_tab << "{\n" ).generate(sink, attributes::unused, context)) return false; // assigments for (auto const& field : struct_.fields) { auto field_name = name_helpers::to_field_name(field.name); if (!as_generator( indent << scope_tab << scope_tab << field_name << " = this." << field_name << ";\n" ).generate(sink, attributes::unused, context)) return false; } // the end return as_generator( indent << scope_tab << "}\n" ).generate(sink, attributes::unused, context); } template bool generate(OutputIterator sink, attributes::struct_def const& struct_, Context const& context) const { EINA_CXX_DOM_LOG_DBG(eolian_mono::domain) << "struct_definition_generator: " << struct_.cxx_name << std::endl; auto const& indent = current_indentation(context).inc(); if(!as_generator(documentation(1)).generate(sink, struct_, context)) return false; auto struct_managed_name = binding_struct_name(struct_); if(!as_generator ( indent << "[StructLayout(LayoutKind.Sequential)]\n" << indent << "[Efl.Eo.BindingEntity]\n" << indent << "[SuppressMessage(\"Microsoft.Naming\", \"CA1724:TypeNamesShouldNotMatchNamespaces\")]\n" << indent << "public struct " << struct_managed_name << " : IEquatable<" << struct_managed_name << ">\n" << indent << "{\n" ) .generate(sink, attributes::unused, context)) return false; // iterate struct fields for (auto const& field : struct_.fields) { if (!as_generator(documentation(indent.n + 1)).generate(sink, field, context)) return false; if (!field.type.doc_summary.empty()) { if (!as_generator(indent << scope_tab << "/// " << field.type.doc_summary << "\n").generate(sink, attributes::unused, context)) return false; } if (!as_generator(indent << scope_tab << "public " << type << " " << name_helpers::to_field_name(field.name) << ";\n").generate(sink, field.type, context)) return false; } auto struct_name = binding_struct_name(struct_); // Check whether this is an extern struct without declared fields in .eo file and generate a // placeholder field if positive. // Mono's JIT is picky when generating function pointer for delegates with empty structs, leading to // those 'mini-amd64.c condition fields not met' crashes. if (struct_.fields.size() == 0) { if (!as_generator(indent << scope_tab << "/// Placeholder field\n" << indent << scope_tab << "public IntPtr field;\n").generate(sink, nullptr, context)) return false; } else { // Constructor with default parameters for easy struct initialization if(!as_generator( indent << scope_tab << "/// Constructor for " << string << ".\n" ).generate(sink, struct_name, context)) return false; if (!struct_.documentation.since.empty()) if (!as_generator(indent << scope_tab << "/// Since EFL " + struct_.documentation.since + ".\n" ).generate(sink, attributes::unused, context)) return false; if (!as_generator( indent << scope_tab << "/// \n" << *(indent << scope_tab << field_argument_docs << "\n") << indent << scope_tab << "public " << string << "(\n" << ((indent << scope_tab << scope_tab << field_argument_default) % ",\n") << indent << scope_tab << ")\n" << indent << scope_tab << "{\n" << *(indent << scope_tab << scope_tab << field_argument_assignment << ";\n") << indent << scope_tab << "}\n\n") .generate(sink, std::make_tuple(struct_.fields, struct_name, struct_.fields, struct_.fields), context)) return false; if (!generate_implicit_operator(struct_, sink, context)) return false; if (!generate_deconstruct_method(sink, struct_, context)) return false; } std::string since_line; if (!struct_.documentation.since.empty()) if (!as_generator(indent << scope_tab << "/// Since EFL " + struct_.documentation.since + ".\n" ).generate(std::back_inserter(since_line), attributes::unused, context)) return false; // GetHashCode (needed by the equality comparisons) if (!as_generator( indent << scope_tab << "/// Get a hash code for this item.\n" << since_line << indent << scope_tab << "/// \n" << indent << scope_tab << "public override int GetHashCode()\n" << indent << scope_tab << "{\n" ).generate(sink, attributes::unused, context)) return false; if (struct_.fields.size() != 0 ) { // int hash = 17; // hash = 23 * fieldA.GetHashCode(); // hash = 23 * fieldB.GetHashCode(); // hash = 23 * fieldC.GetHashCode(); // return hash if (!as_generator( indent << scope_tab << scope_tab << "int hash = 17;\n" << *(grammar::attribute_reorder<-1, -1>(indent << scope_tab << scope_tab << "hash = hash * 23 + " << name_helpers::struct_field_name << ".GetHashCode(" << culture_info << ");\n")) << indent << scope_tab << scope_tab << "return hash;\n" ).generate(sink, struct_.fields, context)) return false; } else { // Just compare the place holder pointers if (!as_generator( "return field.GetHashCode();\n" ).generate(sink, attributes::unused, context)) return false; } if (!as_generator( indent << scope_tab << "}\n" ).generate(sink, attributes::unused, context)) return false; // IEquatable Equals if (!as_generator( indent << scope_tab << "/// Equality comparison.\n" << since_line << indent << scope_tab << "/// \n" << indent << scope_tab << "public bool Equals(" << struct_managed_name << " other)\n" << indent << scope_tab << "{\n" << indent << scope_tab << scope_tab << "return " ).generate(sink, attributes::unused, context)) return false; if (struct_.fields.size() != 0 ) { if (!as_generator( grammar::attribute_reorder<-1, -1>((name_helpers::struct_field_name << " == other." << name_helpers::struct_field_name)) % " && " ).generate(sink, struct_.fields, context)) return false; } else { // Just compare the place holder pointers if (!as_generator( "field.Equals(other.field)" ).generate(sink, attributes::unused, context)) return false; } if (!as_generator( indent << scope_tab << scope_tab << ";\n" << indent << scope_tab << "}\n" ).generate(sink, attributes::unused, context)) return false; // ValueType.Equals if (!as_generator( indent << scope_tab << "/// Equality comparison.\n" << since_line << indent << scope_tab << "/// \n" << indent << scope_tab << "public override bool Equals(object other)\n" << indent << scope_tab << scope_tab << "=> ((other is " << struct_managed_name << ") ? Equals((" << struct_managed_name << ")other) : false);\n" ).generate(sink, attributes::unused, context)) return false; // Equality operators if (!as_generator( indent << scope_tab << "/// Equality comparison.\n" << since_line << indent << scope_tab << "/// \n" << indent << scope_tab << "public static bool operator ==(" << struct_managed_name << " lhs, " << struct_managed_name << " rhs)\n" << indent << scope_tab << scope_tab << "=> lhs.Equals(rhs);" ).generate(sink, attributes::unused, context)) return false; if (!as_generator( indent << scope_tab << "/// Equality comparison.\n" << since_line << indent << scope_tab << "/// \n" << indent << scope_tab << "public static bool operator !=(" << struct_managed_name << " lhs, " << struct_managed_name << " rhs)\n" << indent << scope_tab << scope_tab << "=> !lhs.Equals(rhs);" ).generate(sink, attributes::unused, context)) return false; // Conversions from/to internal struct and IntPtrs if(!as_generator( indent << scope_tab << "/// Implicit conversion to the managed representation from a native pointer.\n" ).generate(sink, attributes::unused, context)) return false; if (!struct_.documentation.since.empty()) if (!as_generator(indent << scope_tab << "/// Since EFL " + struct_.documentation.since + ".\n" ).generate(sink, attributes::unused, context)) return false; if (!as_generator( indent << scope_tab << "/// \n" << indent << scope_tab << "/// Native pointer to be converted.\n" << indent << scope_tab << "public static implicit operator " << struct_name << "(IntPtr ptr)\n" << indent << scope_tab << "{\n" << indent << scope_tab << scope_tab << "var tmp = (" << struct_name << ".NativeStruct)Marshal.PtrToStructure(ptr, typeof(" << struct_name << ".NativeStruct));\n" << indent << scope_tab << scope_tab << "return tmp;\n" << indent << scope_tab << "}\n\n" ).generate(sink, attributes::unused, context)) return false; if(!as_generator( indent << scope_tab << "/// Conversion to the managed representation from a native pointer.\n" ).generate(sink, attributes::unused, context)) return false; if (!struct_.documentation.since.empty()) if (!as_generator(indent << scope_tab << "/// Since EFL " + struct_.documentation.since + ".\n" ).generate(sink, attributes::unused, context)) return false; if (!as_generator( indent << scope_tab << "/// \n" << indent << scope_tab << "/// Native pointer to be converted.\n" << indent << scope_tab << "public static " << struct_name << " FromIntPtr(IntPtr ptr)\n" << indent << scope_tab << "{\n" << indent << scope_tab << scope_tab << "return ptr;\n" << indent << scope_tab << "}\n\n" ).generate(sink, attributes::unused, context)) return false; if (!struct_internal_definition.generate(sink, struct_, change_indentation(indent.inc(), context))) return false; if(!as_generator(indent << "}\n\n").generate(sink, attributes::unused, context)) return false; return true; } } const struct_definition {}; struct struct_entities_generator { template bool generate(OutputIterator sink, attributes::struct_def const& struct_, Context const& context) const { if (blacklist::is_struct_blacklisted(struct_, context)) return true; if (!name_helpers::open_namespaces(sink, struct_.namespaces, context)) return false; if (!struct_definition.generate(sink, struct_, context)) return false; return name_helpers::close_namespaces(sink, struct_.namespaces, context); } } const struct_entities {}; } namespace efl { namespace eolian { namespace grammar { template <> struct is_eager_generator< ::eolian_mono::struct_definition_generator> : std::true_type {}; template <> struct is_generator< ::eolian_mono::struct_definition_generator> : std::true_type {}; template <> struct is_eager_generator< ::eolian_mono::struct_internal_definition_generator> : std::true_type {}; template <> struct is_generator< ::eolian_mono::struct_internal_definition_generator> : std::true_type {}; template <> struct is_eager_generator< ::eolian_mono::to_internal_field_convert_generator> : std::true_type {}; template <> struct is_generator< ::eolian_mono::to_internal_field_convert_generator> : std::true_type {}; template <> struct is_eager_generator< ::eolian_mono::to_external_field_convert_generator> : std::true_type {}; template <> struct is_generator< ::eolian_mono::to_external_field_convert_generator> : std::true_type {}; template <> struct is_eager_generator< ::eolian_mono::struct_entities_generator> : std::true_type {}; template <> struct is_generator< ::eolian_mono::struct_entities_generator> : std::true_type {}; namespace type_traits { template <> struct attributes_needed< ::eolian_mono::struct_definition_generator> : std::integral_constant {}; template <> struct attributes_needed< ::eolian_mono::struct_internal_definition_generator> : std::integral_constant {}; template <> struct attributes_needed< ::eolian_mono::to_internal_field_convert_generator> : std::integral_constant {}; template <> struct attributes_needed< ::eolian_mono::to_external_field_convert_generator> : std::integral_constant {}; template <> struct attributes_needed< ::eolian_mono::struct_entities_generator> : std::integral_constant {}; } } } } #endif diff --git a/src/bin/eolian_mono/eolian/mono/type_impl.hh b/src/bin/eolian_mono/eolian/mono/type_impl.hh index f365a0d5a8..4475844e2d 100644 --- a/src/bin/eolian_mono/eolian/mono/type_impl.hh +++ b/src/bin/eolian_mono/eolian/mono/type_impl.hh @@ -1,460 +1,460 @@ /* * Copyright 2019 by its authors. See AUTHORS. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef EOLIAN_MONO_TYPE_IMPL_HH #define EOLIAN_MONO_TYPE_IMPL_HH #include "grammar/generator.hpp" #include "grammar/klass_def.hpp" #include "grammar/case.hpp" #include "name_helpers.hh" #include "type_match.hh" namespace eolian_mono { namespace eina = efl::eina; template T const* as_const_pointer(T* p) { return p; } inline attributes::regular_type_def replace_base_type(attributes::regular_type_def v, std::string name) { v.base_type = name; return v; } template attributes::regular_type_def replace_base_integer(attributes::regular_type_def v) { bool s = std::is_signed::value; switch (sizeof(T)) { case 1: return s ? replace_base_type(v, "sbyte") : replace_base_type(v, "byte"); case 2: return s ? replace_base_type(v, "short") : replace_base_type(v, "ushort"); case 4: return s ? replace_base_type(v, "int") : replace_base_type(v, "uint"); case 8: return s ? replace_base_type(v, "long") : replace_base_type(v, "ulong"); default: return v; } } template attributes::regular_type_def replace_base_opt_integer(attributes::regular_type_def v) { bool s = std::is_signed::value; switch (sizeof(T)) { case 1: return s ? replace_base_type(v, "sbyte?") : replace_base_type(v, "byte?"); case 2: return s ? replace_base_type(v, "short?") : replace_base_type(v, "ushort?"); case 4: return s ? replace_base_type(v, "int?") : replace_base_type(v, "uint?"); case 8: return s ? replace_base_type(v, "long?") : replace_base_type(v, "ulong?"); default: return v; } } inline attributes::complex_type_def replace_outer(attributes::complex_type_def v, attributes::regular_type_def const& regular) { v.outer = regular; return v; } template struct visitor_regular_type_def_printer { typedef visitor_regular_type_def_printer visitor_type; typedef bool result_type; mutable OutputIterator sink; Context const* context; bool operator()(grammar::attributes::regular_type_def const ®ular) const { return as_generator(string).generate(sink, name_helpers::type_full_managed_name(regular), *context); } template bool operator()(T const&) const { return true; } }; template struct visitor_generate { mutable OutputIterator sink; Context const* context; std::string c_type; bool is_out; bool is_return; bool is_ptr; mutable bool is_optional; bool is_special_subtype; typedef visitor_generate visitor_type; typedef bool result_type; bool operator()(attributes::regular_type_def const& regular) const { using attributes::regular_type_def; struct match { eina::optional name; eina::optional has_own; std::function function; } const optional_match_table[] = { // signed primitives {"byte", nullptr, [&] { return replace_base_type(regular, "sbyte?"); }} , {"float", nullptr, [&] { return replace_base_type(regular, "float?"); }} , {"double", nullptr, [&] { return replace_base_type(regular, "double?"); }} , {"bool", nullptr, [&] { return replace_base_type(regular, "bool?"); }} , {"short", nullptr, [&] { return replace_base_opt_integer(regular); }} , {"int", nullptr, [&] { return replace_base_opt_integer(regular); }} , {"long", nullptr, [&] { return replace_base_opt_integer(regular); }} , {"llong", nullptr, [&] { return replace_base_opt_integer(regular); }} , {"int8", nullptr, [&] { return replace_base_type(regular, "sbyte?"); }} , {"int16", nullptr, [&] { return replace_base_type(regular, "short?"); }} , {"int32", nullptr, [&] { return replace_base_type(regular, "int?"); }} , {"int64", nullptr, [&] { return replace_base_type(regular, "long?"); }} , {"ssize", nullptr, [&] { return replace_base_opt_integer(regular); }} // unsigned primitives , {"ubyte", nullptr, [&] { return replace_base_type(regular, "byte?"); }} , {"ushort", nullptr, [&] { return replace_base_opt_integer(regular); }} , {"uint", nullptr, [&] { return replace_base_opt_integer(regular); }} , {"ulong", nullptr, [&] { return replace_base_opt_integer(regular); }} , {"ullong", nullptr, [&] { return replace_base_opt_integer(regular); }} , {"uint8", nullptr, [&] { return replace_base_type(regular, "byte?"); }} , {"uint16", nullptr, [&] { return replace_base_type(regular, "ushort?"); }} , {"uint32", nullptr, [&] { return replace_base_type(regular, "uint?"); }} , {"uint64", nullptr, [&] { return replace_base_type(regular, "ulong?"); }} , {"size", nullptr, [&] { return replace_base_opt_integer(regular); }} , {"ptrdiff", nullptr, [&] { return replace_base_opt_integer(regular); }} , {"intptr", nullptr, [&] { return replace_base_type(regular, "System.IntPtr?"); }} , {"uintptr", nullptr, [&] { return replace_base_type(regular, "System.IntPtr?"); }} , {"void_ptr", nullptr, [&] { return replace_base_type(regular, "System.IntPtr?"); }} }; struct match const match_table[] = { // signed primitives {"byte", nullptr, [&] { return replace_base_type(regular, "sbyte"); }} , {"short", nullptr, [&] { return replace_base_integer(regular); }} , {"int", nullptr, [&] { return replace_base_integer(regular); }} , {"long", nullptr, [&] { return replace_base_integer(regular); }} , {"llong", nullptr, [&] { return replace_base_integer(regular); }} , {"int8", nullptr, [&] { return replace_base_type(regular, "sbyte"); }} , {"int16", nullptr, [&] { return replace_base_type(regular, "short"); }} , {"int32", nullptr, [&] { return replace_base_type(regular, "int"); }} , {"int64", nullptr, [&] { return replace_base_type(regular, "long"); }} , {"ssize", nullptr, [&] { return replace_base_integer(regular); }} // unsigned primitives , {"ubyte", nullptr, [&] { return replace_base_type(regular, "byte"); }} , {"ushort", nullptr, [&] { return replace_base_integer(regular); }} , {"uint", nullptr, [&] { return replace_base_integer(regular); }} , {"ulong", nullptr, [&] { return replace_base_integer(regular); }} , {"ullong", nullptr, [&] { return replace_base_integer(regular); }} , {"uint8", nullptr, [&] { return replace_base_type(regular, "byte"); }} , {"uint16", nullptr, [&] { return replace_base_type(regular, "ushort"); }} , {"uint32", nullptr, [&] { return replace_base_type(regular, "uint"); }} , {"uint64", nullptr, [&] { return replace_base_type(regular, "ulong"); }} , {"size", nullptr, [&] { return replace_base_integer(regular); }} , {"ptrdiff", nullptr, [&] { return replace_base_integer(regular); }} , {"intptr", nullptr, [&] { return replace_base_type(regular, "System.IntPtr"); }} , {"uintptr", nullptr, [&] { return replace_base_type(regular, "System.IntPtr"); }} , {"void_ptr", nullptr, [&] { return replace_base_type(regular, "System.IntPtr"); }} , {"void", nullptr, [&] { regular_type_def r = regular; r.namespaces.clear(); if (is_out) // @inout too r.base_type = "System.IntPtr"; else r.base_type = "void"; return r; }} , {"Eina.Error", nullptr, [&] // Eina.Error { return regular_type_def{"Eina.Error", regular.base_qualifier, {}}; }} // TODO , {"string", nullptr, [&] { regular_type_def r = regular; r.base_qualifier.qualifier ^= qualifier_info::is_ref; return replace_base_type(r, "System.String"); }} , {"mstring", nullptr, [&] { regular_type_def r = regular; r.base_qualifier.qualifier ^= qualifier_info::is_ref; return replace_base_type(r, "System.String"); }} , {"stringshare", nullptr, [&] { regular_type_def r = regular; r.base_qualifier.qualifier ^= qualifier_info::is_ref; if (is_special_subtype) return replace_base_type(r, "Eina.Stringshare"); return replace_base_type(r, "System.String"); }} , {"strbuf", nullptr, [&] { return regular_type_def{"Eina.Strbuf", regular.base_qualifier, {}}; }} , {"binbuf", nullptr, [&] { return regular_type_def{"Eina.Binbuf", regular.base_qualifier, {}}; }} , {"event", nullptr, [&] { return regular_type_def{"Efl.Event", regular.base_qualifier, {}}; }} , {"any_value", true, [&] { return regular_type_def{"Eina.Value", regular.base_qualifier, {}}; }} , {"any_value", false, [&] { return regular_type_def{"Eina.Value", regular.base_qualifier, {}}; }} , {"any_value_ref", nullptr, [&] { return regular_type_def{"Eina.Value", regular.base_qualifier, {}}; }} // FIXME add proper support for any_value_ref }; std::string full_type_name = name_helpers::type_full_eolian_name(regular); if(eina::optional b = type_match::get_match (optional_match_table , [&] (match const& m) { return is_optional && (!m.name || *m.name == regular.base_type || *m.name == full_type_name) && (!m.has_own || *m.has_own == (bool)(regular.base_qualifier & qualifier_info::is_own)) ; } , [&] (attributes::type_def::variant_type const& v) { return v.visit(*this); // we want to keep is_out info })) { return *b; } else if (is_optional && (regular.is_struct() || regular.is_enum() || regular.is_struct_opaque())) { attributes::regular_type_def r = regular; r.base_type.push_back('?'); is_optional = false; return (*this)(r); } else if(eina::optional b = type_match::get_match (match_table , [&] (match const& m) { return (!m.name || *m.name == regular.base_type || *m.name == full_type_name) && (!m.has_own || *m.has_own == (bool)(regular.base_qualifier & qualifier_info::is_own)) ; } , [&] (attributes::type_def::variant_type const& v) { return v.visit(visitor_regular_type_def_printer{sink, context}); // we want to keep is_out info })) { return *b; } // in A @optional -> optional // in A& @optional -> optional // in A& @optional -> optional // in own(A&) @optional -> A* // // out A @optional -> optional // out A& @optional -> optional // out own(A&) @optional -> optional // else if(regular.base_qualifier & qualifier_info::is_optional) // { // attributes::regular_type_def no_optional_regular = regular; // no_optional_regular.base_qualifier.qualifier ^= qualifier_info::is_optional; // if(is_out) // { // if(no_optional_regular.base_qualifier & qualifier_info::is_own) // { // return as_generator(" ::efl::eina::optional<").generate(sink, attributes::unused, *context) // && (*this)(no_optional_regular) // && as_generator("&>").generate(sink, attributes::unused, *context); // } // else if(no_optional_regular.base_qualifier & qualifier_info::is_ref) // { // no_optional_regular.base_qualifier.qualifier ^= qualifier_info::is_ref; // return (*this)(no_optional_regular) // && as_generator("**").generate(sink, attributes::unused, *context); // } // else // return (*this)(no_optional_regular) // && as_generator("*").generate(sink, attributes::unused, *context); // } // else // { // // regular.base_qualifier & qualifier_info::is_ref // return as_generator(" ::efl::eina::optional<").generate(sink, attributes::unused, *context) // && (*this)(no_optional_regular) // && as_generator(">").generate(sink, attributes::unused, *context); // } // } // else if((is_return || is_out) && regular.base_qualifier & qualifier_info::is_ref // && regular.base_qualifier & qualifier_info::is_own) // { // if(as_generator // ( // " ::std::unique_ptr<" // << *(string << "_") // << string // << (regular.base_qualifier & qualifier_info::is_const ? " const" : "") // << ", ::efl::eina::malloc_deleter>" // ) // .generate(sink, std::make_tuple(regular.namespaces, regular.base_type), *context)) // return true; // else // return false; // } // else if(Eolian_Typedecl const* typedecl = eolian_state_struct_by_name_get(c_type.c_str())) // { // return as_generator // ( // *(string << ".") // << string // ) // .generate(sink, std::make_tuple(regular.namespaces, regular.base_type), *context); // } else { return as_generator(string).generate(sink, name_helpers::type_full_managed_name(regular), *context); } } bool operator()(attributes::klass_name klass) const { // Efl.Class is manually handled in a custom marshall to be represented by a System.Type. if (name_helpers::klass_full_concrete_name(klass) == "Efl.Class") return as_generator(lit("Type")).generate(sink, attributes::unused, *context); if(klass.type == attributes::class_type::regular || klass.type == attributes::class_type::abstract_) return as_generator(string).generate(sink, name_helpers::klass_full_concrete_name(klass), *context); else return as_generator(string).generate(sink, name_helpers::klass_full_interface_name(klass), *context); } bool operator()(attributes::complex_type_def const& complex) const { using attributes::regular_type_def; using attributes::complex_type_def; using attributes::qualifier_info; struct match { eina::optional name; eina::optional has_own; eina::optional is_const; std::function function; } const matches[] = { {"list", nullptr, nullptr, [&] { complex_type_def c = complex; - c.outer.base_type = "Eina.List"; + c.outer.base_type = "IList"; return c; }} , {"array", nullptr, nullptr, [&] { complex_type_def c = complex; - c.outer.base_type = "Eina.Array"; + c.outer.base_type = "IList"; return c; }} , {"hash", nullptr, nullptr , [&] { complex_type_def c = complex; c.outer.base_type = "Eina.Hash"; return c; }} , {"future", nullptr, nullptr, [&] { (*this)(regular_type_def{" Eina.Future", complex.outer.base_qualifier, {}}); return attributes::type_def::variant_type(); } } , {"iterator", nullptr, nullptr, [&] { complex_type_def c = complex; c.outer.base_type = "IEnumerable"; return c; } } , {"accessor", nullptr, nullptr, [&] { complex_type_def c = complex; c.outer.base_type = "IEnumerable"; return c; } } , {"slice", nullptr, nullptr, [&] { return regular_type_def{" Eina.Slice", complex.outer.base_qualifier, {}}; } } , {"rw_slice", nullptr, nullptr, [&] { return regular_type_def{" Eina.RwSlice", complex.outer.base_qualifier, {}}; } } }; auto default_match = [&] (attributes::complex_type_def const& complex) { regular_type_def no_pointer_regular = complex.outer; // std::vector pointers; // pointers.swap(no_pointer_regular.pointers); // if(is_out) // pointers.push_back({{attributes::qualifier_info::is_none, {}}, true}); return visitor_type{sink, context, c_type, false, false, false, false, false}(no_pointer_regular) && as_generator("<" << (type(false, false, true) % ", ") << ">").generate(sink, complex.subtypes, *context) ; // && detail::generate_pointers(sink, pointers, *context, false); }; if(eina::optional b = type_match::get_match (matches , [&] (match const& m) { return (!m.name || *m.name == complex.outer.base_type) && (!m.has_own || *m.has_own == bool(complex.outer.base_qualifier & qualifier_info::is_own)) && (!m.is_const || *m.is_const == bool(complex.outer.base_qualifier & qualifier_info::is_const)); } , [&] (attributes::type_def::variant_type const& v) { if(v.empty()) return true; else if(attributes::complex_type_def const* complex = eina::get(&v)) return default_match(*complex); else return v.visit(*this); })) return *b; else { return default_match(complex); } } }; } #endif diff --git a/src/bindings/mono/efl_mono/efl_csharp_application.cs b/src/bindings/mono/efl_mono/efl_csharp_application.cs index 8493abd6ab..9c2f7f0f06 100644 --- a/src/bindings/mono/efl_mono/efl_csharp_application.cs +++ b/src/bindings/mono/efl_mono/efl_csharp_application.cs @@ -1,242 +1,241 @@ /* * Copyright 2019 by its authors. See AUTHORS. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; using System.Runtime.InteropServices; using System.Threading; using System.Diagnostics.CodeAnalysis; using System.Collections.Generic; using static Efl.UnsafeNativeMethods; namespace Efl.Csharp { /// The components to be initialized. /// Since EFL 1.23. /// [Flags] public enum Components : Int32 { // Base flags. /// /// Initialize nothing. /// Since EFL 1.24. /// None = 0x0, ///Basic components: Eina, Eo, Ecore, Evas and DBus. /// Since EFL 1.24. /// Basic = 0x1, /// /// Elementary Widget toolkit: Elm. /// it's depend of . /// Since EFL 1.24. /// Ui = Basic | 0x2, // Combined flags. /// /// Enable all components, equals to . /// Since EFL 1.24. /// All = int.MaxValue, } /// /// This represents the entry point for the EFL framework /// You can use this class to implement the 4 abstract methods which will then be called accordingly /// All subsystems of efl are booted up correctly when the abstract methods of this class are called. /// Since EFL 1.23. /// /// /// Calls to efl outside those efl-callbacks or outside the mainloop are not allowed and will lead to issues /// /// /// /// UserApp is the class that implements the Application abstract /// /// public static void Main() /// { /// UserApp editor = new UserApp(); /// editor.Launch(editor); /// } /// /// public abstract class Application { //the initializied components private static Components initComponents = Components.All; //what follows are 3 private functions to boot up the internals of efl private static void Init(Efl.Csharp.Components components = Components.All) { if (components == Components.None) { return; } initComponents = components; if ((initComponents & Components.Basic) == Components.Basic) { Eina.Config.Init(); Efl.Eo.Config.Init(); ecore_init(); ecore_init_ex(0, IntPtr.Zero); evas_init(); eldbus.Config.Init(); } if ((initComponents & Components.Ui) == Components.Ui) { #if WIN32 // TODO Support elm command line arguments // Not a native define, we define it in our build system // Ecore_Win32 uses OleInitialize, which requires single thread apartments if (System.Threading.Thread.CurrentThread.GetApartmentState() != ApartmentState.STA) { throw new InvalidOperationException("UI Applications require STAThreadAttribute in Main()"); } #endif elm_init(0, IntPtr.Zero); Efl.Ui.Win.ExitOnAllWindowsClosed = new Eina.Value(0); } } private static void Shutdown() { // Try to cleanup everything before actually shutting down. System.GC.Collect(); System.GC.WaitForPendingFinalizers(); if (initComponents == Components.None) { return; } if ((initComponents & Components.Ui) == Components.Ui) { elm_shutdown(); } if ((initComponents & Components.Basic) == Components.Basic) { eldbus.Config.Shutdown(); evas_shutdown(); ecore_shutdown(); Efl.Eo.Config.Shutdown(); Eina.Config.Shutdown(); } } /// /// Called when the application is started. Arguments from the command line are passed here. /// Since EFL 1.23. /// /// Arguments passed from command line. protected abstract void OnInitialize(string[] args); /// /// Arguments are passed here, Additional calls to this function may occure, /// but then the initialization flag is set to false. /// Since EFL 1.23. /// /// /// When Initialize is true then OnInitialize is also called /// /// Argsuments passed from command line protected virtual void OnArguments(Efl.LoopArguments args) { } /// /// Called when the application is not going to be displayed, or is not used by a user for some time. /// Since EFL 1.23. /// protected virtual void OnPause() { } /// /// Called before an application is used again after a call to OnPause(). /// Since EFL 1.23. /// protected virtual void OnResume() { } /// /// Called before starting the shutdown of the application. /// Since EFL 1.23. /// protected virtual void OnTerminate() { } /// /// This function initializices everything in EFL and runs your application. /// This call will result in a call to OnInitialize(), which you application should override. /// Since EFL 1.23. /// /// The to run the application. public void Launch(Efl.Csharp.Components components = Components.All) { Init(components); Efl.App app = Efl.App.AppMain; - var command_line = new Eina.Array(); + var command_line = new List(); //command_line.Add(List.ConvertAll(Environment.GetCommandLineArgs(), s => (Eina.Stringshare)s)); //command_line.AddRange(Environment.GetCommandLineArgs()); #if EFL_BETA app.SetCommandArray(command_line); #endif app.ArgumentsEvent += (object sender, LoopArgumentsEventArgs evt) => { if (evt.arg.Initialization) { var evtArgv = evt.arg.Argv; int n = evtArgv.Count; var argv = new string[n]; for (int i = 0; i < n; ++i) { argv[i] = evtArgv[i]; } OnInitialize(argv); } OnArguments(evt.arg); }; app.PauseEvent += (object sender, EventArgs e) => { OnPause(); }; app.ResumeEvent += (object sender, EventArgs e) => { OnResume(); }; app.TerminateEvent += (object sender, EventArgs e) => { OnTerminate(); }; app.Begin(); - command_line.Dispose(); Shutdown(); } } } diff --git a/src/bindings/mono/eo_mono/iwrapper.cs b/src/bindings/mono/eo_mono/iwrapper.cs index 2a8ebf0620..780735fcca 100644 --- a/src/bindings/mono/eo_mono/iwrapper.cs +++ b/src/bindings/mono/eo_mono/iwrapper.cs @@ -1,1741 +1,1815 @@ /* * Copyright 2019 by its authors. See AUTHORS. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma warning disable 1591 using System; using System.Runtime.InteropServices; using System.Runtime.CompilerServices; using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Reflection; using System.Threading; using System.Linq; using static Eina.NativeCustomExportFunctions; using EoG = Efl.Eo.Globals; namespace Efl { namespace Eo { internal static class Globals { /// Represents the type of the native Efl_Class. internal enum EflClassType { /// Regular EFL classes. Regular = 0, /// Non-instantiable efl classes (i.e. Abstracts). RegularNoInstant, /// Interface types. Interface, /// Mixins types. Mixin, /// Invalid class type. Invalid } [return: MarshalAs(UnmanagedType.U1)] internal delegate bool efl_object_init_delegate(); static readonly FunctionWrapper efl_object_init_ptr = new FunctionWrapper(efl.Libs.EoModule, "efl_object_init"); internal static bool efl_object_init() => efl_object_init_ptr.Value.Delegate(); internal delegate void efl_object_shutdown_delegate(); static readonly FunctionWrapper efl_object_shutdown_ptr = new FunctionWrapper(efl.Libs.EoModule, "efl_object_shutdown"); internal static void efl_object_shutdown() => efl_object_shutdown_ptr.Value.Delegate(); // [DllImport(efl.Libs.Eo)] internal static extern void efl_object_shutdown(); [DllImport(efl.Libs.CustomExports)] internal static extern IntPtr efl_mono_wrapper_supervisor_get(IntPtr eo); [DllImport(efl.Libs.CustomExports)] internal static extern void efl_mono_wrapper_supervisor_set(IntPtr eo, IntPtr ws); [DllImport(efl.Libs.Eo)] internal static extern IntPtr _efl_add_internal_start([MarshalAs(UnmanagedType.LPStr)] String file, int line, IntPtr klass, IntPtr parent, byte is_ref, byte is_fallback); [DllImport(efl.Libs.Eo)] internal static extern IntPtr _efl_add_internal_start_bindings([MarshalAs(UnmanagedType.LPStr)] String file, int line, IntPtr klass, IntPtr parent, byte is_ref, byte is_fallback, IntPtr substitute_ctor, IntPtr data); internal delegate IntPtr _efl_add_end_delegate(IntPtr eo, byte is_ref, byte is_fallback); [DllImport(efl.Libs.Eo)] internal static extern IntPtr _efl_add_end(IntPtr eo, byte is_ref, byte is_fallback); internal delegate IntPtr efl_ref_delegate(IntPtr eo); [DllImport(efl.Libs.Eo)] internal static extern IntPtr efl_ref(IntPtr eo); internal delegate void efl_unref_delegate(IntPtr eo); [DllImport(efl.Libs.CustomExports)] internal static extern void efl_unref(IntPtr eo); internal delegate int efl_ref_count_delegate(IntPtr eo); [DllImport(efl.Libs.Eo)] internal static extern int efl_ref_count(IntPtr eo); [DllImport(efl.Libs.CustomExports)] internal static extern void efl_mono_wrapper_supervisor_callbacks_set(Efl.FreeWrapperSupervisorCb freeWrapperSupervisorCb); [DllImport(efl.Libs.CustomExports)] internal static extern void efl_mono_native_dispose(IntPtr eo); [DllImport(efl.Libs.CustomExports)] internal static extern void efl_mono_thread_safe_native_dispose(IntPtr eo); [DllImport(efl.Libs.CustomExports)] internal static extern void efl_mono_thread_safe_efl_unref(IntPtr eo); [DllImport(efl.Libs.CustomExports)] internal static extern void efl_mono_thread_safe_free_cb_exec(IntPtr free_cb, IntPtr cb_data); [DllImport(efl.Libs.Eo)] internal static extern IntPtr efl_class_name_get(IntPtr eo); [DllImport(efl.Libs.Eo)] internal static extern IntPtr efl_class_new(IntPtr class_description, IntPtr parent, IntPtr term); [DllImport(efl.Libs.Eo)] internal static extern IntPtr efl_class_new(IntPtr class_description, IntPtr parent, IntPtr extn1, IntPtr term); [DllImport(efl.Libs.Eo)] internal static extern IntPtr efl_class_new(IntPtr class_description, IntPtr parent, IntPtr extn1, IntPtr extn2, IntPtr term); [DllImport(efl.Libs.Eo)] internal static extern IntPtr efl_class_new(IntPtr class_description, IntPtr parent, IntPtr extn1, IntPtr extn2, IntPtr extn3, IntPtr term); [DllImport(efl.Libs.Eo)] internal static extern IntPtr efl_class_new(IntPtr class_description, IntPtr parent, IntPtr extn1, IntPtr extn2, IntPtr extn3, IntPtr extn4, IntPtr term); [DllImport(efl.Libs.Eo)] internal static extern IntPtr efl_class_new(IntPtr class_description, IntPtr parent, IntPtr extn1, IntPtr extn2, IntPtr extn3, IntPtr extn4, IntPtr extn5, IntPtr term); [DllImport(efl.Libs.Eo)] internal static extern IntPtr efl_class_new(IntPtr class_description, IntPtr parent, IntPtr extn1, IntPtr extn2, IntPtr extn3, IntPtr extn4, IntPtr extn5, IntPtr extn6, IntPtr term); [DllImport(efl.Libs.Eo)] internal static extern IntPtr efl_class_new(IntPtr class_description, IntPtr parent, IntPtr extn1, IntPtr extn2, IntPtr extn3, IntPtr extn4, IntPtr extn5, IntPtr extn6, IntPtr extn7, IntPtr term); [DllImport(efl.Libs.Eo)] internal static extern IntPtr efl_class_new(IntPtr class_description, IntPtr parent, IntPtr extn1, IntPtr extn2, IntPtr extn3, IntPtr extn4, IntPtr extn5, IntPtr extn6, IntPtr extn7, IntPtr extn8, IntPtr term); [DllImport(efl.Libs.Eo)] internal static extern IntPtr efl_class_new(IntPtr class_description, IntPtr parent, IntPtr extn1, IntPtr extn2, IntPtr extn3, IntPtr extn4, IntPtr extn5, IntPtr extn6, IntPtr extn7, IntPtr extn8, IntPtr extn9, IntPtr term); [DllImport(efl.Libs.Eo)] internal static extern IntPtr efl_class_new(IntPtr class_description, IntPtr parent, IntPtr extn1, IntPtr extn2, IntPtr extn3, IntPtr extn4, IntPtr extn5, IntPtr extn6, IntPtr extn7, IntPtr extn8, IntPtr extn9, IntPtr extn10, IntPtr term); [DllImport(efl.Libs.Eo)] internal static extern IntPtr efl_class_new(IntPtr class_description, IntPtr parent, IntPtr extn1, IntPtr extn2, IntPtr extn3, IntPtr extn4, IntPtr extn5, IntPtr extn6, IntPtr extn7, IntPtr extn8, IntPtr extn9, IntPtr extn10, IntPtr extn11, IntPtr term); [DllImport(efl.Libs.Eo)] internal static extern IntPtr efl_class_new(IntPtr class_description, IntPtr parent, IntPtr extn1, IntPtr extn2, IntPtr extn3, IntPtr extn4, IntPtr extn5, IntPtr extn6, IntPtr extn7, IntPtr extn8, IntPtr extn9, IntPtr extn10, IntPtr extn11, IntPtr extn12, IntPtr term); [DllImport(efl.Libs.Eo)] internal static extern IntPtr efl_class_new(IntPtr class_description, IntPtr parent, IntPtr extn1, IntPtr extn2, IntPtr extn3, IntPtr extn4, IntPtr extn5, IntPtr extn6, IntPtr extn7, IntPtr extn8, IntPtr extn9, IntPtr extn10, IntPtr extn11, IntPtr extn12, IntPtr extn13, IntPtr term); [DllImport(efl.Libs.Eo)] internal static extern IntPtr efl_class_new(IntPtr class_description, IntPtr parent, IntPtr extn1, IntPtr extn2, IntPtr extn3, IntPtr extn4, IntPtr extn5, IntPtr extn6, IntPtr extn7, IntPtr extn8, IntPtr extn9, IntPtr extn10, IntPtr extn11, IntPtr extn12, IntPtr extn13, IntPtr extn14, IntPtr term); [DllImport(efl.Libs.Eo)] internal static extern IntPtr efl_class_new(IntPtr class_description, IntPtr parent, IntPtr extn1, IntPtr extn2, IntPtr extn3, IntPtr extn4, IntPtr extn5, IntPtr extn6, IntPtr extn7, IntPtr extn8, IntPtr extn9, IntPtr extn10, IntPtr extn11, IntPtr extn12, IntPtr extn13, IntPtr extn14, IntPtr extn15, IntPtr term); [DllImport(efl.Libs.Eo)] internal static extern IntPtr efl_class_new(IntPtr class_description, IntPtr parent, IntPtr extn1, IntPtr extn2, IntPtr extn3, IntPtr extn4, IntPtr extn5, IntPtr extn6, IntPtr extn7, IntPtr extn8, IntPtr extn9, IntPtr extn10, IntPtr extn11, IntPtr extn12, IntPtr extn13, IntPtr extn14, IntPtr extn15, IntPtr extn16, IntPtr term); [DllImport(efl.Libs.Eo)] internal static extern IntPtr efl_class_new(IntPtr class_description, IntPtr parent, IntPtr extn1, IntPtr extn2, IntPtr extn3, IntPtr extn4, IntPtr extn5, IntPtr extn6, IntPtr extn7, IntPtr extn8, IntPtr extn9, IntPtr extn10, IntPtr extn11, IntPtr extn12, IntPtr extn13, IntPtr extn14, IntPtr extn15, IntPtr extn16, IntPtr extn17, IntPtr term); [DllImport(efl.Libs.Eo)] internal static extern IntPtr efl_class_new(IntPtr class_description, IntPtr parent, IntPtr extn1, IntPtr extn2, IntPtr extn3, IntPtr extn4, IntPtr extn5, IntPtr extn6, IntPtr extn7, IntPtr extn8, IntPtr extn9, IntPtr extn10, IntPtr extn11, IntPtr extn12, IntPtr extn13, IntPtr extn14, IntPtr extn15, IntPtr extn16, IntPtr extn17, IntPtr extn18, IntPtr term); [DllImport(efl.Libs.Eo)] internal static extern IntPtr efl_class_new(IntPtr class_description, IntPtr parent, IntPtr extn1, IntPtr extn2, IntPtr extn3, IntPtr extn4, IntPtr extn5, IntPtr extn6, IntPtr extn7, IntPtr extn8, IntPtr extn9, IntPtr extn10, IntPtr extn11, IntPtr extn12, IntPtr extn13, IntPtr extn14, IntPtr extn15, IntPtr extn16, IntPtr extn17, IntPtr extn18, IntPtr extn19, IntPtr term); [DllImport(efl.Libs.Eo)] internal static extern IntPtr efl_class_new(IntPtr class_description, IntPtr parent, IntPtr extn1, IntPtr extn2, IntPtr extn3, IntPtr extn4, IntPtr extn5, IntPtr extn6, IntPtr extn7, IntPtr extn8, IntPtr extn9, IntPtr extn10, IntPtr extn11, IntPtr extn12, IntPtr extn13, IntPtr extn14, IntPtr extn15, IntPtr extn16, IntPtr extn17, IntPtr extn18, IntPtr extn19, IntPtr extn20, IntPtr term); [DllImport(efl.Libs.Eo)] internal static extern IntPtr efl_class_new(IntPtr class_description, IntPtr parent, IntPtr extn1, IntPtr extn2, IntPtr extn3, IntPtr extn4, IntPtr extn5, IntPtr extn6, IntPtr extn7, IntPtr extn8, IntPtr extn9, IntPtr extn10, IntPtr extn11, IntPtr extn12, IntPtr extn13, IntPtr extn14, IntPtr extn15, IntPtr extn16, IntPtr extn17, IntPtr extn18, IntPtr extn19, IntPtr extn20, IntPtr extn21, IntPtr term); [DllImport(efl.Libs.Eo)] internal static extern IntPtr efl_class_new(IntPtr class_description, IntPtr parent, IntPtr extn1, IntPtr extn2, IntPtr extn3, IntPtr extn4, IntPtr extn5, IntPtr extn6, IntPtr extn7, IntPtr extn8, IntPtr extn9, IntPtr extn10, IntPtr extn11, IntPtr extn12, IntPtr extn13, IntPtr extn14, IntPtr extn15, IntPtr extn16, IntPtr extn17, IntPtr extn18, IntPtr extn19, IntPtr extn20, IntPtr extn21, IntPtr extn22, IntPtr term); [DllImport(efl.Libs.Eo)] internal static extern IntPtr efl_class_new(IntPtr class_description, IntPtr parent, IntPtr extn1, IntPtr extn2, IntPtr extn3, IntPtr extn4, IntPtr extn5, IntPtr extn6, IntPtr extn7, IntPtr extn8, IntPtr extn9, IntPtr extn10, IntPtr extn11, IntPtr extn12, IntPtr extn13, IntPtr extn14, IntPtr extn15, IntPtr extn16, IntPtr extn17, IntPtr extn18, IntPtr extn19, IntPtr extn20, IntPtr extn21, IntPtr extn22, IntPtr extn23, IntPtr term); [DllImport(efl.Libs.Eo)] internal static extern IntPtr efl_class_new(IntPtr class_description, IntPtr parent, IntPtr extn1, IntPtr extn2, IntPtr extn3, IntPtr extn4, IntPtr extn5, IntPtr extn6, IntPtr extn7, IntPtr extn8, IntPtr extn9, IntPtr extn10, IntPtr extn11, IntPtr extn12, IntPtr extn13, IntPtr extn14, IntPtr extn15, IntPtr extn16, IntPtr extn17, IntPtr extn18, IntPtr extn19, IntPtr extn20, IntPtr extn21, IntPtr extn22, IntPtr extn23, IntPtr extn24, IntPtr term); [DllImport(efl.Libs.Eo)] internal static extern IntPtr efl_class_new(IntPtr class_description, IntPtr parent, IntPtr extn1, IntPtr extn2, IntPtr extn3, IntPtr extn4, IntPtr extn5, IntPtr extn6, IntPtr extn7, IntPtr extn8, IntPtr extn9, IntPtr extn10, IntPtr extn11, IntPtr extn12, IntPtr extn13, IntPtr extn14, IntPtr extn15, IntPtr extn16, IntPtr extn17, IntPtr extn18, IntPtr extn19, IntPtr extn20, IntPtr extn21, IntPtr extn22, IntPtr extn23, IntPtr extn24, IntPtr extn25, IntPtr term); [DllImport(efl.Libs.Eo)] internal static extern IntPtr efl_class_new(IntPtr class_description, IntPtr parent, IntPtr extn1, IntPtr extn2, IntPtr extn3, IntPtr extn4, IntPtr extn5, IntPtr extn6, IntPtr extn7, IntPtr extn8, IntPtr extn9, IntPtr extn10, IntPtr extn11, IntPtr extn12, IntPtr extn13, IntPtr extn14, IntPtr extn15, IntPtr extn16, IntPtr extn17, IntPtr extn18, IntPtr extn19, IntPtr extn20, IntPtr extn21, IntPtr extn22, IntPtr extn23, IntPtr extn24, IntPtr extn25, IntPtr extn26, IntPtr term); [DllImport(efl.Libs.Eo)] internal static extern IntPtr efl_class_new(IntPtr class_description, IntPtr parent, IntPtr extn1, IntPtr extn2, IntPtr extn3, IntPtr extn4, IntPtr extn5, IntPtr extn6, IntPtr extn7, IntPtr extn8, IntPtr extn9, IntPtr extn10, IntPtr extn11, IntPtr extn12, IntPtr extn13, IntPtr extn14, IntPtr extn15, IntPtr extn16, IntPtr extn17, IntPtr extn18, IntPtr extn19, IntPtr extn20, IntPtr extn21, IntPtr extn22, IntPtr extn23, IntPtr extn24, IntPtr extn25, IntPtr extn26, IntPtr extn27, IntPtr term); [DllImport(efl.Libs.Eo)] internal static extern IntPtr efl_class_new(IntPtr class_description, IntPtr parent, IntPtr extn1, IntPtr extn2, IntPtr extn3, IntPtr extn4, IntPtr extn5, IntPtr extn6, IntPtr extn7, IntPtr extn8, IntPtr extn9, IntPtr extn10, IntPtr extn11, IntPtr extn12, IntPtr extn13, IntPtr extn14, IntPtr extn15, IntPtr extn16, IntPtr extn17, IntPtr extn18, IntPtr extn19, IntPtr extn20, IntPtr extn21, IntPtr extn22, IntPtr extn23, IntPtr extn24, IntPtr extn25, IntPtr extn26, IntPtr extn27, IntPtr extn28, IntPtr term); [DllImport(efl.Libs.Eo)] internal static extern IntPtr efl_class_new(IntPtr class_description, IntPtr parent, IntPtr extn1, IntPtr extn2, IntPtr extn3, IntPtr extn4, IntPtr extn5, IntPtr extn6, IntPtr extn7, IntPtr extn8, IntPtr extn9, IntPtr extn10, IntPtr extn11, IntPtr extn12, IntPtr extn13, IntPtr extn14, IntPtr extn15, IntPtr extn16, IntPtr extn17, IntPtr extn18, IntPtr extn19, IntPtr extn20, IntPtr extn21, IntPtr extn22, IntPtr extn23, IntPtr extn24, IntPtr extn25, IntPtr extn26, IntPtr extn27, IntPtr extn28, IntPtr extn29, IntPtr term); [DllImport(efl.Libs.Eo)] internal static extern IntPtr efl_class_new(IntPtr class_description, IntPtr parent, IntPtr extn1, IntPtr extn2, IntPtr extn3, IntPtr extn4, IntPtr extn5, IntPtr extn6, IntPtr extn7, IntPtr extn8, IntPtr extn9, IntPtr extn10, IntPtr extn11, IntPtr extn12, IntPtr extn13, IntPtr extn14, IntPtr extn15, IntPtr extn16, IntPtr extn17, IntPtr extn18, IntPtr extn19, IntPtr extn20, IntPtr extn21, IntPtr extn22, IntPtr extn23, IntPtr extn24, IntPtr extn25, IntPtr extn26, IntPtr extn27, IntPtr extn28, IntPtr extn29, IntPtr extn30, IntPtr term); [DllImport(efl.Libs.Eo)] internal static extern IntPtr efl_class_new(IntPtr class_description, IntPtr parent, IntPtr extn1, IntPtr extn2, IntPtr extn3, IntPtr extn4, IntPtr extn5, IntPtr extn6, IntPtr extn7, IntPtr extn8, IntPtr extn9, IntPtr extn10, IntPtr extn11, IntPtr extn12, IntPtr extn13, IntPtr extn14, IntPtr extn15, IntPtr extn16, IntPtr extn17, IntPtr extn18, IntPtr extn19, IntPtr extn20, IntPtr extn21, IntPtr extn22, IntPtr extn23, IntPtr extn24, IntPtr extn25, IntPtr extn26, IntPtr extn27, IntPtr extn28, IntPtr extn29, IntPtr extn30, IntPtr extn31, IntPtr term); [DllImport(efl.Libs.Eo)] internal static extern IntPtr efl_class_new(IntPtr class_description, IntPtr parent, IntPtr extn1, IntPtr extn2, IntPtr extn3, IntPtr extn4, IntPtr extn5, IntPtr extn6, IntPtr extn7, IntPtr extn8, IntPtr extn9, IntPtr extn10, IntPtr extn11, IntPtr extn12, IntPtr extn13, IntPtr extn14, IntPtr extn15, IntPtr extn16, IntPtr extn17, IntPtr extn18, IntPtr extn19, IntPtr extn20, IntPtr extn21, IntPtr extn22, IntPtr extn23, IntPtr extn24, IntPtr extn25, IntPtr extn26, IntPtr extn27, IntPtr extn28, IntPtr extn29, IntPtr extn30, IntPtr extn31, IntPtr extn32, IntPtr term); [DllImport(efl.Libs.Eo)] internal static extern IntPtr efl_class_new(IntPtr class_description, IntPtr parent, IntPtr extn1, IntPtr extn2, IntPtr extn3, IntPtr extn4, IntPtr extn5, IntPtr extn6, IntPtr extn7, IntPtr extn8, IntPtr extn9, IntPtr extn10, IntPtr extn11, IntPtr extn12, IntPtr extn13, IntPtr extn14, IntPtr extn15, IntPtr extn16, IntPtr extn17, IntPtr extn18, IntPtr extn19, IntPtr extn20, IntPtr extn21, IntPtr extn22, IntPtr extn23, IntPtr extn24, IntPtr extn25, IntPtr extn26, IntPtr extn27, IntPtr extn28, IntPtr extn29, IntPtr extn30, IntPtr extn31, IntPtr extn32, IntPtr extn33, IntPtr term); [DllImport(efl.Libs.Eo)] internal static extern IntPtr efl_class_new(IntPtr class_description, IntPtr parent, IntPtr extn1, IntPtr extn2, IntPtr extn3, IntPtr extn4, IntPtr extn5, IntPtr extn6, IntPtr extn7, IntPtr extn8, IntPtr extn9, IntPtr extn10, IntPtr extn11, IntPtr extn12, IntPtr extn13, IntPtr extn14, IntPtr extn15, IntPtr extn16, IntPtr extn17, IntPtr extn18, IntPtr extn19, IntPtr extn20, IntPtr extn21, IntPtr extn22, IntPtr extn23, IntPtr extn24, IntPtr extn25, IntPtr extn26, IntPtr extn27, IntPtr extn28, IntPtr extn29, IntPtr extn30, IntPtr extn31, IntPtr extn32, IntPtr extn33, IntPtr extn34, IntPtr term); [DllImport(efl.Libs.Eo)] internal static extern IntPtr efl_class_new(IntPtr class_description, IntPtr parent, IntPtr extn1, IntPtr extn2, IntPtr extn3, IntPtr extn4, IntPtr extn5, IntPtr extn6, IntPtr extn7, IntPtr extn8, IntPtr extn9, IntPtr extn10, IntPtr extn11, IntPtr extn12, IntPtr extn13, IntPtr extn14, IntPtr extn15, IntPtr extn16, IntPtr extn17, IntPtr extn18, IntPtr extn19, IntPtr extn20, IntPtr extn21, IntPtr extn22, IntPtr extn23, IntPtr extn24, IntPtr extn25, IntPtr extn26, IntPtr extn27, IntPtr extn28, IntPtr extn29, IntPtr extn30, IntPtr extn31, IntPtr extn32, IntPtr extn33, IntPtr extn34, IntPtr extn35, IntPtr term); [DllImport(efl.Libs.Eo)] internal static extern IntPtr efl_class_new(IntPtr class_description, IntPtr parent, IntPtr extn1, IntPtr extn2, IntPtr extn3, IntPtr extn4, IntPtr extn5, IntPtr extn6, IntPtr extn7, IntPtr extn8, IntPtr extn9, IntPtr extn10, IntPtr extn11, IntPtr extn12, IntPtr extn13, IntPtr extn14, IntPtr extn15, IntPtr extn16, IntPtr extn17, IntPtr extn18, IntPtr extn19, IntPtr extn20, IntPtr extn21, IntPtr extn22, IntPtr extn23, IntPtr extn24, IntPtr extn25, IntPtr extn26, IntPtr extn27, IntPtr extn28, IntPtr extn29, IntPtr extn30, IntPtr extn31, IntPtr extn32, IntPtr extn33, IntPtr extn34, IntPtr extn35, IntPtr extn36, IntPtr term); [DllImport(efl.Libs.Eo)] internal static extern IntPtr efl_class_new(IntPtr class_description, IntPtr parent, IntPtr extn1, IntPtr extn2, IntPtr extn3, IntPtr extn4, IntPtr extn5, IntPtr extn6, IntPtr extn7, IntPtr extn8, IntPtr extn9, IntPtr extn10, IntPtr extn11, IntPtr extn12, IntPtr extn13, IntPtr extn14, IntPtr extn15, IntPtr extn16, IntPtr extn17, IntPtr extn18, IntPtr extn19, IntPtr extn20, IntPtr extn21, IntPtr extn22, IntPtr extn23, IntPtr extn24, IntPtr extn25, IntPtr extn26, IntPtr extn27, IntPtr extn28, IntPtr extn29, IntPtr extn30, IntPtr extn31, IntPtr extn32, IntPtr extn33, IntPtr extn34, IntPtr extn35, IntPtr extn36, IntPtr extn37, IntPtr term); [DllImport(efl.Libs.Eo)] internal static extern IntPtr efl_class_new(IntPtr class_description, IntPtr parent, IntPtr extn1, IntPtr extn2, IntPtr extn3, IntPtr extn4, IntPtr extn5, IntPtr extn6, IntPtr extn7, IntPtr extn8, IntPtr extn9, IntPtr extn10, IntPtr extn11, IntPtr extn12, IntPtr extn13, IntPtr extn14, IntPtr extn15, IntPtr extn16, IntPtr extn17, IntPtr extn18, IntPtr extn19, IntPtr extn20, IntPtr extn21, IntPtr extn22, IntPtr extn23, IntPtr extn24, IntPtr extn25, IntPtr extn26, IntPtr extn27, IntPtr extn28, IntPtr extn29, IntPtr extn30, IntPtr extn31, IntPtr extn32, IntPtr extn33, IntPtr extn34, IntPtr extn35, IntPtr extn36, IntPtr extn37, IntPtr extn38, IntPtr term); [DllImport(efl.Libs.Eo)] internal static extern IntPtr efl_class_new(IntPtr class_description, IntPtr parent, IntPtr extn1, IntPtr extn2, IntPtr extn3, IntPtr extn4, IntPtr extn5, IntPtr extn6, IntPtr extn7, IntPtr extn8, IntPtr extn9, IntPtr extn10, IntPtr extn11, IntPtr extn12, IntPtr extn13, IntPtr extn14, IntPtr extn15, IntPtr extn16, IntPtr extn17, IntPtr extn18, IntPtr extn19, IntPtr extn20, IntPtr extn21, IntPtr extn22, IntPtr extn23, IntPtr extn24, IntPtr extn25, IntPtr extn26, IntPtr extn27, IntPtr extn28, IntPtr extn29, IntPtr extn30, IntPtr extn31, IntPtr extn32, IntPtr extn33, IntPtr extn34, IntPtr extn35, IntPtr extn36, IntPtr extn37, IntPtr extn38, IntPtr extn39, IntPtr term); [DllImport(efl.Libs.Eo)] internal static extern IntPtr efl_class_new(IntPtr class_description, IntPtr parent, IntPtr extn1, IntPtr extn2, IntPtr extn3, IntPtr extn4, IntPtr extn5, IntPtr extn6, IntPtr extn7, IntPtr extn8, IntPtr extn9, IntPtr extn10, IntPtr extn11, IntPtr extn12, IntPtr extn13, IntPtr extn14, IntPtr extn15, IntPtr extn16, IntPtr extn17, IntPtr extn18, IntPtr extn19, IntPtr extn20, IntPtr extn21, IntPtr extn22, IntPtr extn23, IntPtr extn24, IntPtr extn25, IntPtr extn26, IntPtr extn27, IntPtr extn28, IntPtr extn29, IntPtr extn30, IntPtr extn31, IntPtr extn32, IntPtr extn33, IntPtr extn34, IntPtr extn35, IntPtr extn36, IntPtr extn37, IntPtr extn38, IntPtr extn39, IntPtr extn40, IntPtr term); [DllImport(efl.Libs.Eo)] internal static extern IntPtr efl_class_new(IntPtr class_description, IntPtr parent, IntPtr extn1, IntPtr extn2, IntPtr extn3, IntPtr extn4, IntPtr extn5, IntPtr extn6, IntPtr extn7, IntPtr extn8, IntPtr extn9, IntPtr extn10, IntPtr extn11, IntPtr extn12, IntPtr extn13, IntPtr extn14, IntPtr extn15, IntPtr extn16, IntPtr extn17, IntPtr extn18, IntPtr extn19, IntPtr extn20, IntPtr extn21, IntPtr extn22, IntPtr extn23, IntPtr extn24, IntPtr extn25, IntPtr extn26, IntPtr extn27, IntPtr extn28, IntPtr extn29, IntPtr extn30, IntPtr extn31, IntPtr extn32, IntPtr extn33, IntPtr extn34, IntPtr extn35, IntPtr extn36, IntPtr extn37, IntPtr extn38, IntPtr extn39, IntPtr extn40, IntPtr extn41, IntPtr term); [DllImport(efl.Libs.Eo)] internal static extern IntPtr efl_class_new(IntPtr class_description, IntPtr parent, IntPtr extn1, IntPtr extn2, IntPtr extn3, IntPtr extn4, IntPtr extn5, IntPtr extn6, IntPtr extn7, IntPtr extn8, IntPtr extn9, IntPtr extn10, IntPtr extn11, IntPtr extn12, IntPtr extn13, IntPtr extn14, IntPtr extn15, IntPtr extn16, IntPtr extn17, IntPtr extn18, IntPtr extn19, IntPtr extn20, IntPtr extn21, IntPtr extn22, IntPtr extn23, IntPtr extn24, IntPtr extn25, IntPtr extn26, IntPtr extn27, IntPtr extn28, IntPtr extn29, IntPtr extn30, IntPtr extn31, IntPtr extn32, IntPtr extn33, IntPtr extn34, IntPtr extn35, IntPtr extn36, IntPtr extn37, IntPtr extn38, IntPtr extn39, IntPtr extn40, IntPtr extn41, IntPtr extn42, IntPtr term); [DllImport(efl.Libs.Eo)] internal static extern IntPtr efl_class_new(IntPtr class_description, IntPtr parent, IntPtr extn1, IntPtr extn2, IntPtr extn3, IntPtr extn4, IntPtr extn5, IntPtr extn6, IntPtr extn7, IntPtr extn8, IntPtr extn9, IntPtr extn10, IntPtr extn11, IntPtr extn12, IntPtr extn13, IntPtr extn14, IntPtr extn15, IntPtr extn16, IntPtr extn17, IntPtr extn18, IntPtr extn19, IntPtr extn20, IntPtr extn21, IntPtr extn22, IntPtr extn23, IntPtr extn24, IntPtr extn25, IntPtr extn26, IntPtr extn27, IntPtr extn28, IntPtr extn29, IntPtr extn30, IntPtr extn31, IntPtr extn32, IntPtr extn33, IntPtr extn34, IntPtr extn35, IntPtr extn36, IntPtr extn37, IntPtr extn38, IntPtr extn39, IntPtr extn40, IntPtr extn41, IntPtr extn42, IntPtr extn43, IntPtr term); [DllImport(efl.Libs.Eo)] internal static extern IntPtr efl_class_new(IntPtr class_description, IntPtr parent, IntPtr extn1, IntPtr extn2, IntPtr extn3, IntPtr extn4, IntPtr extn5, IntPtr extn6, IntPtr extn7, IntPtr extn8, IntPtr extn9, IntPtr extn10, IntPtr extn11, IntPtr extn12, IntPtr extn13, IntPtr extn14, IntPtr extn15, IntPtr extn16, IntPtr extn17, IntPtr extn18, IntPtr extn19, IntPtr extn20, IntPtr extn21, IntPtr extn22, IntPtr extn23, IntPtr extn24, IntPtr extn25, IntPtr extn26, IntPtr extn27, IntPtr extn28, IntPtr extn29, IntPtr extn30, IntPtr extn31, IntPtr extn32, IntPtr extn33, IntPtr extn34, IntPtr extn35, IntPtr extn36, IntPtr extn37, IntPtr extn38, IntPtr extn39, IntPtr extn40, IntPtr extn41, IntPtr extn42, IntPtr extn43, IntPtr extn44, IntPtr term); [DllImport(efl.Libs.Eo)] internal static extern IntPtr efl_class_new(IntPtr class_description, IntPtr parent, IntPtr extn1, IntPtr extn2, IntPtr extn3, IntPtr extn4, IntPtr extn5, IntPtr extn6, IntPtr extn7, IntPtr extn8, IntPtr extn9, IntPtr extn10, IntPtr extn11, IntPtr extn12, IntPtr extn13, IntPtr extn14, IntPtr extn15, IntPtr extn16, IntPtr extn17, IntPtr extn18, IntPtr extn19, IntPtr extn20, IntPtr extn21, IntPtr extn22, IntPtr extn23, IntPtr extn24, IntPtr extn25, IntPtr extn26, IntPtr extn27, IntPtr extn28, IntPtr extn29, IntPtr extn30, IntPtr extn31, IntPtr extn32, IntPtr extn33, IntPtr extn34, IntPtr extn35, IntPtr extn36, IntPtr extn37, IntPtr extn38, IntPtr extn39, IntPtr extn40, IntPtr extn41, IntPtr extn42, IntPtr extn43, IntPtr extn44, IntPtr extn45, IntPtr term); [DllImport(efl.Libs.Eo)] internal static extern IntPtr efl_class_new(IntPtr class_description, IntPtr parent, IntPtr extn1, IntPtr extn2, IntPtr extn3, IntPtr extn4, IntPtr extn5, IntPtr extn6, IntPtr extn7, IntPtr extn8, IntPtr extn9, IntPtr extn10, IntPtr extn11, IntPtr extn12, IntPtr extn13, IntPtr extn14, IntPtr extn15, IntPtr extn16, IntPtr extn17, IntPtr extn18, IntPtr extn19, IntPtr extn20, IntPtr extn21, IntPtr extn22, IntPtr extn23, IntPtr extn24, IntPtr extn25, IntPtr extn26, IntPtr extn27, IntPtr extn28, IntPtr extn29, IntPtr extn30, IntPtr extn31, IntPtr extn32, IntPtr extn33, IntPtr extn34, IntPtr extn35, IntPtr extn36, IntPtr extn37, IntPtr extn38, IntPtr extn39, IntPtr extn40, IntPtr extn41, IntPtr extn42, IntPtr extn43, IntPtr extn44, IntPtr extn45, IntPtr extn46, IntPtr term); [DllImport(efl.Libs.Eo)] internal static extern IntPtr efl_class_new(IntPtr class_description, IntPtr parent, IntPtr extn1, IntPtr extn2, IntPtr extn3, IntPtr extn4, IntPtr extn5, IntPtr extn6, IntPtr extn7, IntPtr extn8, IntPtr extn9, IntPtr extn10, IntPtr extn11, IntPtr extn12, IntPtr extn13, IntPtr extn14, IntPtr extn15, IntPtr extn16, IntPtr extn17, IntPtr extn18, IntPtr extn19, IntPtr extn20, IntPtr extn21, IntPtr extn22, IntPtr extn23, IntPtr extn24, IntPtr extn25, IntPtr extn26, IntPtr extn27, IntPtr extn28, IntPtr extn29, IntPtr extn30, IntPtr extn31, IntPtr extn32, IntPtr extn33, IntPtr extn34, IntPtr extn35, IntPtr extn36, IntPtr extn37, IntPtr extn38, IntPtr extn39, IntPtr extn40, IntPtr extn41, IntPtr extn42, IntPtr extn43, IntPtr extn44, IntPtr extn45, IntPtr extn46, IntPtr extn47, IntPtr term); [DllImport(efl.Libs.Eo)] internal static extern IntPtr efl_class_new(IntPtr class_description, IntPtr parent, IntPtr extn1, IntPtr extn2, IntPtr extn3, IntPtr extn4, IntPtr extn5, IntPtr extn6, IntPtr extn7, IntPtr extn8, IntPtr extn9, IntPtr extn10, IntPtr extn11, IntPtr extn12, IntPtr extn13, IntPtr extn14, IntPtr extn15, IntPtr extn16, IntPtr extn17, IntPtr extn18, IntPtr extn19, IntPtr extn20, IntPtr extn21, IntPtr extn22, IntPtr extn23, IntPtr extn24, IntPtr extn25, IntPtr extn26, IntPtr extn27, IntPtr extn28, IntPtr extn29, IntPtr extn30, IntPtr extn31, IntPtr extn32, IntPtr extn33, IntPtr extn34, IntPtr extn35, IntPtr extn36, IntPtr extn37, IntPtr extn38, IntPtr extn39, IntPtr extn40, IntPtr extn41, IntPtr extn42, IntPtr extn43, IntPtr extn44, IntPtr extn45, IntPtr extn46, IntPtr extn47, IntPtr extn48, IntPtr term); internal delegate byte efl_class_functions_set_delegate(IntPtr klass_id, IntPtr object_ops, IntPtr class_ops); [DllImport(efl.Libs.Eo)] internal static extern byte efl_class_functions_set(IntPtr klass_id, IntPtr object_ops, IntPtr class_ops); internal delegate IntPtr efl_data_scope_get_delegate(IntPtr obj, IntPtr klass); [DllImport(efl.Libs.Eo)] internal static extern IntPtr efl_data_scope_get(IntPtr obj, IntPtr klass); internal delegate IntPtr efl_super_delegate(IntPtr obj, IntPtr klass); /// Gets a native pointer to obj that forwards the method call to its parent /// implementation. /// /// For generated code use only. /// Since EFL 1.23. /// /// The native pointer to be prepared. /// The current class. /// The native pointer to obj prepared to call the parent implementation of klass. internal static IntPtr Super(IntPtr obj, IntPtr klass) { return efl_super(obj, klass); } [DllImport(efl.Libs.Eo)] internal static extern IntPtr efl_super(IntPtr obj, IntPtr klass); internal delegate IntPtr efl_class_get_delegate(IntPtr obj); [DllImport(efl.Libs.Eo)] internal static extern IntPtr efl_class_get(IntPtr obj); /// Gets the native EO class pointer for the given object. /// For generated code use only. /// Since EFL 1.23. /// /// The native pointer to the instance to get the native class /// from. /// The native class pointer or if no such class existis. internal static IntPtr GetClass(IntPtr obj) { return efl_class_get(obj); } [DllImport(efl.Libs.Eo)] internal static extern EflClassType efl_class_type_get(IntPtr klass); internal delegate IntPtr dlerror_delegate(); [DllImport(efl.Libs.Evil)] internal static extern IntPtr dlerror(); [DllImport(efl.Libs.Eo)] internal static extern IntPtr efl_constructor(IntPtr obj); [DllImport(efl.Libs.CustomExports)] internal static extern IntPtr efl_mono_avoid_top_level_constructor_callback_addr_get(); [DllImport(efl.Libs.Eo)] [return: MarshalAs(UnmanagedType.U1)] internal static extern bool efl_event_callback_priority_add(IntPtr obj, IntPtr desc, short priority, IntPtr cb, IntPtr data); [DllImport(efl.Libs.Eo)] [return: MarshalAs(UnmanagedType.U1)] internal static extern bool efl_event_callback_del(IntPtr obj, IntPtr desc, IntPtr cb, IntPtr data); [DllImport(efl.Libs.Eo)] [return: MarshalAs(UnmanagedType.U1)] internal static extern bool efl_event_callback_call(IntPtr obj, IntPtr desc, IntPtr event_info); /// Calls the callbacks associated to an event. /// For generated code use only. /// Since EFL 1.23. /// /// The native pointer to the instance that will be the emitter /// of the event. /// The native event description. /// The native payload of the event. /// false if one of the callbacks aborted the call. true otherwise. internal static bool CallEventCallback(IntPtr obj, IntPtr desc, IntPtr event_info) { return efl_event_callback_call(obj, desc, event_info); } internal const int RTLD_NOW = 2; internal delegate byte class_initializer(IntPtr klass); internal static T GetParamHelper(Nullable v) where T : struct { return v.Value; } internal static U GetParamHelper(U v) { return v; } internal static bool ParamHelperCheck(Nullable v) where T : struct { return v.HasValue; } internal static bool ParamHelperCheck(U v) { return v != null; } internal static IntPtr register_class(String class_name, IntPtr base_klass, System.Type type) { ClassDescription description; description.version = 2; // EO_VERSION description.name = class_name; description.class_type = 0; // REGULAR description.data_size = (UIntPtr)0; description.class_initializer = IntPtr.Zero; description.class_constructor = IntPtr.Zero; description.class_destructor = IntPtr.Zero; class_initializer init = (IntPtr kls) => { return Globals.class_initializer_call(kls, type); }; description.class_initializer = Marshal.GetFunctionPointerForDelegate(init); IntPtr description_ptr = Eina.MemoryNative.Alloc(Marshal.SizeOf(description)); Marshal.StructureToPtr(description, description_ptr, false); // FIXME: description_ptr seems to be leaking memory even after an eo_shutdown var interface_list = EoG.get_efl_interfaces(type); Eina.Log.Debug($"Going to register new class named {class_name}"); IntPtr klass = EoG.call_efl_class_new(description_ptr, base_klass, interface_list); if (klass == IntPtr.Zero) { Eina.Log.Error("klass was not registered"); } else { Eina.Log.Debug("Registered class successfully"); } return klass; } internal static List get_efl_interfaces(System.Type type) { System.Type base_type = type.BaseType; var ifaces_lst = new List(); var base_ifaces = base_type.GetInterfaces(); var ifaces = type.GetInterfaces(); foreach (var iface in ifaces) { if (!System.Array.Exists(base_ifaces, element => element == iface)) { var attrs = System.Attribute.GetCustomAttributes(iface); foreach (var attr in attrs) { if (attr is Efl.Eo.NativeClass) { ifaces_lst.Add(((Efl.Eo.NativeClass)attr).GetEflClass()); break; } } } } return ifaces_lst; } private static Efl.Eo.NativeClass GetNativeClass(System.Type type) { var attrs = System.Attribute.GetCustomAttributes(type, false); foreach (var attr in attrs) { if (attr is Efl.Eo.NativeClass) { return (Efl.Eo.NativeClass)attr; } } return null; } internal static System.Collections.Generic.List GetUserMethods(System.Type type) { var r = new System.Collections.Generic.List(); var flags = System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.DeclaredOnly | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic; for (var base_type = type;;base_type = base_type.BaseType) { r.AddRange(base_type.GetMethods(flags) .AsParallel().Select(info=>info.Name).ToList()); if (IsGeneratedClass(base_type.BaseType)) { break; } if (base_type.BaseType == null) { break; } } return r; } internal static byte class_initializer_call(IntPtr klass, System.Type type) { Eina.Log.Debug($"called with 0x{klass.ToInt64():x} {type}"); var derived = type.BaseType; Efl.Eo.NativeClass nativeClass = GetNativeClass(derived); while (nativeClass == null) { derived = derived.BaseType; if (derived == null) break; nativeClass = GetNativeClass(derived); } if (nativeClass != null) { Eina.Log.Debug("nativeClass != null"); var descs = nativeClass.GetEoOps(type, true); var count = descs.Count; IntPtr descs_ptr = IntPtr.Zero; if (count > 0) { descs_ptr = Marshal.AllocHGlobal(Marshal.SizeOf(descs[0]) * count); } IntPtr ptr = descs_ptr; for (int i = 0; i != count; ++i) { Marshal.StructureToPtr(descs[i], ptr, false); ptr = IntPtr.Add(ptr, Marshal.SizeOf(descs[0])); } EflObjectOps ops; ops.descs = descs_ptr; ops.count = (UIntPtr)count; IntPtr ops_ptr = Marshal.AllocHGlobal(Marshal.SizeOf(ops)); Marshal.StructureToPtr(ops, ops_ptr, false); Efl.Eo.Globals.efl_class_functions_set(klass, ops_ptr, IntPtr.Zero); //EoKlass = klass; } else { Eina.Log.Debug("nativeClass == null"); } return 1; } internal static IntPtr call_efl_class_new(IntPtr desc, IntPtr bk, List il = null) { IntPtr nul = IntPtr.Zero; int iface_list_count = (il == null ? 0 : il.Count); switch (iface_list_count) { default: return nul; case 0: return EoG.efl_class_new(desc, bk, nul); case 1: return EoG.efl_class_new(desc, bk, il[0], nul); case 2: return EoG.efl_class_new(desc, bk, il[0], il[1], nul); case 3: return EoG.efl_class_new(desc, bk, il[0], il[1], il[2], nul); case 4: return EoG.efl_class_new(desc, bk, il[0], il[1], il[2], il[3], nul); case 5: return EoG.efl_class_new(desc, bk, il[0], il[1], il[2], il[3], il[4], nul); case 6: return EoG.efl_class_new(desc, bk, il[0], il[1], il[2], il[3], il[4], il[5], nul); case 7: return EoG.efl_class_new(desc, bk, il[0], il[1], il[2], il[3], il[4], il[5], il[6], nul); case 8: return EoG.efl_class_new(desc, bk, il[0], il[1], il[2], il[3], il[4], il[5], il[6], il[7], nul); case 9: return EoG.efl_class_new(desc, bk, il[0], il[1], il[2], il[3], il[4], il[5], il[6], il[7], il[8], nul); case 10: return EoG.efl_class_new(desc, bk, il[0], il[1], il[2], il[3], il[4], il[5], il[6], il[7], il[8], il[9], nul); case 11: return EoG.efl_class_new(desc, bk, il[0], il[1], il[2], il[3], il[4], il[5], il[6], il[7], il[8], il[9], il[10], nul); case 12: return EoG.efl_class_new(desc, bk, il[0], il[1], il[2], il[3], il[4], il[5], il[6], il[7], il[8], il[9], il[10], il[11], nul); case 13: return EoG.efl_class_new(desc, bk, il[0], il[1], il[2], il[3], il[4], il[5], il[6], il[7], il[8], il[9], il[10], il[11], il[12], nul); case 14: return EoG.efl_class_new(desc, bk, il[0], il[1], il[2], il[3], il[4], il[5], il[6], il[7], il[8], il[9], il[10], il[11], il[12], il[13], nul); case 15: return EoG.efl_class_new(desc, bk, il[0], il[1], il[2], il[3], il[4], il[5], il[6], il[7], il[8], il[9], il[10], il[11], il[12], il[13], il[14], nul); case 16: return EoG.efl_class_new(desc, bk, il[0], il[1], il[2], il[3], il[4], il[5], il[6], il[7], il[8], il[9], il[10], il[11], il[12], il[13], il[14], il[15], nul); case 17: return EoG.efl_class_new(desc, bk, il[0], il[1], il[2], il[3], il[4], il[5], il[6], il[7], il[8], il[9], il[10], il[11], il[12], il[13], il[14], il[15], il[16], nul); case 18: return EoG.efl_class_new(desc, bk, il[0], il[1], il[2], il[3], il[4], il[5], il[6], il[7], il[8], il[9], il[10], il[11], il[12], il[13], il[14], il[15], il[16], il[17], nul); case 19: return EoG.efl_class_new(desc, bk, il[0], il[1], il[2], il[3], il[4], il[5], il[6], il[7], il[8], il[9], il[10], il[11], il[12], il[13], il[14], il[15], il[16], il[17], il[18], nul); case 20: return EoG.efl_class_new(desc, bk, il[0], il[1], il[2], il[3], il[4], il[5], il[6], il[7], il[8], il[9], il[10], il[11], il[12], il[13], il[14], il[15], il[16], il[17], il[18], il[19], nul); case 21: return EoG.efl_class_new(desc, bk, il[0], il[1], il[2], il[3], il[4], il[5], il[6], il[7], il[8], il[9], il[10], il[11], il[12], il[13], il[14], il[15], il[16], il[17], il[18], il[19], il[20], nul); case 22: return EoG.efl_class_new(desc, bk, il[0], il[1], il[2], il[3], il[4], il[5], il[6], il[7], il[8], il[9], il[10], il[11], il[12], il[13], il[14], il[15], il[16], il[17], il[18], il[19], il[20], il[21], nul); case 23: return EoG.efl_class_new(desc, bk, il[0], il[1], il[2], il[3], il[4], il[5], il[6], il[7], il[8], il[9], il[10], il[11], il[12], il[13], il[14], il[15], il[16], il[17], il[18], il[19], il[20], il[21], il[22], nul); case 24: return EoG.efl_class_new(desc, bk, il[0], il[1], il[2], il[3], il[4], il[5], il[6], il[7], il[8], il[9], il[10], il[11], il[12], il[13], il[14], il[15], il[16], il[17], il[18], il[19], il[20], il[21], il[22], il[23], nul); case 25: return EoG.efl_class_new(desc, bk, il[0], il[1], il[2], il[3], il[4], il[5], il[6], il[7], il[8], il[9], il[10], il[11], il[12], il[13], il[14], il[15], il[16], il[17], il[18], il[19], il[20], il[21], il[22], il[23], il[24], nul); case 26: return EoG.efl_class_new(desc, bk, il[0], il[1], il[2], il[3], il[4], il[5], il[6], il[7], il[8], il[9], il[10], il[11], il[12], il[13], il[14], il[15], il[16], il[17], il[18], il[19], il[20], il[21], il[22], il[23], il[24], il[25], nul); case 27: return EoG.efl_class_new(desc, bk, il[0], il[1], il[2], il[3], il[4], il[5], il[6], il[7], il[8], il[9], il[10], il[11], il[12], il[13], il[14], il[15], il[16], il[17], il[18], il[19], il[20], il[21], il[22], il[23], il[24], il[25], il[26], nul); case 28: return EoG.efl_class_new(desc, bk, il[0], il[1], il[2], il[3], il[4], il[5], il[6], il[7], il[8], il[9], il[10], il[11], il[12], il[13], il[14], il[15], il[16], il[17], il[18], il[19], il[20], il[21], il[22], il[23], il[24], il[25], il[26], il[27], nul); case 29: return EoG.efl_class_new(desc, bk, il[0], il[1], il[2], il[3], il[4], il[5], il[6], il[7], il[8], il[9], il[10], il[11], il[12], il[13], il[14], il[15], il[16], il[17], il[18], il[19], il[20], il[21], il[22], il[23], il[24], il[25], il[26], il[27], il[28], nul); case 30: return EoG.efl_class_new(desc, bk, il[0], il[1], il[2], il[3], il[4], il[5], il[6], il[7], il[8], il[9], il[10], il[11], il[12], il[13], il[14], il[15], il[16], il[17], il[18], il[19], il[20], il[21], il[22], il[23], il[24], il[25], il[26], il[27], il[28], il[29], nul); case 31: return EoG.efl_class_new(desc, bk, il[0], il[1], il[2], il[3], il[4], il[5], il[6], il[7], il[8], il[9], il[10], il[11], il[12], il[13], il[14], il[15], il[16], il[17], il[18], il[19], il[20], il[21], il[22], il[23], il[24], il[25], il[26], il[27], il[28], il[29], il[30], nul); case 32: return EoG.efl_class_new(desc, bk, il[0], il[1], il[2], il[3], il[4], il[5], il[6], il[7], il[8], il[9], il[10], il[11], il[12], il[13], il[14], il[15], il[16], il[17], il[18], il[19], il[20], il[21], il[22], il[23], il[24], il[25], il[26], il[27], il[28], il[29], il[30], il[31], nul); case 33: return EoG.efl_class_new(desc, bk, il[0], il[1], il[2], il[3], il[4], il[5], il[6], il[7], il[8], il[9], il[10], il[11], il[12], il[13], il[14], il[15], il[16], il[17], il[18], il[19], il[20], il[21], il[22], il[23], il[24], il[25], il[26], il[27], il[28], il[29], il[30], il[31], il[32], nul); case 34: return EoG.efl_class_new(desc, bk, il[0], il[1], il[2], il[3], il[4], il[5], il[6], il[7], il[8], il[9], il[10], il[11], il[12], il[13], il[14], il[15], il[16], il[17], il[18], il[19], il[20], il[21], il[22], il[23], il[24], il[25], il[26], il[27], il[28], il[29], il[30], il[31], il[32], il[33], nul); case 35: return EoG.efl_class_new(desc, bk, il[0], il[1], il[2], il[3], il[4], il[5], il[6], il[7], il[8], il[9], il[10], il[11], il[12], il[13], il[14], il[15], il[16], il[17], il[18], il[19], il[20], il[21], il[22], il[23], il[24], il[25], il[26], il[27], il[28], il[29], il[30], il[31], il[32], il[33], il[34], nul); case 36: return EoG.efl_class_new(desc, bk, il[0], il[1], il[2], il[3], il[4], il[5], il[6], il[7], il[8], il[9], il[10], il[11], il[12], il[13], il[14], il[15], il[16], il[17], il[18], il[19], il[20], il[21], il[22], il[23], il[24], il[25], il[26], il[27], il[28], il[29], il[30], il[31], il[32], il[33], il[34], il[35], nul); case 37: return EoG.efl_class_new(desc, bk, il[0], il[1], il[2], il[3], il[4], il[5], il[6], il[7], il[8], il[9], il[10], il[11], il[12], il[13], il[14], il[15], il[16], il[17], il[18], il[19], il[20], il[21], il[22], il[23], il[24], il[25], il[26], il[27], il[28], il[29], il[30], il[31], il[32], il[33], il[34], il[35], il[36], nul); case 38: return EoG.efl_class_new(desc, bk, il[0], il[1], il[2], il[3], il[4], il[5], il[6], il[7], il[8], il[9], il[10], il[11], il[12], il[13], il[14], il[15], il[16], il[17], il[18], il[19], il[20], il[21], il[22], il[23], il[24], il[25], il[26], il[27], il[28], il[29], il[30], il[31], il[32], il[33], il[34], il[35], il[36], il[37], nul); case 39: return EoG.efl_class_new(desc, bk, il[0], il[1], il[2], il[3], il[4], il[5], il[6], il[7], il[8], il[9], il[10], il[11], il[12], il[13], il[14], il[15], il[16], il[17], il[18], il[19], il[20], il[21], il[22], il[23], il[24], il[25], il[26], il[27], il[28], il[29], il[30], il[31], il[32], il[33], il[34], il[35], il[36], il[37], il[38], nul); case 40: return EoG.efl_class_new(desc, bk, il[0], il[1], il[2], il[3], il[4], il[5], il[6], il[7], il[8], il[9], il[10], il[11], il[12], il[13], il[14], il[15], il[16], il[17], il[18], il[19], il[20], il[21], il[22], il[23], il[24], il[25], il[26], il[27], il[28], il[29], il[30], il[31], il[32], il[33], il[34], il[35], il[36], il[37], il[38], il[39], nul); case 41: return EoG.efl_class_new(desc, bk, il[0], il[1], il[2], il[3], il[4], il[5], il[6], il[7], il[8], il[9], il[10], il[11], il[12], il[13], il[14], il[15], il[16], il[17], il[18], il[19], il[20], il[21], il[22], il[23], il[24], il[25], il[26], il[27], il[28], il[29], il[30], il[31], il[32], il[33], il[34], il[35], il[36], il[37], il[38], il[39], il[40], nul); case 42: return EoG.efl_class_new(desc, bk, il[0], il[1], il[2], il[3], il[4], il[5], il[6], il[7], il[8], il[9], il[10], il[11], il[12], il[13], il[14], il[15], il[16], il[17], il[18], il[19], il[20], il[21], il[22], il[23], il[24], il[25], il[26], il[27], il[28], il[29], il[30], il[31], il[32], il[33], il[34], il[35], il[36], il[37], il[38], il[39], il[40], il[41], nul); case 43: return EoG.efl_class_new(desc, bk, il[0], il[1], il[2], il[3], il[4], il[5], il[6], il[7], il[8], il[9], il[10], il[11], il[12], il[13], il[14], il[15], il[16], il[17], il[18], il[19], il[20], il[21], il[22], il[23], il[24], il[25], il[26], il[27], il[28], il[29], il[30], il[31], il[32], il[33], il[34], il[35], il[36], il[37], il[38], il[39], il[40], il[41], il[42], nul); case 44: return EoG.efl_class_new(desc, bk, il[0], il[1], il[2], il[3], il[4], il[5], il[6], il[7], il[8], il[9], il[10], il[11], il[12], il[13], il[14], il[15], il[16], il[17], il[18], il[19], il[20], il[21], il[22], il[23], il[24], il[25], il[26], il[27], il[28], il[29], il[30], il[31], il[32], il[33], il[34], il[35], il[36], il[37], il[38], il[39], il[40], il[41], il[42], il[43], nul); case 45: return EoG.efl_class_new(desc, bk, il[0], il[1], il[2], il[3], il[4], il[5], il[6], il[7], il[8], il[9], il[10], il[11], il[12], il[13], il[14], il[15], il[16], il[17], il[18], il[19], il[20], il[21], il[22], il[23], il[24], il[25], il[26], il[27], il[28], il[29], il[30], il[31], il[32], il[33], il[34], il[35], il[36], il[37], il[38], il[39], il[40], il[41], il[42], il[43], il[44], nul); case 46: return EoG.efl_class_new(desc, bk, il[0], il[1], il[2], il[3], il[4], il[5], il[6], il[7], il[8], il[9], il[10], il[11], il[12], il[13], il[14], il[15], il[16], il[17], il[18], il[19], il[20], il[21], il[22], il[23], il[24], il[25], il[26], il[27], il[28], il[29], il[30], il[31], il[32], il[33], il[34], il[35], il[36], il[37], il[38], il[39], il[40], il[41], il[42], il[43], il[44], il[45], nul); case 47: return EoG.efl_class_new(desc, bk, il[0], il[1], il[2], il[3], il[4], il[5], il[6], il[7], il[8], il[9], il[10], il[11], il[12], il[13], il[14], il[15], il[16], il[17], il[18], il[19], il[20], il[21], il[22], il[23], il[24], il[25], il[26], il[27], il[28], il[29], il[30], il[31], il[32], il[33], il[34], il[35], il[36], il[37], il[38], il[39], il[40], il[41], il[42], il[43], il[44], il[45], il[46], nul); case 48: return EoG.efl_class_new(desc, bk, il[0], il[1], il[2], il[3], il[4], il[5], il[6], il[7], il[8], il[9], il[10], il[11], il[12], il[13], il[14], il[15], il[16], il[17], il[18], il[19], il[20], il[21], il[22], il[23], il[24], il[25], il[26], il[27], il[28], il[29], il[30], il[31], il[32], il[33], il[34], il[35], il[36], il[37], il[38], il[39], il[40], il[41], il[42], il[43], il[44], il[45], il[46], il[47], nul); } } internal static Efl.Eo.WrapperSupervisor WrapperSupervisorPtrToManaged(IntPtr wsPtr) { return (Efl.Eo.WrapperSupervisor) GCHandle.FromIntPtr(wsPtr).Target; } internal static Efl.Eo.WrapperSupervisor GetWrapperSupervisor(IntPtr eo) { var wsPtr = Efl.Eo.Globals.efl_mono_wrapper_supervisor_get(eo); if (wsPtr == IntPtr.Zero) { return null; } return WrapperSupervisorPtrToManaged(wsPtr); } internal static void SetWrapperSupervisor(IntPtr eo, Efl.Eo.WrapperSupervisor ws) { GCHandle gch = GCHandle.Alloc(ws); Efl.Eo.Globals.efl_mono_wrapper_supervisor_set(eo, GCHandle.ToIntPtr(gch)); } internal static void free_dict_values(Dictionary dict) { foreach (IntPtr ptr in dict.Values) { Eina.MemoryNative.Free(ptr); } } internal static void free_stringshare_values(Dictionary dict) { foreach (IntPtr ptr in dict.Values) { Eina.NativeMethods.eina_stringshare_del(ptr); } } internal static void free_gchandle(IntPtr ptr) { GCHandle handle = GCHandle.FromIntPtr(ptr); handle.Free(); } internal static System.Threading.Tasks.Task WrapAsync(Eina.Future future, CancellationToken token) { // Creates a task that will wait for SetResult for completion. // TaskCompletionSource is used to create tasks for 'external' Task sources. var tcs = new System.Threading.Tasks.TaskCompletionSource(); // Flag to be passed to the cancell callback bool fulfilled = false; future.Then((Eina.Value received) => { lock (future) { // Convert an failed Future to a failed Task. if (received.GetValueType() == Eina.ValueType.Error) { Eina.Error err; received.Get(out err); if (err == Eina.Error.ECANCELED) { tcs.SetCanceled(); } else { tcs.TrySetException(new Efl.FutureException(err)); } } else { // Async receiver methods may consume the value C# wrapper, like when awaiting in the start of an // using block. In order to continue to forward the value correctly to the next futures // in the chain, we give the Async wrapper a copy of the received wrapper. tcs.SetResult(new Eina.Value(received)); } fulfilled = true; return received; } }); // Callback to be called when the token is cancelled. token.Register(() => { lock (future) { // Will trigger the Then callback above with an Eina.Error if (!fulfilled) { future.Cancel(); } } }); return tcs.Task; } /// Returns whether the given type was generated by eolian-mono /// The type to check. /// True if generated by eolian-mono. False otherwise. private static bool IsGeneratedClass(System.Type managedType) { return GetNativeClass(managedType) != null; } /// Creates a new wrapper for the given Eo id. /// /// If the Eo have a WrapperSupervisor, it returns the C# instance handle stored in its /// WrapperSupervisor. otherwise, we use reflection to get the correct C# type to re-wrap it. /// /// /// The Eo id to be wrapped. /// Whether we should increase the refcount of the Eo instance. /// The C# wrapper for this instance. internal static Efl.Eo.IWrapper CreateWrapperFor(System.IntPtr handle, bool shouldIncRef=true) { if (handle == IntPtr.Zero) { return null; } Efl.Eo.Globals.efl_ref(handle); try { var ws = Efl.Eo.Globals.GetWrapperSupervisor(handle); if (ws != null && ws.Target != null) { if (!shouldIncRef) { Efl.Eo.Globals.efl_unref(handle); } return ws.Target; } IntPtr eoKlass = efl_class_get(handle); if (eoKlass == IntPtr.Zero) { throw new InvalidOperationException($"Can't get Eo class for object handle 0x{handle.ToInt64():x}"); } var managedType = ClassRegister.GetManagedType(eoKlass); if (managedType == null) { IntPtr nativeName = efl_class_name_get(eoKlass); var name = Eina.StringConversion.NativeUtf8ToManagedString(nativeName); throw new InvalidOperationException($"Can't get Managed class for object handle 0x{handle.ToInt64():x} with native class [{name}]"); } Debug.Assert(IsGeneratedClass(managedType)); System.Reflection.ConstructorInfo constructor = null; try { var flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; constructor = managedType.GetConstructor(flags, null, new Type[1] { typeof(WrappingHandle) }, null); } catch (InvalidOperationException) { throw new InvalidOperationException($"Can't get constructor for type {managedType}"); } WrappingHandle wh = new WrappingHandle(handle); var ret = (Efl.Eo.IWrapper) constructor.Invoke(new object[1] { wh }); if (ret == null) { throw new InvalidOperationException($"Can't construct type {managedType} from IntPtr handle"); } if (shouldIncRef) { Efl.Eo.Globals.efl_ref(handle); } return ret; } finally { Efl.Eo.Globals.efl_unref(handle); } } private static Efl.FreeWrapperSupervisorCb FreeWrapperSupervisorCallbackDelegate = new Efl.FreeWrapperSupervisorCb(FreeWrapperSupervisorCallback); internal static void FreeWrapperSupervisorCallback(IntPtr eo) { try { var wsPtr = Efl.Eo.Globals.efl_mono_wrapper_supervisor_get(eo); if (wsPtr == IntPtr.Zero) { Eina.Log.Error($"Invalid wrapper supervisor [Eo pointer: {eo.ToInt64():x}]"); return; } Efl.Eo.Globals.efl_mono_wrapper_supervisor_set(eo, IntPtr.Zero); GCHandle gch = GCHandle.FromIntPtr(wsPtr); var ws = (Efl.Eo.WrapperSupervisor) gch.Target; foreach (var item in ws.EoEvents) { if (!efl_event_callback_del(eo, item.Key.desc, item.Value.evtCallerPtr, wsPtr)) { Eina.Log.Error($"Failed to remove event proxy for event {item.Key.desc} [eo: {eo.ToInt64():x}; cb: {item.Value.evtCallerPtr.ToInt64():x}]"); } } // Free the native eo Efl.Eo.Globals.efl_unref(eo); // now the WrapperSupervisor can be collected, and so its member: // - the event dictionary // - and the EoWrapper if it is still pinned gch.Free(); } catch (Exception e) { Eina.Log.Error(e.ToString()); Eina.Error.Set(Eina.Error.UNHANDLED_EXCEPTION); } } internal static void SetNativeDisposeCallbacks() { efl_mono_wrapper_supervisor_callbacks_set(FreeWrapperSupervisorCallbackDelegate); } internal static void ThreadSafeFreeCbExec(Eina.Callbacks.EinaFreeCb cbFreeCb, IntPtr cbData) { Eina.Callbacks.EinaFreeCb cb = (IntPtr gcHandlePtr) => { cbFreeCb(cbData); GCHandle gcHandle = GCHandle.FromIntPtr(gcHandlePtr); gcHandle.Free(); }; Monitor.Enter(Efl.All.InitLock); if (Efl.All.MainLoopInitialized) { IntPtr cbPtr = Marshal.GetFunctionPointerForDelegate(cb); var handle = GCHandle.Alloc(cb); var handlePtr = GCHandle.ToIntPtr(handle); efl_mono_thread_safe_free_cb_exec(cbPtr, handlePtr); } Monitor.Exit(Efl.All.InitLock); } internal static IEnumerable AccessorToIEnumerable(IntPtr accessor) { if (accessor == IntPtr.Zero) throw new ArgumentException("accessor is null", nameof(accessor)); IntPtr data = IntPtr.Zero; uint position = 0; while (Eina.AccessorNativeFunctions.eina_accessor_data_get(accessor, position, out data)) { yield return Eina.TraitFunctions.NativeToManaged(data); position += 1; } } internal static IntPtr IEnumerableToAccessor(IEnumerable enumerable, bool isMoved) { if (enumerable == null) { throw new ArgumentException("enumerable is null", nameof(enumerable)); } // If we are a wrapper around an existing Eina.Accessor, we can just forward // it and avoid unnecessary copying in non-owning transfers. var wrappedAccessor = enumerable as Eina.Accessor; if (wrappedAccessor != null && !isMoved) { return wrappedAccessor.Handle; } // TODO: Check if we're either an Eina.List or Eina.Collection? // We could just rewrap their native accessors IntPtr[] intPtrs = new IntPtr[enumerable.Count()]; int i = 0; foreach (T data in enumerable) { intPtrs[i] = Eina.TraitFunctions.ManagedToNativeAlloc(data); i++; } GCHandle pinnedArray = GCHandle.Alloc(intPtrs, GCHandleType.Pinned); IntPtr nativeAccessor = IntPtr.Zero; if (isMoved) { // We need a custom accessor that would unpin the data when freed. nativeAccessor = Eina.AccessorNativeFunctions.eina_mono_owned_carray_length_accessor_new(pinnedArray.AddrOfPinnedObject(), (uint)IntPtr.Size, (uint)intPtrs.Length, free_gchandle, GCHandle.ToIntPtr(pinnedArray)); } else { // FIXME: Leaking.... nativeAccessor = Eina.AccessorNativeFunctions.eina_carray_length_accessor_new(pinnedArray.AddrOfPinnedObject(), (uint)(IntPtr.Size), (uint)intPtrs.Length); } if (nativeAccessor == IntPtr.Zero) { pinnedArray.Free(); throw new InvalidOperationException("Failed to get native accessor for the given container"); } return nativeAccessor; } internal static IEnumerable IteratorToIEnumerable(IntPtr iterator) { if (iterator == IntPtr.Zero) throw new ArgumentException("iterator is null", nameof(iterator)); while (Eina.IteratorNativeFunctions.eina_iterator_next(iterator, out IntPtr data)) { yield return Eina.TraitFunctions.NativeToManaged(data); } } internal static IntPtr IEnumerableToIterator(IEnumerable enumerable, bool isMoved) { if (enumerable == null) { throw new ArgumentException("enumerable is null", nameof(enumerable)); } // If we are a wrapper around an existing Eina.Iterator, we can just forward // it and avoid unnecessary copying in non-owning transfers. var wrappedIterator = enumerable as Eina.Iterator; if (wrappedIterator != null && !isMoved) { return wrappedIterator.Handle; } var list = new List(); foreach (T data in enumerable) { list.Add(Eina.TraitFunctions.ManagedToNativeAlloc(data)); } IntPtr[] dataArray = list.ToArray(); GCHandle pinnedArray = GCHandle.Alloc(dataArray, GCHandleType.Pinned); IntPtr ret = Eina.IteratorNativeFunctions.eina_carray_length_iterator_new(pinnedArray.AddrOfPinnedObject(), (uint)(IntPtr.Size), (uint)dataArray.Length); if (!isMoved) { // FIXME Need to free ret and unpin pinnedArray in the future. } return ret; } - internal static IEnumerable ListToIEnumerable(IntPtr list) + internal static IList NativeListToIList(IntPtr nativeList) { - if (list == IntPtr.Zero) - throw new ArgumentException("list is null", nameof(list)); + if (nativeList == IntPtr.Zero) + throw new ArgumentException("nativeList is null", nameof(nativeList)); IntPtr l; - - for (l = list; l != IntPtr.Zero; l = Eina.ListNativeFunctions.eina_list_next_custom_export_mono(l)) + List list = new List(); + for (l = nativeList; l != IntPtr.Zero; l = Eina.ListNativeFunctions.eina_list_next_custom_export_mono(l)) { - yield return Eina.TraitFunctions.NativeToManaged(Eina.ListNativeFunctions.eina_list_data_get_custom_export_mono(l)); + list.Add(Eina.TraitFunctions.NativeToManaged(Eina.ListNativeFunctions.eina_list_data_get_custom_export_mono(l))); } + return list; } - internal static IntPtr IEnumerableToList(IEnumerable enumerable) + internal static IntPtr IListToNativeList(IList list, bool isMoved) { - if (enumerable == null) - throw new ArgumentException("enumerable is null", nameof(enumerable)); + if (list == null) + throw new ArgumentException("list is null", nameof(list)); - IntPtr list = IntPtr.Zero; - foreach (T data in enumerable) + // If we are a wrapper around an existing Eina.List, we can just forward + // it and avoid unnecessary copying in non-owning transfers. + var wrappedList = list as Eina.List; + + if (wrappedList != null && !isMoved) + { + return wrappedList.Handle; + } + + IntPtr nativeList = IntPtr.Zero; + foreach (T data in list) { - list = Eina.ListNativeFunctions.eina_list_append(list, Eina.TraitFunctions.ManagedToNativeAlloc(data)); + nativeList = Eina.ListNativeFunctions.eina_list_append(nativeList, Eina.TraitFunctions.ManagedToNativeAlloc(data)); //FIXME: need to free } + + if (!isMoved) + { + // FIXME Need to free ret and unpin pinnedArray in the future. + } + + return nativeList; + } + + internal static IList NativeArrayToIList(IntPtr nativeArray) + { + if (nativeArray == IntPtr.Zero) + throw new ArgumentException("nativeArray is null", nameof(nativeArray)); + + List list = new List(); + UpdateListFromNativeArray(list, nativeArray); + // FIXME need to free `list` if the returned list is not @moved return list; } + internal static IntPtr IListToNativeArray(IList list, bool isMoved) + { + if (list == null) + throw new ArgumentException("list is null", nameof(list)); + + // If we are a wrapper around an existing Eina.Array, we can just forward + // it and avoid unnecessary copying in non-owning transfers. + var wrappedArray = list as Eina.Array; + + if (wrappedArray != null && !isMoved) + { + return wrappedArray.Handle; + } + + IntPtr nativeArray = Eina.ArrayNativeFunctions.eina_array_new(4); + foreach (T data in list) + { + Eina.ArrayNativeFunctions.eina_array_push_custom_export_mono(nativeArray, Eina.TraitFunctions.ManagedToNativeAlloc(data)); //FIXME: need to free + } + + if (!isMoved) + { + // FIXME Need to free ret and unpin pinnedArray in the future. + } + + return nativeArray; + } + + internal static void UpdateListFromNativeArray(IList list, IntPtr nativeArray) + { + // Do not update if list Handle is same to nativeArray. They already updated in native code. + var wrappedArray = list as Eina.Array; + if (wrappedArray != null && wrappedArray.Handle == nativeArray) + return; + + list.Clear(); + if (nativeArray == IntPtr.Zero) + { + return; + } + + uint count = Eina.ArrayNativeFunctions.eina_array_count_custom_export_mono(nativeArray); + for (uint i = 0; i < count; i++) + { + list.Add(Eina.TraitFunctions.NativeToManaged(Eina.ArrayNativeFunctions.eina_array_data_get_custom_export_mono(nativeArray, i))); + } + } } // Globals /// /// Internal struct used by the binding to pass the native handle pointer /// to the managed object wrapping constructor. /// Internal usage only: do not use this class in inherited classes. /// internal struct WrappingHandle { public WrappingHandle(IntPtr h) { NativeHandle = h; } public IntPtr NativeHandle { get; private set; } } /// /// Manage the initialization and cleanup for the Efl object subsystem. /// Since EFL 1.24. /// public static class Config { /// /// Initialize the EFL object subsystem. /// Since EFL 1.24. /// public static void Init() { Globals.efl_object_init(); Globals.SetNativeDisposeCallbacks(); } /// /// Shutdown the EFL object subsystem. /// Since EFL 1.24. /// public static void Shutdown() { Globals.efl_object_shutdown(); } } [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Interface, AllowMultiple = false, Inherited = false) ] abstract class NativeClass : System.Attribute { internal abstract IntPtr GetEflClass(); internal abstract System.Collections.Generic.List GetEoOps(System.Type type, bool includeInherited); } /// Attribute for private native classes. /// /// For internal usage by generated code only. class PrivateNativeClass : NativeClass { internal override IntPtr GetEflClass() { return IntPtr.Zero; } internal override System.Collections.Generic.List GetEoOps(System.Type type, bool includeInherited) { return null; } } [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Interface | System.AttributeTargets.Enum | System.AttributeTargets.Delegate | System.AttributeTargets.Struct, AllowMultiple = false, Inherited = false) ] internal class BindingEntityAttribute: System.Attribute { public static bool IsBindingEntity(System.Type t) { return Attribute.GetCustomAttribute(t, typeof(BindingEntityAttribute), false) != null; } } public interface IWrapper { /// Pointer to internal Eo instance. IntPtr NativeHandle { get; } /// Pointer to internal Eo class. IntPtr NativeClass { get; } } internal static class ClassRegister { internal static System.Type GetManagedType(IntPtr klass) { System.Type t; if (Efl.Eo.ClassRegister.typeFromKlass.TryGetValue(klass, out t)) { return t; } // If it isn't on the dictionary then it is a Native binding class IntPtr namePtr = Efl.Eo.Globals.efl_class_name_get(klass); if (namePtr == IntPtr.Zero) { throw new System.InvalidOperationException($"Could not get Native class name. Handle: {klass}"); } #pragma warning disable CA1307 string name = Eina.StringConversion.NativeUtf8ToManagedString(namePtr) .Replace("_", ""); // Convert Efl C name to C# name #pragma warning restore CA1307 // Check if this is an internal implementation of an abstract class var abstract_impl_suffix = "Realized"; if (name.EndsWith(abstract_impl_suffix, StringComparison.Ordinal)) { name = name.Substring(0, name.Length - abstract_impl_suffix.Length); var lastDot = name.LastIndexOf(".", StringComparison.Ordinal); var klassName = name.Substring(lastDot + 1); name += "+" + klassName + abstract_impl_suffix; // '+' is the separator for nested classes } // When converting to managed, interfaces and mixins gets the 'I' prefix. var klass_type = Efl.Eo.Globals.efl_class_type_get(klass); if (klass_type == Efl.Eo.Globals.EflClassType.Interface || klass_type == Efl.Eo.Globals.EflClassType.Mixin) { var pos = name.LastIndexOf(".", StringComparison.Ordinal); name = name.Insert(pos + 1, "I"); // -1 if not found, inserts at 0 normally } var curr_asm = typeof(IWrapper).Assembly; t = curr_asm.GetType(name); if (t == null) { foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) { if (assembly == curr_asm) { continue; } t = assembly.GetType(name); if (t != null) { break; } } if (t == null) { return typeof(Efl.ObjectRealized); } } AddToKlassTypeBiDictionary(klass, t); // Cache it in the dictionary return t; } internal static IntPtr GetKlass(System.Type objectType) { IntPtr klass; if (klassFromType.TryGetValue(objectType, out klass)) { return klass; } // Check if it is a Native binding class klass = GetNativeKlassPtr(objectType); if (klass != IntPtr.Zero) { // Add to the dictionary cache AddToKlassTypeBiDictionary(klass, objectType); return klass; } // Unregistered Inherited class, let's register it IntPtr baseKlass = GetNativeBaseKlassPtr(objectType); if (baseKlass == IntPtr.Zero) { throw new System.InvalidOperationException($"Could not get base C# binding class for Inherited type: {objectType.FullName}"); } return RegisterKlass(baseKlass, objectType); } internal static IntPtr GetInheritKlassOrRegister(IntPtr baseKlass, System.Type objectType) { IntPtr klass; if (klassFromType.TryGetValue(objectType, out klass)) { return klass; } return RegisterKlass(baseKlass, objectType); } private static IntPtr RegisterKlass(IntPtr baseKlass, System.Type objectType) { lock (klassAllocLock) { IntPtr newKlass = Efl.Eo.Globals.register_class(objectType.FullName, baseKlass, objectType); if (newKlass == IntPtr.Zero) { throw new System.InvalidOperationException($"Failed to register class '{objectType.FullName}'"); } AddToKlassTypeBiDictionary(newKlass, objectType); return newKlass; } } private static IntPtr GetNativeBaseKlassPtr(System.Type objectType) { for (System.Type t = objectType.BaseType; t != null; t = t.BaseType) { var ptr = GetNativeKlassPtr(t); if (ptr != IntPtr.Zero) { return ptr; } } throw new System.InvalidOperationException($"Class '{objectType.FullName}' is not an Efl object"); } private static IntPtr GetNativeKlassPtr(System.Type objectType) { if (objectType == null) { return IntPtr.Zero; } if (objectType.IsInterface) { // Try to get the *Concrete class var assembly = objectType.Assembly; objectType = assembly.GetType(objectType.FullName + "Concrete"); if (objectType == null) { return IntPtr.Zero; } } var method = objectType.GetMethod("GetEflClassStatic", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic); if (method == null) { return IntPtr.Zero; } return (IntPtr)(method.Invoke(null, null)); } internal static void AddToKlassTypeBiDictionary(IntPtr klassPtr, System.Type objectType) { klassFromType[objectType] = klassPtr; typeFromKlass[klassPtr] = objectType; } internal static readonly System.Collections.Concurrent.ConcurrentDictionary klassFromType = new System.Collections.Concurrent.ConcurrentDictionary(); internal static readonly System.Collections.Concurrent.ConcurrentDictionary typeFromKlass = new System.Collections.Concurrent.ConcurrentDictionary(); private static readonly object klassAllocLock = new object(); } /// Custom marshaler for Eo objects that do not move ownership between native and managed code. /// /// For internal usage by generated code. /// /// Since EFL 1.24. /// class MarshalEoNoMove : ICustomMarshaler { private static ICustomMarshaler instance = new MarshalEoNoMove(); /// /// Gets an instance of this marshaler. /// Since EFL 1.24. /// /// Cookie to identify the marshaler. Unused. /// The marshaler instance. [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", Justification = "The same marshaler is used for all cases.")] public static ICustomMarshaler GetInstance(string cookie) => instance; /// /// Clean ups the managed data. /// Since EFL 1.24. /// /// The object to be cleaned. public void CleanUpManagedData(object ManagedObj) { } /// /// Clean ups the native data if it was created. /// Since EFL 1.24. /// /// The native data to be cleaned. public void CleanUpNativeData(IntPtr pNativeData) { } /// /// Gets the native data size. /// Since EFL 1.24. /// /// The data size in bytes. public int GetNativeDataSize() => -1; /// /// Marshals the given managed object to its native handle. /// As this marshaler does not move the reference, the managed code /// can keep its reference and does not need to incref. /// Since EFL 1.24. /// /// The object to be marshalled. /// The marshalled native data. public IntPtr MarshalManagedToNative(object ManagedObj) { if (ManagedObj == null) { return IntPtr.Zero; } IWrapper wrapper = ManagedObj as IWrapper; if (wrapper == null) { throw new ArgumentException("Managed object to be marshalled must be an IWrapper."); } return wrapper.NativeHandle; } /// /// Marshals the given native pointer into a managed object. /// The given native object has its reference count incremented in order to make /// the C# wrapper capable of accessing it while the wrapper is alive. /// Since EFL 1.24. /// /// The native pointer to the EO object. /// The managed wrapper for the given native object. public object MarshalNativeToManaged(IntPtr pNativeData) { return Efl.Eo.Globals.CreateWrapperFor(pNativeData, shouldIncRef : true); } } /// Custom marshaler for Eo objects that move ownership between native and managed code. /// /// For internal usage by generated code. /// /// Since EFL 1.24. /// class MarshalEoMove : ICustomMarshaler { private static ICustomMarshaler instance = new MarshalEoMove(); /// /// Gets an instance of this marshaler. /// Since EFL 1.24. /// /// Cookie to identify the marshaler. Unused. /// The marshaler instance. [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", Justification = "The same marshaler is used for all cases.")] public static ICustomMarshaler GetInstance(string cookie) => instance; /// /// Clean ups the managed data. /// Since EFL 1.24. /// /// The object to be cleaned. public void CleanUpManagedData(object ManagedObj) { } /// /// Clean ups the native data if it was created. /// Since EFL 1.24. /// /// The native data to be cleaned. public void CleanUpNativeData(IntPtr pNativeData) { } /// /// Gets the native data size. /// Since EFL 1.24. /// /// The data size in bytes. public int GetNativeDataSize() => -1; /// /// Marshals the given managed object to its native handle. /// The wrapper given as parameter needs to keep a reference to the native /// object, so the EO has its refcount incremented. /// Since EFL 1.24. /// /// The object to be marshalled. /// The marshalled native data. public IntPtr MarshalManagedToNative(object ManagedObj) { if (ManagedObj == null) { return IntPtr.Zero; } IWrapper wrapper = ManagedObj as IWrapper; if (wrapper == null) { throw new ArgumentException("Managed object to be marshalled must be an IWrapper."); } return Efl.Eo.Globals.efl_ref(wrapper.NativeHandle); } /// /// Marshals the given native pointer into a managed object. /// The returned wrapper "steals" the reference to keep it alive. /// Since EFL 1.24. /// /// The native pointer to the EO object. /// The managed wrapper for the given native object. public object MarshalNativeToManaged(IntPtr pNativeData) { return Efl.Eo.Globals.CreateWrapperFor(pNativeData, shouldIncRef : false); } } ///Marshals between System.Type instances and Eo classes (IntPtrs). class MarshalEflClass : ICustomMarshaler { internal static ICustomMarshaler GetInstance(string cookie) { Eina.Log.Debug("MarshalEflClass.GetInstance cookie " + cookie); return new MarshalEflClass(); } public void CleanUpManagedData(object ManagedObj) { } public void CleanUpNativeData(IntPtr pNativeData) { } public int GetNativeDataSize() { Eina.Log.Debug("MarshalEflClass.GetNativeDataSize"); return 0; } public IntPtr MarshalManagedToNative(object ManagedObj) { Eina.Log.Debug("MarshalEflClass.MarshallManagedToNative"); if (ManagedObj == null) { return IntPtr.Zero; } var t = (System.Type)ManagedObj; return Efl.Eo.ClassRegister.GetKlass(t); } public object MarshalNativeToManaged(IntPtr pNativeData) { Eina.Log.Debug("MarshalEflClass.MarshalNativeToManaged"); if (pNativeData == IntPtr.Zero) { return null; } return Efl.Eo.ClassRegister.GetManagedType(pNativeData); } } class StringPassOwnershipMarshaler : ICustomMarshaler { public object MarshalNativeToManaged(IntPtr pNativeData) { var ret = Eina.StringConversion.NativeUtf8ToManagedString(pNativeData); Eina.MemoryNative.Free(pNativeData); return ret; } public IntPtr MarshalManagedToNative(object managedObj) { return Eina.MemoryNative.StrDup((string)managedObj); } public void CleanUpNativeData(IntPtr pNativeData) { // No need to cleanup. C will take care of it. } public void CleanUpManagedData(object managedObj) { } public int GetNativeDataSize() { return -1; } internal static ICustomMarshaler GetInstance(string cookie) { if (marshaler == null) { marshaler = new StringPassOwnershipMarshaler(); } return marshaler; } static private StringPassOwnershipMarshaler marshaler; } class StringKeepOwnershipMarshaler: ICustomMarshaler { public object MarshalNativeToManaged(IntPtr pNativeData) { return Eina.StringConversion.NativeUtf8ToManagedString(pNativeData); } public IntPtr MarshalManagedToNative(object managedObj) { return Eina.StringConversion.ManagedStringToNativeUtf8Alloc((string)managedObj); } public void CleanUpNativeData(IntPtr pNativeData) { // No need to free. The Native side will keep the ownership. } public void CleanUpManagedData(object managedObj) { } public int GetNativeDataSize() { return -1; } internal static ICustomMarshaler GetInstance(string cookie) { if (marshaler == null) { marshaler = new StringKeepOwnershipMarshaler(); } return marshaler; } static private StringKeepOwnershipMarshaler marshaler; } class StringsharePassOwnershipMarshaler : ICustomMarshaler { public object MarshalNativeToManaged(IntPtr pNativeData) { var ret = Eina.StringConversion.NativeUtf8ToManagedString(pNativeData); Eina.NativeMethods.eina_stringshare_del(pNativeData); return ret; } public IntPtr MarshalManagedToNative(object managedObj) { return Eina.MemoryNative.AddStringshare((string)managedObj); } public void CleanUpNativeData(IntPtr pNativeData) { // No need to free as it's for own() parameters. } public void CleanUpManagedData(object managedObj) { } public int GetNativeDataSize() { return -1; } internal static ICustomMarshaler GetInstance(string cookie) { if (marshaler == null) { marshaler = new StringsharePassOwnershipMarshaler(); } return marshaler; } static private StringsharePassOwnershipMarshaler marshaler; } class StringshareKeepOwnershipMarshaler : ICustomMarshaler { public object MarshalNativeToManaged(IntPtr pNativeData) { return Eina.StringConversion.NativeUtf8ToManagedString(pNativeData); } public IntPtr MarshalManagedToNative(object managedObj) { return Eina.MemoryNative.AddStringshare((string)managedObj); } public void CleanUpNativeData(IntPtr pNativeData) { // No need to free, as the native side will keep ownership. } public void CleanUpManagedData(object managedObj) { } public int GetNativeDataSize() { return -1; } internal static ICustomMarshaler GetInstance(string cookie) { if (marshaler == null) { marshaler = new StringshareKeepOwnershipMarshaler(); } return marshaler; } static private StringshareKeepOwnershipMarshaler marshaler; } class StrbufPassOwnershipMarshaler : ICustomMarshaler { public object MarshalNativeToManaged(IntPtr pNativeData) { return new Eina.Strbuf(pNativeData, Eina.Ownership.Managed); } public IntPtr MarshalManagedToNative(object managedObj) { Eina.Strbuf buf = managedObj as Eina.Strbuf; buf.ReleaseOwnership(); return buf.Handle; } public void CleanUpNativeData(IntPtr pNativeData) { // No need to cleanup. C will take care of it. } public void CleanUpManagedData(object managedObj) { } public int GetNativeDataSize() { return -1; } internal static ICustomMarshaler GetInstance(string cookie) { if (marshaler == null) { marshaler = new StrbufPassOwnershipMarshaler(); } return marshaler; } static private StrbufPassOwnershipMarshaler marshaler; } class StrbufKeepOwnershipMarshaler: ICustomMarshaler { public object MarshalNativeToManaged(IntPtr pNativeData) { return new Eina.Strbuf(pNativeData, Eina.Ownership.Unmanaged); } public IntPtr MarshalManagedToNative(object managedObj) { Eina.Strbuf buf = managedObj as Eina.Strbuf; return buf.Handle; } public void CleanUpNativeData(IntPtr pNativeData) { // No need to free. The Native side will keep the ownership. } public void CleanUpManagedData(object managedObj) { } public int GetNativeDataSize() { return -1; } internal static ICustomMarshaler GetInstance(string cookie) { if (marshaler == null) { marshaler = new StrbufKeepOwnershipMarshaler(); } return marshaler; } static private StrbufKeepOwnershipMarshaler marshaler; } } // namespace eo /// General exception for errors inside the binding. public class EflException : Exception { /// /// Default Constructor. /// Since EFL 1.23. /// public EflException() { } /// Create a new EflException with the given message. public EflException(string message) : base(message) { } /// /// Create a new EflException with the given message and inner exception. /// Since EFL 1.23. /// /// The message of the exception. /// The inner exception. public EflException(string message, Exception innerException) : base(message, innerException) { } } /// Exception to be raised when a Task fails due to a failed Eina.Future. public class FutureException : EflException { /// The error code returned by the failed Eina.Future. public Eina.Error Error { get; private set; } /// /// Default constructor. /// Since EFL 1.23. /// public FutureException() : this(Eina.Error.UNHANDLED_EXCEPTION) { } /// /// Construct a new exception from the /// with a given message /// Since EFL 1.23. /// /// The message of the exception. public FutureException(string message) : this(Eina.Error.UNHANDLED_EXCEPTION, message) { } /// /// Construct a new exception from the /// with a given message and inner exception. /// Since EFL 1.23. /// /// The message of the exception. /// The inner exception. public FutureException(string message, Exception innerException) : this(Eina.Error.UNHANDLED_EXCEPTION, message, innerException) { } /// /// Construct a new exception from the /// with a given error. /// Since EFL 1.23. /// /// The error of the exception.. public FutureException(Eina.Error error) : this(error, "Future failed.") { } /// /// Construct a new exception from the /// with a given error and message. /// Since EFL 1.23. /// /// The error of the exception.. /// The message of the exception. public FutureException(Eina.Error error, string message) : this(error, message, null) { } /// /// Construct a new exception from the /// with a given error, message and innerException. /// Since EFL 1.23. /// /// The error of the exception.. /// The message of the exception. /// The inner exception. public FutureException(Eina.Error error, string message, Exception innerException) : base(message, innerException) => Error = error; } } // namespace efl diff --git a/src/tests/efl_mono/Eina.cs b/src/tests/efl_mono/Eina.cs index bee62169bb..461dee6759 100644 --- a/src/tests/efl_mono/Eina.cs +++ b/src/tests/efl_mono/Eina.cs @@ -1,4649 +1,4550 @@ /* * Copyright 2019 by its authors. See AUTHORS. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using System.Runtime.CompilerServices; using Eina; using EinaTestData; using static EinaTestData.BaseData; namespace TestSuite { #if EFL_BETA class TestEinaBinbuf { private static readonly byte[] test_string = System.Text.Encoding.UTF8.GetBytes("0123456789ABCDEF"); private static readonly byte[] base_seq = BaseSequence.Values(); public static void eina_binbuf_default() { var binbuf = new Eina.Binbuf(); Test.Assert(binbuf.Handle != IntPtr.Zero); Test.Assert(binbuf.GetBytes().SequenceEqual(Array.Empty())); binbuf.Dispose(); } public static void eina_binbuf_bytes() { var binbuf = new Eina.Binbuf(test_string); Test.Assert(binbuf.Handle != IntPtr.Zero); byte[] cmp = binbuf.GetBytes(); Test.Assert(cmp != test_string); Test.Assert(cmp.SequenceEqual(test_string)); binbuf.Dispose(); } public static void eina_binbuf_bytes_length() { var binbuf = new Eina.Binbuf(test_string, 7); Test.Assert(binbuf.Handle != IntPtr.Zero); byte[] cmp = binbuf.GetBytes(); byte[] expected = System.Text.Encoding.UTF8.GetBytes("0123456"); Test.Assert(cmp != test_string); Test.Assert(cmp != expected); Test.Assert(cmp.SequenceEqual(expected)); binbuf.Dispose(); } public static void eina_binbuf_copy_ctor() { var binbuf = new Eina.Binbuf(test_string); Test.Assert(binbuf.Handle != IntPtr.Zero); var binbuf2 = new Eina.Binbuf(binbuf); Test.Assert(binbuf2.Handle != IntPtr.Zero && binbuf.Handle != binbuf2.Handle); byte[] cmp = binbuf.GetBytes(); byte[] cmp2 = binbuf2.GetBytes(); Test.Assert(cmp != cmp2); Test.Assert(cmp.SequenceEqual(cmp2)); binbuf2.Dispose(); binbuf.Dispose(); } public static void free_get_null_handle() { var binbuf = new Eina.Binbuf(test_string); Test.Assert(binbuf.Handle != IntPtr.Zero); binbuf.Free(); Test.Assert(binbuf.Handle == IntPtr.Zero); binbuf.Dispose(); } public static void reset_get_empty_string() { var binbuf = new Eina.Binbuf(test_string); Test.Assert(binbuf.Handle != IntPtr.Zero); byte[] cmp = binbuf.GetBytes(); Test.Assert(cmp != test_string); Test.Assert(cmp.SequenceEqual(test_string)); binbuf.Reset(); Test.Assert(binbuf.Handle != IntPtr.Zero); Test.Assert(binbuf.GetBytes().SequenceEqual(Array.Empty())); binbuf.Dispose(); } public static void append_bytes() { var binbuf = new Eina.Binbuf(); binbuf.Append(test_string); byte[] cmp = binbuf.GetBytes(); Test.Assert(cmp != test_string); Test.Assert(cmp.SequenceEqual(test_string)); binbuf.Dispose(); } public static void append_bytes_length() { var binbuf = new Eina.Binbuf(); binbuf.Append(test_string, 7); byte[] cmp = binbuf.GetBytes(); byte[] expected = System.Text.Encoding.UTF8.GetBytes("0123456"); Test.Assert(cmp != expected); Test.Assert(cmp.SequenceEqual(expected)); binbuf.Dispose(); } public static void append_binbuf() { var binbuf = new Eina.Binbuf(); Test.Assert(binbuf.GetBytes().SequenceEqual(Array.Empty())); var binbuf2 = new Eina.Binbuf(test_string); binbuf.Append(binbuf2); byte[] cmp = binbuf.GetBytes(); byte[] cmp2 = binbuf2.GetBytes(); Test.Assert(cmp != cmp2); Test.Assert(cmp2.SequenceEqual(cmp)); Test.Assert(cmp2.SequenceEqual(test_string)); binbuf2.Dispose(); binbuf.Dispose(); } public static void append_char() { var binbuf = new Eina.Binbuf(); binbuf.Append((byte) 0); binbuf.Append((byte) 12); binbuf.Append((byte) 42); byte[] cmp = binbuf.GetBytes(); Test.Assert(cmp.Length == 3); Test.Assert(cmp[0] == 0 && cmp[1] == 12 && cmp[2] == 42); binbuf.Dispose(); } public static void remove() { var binbuf = new Eina.Binbuf(test_string); Test.Assert(binbuf.GetBytes().SequenceEqual(test_string)); binbuf.Remove(2, 9); Test.Assert(binbuf.Handle != IntPtr.Zero); byte[] expected = System.Text.Encoding.UTF8.GetBytes("019ABCDEF"); Test.Assert(binbuf.GetBytes().SequenceEqual(expected)); binbuf.Dispose(); } public static void get_string_native() { var binbuf = new Eina.Binbuf(test_string); Test.Assert(binbuf.GetBytes().SequenceEqual(test_string)); Test.Assert(binbuf.GetStringNative() != IntPtr.Zero); binbuf.Dispose(); } public static void binbuf_free_string() { var binbuf = new Eina.Binbuf(test_string); Test.Assert(binbuf.GetBytes().SequenceEqual(test_string)); binbuf.FreeString(); Test.Assert(binbuf.Handle != IntPtr.Zero); Test.Assert(binbuf.GetBytes().SequenceEqual(Array.Empty())); binbuf.Dispose(); } public static void binbuf_length() { var binbuf = new Eina.Binbuf(test_string, 6); Test.Assert(binbuf.Length == 6); Test.Assert(binbuf.GetBytes().Length == 6); binbuf.Dispose(); } public static void test_eina_binbuf_in() { var t = new Dummy.TestObject(); var binbuf = new Eina.Binbuf(base_seq, (uint)base_seq.Length); Test.Assert(t.EinaBinbufIn(binbuf)); Test.Assert(binbuf.Own); Test.Assert(binbuf.GetBytes().SequenceEqual( new byte[]{43, 42, 0x0, 0x2A, 0x42, 33})); binbuf.Dispose(); Test.Assert(binbuf.Handle == IntPtr.Zero); t.Dispose(); } public static void test_eina_binbuf_in_own() { var t = new Dummy.TestObject(); var binbuf = new Eina.Binbuf(base_seq, (uint)base_seq.Length); Test.Assert(t.EinaBinbufInOwn(binbuf)); Test.Assert(!binbuf.Own); Test.Assert(binbuf.GetBytes().SequenceEqual( new byte[]{43, 42, 0x0, 0x2A, 0x42, 33})); binbuf.Dispose(); Test.Assert(binbuf.Handle == IntPtr.Zero); Test.Assert(t.CheckBinbufInOwn()); t.Dispose(); } public static void test_eina_binbuf_out() { var t = new Dummy.TestObject(); Eina.Binbuf binbuf; Test.Assert(t.EinaBinbufOut(out binbuf)); Test.Assert(!binbuf.Own); Test.Assert(binbuf.GetBytes().SequenceEqual(new byte[]{33})); binbuf.Reset(); Test.Assert(binbuf.Append(base_seq)); binbuf.Dispose(); Test.Assert(binbuf.Handle == IntPtr.Zero); Test.Assert(t.CheckBinbufOut()); t.Dispose(); } public static void test_eina_binbuf_out_own() { var t = new Dummy.TestObject(); Eina.Binbuf binbuf; Test.Assert(t.EinaBinbufOutOwn(out binbuf)); Test.Assert(binbuf.Own); Test.Assert(binbuf.GetBytes().SequenceEqual(new byte[]{33})); binbuf.Reset(); Test.Assert(binbuf.Append(base_seq)); binbuf.Dispose(); Test.Assert(binbuf.Handle == IntPtr.Zero); t.Dispose(); } public static void test_eina_binbuf_return() { var t = new Dummy.TestObject(); var binbuf = t.EinaBinbufReturn(); Test.Assert(!binbuf.Own); Test.Assert(binbuf.GetBytes().SequenceEqual(new byte[]{33})); binbuf.Reset(); Test.Assert(binbuf.Append(base_seq)); binbuf.Dispose(); Test.Assert(binbuf.Handle == IntPtr.Zero); Test.Assert(t.CheckBinbufReturn()); t.Dispose(); } public static void test_eina_binbuf_return_own() { var t = new Dummy.TestObject(); var binbuf = t.EinaBinbufReturnOwn(); Test.Assert(binbuf.Own); Test.Assert(binbuf.GetBytes().SequenceEqual(new byte[]{33})); binbuf.Reset(); Test.Assert(binbuf.Append(base_seq)); binbuf.Dispose(); Test.Assert(binbuf.Handle == IntPtr.Zero); t.Dispose(); } // // // Inherit // public static void test_inherit_eina_binbuf_in() { var t = new NativeInheritImpl(); var binbuf = new Eina.Binbuf(base_seq, (uint)base_seq.Length); Test.Assert(t.CallEinaBinbufIn(binbuf)); Test.Assert(t.binbuf_in_flag); Test.Assert(binbuf.Own); Test.Assert(binbuf.GetBytes().SequenceEqual( new byte[]{43, 42, 0x0, 0x2A, 0x42, 33})); binbuf.Dispose(); Test.Assert(binbuf.Handle == IntPtr.Zero); t.Dispose(); } public static void test_inherit_eina_binbuf_in_own() { var t = new NativeInheritImpl(); var binbuf = new Eina.Binbuf(base_seq, (uint)base_seq.Length); binbuf.Own = false; Test.Assert(t.CallEinaBinbufInOwn(binbuf)); Test.Assert(t.binbuf_in_own_flag); Test.Assert(binbuf.GetBytes().SequenceEqual( new byte[]{43, 42, 0x0, 0x2A, 0x42, 33})); binbuf.Dispose(); Test.Assert(binbuf.Handle == IntPtr.Zero); Test.Assert(t.binbuf_in_own_still_usable()); t.Dispose(); } public static void test_inherit_eina_binbuf_out() { var t = new NativeInheritImpl(); Eina.Binbuf binbuf = t.CallEinaBinbufOut(); Test.Assert(t.binbuf_out_flag); Test.Assert(binbuf.GetBytes().SequenceEqual(new byte[]{33})); binbuf.Reset(); Test.Assert(binbuf.Append(base_seq)); binbuf.Dispose(); Test.Assert(binbuf.Handle == IntPtr.Zero); Test.Assert(t.binbuf_out_still_usable()); t.Dispose(); } public static void test_inherit_eina_binbuf_out_own() { var t = new NativeInheritImpl(); Eina.Binbuf binbuf = t.CallEinaBinbufOutOwn(); Test.Assert(t.binbuf_out_own_flag); Test.Assert(binbuf.GetBytes().SequenceEqual(new byte[]{33})); binbuf.Reset(); Test.Assert(binbuf.Append(base_seq)); binbuf.Dispose(); Test.Assert(binbuf.Handle == IntPtr.Zero); Test.Assert(t.binbuf_out_own_no_longer_own()); t.Dispose(); } public static void test_inherit_eina_binbuf_return() { var t = new NativeInheritImpl(); var binbuf = t.CallEinaBinbufReturn(); Test.Assert(t.binbuf_return_flag); Test.Assert(binbuf.GetBytes().SequenceEqual(new byte[]{33})); binbuf.Reset(); Test.Assert(binbuf.Append(base_seq)); binbuf.Dispose(); Test.Assert(binbuf.Handle == IntPtr.Zero); Test.Assert(t.binbuf_return_still_usable()); t.Dispose(); } public static void test_inherit_eina_binbuf_return_own() { var t = new NativeInheritImpl(); var binbuf = t.CallEinaBinbufReturnOwn(); Test.Assert(t.binbuf_return_own_flag); Test.Assert(binbuf.GetBytes().SequenceEqual(new byte[]{33})); binbuf.Reset(); Test.Assert(binbuf.Append(base_seq)); binbuf.Dispose(); Test.Assert(binbuf.Handle == IntPtr.Zero); Test.Assert(t.binbuf_return_own_no_longer_own()); t.Dispose(); } } #endif class TestEinaSlice { private static readonly byte[] base_seq = BaseSequence.Values(); private static readonly GCHandle pinnedData = GCHandle.Alloc(base_seq, GCHandleType.Pinned); private static readonly IntPtr pinnedPtr = pinnedData.AddrOfPinnedObject(); #if EFL_BETA public static void eina_slice_marshalling() { var binbuf = new Eina.Binbuf(base_seq); Test.Assert(binbuf.Handle != IntPtr.Zero); Eina.Slice slc = binbuf.GetSlice(); Test.Assert(slc.GetBytes().SequenceEqual(base_seq)); Test.Assert(base_seq.Length == (int)(slc.Len)); binbuf.Dispose(); } #endif public static void eina_slice_size() { Test.Assert(Marshal.SizeOf(typeof(Eina.Slice)) == Marshal.SizeOf(typeof(UIntPtr)) + Marshal.SizeOf(typeof(IntPtr))); Test.Assert(Marshal.SizeOf(typeof(Eina.RwSlice)) == Marshal.SizeOf(typeof(UIntPtr)) + Marshal.SizeOf(typeof(IntPtr))); } #if EFL_BETA public static void pinned_data_set() { var binbuf = new Eina.Binbuf(); binbuf.Append(new Eina.Slice(pinnedPtr, (UIntPtr)3)); Test.Assert(binbuf.GetBytes().SequenceEqual(base_seq)); binbuf.Dispose(); } #endif public static void test_eina_slice_in() { var t = new Dummy.TestObject(); var slc = new Eina.Slice(pinnedPtr, (UIntPtr)3); Test.Assert(t.EinaSliceIn(slc)); t.Dispose(); } public static void test_eina_rw_slice_in() { var rw_seq = base_seq.Clone(); GCHandle pinnedRWData = GCHandle.Alloc(rw_seq, GCHandleType.Pinned); IntPtr ptr = pinnedRWData.AddrOfPinnedObject(); var slc = new Eina.RwSlice(ptr, (UIntPtr)3); var t = new Dummy.TestObject(); Test.Assert(t.EinaRwSliceIn(slc)); Test.Assert(slc.GetBytes().SequenceEqual(new byte[3]{0x1, 0x2B, 0x43})); pinnedRWData.Free(); t.Dispose(); } public static void test_eina_slice_out() { var t = new Dummy.TestObject(); var slc = new Eina.Slice(); Test.Assert(t.EinaSliceOut(ref slc)); Test.Assert(slc.Mem != IntPtr.Zero); Test.Assert(slc.Length == base_seq.Length); Test.Assert(slc.GetBytes().SequenceEqual(base_seq)); t.Dispose(); } public static void test_eina_rw_slice_out() { var t = new Dummy.TestObject(); var slc = new Eina.RwSlice(); Test.Assert(t.EinaRwSliceOut(ref slc)); Test.Assert(slc.Mem != IntPtr.Zero); Test.Assert(slc.Length == base_seq.Length); Test.Assert(slc.GetBytes().SequenceEqual(base_seq)); t.Dispose(); } public static void test_eina_rw_slice_inout() { var t = new Dummy.TestObject(); var rw_seq = new byte[4]{0xA, 0xA, 0xA, 0xA}; var expected_seq = new byte[4]{0xA, 0xB, 0xC, 0xD}; var pinnedRWData = GCHandle.Alloc(rw_seq, GCHandleType.Pinned); IntPtr ptr = pinnedRWData.AddrOfPinnedObject(); var slc = new Eina.RwSlice(ptr, (UIntPtr)4); Test.Assert(t.EinaRwSliceInout(ref slc)); Test.Assert(slc.Mem != IntPtr.Zero); Test.Assert(slc.Length == rw_seq.Length); Test.Assert(slc.GetBytes().SequenceEqual(expected_seq)); t.Dispose(); } /* public static void test_eina_slice_return() { } public static void test_eina_rw_slice_return() { } */ public static void test_inherit_eina_slice_in() { var t = new NativeInheritImpl(); var slc = new Eina.Slice(pinnedPtr, (UIntPtr)3); Test.Assert(t.EinaSliceIn(slc)); Test.Assert(t.slice_in_flag); t.Dispose(); } public static void test_inherit_eina_rw_slice_in() { var rw_seq = base_seq.Clone(); GCHandle pinnedRWData = GCHandle.Alloc(rw_seq, GCHandleType.Pinned); IntPtr ptr = pinnedRWData.AddrOfPinnedObject(); var slc = new Eina.RwSlice(ptr, (UIntPtr)3); var t = new NativeInheritImpl(); Test.Assert(t.EinaRwSliceIn(slc)); Test.Assert(t.rw_slice_in_flag); Test.Assert(slc.GetBytes().SequenceEqual(base_seq)); pinnedRWData.Free(); t.Dispose(); } public static void test_inherit_eina_slice_out() { var t = new NativeInheritImpl(); var slc = new Eina.Slice(); Test.Assert(t.EinaSliceOut(ref slc)); Test.Assert(t.slice_out_flag); Test.Assert(slc.Mem != IntPtr.Zero); Test.Assert(slc.Length == base_seq.Length); Test.Assert(slc.GetBytes().SequenceEqual(base_seq)); t.Dispose(); } public static void test_inherit_eina_rw_slice_out() { var t = new NativeInheritImpl(); var slc = new Eina.RwSlice(); Test.Assert(t.EinaRwSliceOut(ref slc)); Test.Assert(t.rw_slice_out_flag); Test.Assert(slc.Mem != IntPtr.Zero); Test.Assert(slc.Length == base_seq.Length); Test.Assert(slc.GetBytes().SequenceEqual(base_seq)); t.Dispose(); } } class TestEinaArray { public static void SetUp() { Dummy.TestObject.CreateCmpArrayObjects(); } public static void TearDown() { Dummy.TestObject.DestroyCmpArrayObjects(); } public static void eina_array_default() { var a = new Eina.Array(); Test.Assert(a.Handle != IntPtr.Zero); a.Dispose(); } public static void create_array_from_null() { Test.AssertRaises(() => new Eina.Array(IntPtr.Zero, false)); Test.AssertRaises(() => new Eina.Array(IntPtr.Zero, false, false)); } public static void push_int() { var a = new Eina.Array(); Test.Assert(a.Handle != IntPtr.Zero); Test.Assert(a.Push(88)); Test.Assert(a[0] == 88); a.Dispose(); } public static void push_string() { var a = new Eina.Array(); Test.Assert(a.Handle != IntPtr.Zero); Test.Assert(a.Push("test string §éΨبÿツ")); Test.AssertEquals("test string §éΨبÿツ", a[0]); a.Dispose(); } public static void push_stringshare() { var a = new Eina.Array(); Test.Assert(a.Handle != IntPtr.Zero); Test.Assert(a.Push("test string §éΨبÿツ")); Test.AssertEquals("test string §éΨبÿツ", a[0].Str); a.Dispose(); } public static void push_obj() { var a = new Eina.Array(); Test.Assert(a.Handle != IntPtr.Zero); var o = new Dummy.Numberwrapper(); o.SetNumber(88); Test.Assert(a.Push(o)); Test.Assert(a[0].NativeHandle == o.NativeHandle); Test.Assert(a[0].GetNumber() == 88); o.Dispose(); a.Dispose(); } public static void pop_int() { var a = new Eina.Array(); Test.Assert(a.Handle != IntPtr.Zero); Test.Assert(a.Push(88)); Test.Assert(a.Pop() == 88); Test.Assert(a.Count() == 0); a.Dispose(); } public static void pop_string() { var a = new Eina.Array(); Test.Assert(a.Handle != IntPtr.Zero); Test.Assert(a.Push("test string")); Test.Assert(a.Pop() == "test string"); Test.Assert(a.Count() == 0); a.Dispose(); } public static void pop_stringshare() { var a = new Eina.Array(); Test.Assert(a.Handle != IntPtr.Zero); Test.Assert(a.Push("test string")); Test.Assert(a.Pop() == "test string"); Test.Assert(a.Count() == 0); a.Dispose(); } public static void pop_obj() { var a = new Eina.Array(); Test.Assert(a.Handle != IntPtr.Zero); var o = new Dummy.Numberwrapper(); o.SetNumber(88); Test.Assert(a.Push(o)); var p = a.Pop(); Test.Assert(p.NativeHandle == o.NativeHandle); Test.Assert(p.GetNumber() == 88); Test.Assert(a.Count() == 0); o.Dispose(); a.Dispose(); } public static void data_set_int() { var a = new Eina.Array(); Test.Assert(a.Handle != IntPtr.Zero); Test.Assert(a.Push(88)); Test.Assert(a[0] == 88); a.DataSet(0, 44); Test.Assert(a[0] == 44); a[0] = 22; Test.Assert(a[0] == 22); a.Dispose(); } public static void data_set_string() { var a = new Eina.Array(); Test.Assert(a.Handle != IntPtr.Zero); Test.Assert(a.Push("test string")); Test.Assert(a[0] == "test string"); a.DataSet(0, "other string"); Test.Assert(a[0] == "other string"); a[0] = "abc"; Test.Assert(a[0] == "abc"); a.Dispose(); } public static void data_set_stringshare() { var a = new Eina.Array(); Test.Assert(a.Handle != IntPtr.Zero); Test.Assert(a.Push("test string")); Test.Assert(a[0] == "test string"); a.DataSet(0, "other string"); Test.Assert(a[0] == "other string"); a[0] = "abc"; Test.Assert(a[0] == "abc"); a.Dispose(); } public static void data_set_obj() { var a = new Eina.Array(); Test.Assert(a.Handle != IntPtr.Zero); var o1 = new Dummy.Numberwrapper(); o1.SetNumber(88); Test.Assert(a.Push(o1)); Test.Assert(a[0].NativeHandle == o1.NativeHandle); Test.Assert(a[0].GetNumber() == 88); var o2 = new Dummy.Numberwrapper(); o2.SetNumber(44); a.DataSet(0, o2); Test.Assert(a[0].NativeHandle == o2.NativeHandle); Test.Assert(a[0].GetNumber() == 44); var o3 = new Dummy.Numberwrapper(); o3.SetNumber(22); a[0] = o3; Test.Assert(a[0].NativeHandle == o3.NativeHandle); Test.Assert(a[0].GetNumber() == 22); o3.Dispose(); o2.Dispose(); o1.Dispose(); a.Dispose(); } public static void count_int() { var a = new Eina.Array(); Test.Assert(a.Handle != IntPtr.Zero); Test.Assert(a.Count() == 0); Test.Assert(a.Push(88)); Test.Assert(a[0] == 88); Test.Assert(a.Count() == 1); Test.Assert(a.Push(44)); Test.Assert(a[1] == 44); Test.Assert(a.Count() == 2); Test.Assert(a.Push(22)); Test.Assert(a[2] == 22); Test.Assert(a.Count() == 3); a.Dispose(); } public static void count_string() { var a = new Eina.Array(); Test.Assert(a.Handle != IntPtr.Zero); Test.Assert(a.Count() == 0); Test.Assert(a.Push("a")); Test.Assert(a[0] == "a"); Test.Assert(a.Count() == 1); Test.Assert(a.Push("b")); Test.Assert(a[1] == "b"); Test.Assert(a.Count() == 2); Test.Assert(a.Push("c")); Test.Assert(a[2] == "c"); Test.Assert(a.Count() == 3); a.Dispose(); } public static void count_stringshare() { var a = new Eina.Array(); Test.Assert(a.Handle != IntPtr.Zero); Test.Assert(a.Count() == 0); Test.Assert(a.Push("a")); Test.Assert(a[0] == "a"); Test.Assert(a.Count() == 1); Test.Assert(a.Push("b")); Test.Assert(a[1] == "b"); Test.Assert(a.Count() == 2); Test.Assert(a.Push("c")); Test.Assert(a[2] == "c"); Test.Assert(a.Count() == 3); a.Dispose(); } public static void count_obj() { var a = new Eina.Array(); Test.Assert(a.Handle != IntPtr.Zero); Test.Assert(a.Count() == 0); var o1 = new Dummy.Numberwrapper(); o1.SetNumber(88); Test.Assert(a.Push(o1)); Test.Assert(a[0].NativeHandle == o1.NativeHandle); Test.Assert(a[0].GetNumber() == 88); Test.Assert(a.Count() == 1); var o2 = new Dummy.Numberwrapper(); o2.SetNumber(44); Test.Assert(a.Push(o2)); Test.Assert(a[1].NativeHandle == o2.NativeHandle); Test.Assert(a[1].GetNumber() == 44); Test.Assert(a.Count() == 2); var o3 = new Dummy.Numberwrapper(); o3.SetNumber(22); Test.Assert(a.Push(o3)); Test.Assert(a[2].NativeHandle == o3.NativeHandle); Test.Assert(a[2].GetNumber() == 22); Test.Assert(a.Count() == 3); o3.Dispose(); o2.Dispose(); o1.Dispose(); a.Dispose(); } public static void length_int() { var a = new Eina.Array(); Test.Assert(a.Handle != IntPtr.Zero); Test.Assert(a.Count == 0); Test.Assert(a.Push(88)); Test.Assert(a[0] == 88); Test.Assert(a.Count == 1); Test.Assert(a.Push(44)); Test.Assert(a[1] == 44); Test.Assert(a.Count == 2); Test.Assert(a.Push(22)); Test.Assert(a[2] == 22); Test.Assert(a.Count == 3); a.Dispose(); } public static void length_string() { var a = new Eina.Array(); Test.Assert(a.Handle != IntPtr.Zero); Test.Assert(a.Count == 0); Test.Assert(a.Push("a")); Test.Assert(a[0] == "a"); Test.Assert(a.Count == 1); Test.Assert(a.Push("b")); Test.Assert(a[1] == "b"); Test.Assert(a.Count == 2); Test.Assert(a.Push("c")); Test.Assert(a[2] == "c"); Test.Assert(a.Count == 3); a.Dispose(); } public static void length_stringshare() { var a = new Eina.Array(); Test.Assert(a.Handle != IntPtr.Zero); Test.Assert(a.Count == 0); Test.Assert(a.Push("a")); Test.Assert(a[0] == "a"); Test.Assert(a.Count == 1); Test.Assert(a.Push("b")); Test.Assert(a[1] == "b"); Test.Assert(a.Count == 2); Test.Assert(a.Push("c")); Test.Assert(a[2] == "c"); Test.Assert(a.Count == 3); a.Dispose(); } public static void eina_array_as_ienumerable_int() { var a = new Eina.Array(); Test.Assert(a.Handle != IntPtr.Zero); Test.Assert(a.Push(88)); Test.Assert(a.Push(44)); Test.Assert(a.Push(22)); int cmp = 88; foreach (int e in a) { Test.AssertEquals(cmp, e); cmp /= 2; } a.Dispose(); } public static void eina_array_as_ienumerable_string() { var a = new Eina.Array(); Test.Assert(a.Handle != IntPtr.Zero); Test.Assert(a.Push("X")); Test.Assert(a.Push("XX")); Test.Assert(a.Push("XXX")); string cmp = "X"; foreach (string e in a) { Test.AssertEquals(cmp, e); cmp = cmp + "X"; } a.Dispose(); } public static void eina_array_as_ienumerable_stringshare() { var a = new Eina.Array(); Test.Assert(a.Handle != IntPtr.Zero); Test.Assert(a.Push("X")); Test.Assert(a.Push("XX")); Test.Assert(a.Push("XXX")); string cmp = "X"; foreach (string e in a) { Test.AssertEquals(cmp, e); cmp = cmp + "X"; } a.Dispose(); } public static void eina_array_as_ienumerable_obj() { var a = new Dummy.Numberwrapper(); var b = new Dummy.Numberwrapper(); var c = new Dummy.Numberwrapper(); a.SetNumber(88); b.SetNumber(44); c.SetNumber(22); var cmp = new Dummy.Numberwrapper[]{a, b, c}; var arr = new Eina.Array(); Test.Assert(arr.Handle != IntPtr.Zero); Test.Assert(arr.Push(a)); Test.Assert(arr.Push(b)); Test.Assert(arr.Push(c)); int i = 0; foreach (Dummy.Numberwrapper e in arr) { Test.AssertEquals(cmp[i].GetNumber(), e.GetNumber()); Test.Assert(cmp[i].NativeHandle == e.NativeHandle); ++i; } arr.Dispose(); } // // // Code Generation // // Integer // public static void test_eina_array_int_in() { var t = new Dummy.TestObject(); var arr = new Eina.Array(); arr.Append(base_seq_int); Test.Assert(t.EinaArrayIntIn(arr)); Test.Assert(arr.Own); Test.Assert(arr.ToArray().SequenceEqual(modified_seq_int)); arr.Dispose(); Test.Assert(arr.Handle == IntPtr.Zero); t.Dispose(); } public static void test_eina_array_int_in_own() { var t = new Dummy.TestObject(); var arr = new Eina.Array(); arr.Append(base_seq_int); Test.Assert(t.EinaArrayIntInOwn(arr)); - Test.Assert(!arr.Own); + Test.Assert(arr.Own); Test.Assert(arr.ToArray().SequenceEqual(modified_seq_int)); arr.Dispose(); Test.Assert(arr.Handle == IntPtr.Zero); Test.Assert(t.CheckEinaArrayIntInOwn()); t.Dispose(); } public static void test_eina_array_int_out() { var t = new Dummy.TestObject(); - Eina.Array arr; + IList arr; Test.Assert(t.EinaArrayIntOut(out arr)); - Test.Assert(!arr.Own); Test.Assert(arr.ToArray().SequenceEqual(base_seq_int)); - Test.AssertRaises(() => arr.Append(append_seq_int)); - arr.Dispose(); - Test.Assert(arr.Handle == IntPtr.Zero); + Test.Assert(arr.Concat(append_seq_int) != null); Test.Assert(t.CheckEinaArrayIntOut()); t.Dispose(); } public static void test_eina_array_int_out_own() { var t = new Dummy.TestObject(); - Eina.Array arr; + IList arr; Test.Assert(t.EinaArrayIntOutOwn(out arr)); - Test.Assert(arr.Own); Test.Assert(arr.ToArray().SequenceEqual(base_seq_int)); - Test.Assert(arr.Append(append_seq_int)); - arr.Dispose(); - Test.Assert(arr.Handle == IntPtr.Zero); + Test.Assert(arr.Concat(append_seq_int) != null); t.Dispose(); } public static void test_eina_array_int_return() { var t = new Dummy.TestObject(); var arr = t.EinaArrayIntReturn(); - Test.Assert(!arr.Own); - Test.Assert(!arr.OwnContent); Test.Assert(arr.ToArray().SequenceEqual(base_seq_int)); - Test.AssertRaises(() => arr.Append(append_seq_int)); - arr.Dispose(); - Test.Assert(arr.Handle == IntPtr.Zero); + Test.Assert(arr.Concat(append_seq_int) != null); Test.Assert(t.CheckEinaArrayIntReturn()); t.Dispose(); } public static void test_eina_array_int_return_own() { var t = new Dummy.TestObject(); var arr = t.EinaArrayIntReturnOwn(); - Test.Assert(arr.Own); Test.Assert(arr.ToArray().SequenceEqual(base_seq_int)); - Test.Assert(arr.Append(append_seq_int)); - arr.Dispose(); - Test.Assert(arr.Handle == IntPtr.Zero); + Test.Assert(arr.Concat(append_seq_int) != null); t.Dispose(); } // String // public static void test_eina_array_str_in() { var t = new Dummy.TestObject(); var arr = new Eina.Array(); arr.Append(base_seq_str); Test.Assert(t.EinaArrayStrIn(arr)); Test.Assert(arr.Own); Test.Assert(arr.ToArray().SequenceEqual(modified_seq_str)); arr.Dispose(); Test.Assert(arr.Handle == IntPtr.Zero); t.Dispose(); } public static void test_eina_array_str_in_own() { var t = new Dummy.TestObject(); var arr = new Eina.Array(); arr.Append(base_seq_str); Test.Assert(t.EinaArrayStrInOwn(arr)); - Test.Assert(!arr.Own); + Test.Assert(arr.Own); Test.Assert(arr.ToArray().SequenceEqual(modified_seq_str)); arr.Dispose(); Test.Assert(arr.Handle == IntPtr.Zero); Test.Assert(t.CheckEinaArrayStrInOwn()); t.Dispose(); } public static void test_eina_array_str_out() { var t = new Dummy.TestObject(); - Eina.Array arr; + IList arr; Test.Assert(t.EinaArrayStrOut(out arr)); - Test.Assert(!arr.Own); Test.Assert(arr.ToArray().SequenceEqual(base_seq_str)); - Test.AssertRaises(() => arr.Append(append_seq_str)); - arr.Dispose(); - Test.Assert(arr.Handle == IntPtr.Zero); + Test.Assert(arr.Concat(append_seq_str) != null); Test.Assert(t.CheckEinaArrayStrOut()); t.Dispose(); } public static void test_eina_array_str_out_own() { var t = new Dummy.TestObject(); - Eina.Array arr; + IList arr; Test.Assert(t.EinaArrayStrOutOwn(out arr)); - Test.Assert(arr.Own); Test.Assert(arr.ToArray().SequenceEqual(base_seq_str)); - Test.Assert(arr.Append(append_seq_str)); - arr.Dispose(); - Test.Assert(arr.Handle == IntPtr.Zero); + Test.Assert(arr.Concat(append_seq_str) != null); t.Dispose(); } public static void test_eina_array_str_return() { var t = new Dummy.TestObject(); var arr = t.EinaArrayStrReturn(); - Test.Assert(!arr.Own); Test.Assert(arr.ToArray().SequenceEqual(base_seq_str)); - Test.AssertRaises(() => arr.Append(append_seq_str)); - arr.Dispose(); - Test.Assert(arr.Handle == IntPtr.Zero); + Test.Assert(arr.Concat(append_seq_str) != null); Test.Assert(t.CheckEinaArrayStrReturn()); t.Dispose(); } public static void test_eina_array_str_return_own() { var t = new Dummy.TestObject(); var arr = t.EinaArrayStrReturnOwn(); - Test.Assert(arr.Own); Test.Assert(arr.ToArray().SequenceEqual(base_seq_str)); - Test.Assert(arr.Append(append_seq_str)); - arr.Dispose(); - Test.Assert(arr.Handle == IntPtr.Zero); + Test.Assert(arr.Concat(append_seq_str) != null); t.Dispose(); } // Eina.Stringshare // public static void test_eina_array_strshare_in() { var t = new Dummy.TestObject(); var arr = new Eina.Array(); arr.Append(base_seq_strshare); Test.Assert(t.EinaArrayStrshareIn(arr)); Test.Assert(arr.Own); Test.Assert(arr.ToArray().SequenceEqual(modified_seq_strshare)); arr.Dispose(); Test.Assert(arr.Handle == IntPtr.Zero); t.Dispose(); } public static void test_eina_array_strshare_in_own() { var t = new Dummy.TestObject(); var arr = new Eina.Array(); arr.Append(base_seq_strshare); Test.Assert(t.EinaArrayStrshareInOwn(arr)); - Test.Assert(!arr.Own); + Test.Assert(arr.Own); Test.Assert(arr.ToArray().SequenceEqual(modified_seq_strshare)); arr.Dispose(); Test.Assert(arr.Handle == IntPtr.Zero); Test.Assert(t.CheckEinaArrayStrshareInOwn()); t.Dispose(); } public static void test_eina_array_strshare_out() { var t = new Dummy.TestObject(); - Eina.Array arr; + IList arr; Test.Assert(t.EinaArrayStrshareOut(out arr)); - Test.Assert(!arr.Own); Test.Assert(arr.ToArray().SequenceEqual(base_seq_strshare)); - Test.AssertRaises(() => arr.Append(append_seq_strshare)); - arr.Dispose(); - Test.Assert(arr.Handle == IntPtr.Zero); + Test.Assert(arr.Concat(append_seq_strshare) != null); Test.Assert(t.CheckEinaArrayStrshareOut()); t.Dispose(); } public static void test_eina_array_strshare_out_own() { var t = new Dummy.TestObject(); - Eina.Array arr; + IList arr; Test.Assert(t.EinaArrayStrshareOutOwn(out arr)); - Test.Assert(arr.Own); Test.Assert(arr.ToArray().SequenceEqual(base_seq_strshare)); - Test.Assert(arr.Append(append_seq_strshare)); - arr.Dispose(); - Test.Assert(arr.Handle == IntPtr.Zero); + Test.Assert(arr.Concat(append_seq_strshare) != null); t.Dispose(); } public static void test_eina_array_strshare_return() { var t = new Dummy.TestObject(); var arr = t.EinaArrayStrshareReturn(); - Test.Assert(!arr.Own); Test.Assert(arr.ToArray().SequenceEqual(base_seq_strshare)); - Test.AssertRaises(() => arr.Append(append_seq_strshare)); - arr.Dispose(); - Test.Assert(arr.Handle == IntPtr.Zero); + Test.Assert(arr.Concat(append_seq_strshare) != null); Test.Assert(t.CheckEinaArrayStrshareReturn()); t.Dispose(); } public static void test_eina_array_strshare_return_own() { var t = new Dummy.TestObject(); var arr = t.EinaArrayStrshareReturnOwn(); - Test.Assert(arr.Own); Test.Assert(arr.ToArray().SequenceEqual(base_seq_strshare)); - Test.Assert(arr.Append(append_seq_strshare)); - arr.Dispose(); - Test.Assert(arr.Handle == IntPtr.Zero); + Test.Assert(arr.Concat(append_seq_strshare) != null); t.Dispose(); } // Object // public static void test_eina_array_obj_in() { var t = new Dummy.TestObject(); var arr = new Eina.Array(); arr.Append(BaseSeqObj()); Test.Assert(t.EinaArrayObjIn(arr)); Test.Assert(arr.Own); NumberwrapperSequenceAssertEqual(arr.ToArray(), ModifiedSeqObj()); arr.Dispose(); Test.Assert(arr.Handle == IntPtr.Zero); t.Dispose(); } public static void test_eina_array_obj_in_own() { var t = new Dummy.TestObject(); var arr = new Eina.Array(); arr.Append(BaseSeqObj()); Test.Assert(t.EinaArrayObjInOwn(arr)); - Test.Assert(!arr.Own); + Test.Assert(arr.Own); NumberwrapperSequenceAssertEqual(arr.ToArray(), ModifiedSeqObj()); arr.Dispose(); Test.Assert(arr.Handle == IntPtr.Zero); Test.Assert(t.CheckEinaArrayObjInOwn()); t.Dispose(); } public static void test_eina_array_obj_out() { var t = new Dummy.TestObject(); - Eina.Array arr; + IList arr; Test.Assert(t.EinaArrayObjOut(out arr)); - Test.Assert(!arr.Own); NumberwrapperSequenceAssertEqual(arr.ToArray(), BaseSeqObj()); - Test.AssertRaises(() => arr.Append(AppendSeqObj())); - arr.Dispose(); - Test.Assert(arr.Handle == IntPtr.Zero); + Test.Assert(arr.Concat(AppendSeqObj()) != null); Test.Assert(t.CheckEinaArrayObjOut()); t.Dispose(); } public static void test_eina_array_obj_out_own() { var t = new Dummy.TestObject(); - Eina.Array arr; + IList arr; Test.Assert(t.EinaArrayObjOutOwn(out arr)); - Test.Assert(arr.Own); NumberwrapperSequenceAssertEqual(arr.ToArray(), BaseSeqObj()); - Test.Assert(arr.Append(AppendSeqObj())); - arr.Dispose(); - Test.Assert(arr.Handle == IntPtr.Zero); + Test.Assert(arr.Concat(AppendSeqObj()) != null); t.Dispose(); } public static void test_eina_array_obj_return() { var t = new Dummy.TestObject(); var arr = t.EinaArrayObjReturn(); - Test.Assert(!arr.Own); NumberwrapperSequenceAssertEqual(arr.ToArray(), BaseSeqObj()); - Test.AssertRaises(() => arr.Append(AppendSeqObj())); - arr.Dispose(); - Test.Assert(arr.Handle == IntPtr.Zero); + Test.Assert(arr.Concat(AppendSeqObj()) != null); Test.Assert(t.CheckEinaArrayObjReturn()); t.Dispose(); } public static void test_eina_array_obj_return_own() { var t = new Dummy.TestObject(); var arr = t.EinaArrayObjReturnOwn(); - Test.Assert(arr.Own); NumberwrapperSequenceAssertEqual(arr.ToArray(), BaseSeqObj()); - Test.Assert(arr.Append(AppendSeqObj())); - arr.Dispose(); - Test.Assert(arr.Handle == IntPtr.Zero); + Test.Assert(arr.Concat(AppendSeqObj()) != null); t.Dispose(); } public static void test_eina_array_obj_return_in_same_id() { var t = new Dummy.TestObject(); var cmp = BaseSeqObj(); var a = new Eina.Array(); a.Append(cmp); var b = t.EinaArrayObjReturnIn(a); NumberwrapperSequenceAssertEqual(a.ToArray(), b.ToArray()); NumberwrapperSequenceAssertEqual(a.ToArray(), BaseSeqObj()); int len = a.Count; for (int i=0; i < len; ++i) { Test.Assert(a[i].NativeHandle == b[i].NativeHandle); Test.Assert(a[i].NativeHandle == cmp[i].NativeHandle); } a.Dispose(); t.Dispose(); } // // // Inherit // } class TestEinaInarray { public static void eina_inarray_default() { var a = new Eina.Inarray(); Test.Assert(a.Handle != IntPtr.Zero); a.Dispose(); } public static void push_int() { var a = new Eina.Inarray(); Test.Assert(a.Handle != IntPtr.Zero); Test.Assert(a.Push(88) == 0); Test.Assert(a[0] == 88); a.Dispose(); } public static void push_string() { var a = new Eina.Inarray(); Test.Assert(a.Handle != IntPtr.Zero); Test.Assert(a.Push("test string") == 0); Test.Assert(a[0] == "test string"); a.Dispose(); } public static void push_obj() { var a = new Eina.Inarray(); Test.Assert(a.Handle != IntPtr.Zero); var o = new Dummy.Numberwrapper(); o.SetNumber(88); Test.Assert(a.Push(o) == 0); Test.Assert(a[0].NativeHandle == o.NativeHandle); Test.Assert(a[0].GetNumber() == 88); o.Dispose(); a.Dispose(); } public static void pop_int() { var a = new Eina.Inarray(); Test.Assert(a.Handle != IntPtr.Zero); Test.Assert(a.Push(88) >= 0); Test.Assert(a.Pop() == 88); Test.Assert(a.Count() == 0); a.Dispose(); } public static void pop_string() { var a = new Eina.Inarray(); Test.Assert(a.Handle != IntPtr.Zero); Test.Assert(a.Push("test string") >= 0); Test.Assert(a.Pop() == "test string"); Test.Assert(a.Count() == 0); a.Dispose(); } public static void pop_obj() { var a = new Eina.Inarray(); Test.Assert(a.Handle != IntPtr.Zero); var o = new Dummy.Numberwrapper(); o.SetNumber(88); Test.Assert(a.Push(o) >= 0); var p = a.Pop(); Test.Assert(p.NativeHandle == o.NativeHandle); Test.Assert(p.GetNumber() == 88); Test.Assert(a.Count() == 0); o.Dispose(); a.Dispose(); } public static void replace_at_int() { var a = new Eina.Inarray(); Test.Assert(a.Handle != IntPtr.Zero); Test.Assert(a.Push(88) >= 0); Test.Assert(a[0] == 88); a.ReplaceAt(0, 44); Test.Assert(a[0] == 44); Test.Assert(a.Count() == 1); a[0] = 22; Test.Assert(a[0] == 22); Test.Assert(a.Count() == 1); a.Dispose(); } public static void replace_at_string() { var a = new Eina.Inarray(); Test.Assert(a.Handle != IntPtr.Zero); Test.Assert(a.Push("test string") >= 0); Test.Assert(a[0] == "test string"); a.ReplaceAt(0, "other string"); Test.Assert(a[0] == "other string"); Test.Assert(a.Count() == 1); a[0] = "abc"; Test.Assert(a[0] == "abc"); Test.Assert(a.Count() == 1); a.Dispose(); } public static void replace_at_obj() { var a = new Eina.Inarray(); Test.Assert(a.Handle != IntPtr.Zero); var o1 = new Dummy.Numberwrapper(); o1.SetNumber(88); Test.Assert(a.Push(o1) >= 0); Test.Assert(a[0].NativeHandle == o1.NativeHandle); Test.Assert(a[0].GetNumber() == 88); var o2 = new Dummy.Numberwrapper(); o2.SetNumber(44); a.ReplaceAt(0, o2); Test.Assert(a[0].NativeHandle == o2.NativeHandle); Test.Assert(a[0].GetNumber() == 44); Test.Assert(a.Count() == 1); var o3 = new Dummy.Numberwrapper(); o3.SetNumber(22); a[0] = o3; Test.Assert(a[0].NativeHandle == o3.NativeHandle); Test.Assert(a[0].GetNumber() == 22); Test.Assert(a.Count() == 1); o3.Dispose(); o2.Dispose(); o1.Dispose(); a.Dispose(); } public static void count_int() { var a = new Eina.Inarray(); Test.Assert(a.Handle != IntPtr.Zero); Test.Assert(a.Count() == 0); Test.Assert(a.Push(88) == 0); Test.Assert(a[0] == 88); Test.Assert(a.Count() == 1); Test.Assert(a.Push(44) == 1); Test.Assert(a[1] == 44); Test.Assert(a.Count() == 2); Test.Assert(a.Push(22) == 2); Test.Assert(a[2] == 22); Test.Assert(a.Count() == 3); a.Dispose(); } public static void count_string() { var a = new Eina.Inarray(); Test.Assert(a.Handle != IntPtr.Zero); Test.Assert(a.Count() == 0); Test.Assert(a.Push("a") == 0); Test.Assert(a[0] == "a"); Test.Assert(a.Count() == 1); Test.Assert(a.Push("b") == 1); Test.Assert(a[1] == "b"); Test.Assert(a.Count() == 2); Test.Assert(a.Push("c") == 2); Test.Assert(a[2] == "c"); Test.Assert(a.Count() == 3); a.Dispose(); } public static void count_obj() { var a = new Eina.Inarray(); Test.Assert(a.Handle != IntPtr.Zero); Test.Assert(a.Count() == 0); var o1 = new Dummy.Numberwrapper(); o1.SetNumber(88); Test.Assert(a.Push(o1) == 0); Test.Assert(a[0].NativeHandle == o1.NativeHandle); Test.Assert(a[0].GetNumber() == 88); Test.Assert(a.Count() == 1); var o2 = new Dummy.Numberwrapper(); o2.SetNumber(44); Test.Assert(a.Push(o2) == 1); Test.Assert(a[1].NativeHandle == o2.NativeHandle); Test.Assert(a[1].GetNumber() == 44); Test.Assert(a.Count() == 2); var o3 = new Dummy.Numberwrapper(); o3.SetNumber(22); Test.Assert(a.Push(o3) == 2); Test.Assert(a[2].NativeHandle == o3.NativeHandle); Test.Assert(a[2].GetNumber() == 22); Test.Assert(a.Count() == 3); o3.Dispose(); o2.Dispose(); o1.Dispose(); a.Dispose(); } public static void length_int() { var a = new Eina.Inarray(); Test.Assert(a.Handle != IntPtr.Zero); Test.Assert(a.Length == 0); Test.Assert(a.Push(88) >= 0); Test.Assert(a[0] == 88); Test.Assert(a.Length == 1); Test.Assert(a.Push(44) >= 0); Test.Assert(a[1] == 44); Test.Assert(a.Length == 2); Test.Assert(a.Push(22) >= 0); Test.Assert(a[2] == 22); Test.Assert(a.Length == 3); a.Dispose(); } public static void length_string() { var a = new Eina.Inarray(); Test.Assert(a.Handle != IntPtr.Zero); Test.Assert(a.Length == 0); Test.Assert(a.Push("a") >= 0); Test.Assert(a[0] == "a"); Test.Assert(a.Length == 1); Test.Assert(a.Push("b") >= 0); Test.Assert(a[1] == "b"); Test.Assert(a.Length == 2); Test.Assert(a.Push("c") >= 0); Test.Assert(a[2] == "c"); Test.Assert(a.Length == 3); a.Dispose(); } public static void eina_inarray_as_ienumerable_int() { var a = new Eina.Inarray(); Test.Assert(a.Handle != IntPtr.Zero); Test.Assert(a.Push(88) == 0); Test.Assert(a.Push(44) == 1); Test.Assert(a.Push(22) == 2); int cmp = 88; foreach (int e in a) { Test.AssertEquals(cmp, e); cmp /= 2; } a.Dispose(); } public static void eina_inarray_as_ienumerable_string() { var a = new Eina.Inarray(); Test.Assert(a.Handle != IntPtr.Zero); Test.Assert(a.Push("X") == 0); Test.Assert(a.Push("XX") == 1); Test.Assert(a.Push("XXX") == 2); string cmp = "X"; foreach (string e in a) { Test.AssertEquals(cmp, e); cmp = cmp + "X"; } a.Dispose(); } public static void eina_inarray_as_ienumerable_obj() { var a = new Dummy.Numberwrapper(); var b = new Dummy.Numberwrapper(); var c = new Dummy.Numberwrapper(); a.SetNumber(88); b.SetNumber(44); c.SetNumber(22); var cmp = new Dummy.Numberwrapper[]{a, b, c}; var arr = new Eina.Inarray(); Test.Assert(arr.Handle != IntPtr.Zero); Test.Assert(arr.Push(a) == 0); Test.Assert(arr.Push(b) == 1); Test.Assert(arr.Push(c) == 2); int i = 0; foreach (Dummy.Numberwrapper e in arr) { Test.AssertEquals(cmp[i].GetNumber(), e.GetNumber()); Test.Assert(cmp[i].NativeHandle == e.NativeHandle); ++i; } arr.Dispose(); } } class TestEinaList { public static void SetUp() { Dummy.TestObject.CreateCmpArrayObjects(); } public static void TearDown() { Dummy.TestObject.DestroyCmpArrayObjects(); } public static void data_set_int() { var lst = new Eina.List(); lst.Append(88); Test.Assert(lst[0] == 88); lst.DataSet(0, 44); Test.Assert(lst[0] == 44); lst[0] = 22; Test.Assert(lst[0] == 22); lst.Dispose(); } public static void data_set_string() { var lst = new Eina.List(); lst.Append("test string"); Test.Assert(lst[0] == "test string"); lst.DataSet(0, "other string"); Test.Assert(lst[0] == "other string"); lst[0] = "abc"; Test.Assert(lst[0] == "abc"); lst.Dispose(); } public static void data_set_stringshare() { var lst = new Eina.List(); lst.Append("test string"); Test.Assert(lst[0] == "test string"); lst.DataSet(0, "other string"); Test.Assert(lst[0] == "other string"); lst[0] = "abc"; Test.Assert(lst[0] == "abc"); lst.Dispose(); } public static void data_set_obj() { var lst = new Eina.List(); var o1 = new Dummy.Numberwrapper(); o1.SetNumber(88); lst.Append(o1); Test.Assert(lst[0].NativeHandle == o1.NativeHandle); Test.Assert(lst[0].GetNumber() == 88); var o2 = new Dummy.Numberwrapper(); o2.SetNumber(44); lst.DataSet(0, o2); Test.Assert(lst[0].NativeHandle == o2.NativeHandle); Test.Assert(lst[0].GetNumber() == 44); var o3 = new Dummy.Numberwrapper(); o3.SetNumber(22); lst[0] = o3; Test.Assert(lst[0].NativeHandle == o3.NativeHandle); Test.Assert(lst[0].GetNumber() == 22); o3.Dispose(); o2.Dispose(); o1.Dispose(); lst.Dispose(); } public static void append_count_int() { var lst = new Eina.List(); Test.Assert(lst.Count() == 0); lst.Append(88); Test.Assert(lst[0] == 88); Test.Assert(lst.Count() == 1); lst.Append(44); Test.Assert(lst[1] == 44); Test.Assert(lst.Count() == 2); lst.Append(22); Test.Assert(lst[2] == 22); Test.Assert(lst.Count() == 3); lst.Dispose(); } public static void append_count_string() { var lst = new Eina.List(); Test.Assert(lst.Count() == 0); lst.Append("a"); Test.Assert(lst[0] == "a"); Test.Assert(lst.Count() == 1); lst.Append("b"); Test.Assert(lst[1] == "b"); Test.Assert(lst.Count() == 2); lst.Append("c"); Test.Assert(lst[2] == "c"); Test.Assert(lst.Count() == 3); lst.Dispose(); } public static void append_count_stringshare() { var lst = new Eina.List(); Test.Assert(lst.Count() == 0); lst.Append("a"); Test.Assert(lst[0] == "a"); Test.Assert(lst.Count() == 1); lst.Append("b"); Test.Assert(lst[1] == "b"); Test.Assert(lst.Count() == 2); lst.Append("c"); Test.Assert(lst[2] == "c"); Test.Assert(lst.Count() == 3); lst.Dispose(); } public static void append_count_obj() { var lst = new Eina.List(); Test.Assert(lst.Count() == 0); var o1 = new Dummy.Numberwrapper(); o1.SetNumber(88); lst.Append(o1); Test.Assert(lst[0].NativeHandle == o1.NativeHandle); Test.Assert(lst[0].GetNumber() == 88); Test.Assert(lst.Count() == 1); var o2 = new Dummy.Numberwrapper(); o2.SetNumber(44); lst.Append(o2); Test.Assert(lst[1].NativeHandle == o2.NativeHandle); Test.Assert(lst[1].GetNumber() == 44); Test.Assert(lst.Count() == 2); var o3 = new Dummy.Numberwrapper(); o3.SetNumber(22); lst.Append(o3); Test.Assert(lst[2].NativeHandle == o3.NativeHandle); Test.Assert(lst[2].GetNumber() == 22); Test.Assert(lst.Count() == 3); o3.Dispose(); o2.Dispose(); o1.Dispose(); lst.Dispose(); } public static void length_int() { var lst = new Eina.List(); Test.Assert(lst.Count == 0); lst.Append(88); Test.Assert(lst[0] == 88); Test.Assert(lst.Count == 1); lst.Append(44); Test.Assert(lst[1] == 44); Test.Assert(lst.Count == 2); lst.Append(22); Test.Assert(lst[2] == 22); Test.Assert(lst.Count == 3); lst.Dispose(); } public static void length_string() { var lst = new Eina.List(); Test.Assert(lst.Count == 0); lst.Append("a"); Test.Assert(lst[0] == "a"); Test.Assert(lst.Count == 1); lst.Append("b"); Test.Assert(lst[1] == "b"); Test.Assert(lst.Count == 2); lst.Append("c"); Test.Assert(lst[2] == "c"); Test.Assert(lst.Count == 3); lst.Dispose(); } public static void length_stringshare() { var lst = new Eina.List(); Test.Assert(lst.Count == 0); lst.Append("a"); Test.Assert(lst[0] == "a"); Test.Assert(lst.Count == 1); lst.Append("b"); Test.Assert(lst[1] == "b"); Test.Assert(lst.Count == 2); lst.Append("c"); Test.Assert(lst[2] == "c"); Test.Assert(lst.Count == 3); lst.Dispose(); } public static void prepend_count_int() { var lst = new Eina.List(); Test.Assert(lst.Count() == 0); lst.Prepend(88); Test.Assert(lst[0] == 88); Test.Assert(lst.Count() == 1); lst.Prepend(44); Test.Assert(lst[0] == 44); Test.Assert(lst.Count() == 2); lst.Prepend(22); Test.Assert(lst[0] == 22); Test.Assert(lst.Count() == 3); lst.Dispose(); } public static void prepend_count_string() { var lst = new Eina.List(); Test.Assert(lst.Count() == 0); lst.Prepend("a"); Test.Assert(lst[0] == "a"); Test.Assert(lst.Count() == 1); lst.Prepend("b"); Test.Assert(lst[0] == "b"); Test.Assert(lst.Count() == 2); lst.Prepend("c"); Test.Assert(lst[0] == "c"); Test.Assert(lst.Count() == 3); lst.Dispose(); } public static void prepend_count_stringshare() { var lst = new Eina.List(); Test.Assert(lst.Count() == 0); lst.Prepend("a"); Test.Assert(lst[0] == "a"); Test.Assert(lst.Count() == 1); lst.Prepend("b"); Test.Assert(lst[0] == "b"); Test.Assert(lst.Count() == 2); lst.Prepend("c"); Test.Assert(lst[0] == "c"); Test.Assert(lst.Count() == 3); lst.Dispose(); } public static void prepend_count_obj() { var lst = new Eina.List(); Test.Assert(lst.Count() == 0); var o1 = new Dummy.Numberwrapper(); o1.SetNumber(88); lst.Prepend(o1); Test.Assert(lst[0].NativeHandle == o1.NativeHandle); Test.Assert(lst[0].GetNumber() == 88); Test.Assert(lst.Count() == 1); var o2 = new Dummy.Numberwrapper(); o2.SetNumber(44); lst.Prepend(o2); Test.Assert(lst[0].NativeHandle == o2.NativeHandle); Test.Assert(lst[0].GetNumber() == 44); Test.Assert(lst.Count() == 2); var o3 = new Dummy.Numberwrapper(); o3.SetNumber(22); lst.Prepend(o3); Test.Assert(lst[0].NativeHandle == o3.NativeHandle); Test.Assert(lst[0].GetNumber() == 22); Test.Assert(lst.Count() == 3); o3.Dispose(); o2.Dispose(); o1.Dispose(); lst.Dispose(); } public static void sorted_insert_int() { var lst = new Eina.List(); lst.SortedInsert(88); Test.Assert(lst.ToArray().SequenceEqual(new int[]{88})); lst.SortedInsert(22); Test.Assert(lst.ToArray().SequenceEqual(new int[]{22, 88})); lst.SortedInsert(44); Test.Assert(lst.ToArray().SequenceEqual(new int[]{22, 44, 88})); lst.Dispose(); } public static void sorted_insert_string() { var lst = new Eina.List(); lst.SortedInsert("c"); Test.Assert(lst.ToArray().SequenceEqual(new string[]{"c"})); lst.SortedInsert("a"); Test.Assert(lst.ToArray().SequenceEqual(new string[]{"a", "c"})); lst.SortedInsert("b"); Test.Assert(lst.ToArray().SequenceEqual(new string[]{"a", "b", "c"})); lst.Dispose(); } public static void sorted_insert_stringshare() { var lst = new Eina.List(); lst.SortedInsert("c"); Test.Assert(lst.ToArray().SequenceEqual(new Eina.Stringshare[]{"c"})); lst.SortedInsert("a"); Test.Assert( lst.ToArray().SequenceEqual(new Eina.Stringshare[]{"a", "c"})); lst.SortedInsert("b"); Test.Assert( lst.ToArray().SequenceEqual(new Eina.Stringshare[]{"a", "b", "c"})); lst.Dispose(); } public static void sorted_insert_custom_comparer_natural() { var lst = new Eina.List(); Eina.List.Compare comparator = (int a, int b) => a - b; lst.SortedInsert(comparator, 1); Test.Assert(lst.ToArray().SequenceEqual(new int[]{1})); lst.SortedInsert(comparator, 2); Test.Assert(lst.ToArray().SequenceEqual(new int[]{1, 2})); lst.SortedInsert(comparator, 3); Test.Assert(lst.ToArray().SequenceEqual(new int[]{1, 2, 3})); lst.SortedInsert(comparator, -1); Test.Assert(lst.ToArray().SequenceEqual(new int[]{-1, 1, 2, 3})); lst.Dispose(); } public static void sorted_insert_custom_comparer_reversed() { var lst = new Eina.List(); Eina.List.Compare comparator = (int a, int b) => b - a; lst.SortedInsert(comparator, 1); Test.Assert(lst.ToArray().SequenceEqual(new int[]{1})); lst.SortedInsert(comparator, 2); Test.Assert(lst.ToArray().SequenceEqual(new int[]{2, 1})); lst.SortedInsert(comparator, 3); Test.Assert(lst.ToArray().SequenceEqual(new int[]{3, 2, 1})); lst.SortedInsert(comparator, -1); Test.Assert(lst.ToArray().SequenceEqual(new int[]{3, 2, 1, -1})); lst.Dispose(); } public static void sorted_insert_custom_comparer_string() { var lst = new Eina.List(); Eina.List.Compare comparator = (string a, string b) => b.Length - a.Length; lst.SortedInsert(comparator, "The"); Test.Assert(lst.ToArray().SequenceEqual(new string[]{"The"})); lst.SortedInsert(comparator, "Quick"); Test.Assert(lst.ToArray().SequenceEqual(new string[]{"Quick", "The"})); lst.SortedInsert(comparator, "Brown"); Test.Assert(lst.ToArray().SequenceEqual(new string[]{"Brown", "Quick", "The"})); lst.SortedInsert(comparator, "Jumped"); Test.Assert(lst.ToArray().SequenceEqual( new string[]{"Jumped", "Brown", "Quick", "The"})); lst.Dispose(); } public static void sort_int() { var lst = new Eina.List(); lst.Append(88); lst.Append(22); lst.Append(11); lst.Append(44); Test.Assert(lst.ToArray().SequenceEqual(new int[]{88, 22, 11, 44})); lst.Sort(); Test.Assert(lst.ToArray().SequenceEqual(new int[]{11, 22, 44, 88})); lst.Dispose(); } public static void sort_string() { var lst = new Eina.List(); lst.Append("d"); lst.Append("b"); lst.Append("a"); lst.Append("c"); Test.Assert( lst.ToArray().SequenceEqual(new string[]{"d", "b", "a", "c"})); lst.Sort(); Test.Assert( lst.ToArray().SequenceEqual(new string[]{"a", "b", "c", "d"})); lst.Dispose(); } public static void sort_stringshare() { var lst = new Eina.List(); lst.Append("d"); lst.Append("b"); lst.Append("a"); lst.Append("c"); Test.Assert(lst.ToArray().SequenceEqual( new Eina.Stringshare[]{"d", "b", "a", "c"})); lst.Sort(); Test.Assert(lst.ToArray().SequenceEqual( new Eina.Stringshare[]{"a", "b", "c", "d"})); lst.Dispose(); } public static void reverse_int() { var lst = new Eina.List(); lst.Append(22); lst.Append(44); lst.Append(88); Test.Assert(lst.ToArray().SequenceEqual(new int[]{22, 44, 88})); lst.Reverse(); Test.Assert(lst.ToArray().SequenceEqual(new int[]{88, 44, 22})); lst.Dispose(); } public static void reverse_string() { var lst = new Eina.List(); lst.Append("a"); lst.Append("b"); lst.Append("c"); Test.Assert(lst.ToArray().SequenceEqual(new string[]{"a", "b", "c"})); lst.Reverse(); Test.Assert(lst.ToArray().SequenceEqual(new string[]{"c", "b", "a"})); lst.Dispose(); } public static void reverse_stringshare() { var lst = new Eina.List(); lst.Append("a"); lst.Append("b"); lst.Append("c"); Test.Assert( lst.ToArray().SequenceEqual(new Eina.Stringshare[]{"a", "b", "c"})); lst.Reverse(); Test.Assert( lst.ToArray().SequenceEqual(new Eina.Stringshare[]{"c", "b", "a"})); lst.Dispose(); } public static void eina_list_as_ienumerable_int() { var lst = new Eina.List(); lst.Append(88); lst.Append(44); lst.Append(22); int cmp = 88; foreach (int e in lst) { Test.AssertEquals(cmp, e); cmp /= 2; } lst.Dispose(); } public static void eina_list_as_ienumerable_string() { var lst = new Eina.List(); lst.Append("X"); lst.Append("XX"); lst.Append("XXX"); string cmp = "X"; foreach (string e in lst) { Test.AssertEquals(cmp, e); cmp = cmp + "X"; } lst.Dispose(); } public static void eina_list_as_ienumerable_stringshare() { var lst = new Eina.List(); lst.Append("X"); lst.Append("XX"); lst.Append("XXX"); string cmp = "X"; foreach (string e in lst) { Test.AssertEquals(cmp, e); cmp = cmp + "X"; } lst.Dispose(); } public static void eina_list_as_ienumerable_obj() { var a = new Dummy.Numberwrapper(); var b = new Dummy.Numberwrapper(); var c = new Dummy.Numberwrapper(); a.SetNumber(88); b.SetNumber(44); c.SetNumber(22); var cmp = new Dummy.Numberwrapper[]{a, b, c}; var lst = new Eina.List(); lst.Append(a); lst.Append(b); lst.Append(c); int i = 0; foreach (Dummy.Numberwrapper e in lst) { Test.AssertEquals(cmp[i].GetNumber(), e.GetNumber()); Test.Assert(cmp[i].NativeHandle == e.NativeHandle); ++i; } lst.Dispose(); } // // // Code Generation // // Integer // public static void test_eina_list_int_in() { var t = new Dummy.TestObject(); var lst = new Eina.List(); lst.Append(base_seq_int); Test.Assert(t.EinaListIntIn(lst)); Test.Assert(lst.Own); Test.Assert(lst.ToArray().SequenceEqual(base_seq_int)); lst.Dispose(); Test.Assert(lst.Handle == IntPtr.Zero); t.Dispose(); } public static void test_eina_list_int_in_own() { var t = new Dummy.TestObject(); var lst = new Eina.List(); lst.Append(base_seq_int); Test.Assert(t.EinaListIntInOwn(lst)); - Test.Assert(!lst.Own); - Test.Assert(!lst.OwnContent); + Test.Assert(lst.Own); + Test.Assert(lst.OwnContent); lst.Dispose(); Test.Assert(lst.Handle == IntPtr.Zero); Test.Assert(t.CheckEinaListIntInOwn()); t.Dispose(); } public static void test_eina_list_int_out() { var t = new Dummy.TestObject(); - Eina.List lst; + IList lst; Test.Assert(t.EinaListIntOut(out lst)); - Test.Assert(!lst.Own); - Test.Assert(!lst.OwnContent); Test.Assert(lst.ToArray().SequenceEqual(base_seq_int)); - lst.Dispose(); - Test.Assert(lst.Handle == IntPtr.Zero); Test.Assert(t.CheckEinaListIntOut()); t.Dispose(); } public static void test_eina_list_int_out_own() { var t = new Dummy.TestObject(); - Eina.List lst; + IList lst; Test.Assert(t.EinaListIntOutOwn(out lst)); - Test.Assert(lst.Own); Test.Assert(lst.ToArray().SequenceEqual(base_seq_int)); - lst.Append(append_seq_int); - lst.Dispose(); - Test.Assert(lst.Handle == IntPtr.Zero); + lst.Concat(append_seq_int); t.Dispose(); } public static void test_eina_list_int_return() { var t = new Dummy.TestObject(); var lst = t.EinaListIntReturn(); - Test.Assert(!lst.Own); - Test.Assert(!lst.OwnContent); Test.Assert(lst.ToArray().SequenceEqual(base_seq_int)); - lst.Dispose(); - Test.Assert(lst.Handle == IntPtr.Zero); Test.Assert(t.CheckEinaListIntReturn()); t.Dispose(); } public static void test_eina_list_int_return_own() { var t = new Dummy.TestObject(); var lst = t.EinaListIntReturnOwn(); - Test.Assert(lst.Own); Test.Assert(lst.ToArray().SequenceEqual(base_seq_int)); - lst.Append(append_seq_int); - lst.Dispose(); - Test.Assert(lst.Handle == IntPtr.Zero); + lst.Concat(append_seq_int); t.Dispose(); } // String // public static void test_eina_list_str_in() { var t = new Dummy.TestObject(); var lst = new Eina.List(); lst.Append(base_seq_str); Test.Assert(t.EinaListStrIn(lst)); Test.Assert(lst.Own); Test.Assert(lst.ToArray().SequenceEqual(base_seq_str)); lst.Dispose(); Test.Assert(lst.Handle == IntPtr.Zero); t.Dispose(); } public static void test_eina_list_str_in_own() { var t = new Dummy.TestObject(); var lst = new Eina.List(); lst.Append(base_seq_str); Test.Assert(t.EinaListStrInOwn(lst)); - Test.Assert(!lst.Own); + Test.Assert(lst.Own); lst.Dispose(); Test.Assert(lst.Handle == IntPtr.Zero); Test.Assert(t.CheckEinaListStrInOwn()); t.Dispose(); } public static void test_eina_list_str_out() { var t = new Dummy.TestObject(); - Eina.List lst; + IList lst; Test.Assert(t.EinaListStrOut(out lst)); - Test.Assert(!lst.Own); Test.Assert(lst.ToArray().SequenceEqual(base_seq_str)); - lst.Dispose(); - Test.Assert(lst.Handle == IntPtr.Zero); Test.Assert(t.CheckEinaListStrOut()); t.Dispose(); } public static void test_eina_list_str_out_own() { var t = new Dummy.TestObject(); - Eina.List lst; + IList lst; Test.Assert(t.EinaListStrOutOwn(out lst)); - Test.Assert(lst.Own); Test.Assert(lst.ToArray().SequenceEqual(base_seq_str)); - lst.Append(append_seq_str); - lst.Dispose(); - Test.Assert(lst.Handle == IntPtr.Zero); + lst.Concat(append_seq_str); t.Dispose(); } public static void test_eina_list_str_return() { var t = new Dummy.TestObject(); var lst = t.EinaListStrReturn(); - Test.Assert(!lst.Own); Test.Assert(lst.ToArray().SequenceEqual(base_seq_str)); - lst.Dispose(); - Test.Assert(lst.Handle == IntPtr.Zero); Test.Assert(t.CheckEinaListStrReturn()); t.Dispose(); } public static void test_eina_list_str_return_own() { var t = new Dummy.TestObject(); var lst = t.EinaListStrReturnOwn(); - Test.Assert(lst.Own); Test.Assert(lst.ToArray().SequenceEqual(base_seq_str)); - lst.Append(append_seq_str); - lst.Dispose(); - Test.Assert(lst.Handle == IntPtr.Zero); + lst.Concat(append_seq_str); t.Dispose(); } // Eina.Stringshare // public static void test_eina_list_strshare_in() { var t = new Dummy.TestObject(); var lst = new Eina.List(); lst.Append(base_seq_strshare); Test.Assert(t.EinaListStrshareIn(lst)); Test.Assert(lst.Own); Test.Assert(lst.ToArray().SequenceEqual(base_seq_strshare)); lst.Dispose(); Test.Assert(lst.Handle == IntPtr.Zero); t.Dispose(); } public static void test_eina_list_strshare_in_own() { var t = new Dummy.TestObject(); var lst = new Eina.List(); lst.Append(base_seq_strshare); Test.Assert(t.EinaListStrshareInOwn(lst)); - Test.Assert(!lst.Own); + Test.Assert(lst.Own); lst.Dispose(); Test.Assert(lst.Handle == IntPtr.Zero); Test.Assert(t.CheckEinaListStrshareInOwn()); t.Dispose(); } public static void test_eina_list_strshare_out() { var t = new Dummy.TestObject(); - Eina.List lst; + IList lst; Test.Assert(t.EinaListStrshareOut(out lst)); - Test.Assert(!lst.Own); Test.Assert(lst.ToArray().SequenceEqual(base_seq_strshare)); - lst.Dispose(); - Test.Assert(lst.Handle == IntPtr.Zero); Test.Assert(t.CheckEinaListStrshareOut()); t.Dispose(); } public static void test_eina_list_strshare_out_own() { var t = new Dummy.TestObject(); - Eina.List lst; + IList lst; Test.Assert(t.EinaListStrshareOutOwn(out lst)); - Test.Assert(lst.Own); Test.Assert(lst.ToArray().SequenceEqual(base_seq_strshare)); - lst.Append(append_seq_strshare); - lst.Dispose(); - Test.Assert(lst.Handle == IntPtr.Zero); + lst.Concat(append_seq_strshare); t.Dispose(); } public static void test_eina_list_strshare_return() { var t = new Dummy.TestObject(); var lst = t.EinaListStrshareReturn(); - Test.Assert(!lst.Own); Test.Assert(lst.ToArray().SequenceEqual(base_seq_strshare)); - lst.Dispose(); - Test.Assert(lst.Handle == IntPtr.Zero); Test.Assert(t.CheckEinaListStrshareReturn()); t.Dispose(); } public static void test_eina_list_strshare_return_own() { var t = new Dummy.TestObject(); var lst = t.EinaListStrshareReturnOwn(); - Test.Assert(lst.Own); Test.Assert(lst.ToArray().SequenceEqual(base_seq_strshare)); - lst.Append(append_seq_strshare); - lst.Dispose(); - Test.Assert(lst.Handle == IntPtr.Zero); + lst.Concat(append_seq_strshare); t.Dispose(); } // Object // public static void test_eina_list_obj_in() { var t = new Dummy.TestObject(); var lst = new Eina.List(); lst.Append(BaseSeqObj()); Test.Assert(t.EinaListObjIn(lst)); Test.Assert(lst.Own); NumberwrapperSequenceAssertEqual(lst.ToArray(), BaseSeqObj()); lst.Dispose(); Test.Assert(lst.Handle == IntPtr.Zero); t.Dispose(); } public static void test_eina_list_obj_in_own() { var t = new Dummy.TestObject(); var lst = new Eina.List(); lst.Append(BaseSeqObj()); Test.Assert(t.EinaListObjInOwn(lst)); - Test.Assert(!lst.Own); + Test.Assert(lst.Own); lst.Dispose(); Test.Assert(lst.Handle == IntPtr.Zero); Test.Assert(t.CheckEinaListObjInOwn()); t.Dispose(); } public static void test_eina_list_obj_out() { var t = new Dummy.TestObject(); - Eina.List lst; + IList lst; Test.Assert(t.EinaListObjOut(out lst)); - Test.Assert(!lst.Own); NumberwrapperSequenceAssertEqual(lst.ToArray(), BaseSeqObj()); - lst.Dispose(); - Test.Assert(lst.Handle == IntPtr.Zero); Test.Assert(t.CheckEinaListObjOut()); t.Dispose(); } public static void test_eina_list_obj_out_own() { var t = new Dummy.TestObject(); - Eina.List lst; + IList lst; Test.Assert(t.EinaListObjOutOwn(out lst)); - Test.Assert(lst.Own); NumberwrapperSequenceAssertEqual(lst.ToArray(), BaseSeqObj()); - lst.Append(AppendSeqObj()); - lst.Dispose(); - Test.Assert(lst.Handle == IntPtr.Zero); + lst.Concat(AppendSeqObj()); t.Dispose(); } public static void test_eina_list_obj_return() { var t = new Dummy.TestObject(); var lst = t.EinaListObjReturn(); - Test.Assert(!lst.Own); NumberwrapperSequenceAssertEqual(lst.ToArray(), BaseSeqObj()); - lst.Dispose(); - Test.Assert(lst.Handle == IntPtr.Zero); Test.Assert(t.CheckEinaListObjReturn()); t.Dispose(); } public static void test_eina_list_obj_return_own() { var t = new Dummy.TestObject(); var lst = t.EinaListObjReturnOwn(); - Test.Assert(lst.Own); NumberwrapperSequenceAssertEqual(lst.ToArray(), BaseSeqObj()); - lst.Append(AppendSeqObj()); - lst.Dispose(); - Test.Assert(lst.Handle == IntPtr.Zero); + lst.Concat(AppendSeqObj()); t.Dispose(); } public static void test_eina_list_obj_return_in_same_id() { var t = new Dummy.TestObject(); var cmp = BaseSeqObj(); var a = new Eina.List(); a.Append(cmp); var b = t.EinaListObjReturnIn(a); NumberwrapperSequenceAssertEqual(a.ToArray(), b.ToArray()); NumberwrapperSequenceAssertEqual(a.ToArray(), BaseSeqObj()); int len = a.Count; for (int i=0; i < len; ++i) { Test.Assert(a[i].NativeHandle == b[i].NativeHandle); Test.Assert(a[i].NativeHandle == cmp[i].NativeHandle); } a.Dispose(); t.Dispose(); } } class TestEinaInlist { public static void data_set_int() { var lst = new Eina.Inlist(); lst.Append(88); Test.Assert(lst[0] == 88); lst.DataSet(0, 44); Test.Assert(lst[0] == 44); lst[0] = 22; Test.Assert(lst[0] == 22); Test.Assert(lst.Count() == 1); lst.Dispose(); } public static void data_set_string() { var lst = new Eina.Inlist(); lst.Append("test string"); Test.Assert(lst[0] == "test string"); lst.DataSet(0, "other string"); Test.Assert(lst[0] == "other string"); lst[0] = "abc"; Test.Assert(lst[0] == "abc"); Test.Assert(lst.Count() == 1); lst.Dispose(); } public static void data_set_obj() { var lst = new Eina.Inlist(); var o1 = new Dummy.Numberwrapper(); o1.SetNumber(88); lst.Append(o1); Test.Assert(lst[0].NativeHandle == o1.NativeHandle); Test.Assert(lst[0].GetNumber() == 88); var o2 = new Dummy.Numberwrapper(); o2.SetNumber(44); lst.DataSet(0, o2); Test.Assert(lst[0].NativeHandle == o2.NativeHandle); Test.Assert(lst[0].GetNumber() == 44); var o3 = new Dummy.Numberwrapper(); o3.SetNumber(22); lst[0] = o3; Test.Assert(lst[0].NativeHandle == o3.NativeHandle); Test.Assert(lst[0].GetNumber() == 22); Test.Assert(lst.Count() == 1); o3.Dispose(); o2.Dispose(); o1.Dispose(); lst.Dispose(); } public static void append_count_int() { var lst = new Eina.Inlist(); Test.Assert(lst.Count() == 0); lst.Append(88); Test.Assert(lst[0] == 88); Test.Assert(lst.Count() == 1); lst.Append(44); Test.Assert(lst[1] == 44); Test.Assert(lst.Count() == 2); lst.Append(22); Test.Assert(lst[2] == 22); Test.Assert(lst.Count() == 3); lst.Dispose(); } public static void append_count_string() { var lst = new Eina.Inlist(); Test.Assert(lst.Count() == 0); lst.Append("a"); Test.Assert(lst[0] == "a"); Test.Assert(lst.Count() == 1); lst.Append("b"); Test.Assert(lst[1] == "b"); Test.Assert(lst.Count() == 2); lst.Append("c"); Test.Assert(lst[2] == "c"); Test.Assert(lst.Count() == 3); lst.Dispose(); } public static void append_count_obj() { var lst = new Eina.Inlist(); Test.Assert(lst.Count() == 0); var o1 = new Dummy.Numberwrapper(); o1.SetNumber(88); lst.Append(o1); Test.Assert(lst[0].NativeHandle == o1.NativeHandle); Test.Assert(lst[0].GetNumber() == 88); Test.Assert(lst.Count() == 1); var o2 = new Dummy.Numberwrapper(); o2.SetNumber(44); lst.Append(o2); Test.Assert(lst[1].NativeHandle == o2.NativeHandle); Test.Assert(lst[1].GetNumber() == 44); Test.Assert(lst.Count() == 2); var o3 = new Dummy.Numberwrapper(); o3.SetNumber(22); lst.Append(o3); Test.Assert(lst[2].NativeHandle == o3.NativeHandle); Test.Assert(lst[2].GetNumber() == 22); Test.Assert(lst.Count() == 3); o3.Dispose(); o2.Dispose(); o1.Dispose(); lst.Dispose(); } public static void length_int() { var lst = new Eina.Inlist(); Test.Assert(lst.Length == 0); lst.Append(88); Test.Assert(lst[0] == 88); Test.Assert(lst.Length == 1); lst.Append(44); Test.Assert(lst[1] == 44); Test.Assert(lst.Length == 2); lst.Append(22); Test.Assert(lst[2] == 22); Test.Assert(lst.Length == 3); lst.Dispose(); } public static void length_string() { var lst = new Eina.Inlist(); Test.Assert(lst.Length == 0); lst.Append("a"); Test.Assert(lst[0] == "a"); Test.Assert(lst.Length == 1); lst.Append("b"); Test.Assert(lst[1] == "b"); Test.Assert(lst.Length == 2); lst.Append("c"); Test.Assert(lst[2] == "c"); Test.Assert(lst.Length == 3); lst.Dispose(); } public static void prepend_count_int() { var lst = new Eina.Inlist(); Test.Assert(lst.Count() == 0); lst.Prepend(88); Test.Assert(lst[0] == 88); Test.Assert(lst.Count() == 1); lst.Prepend(44); Test.Assert(lst[0] == 44); Test.Assert(lst.Count() == 2); lst.Prepend(22); Test.Assert(lst[0] == 22); Test.Assert(lst.Count() == 3); lst.Dispose(); } public static void prepend_count_string() { var lst = new Eina.Inlist(); Test.Assert(lst.Count() == 0); lst.Prepend("a"); Test.Assert(lst[0] == "a"); Test.Assert(lst.Count() == 1); lst.Prepend("b"); Test.Assert(lst[0] == "b"); Test.Assert(lst.Count() == 2); lst.Prepend("c"); Test.Assert(lst[0] == "c"); Test.Assert(lst.Count() == 3); lst.Dispose(); } public static void prepend_count_obj() { var lst = new Eina.Inlist(); Test.Assert(lst.Count() == 0); var o1 = new Dummy.Numberwrapper(); o1.SetNumber(88); lst.Prepend(o1); Test.Assert(lst[0].NativeHandle == o1.NativeHandle); Test.Assert(lst[0].GetNumber() == 88); Test.Assert(lst.Count() == 1); var o2 = new Dummy.Numberwrapper(); o2.SetNumber(44); lst.Prepend(o2); Test.Assert(lst[0].NativeHandle == o2.NativeHandle); Test.Assert(lst[0].GetNumber() == 44); Test.Assert(lst.Count() == 2); var o3 = new Dummy.Numberwrapper(); o3.SetNumber(22); lst.Prepend(o3); Test.Assert(lst[0].NativeHandle == o3.NativeHandle); Test.Assert(lst[0].GetNumber() == 22); Test.Assert(lst.Count() == 3); o3.Dispose(); o2.Dispose(); o1.Dispose(); lst.Dispose(); } public static void eina_inlist_as_ienumerable_int() { var lst = new Eina.Inlist(); lst.Append(88); lst.Append(44); lst.Append(22); int cmp = 88; foreach (int e in lst) { Test.AssertEquals(cmp, e); cmp /= 2; } lst.Dispose(); } public static void eina_inlist_as_ienumerable_string() { var lst = new Eina.Inlist(); lst.Append("X"); lst.Append("XX"); lst.Append("XXX"); string cmp = "X"; foreach (string e in lst) { Test.AssertEquals(cmp, e); cmp = cmp + "X"; } lst.Dispose(); } public static void eina_inlist_as_ienumerable_obj() { var a = new Dummy.Numberwrapper(); var b = new Dummy.Numberwrapper(); var c = new Dummy.Numberwrapper(); a.SetNumber(88); b.SetNumber(44); c.SetNumber(22); var cmp = new Dummy.Numberwrapper[]{a, b, c}; var lst = new Eina.Inlist(); lst.Append(a); lst.Append(b); lst.Append(c); int i = 0; foreach (Dummy.Numberwrapper e in lst) { Test.AssertEquals(cmp[i].GetNumber(), e.GetNumber()); Test.Assert(cmp[i].NativeHandle == e.NativeHandle); ++i; } lst.Dispose(); } } // < TestEinaInlist #if EFL_BETA class TestEinaHash { public static void data_set_int() { var hsh = new Eina.Hash(); Test.Assert(hsh.Count == 0); hsh[88] = 888; Test.Assert(hsh[88] == 888); Test.Assert(hsh.Count == 1); hsh[44] = 444; Test.Assert(hsh[44] == 444); Test.Assert(hsh.Count == 2); hsh[22] = 222; Test.Assert(hsh[22] == 222); Test.Assert(hsh.Count == 3); hsh.Dispose(); } public static void data_set_str() { var hsh = new Eina.Hash(); Test.Assert(hsh.Count == 0); hsh["aa"] = "aaa"; Test.Assert(hsh["aa"] == "aaa"); Test.Assert(hsh.Count == 1); hsh["bb"] = "bbb"; Test.Assert(hsh["bb"] == "bbb"); Test.Assert(hsh.Count == 2); hsh["cc"] = "ccc"; Test.Assert(hsh["cc"] == "ccc"); Test.Assert(hsh.Count == 3); hsh.Dispose(); } public static void data_set_strshare() { var hsh = new Eina.Hash(); Test.Assert(hsh.Count == 0); hsh["aa"] = "aaa"; Test.Assert(hsh["aa"] == "aaa"); Test.Assert(hsh.Count == 1); hsh["bb"] = "bbb"; Test.Assert(hsh["bb"] == "bbb"); Test.Assert(hsh.Count == 2); hsh["cc"] = "ccc"; Test.Assert(hsh["cc"] == "ccc"); Test.Assert(hsh.Count == 3); hsh.Dispose(); } public static void data_set_obj() { var hsh = new Eina.Hash(); Test.Assert(hsh.Count == 0); var a = NW(22); var aa = NW(222); var b = NW(44); var bb = NW(444); var c = NW(88); var cc = NW(888); hsh[a] = aa; Test.Assert(hsh[a].NativeHandle == aa.NativeHandle); Test.Assert(hsh[a].GetNumber() == aa.GetNumber()); Test.Assert(hsh.Count == 1); hsh[b] = bb; Test.Assert(hsh[b].NativeHandle == bb.NativeHandle); Test.Assert(hsh[b].GetNumber() == bb.GetNumber()); Test.Assert(hsh.Count == 2); hsh[c] = cc; Test.Assert(hsh[c].NativeHandle == cc.NativeHandle); Test.Assert(hsh[c].GetNumber() == cc.GetNumber()); Test.Assert(hsh.Count == 3); c.Dispose(); b.Dispose(); a.Dispose(); hsh.Dispose(); } public static void eina_hash_as_ienumerable_int() { var hsh = new Eina.Hash(); var dct = new Dictionary(); hsh[88] = 888; hsh[44] = 444; hsh[22] = 222; dct[88] = 888; dct[44] = 444; dct[22] = 222; int count = 0; foreach (KeyValuePair kvp in hsh) { Test.Assert(dct[kvp.Key] == kvp.Value); dct.Remove(kvp.Key); ++count; } Test.AssertEquals(count, 3); Test.AssertEquals(dct.Count, 0); hsh.Dispose(); } public static void eina_hash_as_ienumerable_str() { var hsh = new Eina.Hash(); var dct = new Dictionary(); hsh["aa"] = "aaa"; hsh["bb"] = "bbb"; hsh["cc"] = "ccc"; dct["aa"] = "aaa"; dct["bb"] = "bbb"; dct["cc"] = "ccc"; int count = 0; foreach (KeyValuePair kvp in hsh) { Test.Assert(dct[kvp.Key] == kvp.Value); dct.Remove(kvp.Key); ++count; } Test.AssertEquals(count, 3); Test.AssertEquals(dct.Count, 0); hsh.Dispose(); } public static void eina_hash_as_ienumerable_strshare() { var hsh = new Eina.Hash(); var dct = new Dictionary(); hsh["aa"] = "aaa"; hsh["bb"] = "bbb"; hsh["cc"] = "ccc"; dct["aa"] = "aaa"; dct["bb"] = "bbb"; dct["cc"] = "ccc"; int count = 0; foreach (KeyValuePair kvp in hsh) { Test.Assert(dct[kvp.Key] == kvp.Value); dct.Remove(kvp.Key); ++count; } Test.AssertEquals(count, 3); Test.AssertEquals(dct.Count, 0); hsh.Dispose(); } public static void eina_hash_as_ienumerable_obj() { var hsh = new Eina.Hash(); var dct = new Dictionary(); var a = NW(22); var aa = NW(222); var b = NW(44); var bb = NW(444); var c = NW(88); var cc = NW(888); hsh[a] = aa; hsh[b] = bb; hsh[c] = cc; dct[a.GetNumber()] = aa; dct[b.GetNumber()] = bb; dct[c.GetNumber()] = cc; int count = 0; foreach (KeyValuePair kvp in hsh) { Test.Assert(dct[kvp.Key.GetNumber()].NativeHandle == kvp.Value.NativeHandle); Test.Assert(dct[kvp.Key.GetNumber()].GetNumber() == kvp.Value.GetNumber()); dct.Remove(kvp.Key.GetNumber()); ++count; } Test.AssertEquals(count, 3); Test.AssertEquals(dct.Count, 0); a.Dispose(); b.Dispose(); c.Dispose(); hsh.Dispose(); } // // // Code Generation // // Integer // public static void test_eina_hash_int_in() { var t = new Dummy.TestObject(); var hsh = new Eina.Hash(); hsh[22] = 222; Test.Assert(t.EinaHashIntIn(hsh)); Test.Assert(hsh.Own); Test.Assert(hsh[22] == 222); Test.Assert(hsh[44] == 444); hsh.Dispose(); Test.Assert(hsh.Handle == IntPtr.Zero); t.Dispose(); } /* public static void test_eina_hash_int_in_own() { var t = new Dummy.TestObject(); var hsh = new Eina.Hash(); hsh[22] = 222; Test.Assert(t.EinaHashIntInOwn(hsh)); Test.Assert(!hsh.Own); Test.Assert(hsh[22] == 222); Test.Assert(hsh[44] == 444); hsh[88] = 888; hsh.Dispose(); Test.Assert(hsh.Handle == IntPtr.Zero); Test.Assert(t.CheckEinaHashIntInOwn()); t.Dispose(); } */ public static void test_eina_hash_int_out() { var t = new Dummy.TestObject(); Eina.Hashhsh; Test.Assert(t.EinaHashIntOut(out hsh)); Test.Assert(!hsh.Own); Test.Assert(hsh[22] == 222); hsh[44] = 444; Test.Assert(hsh[44] == 444); hsh.Dispose(); Test.Assert(hsh.Handle == IntPtr.Zero); Test.Assert(t.CheckEinaHashIntOut()); t.Dispose(); } /* public static void test_eina_hash_int_out_own() { var t = new Dummy.TestObject(); Eina.Hash hsh; Test.Assert(t.EinaHashIntOutOwn(out hsh)); Test.Assert(hsh.Own); Test.Assert(hsh[22] == 222); hsh[44] = 444; Test.Assert(hsh[44] == 444); hsh.Dispose(); Test.Assert(hsh.Handle == IntPtr.Zero); Test.Assert(t.CheckEinaHashIntOutOwn()); t.Dispose(); } */ public static void test_eina_hash_int_return() { var t = new Dummy.TestObject(); var hsh = t.EinaHashIntReturn(); Test.Assert(!hsh.Own); Test.Assert(hsh[22] == 222); hsh[44] = 444; Test.Assert(hsh[44] == 444); hsh.Dispose(); Test.Assert(hsh.Handle == IntPtr.Zero); Test.Assert(t.CheckEinaHashIntReturn()); t.Dispose(); } /* public static void test_eina_hash_int_return_own() { var t = new Dummy.TestObject(); var hsh = t.EinaHashIntReturnOwn(); Test.Assert(hsh.Own); Test.Assert(hsh[22] == 222); hsh[44] = 444; Test.Assert(hsh[44] == 444); hsh.Dispose(); Test.Assert(hsh.Handle == IntPtr.Zero); Test.Assert(t.CheckEinaHashIntReturnOwn()); t.Dispose(); } */ // String // public static void test_eina_hash_str_in() { var t = new Dummy.TestObject(); var hsh = new Eina.Hash(); hsh["aa"] = "aaa"; Test.Assert(t.EinaHashStrIn(hsh)); Test.Assert(hsh.Own); Test.Assert(hsh["aa"] == "aaa"); Test.Assert(hsh["bb"] == "bbb"); hsh.Dispose(); Test.Assert(hsh.Handle == IntPtr.Zero); t.Dispose(); } public static void test_eina_hash_str_in_own() { var t = new Dummy.TestObject(); var hsh = new Eina.Hash(); hsh["aa"] = "aaa"; Test.Assert(t.EinaHashStrInOwn(hsh)); Test.Assert(!hsh.Own); Test.Assert(hsh["aa"] == "aaa"); Test.Assert(hsh["bb"] == "bbb"); hsh["cc"] = "ccc"; hsh.Dispose(); Test.Assert(hsh.Handle == IntPtr.Zero); Test.Assert(t.CheckEinaHashStrInOwn()); t.Dispose(); } public static void test_eina_hash_str_out() { var t = new Dummy.TestObject(); Eina.Hashhsh; Test.Assert(t.EinaHashStrOut(out hsh)); Test.Assert(!hsh.Own); Test.Assert(hsh["aa"] == "aaa"); hsh["bb"] = "bbb"; Test.Assert(hsh["bb"] == "bbb"); hsh.Dispose(); Test.Assert(hsh.Handle == IntPtr.Zero); Test.Assert(t.CheckEinaHashStrOut()); t.Dispose(); } public static void test_eina_hash_str_out_own() { var t = new Dummy.TestObject(); Eina.Hashhsh; Test.Assert(t.EinaHashStrOutOwn(out hsh)); Test.Assert(hsh.Own); Test.Assert(hsh["aa"] == "aaa"); hsh["bb"] = "bbb"; Test.Assert(hsh["bb"] == "bbb"); hsh.Dispose(); Test.Assert(hsh.Handle == IntPtr.Zero); Test.Assert(t.CheckEinaHashStrOutOwn()); t.Dispose(); } public static void test_eina_hash_str_return() { var t = new Dummy.TestObject(); var hsh = t.EinaHashStrReturn(); Test.Assert(!hsh.Own); Test.Assert(hsh["aa"] == "aaa"); hsh["bb"] = "bbb"; Test.Assert(hsh["bb"] == "bbb"); hsh.Dispose(); Test.Assert(hsh.Handle == IntPtr.Zero); Test.Assert(t.CheckEinaHashStrReturn()); t.Dispose(); } public static void test_eina_hash_str_return_own() { var t = new Dummy.TestObject(); var hsh = t.EinaHashStrReturnOwn(); Test.Assert(hsh.Own); Test.Assert(hsh["aa"] == "aaa"); hsh["bb"] = "bbb"; Test.Assert(hsh["bb"] == "bbb"); hsh.Dispose(); Test.Assert(hsh.Handle == IntPtr.Zero); Test.Assert(t.CheckEinaHashStrReturnOwn()); t.Dispose(); } // Eina.Stringshare // /*public static void test_eina_hash_strshare_in() { var t = new Dummy.TestObject(); var hsh = new Eina.Hash(); hsh["aa"] = "aaa"; Test.Assert(t.EinaHashStrshareIn(hsh)); Test.Assert(hsh.Own); Test.Assert(hsh["aa"] == "aaa"); Test.Assert(hsh["bb"] == "bbb"); hsh.Dispose(); Test.Assert(hsh.Handle == IntPtr.Zero); } public static void test_eina_hash_strshare_in_own() { var t = new Dummy.TestObject(); var hsh = new Eina.Hash(); hsh["aa"] = "aaa"; Test.Assert(t.EinaHashStrshareInOwn(hsh)); Test.Assert(!hsh.Own); Test.Assert(hsh["aa"] == "aaa"); Test.Assert(hsh["bb"] == "bbb"); hsh["cc"] = "ccc"; hsh.Dispose(); Test.Assert(hsh.Handle == IntPtr.Zero); Test.Assert(t.CheckEinaHashStrshareInOwn()); } public static void test_eina_hash_strshare_out() { var t = new Dummy.TestObject(); Eina.Hash hsh; Test.Assert(t.EinaHashStrshareOut(out hsh)); Test.Assert(!hsh.Own); Test.Assert(hsh["aa"] == "aaa"); hsh["bb"] = "bbb"; Test.Assert(hsh["bb"] == "bbb"); hsh.Dispose(); Test.Assert(hsh.Handle == IntPtr.Zero); Test.Assert(t.CheckEinaHashStrshareOut()); } public static void test_eina_hash_strshare_out_own() { var t = new Dummy.TestObject(); Eina.Hash hsh; Test.Assert(t.EinaHashStrshareOutOwn(out hsh)); Test.Assert(hsh.Own); Test.Assert(hsh["aa"] == "aaa"); hsh["bb"] = "bbb"; Test.Assert(hsh["bb"] == "bbb"); hsh.Dispose(); Test.Assert(hsh.Handle == IntPtr.Zero); Test.Assert(t.CheckEinaHashStrshareOutOwn()); } public static void test_eina_hash_strshare_return() { var t = new Dummy.TestObject(); var hsh = t.EinaHashStrshareReturn(); Test.Assert(!hsh.Own); Test.Assert(hsh["aa"] == "aaa"); hsh["bb"] = "bbb"; Test.Assert(hsh["bb"] == "bbb"); hsh.Dispose(); Test.Assert(hsh.Handle == IntPtr.Zero); Test.Assert(t.CheckEinaHashStrshareReturn()); } public static void test_eina_hash_strshare_return_own() { var t = new Dummy.TestObject(); var hsh = t.EinaHashStrshareReturnOwn(); Test.Assert(hsh.Own); Test.Assert(hsh["aa"] == "aaa"); hsh["bb"] = "bbb"; Test.Assert(hsh["bb"] == "bbb"); hsh.Dispose(); Test.Assert(hsh.Handle == IntPtr.Zero); Test.Assert(t.CheckEinaHashStrshareReturnOwn()); }*/ // Object // public static void test_eina_hash_obj_in() { var t = new Dummy.TestObject(); var hsh = new Eina.Hash(); var nwk1 = NW(22); var nwv1 = NW(222); hsh[nwk1] = nwv1; Dummy.Numberwrapper nwk2; Dummy.Numberwrapper nwv2; Test.Assert(t.EinaHashObjIn(hsh, nwk1, nwv1, out nwk2, out nwv2)); Test.Assert(hsh.Own); Test.Assert(hsh[nwk1].NativeHandle == nwv1.NativeHandle); Test.Assert(hsh[nwk1].GetNumber() == nwv1.GetNumber()); Test.Assert(hsh[nwk1].GetNumber() == 222); Test.Assert(hsh[nwk2].NativeHandle == nwv2.NativeHandle); Test.Assert(hsh[nwk2].GetNumber() == nwv2.GetNumber()); Test.Assert(hsh[nwk2].GetNumber() == 444); nwk1.Dispose(); nwk2.Dispose(); nwv1.Dispose(); nwv2.Dispose(); hsh.Dispose(); Test.Assert(hsh.Handle == IntPtr.Zero); t.Dispose(); } public static void test_eina_hash_obj_in_own() { var t = new Dummy.TestObject(); var hsh = new Eina.Hash(); var nwk1 = NW(22); var nwv1 = NW(222); hsh[nwk1] = nwv1; Dummy.Numberwrapper nwk2; Dummy.Numberwrapper nwv2; Test.Assert(t.EinaHashObjInOwn(hsh, nwk1, nwv1, out nwk2, out nwv2)); Test.Assert(!hsh.Own); Test.Assert(hsh[nwk1].NativeHandle == nwv1.NativeHandle); Test.Assert(hsh[nwk1].GetNumber() == nwv1.GetNumber()); Test.Assert(hsh[nwk1].GetNumber() == 222); Test.Assert(hsh[nwk2].NativeHandle == nwv2.NativeHandle); Test.Assert(hsh[nwk2].GetNumber() == nwv2.GetNumber()); Test.Assert(hsh[nwk2].GetNumber() == 444); hsh.Dispose(); Test.Assert(hsh.Handle == IntPtr.Zero); Test.Assert(t.CheckEinaHashObjInOwn(nwk1, nwv1, nwk2, nwv2)); nwk1.Dispose(); nwk2.Dispose(); nwv1.Dispose(); nwv2.Dispose(); t.Dispose(); } public static void test_eina_hash_obj_out() { var t = new Dummy.TestObject(); Eina.Hash hsh; Dummy.Numberwrapper nwk1; Dummy.Numberwrapper nwv1; Test.Assert(t.EinaHashObjOut(out hsh, out nwk1, out nwv1)); Test.Assert(!hsh.Own); Test.Assert(hsh[nwk1].NativeHandle == nwv1.NativeHandle); Test.Assert(hsh[nwk1].GetNumber() == nwv1.GetNumber()); Test.Assert(hsh[nwk1].GetNumber() == 222); Dummy.Numberwrapper nwk2 = NW(44); Dummy.Numberwrapper nwv2 = NW(444); hsh[nwk2] = nwv2; hsh.Dispose(); Test.Assert(hsh.Handle == IntPtr.Zero); Test.Assert(t.CheckEinaHashObjOut(nwk1, nwv1, nwk2, nwv2)); nwk1.Dispose(); nwk2.Dispose(); nwv1.Dispose(); nwv2.Dispose(); t.Dispose(); } public static void test_eina_hash_obj_out_own() { var t = new Dummy.TestObject(); Eina.Hash hsh; Dummy.Numberwrapper nwk1; Dummy.Numberwrapper nwv1; Test.Assert(t.EinaHashObjOutOwn(out hsh, out nwk1, out nwv1)); Test.Assert(hsh.Own); Test.Assert(hsh[nwk1].NativeHandle == nwv1.NativeHandle); Test.Assert(hsh[nwk1].GetNumber() == nwv1.GetNumber()); Test.Assert(hsh[nwk1].GetNumber() == 222); Dummy.Numberwrapper nwk2 = NW(44); Dummy.Numberwrapper nwv2 = NW(444); hsh[nwk2] = nwv2; nwk1.Dispose(); nwk2.Dispose(); nwv1.Dispose(); nwv2.Dispose(); hsh.Dispose(); Test.Assert(hsh.Handle == IntPtr.Zero); Test.Assert(t.CheckEinaHashObjOutOwn()); t.Dispose(); } public static void test_eina_hash_obj_return() { var t = new Dummy.TestObject(); Dummy.Numberwrapper nwk1; Dummy.Numberwrapper nwv1; var hsh = t.EinaHashObjReturn(out nwk1, out nwv1); Test.Assert(!hsh.Own); Test.Assert(hsh[nwk1].NativeHandle == nwv1.NativeHandle); Test.Assert(hsh[nwk1].GetNumber() == nwv1.GetNumber()); Test.Assert(hsh[nwk1].GetNumber() == 222); Dummy.Numberwrapper nwk2 = NW(44); Dummy.Numberwrapper nwv2 = NW(444); hsh[nwk2] = nwv2; hsh.Dispose(); Test.Assert(hsh.Handle == IntPtr.Zero); Test.Assert(t.CheckEinaHashObjReturn(nwk1, nwv1, nwk2, nwv2)); nwk1.Dispose(); nwk2.Dispose(); nwv1.Dispose(); nwv2.Dispose(); t.Dispose(); } public static void test_eina_hash_obj_return_own() { var t = new Dummy.TestObject(); Dummy.Numberwrapper nwk1; Dummy.Numberwrapper nwv1; var hsh = t.EinaHashObjReturnOwn(out nwk1, out nwv1); Test.Assert(hsh.Own); Test.Assert(hsh[nwk1].NativeHandle == nwv1.NativeHandle); Test.Assert(hsh[nwk1].GetNumber() == nwv1.GetNumber()); Test.Assert(hsh[nwk1].GetNumber() == 222); Dummy.Numberwrapper nwk2 = NW(44); Dummy.Numberwrapper nwv2 = NW(444); hsh[nwk2] = nwv2; nwk1.Dispose(); nwk2.Dispose(); nwv1.Dispose(); nwv2.Dispose(); hsh.Dispose(); Test.Assert(hsh.Handle == IntPtr.Zero); Test.Assert(t.CheckEinaHashObjReturnOwn()); t.Dispose(); } } #endif // EFL_BETA class TestEinaIterator { public static void SetUp() { Dummy.TestObject.CreateCmpArrayObjects(); } public static void TearDown() { Dummy.TestObject.DestroyCmpArrayObjects(); } // Array // public static void eina_array_int_empty_iterator() { var arr = new Eina.Array(); var itr = arr.GetIterator(); int idx = 0; foreach (int e in itr) { ++idx; } Test.AssertEquals(idx, 0); itr.Dispose(); arr.Dispose(); } public static void eina_array_int_filled_iterator() { var arr = new Eina.Array(); arr.Append(base_seq_int); var itr = arr.GetIterator(); int idx = 0; foreach (int e in itr) { Test.Assert(e == base_seq_int[idx]); ++idx; } Test.AssertEquals(idx, base_seq_int.Length); itr.Dispose(); arr.Dispose(); } public static void eina_array_str_empty_iterator() { var arr = new Eina.Array(); var itr = arr.GetIterator(); int idx = 0; foreach (string e in itr) { ++idx; } Test.AssertEquals(idx, 0); itr.Dispose(); arr.Dispose(); } public static void eina_array_str_filled_iterator() { var arr = new Eina.Array(); arr.Append(base_seq_str); var itr = arr.GetIterator(); int idx = 0; foreach (string e in itr) { Test.Assert(e == base_seq_str[idx]); ++idx; } Test.AssertEquals(idx, base_seq_str.Length); itr.Dispose(); arr.Dispose(); } public static void eina_array_strshare_empty_iterator() { var arr = new Eina.Array(); var itr = arr.GetIterator(); int idx = 0; foreach (string e in itr) { ++idx; } Test.AssertEquals(idx, 0); itr.Dispose(); arr.Dispose(); } public static void eina_array_strshare_filled_iterator() { var arr = new Eina.Array(); arr.Append(base_seq_strshare); var itr = arr.GetIterator(); int idx = 0; foreach (string e in itr) { Test.Assert(e == base_seq_strshare[idx]); ++idx; } Test.AssertEquals(idx, base_seq_strshare.Length); itr.Dispose(); arr.Dispose(); } public static void eina_array_obj_empty_iterator() { var arr = new Eina.Array(); var itr = arr.GetIterator(); int idx = 0; foreach (Dummy.Numberwrapper e in itr) { ++idx; } Test.AssertEquals(idx, 0); itr.Dispose(); arr.Dispose(); } public static void eina_array_obj_filled_iterator() { var arr = new Eina.Array(); var base_objs = BaseSeqObj(); arr.Append(base_objs); var itr = arr.GetIterator(); int idx = 0; foreach (Dummy.Numberwrapper e in itr) { Test.Assert(e.NativeHandle == base_objs[idx].NativeHandle); Test.Assert(e.GetNumber() == base_objs[idx].GetNumber()); ++idx; } Test.AssertEquals(idx, base_objs.Length); itr.Dispose(); arr.Dispose(); } // Inarray public static void eina_inarray_int_empty_iterator() { var arr = new Eina.Inarray(); var itr = arr.GetIterator(); int idx = 0; foreach (int e in itr) { ++idx; } Test.AssertEquals(idx, 0); itr.Dispose(); arr.Dispose(); } public static void eina_inarray_int_filled_iterator() { var arr = new Eina.Inarray(); arr.Append(base_seq_int); var itr = arr.GetIterator(); int idx = 0; foreach (int e in itr) { Test.Assert(e == base_seq_int[idx]); ++idx; } Test.AssertEquals(idx, base_seq_int.Length); itr.Dispose(); arr.Dispose(); } // List // public static void eina_list_int_empty_iterator() { var lst = new Eina.List(); var itr = lst.GetIterator(); int idx = 0; foreach (int e in itr) { ++idx; } Test.AssertEquals(idx, 0); itr.Dispose(); lst.Dispose(); } public static void eina_list_int_filled_iterator() { var lst = new Eina.List(); lst.Append(base_seq_int); var itr = lst.GetIterator(); int idx = 0; foreach (int e in itr) { Test.Assert(e == base_seq_int[idx]); ++idx; } Test.AssertEquals(idx, base_seq_int.Length); itr.Dispose(); lst.Dispose(); } public static void eina_list_str_empty_iterator() { var lst = new Eina.List(); var itr = lst.GetIterator(); int idx = 0; foreach (string e in itr) { ++idx; } Test.AssertEquals(idx, 0); itr.Dispose(); lst.Dispose(); } public static void eina_list_str_filled_iterator() { var lst = new Eina.List(); lst.Append(base_seq_str); var itr = lst.GetIterator(); int idx = 0; foreach (string e in itr) { Test.Assert(e == base_seq_str[idx]); ++idx; } Test.AssertEquals(idx, base_seq_str.Length); itr.Dispose(); lst.Dispose(); } public static void eina_list_strshare_empty_iterator() { var lst = new Eina.List(); var itr = lst.GetIterator(); int idx = 0; foreach (string e in itr) { ++idx; } Test.AssertEquals(idx, 0); itr.Dispose(); lst.Dispose(); } public static void eina_list_strshare_filled_iterator() { var lst = new Eina.List(); lst.Append(base_seq_strshare); var itr = lst.GetIterator(); int idx = 0; foreach (string e in itr) { Test.Assert(e == base_seq_strshare[idx]); ++idx; } Test.AssertEquals(idx, base_seq_strshare.Length); itr.Dispose(); lst.Dispose(); } public static void eina_list_obj_empty_iterator() { var lst = new Eina.List(); var itr = lst.GetIterator(); int idx = 0; foreach (Dummy.Numberwrapper e in itr) { ++idx; } Test.AssertEquals(idx, 0); itr.Dispose(); lst.Dispose(); } public static void eina_list_obj_filled_iterator() { var lst = new Eina.List(); var base_objs = BaseSeqObj(); lst.Append(base_objs); var itr = lst.GetIterator(); int idx = 0; foreach (Dummy.Numberwrapper e in itr) { Test.Assert(e.NativeHandle == base_objs[idx].NativeHandle); Test.Assert(e.GetNumber() == base_objs[idx].GetNumber()); ++idx; } Test.AssertEquals(idx, base_objs.Length); itr.Dispose(); lst.Dispose(); } // Inlist // public static void eina_inlist_int_empty_iterator() { var lst = new Eina.Inlist(); var itr = lst.GetIterator(); int idx = 0; foreach (int e in itr) { ++idx; } Test.AssertEquals(idx, 0); itr.Dispose(); lst.Dispose(); } public static void eina_inlist_int_filled_iterator() { var lst = new Eina.Inlist(); lst.AppendArray(base_seq_int); var itr = lst.GetIterator(); int idx = 0; foreach (int e in itr) { Test.Assert(e == base_seq_int[idx]); ++idx; } Test.AssertEquals(idx, base_seq_int.Length); itr.Dispose(); lst.Dispose(); } // Hash // public static void eina_hash_keys_int_empty_iterator() { var hsh = new Eina.Hash(); var itr = hsh.Keys(); bool entered = false; foreach (int e in itr) { entered = true; } Test.Assert(!entered); itr.Dispose(); hsh.Dispose(); } public static void eina_hash_values_int_empty_iterator() { var hsh = new Eina.Hash(); var itr = hsh.Values(); bool entered = false; foreach (int e in itr) { entered = true; } Test.Assert(!entered); itr.Dispose(); hsh.Dispose(); } public static void eina_hash_keys_int_filled_iterator() { var hsh = new Eina.Hash(); var dct = new Dictionary(); hsh[22] = 222; hsh[44] = 444; hsh[88] = 888; dct[22] = true; dct[44] = true; dct[88] = true; var itr = hsh.Keys(); int idx = 0; foreach (int e in itr) { Test.Assert(dct[e]); dct.Remove(e); ++idx; } Test.AssertEquals(dct.Count, 0); Test.AssertEquals(idx, 3); itr.Dispose(); hsh.Dispose(); } public static void eina_hash_values_int_filled_iterator() { var hsh = new Eina.Hash(); var dct = new Dictionary(); hsh[22] = 222; hsh[44] = 444; hsh[88] = 888; dct[222] = true; dct[444] = true; dct[888] = true; var itr = hsh.Values(); int idx = 0; foreach (int e in itr) { Test.Assert(dct[e]); dct.Remove(e); ++idx; } Test.AssertEquals(dct.Count, 0); Test.AssertEquals(idx, 3); itr.Dispose(); hsh.Dispose(); } public static void eina_hash_keys_str_empty_iterator() { var hsh = new Eina.Hash(); var itr = hsh.Keys(); bool entered = false; foreach (string e in itr) { entered = true; } Test.Assert(!entered); itr.Dispose(); hsh.Dispose(); } public static void eina_hash_values_str_empty_iterator() { var hsh = new Eina.Hash(); var itr = hsh.Values(); bool entered = false; foreach (string e in itr) { entered = true; } Test.Assert(!entered); itr.Dispose(); hsh.Dispose(); } public static void eina_hash_keys_str_filled_iterator() { var hsh = new Eina.Hash(); var dct = new Dictionary(); hsh["aa"] = "aaa"; hsh["bb"] = "bbb"; hsh["cc"] = "ccc"; dct["aa"] = true; dct["bb"] = true; dct["cc"] = true; var itr = hsh.Keys(); int idx = 0; foreach (string e in itr) { Test.Assert(dct[e]); dct.Remove(e); ++idx; } Test.AssertEquals(dct.Count, 0); Test.AssertEquals(idx, 3); itr.Dispose(); hsh.Dispose(); } public static void eina_hash_values_str_filled_iterator() { var hsh = new Eina.Hash(); var dct = new Dictionary(); hsh["aa"] = "aaa"; hsh["bb"] = "bbb"; hsh["cc"] = "ccc"; dct["aaa"] = true; dct["bbb"] = true; dct["ccc"] = true; var itr = hsh.Values(); int idx = 0; foreach (string e in itr) { Test.Assert(dct[e]); dct.Remove(e); ++idx; } Test.AssertEquals(dct.Count, 0); Test.AssertEquals(idx, 3); itr.Dispose(); hsh.Dispose(); } /* public static void eina_hash_keys_strshare_empty_iterator() { var hsh = new Eina.Hash(); var itr = hsh.Keys(); bool entered = false; foreach (string e in itr) { entered = true; } Test.Assert(!entered); itr.Dispose(); hsh.Dispose(); } public static void eina_hash_values_strshare_empty_iterator() { var hsh = new Eina.Hash(); var itr = hsh.Values(); bool entered = false; foreach (string e in itr) { entered = true; } Test.Assert(!entered); itr.Dispose(); hsh.Dispose(); } public static void eina_hash_keys_strshare_filled_iterator() { var hsh = new Eina.Hash(); var dct = new Dictionary(); hsh["aa"] = "aaa"; hsh["bb"] = "bbb"; hsh["cc"] = "ccc"; dct["aa"] = true; dct["bb"] = true; dct["cc"] = true; var itr = hsh.Keys(); int idx = 0; foreach (string e in itr) { Test.Assert(dct[e]); dct.Remove(e); ++idx; } Test.AssertEquals(dct.Count, 0); Test.AssertEquals(idx, 3); itr.Dispose(); hsh.Dispose(); } public static void eina_hash_values_strshare_filled_iterator() { var hsh = new Eina.Hash(); var dct = new Dictionary(); hsh["aa"] = "aaa"; hsh["bb"] = "bbb"; hsh["cc"] = "ccc"; dct["aaa"] = true; dct["bbb"] = true; dct["ccc"] = true; var itr = hsh.Values(); int idx = 0; foreach (string e in itr) { Test.Assert(dct[e]); dct.Remove(e); ++idx; } Test.AssertEquals(dct.Count, 0); Test.AssertEquals(idx, 3); itr.Dispose(); hsh.Dispose(); } */ public static void eina_hash_keys_obj_empty_iterator() { var hsh = new Eina.Hash(); var itr = hsh.Keys(); bool entered = false; foreach (Dummy.Numberwrapper e in itr) { entered = true; } Test.Assert(!entered); itr.Dispose(); hsh.Dispose(); } public static void eina_hash_values_obj_empty_iterator() { var hsh = new Eina.Hash(); var itr = hsh.Values(); bool entered = false; foreach (Dummy.Numberwrapper e in itr) { entered = true; } Test.Assert(!entered); itr.Dispose(); hsh.Dispose(); } public static void eina_hash_keys_obj_filled_iterator() { var hsh = new Eina.Hash(); var dct = new Eina.Hash(); var a = NW(22); var b = NW(44); var c = NW(88); var aa = NW(222); var bb = NW(444); var cc = NW(888); hsh[a] = aa; hsh[b] = bb; hsh[c] = cc; dct[a.GetNumber()] = a; dct[b.GetNumber()] = b; dct[c.GetNumber()] = c; var itr = hsh.Keys(); int idx = 0; foreach (Dummy.Numberwrapper e in itr) { Test.Assert(dct[e.GetNumber()] != null); Test.Assert(dct[e.GetNumber()].NativeHandle == e.NativeHandle); Test.Assert(dct[e.GetNumber()].GetNumber() == e.GetNumber()); dct.Remove(e.GetNumber()); ++idx; } Test.AssertEquals(dct.Count, 0); Test.AssertEquals(idx, 3); itr.Dispose(); dct.Dispose(); hsh.Dispose(); } public static void eina_hash_values_obj_filled_iterator() { var hsh = new Eina.Hash(); var dct = new Eina.Hash(); var a = NW(22); var b = NW(44); var c = NW(88); var aa = NW(222); var bb = NW(444); var cc = NW(888); hsh[a] = aa; hsh[b] = bb; hsh[c] = cc; dct[aa.GetNumber()] = aa; dct[bb.GetNumber()] = bb; dct[cc.GetNumber()] = cc; var itr = hsh.Values(); int idx = 0; foreach (Dummy.Numberwrapper e in itr) { Test.Assert(dct[e.GetNumber()] != null); Test.Assert(dct[e.GetNumber()].NativeHandle == e.NativeHandle); Test.Assert(dct[e.GetNumber()].GetNumber() == e.GetNumber()); dct.Remove(e.GetNumber()); ++idx; } Test.AssertEquals(dct.Count, 0); Test.AssertEquals(idx, 3); itr.Dispose(); a.Dispose(); b.Dispose(); c.Dispose(); dct.Dispose(); hsh.Dispose(); } // // // Code Generation // // Integer // public static void test_eina_iterator_int_in() { var t = new Dummy.TestObject(); var arr = new Eina.Array(); arr.Append(base_seq_int); var itr = arr.GetIterator(); Test.Assert(itr.Own); Test.Assert(arr.Own); Test.Assert(arr.OwnContent); Test.Assert(t.EinaIteratorIntIn(itr)); Test.Assert(itr.Own); Test.Assert(arr.Own); Test.Assert(arr.OwnContent); itr.Dispose(); arr.Dispose(); t.Dispose(); } public static void test_eina_iterator_int_in_own() { var t = new Dummy.TestObject(); var arr = new Eina.Array(); arr.Append(base_seq_int); var itr = arr.GetIterator(); Test.Assert(itr.Own); Test.Assert(arr.Own); Test.Assert(arr.OwnContent); // Will copy the Iterator, owning the copy. Test.Assert(t.EinaIteratorIntInOwn(itr)); Test.Assert(itr.Own); Test.Assert(arr.Own); // Content must continue to be owned by the array Test.Assert(arr.OwnContent); itr.Dispose(); arr.Dispose(); Test.Assert(t.CheckEinaIteratorIntInOwn()); t.Dispose(); } public static void test_eina_iterator_int_out() { var t = new Dummy.TestObject(); IEnumerable itr; Test.Assert(t.EinaIteratorIntOut(out itr)); int idx = 0; foreach (int e in itr) { Test.AssertEquals(e, base_seq_int[idx]); ++idx; } Test.AssertEquals(idx, base_seq_int.Length); Test.Assert(t.CheckEinaIteratorIntOut()); t.Dispose(); } public static void test_eina_iterator_int_out_own() { var t = new Dummy.TestObject(); IEnumerable itr; Test.Assert(t.EinaIteratorIntOutOwn(out itr)); int idx = 0; foreach (int e in itr) { Test.AssertEquals(e, base_seq_int[idx]); ++idx; } Test.AssertEquals(idx, base_seq_int.Length); t.Dispose(); } public static void test_eina_iterator_int_return() { var t = new Dummy.TestObject(); var itr = t.EinaIteratorIntReturn(); int idx = 0; foreach (int e in itr) { Test.AssertEquals(e, base_seq_int[idx]); ++idx; } Test.AssertEquals(idx, base_seq_int.Length); Test.Assert(t.CheckEinaIteratorIntReturn()); t.Dispose(); } public static void test_eina_iterator_int_return_own() { var t = new Dummy.TestObject(); var itr = t.EinaIteratorIntReturnOwn(); int idx = 0; foreach (int e in itr) { Test.AssertEquals(e, base_seq_int[idx]); ++idx; } Test.AssertEquals(idx, base_seq_int.Length); t.Dispose(); } // String // public static void test_eina_iterator_str_in() { var t = new Dummy.TestObject(); var arr = new Eina.Array(); arr.Append(base_seq_str); var itr = arr.GetIterator(); Test.Assert(itr.Own); Test.Assert(arr.Own); Test.Assert(arr.OwnContent); Test.Assert(t.EinaIteratorStrIn(itr)); Test.Assert(itr.Own); Test.Assert(arr.Own); Test.Assert(arr.OwnContent); itr.Dispose(); arr.Dispose(); t.Dispose(); } public static void test_eina_iterator_str_in_own() { var t = new Dummy.TestObject(); var arr = new Eina.Array(); arr.Append(base_seq_str); var itr = arr.GetIterator(); Test.Assert(itr.Own); Test.Assert(arr.Own); Test.Assert(arr.OwnContent); Test.Assert(t.EinaIteratorStrInOwn(itr)); Test.Assert(itr.Own); Test.Assert(arr.Own); Test.Assert(arr.OwnContent); itr.Dispose(); arr.Dispose(); Test.Assert(t.CheckEinaIteratorStrInOwn()); t.Dispose(); } public static void test_eina_iterator_str_out() { var t = new Dummy.TestObject(); IEnumerable itr; Test.Assert(t.EinaIteratorStrOut(out itr)); int idx = 0; foreach (string e in itr) { Test.AssertEquals(e, base_seq_str[idx]); ++idx; } Test.AssertEquals(idx, base_seq_str.Length); Test.Assert(t.CheckEinaIteratorStrOut()); t.Dispose(); } public static void test_eina_iterator_str_out_own() { var t = new Dummy.TestObject(); IEnumerable itr; Test.Assert(t.EinaIteratorStrOutOwn(out itr)); int idx = 0; foreach (string e in itr) { Test.AssertEquals(e, base_seq_str[idx]); ++idx; } Test.AssertEquals(idx, base_seq_str.Length); t.Dispose(); } public static void test_eina_iterator_str_return() { var t = new Dummy.TestObject(); var itr = t.EinaIteratorStrReturn(); int idx = 0; foreach (string e in itr) { Test.AssertEquals(e, base_seq_str[idx]); ++idx; } Test.AssertEquals(idx, base_seq_str.Length); Test.Assert(t.CheckEinaIteratorStrReturn()); t.Dispose(); } public static void test_eina_iterator_str_return_own() { var t = new Dummy.TestObject(); var itr = t.EinaIteratorStrReturnOwn(); int idx = 0; foreach (string e in itr) { Test.AssertEquals(e, base_seq_str[idx]); ++idx; } Test.AssertEquals(idx, base_seq_str.Length); t.Dispose(); } // Eina.Stringshare // public static void test_eina_iterator_strshare_in() { var t = new Dummy.TestObject(); var arr = new Eina.Array(); arr.Append(base_seq_strshare); var itr = arr.GetIterator(); Test.Assert(itr.Own); Test.Assert(arr.Own); Test.Assert(arr.OwnContent); Test.Assert(t.EinaIteratorStrshareIn(itr)); Test.Assert(itr.Own); Test.Assert(arr.Own); Test.Assert(arr.OwnContent); itr.Dispose(); arr.Dispose(); t.Dispose(); } public static void test_eina_iterator_strshare_in_own() { var t = new Dummy.TestObject(); var arr = new Eina.Array(); arr.Append(base_seq_strshare); var itr = arr.GetIterator(); Test.Assert(itr.Own); Test.Assert(arr.Own); Test.Assert(arr.OwnContent); Test.Assert(t.EinaIteratorStrshareInOwn(itr)); // Moving collections currently copy them, should not reflect on managed objects. Test.Assert(itr.Own); Test.Assert(arr.Own); Test.Assert(arr.OwnContent); itr.Dispose(); arr.Dispose(); Test.Assert(t.CheckEinaIteratorStrshareInOwn()); t.Dispose(); } public static void test_eina_iterator_strshare_out() { var t = new Dummy.TestObject(); IEnumerable itr; Test.Assert(t.EinaIteratorStrshareOut(out itr)); int idx = 0; foreach (Eina.Stringshare e in itr) { Test.AssertEquals(e, base_seq_strshare[idx]); ++idx; } Test.AssertEquals(idx, base_seq_strshare.Length); Test.Assert(t.CheckEinaIteratorStrshareOut()); t.Dispose(); } public static void test_eina_iterator_strshare_out_own() { var t = new Dummy.TestObject(); IEnumerable itr; Test.Assert(t.EinaIteratorStrshareOutOwn(out itr)); int idx = 0; foreach (Eina.Stringshare e in itr) { Test.AssertEquals(e, base_seq_strshare[idx]); ++idx; } Test.AssertEquals(idx, base_seq_strshare.Length); t.Dispose(); } public static void test_eina_iterator_strshare_return() { var t = new Dummy.TestObject(); var itr = t.EinaIteratorStrshareReturn(); int idx = 0; foreach (Eina.Stringshare e in itr) { Test.AssertEquals(e, base_seq_strshare[idx]); ++idx; } Test.AssertEquals(idx, base_seq_strshare.Length); Test.Assert(t.CheckEinaIteratorStrshareReturn()); t.Dispose(); } public static void test_eina_iterator_strshare_return_own() { var t = new Dummy.TestObject(); var itr = t.EinaIteratorStrshareReturnOwn(); int idx = 0; foreach (Eina.Stringshare e in itr) { Test.AssertEquals(e, base_seq_strshare[idx]); ++idx; } Test.AssertEquals(idx, base_seq_strshare.Length); t.Dispose(); } // Object // public static void test_eina_iterator_obj_in() { var t = new Dummy.TestObject(); var arr = new Eina.Array(); arr.Append(BaseSeqObj()); var itr = arr.GetIterator(); Test.Assert(itr.Own); Test.Assert(arr.Own); Test.Assert(arr.OwnContent); Test.Assert(t.EinaIteratorObjIn(itr)); Test.Assert(itr.Own); Test.Assert(arr.Own); Test.Assert(arr.OwnContent); itr.Dispose(); arr.Dispose(); t.Dispose(); } public static void test_eina_iterator_obj_in_own() { var t = new Dummy.TestObject(); var arr = new Eina.Array(); arr.Append(BaseSeqObj()); var itr = arr.GetIterator(); Test.Assert(itr.Own); Test.Assert(arr.Own); Test.Assert(arr.OwnContent); Test.Assert(t.EinaIteratorObjInOwn(itr)); Test.Assert(itr.Own); Test.Assert(arr.Own); Test.Assert(arr.OwnContent); itr.Dispose(); arr.Dispose(); Test.Assert(t.CheckEinaIteratorObjInOwn()); t.Dispose(); } public static void test_eina_iterator_obj_out() { var t = new Dummy.TestObject(); IEnumerable itr; Test.Assert(t.EinaIteratorObjOut(out itr)); var base_seq_obj = BaseSeqObj(); int idx = 0; foreach (Dummy.Numberwrapper e in itr) { Test.AssertEquals(e.GetNumber(), base_seq_obj[idx].GetNumber()); ++idx; } Test.AssertEquals(idx, base_seq_obj.Length); Test.Assert(t.CheckEinaIteratorObjOut()); t.Dispose(); } public static void test_eina_iterator_obj_out_own() { var t = new Dummy.TestObject(); IEnumerable itr; Test.Assert(t.EinaIteratorObjOutOwn(out itr)); var base_seq_obj = BaseSeqObj(); int idx = 0; foreach (Dummy.Numberwrapper e in itr) { Test.AssertEquals(e.GetNumber(), base_seq_obj[idx].GetNumber()); ++idx; } Test.AssertEquals(idx, base_seq_obj.Length); t.Dispose(); } public static void test_eina_iterator_obj_return() { var t = new Dummy.TestObject(); var itr = t.EinaIteratorObjReturn(); var base_seq_obj = BaseSeqObj(); int idx = 0; foreach (Dummy.Numberwrapper e in itr) { Test.AssertEquals(e.GetNumber(), base_seq_obj[idx].GetNumber()); ++idx; } Test.AssertEquals(idx, base_seq_obj.Length); Test.Assert(t.CheckEinaIteratorObjReturn()); t.Dispose(); } public static void test_eina_iterator_obj_return_own() { var t = new Dummy.TestObject(); var itr = t.EinaIteratorObjReturnOwn(); var base_seq_obj = BaseSeqObj(); int idx = 0; foreach (Dummy.Numberwrapper e in itr) { Test.AssertEquals(e.GetNumber(), base_seq_obj[idx].GetNumber()); ++idx; } Test.AssertEquals(idx, base_seq_obj.Length); t.Dispose(); } } // < TestEinaIterator class TestEinaAccessor { public static void basic_accessor_list() { var lst = new Eina.List(); lst.Append(1); lst.Append(2); lst.Append(3); lst.Append(4); Eina.Accessor accessor = lst.GetAccessor(); var zipped = accessor.Zip(lst, (first, second) => new Tuple(first, second)); foreach (Tuple pair in zipped) { Test.AssertEquals(pair.Item1, pair.Item2); } IEnumerable seq = accessor; Test.AssertEquals(seq.Count(), 4); lst.Dispose(); } public static void basic_accessor_array() { var arr = new Eina.Array(); arr.Append(base_seq_str); Eina.Accessor accessor = arr.GetAccessor(); var zipped = accessor.Zip(arr, (first, second) => new Tuple(first, second)); foreach (Tuple pair in zipped) { Test.AssertEquals(pair.Item1, pair.Item2); } arr.Dispose(); } public static void basic_accessor_inlist() { var lst = new Eina.Inlist(); lst.Append(1); lst.Append(2); lst.Append(3); lst.Append(4); Eina.Accessor accessor = lst.GetAccessor(); var zipped = accessor.Zip(lst, (first, second) => new Tuple(first, second)); foreach (Tuple pair in zipped) { Test.AssertEquals(pair.Item1, pair.Item2); } lst.Dispose(); } public static void basic_accessor_inarray() { var arr = new Eina.Inarray(); arr.Append(base_seq_int); Eina.Accessor accessor = arr.GetAccessor(); var zipped = accessor.Zip(arr, (first, second) => new Tuple(first, second)); foreach (Tuple pair in zipped) { Test.AssertEquals(pair.Item1, pair.Item2); } arr.Dispose(); } } class TestEinaLog { public static void basic_log_usage() { Eina.Log.Error("This should work"); } } } diff --git a/src/tests/efl_mono/Events.cs b/src/tests/efl_mono/Events.cs index 824d9a132c..5f8cc0fa52 100644 --- a/src/tests/efl_mono/Events.cs +++ b/src/tests/efl_mono/Events.cs @@ -1,369 +1,369 @@ /* * Copyright 2019 by its authors. See AUTHORS. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; using System.Linq; +using System.Collections.Generic; namespace TestSuite { class TestEoEvents { public bool called = false; public bool correct_sender = false; public Efl.Loop loop { get; set; } protected void callback(object sender, EventArgs e) { called = true; Efl.Object obj = sender as Efl.Object; if (obj != null) { obj.SetName("loop_called"); correct_sender = true; } Eina.Value v = new Eina.Value(Eina.ValueType.Int32); v.Set(0); loop.Quit(v); v.Dispose(); } protected void another_callback(object sender, EventArgs e) { } public static void idle_event() { Efl.Loop loop = Efl.App.AppMain; loop.SetName("loop"); TestEoEvents listener = new TestEoEvents(); listener.loop = loop; loop.IdleEvent += listener.callback; Test.Assert(!listener.called); Test.Assert(!listener.correct_sender); Test.AssertEquals("loop", loop.GetName()); loop.Begin(); Test.Assert(listener.called); Test.Assert(listener.correct_sender); Test.AssertEquals("loop_called", loop.GetName()); loop.IdleEvent -= listener.callback; } public static void event_with_string_payload() { var obj = new Dummy.TestObject(); string received_string = null; obj.EvtWithStringEvent += (object sender, Dummy.TestObjectEvtWithStringEventArgs e) => { received_string = e.arg; }; obj.EmitEventWithString("Some args"); Test.AssertEquals("Some args", received_string); obj.Dispose(); } public static void event_with_int_payload() { var obj = new Dummy.TestObject(); int received_int= 0; obj.EvtWithIntEvent += (object sender, Dummy.TestObjectEvtWithIntEventArgs e) => { received_int = e.arg; }; obj.EmitEventWithInt(-1984); Test.AssertEquals(-1984, received_int); obj.Dispose(); } public static void event_with_bool_payload() { var obj = new Dummy.TestObject(); bool received_bool = false; obj.EvtWithBoolEvent += (object sender, Dummy.TestObjectEvtWithBoolEventArgs e) => { received_bool = e.arg; }; obj.EmitEventWithBool(true); Test.AssertEquals(true, received_bool); obj.EmitEventWithBool(false); Test.AssertEquals(false, received_bool); obj.Dispose(); } public static void event_with_uint_payload() { var obj = new Dummy.TestObject(); uint received_uint = 0; obj.EvtWithUintEvent += (object sender, Dummy.TestObjectEvtWithUintEventArgs e) => { received_uint = e.arg; }; obj.EmitEventWithUint(0xbeef); Test.AssertEquals(0xbeef, received_uint); obj.Dispose(); } public static void event_with_float_payload() { var obj = new Dummy.TestObject(); float received_float = 0; obj.EvtWithFloatEvent += (object sender, Dummy.TestObjectEvtWithFloatEventArgs e) => { received_float = e.arg; }; obj.EmitEventWithFloat(3.14f); Test.AssertAlmostEquals(3.14f, received_float); obj.Dispose(); } public static void event_with_double_payload() { var obj = new Dummy.TestObject(); double received_double = 0; double reference = float.MaxValue + 42; obj.EvtWithDoubleEvent += (object sender, Dummy.TestObjectEvtWithDoubleEventArgs e) => { received_double = e.arg; }; obj.EmitEventWithDouble(reference); Test.AssertAlmostEquals(reference, received_double); obj.Dispose(); } public static void event_with_object_payload() { var obj = new Dummy.TestObject(); Dummy.TestObject received_obj = null; obj.EvtWithObjEvent += (object sender, Dummy.TestObjectEvtWithObjEventArgs e) => { received_obj = e.arg; }; var sent_obj = new Dummy.TestObject(); obj.EmitEventWithObj(sent_obj); Test.AssertEquals(sent_obj, received_obj); sent_obj.Dispose(); obj.Dispose(); } public static void event_with_error_payload() { var obj = new Dummy.TestObject(); Eina.Error received_error = 0; obj.EvtWithErrorEvent += (object sender, Dummy.TestObjectEvtWithErrorEventArgs e) => { received_error = e.arg; }; Eina.Error sent_error = -2001; obj.EmitEventWithError(sent_error); Test.AssertEquals(sent_error, received_error); obj.Dispose(); } public static void event_with_struct_payload() { var obj = new Dummy.TestObject(); Dummy.StructSimple received_struct = default(Dummy.StructSimple); obj.EvtWithStructEvent += (object sender, Dummy.TestObjectEvtWithStructEventArgs e) => { received_struct = e.arg; }; Dummy.StructSimple sent_struct = default(Dummy.StructSimple); sent_struct.Fstring = "Struct Event"; obj.EmitEventWithStruct(sent_struct); Test.AssertEquals(sent_struct.Fstring, received_struct.Fstring); obj.Dispose(); } #if EFL_BETA public static void event_with_struct_complex_payload() { var obj = new Dummy.TestObject(); Dummy.StructComplex received_struct = default(Dummy.StructComplex); obj.EvtWithStructComplexEvent += (object sender, Dummy.TestObjectEvtWithStructComplexEventArgs e) => { received_struct = e.arg; }; Dummy.StructComplex sent_struct = StructHelpers.structComplexWithValues(); obj.EmitEventWithStructComplex(sent_struct); Test.AssertEquals(sent_struct.Fobj, received_struct.Fobj); obj.Dispose(); } #endif public static void event_with_array_payload() { var obj = new Dummy.TestObject(); - Eina.Array received = null; + List received = null; Eina.Array sent = new Eina.Array(); sent.Append("Abc"); sent.Append("Def"); sent.Append("Ghi"); obj.EvtWithArrayEvent += (object sender, Dummy.TestObjectEvtWithArrayEventArgs e) => { - received = e.arg; + received = e.arg as List; }; obj.EmitEventWithArray(sent); Test.AssertEquals(sent.Count, received.Count); var pairs = sent.Zip(received, (string sentItem, string receivedItem) => new { Sent = sentItem, Received = receivedItem } ); foreach (var pair in pairs) { Test.AssertEquals(pair.Sent, pair.Received); } sent.Dispose(); - received.Dispose(); obj.Dispose(); } } class TestEventAddRemove { public static void test_add_remove_event() { var obj = new Dummy.TestObject(); bool called = true; EventHandler evtCb = (object sender, Dummy.TestObjectEvtWithIntEventArgs e) => { called = true; }; obj.EvtWithIntEvent += evtCb; obj.EmitEventWithInt(42); Test.Assert(called); called = false; obj.EvtWithIntEvent -= evtCb; obj.EmitEventWithInt(42); Test.Assert(!called); obj.Dispose(); } } class TestInterfaceEvents { public static void test_nonconflicting_events() { var obj = new Dummy.TestObject(); var called = false; EventHandler cb = (object sender, EventArgs e) => { called = true; }; obj.NonconflictedEvent += cb; obj.EmitNonconflicted(); Test.Assert(called); obj.Dispose(); } } class TestEventNaming { // For events named line focus_geometry,changed public static void test_event_naming() { var obj = new Dummy.TestObject(); var test_called = false; EventHandler cb = (object sender, EventArgs e) => { test_called = true; }; obj.EvtWithUnderEvent += cb; obj.EmitEventWithUnder(); Test.Assert(test_called); obj.Dispose(); } } class TestEventWithDeadWrappers { private static WeakReference AttachToManager(Dummy.EventManager manager, EventHandler cb) { var obj = new Dummy.TestObject(); manager.Emitter = obj; obj.EvtWithIntEvent += cb; return new WeakReference(obj); } public static void test_event_from_c_owned_wrapper() { // Set upon object instantiation WeakReference wref = null; // Checks in the callback called bool callbackCalled = false; int received = -1; // attach to evt with int EventHandler cb = (object sender, Dummy.TestObjectEvtWithIntEventArgs args) => { callbackCalled = true; received = args.arg; Test.Assert(Object.ReferenceEquals(sender, wref.Target)); }; Dummy.EventManager manager = new Dummy.EventManager(); wref = AttachToManager(manager, cb); Test.CollectAndIterate(); manager.EmitWithInt(42); Test.CollectAndIterate(); Test.Assert(callbackCalled, "Callback must have been called."); Test.AssertEquals(42, received, "Wrong value received."); // Cleanup checks manager.Release(); // Make sure the released wrapper is collected and release the Eo object Test.CollectAndIterate(); Test.AssertNull(wref.Target); manager.Dispose(); } } } diff --git a/src/tests/efl_mono/StructHelpers.cs b/src/tests/efl_mono/StructHelpers.cs index 9c9f75076e..5e6dc506a7 100644 --- a/src/tests/efl_mono/StructHelpers.cs +++ b/src/tests/efl_mono/StructHelpers.cs @@ -1,234 +1,235 @@ /* * Copyright 2019 by its authors. See AUTHORS. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; using System.Linq; using System.Runtime.InteropServices; +using System.Collections.Generic; using Eina; using static EinaTestData.BaseData; namespace TestSuite { internal class StructHelpers { // Auxiliary function // internal static Dummy.StructSimple structSimpleWithValues() { var simple = new Dummy.StructSimple(); simple.Fbyte = (sbyte)-126; simple.Fubyte = (byte) 254u; simple.Fchar = '~'; simple.Fshort = (short) -32766; simple.Fushort = (ushort) 65534u; simple.Fint = -32766; simple.Fuint = 65534u; simple.Flong = -2147483646; simple.Fulong = 4294967294u; simple.Fllong = -9223372036854775806; simple.Fullong = 18446744073709551614u; simple.Fint8 = (sbyte) -126; simple.Fuint8 = (byte) 254u; simple.Fint16 = (short) -32766; simple.Fuint16 = (ushort) 65534u; simple.Fint32 = -2147483646; simple.Fuint32 = 4294967294u; simple.Fint64 = -9223372036854775806; simple.Fuint64 = 18446744073709551614u; simple.Fssize = -2147483646; simple.Fsize = 4294967294u; simple.Fintptr = (IntPtr) 0xFE; simple.Fptrdiff = -2147483646; simple.Ffloat = -16777216.0f; simple.Fdouble = -9007199254740992.0; simple.Fbool = true; simple.Fenum = Dummy.SampleEnum.V2; simple.Fstring = "test/string"; simple.Fmstring = "test/mstring"; simple.Fstringshare = "test/stringshare"; return simple; } internal static void checkStructSimple(Dummy.StructSimple simple) { Test.Assert(simple.Fbyte == (sbyte) -126); Test.Assert(simple.Fubyte == (byte) 254u); Test.Assert(simple.Fchar == '~'); Test.Assert(simple.Fshort == (short) -32766); Test.Assert(simple.Fushort == (ushort) 65534u); Test.Assert(simple.Fint == -32766); Test.Assert(simple.Fuint == 65534u); Test.Assert(simple.Flong == -2147483646); Test.Assert(simple.Fulong == 4294967294u); Test.Assert(simple.Fllong == -9223372036854775806); Test.Assert(simple.Fullong == 18446744073709551614u); Test.Assert(simple.Fint8 == (sbyte) -126); Test.Assert(simple.Fuint8 == (byte) 254u); Test.Assert(simple.Fint16 == (short) -32766); Test.Assert(simple.Fuint16 == (ushort) 65534u); Test.Assert(simple.Fint32 == -2147483646); Test.Assert(simple.Fuint32 == 4294967294u); Test.Assert(simple.Fint64 == -9223372036854775806); Test.Assert(simple.Fuint64 == 18446744073709551614u); Test.Assert(simple.Fssize == -2147483646); Test.Assert(simple.Fsize == 4294967294u); Test.Assert(simple.Fintptr == (IntPtr) 0xFE); Test.Assert(simple.Fptrdiff == -2147483646); Test.Assert(simple.Ffloat == -16777216.0f); Test.Assert(simple.Fdouble == -9007199254740992.0); Test.Assert(simple.Fbool == true); Test.Assert(simple.Fenum == Dummy.SampleEnum.V2); Test.Assert(simple.Fstring == "test/string"); Test.Assert(simple.Fmstring == "test/mstring"); Test.Assert(simple.Fstringshare == "test/stringshare"); } internal static void checkZeroedStructSimple(Dummy.StructSimple simple) { Test.Assert(simple.Fbyte == 0); Test.Assert(simple.Fubyte == 0); Test.Assert(simple.Fchar == '\0'); Test.Assert(simple.Fshort == 0); Test.Assert(simple.Fushort == 0); Test.Assert(simple.Fint == 0); Test.Assert(simple.Fuint == 0); Test.Assert(simple.Flong == 0); Test.Assert(simple.Fulong == 0); Test.Assert(simple.Fllong == 0); Test.Assert(simple.Fullong == 0); Test.Assert(simple.Fint8 == 0); Test.Assert(simple.Fuint8 == 0); Test.Assert(simple.Fint16 == 0); Test.Assert(simple.Fuint16 == 0); Test.Assert(simple.Fint32 == 0); Test.Assert(simple.Fuint32 == 0); Test.Assert(simple.Fint64 == 0); Test.Assert(simple.Fuint64 == 0); Test.Assert(simple.Fssize == 0); Test.Assert(simple.Fsize == 0); Test.Assert(simple.Fintptr == IntPtr.Zero); Test.Assert(simple.Fptrdiff == 0); Test.Assert(simple.Ffloat == 0); Test.Assert(simple.Fdouble == 0); Test.Assert(simple.Fbool == false); Test.Assert(simple.Fenum == Dummy.SampleEnum.V0); Test.Assert(simple.Fstring == null); Test.Assert(simple.Fmstring == null); Test.Assert(simple.Fstringshare == null); } #if EFL_BETA internal static Dummy.StructComplex structComplexWithValues() { var complex = new Dummy.StructComplex(); complex.Farray = new Eina.Array(); - complex.Farray.Push("0x0"); - complex.Farray.Push("0x2A"); - complex.Farray.Push("0x42"); + complex.Farray.Add("0x0"); + complex.Farray.Add("0x2A"); + complex.Farray.Add("0x42"); complex.Flist = new Eina.List(); - complex.Flist.Append("0x0"); - complex.Flist.Append("0x2A"); - complex.Flist.Append("0x42"); + complex.Flist.Add("0x0"); + complex.Flist.Add("0x2A"); + complex.Flist.Add("0x42"); complex.Fhash = new Eina.Hash(); complex.Fhash["aa"] = "aaa"; complex.Fhash["bb"] = "bbb"; complex.Fhash["cc"] = "ccc"; - complex.Fiterator = complex.Farray.GetIterator(); + complex.Fiterator = ((Eina.Array)complex.Farray).GetIterator(); complex.Fany_value = new Eina.Value(Eina.ValueType.Double); complex.Fany_value.Set(-9007199254740992.0); complex.Fany_value_ref = new Eina.Value(Eina.ValueType.String); complex.Fany_value_ref.Set("abc"); complex.Fbinbuf = new Eina.Binbuf(); complex.Fbinbuf.Append(126); complex.Fslice.Length = 1; complex.Fslice.Mem = Eina.MemoryNative.Alloc(1); Marshal.WriteByte(complex.Fslice.Mem, 125); complex.Fobj = new Dummy.Numberwrapper(); complex.Fobj.SetNumber(42); return complex; } internal static void checkStructComplex(Dummy.StructComplex complex) { Test.Assert(complex.Farray.ToArray().SequenceEqual(base_seq_str)); Test.Assert(complex.Flist.ToArray().SequenceEqual(base_seq_str)); Test.Assert(complex.Fhash["aa"] == "aaa"); Test.Assert(complex.Fhash["bb"] == "bbb"); Test.Assert(complex.Fhash["cc"] == "ccc"); int idx = 0; foreach (string e in complex.Fiterator) { Test.Assert(e == base_seq_str[idx]); ++idx; } Test.AssertEquals(idx, base_seq_str.Length); double double_val = 0; Test.Assert(complex.Fany_value.Get(out double_val)); Test.Assert(double_val == -9007199254740992.0); string str_val = null; Test.Assert(complex.Fany_value_ref.Get(out str_val)); Test.Assert(str_val == "abc"); Test.Assert(complex.Fbinbuf.Length == 1); Test.Assert(complex.Fbinbuf.GetBytes()[0] == 126); Test.Assert(complex.Fslice.Length == 1); Test.Assert(complex.Fslice.GetBytes()[0] == 125); Test.Assert(complex.Fobj != null); Test.Assert(complex.Fobj.GetNumber() == 42); } internal static void checkZeroedStructComplex(Dummy.StructComplex complex) { Test.Assert(complex.Farray == null); Test.Assert(complex.Flist == null); Test.Assert(complex.Fhash == null); Test.Assert(complex.Fiterator == null); Test.Assert(complex.Fany_value == null); Test.Assert(complex.Fany_value_ref == null); Test.Assert(complex.Fbinbuf == null); Test.Assert(complex.Fslice.Length == 0); Test.Assert(complex.Fslice.Mem == IntPtr.Zero); Test.Assert(complex.Fobj == null); } #endif } }