csharp: Move collection conversions to a new file

This commit is contained in:
Lauro Moura 2019-12-03 17:47:27 -03:00
parent 3cbe4d3e7c
commit 786bb1fe3b
6 changed files with 190 additions and 155 deletions

View File

@ -132,9 +132,9 @@ struct unpack_event_args_visitor
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);
return as_generator("Efl.Eo.CollectionConversions.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);
return as_generator("Efl.Eo.CollectionConversions.AccessorTo" << eolian_mono::type << "(info)").generate(sink, type, *context);
else
return as_generator("new " << eolian_mono::type << "(info, false, false)").generate(sink, type, *context);
}

View File

@ -645,7 +645,7 @@ struct native_convert_in_variable_generator
if (!complex)
return false;
return as_generator(
"var " << string << " = Efl.Eo.Globals.IteratorTo" << type << "(" << escape_keyword(param.param_name)
"var " << string << " = Efl.Eo.CollectionConversions.IteratorTo" << type << "(" << escape_keyword(param.param_name)
<< ");\n"
).generate(sink, std::make_tuple(in_variable_name(param.param_name), param.type), context);
}
@ -655,7 +655,7 @@ struct native_convert_in_variable_generator
if (!complex)
return false;
return as_generator(
"var " << string << " = Efl.Eo.Globals.AccessorTo" << type << "(" << escape_keyword(param.param_name) << ", " << (param.type.has_own ? "true" : "false") << ");\n"
"var " << string << " = Efl.Eo.CollectionConversions.AccessorTo" << type << "(" << escape_keyword(param.param_name) << ", " << (param.type.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_Value")
@ -758,7 +758,7 @@ struct convert_in_variable_generator
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) << ");\n"
"var " << string << " = " << "Efl.Eo.CollectionConversions.IEnumerableToIterator(" << escape_keyword(param.param_name) << ");\n"
).generate(sink, var_name, context))
return false;
}
@ -769,7 +769,7 @@ struct convert_in_variable_generator
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"
"var " << string << " = Efl.Eo.CollectionConversions.IEnumerableToAccessor(" << escape_keyword(param.param_name) << ", " << (param.type.has_own ? "true" : "false")<< ");\n"
).generate(sink, var_name, context))
return false;
}
@ -1021,7 +1021,7 @@ struct convert_out_assign_generator
if (!complex)
return false;
return as_generator(
string << " = Efl.Eo.Globals.AccessorTo" << type << "(" << string << ", " << (param.type.has_own ? "true" : "false") << ");\n"
string << " = Efl.Eo.CollectionConversions.AccessorTo" << type << "(" << string << ", " << (param.type.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_Iterator *", WANT_OWN, WANT_OUT)
@ -1034,7 +1034,7 @@ struct convert_out_assign_generator
if (!complex)
return false;
return as_generator(
string << " = Efl.Eo.Globals.IteratorTo" << type << "(" << string
string << " = Efl.Eo.CollectionConversions.IteratorTo" << type << "(" << string
<< ");\n"
).generate(sink, std::make_tuple(escape_keyword(param.param_name), param.type, out_variable_name(param.param_name)), context);
}
@ -1154,7 +1154,7 @@ struct convert_return_generator
attributes::complex_type_def const* complex = efl::eina::get<attributes::complex_type_def>(&ret_type.original_type);
if (!complex)
return false;
if (!as_generator("return Efl.Eo.Globals.AccessorTo" << type << "(_ret_var, " << (ret_type.has_own ? "true" : "false") << ");")
if (!as_generator("return Efl.Eo.CollectionConversions.AccessorTo" << type << "(_ret_var, " << (ret_type.has_own ? "true" : "false") << ");")
.generate(sink, ret_type, context))
return false;
}
@ -1163,7 +1163,7 @@ struct convert_return_generator
attributes::complex_type_def const* complex = efl::eina::get<attributes::complex_type_def>(&ret_type.original_type);
if (!complex)
return false;
if (!as_generator("return Efl.Eo.Globals.IteratorTo" << type << "(_ret_var);")
if (!as_generator("return Efl.Eo.CollectionConversions.IteratorTo" << type << "(_ret_var);")
.generate(sink, ret_type, context))
return false;
}
@ -1312,7 +1312,7 @@ struct native_convert_out_assign_generator
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"
string << " = Efl.Eo.CollectionConversions.IEnumerableToAccessor(" << string << ", " << (param.type.has_own ? "true" : "false")<< ");\n"
).generate(sink, std::make_tuple(escape_keyword(param.param_name), outvar), context))
return false;
}
@ -1327,7 +1327,7 @@ struct native_convert_out_assign_generator
return false;
auto outvar = out_variable_name(param.param_name);
if (!as_generator(
string << " = Efl.Eo.Globals.IEnumerableToIterator(" << string << ");\n"
string << " = Efl.Eo.CollectionConversions.IEnumerableToIterator(" << string << ");\n"
).generate(sink, std::make_tuple(escape_keyword(param.param_name), outvar), context))
return false;
}
@ -1467,12 +1467,12 @@ struct native_convert_return_generator
}
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") << ");")
return as_generator(lit("return Efl.Eo.CollectionConversions.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("return Efl.Eo.Globals.IEnumerableToIterator(_ret_var);")
return as_generator("return Efl.Eo.CollectionConversions.IEnumerableToIterator(_ret_var);")
.generate(sink, attributes::unused, context);
}
else if (ret_type.c_type != "void")

View File

@ -72,7 +72,7 @@ struct to_internal_field_convert_generator
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 << ");\n")
indent << scope_tab << scope_tab << "_internal_struct." << string << " = Efl.Eo.CollectionConversions.IEnumerableToIterator(_external_struct." << string << ");\n")
.generate(sink, std::make_tuple(field_name, field_name), context))
return false;
}
@ -212,7 +212,7 @@ struct to_external_field_convert_generator
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")
indent << scope_tab << scope_tab << "_external_struct." << string << " = Efl.Eo.CollectionConversions.IteratorTo" << type << "(_internal_struct." << string << ");\n")
.generate(sink, std::make_tuple(field_name, field.type, field_name), context))
return false;
}

View File

@ -0,0 +1,173 @@
/*
* 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.Linq;
namespace Efl
{
namespace Eo
{
/// <summary>
/// Helper class with method to convert between managed and native collections
/// </summary>
internal class CollectionConversions
{
internal static IEnumerable<T> AccessorToIEnumerable<T>(IntPtr accessor, bool isMoved)
{
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<T>(data);
position += 1;
}
if (isMoved)
{
Eina.AccessorNativeFunctions.eina_accessor_free(accessor);
}
}
internal static IntPtr IEnumerableToAccessor<T>(IEnumerable<T> 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.
var wrappedAccessor = enumerable as Eina.Accessor<T>;
if (wrappedAccessor != null)
{
if (isMoved)
{
wrappedAccessor.Own = false;
}
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<T>(data);
i++;
}
IntPtr[] dataArray = intPtrs.ToArray();
GCHandle pinnedArray = GCHandle.Alloc(dataArray, 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)dataArray.Length,
Efl.Eo.Globals.free_gchandle,
GCHandle.ToIntPtr(pinnedArray));
}
else
{
// FIXME: Leaking....
nativeAccessor = Eina.AccessorNativeFunctions.eina_carray_length_accessor_new(pinnedArray.AddrOfPinnedObject(), (uint)(IntPtr.Size), (uint)dataArray.Length);
}
if (nativeAccessor == IntPtr.Zero)
{
pinnedArray.Free();
throw new InvalidOperationException("Failed to get native accessor for the given container");
}
return nativeAccessor;
}
internal static IEnumerable<T> IteratorToIEnumerable<T>(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<T>(data);
}
}
internal static IntPtr IEnumerableToIterator<T>(IEnumerable<T> enumerable)
{
if (enumerable == null)
throw new ArgumentException("enumerable is null", nameof(enumerable));
IntPtr[] intPtrs = new IntPtr[enumerable.Count()];
int i = 0;
foreach (T data in enumerable)
{
intPtrs[i] = Eina.TraitFunctions.ManagedToNativeAlloc<T>(data);
i++;
}
IntPtr[] dataArray = intPtrs.ToArray();
GCHandle pinnedArray = GCHandle.Alloc(dataArray, GCHandleType.Pinned); //FIXME: Need to free.
return Eina.IteratorNativeFunctions.eina_carray_length_iterator_new(pinnedArray.AddrOfPinnedObject(), (uint)(IntPtr.Size), (uint)dataArray.Length);
}
internal static IEnumerable<T> ListToIEnumerable<T>(IntPtr list)
{
if (list == IntPtr.Zero)
throw new ArgumentException("list is null", nameof(list));
IntPtr l;
for (l = list; l != IntPtr.Zero; l = Eina.ListNativeFunctions.eina_list_next_custom_export_mono(l))
{
yield return Eina.TraitFunctions.NativeToManaged<T>(Eina.ListNativeFunctions.eina_list_data_get_custom_export_mono(l));
}
}
internal static IntPtr IEnumerableToList<T>(IEnumerable<T> enumerable)
{
if (enumerable == null)
throw new ArgumentException("enumerable is null", nameof(enumerable));
IntPtr list = IntPtr.Zero;
foreach (T data in enumerable)
{
list = Eina.ListNativeFunctions.eina_list_append(list, Eina.TraitFunctions.ManagedToNativeAlloc(data)); //FIXME: need to free
}
return list;
}
}
}
}

View File

@ -758,145 +758,6 @@ public static class Globals
}
Monitor.Exit(Efl.All.InitLock);
}
internal static IEnumerable<T> AccessorToIEnumerable<T>(IntPtr accessor, bool isMoved)
{
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<T>(data);
position += 1;
}
if (isMoved)
{
Eina.AccessorNativeFunctions.eina_accessor_free(accessor);
}
}
internal static IntPtr IEnumerableToAccessor<T>(IEnumerable<T> 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.
var wrappedAccessor = enumerable as Eina.Accessor<T>;
if (wrappedAccessor != null)
{
if (isMoved)
{
wrappedAccessor.Own = false;
}
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<T>(data);
i++;
}
IntPtr[] dataArray = intPtrs.ToArray();
GCHandle pinnedArray = GCHandle.Alloc(dataArray, 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)dataArray.Length,
free_gchandle,
GCHandle.ToIntPtr(pinnedArray));
}
else
{
// FIXME: Leaking....
nativeAccessor = Eina.AccessorNativeFunctions.eina_carray_length_accessor_new(pinnedArray.AddrOfPinnedObject(), (uint)(IntPtr.Size), (uint)dataArray.Length);
}
if (nativeAccessor == IntPtr.Zero)
{
pinnedArray.Free();
throw new InvalidOperationException("Failed to get native accessor for the given container");
}
return nativeAccessor;
}
internal static IEnumerable<T> IteratorToIEnumerable<T>(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<T>(data);
}
}
internal static IntPtr IEnumerableToIterator<T>(IEnumerable<T> enumerable)
{
if (enumerable == null)
throw new ArgumentException("enumerable is null", nameof(enumerable));
IntPtr[] intPtrs = new IntPtr[enumerable.Count()];
int i = 0;
foreach (T data in enumerable)
{
intPtrs[i] = Eina.TraitFunctions.ManagedToNativeAlloc<T>(data);
i++;
}
IntPtr[] dataArray = intPtrs.ToArray();
GCHandle pinnedArray = GCHandle.Alloc(dataArray, GCHandleType.Pinned); //FIXME: Need to free.
return Eina.IteratorNativeFunctions.eina_carray_length_iterator_new(pinnedArray.AddrOfPinnedObject(), (uint)(IntPtr.Size), (uint)dataArray.Length);
}
internal static IEnumerable<T> ListToIEnumerable<T>(IntPtr list)
{
if (list == IntPtr.Zero)
throw new ArgumentException("list is null", nameof(list));
IntPtr l;
for (l = list; l != IntPtr.Zero; l = Eina.ListNativeFunctions.eina_list_next_custom_export_mono(l))
{
yield return Eina.TraitFunctions.NativeToManaged<T>(Eina.ListNativeFunctions.eina_list_data_get_custom_export_mono(l));
}
}
internal static IntPtr IEnumerableToList<T>(IEnumerable<T> enumerable)
{
if (enumerable == null)
throw new ArgumentException("enumerable is null", nameof(enumerable));
IntPtr list = IntPtr.Zero;
foreach (T data in enumerable)
{
list = Eina.ListNativeFunctions.eina_list_append(list, Eina.TraitFunctions.ManagedToNativeAlloc(data)); //FIXME: need to free
}
return list;
}
} // Globals
/// <summary>

View File

@ -1,6 +1,7 @@
mono_files += files(
'iwrapper.cs',
'workaround.cs',
'CollectionConversions.cs',
'FunctionWrapper.cs',
'NativeModule.cs',
'EoWrapper.cs',