csharp: fix Eina_Stringshare support in containers for manual and generated API

Summary:
Both C strings and eina stringshares are bound as regular strings in EFL#, as
working directly with these types would demand unnecessary hassle from the user
viewpoint.
But for eina containers this distinction is important, and since C# generics
do not provide a convenient way of dealing with the same type requiring a
different management based on some other condition (at least not without
compromising the usability for other types), we added a simple `System.String`
wrapper named `Eina.Stringshare` that works as a placeholder for signaling
this distinction.

Working with this class should be transparent in most use cases because it
converts to and from `System.String` implicitly.
It also implements equality/inequality methods for easier comparison with
strings and other stringshare objects.

Add new methods and a new container element trait for dealing specifically
with `Eina_Stringshare` elements.

Adapt eolian_mono to identify and generate the proper placeholder in methods
that require stringshare containers.

Remove some direct uses of DllImport-ed functions in favor of more flexible
manual binding methods.

Move `Eina.Stringshare` DllImport directives to a static class named
`NativeMethods`, in accordance with the code design warning CA1060.
Also add a TODO comment to move all other DllImport directives to this class.

Change parameter of the method `Efl.Csharp.Application.OnInitialize` from
`Eina.Array<System.String>` to `string[]`.
This will make this API more similar with the default C# way of receiving
command line arguments.

Add tests for containers storing stringshare elements.

Reviewers: felipealmeida, lauromoura, segfaultxavi, bu5hm4n

Reviewed By: lauromoura

Subscribers: cedric, #reviewers, #committers

Tags: #efl

Differential Revision: https://phab.enlightenment.org/D9178
This commit is contained in:
Vitor Sousa 2019-06-28 10:40:52 -03:00
parent b7fa7d48ac
commit 4496022a3c
16 changed files with 2260 additions and 43 deletions

View File

@ -26,23 +26,41 @@ struct marshall_annotation_visitor_generate;
*/
struct marshall_type_generator
{
marshall_type_generator(bool is_return = false)
: is_return(is_return) {}
marshall_type_generator(bool is_return = false, bool is_special_subtype = false)
: is_return(is_return)
, is_special_subtype(is_special_subtype)
{}
template <typename OutputIterator, typename Context>
bool generate(OutputIterator sink, attributes::type_def const& type, Context const& context) const
{
return type.original_type.visit(detail::marshall_type_visitor_generate<OutputIterator, Context>{sink, &context, type.c_type, false, is_return, type.is_ptr });
return type.original_type.visit(detail::marshall_type_visitor_generate<OutputIterator, Context>{
sink
, &context
, type.c_type
, false
, is_return
, type.is_ptr
, is_special_subtype
});
}
/* Some types may require a different conversion when they are in @out parameters. */
template <typename OutputIterator, typename Context>
bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
{
return param.type.original_type.visit(detail::marshall_type_visitor_generate<OutputIterator, Context>{sink, &context, param.type.c_type
, param.direction != attributes::parameter_direction::in, false, param.type.is_ptr});
return param.type.original_type.visit(detail::marshall_type_visitor_generate<OutputIterator, Context>{
sink
, &context
, param.type.c_type
, param.direction != attributes::parameter_direction::in
, false
, param.type.is_ptr
, is_special_subtype
});
}
bool is_return;
bool is_special_subtype;
};
/*
@ -73,9 +91,9 @@ struct marshall_annotation_generator
struct marshall_type_terminal
{
marshall_type_generator const operator()(bool is_return) const
marshall_type_generator const operator()(bool is_return, bool is_special_subtype = false) const
{
return marshall_type_generator(is_return);
return marshall_type_generator(is_return, is_special_subtype);
}
} const marshall_type = {};

View File

@ -25,6 +25,7 @@ struct marshall_type_visitor_generate
bool is_out;
bool is_return;
bool is_ptr;
bool is_special_subtype;
typedef marshall_type_visitor_generate<OutputIterator, Context> visitor_type;
typedef bool result_type;
@ -70,12 +71,16 @@ struct marshall_type_visitor_generate
{
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");
}}
, {"stringshare", false, [&]
{
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, [&]
@ -171,16 +176,40 @@ struct marshall_type_visitor_generate
regular_type_def r = regular;
r.base_type = "System.IntPtr";
r.namespaces.clear();
return visitor_generate<OutputIterator, Context>{sink, context, c_type, is_out, is_return, is_ptr}(r);
return visitor_generate<OutputIterator, Context>{
sink
, context
, c_type
, is_out
, is_return
, is_ptr
, is_special_subtype
}(r);
}
else
{
return visitor_generate<OutputIterator, Context>{sink, context, c_type, is_out, is_return, is_ptr}(regular);
return visitor_generate<OutputIterator, Context>{
sink
, context
, c_type
, is_out
, is_return
, is_ptr
, is_special_subtype
}(regular);
}
}
bool operator()(attributes::klass_name klass_name) const
{
return visitor_generate<OutputIterator, Context>{sink, context, c_type, is_out, is_return, is_ptr}(klass_name);
return visitor_generate<OutputIterator, Context>{
sink
, context
, c_type
, is_out
, is_return
, is_ptr
, is_special_subtype
}(klass_name);
}
bool operator()(attributes::complex_type_def const& complex) const
{
@ -225,7 +254,7 @@ struct marshall_type_visitor_generate
{
regular_type_def no_pointer_regular = complex.outer;
return visitor_type{sink, context, c_type, false}(no_pointer_regular)
&& as_generator("<" << (type % ", ") << ">").generate(sink, complex.subtypes, *context);
&& as_generator("<" << (type(false, false, true) % ", ") << ">").generate(sink, complex.subtypes, *context);
};
if(eina::optional<bool> b = call_match
@ -250,7 +279,15 @@ struct marshall_type_visitor_generate
return *b;
}
return visitor_generate<OutputIterator, Context>{sink, context, c_type, is_out, is_return, is_ptr}(complex);
return visitor_generate<OutputIterator, Context>{
sink
, context
, c_type
, is_out
, is_return
, is_ptr
, is_special_subtype
}(complex);
}
};
} }

View File

@ -88,7 +88,7 @@ struct to_internal_field_convert_generator
else if (regular && regular->base_type == "stringshare")
{
if (!as_generator(
indent << scope_tab << scope_tab << "_internal_struct." << string << " = Eina.Stringshare.eina_stringshare_add(_external_struct." << string << ");\n")
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;
}

View File

@ -14,29 +14,49 @@ struct visitor_generate;
struct type_generator
{
type_generator(bool is_return = false, bool is_optional = false)
: is_return(is_return), is_optional(is_optional) {}
type_generator(bool is_return = false, bool is_optional = false, bool is_special_subtype = false)
: is_return(is_return)
, is_optional(is_optional)
, is_special_subtype(is_special_subtype)
{}
template <typename OutputIterator, typename Context>
bool generate(OutputIterator sink, attributes::type_def const& type, Context const& context) const
{
return type.original_type.visit(visitor_generate<OutputIterator, Context>{sink, &context, type.c_type, false, is_return, type.is_ptr, is_optional});
return type.original_type.visit(visitor_generate<OutputIterator, Context>{
sink
, &context
, type.c_type
, false
, is_return
, type.is_ptr
, is_optional
, is_special_subtype
});
}
template <typename OutputIterator, typename Context>
bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
{
return param.type.original_type.visit(visitor_generate<OutputIterator, Context>{sink, &context, param.type.c_type
, param.direction != attributes::parameter_direction::in, false, param.type.is_ptr, is_optional});
return param.type.original_type.visit(visitor_generate<OutputIterator, Context>{
sink
, &context
, param.type.c_type
, param.direction != attributes::parameter_direction::in
, false
, param.type.is_ptr
, is_optional
, is_special_subtype
});
}
bool is_return, is_optional;
bool is_return, is_optional, is_special_subtype;
};
struct type_terminal
{
type_generator const operator()(bool is_return, bool is_optional = false) const
type_generator const operator()(bool is_return, bool is_optional = false, bool is_special_subtype = false) const
{
return type_generator(is_return, is_optional);
return type_generator(is_return, is_optional, is_special_subtype);
}
} const type = {};

View File

@ -99,6 +99,7 @@ struct visitor_generate
bool is_return;
bool is_ptr;
mutable bool is_optional;
bool is_special_subtype;
typedef visitor_generate<OutputIterator, Context> visitor_type;
typedef bool result_type;
@ -205,6 +206,8 @@ struct visitor_generate
{
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, [&]
@ -400,7 +403,7 @@ struct visitor_generate
// if(is_out)
// pointers.push_back({{attributes::qualifier_info::is_none, {}}, true});
return visitor_type{sink, context, c_type, false}(no_pointer_regular)
&& as_generator("<" << (type % ", ") << ">").generate(sink, complex.subtypes, *context)
&& as_generator("<" << (type(false, false, true) % ", ") << ">").generate(sink, complex.subtypes, *context)
;
// && detail::generate_pointers(sink, pointers, *context, false);
};

View File

@ -88,7 +88,7 @@ public abstract class Application
/// <summary>
/// Called when the application is started. Arguments from the command line are passed here.
/// </summary>
protected abstract void OnInitialize(Eina.Array<System.String> args);
protected abstract void OnInitialize(string[] args);
/// <summary>
/// Arguments are passed here, Additional calls to this function may occure,
@ -130,8 +130,8 @@ public abstract class Application
{
Init(components);
Efl.App app = Efl.App.AppMain;
Eina.Array<String> command_line = new Eina.Array<String>();
command_line.Append(Environment.GetCommandLineArgs());
var command_line = new Eina.Array<Eina.Stringshare>();
command_line.Append(Array.ConvertAll(Environment.GetCommandLineArgs(), s => (Eina.Stringshare)s));
#if EFL_BETA
app.SetCommandArray(command_line);
#endif
@ -139,7 +139,15 @@ public abstract class Application
{
if (evt.arg.Initialization)
{
OnInitialize(evt.arg.Argv);
var evtArgv = evt.arg.Argv;
int n = evtArgv.Length;
var argv = new string[n];
for (int i = 0; i < n; ++i)
{
argv[i] = evtArgv[i];
}
OnInitialize(argv);
}
OnArguments(evt.arg);

View File

@ -75,6 +75,30 @@ public static class MemoryNative
return NativeCustomExportFunctions.efl_mono_native_strdup(str);
}
public static IntPtr AddStringshare(string str)
{
IntPtr nativeStr = StringConversion.ManagedStringToNativeUtf8Alloc(str);
try
{
var strShare = NativeMethods.eina_stringshare_add(nativeStr);
return strShare;
}
finally
{
Eina.MemoryNative.Free(nativeStr);
}
}
public static void DelStringshare(IntPtr str)
{
NativeMethods.eina_stringshare_del(str);
}
public static void DelStringshareRef(IntPtr ptr)
{
NativeMethods.efl_mono_native_stringshare_del_ref(ptr);
}
// IntPtr's for some native functions
public static IntPtr PtrCompareFuncPtrGet()
{
@ -91,6 +115,11 @@ public static class MemoryNative
return NativeCustomExportFunctions.efl_mono_native_free_addr_get();
}
public static IntPtr StringshareDelFuncPtrGet()
{
return NativeMethods.efl_mono_native_stringshare_del_addr_get();
}
public static IntPtr EflUnrefFuncPtrGet()
{
return NativeCustomExportFunctions.efl_mono_native_efl_unref_addr_get();
@ -130,9 +159,17 @@ public static class StringConversion
byte[] strbuf = Encoding.UTF8.GetBytes(managedString);
IntPtr native = MemoryNative.Alloc(strbuf.Length + 1);
Marshal.Copy(strbuf, 0, native, strbuf.Length);
Marshal.WriteByte(native + strbuf.Length, 0); // write the terminating null
return native;
try
{
Marshal.Copy(strbuf, 0, native, strbuf.Length);
Marshal.WriteByte(native + strbuf.Length, 0); // write the terminating null
return native;
}
catch(Exception e)
{
MemoryNative.Free(native);
throw e;
}
}
public static string NativeUtf8ToManagedString(IntPtr pNativeData)

View File

@ -19,6 +19,7 @@ public enum ElementType
{
NumericType,
StringType,
StringshareType,
ObjectType
};
@ -195,6 +196,145 @@ public class StringElementTraits : IBaseElementTraits<string>
}
}
public class StringshareElementTraits : IBaseElementTraits<Eina.Stringshare>
{
public StringshareElementTraits()
{
}
public IntPtr ManagedToNativeAlloc(Eina.Stringshare man)
{
var strShare = MemoryNative.AddStringshare(man);
return strShare;
}
public IntPtr ManagedToNativeAllocInlistNode(Eina.Stringshare man)
{
var node = new InlistNode<IntPtr>();
node.Val = ManagedToNativeAlloc(man);
GCHandle pinnedData = GCHandle.Alloc(node, GCHandleType.Pinned);
IntPtr ptr = pinnedData.AddrOfPinnedObject();
IntPtr nat = MemoryNative.AllocCopy
(ptr, Marshal.SizeOf<InlistMem>() + Marshal.SizeOf<IntPtr>());
pinnedData.Free();
return nat;
}
public void ManagedToNativeCopyTo(Eina.Stringshare man, IntPtr mem)
{
IntPtr stringptr = ManagedToNativeAlloc(man);
Marshal.WriteIntPtr(mem, stringptr);
}
public void NativeFree(IntPtr nat)
{
if (nat != IntPtr.Zero)
{
MemoryNative.DelStringshare(nat);
}
}
public void NativeFreeInlistNodeElement(IntPtr nat)
{
if (nat == IntPtr.Zero)
{
return;
}
var val = Marshal.PtrToStructure<IntPtr>
(nat + Marshal.SizeOf<InlistMem>());
NativeFree(val);
}
public void NativeFreeInlistNode(IntPtr nat, bool freeElement)
{
if (nat == IntPtr.Zero)
{
return;
}
if (freeElement)
{
NativeFreeInlistNodeElement(nat);
}
MemoryNative.Free(nat);
}
public void NativeFreeInplace(IntPtr nat)
{
MemoryNative.DelStringshareRef(nat);
}
public void ResidueFreeInplace(IntPtr nat)
{
}
public Eina.Stringshare NativeToManaged(IntPtr nat)
{
if (nat == IntPtr.Zero)
{
return default(Eina.Stringshare);
}
return StringConversion.NativeUtf8ToManagedString(nat);
}
public Eina.Stringshare NativeToManagedInlistNode(IntPtr nat)
{
if (nat == IntPtr.Zero)
{
Eina.Log.Error("Null pointer for Inlist node.");
return default(Eina.Stringshare);
}
IntPtr ptr_location = nat + Marshal.SizeOf<InlistMem>();
return NativeToManaged(Marshal.ReadIntPtr(ptr_location));
}
// Strings inplaced are always a pointer, because they are variable-sized
public Eina.Stringshare NativeToManagedInplace(IntPtr nat)
{
if (nat == IntPtr.Zero)
{
return default(Eina.Stringshare);
}
nat = Marshal.ReadIntPtr(nat);
if (nat == IntPtr.Zero)
{
return default(Eina.Stringshare);
}
return NativeToManaged(nat);
}
public IntPtr EinaCompareCb()
{
return MemoryNative.StrCompareFuncPtrGet();
}
public IntPtr EinaFreeCb()
{
return MemoryNative.StringshareDelFuncPtrGet();
}
public IntPtr EinaHashNew()
{
return eina_hash_stringshared_new(MemoryNative.StringshareDelFuncPtrGet());
}
public IntPtr EinaInarrayNew(uint step)
{
return eina_inarray_new((uint)Marshal.SizeOf<IntPtr>(), step);
}
public IntPtr EinaHashIteratorKeyNew(IntPtr hash)
{
return eina_hash_iterator_key_new(hash);
}
}
public class EflObjectElementTraits<T> : IBaseElementTraits<T>
{
public IntPtr ManagedToNativeAlloc(T man)
@ -709,6 +849,11 @@ public static class TraitFunctions
return type == typeof(string);
}
public static bool IsStringshare(System.Type type)
{
return type == typeof(Eina.Stringshare);
}
public static Eina.ElementType GetElementTypeCode(System.Type type)
{
if (IsEflObject(type))
@ -719,6 +864,10 @@ public static class TraitFunctions
{
return ElementType.StringType;
}
else if (IsStringshare(type))
{
return ElementType.StringshareType;
}
else
{
return ElementType.NumericType;
@ -764,6 +913,10 @@ public static class TraitFunctions
{
traits = new StringElementTraits();
}
else if (IsStringshare(type))
{
traits = new StringshareElementTraits();
}
else if (type.IsValueType)
{
if (type == typeof(int))

View File

@ -363,7 +363,9 @@ public class Hash<TKey, TValue> : IEnumerable<KeyValuePair<TKey,TValue>>, IDi
private static bool ForceRefKey<T>()
{
return (!typeof(T).IsValueType) && (typeof(T) != typeof(string));
return (!typeof(T).IsValueType)
&& (typeof(T) != typeof(string))
&& (typeof(T) != typeof(Eina.Stringshare));
}
private static IntPtr CopyNativeObject<T>(T value, bool forceRef)
@ -439,7 +441,7 @@ public class Hash<TKey, TValue> : IEnumerable<KeyValuePair<TKey,TValue>>, IDi
IntPtr old = eina_hash_set(Handle, nk, nv);
FreeNativeIndirection<TKey>(gchnk, ForceRefKey<TKey>());
FreeNativeIndirection<TValue>(gchnv, false);
if (OwnValue || old != IntPtr.Zero)
if (OwnValue && old != IntPtr.Zero)
{
NativeFree<TValue>(old);
}

View File

@ -7,14 +7,224 @@ using System.Runtime.InteropServices;
namespace Eina
{
public class Stringshare
// TODO: move all native functions to a "NativeMethods" class
public static partial class NativeMethods
{
[DllImport(efl.Libs.Eina)] public static extern IntPtr
eina_stringshare_add(IntPtr str);
[DllImport(efl.Libs.Eina)] public static extern System.IntPtr
eina_stringshare_add_length(string str, System.UInt32 slen);
[DllImport(efl.Libs.Eina)] public static extern System.IntPtr
eina_stringshare_add(string str);
eina_stringshare_add_length(IntPtr str, UInt32 slen);
[DllImport(efl.Libs.Eina)] public static extern void
eina_stringshare_del(System.IntPtr str);
eina_stringshare_del(IntPtr str);
[DllImport(efl.Libs.CustomExports)] public static extern void
efl_mono_native_stringshare_del_ref(IntPtr str);
[DllImport(efl.Libs.CustomExports)] public static extern IntPtr
efl_mono_native_stringshare_del_addr_get();
}
/// <summary>
/// Placeholder type to interact with the native type Eina_Stringshare, mainly for eina containers.
/// </summary>
/// <remarks>
/// Using System.String and merely converting this type to it (by cast or implicitly)
/// is recommended for simplicity and ease of use.
///
/// This type is just a System.String wrapper that works as a placeholder for
/// instrumentalizing proper interaction with native EFL API that demands
/// strings to be stringshares.
///
/// Both C strings and eina stringshares are bound as regular strings in EFL#,
/// as working directly with these types would demand unnecessary hassle from
/// the user viewpoint.
/// But for eina containers this distinction is important, and since C# generics
/// do not provide a convenient way of dealing with the same type requiring
/// a different management based on some other condition (at least not without
/// compromising the usability for other types), we use this string wrapper
/// in order to signal this distinction.
///
/// Implements equality/inequality methods for easier comparison with strings and
/// other Stringshare objects. For more specific operations convert to a string.
/// </remarks>
public class Stringshare : IEquatable<Stringshare>, IEquatable<string>
{
/// <sumary>
/// Main constructor. Wrap the given string.
/// Have private acess to avoid wrapping a null reference,
/// use convertion or the factory method to create a new instance.
/// <see cref="Stringshare.Create(string s)"/>
/// <see cref="Stringshare.operator Stringshare(string s)"/>
/// </sumary>
private Stringshare(string s)
{
Str = s;
}
/// <sumary>
/// Auto-implemented property that holds the wrapped string value.
/// </sumary>
public string Str { get; private set; }
/// <sumary>
/// Factory method to instantiate a new object.
/// Get a wrappper for the given string or a null reference if the given
/// string reference is also null.
/// <seealso cref="Stringshare.operator Stringshare(string s)"/>
/// </sumary>
/// <returns>
/// A new instance wrapping the given string, or a null reference if
/// the given string reference is also null.
/// </returns>
public static Stringshare Create(string s)
{
if (s == null)
{
return null;
}
return new Stringshare(s);
}
/// <sumary>
/// Implicit convertion to string.
/// </sumary>
public static implicit operator string(Stringshare ss)
{
if (ReferenceEquals(null, ss))
{
return null;
}
return ss.Str;
}
/// <sumary>
/// Implicit convertion from string to Stringshare.
/// </sumary>
/// <remarks>
/// Note that this method can be used to create an instance of this class,
/// either via an explicit cast or an implicit convertion.
/// <seealso cref="Stringshare.Create(string s)"/>
/// </remarks>
public static implicit operator Stringshare(string s)
{
if (ReferenceEquals(null, s))
{
return null;
}
return new Stringshare(s);
}
/// <sumary>
/// Check two Stringshare objects for equality.
/// </sumary>
/// <returns>
/// True if both wrapped strings have the same content or if both
/// references are null, false otherwise.
/// </returns>
public static bool operator==(Stringshare ss1, Stringshare ss2)
{
return ((string)ss1) == ((string)ss2);
}
/// <sumary>
/// Check two Stringshare objects for inequality.
/// </sumary>
/// <returns>
/// True if the wrapped strings have different content or if one reference is null
/// and the other is not, false otherwise.
/// </returns>
public static bool operator!=(Stringshare ss1, Stringshare ss2)
{
return !(ss1 == ss2);
}
/// <sumary>
/// Returns the wrapped string.
/// <seealso cref="Stringshare.Str"/>
/// <seealso cref="Stringshare.Get()"/>
/// </sumary>
/// <returns>The wrapped string. Same as the property Str.</returns>
public override string ToString()
{
return Str;
}
/// <sumary>
/// Override of GetHashCode for consistency with user-defined equality methods.
/// </sumary>
/// <returns>
/// The wrapped string hash code.
/// </returns>
public override int GetHashCode()
{
return Str.GetHashCode();
}
/// <sumary>
/// Check the given object for equality.
/// </sumary>
/// <returns>
/// True if the given object is the same object or if it is another Stringshare object
/// and both wrapped strings are equal or if it is a string object and its content
/// is the same of the wrapped string.
/// In any other case it returns false.
/// </returns>
public override bool Equals(object other)
{
if (ReferenceEquals(null, other))
{
return false;
}
if (ReferenceEquals(this, other))
{
return true;
}
if (other.GetType() == typeof(string))
{
return this.Str == (string)other;
}
return other.GetType() == typeof(Stringshare) && this == ((Stringshare)other);
}
/// <sumary>
/// Check the given Stringshare for equality.
/// </sumary>
/// <returns>
/// True if the given Stringshare object is not null and its wrapped string
/// have the same content of this.Str, false otherwise.
/// </returns>
public bool Equals(Stringshare other)
{
return this == other;
}
/// <sumary>
/// Check the given Stringshare for equality.
/// </sumary>
/// <returns>
/// True if the given string is not null and the wrapped string have the same
/// content of the given string, false otherwise.
/// </returns>
public bool Equals(string other)
{
return this.Str == other;
}
/// <sumary>
/// Get the wrapped string.
/// <seealso cref="Stringshare.Str"/>
/// <seealso cref="Stringshare.ToString()"/>
/// </sumary>
/// <returns>The wrapped string. Same as the property Str.</returns>
public string Get()
{
return Str;
}
}
}

View File

@ -494,7 +494,7 @@ public class Globals
{
foreach (IntPtr ptr in dict.Values)
{
Eina.Stringshare.eina_stringshare_del(ptr);
Eina.NativeMethods.eina_stringshare_del(ptr);
}
}
@ -1148,13 +1148,13 @@ public class StringsharePassOwnershipMarshaler : ICustomMarshaler
public object MarshalNativeToManaged(IntPtr pNativeData)
{
var ret = Eina.StringConversion.NativeUtf8ToManagedString(pNativeData);
Eina.Stringshare.eina_stringshare_del(pNativeData);
Eina.NativeMethods.eina_stringshare_del(pNativeData);
return ret;
}
public IntPtr MarshalManagedToNative(object managedObj)
{
return Eina.Stringshare.eina_stringshare_add((string)managedObj);
return Eina.MemoryNative.AddStringshare((string)managedObj);
}
public void CleanUpNativeData(IntPtr pNativeData)
@ -1193,7 +1193,7 @@ public class StringshareKeepOwnershipMarshaler : ICustomMarshaler
public IntPtr MarshalManagedToNative(object managedObj)
{
return Eina.Stringshare.eina_stringshare_add((string)managedObj);
return Eina.MemoryNative.AddStringshare((string)managedObj);
}
public void CleanUpNativeData(IntPtr pNativeData)

View File

@ -125,6 +125,12 @@ EAPI void efl_mono_native_free_ref(void **ptr)
free(*ptr);
}
EAPI void efl_mono_native_stringshare_del_ref(void **str)
{
if (!str) return;
eina_stringshare_del(*str);
}
EAPI void *efl_mono_native_alloc_copy(const void *val, unsigned int size)
{
if (!val) return NULL;
@ -161,6 +167,11 @@ EAPI Eina_Free_Cb efl_mono_native_free_addr_get()
return (Eina_Free_Cb)free;
}
EAPI Eina_Free_Cb efl_mono_native_stringshare_del_addr_get()
{
return (Eina_Free_Cb)eina_stringshare_del;
}
EAPI Eina_Free_Cb efl_mono_native_efl_unref_addr_get()
{
return (Eina_Free_Cb)efl_mono_thread_safe_efl_unref;

View File

@ -492,6 +492,14 @@ class TestEinaArray
Test.AssertEquals("test string §éΨبÿツ", a[0]);
}
public static void push_stringshare()
{
var a = new Eina.Array<Eina.Stringshare>();
Test.Assert(a.Handle != IntPtr.Zero);
Test.Assert(a.Push("test string §éΨبÿツ"));
Test.AssertEquals("test string §éΨبÿツ", a[0].Str);
}
public static void push_obj()
{
var a = new Eina.Array<Dummy.Numberwrapper>();
@ -521,6 +529,15 @@ class TestEinaArray
Test.Assert(a.Count() == 0);
}
public static void pop_stringshare()
{
var a = new Eina.Array<Eina.Stringshare>();
Test.Assert(a.Handle != IntPtr.Zero);
Test.Assert(a.Push("test string"));
Test.Assert(a.Pop() == "test string");
Test.Assert(a.Count() == 0);
}
public static void pop_obj()
{
var a = new Eina.Array<Dummy.Numberwrapper>();
@ -558,6 +575,18 @@ class TestEinaArray
Test.Assert(a[0] == "abc");
}
public static void data_set_stringshare()
{
var a = new Eina.Array<Eina.Stringshare>();
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");
}
public static void data_set_obj()
{
var a = new Eina.Array<Dummy.Numberwrapper>();
@ -617,6 +646,22 @@ class TestEinaArray
Test.Assert(a.Count() == 3);
}
public static void count_stringshare()
{
var a = new Eina.Array<Eina.Stringshare>();
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);
}
public static void count_obj()
{
var a = new Eina.Array<Dummy.Numberwrapper>();
@ -678,6 +723,22 @@ class TestEinaArray
Test.Assert(a.Length == 3);
}
public static void length_stringshare()
{
var a = new Eina.Array<Eina.Stringshare>();
Test.Assert(a.Handle != IntPtr.Zero);
Test.Assert(a.Length == 0);
Test.Assert(a.Push("a"));
Test.Assert(a[0] == "a");
Test.Assert(a.Length == 1);
Test.Assert(a.Push("b"));
Test.Assert(a[1] == "b");
Test.Assert(a.Length == 2);
Test.Assert(a.Push("c"));
Test.Assert(a[2] == "c");
Test.Assert(a.Length == 3);
}
public static void eina_array_as_ienumerable_int()
{
var a = new Eina.Array<int>();
@ -710,6 +771,22 @@ class TestEinaArray
}
}
public static void eina_array_as_ienumerable_stringshare()
{
var a = new Eina.Array<Eina.Stringshare>();
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";
}
}
public static void eina_array_as_ienumerable_obj()
{
var a = new Dummy.Numberwrapper();
@ -888,6 +965,80 @@ class TestEinaArray
Test.Assert(arr.Handle == IntPtr.Zero);
}
// Eina.Stringshare //
public static void test_eina_array_strshare_in()
{
var t = new Dummy.TestObject();
var arr = new Eina.Array<Eina.Stringshare>();
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);
}
public static void test_eina_array_strshare_in_own()
{
var t = new Dummy.TestObject();
var arr = new Eina.Array<Eina.Stringshare>();
arr.Append(base_seq_strshare);
Test.Assert(t.EinaArrayStrshareInOwn(arr));
Test.Assert(!arr.Own);
Test.Assert(arr.ToArray().SequenceEqual(modified_seq_strshare));
arr.Dispose();
Test.Assert(arr.Handle == IntPtr.Zero);
Test.Assert(t.CheckEinaArrayStrshareInOwn());
}
public static void test_eina_array_strshare_out()
{
var t = new Dummy.TestObject();
Eina.Array<Eina.Stringshare> arr;
Test.Assert(t.EinaArrayStrshareOut(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(t.CheckEinaArrayStrshareOut());
}
public static void test_eina_array_strshare_out_own()
{
var t = new Dummy.TestObject();
Eina.Array<Eina.Stringshare> 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);
}
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.Assert(arr.Append(append_seq_strshare));
arr.Dispose();
Test.Assert(arr.Handle == IntPtr.Zero);
Test.Assert(t.CheckEinaArrayStrshareReturn());
}
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);
}
// Object //
public static void test_eina_array_obj_in()
@ -1315,6 +1466,17 @@ class TestEinaList
Test.Assert(lst[0] == "abc");
}
public static void data_set_stringshare()
{
var lst = new Eina.List<Eina.Stringshare>();
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");
}
public static void data_set_obj()
{
var lst = new Eina.List<Dummy.Numberwrapper>();
@ -1371,6 +1533,21 @@ class TestEinaList
Test.Assert(lst.Count() == 3);
}
public static void append_count_stringshare()
{
var lst = new Eina.List<Eina.Stringshare>();
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);
}
public static void append_count_obj()
{
var lst = new Eina.List<Dummy.Numberwrapper>();
@ -1429,6 +1606,21 @@ class TestEinaList
Test.Assert(lst.Length == 3);
}
public static void length_stringshare()
{
var lst = new Eina.List<Eina.Stringshare>();
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);
}
public static void prepend_count_int()
{
var lst = new Eina.List<int>();
@ -1459,6 +1651,21 @@ class TestEinaList
Test.Assert(lst.Count() == 3);
}
public static void prepend_count_stringshare()
{
var lst = new Eina.List<Eina.Stringshare>();
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);
}
public static void prepend_count_obj()
{
var lst = new Eina.List<Dummy.Numberwrapper>();
@ -1511,6 +1718,18 @@ class TestEinaList
}
public static void sorted_insert_stringshare()
{
var lst = new Eina.List<Eina.Stringshare>();
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"}));
}
public static void sort_int()
{
var lst = new Eina.List<int>();
@ -1536,6 +1755,18 @@ class TestEinaList
Test.Assert(lst.ToArray().SequenceEqual(new string[]{"a","b","c","d"}));
}
public static void sort_stringshare()
{
var lst = new Eina.List<Eina.Stringshare>();
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"}));
}
public static void reverse_int()
{
var lst = new Eina.List<int>();
@ -1559,6 +1790,17 @@ class TestEinaList
Test.Assert(lst.ToArray().SequenceEqual(new string[]{"c","b","a"}));
}
public static void reverse_stringshare()
{
var lst = new Eina.List<Eina.Stringshare>();
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"}));
}
public static void eina_list_as_ienumerable_int()
{
var lst = new Eina.List<int>();
@ -1589,6 +1831,21 @@ class TestEinaList
}
}
public static void eina_list_as_ienumerable_stringshare()
{
var lst = new Eina.List<Eina.Stringshare>();
lst.Append("X");
lst.Append("XX");
lst.Append("XXX");
string cmp = "X";
foreach (string e in lst)
{
Test.AssertEquals(cmp, e);
cmp = cmp + "X";
}
}
public static void eina_list_as_ienumerable_obj()
{
var a = new Dummy.Numberwrapper();
@ -1760,6 +2017,77 @@ class TestEinaList
Test.Assert(lst.Handle == IntPtr.Zero);
}
// Eina.Stringshare //
public static void test_eina_list_strshare_in()
{
var t = new Dummy.TestObject();
var lst = new Eina.List<Eina.Stringshare>();
lst.AppendArray(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);
}
public static void test_eina_list_strshare_in_own()
{
var t = new Dummy.TestObject();
var lst = new Eina.List<Eina.Stringshare>();
lst.AppendArray(base_seq_strshare);
Test.Assert(t.EinaListStrshareInOwn(lst));
Test.Assert(!lst.Own);
lst.Dispose();
Test.Assert(lst.Handle == IntPtr.Zero);
Test.Assert(t.CheckEinaListStrshareInOwn());
}
public static void test_eina_list_strshare_out()
{
var t = new Dummy.TestObject();
Eina.List<Eina.Stringshare> 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());
}
public static void test_eina_list_strshare_out_own()
{
var t = new Dummy.TestObject();
Eina.List<Eina.Stringshare> lst;
Test.Assert(t.EinaListStrshareOutOwn(out lst));
Test.Assert(lst.Own);
Test.Assert(lst.ToArray().SequenceEqual(base_seq_strshare));
lst.AppendArray(append_seq_strshare);
lst.Dispose();
Test.Assert(lst.Handle == IntPtr.Zero);
}
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());
}
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.AppendArray(append_seq_strshare);
lst.Dispose();
Test.Assert(lst.Handle == IntPtr.Zero);
}
// Object //
public static void test_eina_list_obj_in()
@ -2149,6 +2477,26 @@ class TestEinaHash
hsh.Dispose();
}
public static void data_set_strshare()
{
var hsh = new Eina.Hash<Eina.Stringshare, Eina.Stringshare>();
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<Dummy.Numberwrapper, Dummy.Numberwrapper>();
@ -2236,6 +2584,34 @@ class TestEinaHash
hsh.Dispose();
}
public static void eina_hash_as_ienumerable_strshare()
{
var hsh = new Eina.Hash<Eina.Stringshare, Eina.Stringshare>();
var dct = new Dictionary<Eina.Stringshare,Eina.Stringshare>();
hsh["aa"] = "aaa";
hsh["bb"] = "bbb";
hsh["cc"] = "ccc";
dct["aa"] = "aaa";
dct["bb"] = "bbb";
dct["cc"] = "ccc";
int count = 0;
foreach (KeyValuePair<Eina.Stringshare, Eina.Stringshare> 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<Dummy.Numberwrapper, Dummy.Numberwrapper>();
@ -2444,6 +2820,90 @@ class TestEinaHash
Test.Assert(t.CheckEinaHashStrReturnOwn());
}
// Eina.Stringshare //
/*public static void test_eina_hash_strshare_in()
{
var t = new Dummy.TestObject();
var hsh = new Eina.Hash<Eina.Stringshare, Eina.Stringshare>();
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<Eina.Stringshare, Eina.Stringshare>();
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<string,string> 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<string,string> 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()
@ -2643,6 +3103,38 @@ class TestEinaIterator
arr.Dispose();
}
public static void eina_array_strshare_empty_iterator()
{
var arr = new Eina.Array<Eina.Stringshare>();
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<Eina.Stringshare>();
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<Dummy.Numberwrapper>();
@ -2777,6 +3269,38 @@ class TestEinaIterator
lst.Dispose();
}
public static void eina_list_strshare_empty_iterator()
{
var lst = new Eina.List<Eina.Stringshare>();
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<Eina.Stringshare>();
lst.AppendArray(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<Dummy.Numberwrapper>();
@ -3015,6 +3539,92 @@ class TestEinaIterator
hsh.Dispose();
}
/*
public static void eina_hash_keys_strshare_empty_iterator()
{
var hsh = new Eina.Hash<Eina.Stringshare, Eina.Stringshare>();
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<Eina.Stringshare, Eina.Stringshare>();
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<Eina.Stringshare, Eina.Stringshare>();
var dct = new Dictionary<Eina.Stringshare, bool>();
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<Eina.Stringshare, Eina.Stringshare>();
var dct = new Dictionary<Eina.Stringshare, bool>();
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<Dummy.Numberwrapper, Dummy.Numberwrapper>();
@ -3377,6 +3987,134 @@ class TestEinaIterator
itr.Dispose();
}
// Eina.Stringshare //
public static void test_eina_iterator_strshare_in()
{
var t = new Dummy.TestObject();
var arr = new Eina.Array<Eina.Stringshare>();
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();
}
public static void test_eina_iterator_strshare_in_own()
{
var t = new Dummy.TestObject();
var arr = new Eina.Array<Eina.Stringshare>();
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));
Test.Assert(!itr.Own);
Test.Assert(arr.Own);
Test.Assert(arr.OwnContent);
itr.Dispose();
arr.Dispose();
Test.Assert(t.CheckEinaIteratorStrshareInOwn());
}
public static void test_eina_iterator_strshare_out()
{
var t = new Dummy.TestObject();
Eina.Iterator<Eina.Stringshare> itr;
Test.Assert(t.EinaIteratorStrshareOut(out itr));
Test.Assert(!itr.Own);
int idx = 0;
foreach (Eina.Stringshare e in itr)
{
Test.AssertEquals(e, base_seq_strshare[idx]);
++idx;
}
Test.AssertEquals(idx, base_seq_strshare.Length);
itr.Dispose();
Test.Assert(t.CheckEinaIteratorStrshareOut());
}
public static void test_eina_iterator_strshare_out_own()
{
var t = new Dummy.TestObject();
Eina.Iterator<Eina.Stringshare> itr;
Test.Assert(t.EinaIteratorStrshareOutOwn(out itr));
Test.Assert(itr.Own);
int idx = 0;
foreach (Eina.Stringshare e in itr)
{
Test.AssertEquals(e, base_seq_strshare[idx]);
++idx;
}
Test.AssertEquals(idx, base_seq_strshare.Length);
itr.Dispose();
}
public static void test_eina_iterator_strshare_return()
{
var t = new Dummy.TestObject();
var itr = t.EinaIteratorStrshareReturn();
Test.Assert(!itr.Own);
int idx = 0;
foreach (Eina.Stringshare e in itr)
{
Test.AssertEquals(e, base_seq_strshare[idx]);
++idx;
}
Test.AssertEquals(idx, base_seq_strshare.Length);
itr.Dispose();
Test.Assert(t.CheckEinaIteratorStrshareReturn());
}
public static void test_eina_iterator_strshare_return_own()
{
var t = new Dummy.TestObject();
var itr = t.EinaIteratorStrshareReturnOwn();
Test.Assert(itr.Own);
int idx = 0;
foreach (Eina.Stringshare e in itr)
{
Test.AssertEquals(e, base_seq_strshare[idx]);
++idx;
}
Test.AssertEquals(idx, base_seq_strshare.Length);
itr.Dispose();
}
// Object //
public static void test_eina_iterator_obj_in()

View File

@ -24,6 +24,10 @@ public static class BaseData
public static readonly string[] append_seq_str = {"42","43","33"};
public static readonly string[] modified_seq_str = {"0x0","0x2A","0x42","42","43","33"};
public static readonly Eina.Stringshare[] base_seq_strshare = {"0x0","0x2A","0x42"};
public static readonly Eina.Stringshare[] append_seq_strshare = {"42","43","33"};
public static readonly Eina.Stringshare[] modified_seq_strshare = {"0x0","0x2A","0x42","42","43","33"};
public static Dummy.Numberwrapper NW(int n)
{
var nw = new Dummy.Numberwrapper();

View File

@ -19,6 +19,7 @@ typedef struct Dummy_Test_Object_Data
// Containers passed to C# as iterator/accessors
Eina_Array *out_array;
Eina_Free_Cb out_array_free_element_cb;
} Dummy_Test_Object_Data;
static
@ -101,7 +102,15 @@ _dummy_test_object_efl_object_destructor(Eo *obj, Dummy_Test_Object_Data *pd)
}
if (pd->out_array)
eina_array_free(pd->out_array);
{
if (pd->out_array_free_element_cb)
{
unsigned n = eina_array_count(pd->out_array);
for (unsigned i = 0; i < n; ++i)
pd->out_array_free_element_cb(eina_array_data_get(pd->out_array, i));
}
eina_array_free(pd->out_array);
}
efl_destructor(efl_super(obj, DUMMY_TEST_OBJECT_CLASS));
}
@ -728,6 +737,139 @@ Eina_Array *_dummy_test_object_eina_array_str_return_own(EINA_UNUSED Eo *obj, EI
return arr;
}
// Eina_Stringshare
Eina_Bool _array_strshare_equal(const Eina_Array *arr, const char * const base[], unsigned int len)
{
Eina_Bool result = EINA_TRUE;
if (eina_array_count(arr) != len)
return EINA_FALSE;
for (unsigned int i = 0; i < len && result; ++i)
{
Eina_Stringshare *ssa = eina_array_data_get(arr, i);
Eina_Stringshare *sse = eina_stringshare_add(base[i]);
result = (ssa == sse);
if (!result)
fprintf(stderr, "Unexpected stringshare value. Expected: \"%s\" [%p]; Actual: \"%s\" [%p].\n", sse, sse, ssa, ssa);
eina_stringshare_del(sse);
}
return result;
}
Eina_Bool _dummy_test_object_eina_array_strshare_in(EINA_UNUSED Eo *obj, EINA_UNUSED Dummy_Test_Object_Data *pd, Eina_Array *arr)
{
Eina_Bool r = _array_strshare_equal(arr, base_seq_str, base_seq_str_size);
eina_array_push(arr, eina_stringshare_add("42"));
eina_array_push(arr, eina_stringshare_add("43"));
eina_array_push(arr, eina_stringshare_add("33"));
return r;
}
static Eina_Array *_array_strshare_in_own_to_check = NULL;
Eina_Bool _dummy_test_object_eina_array_strshare_in_own(EINA_UNUSED Eo *obj, EINA_UNUSED Dummy_Test_Object_Data *pd, Eina_Array *arr)
{
Eina_Bool r = _array_strshare_equal(arr, base_seq_str, base_seq_str_size);
eina_array_push(arr, eina_stringshare_add("42"));
eina_array_push(arr, eina_stringshare_add("43"));
eina_array_push(arr, eina_stringshare_add("33"));
_array_strshare_in_own_to_check = arr;
return r;
}
Eina_Bool _dummy_test_object_check_eina_array_strshare_in_own(EINA_UNUSED Eo *obj, EINA_UNUSED Dummy_Test_Object_Data *pd)
{
if (!_array_strshare_in_own_to_check) return EINA_FALSE;
Eina_Bool r = _array_strshare_equal(_array_strshare_in_own_to_check, modified_seq_str, modified_seq_str_size);
unsigned int i;
Eina_Stringshare *ele;
Eina_Array_Iterator it;
EINA_ARRAY_ITER_NEXT(_array_strshare_in_own_to_check, i, ele, it)
eina_stringshare_del(ele);
eina_array_free(_array_strshare_in_own_to_check);
_array_strshare_in_own_to_check = NULL;
return r;
}
Eina_Array *_array_strshare_out_to_check = NULL;
Eina_Bool _dummy_test_object_eina_array_strshare_out(EINA_UNUSED Eo *obj, EINA_UNUSED Dummy_Test_Object_Data *pd, Eina_Array **arr)
{
if (!arr) return EINA_FALSE;
*arr = eina_array_new(default_step);
eina_array_push(*arr, eina_stringshare_add("0x0"));
eina_array_push(*arr, eina_stringshare_add("0x2A"));
eina_array_push(*arr, eina_stringshare_add("0x42"));
_array_strshare_out_to_check = *arr;
return EINA_TRUE;
}
Eina_Bool _dummy_test_object_check_eina_array_strshare_out(EINA_UNUSED Eo *obj, EINA_UNUSED Dummy_Test_Object_Data *pd)
{
if (!_array_strshare_out_to_check) return EINA_FALSE;
Eina_Bool r = _array_strshare_equal(_array_strshare_out_to_check, modified_seq_str, modified_seq_str_size);
unsigned int i;
Eina_Stringshare *ele;
Eina_Array_Iterator it;
EINA_ARRAY_ITER_NEXT(_array_strshare_out_to_check, i, ele, it)
eina_stringshare_del(ele);
eina_array_free(_array_strshare_out_to_check);
_array_strshare_out_to_check = NULL;
return r;
}
Eina_Bool _dummy_test_object_eina_array_strshare_out_own(EINA_UNUSED Eo *obj, EINA_UNUSED Dummy_Test_Object_Data *pd, Eina_Array **arr)
{
if (!arr) return EINA_FALSE;
*arr = eina_array_new(default_step);
eina_array_push(*arr, eina_stringshare_add("0x0"));
eina_array_push(*arr, eina_stringshare_add("0x2A"));
eina_array_push(*arr, eina_stringshare_add("0x42"));
return EINA_TRUE;
}
Eina_Array *_array_strshare_return_to_check = NULL;
Eina_Array *_dummy_test_object_eina_array_strshare_return(EINA_UNUSED Eo *obj, EINA_UNUSED Dummy_Test_Object_Data *pd)
{
Eina_Array *arr = eina_array_new(default_step);
eina_array_push(arr, eina_stringshare_add("0x0"));
eina_array_push(arr, eina_stringshare_add("0x2A"));
eina_array_push(arr, eina_stringshare_add("0x42"));
_array_strshare_return_to_check = arr;
return arr;
}
Eina_Bool _dummy_test_object_check_eina_array_strshare_return(EINA_UNUSED Eo *obj, EINA_UNUSED Dummy_Test_Object_Data *pd)
{
if (!_array_strshare_return_to_check) return EINA_FALSE;
Eina_Bool r = _array_strshare_equal(_array_strshare_return_to_check, modified_seq_str, modified_seq_str_size);
unsigned int i;
Eina_Stringshare *ele;
Eina_Array_Iterator it;
EINA_ARRAY_ITER_NEXT(_array_strshare_return_to_check, i, ele, it)
eina_stringshare_del(ele);
eina_array_free(_array_strshare_return_to_check);
_array_strshare_return_to_check = NULL;
return r;
}
Eina_Array *_dummy_test_object_eina_array_strshare_return_own(EINA_UNUSED Eo *obj, EINA_UNUSED Dummy_Test_Object_Data *pd)
{
Eina_Array *arr = eina_array_new(default_step);
eina_array_push(arr, eina_stringshare_add("0x0"));
eina_array_push(arr, eina_stringshare_add("0x2A"));
eina_array_push(arr, eina_stringshare_add("0x42"));
return arr;
}
// Object
Eina_Bool _array_obj_equal(const Eina_Array *arr, const Dummy_Numberwrapper * const base[], unsigned int len)
@ -1488,6 +1630,136 @@ Eina_List *_dummy_test_object_eina_list_str_return_own(EINA_UNUSED Eo *obj, EINA
return lst;
}
// Eina_Stringshare
Eina_Bool _list_strshare_equal(const Eina_List *lst, const char * const base[], unsigned int len)
{
if (eina_list_count(lst) != len)
return EINA_FALSE;
const Eina_List *l;
Eina_Stringshare *data;
int i = 0;
EINA_LIST_FOREACH(lst, l, data)
{
Eina_Stringshare *ssa = data;
Eina_Stringshare *sse = eina_stringshare_add(base[i]);
if (ssa != sse)
{
fprintf(stderr, "Unexpected stringshare value. Expected: \"%s\" [%p]; Actual: \"%s\" [%p].\n", sse, sse, ssa, ssa);
eina_stringshare_del(sse);
return EINA_FALSE;
}
eina_stringshare_del(sse);
++i;
}
return EINA_TRUE;
}
Eina_Bool _dummy_test_object_eina_list_strshare_in(EINA_UNUSED Eo *obj, EINA_UNUSED Dummy_Test_Object_Data *pd, Eina_List *lst)
{
Eina_Bool r = _list_strshare_equal(lst, base_seq_str, base_seq_str_size);
return r;
}
static Eina_List *_list_strshare_in_own_to_check = NULL;
Eina_Bool _dummy_test_object_eina_list_strshare_in_own(EINA_UNUSED Eo *obj, EINA_UNUSED Dummy_Test_Object_Data *pd, Eina_List *lst)
{
Eina_Bool r = _list_strshare_equal(lst, base_seq_str, base_seq_str_size);
if (!r) return r;
lst = eina_list_append(lst, eina_stringshare_add("42"));
lst = eina_list_append(lst, eina_stringshare_add("43"));
lst = eina_list_append(lst, eina_stringshare_add("33"));
_list_strshare_in_own_to_check = lst;
return r;
}
Eina_Bool _dummy_test_object_check_eina_list_strshare_in_own(EINA_UNUSED Eo *obj, EINA_UNUSED Dummy_Test_Object_Data *pd)
{
if (!_list_strshare_in_own_to_check) return EINA_FALSE;
Eina_Bool r = _list_strshare_equal(_list_strshare_in_own_to_check, modified_seq_str, modified_seq_str_size);
if (!r) return r;
Eina_Stringshare *ele;
EINA_LIST_FREE(_list_strshare_in_own_to_check, ele)
eina_stringshare_del(ele);
_list_strshare_in_own_to_check = NULL;
return r;
}
Eina_List *_list_strshare_out_to_check = NULL;
Eina_Bool _dummy_test_object_eina_list_strshare_out(EINA_UNUSED Eo *obj, EINA_UNUSED Dummy_Test_Object_Data *pd, Eina_List **lst)
{
if (!lst) return EINA_FALSE;
*lst = eina_list_append(*lst, eina_stringshare_add("0x0"));
*lst = eina_list_append(*lst, eina_stringshare_add("0x2A"));
*lst = eina_list_append(*lst, eina_stringshare_add("0x42"));
_list_strshare_out_to_check = *lst;
return EINA_TRUE;
}
Eina_Bool _dummy_test_object_check_eina_list_strshare_out(EINA_UNUSED Eo *obj, EINA_UNUSED Dummy_Test_Object_Data *pd)
{
if (!_list_strshare_out_to_check) return EINA_FALSE;
Eina_Bool r = _list_strshare_equal(_list_strshare_out_to_check, base_seq_str, base_seq_str_size);
if (!r) return r;
Eina_Stringshare *ele;
EINA_LIST_FREE(_list_strshare_out_to_check, ele)
eina_stringshare_del(ele);
_list_strshare_out_to_check = NULL;
return r;
}
Eina_Bool _dummy_test_object_eina_list_strshare_out_own(EINA_UNUSED Eo *obj, EINA_UNUSED Dummy_Test_Object_Data *pd, Eina_List **lst)
{
if (!lst) return EINA_FALSE;
*lst = eina_list_append(*lst, eina_stringshare_add("0x0"));
*lst = eina_list_append(*lst, eina_stringshare_add("0x2A"));
*lst = eina_list_append(*lst, eina_stringshare_add("0x42"));
return EINA_TRUE;
}
Eina_List *_list_strshare_return_to_check = NULL;
Eina_List *_dummy_test_object_eina_list_strshare_return(EINA_UNUSED Eo *obj, EINA_UNUSED Dummy_Test_Object_Data *pd)
{
Eina_List *lst = NULL;
lst = eina_list_append(lst, eina_stringshare_add("0x0"));
lst = eina_list_append(lst, eina_stringshare_add("0x2A"));
lst = eina_list_append(lst, eina_stringshare_add("0x42"));
_list_strshare_return_to_check = lst;
return lst;
}
Eina_Bool _dummy_test_object_check_eina_list_strshare_return(EINA_UNUSED Eo *obj, EINA_UNUSED Dummy_Test_Object_Data *pd)
{
if (!_list_strshare_return_to_check) return EINA_FALSE;
Eina_Bool r = _list_strshare_equal(_list_strshare_return_to_check, base_seq_str, base_seq_str_size);
if (!r) return r;
Eina_Stringshare *ele;
EINA_LIST_FREE(_list_strshare_return_to_check, ele)
eina_stringshare_del(ele);
_list_strshare_return_to_check = NULL;
return r;
}
Eina_List *_dummy_test_object_eina_list_strshare_return_own(EINA_UNUSED Eo *obj, EINA_UNUSED Dummy_Test_Object_Data *pd)
{
Eina_List *lst = NULL;
lst = eina_list_append(lst, eina_stringshare_add("0x0"));
lst = eina_list_append(lst, eina_stringshare_add("0x2A"));
lst = eina_list_append(lst, eina_stringshare_add("0x42"));
return lst;
}
// Object
Eina_Bool _list_obj_equal(const Eina_List *lst, const Dummy_Numberwrapper * const base[], unsigned int len)
@ -1923,6 +2195,164 @@ Eina_Inlist *_dummy_test_object_eina_inlist_str_return_own(EINA_UNUSED Eo *obj,
return lst;
}
// Eina_Stringshare
typedef struct _Dummy_Inlist_Node_Strshare
{
EINA_INLIST;
Eina_Stringshare *val;
} Dummy_Inlist_Node_Strshare;
Eina_Inlist *_new_inlist_strshare(const char *v)
{
Dummy_Inlist_Node_Strshare *node = malloc(sizeof(Dummy_Inlist_Node_Strshare));
node->val = eina_stringshare_add(v);
return EINA_INLIST_GET(node);
}
Eina_Bool _inlist_strshare_equal(const Eina_Inlist *lst, const char * const base[], unsigned int len)
{
if (eina_inlist_count(lst) != len)
return EINA_FALSE;
const Dummy_Inlist_Node_Strshare *node;
int i = 0;
EINA_INLIST_FOREACH(lst, node)
{
Eina_Stringshare *ssa = node->val;
Eina_Stringshare *sse = eina_stringshare_add(base[i]);
if (ssa != sse)
{
fprintf(stderr, "Unexpected stringshare value. Expected: \"%s\" [%p]; Actual: \"%s\" [%p].\n", sse, sse, ssa, ssa);
eina_stringshare_del(sse);
return EINA_FALSE;
}
eina_stringshare_del(sse);
++i;
}
return EINA_TRUE;
}
Eina_Bool _dummy_test_object_eina_inlist_strshare_in(EINA_UNUSED Eo *obj, EINA_UNUSED Dummy_Test_Object_Data *pd, Eina_Inlist *lst)
{
Eina_Bool r = _inlist_strshare_equal(lst, base_seq_str, base_seq_str_size);
return r;
}
static Eina_Inlist *_inlist_strshare_in_own_to_check = NULL;
Eina_Bool _dummy_test_object_eina_inlist_strshare_in_own(EINA_UNUSED Eo *obj, EINA_UNUSED Dummy_Test_Object_Data *pd, Eina_Inlist *lst)
{
Eina_Bool r = _inlist_strshare_equal(lst, base_seq_str, base_seq_str_size);
if (!r) return r;
lst = eina_inlist_append(lst, _new_inlist_strshare("42"));
lst = eina_inlist_append(lst, _new_inlist_strshare("43"));
lst = eina_inlist_append(lst, _new_inlist_strshare("33"));
_inlist_strshare_in_own_to_check = lst;
return r;
}
Eina_Bool _dummy_test_object_check_eina_inlist_strshare_in_own(EINA_UNUSED Eo *obj, EINA_UNUSED Dummy_Test_Object_Data *pd)
{
Eina_Inlist *lst = _inlist_strshare_in_own_to_check;
if (!lst) return EINA_FALSE;
_inlist_strshare_in_own_to_check = NULL;
Eina_Bool r = _inlist_strshare_equal(lst, modified_seq_str, modified_seq_str_size);
if (!r) return r;
Dummy_Inlist_Node_Strshare *node;
EINA_INLIST_FREE(lst, node)
{
lst = eina_inlist_remove(lst, EINA_INLIST_GET(node));
eina_stringshare_del(node->val);
free(node);
}
return r;
}
Eina_Inlist *_inlist_strshare_out_to_check = NULL;
Eina_Bool _dummy_test_object_eina_inlist_strshare_out(EINA_UNUSED Eo *obj, EINA_UNUSED Dummy_Test_Object_Data *pd, Eina_Inlist **lst)
{
if (!lst) return EINA_FALSE;
*lst = eina_inlist_append(*lst, _new_inlist_strshare("0x0"));
*lst = eina_inlist_append(*lst, _new_inlist_strshare("0x2A"));
*lst = eina_inlist_append(*lst, _new_inlist_strshare("0x42"));
_inlist_strshare_out_to_check = *lst;
return EINA_TRUE;
}
Eina_Bool _dummy_test_object_check_eina_inlist_strshare_out(EINA_UNUSED Eo *obj, EINA_UNUSED Dummy_Test_Object_Data *pd)
{
Eina_Inlist *lst = _inlist_strshare_out_to_check;
if (!lst) return EINA_FALSE;
_inlist_strshare_out_to_check = NULL;
Eina_Bool r = _inlist_strshare_equal(lst, base_seq_str, base_seq_str_size);
if (!r) return r;
Dummy_Inlist_Node_Strshare *node;
EINA_INLIST_FREE(lst, node)
{
lst = eina_inlist_remove(lst, EINA_INLIST_GET(node));
eina_stringshare_del(node->val);
free(node);
}
return r;
}
Eina_Bool _dummy_test_object_eina_inlist_strshare_out_own(EINA_UNUSED Eo *obj, EINA_UNUSED Dummy_Test_Object_Data *pd, Eina_Inlist **lst)
{
if (!lst) return EINA_FALSE;
*lst = eina_inlist_append(*lst, _new_inlist_strshare("0x0"));
*lst = eina_inlist_append(*lst, _new_inlist_strshare("0x2A"));
*lst = eina_inlist_append(*lst, _new_inlist_strshare("0x42"));
return EINA_TRUE;
}
Eina_Inlist *_inlist_strshare_return_to_check = NULL;
Eina_Inlist *_dummy_test_object_eina_inlist_strshare_return(EINA_UNUSED Eo *obj, EINA_UNUSED Dummy_Test_Object_Data *pd)
{
Eina_Inlist *lst = NULL;
lst = eina_inlist_append(lst, _new_inlist_strshare("0x0"));
lst = eina_inlist_append(lst, _new_inlist_strshare("0x2A"));
lst = eina_inlist_append(lst, _new_inlist_strshare("0x42"));
_inlist_strshare_return_to_check = lst;
return lst;
}
Eina_Bool _dummy_test_object_check_eina_inlist_strshare_return(EINA_UNUSED Eo *obj, EINA_UNUSED Dummy_Test_Object_Data *pd)
{
Eina_Inlist *lst = _inlist_strshare_return_to_check;
if (!lst) return EINA_FALSE;
_inlist_strshare_return_to_check = NULL;
Eina_Bool r = _inlist_strshare_equal(lst, base_seq_str, base_seq_str_size);
if (!r) return r;
Dummy_Inlist_Node_Strshare *node;
EINA_INLIST_FREE(lst, node)
{
lst = eina_inlist_remove(lst, EINA_INLIST_GET(node));
eina_stringshare_del(node->val);
free(node);
}
return r;
}
Eina_Inlist *_dummy_test_object_eina_inlist_strshare_return_own(EINA_UNUSED Eo *obj, EINA_UNUSED Dummy_Test_Object_Data *pd)
{
Eina_Inlist *lst = NULL;
lst = eina_inlist_append(lst, _new_inlist_strshare("0x0"));
lst = eina_inlist_append(lst, _new_inlist_strshare("0x2A"));
lst = eina_inlist_append(lst, _new_inlist_strshare("0x42"));
return lst;
}
// Object
typedef struct _Dummy_Inlist_Node_Obj
@ -2444,6 +2874,194 @@ Eina_Bool _dummy_test_object_check_eina_hash_str_return_own(EINA_UNUSED Eo *obj,
}
// Eina_Stringshare //
Eina_Bool _hash_strshare_check(const Eina_Hash *hsh, const char *key, const char *expected_val)
{
Eina_Stringshare *ssk = eina_stringshare_add(key);
Eina_Stringshare *sse = eina_stringshare_add(expected_val);
Eina_Stringshare *ssa = eina_hash_find(hsh, ssk);
Eina_Bool result = (ssa == sse);
if (!result)
fprintf(stderr, "Unexpected stringshare value. Expected: \"%s\" [%p]; Actual: \"%s\" [%p].\n", sse, sse, ssa, ssa);
eina_stringshare_del(ssk);
eina_stringshare_del(sse);
return result;
}
static inline Eina_Bool _hash_strshare_add(Eina_Hash *hsh, const char *key, const char *val)
{
return eina_hash_add(hsh, eina_stringshare_add(key), eina_stringshare_add(val));
}
// strshare in
Eina_Bool _dummy_test_object_eina_hash_strshare_in(EINA_UNUSED Eo *obj, EINA_UNUSED Dummy_Test_Object_Data *pd, Eina_Hash *hsh)
{
if (!_hash_strshare_check(hsh, "aa", "aaa"))
return EINA_FALSE;
return _hash_strshare_add(hsh, "bb", "bbb");
}
// strshare in own
static Eina_Bool _hash_strshare_in_own_free_flag = EINA_FALSE;
static void _hash_strshare_in_own_free_cb(void *data)
{
_hash_strshare_in_own_free_flag = EINA_TRUE;
eina_stringshare_del(data);
}
static Eina_Hash *_hash_strshare_in_own_to_check = NULL;
Eina_Bool _dummy_test_object_eina_hash_strshare_in_own(EINA_UNUSED Eo *obj, EINA_UNUSED Dummy_Test_Object_Data *pd, Eina_Hash *hsh)
{
eina_hash_free_cb_set(hsh, _hash_strshare_in_own_free_cb);
if (!_hash_strshare_check(hsh, "aa", "aaa"))
return EINA_FALSE;
_hash_strshare_in_own_to_check = hsh;
return _hash_strshare_add(hsh, "bb", "bbb");
}
Eina_Bool _dummy_test_object_check_eina_hash_strshare_in_own(EINA_UNUSED Eo *obj, EINA_UNUSED Dummy_Test_Object_Data *pd)
{
if (!_hash_strshare_in_own_to_check) return EINA_FALSE;
Eina_Hash *hsh = _hash_strshare_in_own_to_check;
if (!_hash_strshare_check(hsh, "aa", "aaa")
|| !_hash_strshare_check(hsh, "bb", "bbb")
|| !_hash_strshare_check(hsh, "cc", "ccc"))
return EINA_FALSE;
eina_hash_free(hsh);
return _hash_strshare_in_own_free_flag;
}
// strshare out
static Eina_Bool _hash_strshare_out_free_flag = EINA_FALSE;
static void _hash_strshare_out_free_cb(void *data)
{
_hash_strshare_out_free_flag = EINA_TRUE;
eina_stringshare_del(data);
}
Eina_Hash *_hash_strshare_out_to_check = NULL;
Eina_Bool _dummy_test_object_eina_hash_strshare_out(EINA_UNUSED Eo *obj, EINA_UNUSED Dummy_Test_Object_Data *pd, Eina_Hash **hsh)
{
if (!hsh) return EINA_FALSE;
*hsh = eina_hash_string_superfast_new(_hash_strshare_out_free_cb);
_hash_strshare_out_to_check = *hsh;
return _hash_strshare_add(*hsh, "aa", "aaa");
}
Eina_Bool _dummy_test_object_check_eina_hash_strshare_out(EINA_UNUSED Eo *obj, EINA_UNUSED Dummy_Test_Object_Data *pd)
{
if (!_hash_strshare_out_to_check) return EINA_FALSE;
Eina_Hash *hsh = _hash_strshare_out_to_check;
if (!_hash_strshare_check(hsh, "aa", "aaa")
|| !_hash_strshare_check(hsh, "bb", "bbb"))
return EINA_FALSE;
eina_hash_free(hsh);
_hash_strshare_out_to_check = NULL;
return _hash_strshare_out_free_flag;
}
// strshare out own
static Eina_Bool _hash_strshare_out_own_free_flag = EINA_FALSE;
static void _hash_strshare_out_own_free_cb(void *data)
{
_hash_strshare_out_own_free_flag = EINA_TRUE;
eina_stringshare_del(data);
}
Eina_Bool _dummy_test_object_eina_hash_strshare_out_own(EINA_UNUSED Eo *obj, EINA_UNUSED Dummy_Test_Object_Data *pd, Eina_Hash **hsh)
{
if (!hsh) return EINA_FALSE;
*hsh = eina_hash_string_superfast_new(_hash_strshare_out_own_free_cb);
return _hash_strshare_add(*hsh, "aa", "aaa");
}
Eina_Bool _dummy_test_object_check_eina_hash_strshare_out_own(EINA_UNUSED Eo *obj, EINA_UNUSED Dummy_Test_Object_Data *pd)
{
return !_hash_strshare_out_own_free_flag;
}
// strshare return
static Eina_Bool _hash_strshare_return_free_flag = EINA_FALSE;
static void _hash_strshare_return_free_cb(void *data)
{
_hash_strshare_return_free_flag = EINA_TRUE;
eina_stringshare_del(data);
}
Eina_Hash *_hash_strshare_return_to_check = NULL;
Eina_Hash *_dummy_test_object_eina_hash_strshare_return(EINA_UNUSED Eo *obj, EINA_UNUSED Dummy_Test_Object_Data *pd)
{
Eina_Hash *hsh = eina_hash_string_superfast_new(_hash_strshare_return_free_cb);
_hash_strshare_add(hsh, "aa", "aaa");
_hash_strshare_return_to_check = hsh;
return hsh;
}
Eina_Bool _dummy_test_object_check_eina_hash_strshare_return(EINA_UNUSED Eo *obj, EINA_UNUSED Dummy_Test_Object_Data *pd)
{
if (!_hash_strshare_return_to_check) return EINA_FALSE;
Eina_Hash *hsh = _hash_strshare_return_to_check;
if (!_hash_strshare_check(hsh, "aa", "aaa")
|| !_hash_strshare_check(hsh, "bb", "bbb"))
return EINA_FALSE;
eina_hash_free(hsh);
_hash_strshare_return_to_check = NULL;
return _hash_strshare_return_free_flag;
}
// strshare return own
static Eina_Bool _hash_strshare_return_own_free_flag = EINA_FALSE;
static void _hash_strshare_return_own_free_cb(void *data)
{
_hash_strshare_return_own_free_flag = EINA_TRUE;
eina_stringshare_del(data);
}
Eina_Hash *_dummy_test_object_eina_hash_strshare_return_own(EINA_UNUSED Eo *obj, EINA_UNUSED Dummy_Test_Object_Data *pd)
{
Eina_Hash *hsh = eina_hash_string_superfast_new(_hash_strshare_return_own_free_cb);
_hash_strshare_add(hsh, "aa", "aaa");
return hsh;
}
Eina_Bool _dummy_test_object_check_eina_hash_strshare_return_own(EINA_UNUSED Eo *obj, EINA_UNUSED Dummy_Test_Object_Data *pd)
{
return !_hash_strshare_return_own_free_flag;
}
// Object //
Eina_Bool _hash_obj_check(const Eina_Hash *hsh, Dummy_Numberwrapper *key, Dummy_Numberwrapper *expected_val, int knum, int vnum)
@ -2966,6 +3584,174 @@ Eina_Iterator *_dummy_test_object_eina_iterator_str_return_own(EINA_UNUSED Eo *o
return eina_array_iterator_new(pd->out_array);
}
// Eina_Stringshare //
Eina_Bool _iterator_strshare_equal(Eina_Iterator *itr, const char * const base[], unsigned int len, Eina_Bool release)
{
Eina_Stringshare *ssa;
unsigned i = 0;
EINA_ITERATOR_FOREACH(itr, ssa)
{
Eina_Stringshare *sse = eina_stringshare_add(base[i]);
if (ssa != sse)
{
fprintf(stderr, "Unexpected stringshare value. Expected: \"%s\" [%p]; Actual: \"%s\" [%p].\n", sse, sse, ssa, ssa);
eina_stringshare_del(sse);
return EINA_FALSE;
}
eina_stringshare_del(sse);
if (release)
eina_stringshare_del(ssa);
++i;
}
if (i != len)
return EINA_FALSE;
return EINA_TRUE;
}
Eina_Array *_iterator_strshare_eina_array_new()
{
Eina_Array *arr = eina_array_new(32);
for (unsigned i = 0; i < base_seq_str_size; ++i)
{
eina_array_push(arr, eina_stringshare_add(base_seq_str[i]));
}
return arr;
}
Eina_Bool _iterator_strshare_test_array(Eina_Array *arr)
{
if (eina_array_count(arr) != base_seq_str_size)
return EINA_FALSE;
for (unsigned i = 0; i < base_seq_str_size; ++i)
{
Eina_Stringshare *ssa = eina_array_data_get(arr, i);
Eina_Stringshare *sse = eina_stringshare_add(base_seq_str[i]);
if (ssa != sse)
return EINA_FALSE;
eina_stringshare_del(ssa);
eina_stringshare_del(sse);
}
eina_array_free(arr);
return EINA_TRUE;
}
// <strshare> in
Eina_Bool _dummy_test_object_eina_iterator_strshare_in(EINA_UNUSED Eo *obj, EINA_UNUSED Dummy_Test_Object_Data *pd, Eina_Iterator *itr)
{
Eina_Bool r = _iterator_strshare_equal(itr, base_seq_str, base_seq_str_size, EINA_FALSE);
return r;
}
// <strshare> in own
static Eina_Iterator *_iterator_strshare_in_own_to_check = NULL;
Eina_Bool _dummy_test_object_eina_iterator_strshare_in_own(EINA_UNUSED Eo *obj, EINA_UNUSED Dummy_Test_Object_Data *pd, Eina_Iterator *itr)
{
Eina_Bool r = _iterator_strshare_equal(itr, base_seq_str, base_seq_str_size, EINA_FALSE);
_iterator_strshare_in_own_to_check = itr;
return r;
}
Eina_Bool _dummy_test_object_check_eina_iterator_strshare_in_own(EINA_UNUSED Eo *obj, EINA_UNUSED Dummy_Test_Object_Data *pd)
{
eina_iterator_free(_iterator_strshare_in_own_to_check);
_iterator_strshare_in_own_to_check = NULL;
return EINA_TRUE;
}
// <strshare> out
Eina_Iterator *_iterator_strshare_out_to_check = NULL;
Eina_Array *_iterator_strshare_out_array = NULL;
Eina_Bool _dummy_test_object_eina_iterator_strshare_out(EINA_UNUSED Eo *obj, EINA_UNUSED Dummy_Test_Object_Data *pd, Eina_Iterator **itr)
{
if (!itr) return EINA_FALSE;
_iterator_strshare_out_array = _iterator_strshare_eina_array_new();
*itr = eina_array_iterator_new(_iterator_strshare_out_array);
_iterator_strshare_out_to_check = *itr;
return EINA_TRUE;
}
Eina_Bool _dummy_test_object_check_eina_iterator_strshare_out(EINA_UNUSED Eo *obj, EINA_UNUSED Dummy_Test_Object_Data *pd)
{
Eina_Iterator *itr = _iterator_strshare_out_to_check;
if (!itr) return EINA_FALSE;
_iterator_strshare_out_to_check = NULL;
Eina_Array *arr = _iterator_strshare_out_array;
if (!arr) return EINA_FALSE;
_iterator_strshare_out_array = NULL;
Eina_Bool r = _iterator_strshare_test_array(arr);
if (!r) return r;
eina_iterator_free(itr);
return r;
}
// <strshare> out own
Eina_Bool _dummy_test_object_eina_iterator_strshare_out_own(EINA_UNUSED Eo *obj, Dummy_Test_Object_Data *pd, Eina_Iterator **itr)
{
if (!itr) return EINA_FALSE;
pd->out_array = _iterator_strshare_eina_array_new();
pd->out_array_free_element_cb = (Eina_Free_Cb) eina_stringshare_del;
*itr = eina_array_iterator_new(pd->out_array);
return EINA_TRUE;
}
// <strshare> return
Eina_Iterator *_iterator_strshare_return_to_check = NULL;
Eina_Array *_iterator_strshare_return_array = NULL;
Eina_Iterator *_dummy_test_object_eina_iterator_strshare_return(EINA_UNUSED Eo *obj, EINA_UNUSED Dummy_Test_Object_Data *pd)
{
_iterator_strshare_return_array = _iterator_strshare_eina_array_new();
_iterator_strshare_return_to_check = eina_array_iterator_new(_iterator_strshare_return_array);
return _iterator_strshare_return_to_check;
}
Eina_Bool _dummy_test_object_check_eina_iterator_strshare_return(EINA_UNUSED Eo *obj, EINA_UNUSED Dummy_Test_Object_Data *pd)
{
Eina_Iterator *itr = _iterator_strshare_return_to_check;
if (!itr) return EINA_FALSE;
_iterator_strshare_return_to_check = NULL;
Eina_Array *arr = _iterator_strshare_return_array;
if (!arr) return EINA_FALSE;
_iterator_strshare_return_array = NULL;
Eina_Bool r = _iterator_strshare_test_array(arr);
if (!r) return r;
eina_iterator_free(itr);
return r;
}
// <strshare> return own
Eina_Iterator *_dummy_test_object_eina_iterator_strshare_return_own(EINA_UNUSED Eo *obj, Dummy_Test_Object_Data *pd)
{
pd->out_array = _iterator_strshare_eina_array_new();
pd->out_array_free_element_cb = (Eina_Free_Cb) eina_stringshare_del;
return eina_array_iterator_new(pd->out_array);
}
// Object //
Eina_Bool _iterator_obj_equal(Eina_Iterator *itr, const Dummy_Numberwrapper * const base[], unsigned int len, Eina_Bool release)

View File

@ -468,6 +468,52 @@ class Dummy.Test_Object extends Efl.Object implements Dummy.Test_Iface {
return: array<mstring @owned> @owned;
}
/* Eina_Stringshare */
eina_array_strshare_in {
params {
@in arr: array<stringshare>;
}
return: bool;
}
eina_array_strshare_in_own {
params {
@in arr: array<stringshare @owned> @owned;
}
return: bool;
}
check_eina_array_strshare_in_own {
return: bool;
}
eina_array_strshare_out {
params {
@out arr: array<stringshare>;
}
return: bool;
}
check_eina_array_strshare_out {
return: bool;
}
eina_array_strshare_out_own {
params {
@out arr: array<stringshare @owned> @owned;
}
return: bool;
}
eina_array_strshare_return {
return: array<stringshare>;
}
check_eina_array_strshare_return {
return: bool;
}
eina_array_strshare_return_own {
return: array<stringshare @owned> @owned;
}
/* Object */
eina_array_obj_in {
params {
@ -615,6 +661,52 @@ class Dummy.Test_Object extends Efl.Object implements Dummy.Test_Iface {
return: list<mstring @owned> @owned;
}
/* Eina_Stringshare */
eina_list_strshare_in {
params {
@in lst: list<stringshare>;
}
return: bool;
}
eina_list_strshare_in_own {
params {
@in lst: list<stringshare @owned> @owned;
}
return: bool;
}
check_eina_list_strshare_in_own {
return: bool;
}
eina_list_strshare_out {
params {
@out lst: list<stringshare>;
}
return: bool;
}
check_eina_list_strshare_out {
return: bool;
}
eina_list_strshare_out_own {
params {
@out lst: list<stringshare @owned> @owned;
}
return: bool;
}
eina_list_strshare_return {
return: list<stringshare>;
}
check_eina_list_strshare_return {
return: bool;
}
eina_list_strshare_return_own {
return: list<stringshare @owned> @owned;
}
/* Object */
eina_list_obj_in {
params {
@ -774,6 +866,58 @@ class Dummy.Test_Object extends Efl.Object implements Dummy.Test_Iface {
return: bool;
}
// Eina_Stringshare //
eina_hash_strshare_in {
params {
@in hsh: hash<stringshare, stringshare>;
}
return: bool;
}
eina_hash_strshare_in_own {
params {
@in hsh: hash<stringshare, stringshare @owned> @owned;
}
return: bool;
}
check_eina_hash_strshare_in_own {
return: bool;
}
eina_hash_strshare_out {
params {
@out hsh: hash<stringshare, stringshare>;
}
return: bool;
}
check_eina_hash_strshare_out {
return: bool;
}
eina_hash_strshare_out_own {
params {
@out hsh: hash<stringshare, stringshare @owned> @owned;
}
return: bool;
}
check_eina_hash_strshare_out_own {
return: bool;
}
eina_hash_strshare_return {
return: hash<stringshare, stringshare>;
}
check_eina_hash_strshare_return {
return: bool;
}
eina_hash_strshare_return_own {
return: hash<stringshare, stringshare @owned> @owned;
}
check_eina_hash_strshare_return_own {
return: bool;
}
// Object //
eina_hash_obj_in {
params {
@ -958,6 +1102,52 @@ class Dummy.Test_Object extends Efl.Object implements Dummy.Test_Iface {
return: iterator<mstring> @owned;
}
/* Eina_Stringshare */
eina_iterator_strshare_in {
params {
@in itr: iterator<stringshare>;
}
return: bool;
}
eina_iterator_strshare_in_own {
params {
@in itr: iterator<stringshare> @owned;
}
return: bool;
}
check_eina_iterator_strshare_in_own {
return: bool;
}
eina_iterator_strshare_out {
params {
@out itr: iterator<stringshare>;
}
return: bool;
}
check_eina_iterator_strshare_out {
return: bool;
}
eina_iterator_strshare_out_own {
params {
@out itr: iterator<stringshare> @owned;
}
return: bool;
}
eina_iterator_strshare_return {
return: iterator<stringshare>;
}
check_eina_iterator_strshare_return {
return: bool;
}
eina_iterator_strshare_return_own {
return: iterator<stringshare> @owned;
}
/* Object */
eina_iterator_obj_in {
params {