efl_mono: Initial version of Strbuf support.

Also moved the ValueOwnership enum from eina value to eina.Ownership. It
can be shared among the eina structures if needed.
This commit is contained in:
Lauro Moura 2018-01-26 17:01:03 -03:00 committed by Felipe Magno de Almeida
parent 92f5383e3c
commit e2fafe5b0c
14 changed files with 371 additions and 30 deletions

View File

@ -21,7 +21,8 @@ efl_eina_mono_files = \
bindings/mono/eina_mono/eina_slice.cs \
bindings/mono/eina_mono/eina_stringshare.cs \
bindings/mono/eina_mono/eina_error.cs \
bindings/mono/eina_mono/eina_value.cs
bindings/mono/eina_mono/eina_value.cs \
bindings/mono/eina_mono/eina_strbuf.cs
efl_eldbus_mono_files = \
bindings/mono/eldbus_mono/eldbus_common.cs \
@ -437,6 +438,7 @@ tests_efl_mono_efl_mono_SOURCES = \
tests/efl_mono/Events.cs \
tests/efl_mono/FunctionPointers.cs \
tests/efl_mono/Parts.cs \
tests/efl_mono/Strbuf.cs \
tests/efl_mono/Strings.cs \
tests/efl_mono/Structs.cs \
tests/efl_mono/TestUtils.cs \

View File

@ -41,6 +41,7 @@ inline bool is_struct_blacklisted(std::string const& full_name)
{
return full_name == "Efl.Event.Description"
|| full_name == "Eina.Binbuf"
|| full_name == "Eina.Strbuf"
|| full_name == "Eina.Slice"
|| full_name == "Eina.Rw_Slice";
}

View File

@ -76,6 +76,12 @@ struct marshall_annotation_visitor_generate
{"any_value_ptr", false, [&] {
return " [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(eina.ValueMarshaler))]";
}},
{"strbuf", true, [&] {
return " [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(efl.eo.StrbufPassOwnershipMarshaler))]";
}},
{"strbuf", false, [&] {
return " [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(efl.eo.StrbufKeepOwnershipMarshaler))]";
}},
};
match const return_match_table[] =
{
@ -105,6 +111,12 @@ struct marshall_annotation_visitor_generate
{"any_value_ptr", false, [&] {
return " [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(eina.ValueMarshaler))]";
}},
{"strbuf", true, [&] {
return " [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(efl.eo.StrbufPassOwnershipMarshaler))]";
}},
{"strbuf", false, [&] {
return " [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(efl.eo.StrbufKeepOwnershipMarshaler))]";
}},
};
if(eina::optional<bool> b = call_annotation_match
@ -187,6 +199,12 @@ struct marshall_native_annotation_visitor_generate
return "";
return " [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(efl.eo.StringshareKeepOwnershipMarshaler))]";
}},
{"strbuf", true, [&] {
return " [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(efl.eo.StrbufPassOwnershipMarshaler))]";
}},
{"strbuf", false, [&] {
return " [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(efl.eo.StrbufKeepOwnershipMarshaler))]";
}},
};
match const return_match_table[] =
{
@ -200,6 +218,12 @@ struct marshall_native_annotation_visitor_generate
return " [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(efl.eo.StringsharePassOwnershipMarshaler))]";
}},
{"stringshare", false, [&] { return ""; }},
{"strbuf", true, [&] {
return " [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(efl.eo.StrbufPassOwnershipMarshaler))]";
}},
{"strbuf", false, [&] {
return " [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(efl.eo.StrbufKeepOwnershipMarshaler))]";
}},
};
if(eina::optional<bool> b = call_annotation_match

View File

@ -89,6 +89,12 @@ struct marshall_type_visitor_generate
else
return replace_base_type(r, " System.String");
}}
, {"strbuf", nullptr, [&]
{
regular_type_def r = regular;
r.base_qualifier.qualifier ^= qualifier_info::is_ref;
return replace_base_type(r, " eina.Strbuf");
}}
, {"Binbuf", true, [&]
{
regular_type_def r = regular;

View File

@ -342,7 +342,7 @@ struct to_external_field_convert_generator
else if (field.type.c_type == "Eina_Value *" || field.type.c_type == "const Eina_Value *")
{
if (!as_generator(
scope_tab << scope_tab << "_external_struct." << string << " = new eina.Value(_internal_struct." << string << ", eina.ValueOwnership.Unmanaged);\n"
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;
}

View File

@ -137,6 +137,10 @@ struct visitor_generate
r.base_qualifier.qualifier ^= qualifier_info::is_ref;
return replace_base_type(r, " System.String");
}}
, {"strbuf", nullptr, [&]
{
return regular_type_def{" eina.Strbuf", regular.base_qualifier, {}};
}}
, {"any_value", true, [&]
{ return regular_type_def{" eina.Value", regular.base_qualifier, {}};
}}

View File

@ -159,4 +159,12 @@ public struct Unicode {
}
/// <summary>Enum to handle resource ownership between managed and unmanaged code.</summary>
public enum Ownership {
/// <summary> The resource is owned by the managed code. It should free the handle on disposal.</summary>
Managed,
/// <summary> The resource is owned by the unmanaged code. It won't be freed on disposal.</summary>
Unmanaged
}
}

View File

@ -0,0 +1,156 @@
using System;
using System.Runtime.InteropServices;
using static eina.EinaNative.StrbufNativeMethods;
namespace eina
{
namespace EinaNative
{
static internal class StrbufNativeMethods
{
[DllImport(efl.Libs.Eina)]
internal static extern IntPtr eina_strbuf_new();
[DllImport(efl.Libs.Eina)]
internal static extern void eina_strbuf_free(IntPtr buf);
[DllImport(efl.Libs.Eina)]
internal static extern void eina_strbuf_reset(IntPtr buf);
[DllImport(efl.Libs.Eina)]
[return: MarshalAsAttribute(UnmanagedType.U1)]
internal static extern bool eina_strbuf_append(IntPtr buf, string str);
[DllImport(efl.Libs.Eina)]
[return: MarshalAsAttribute(UnmanagedType.U1)]
internal static extern bool eina_strbuf_append_escaped(IntPtr buf, string str);
[DllImport(efl.Libs.Eina)]
[return: MarshalAsAttribute(UnmanagedType.U1)]
internal static extern bool eina_strbuf_append_char(IntPtr buf, char c);
[DllImport(efl.Libs.Eina)]
internal static extern string eina_strbuf_string_steal(IntPtr buf);
[DllImport(efl.Libs.Eina)]
internal static extern IntPtr eina_strbuf_length_get(IntPtr buf); // Uses IntPtr as wrapper for size_t
}
} // namespace EinaNative
///<summary>Native string buffer, similar to the C# StringBuilder class.</summary>
public class Strbuf : IDisposable
{
///<summary>Pointer to the underlying native handle.</summary>
public IntPtr Handle { get; protected set; }
private Ownership Ownership;
private bool Disposed;
///<summary>Creates a new Strbuf. By default its lifetime is managed.</summary>
public Strbuf(Ownership ownership=Ownership.Managed)
{
this.Handle = eina_strbuf_new();
this.Ownership = ownership;
}
///<summary>Creates a new Strbuf from an existing IntPtr.</summary>
public Strbuf(IntPtr ptr, Ownership ownership)
{
this.Handle = ptr;
this.Ownership = ownership;
}
/// <summary>Releases the ownership of the underlying value to C.</summary>
public void ReleaseOwnership()
{
this.Ownership = Ownership.Unmanaged;
}
/// <summary>Takes the ownership of the underlying value to the Managed runtime.</summary>
public void TakeOwnership()
{
this.Ownership = Ownership.Managed;
}
///<summary>Public method to explicitly free the wrapped buffer.</summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
///<summary>Actually free the wrapped buffer. Can be called from Dispose() or through the GC.</summary>
protected virtual void Dispose(bool disposing)
{
if (this.Ownership == Ownership.Unmanaged)
{
Disposed = true;
return;
}
if (!Disposed && (Handle != IntPtr.Zero)) {
eina_strbuf_free(Handle);
}
Disposed = true;
}
///<summary>Finalizer to be called from the GC.</summary>
~Strbuf()
{
Dispose(false);
}
///<summary>Retrieves the length of the buffer contents.</summary>
public int Length
{
get
{
IntPtr size = eina_strbuf_length_get(Handle);
return size.ToInt32();
}
}
///<summary>Resets a string buffer. Its len is set to 0 and the content to '\\0'</summary>
public void Reset()
{
if (Disposed)
throw new ObjectDisposedException(base.GetType().Name);
eina_strbuf_reset(Handle);
}
///<summary>Appends a string to a buffer, reallocating as necessary.</summary>
public bool Append(string text)
{
if (Disposed)
throw new ObjectDisposedException(base.GetType().Name);
return eina_strbuf_append(Handle, text);
}
///<summary>Appens an escaped string to a buffer, reallocating as necessary.</summary>
public bool AppendEscaped(string text)
{
if (Disposed)
throw new ObjectDisposedException(base.GetType().Name);
return eina_strbuf_append_escaped(Handle, text);
}
///<summary>Appends a char to a buffer, reallocating as necessary.</summary>
public bool Append(char c)
{
if (Disposed)
throw new ObjectDisposedException(base.GetType().Name);
return eina_strbuf_append_char(Handle, c);
}
///<summary>Steals the content of a buffer.</summary>
public string Steal()
{
if (Disposed)
throw new ObjectDisposedException(base.GetType().Name);
return eina_strbuf_string_steal(Handle);
}
}
} // namespace eina

View File

@ -429,13 +429,6 @@ public class InvalidValueTypeException: Exception
protected InvalidValueTypeException(SerializationInfo info, StreamingContext context) : base(info, context) { }
}
/// <summary>Internal enum to handle value ownership between managed and unmanaged code.</summary>
public enum ValueOwnership {
/// <summary> The value is owned by the managed code. It'll free the handle on disposal.</summary>
Managed,
/// <summary> The value is owned by the unmanaged code. It won't be freed on disposal.</summary>
Unmanaged
}
/// <summary>Managed-side Enum to represent Eina_Value_Type constants</summary>
public enum ValueType {
@ -651,7 +644,7 @@ public class Value : IDisposable, IComparable<Value>, IEquatable<Value>
public IntPtr Handle { get; protected set;}
public ValueOwnership Ownership { get; protected set;}
public Ownership Ownership { get; protected set;}
private bool Disposed;
public bool Flushed { get; protected set;}
public bool Optional {
@ -680,10 +673,10 @@ public class Value : IDisposable, IComparable<Value>, IEquatable<Value>
// Constructor to be used by the "FromContainerDesc" methods.
private Value() {
this.Handle = MemoryNative.Alloc(eina_value_sizeof());
this.Ownership = ValueOwnership.Managed;
this.Ownership = Ownership.Managed;
}
public Value(IntPtr handle, ValueOwnership ownership=ValueOwnership.Managed) {
public Value(IntPtr handle, Ownership ownership=Ownership.Managed) {
this.Handle = handle;
this.Ownership = ownership;
}
@ -694,7 +687,7 @@ public class Value : IDisposable, IComparable<Value>, IEquatable<Value>
if (type.IsContainer())
throw new ArgumentException("To use container types you must provide a subtype");
this.Handle = MemoryNative.Alloc(eina_value_sizeof());
this.Ownership = ValueOwnership.Managed;
this.Ownership = Ownership.Managed;
Setup(type);
}
@ -705,7 +698,7 @@ public class Value : IDisposable, IComparable<Value>, IEquatable<Value>
throw new ArgumentException("First type must be a container type.");
this.Handle = MemoryNative.Alloc(eina_value_sizeof());
this.Ownership = ValueOwnership.Managed;
this.Ownership = Ownership.Managed;
Setup(containerType, subtype, step);
}
@ -720,7 +713,7 @@ public class Value : IDisposable, IComparable<Value>, IEquatable<Value>
MemoryNative.Free(this.Handle);
throw;
}
this.Ownership = ValueOwnership.Managed;
this.Ownership = Ownership.Managed;
}
/// <summary>Implicit conversion from managed value to native struct representation.</summary>
@ -758,13 +751,13 @@ public class Value : IDisposable, IComparable<Value>, IEquatable<Value>
/// <summary>Releases the ownership of the underlying value to C.</summary>
public void ReleaseOwnership()
{
this.Ownership = ValueOwnership.Unmanaged;
this.Ownership = Ownership.Unmanaged;
}
/// <summary>Takes the ownership of the underlying value to the Managed runtime.</summary>
public void TakeOwnership()
{
this.Ownership = ValueOwnership.Managed;
this.Ownership = Ownership.Managed;
}
/// <summary>Public method to explicitly free the wrapped eina value.</summary>
@ -777,7 +770,7 @@ public class Value : IDisposable, IComparable<Value>, IEquatable<Value>
/// <summary>Actually free the wrapped eina value. Can be called from Dispose() or through the GC.</summary>
protected virtual void Dispose(bool disposing)
{
if (this.Ownership == ValueOwnership.Unmanaged) {
if (this.Ownership == Ownership.Unmanaged) {
Disposed = true;
return;
}
@ -1516,7 +1509,7 @@ public class ValueMarshaler : ICustomMarshaler {
/// <summary>Creates a managed value from a C pointer, whitout taking ownership of it.</summary>
public object MarshalNativeToManaged(IntPtr pNativeData) {
return new Value(pNativeData, ValueOwnership.Unmanaged);
return new Value(pNativeData, Ownership.Unmanaged);
}
/// <summary>Retrieves the C pointer from a given managed value,
@ -1554,7 +1547,7 @@ public class ValueMarshaler : ICustomMarshaler {
public class ValueMarshalerOwn : ICustomMarshaler {
/// <summary>Creates a managed value from a C pointer, taking the ownership.</summary>
public object MarshalNativeToManaged(IntPtr pNativeData) {
return new Value(pNativeData, ValueOwnership.Managed);
return new Value(pNativeData, Ownership.Managed);
}
/// <summary>Retrieves the C pointer from a given managed value,

View File

@ -384,6 +384,69 @@ public class StringshareKeepOwnershipMarshaler : ICustomMarshaler {
static private StringshareKeepOwnershipMarshaler marshaler;
}
public 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;
}
public static ICustomMarshaler GetInstance(string cookie) {
if (marshaler == null) {
marshaler = new StrbufPassOwnershipMarshaler();
}
return marshaler;
}
static private StrbufPassOwnershipMarshaler marshaler;
}
public 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;
}
public static ICustomMarshaler GetInstance(string cookie) {
if (marshaler == null) {
marshaler = new StrbufKeepOwnershipMarshaler();
}
return marshaler;
}
static private StrbufKeepOwnershipMarshaler marshaler;
}
} // namespace eo
public class EflException : Exception

View File

@ -0,0 +1,59 @@
using System;
namespace TestSuite {
class TestStrBuf
{
public static void test_steal()
{
eina.Strbuf buf = new eina.Strbuf();
buf.Append("Here's");
buf.Append(' ');
buf.Append("Johnny!");
Test.AssertEquals("Here's Jonnny!".Length, buf.Length);
Test.AssertEquals("Here's Johnny!", buf.Steal());
}
public static void test_eolian()
{
test.Testing obj = new test.TestingConcrete();
eina.Strbuf buf = new eina.Strbuf();
obj.AppendToStrbuf(buf, "Appended");
obj.AppendToStrbuf(buf, " to buf");
Test.AssertEquals("Appended to buf", buf.Steal());
}
private class Appender : test.TestingInherit
{
public bool called;
public Appender() : base(null)
{
called = false;
}
public override void AppendToStrbuf(eina.Strbuf buf, string str)
{
eina.Log.Error("Virtual wrapper called");
called = true;
buf.Append(str);
}
}
public static void test_virtual_eolian()
{
Appender obj = new Appender();
eina.Strbuf buf = new eina.Strbuf();
obj.CallAppendToStrbuf(buf, "Is");
obj.CallAppendToStrbuf(buf, " this");
obj.CallAppendToStrbuf(buf, " virtual?");
Test.Assert(obj.called);
Test.AssertEquals("Is this virtual?", buf.Steal());
}
}
} // namespace TestSuite

View File

@ -16,10 +16,10 @@ public static class TestEinaValueEolian {
using (eina.Value v = new eina.Value(eina.ValueType.Int32)) {
v.Set(42);
obj.SetValuePtr(v);
Test.AssertEquals(eina.ValueOwnership.Managed, v.Ownership);
Test.AssertEquals(eina.Ownership.Managed, v.Ownership);
eina.Value v_received = obj.GetValuePtrOwn();
Test.AssertEquals(eina.ValueOwnership.Managed, v_received.Ownership);
Test.AssertEquals(eina.Ownership.Managed, v_received.Ownership);
Test.AssertEquals(v, v_received);
v_received.Dispose();
}
@ -31,13 +31,13 @@ public static class TestEinaValueEolian {
using (eina.Value v = new eina.Value(eina.ValueType.Int32)) {
v.Set(2001);
Test.AssertEquals(eina.ValueOwnership.Managed, v.Ownership);
Test.AssertEquals(eina.Ownership.Managed, v.Ownership);
obj.SetValuePtrOwn(v);
Test.AssertEquals(eina.ValueOwnership.Unmanaged, v.Ownership);
Test.AssertEquals(eina.Ownership.Unmanaged, v.Ownership);
eina.Value v_received = obj.GetValuePtr();
Test.AssertEquals(eina.ValueOwnership.Unmanaged, v_received.Ownership);
Test.AssertEquals(eina.Ownership.Unmanaged, v_received.Ownership);
Test.AssertEquals(v, v_received);
@ -57,7 +57,7 @@ public static class TestEinaValueEolian {
obj.OutValuePtr(out v_out);
Test.AssertEquals(v, v_out);
Test.AssertEquals(eina.ValueOwnership.Unmanaged, v_out.Ownership);
Test.AssertEquals(eina.Ownership.Unmanaged, v_out.Ownership);
}
}
@ -73,7 +73,7 @@ public static class TestEinaValueEolian {
obj.OutValuePtrOwn(out v_out);
Test.AssertEquals(v, v_out);
Test.AssertEquals(eina.ValueOwnership.Managed, v_out.Ownership);
Test.AssertEquals(eina.Ownership.Managed, v_out.Ownership);
}
}
@ -84,11 +84,11 @@ public static class TestEinaValueEolian {
using (eina.Value v = new eina.Value(eina.ValueType.Int32)) {
v.Set(42);
obj.SetValue(v);
Test.AssertEquals(eina.ValueOwnership.Managed, v.Ownership);
Test.AssertEquals(eina.Ownership.Managed, v.Ownership);
// Using get_value_ptr while get_value() is not supported.
eina.Value v_received = obj.GetValuePtrOwn();
Test.AssertEquals(eina.ValueOwnership.Managed, v_received.Ownership);
Test.AssertEquals(eina.Ownership.Managed, v_received.Ownership);
Test.AssertEquals(v, v_received);
v_received.Dispose();
}
@ -106,7 +106,7 @@ public static class TestEinaValueEolian {
obj.OutValue(out v_out);
Test.AssertEquals(v, v_out);
Test.AssertEquals(eina.ValueOwnership.Managed, v_out.Ownership);
Test.AssertEquals(eina.Ownership.Managed, v_out.Ownership);
}
}
}

View File

@ -3741,6 +3741,16 @@ Efl_Object *_test_testing_efl_part_part(const Eo *obj, Test_Testing_Data *pd, co
return NULL;
}
void _test_testing_append_to_strbuf(EINA_UNUSED Eo *obj, EINA_UNUSED Test_Testing_Data *pd, Eina_Strbuf *buf, const char *str)
{
eina_strbuf_append(buf, str);
}
void _test_testing_call_append_to_strbuf(Eo * obj, EINA_UNUSED Test_Testing_Data *pd, Eina_Strbuf *buf, const char *str)
{
test_testing_append_to_strbuf(obj, buf, str);
}
#include "test_testing.eo.c"
#include "test_numberwrapper.eo.c"

View File

@ -1548,6 +1548,21 @@ class Test.Testing (Efl.Object, Efl.Part) {
@in data: Test.Testing;
}
}
append_to_strbuf {
params {
@in buf: strbuf;
@in str: string;
}
}
call_append_to_strbuf {
params {
@in buf: strbuf;
@in str: string;
}
}
}
implements {
class.constructor;