forked from enlightenment/efl
efl_mono: Add support for Eina.Error/Empty in eina.Value
Summary: eina.Value.Empty now means that we have an zeroed (empty) eina value. For optional values that are empty use eina.Value.OptionalEmpty. This was required to support the empty values passed with EINA_VALUE_EMPTY in some Ecore futures. Also, returning an eina_value by value is not supported in eolian for safety reasons, so we removed some tests that tried to use this behavior. Depends on D6171 Reviewers: felipealmeida Reviewed By: felipealmeida Subscribers: cedric, zmike Tags: #efl Differential Revision: https://phab.enlightenment.org/D6172
This commit is contained in:
parent
2b8cbfe2f4
commit
f8a033fd70
|
@ -240,7 +240,7 @@ struct to_internal_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 << "_internal_struct." << string << " = _external_struct." << string << ".Handle;\n"
|
||||
scope_tab << scope_tab << "_internal_struct." << string << " = _external_struct." << string << ".NativeHandle;\n"
|
||||
).generate(sink, std::make_tuple(field_name, field_name), context))
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -22,6 +22,8 @@ internal static class NativeCustomExportFunctions
|
|||
efl_mono_native_free_ref(IntPtr ptr);
|
||||
[DllImport(efl.Libs.CustomExports)] public static extern IntPtr
|
||||
efl_mono_native_alloc(uint count);
|
||||
[DllImport(efl.Libs.CustomExports)] public static extern IntPtr
|
||||
efl_mono_native_memset(IntPtr ptr, uint fill, uint count);
|
||||
[DllImport(efl.Libs.CustomExports)] public static extern IntPtr
|
||||
efl_mono_native_alloc_copy(IntPtr val, uint size);
|
||||
[DllImport(efl.Libs.CustomExports)] public static extern IntPtr
|
||||
|
@ -56,6 +58,11 @@ public static class MemoryNative {
|
|||
return NativeCustomExportFunctions.efl_mono_native_alloc(Convert.ToUInt32(count));
|
||||
}
|
||||
|
||||
public static void Memset(IntPtr ptr, int fill, int count)
|
||||
{
|
||||
NativeCustomExportFunctions.efl_mono_native_memset(ptr, Convert.ToUInt32(fill), Convert.ToUInt32(count));
|
||||
}
|
||||
|
||||
public static IntPtr AllocCopy(IntPtr ptr, int count)
|
||||
{
|
||||
return NativeCustomExportFunctions.efl_mono_native_alloc_copy(ptr, Convert.ToUInt32(count));
|
||||
|
|
|
@ -325,7 +325,7 @@ static internal class UnsafeNativeMethods {
|
|||
[return: MarshalAsAttribute(UnmanagedType.U1)]
|
||||
internal static extern bool eina_value_pset_wrapper(IntPtr handle, ref eina.EinaNative.Value_List ptr);
|
||||
|
||||
[DllImport(efl.Libs.CustomExports)]
|
||||
[DllImport(efl.Libs.Eina)]
|
||||
[return: MarshalAsAttribute(UnmanagedType.U1)]
|
||||
internal static extern bool eina_value_copy(IntPtr src, IntPtr dest);
|
||||
|
||||
|
@ -379,6 +379,10 @@ static internal class UnsafeNativeMethods {
|
|||
// Optional
|
||||
[DllImport(efl.Libs.CustomExports)]
|
||||
internal static extern IntPtr type_optional();
|
||||
|
||||
// Error
|
||||
[DllImport(efl.Libs.CustomExports)]
|
||||
internal static extern IntPtr type_error();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -386,8 +390,8 @@ static internal class UnsafeNativeMethods {
|
|||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct Value_Native
|
||||
{
|
||||
IntPtr type;
|
||||
IntPtr value; // Atually an Eina_Value_Union, but it is padded to 8 bytes.
|
||||
public IntPtr Type;
|
||||
public IntPtr Value; // Atually an Eina_Value_Union, but it is padded to 8 bytes.
|
||||
}
|
||||
|
||||
|
||||
|
@ -470,6 +474,10 @@ public enum ValueType {
|
|||
Hash,
|
||||
/// <summary>Optional (aka empty) values.</summary>
|
||||
Optional,
|
||||
/// <summary>Error values.</summary>
|
||||
Error,
|
||||
/// <summary>Empty values.</summary>
|
||||
Empty,
|
||||
}
|
||||
|
||||
static class ValueTypeMethods {
|
||||
|
@ -521,6 +529,11 @@ static class ValueTypeMethods {
|
|||
return val == ValueType.Optional;
|
||||
}
|
||||
|
||||
public static bool IsError(this ValueType val)
|
||||
{
|
||||
return val == ValueType.Error;
|
||||
}
|
||||
|
||||
/// <summary>Returns the Marshal.SizeOf for the given ValueType native structure.</summary>
|
||||
public static int MarshalSizeOf(this ValueType val)
|
||||
{
|
||||
|
@ -608,6 +621,12 @@ static class ValueTypeBridge
|
|||
ManagedToNative.Add(ValueType.Optional, type_optional());
|
||||
NativeToManaged.Add(type_optional(), ValueType.Optional);
|
||||
|
||||
ManagedToNative.Add(ValueType.Error, type_error());
|
||||
NativeToManaged.Add(type_error(), ValueType.Error);
|
||||
|
||||
ManagedToNative.Add(ValueType.Empty, IntPtr.Zero);
|
||||
NativeToManaged.Add(IntPtr.Zero, ValueType.Empty);
|
||||
|
||||
TypesLoaded = true;
|
||||
}
|
||||
}
|
||||
|
@ -647,10 +666,13 @@ public class Value : IDisposable, IComparable<Value>, IEquatable<Value>
|
|||
// EINA_VALUE_TYPE_STRUCT: Eina_Value_Struct -- FIXME
|
||||
|
||||
|
||||
public IntPtr Handle { get; protected set;}
|
||||
internal IntPtr Handle { get; set;}
|
||||
/// <summary> Whether this wrapper owns (can free) the native value. </summary>
|
||||
public Ownership Ownership { get; protected set;}
|
||||
private bool Disposed;
|
||||
/// <summary> Whether this wrapper has already freed the native value. </summary>
|
||||
public bool Flushed { get; protected set;}
|
||||
/// <summary> Whether this is an Optional value (meaning it can have a value or not). </summary>
|
||||
public bool Optional {
|
||||
get {
|
||||
return GetValueType() == eina.ValueType.Optional;
|
||||
|
@ -663,7 +685,16 @@ public class Value : IDisposable, IComparable<Value>, IEquatable<Value>
|
|||
// }
|
||||
} */
|
||||
}
|
||||
/// <summary> Whether this wrapper is actually empty/uninitialized (zeroed). This is different from an empty optional value. </summary>
|
||||
public bool Empty {
|
||||
get {
|
||||
SanityChecks();
|
||||
return GetValueType() == eina.ValueType.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary> Whether this optional value is empty. </summary>
|
||||
public bool OptionalEmpty {
|
||||
get {
|
||||
OptionalSanityChecks();
|
||||
bool empty;
|
||||
|
@ -690,7 +721,14 @@ 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());
|
||||
if (this.Handle == IntPtr.Zero)
|
||||
throw new OutOfMemoryException("Failed to allocate memory for eina.Value");
|
||||
|
||||
// Initialize to EINA_VALUE_EMPTY before performing any other operation on this value.
|
||||
MemoryNative.Memset(this.Handle, 0, eina_value_sizeof());
|
||||
|
||||
this.Ownership = Ownership.Managed;
|
||||
Setup(type);
|
||||
}
|
||||
|
@ -710,12 +748,22 @@ public class Value : IDisposable, IComparable<Value>, IEquatable<Value>
|
|||
/// <summary>Constructor to build value from Values_Natives passed by value from C.</summary>
|
||||
public Value(Value_Native value)
|
||||
{
|
||||
this.Handle = MemoryNative.Alloc(Marshal.SizeOf(typeof(Value_Native)));
|
||||
IntPtr tmp = MemoryNative.Alloc(Marshal.SizeOf(typeof(Value_Native)));
|
||||
try {
|
||||
Marshal.StructureToPtr(value, tmp, false); // Can't get the address of a struct directly.
|
||||
if (!eina_value_copy(tmp, this.Handle))
|
||||
throw new System.InvalidOperationException("Failed to copy value to managed memory.");
|
||||
if (value.Type == IntPtr.Zero) // Got an EINA_VALUE_EMPTY by value.
|
||||
{
|
||||
this.Handle = tmp;
|
||||
tmp = IntPtr.Zero;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.Handle = MemoryNative.Alloc(Marshal.SizeOf(typeof(Value_Native)));
|
||||
|
||||
// Copy is used to deep copy the pointed payload (e.g. strings) inside this struct, so we can own this value.
|
||||
if (!eina_value_copy(tmp, this.Handle))
|
||||
throw new System.InvalidOperationException("Failed to copy value to managed memory.");
|
||||
}
|
||||
} catch {
|
||||
MemoryNative.Free(this.Handle);
|
||||
throw;
|
||||
|
@ -786,7 +834,7 @@ public class Value : IDisposable, IComparable<Value>, IEquatable<Value>
|
|||
}
|
||||
|
||||
if (!Disposed && (Handle != IntPtr.Zero)) {
|
||||
if (!Flushed)
|
||||
if (!Flushed && !Empty)
|
||||
eina_value_flush_wrapper(this.Handle);
|
||||
|
||||
MemoryNative.Free(this.Handle);
|
||||
|
@ -801,11 +849,12 @@ public class Value : IDisposable, IComparable<Value>, IEquatable<Value>
|
|||
}
|
||||
|
||||
/// <summary>Returns the native handle wrapped by this object.</summary>
|
||||
public IntPtr NativeHandle()
|
||||
{
|
||||
if (Disposed)
|
||||
throw new ObjectDisposedException(base.GetType().Name);
|
||||
return this.Handle;
|
||||
public IntPtr NativeHandle {
|
||||
get {
|
||||
if (Disposed)
|
||||
throw new ObjectDisposedException(base.GetType().Name);
|
||||
return this.Handle;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Converts this storage to type 'type'</summary>
|
||||
|
@ -814,6 +863,18 @@ public class Value : IDisposable, IComparable<Value>, IEquatable<Value>
|
|||
if (Disposed)
|
||||
throw new ObjectDisposedException(base.GetType().Name);
|
||||
|
||||
// Can't call setup with Empty value type (would give an eina error)
|
||||
if (type == eina.ValueType.Empty)
|
||||
{
|
||||
// Need to cleanup as it may point to payload outside the underlying Eina_Value (like arrays and strings).
|
||||
if (!Empty)
|
||||
eina_value_flush_wrapper(this.Handle);
|
||||
|
||||
MemoryNative.Memset(this.Handle, 0, eina_value_sizeof());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (type.IsContainer())
|
||||
throw new ArgumentException("To setup a container you must provide a subtype.");
|
||||
|
||||
|
@ -1075,6 +1136,21 @@ public class Value : IDisposable, IComparable<Value>, IEquatable<Value>
|
|||
return eina_value_set_wrapper_string(this.Handle, value);
|
||||
}
|
||||
|
||||
/// <summary>Stores the given error value.</summary>
|
||||
public bool Set(eina.Error value)
|
||||
{
|
||||
SanityChecks();
|
||||
|
||||
int error_code = value;
|
||||
|
||||
if (this.Optional)
|
||||
return eina_value_optional_pset(this.Handle,
|
||||
ValueTypeBridge.GetNative(ValueType.Error),
|
||||
ref error_code);
|
||||
|
||||
return eina_value_set_wrapper_int(this.Handle, error_code);
|
||||
}
|
||||
|
||||
/// <summary>Stores the given value into this value. The target value must be an optional.</summary>
|
||||
public bool Set(Value value)
|
||||
{
|
||||
|
@ -1228,6 +1304,22 @@ public class Value : IDisposable, IComparable<Value>, IEquatable<Value>
|
|||
return true;
|
||||
}
|
||||
|
||||
/// <summary>Gets the currently stored value as an eina.Error.</summary>
|
||||
public bool Get(out eina.Error value)
|
||||
{
|
||||
SanityChecks();
|
||||
bool ret;
|
||||
int intermediate; // It seems out doesn't play well with implicit operators...
|
||||
if (this.Optional)
|
||||
ret = eina_value_optional_pget(this.Handle, out intermediate);
|
||||
else
|
||||
ret = eina_value_get_wrapper(this.Handle, out intermediate);
|
||||
|
||||
value = intermediate;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// <summary>Gets the currently stored value as an complex (e.g. container) eina.Value.</summary>
|
||||
public bool Get(out Value value)
|
||||
{
|
||||
|
|
|
@ -27,6 +27,11 @@ EAPI void *efl_mono_native_alloc(unsigned int size)
|
|||
return malloc(size);
|
||||
}
|
||||
|
||||
EAPI void efl_mono_native_memset(void *ptr, unsigned int fill, unsigned int count)
|
||||
{
|
||||
memset(ptr, fill, count);
|
||||
}
|
||||
|
||||
EAPI void efl_mono_native_free(void *ptr)
|
||||
{
|
||||
free(ptr);
|
||||
|
@ -313,6 +318,9 @@ EAPI const Eina_Value_Type *type_array() {
|
|||
EAPI const Eina_Value_Type *type_list() {
|
||||
return EINA_VALUE_TYPE_LIST;
|
||||
}
|
||||
EAPI const Eina_Value_Type *type_error() {
|
||||
return EINA_VALUE_TYPE_ERROR;
|
||||
}
|
||||
|
||||
EAPI const Eina_Value_Type *type_optional() {
|
||||
return EINA_VALUE_TYPE_OPTIONAL;
|
||||
|
@ -354,6 +362,11 @@ EAPI void eina_value_flush_wrapper(Eina_Value *value)
|
|||
|
||||
EAPI const Eina_Value_Type *eina_value_type_get_wrapper(const Eina_Value *value)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(value, NULL);
|
||||
|
||||
// Can't pass null value type (for Empty values) to value_type_get.
|
||||
if (value->type == NULL)
|
||||
return NULL;
|
||||
return eina_value_type_get(value);
|
||||
}
|
||||
|
||||
|
|
|
@ -135,6 +135,17 @@ public static class TestEinaValue {
|
|||
}
|
||||
}
|
||||
|
||||
public static void TestErrorSimple()
|
||||
{
|
||||
using (eina.Value v = new eina.Value(eina.ValueType.Error)) {
|
||||
eina.Error error = new eina.Error(eina.Error.NO_ERROR);
|
||||
Test.Assert(v.Set(error));
|
||||
eina.Error x;
|
||||
Test.Assert(v.Get(out x));
|
||||
Test.AssertEquals(error, x);
|
||||
}
|
||||
}
|
||||
|
||||
public static void TestSetWrongType()
|
||||
{
|
||||
using (eina.Value v = new eina.Value(eina.ValueType.String)) {
|
||||
|
@ -209,20 +220,20 @@ public static class TestEinaValue {
|
|||
{
|
||||
using (eina.Value a = new eina.Value(eina.ValueType.Optional)) {
|
||||
Test.Assert(a.Optional);
|
||||
Test.Assert(a.Empty); // By default, optional values are empty
|
||||
Test.Assert(a.OptionalEmpty); // By default, optional values are empty
|
||||
|
||||
// Sets expectation
|
||||
int expected = 1984;
|
||||
Test.Assert(a.Set(expected));
|
||||
Test.Assert(a.Optional);
|
||||
Test.Assert(!a.Empty);
|
||||
Test.Assert(!a.OptionalEmpty);
|
||||
|
||||
Test.Assert(a.Reset());
|
||||
Test.Assert(a.Empty);
|
||||
Test.Assert(a.OptionalEmpty);
|
||||
|
||||
expected = -4891;
|
||||
Test.Assert(a.Set(expected)); // Set() automatically infers the subtype from the argument.
|
||||
Test.Assert(!a.Empty);
|
||||
Test.Assert(!a.OptionalEmpty);
|
||||
|
||||
int actual = 0;
|
||||
Test.Assert(a.Get(out actual));
|
||||
|
@ -233,20 +244,20 @@ public static class TestEinaValue {
|
|||
{
|
||||
using (eina.Value a = new eina.Value(eina.ValueType.Optional)) {
|
||||
Test.Assert(a.Optional);
|
||||
Test.Assert(a.Empty); // By default, optional values are empty
|
||||
Test.Assert(a.OptionalEmpty); // By default, optional values are empty
|
||||
|
||||
// Sets expectation
|
||||
uint expected = 1984;
|
||||
Test.Assert(a.Set(expected));
|
||||
Test.Assert(a.Optional);
|
||||
Test.Assert(!a.Empty);
|
||||
Test.Assert(!a.OptionalEmpty);
|
||||
|
||||
Test.Assert(a.Reset());
|
||||
Test.Assert(a.Empty);
|
||||
Test.Assert(a.OptionalEmpty);
|
||||
|
||||
expected = 0xdeadbeef;
|
||||
Test.Assert(a.Set(expected));
|
||||
Test.Assert(!a.Empty);
|
||||
Test.Assert(!a.OptionalEmpty);
|
||||
|
||||
uint actual = 0;
|
||||
Test.Assert(a.Get(out actual));
|
||||
|
@ -257,26 +268,26 @@ public static class TestEinaValue {
|
|||
{
|
||||
using (eina.Value a = new eina.Value(eina.ValueType.Int32)) {
|
||||
Test.Assert(!a.Optional);
|
||||
BoolRet dummy = () => a.Empty;
|
||||
BoolRet dummy = () => a.OptionalEmpty;
|
||||
Test.AssertRaises<eina.InvalidValueTypeException>(() => dummy());
|
||||
}
|
||||
|
||||
using (eina.Value a = new eina.Value(eina.ValueType.Optional)) {
|
||||
Test.Assert(a.Optional);
|
||||
Test.Assert(a.Empty); // By default, optional values are empty
|
||||
Test.Assert(a.OptionalEmpty); // By default, optional values are empty
|
||||
|
||||
// Sets expectation
|
||||
string expected = "Hello, world!";
|
||||
Test.Assert(a.Set(expected));
|
||||
Test.Assert(a.Optional);
|
||||
Test.Assert(!a.Empty);
|
||||
Test.Assert(!a.OptionalEmpty);
|
||||
|
||||
Test.Assert(a.Reset());
|
||||
Test.Assert(a.Empty);
|
||||
Test.Assert(a.OptionalEmpty);
|
||||
|
||||
expected = "!dlrow olleH";
|
||||
Test.Assert(a.Set(expected));
|
||||
Test.Assert(!a.Empty);
|
||||
Test.Assert(!a.OptionalEmpty);
|
||||
|
||||
string actual = String.Empty;
|
||||
Test.Assert(a.Get(out actual));
|
||||
|
@ -291,7 +302,7 @@ public static class TestEinaValue {
|
|||
{
|
||||
|
||||
Test.Assert(a.Optional);
|
||||
Test.Assert(a.Empty); // By default, optional values are empty
|
||||
Test.Assert(a.OptionalEmpty); // By default, optional values are empty
|
||||
|
||||
// Sets expectation
|
||||
Test.Assert(expected.Append(-1));
|
||||
|
@ -300,14 +311,14 @@ public static class TestEinaValue {
|
|||
|
||||
Test.Assert(a.Set(expected));
|
||||
Test.Assert(a.Optional);
|
||||
Test.Assert(!a.Empty);
|
||||
Test.Assert(!a.OptionalEmpty);
|
||||
|
||||
Test.Assert(a.Reset());
|
||||
Test.Assert(a.Empty);
|
||||
Test.Assert(a.OptionalEmpty);
|
||||
|
||||
expected.Append(-42);
|
||||
Test.Assert(a.Set(expected));
|
||||
Test.Assert(!a.Empty);
|
||||
Test.Assert(!a.OptionalEmpty);
|
||||
|
||||
eina.Value actual = null;
|
||||
Test.Assert(a.Get(out actual));
|
||||
|
@ -325,7 +336,7 @@ public static class TestEinaValue {
|
|||
{
|
||||
|
||||
Test.Assert(a.Optional);
|
||||
Test.Assert(a.Empty); // By default, optional values are empty
|
||||
Test.Assert(a.OptionalEmpty); // By default, optional values are empty
|
||||
|
||||
// Sets expectation
|
||||
Test.Assert(expected.Append(-1));
|
||||
|
@ -334,14 +345,14 @@ public static class TestEinaValue {
|
|||
|
||||
Test.Assert(a.Set(expected));
|
||||
Test.Assert(a.Optional);
|
||||
Test.Assert(!a.Empty);
|
||||
Test.Assert(!a.OptionalEmpty);
|
||||
|
||||
Test.Assert(a.Reset());
|
||||
Test.Assert(a.Empty);
|
||||
Test.Assert(a.OptionalEmpty);
|
||||
|
||||
expected.Append(-42);
|
||||
Test.Assert(a.Set(expected));
|
||||
Test.Assert(!a.Empty);
|
||||
Test.Assert(!a.OptionalEmpty);
|
||||
|
||||
eina.Value actual = null;
|
||||
Test.Assert(a.Get(out actual));
|
||||
|
@ -807,9 +818,23 @@ public static class TestEinaValue {
|
|||
value_ptr.Set(payload);
|
||||
eina.Value_Native byvalue = value_ptr;
|
||||
eina.Value another_value_ptr = byvalue;
|
||||
Test.AssertEquals(value_ptr, another_value_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
public static void TestValueEmpty() {
|
||||
using (eina.Value empty = new eina.Value(eina.ValueType.Empty)) {
|
||||
Test.Assert(empty.Empty, "Value must be empty");
|
||||
|
||||
empty.Setup(eina.ValueType.Int32);
|
||||
|
||||
// Values already set-up are not empty. For this kind of empty, use Optional
|
||||
Test.Assert(!empty.Empty, "Values already set-up must not be empty.");
|
||||
|
||||
empty.Set(42);
|
||||
Test.Assert(!empty.Empty, "Values with payload must not be empty.");
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME Add remaining list tests
|
||||
|
||||
|
|
|
@ -77,23 +77,6 @@ public static class TestEinaValueEolian {
|
|||
}
|
||||
}
|
||||
|
||||
public static void TestEolianEinaValueInReturnByValue()
|
||||
{
|
||||
test.ITesting obj = new test.Testing();
|
||||
|
||||
using (eina.Value v = new eina.Value(eina.ValueType.Int32)) {
|
||||
v.Set(42);
|
||||
obj.SetValue(v);
|
||||
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.Ownership.Managed, v_received.Ownership);
|
||||
Test.AssertEquals(v, v_received);
|
||||
v_received.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
public static void TestEolianEinaValueOutByValue()
|
||||
{
|
||||
test.ITesting obj = new test.Testing();
|
||||
|
|
|
@ -3680,14 +3680,6 @@ Eina_Value *_test_testing_get_value_ptr(EINA_UNUSED Eo *obj, Test_Testing_Data *
|
|||
return pd->stored_value;
|
||||
}
|
||||
|
||||
/* Currently the Eolian declaration FUNC_BODY in the .eo.c file seems to be broken for
|
||||
* generic value.
|
||||
*/
|
||||
/* Eina_Value _test_testing_get_value(EINA_UNUSED Eo *obj, Test_Testing_Data *pd)
|
||||
{
|
||||
return *pd->stored_value;
|
||||
}*/
|
||||
|
||||
void _test_testing_clear_value(EINA_UNUSED Eo *obj, Test_Testing_Data *pd)
|
||||
{
|
||||
if (pd->stored_value) {
|
||||
|
|
Loading…
Reference in New Issue