summaryrefslogtreecommitdiff
path: root/src/bindings/mono/eina_mono/eina_stringshare.cs
blob: 76f218271924271a2f85aea2fc866e368af5f091 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
/*
 * Copyright 2019 by its authors. See AUTHORS.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#pragma warning disable 1591

using System;
using System.Runtime.InteropServices;
using System.ComponentModel;


namespace Eina
{

// TODO: move all native functions to a "NativeMethods" class
[EditorBrowsable(EditorBrowsableState.Never)]
static partial class NativeMethods
{
    [DllImport(efl.Libs.Eina)] internal static extern IntPtr
        eina_stringshare_add(IntPtr str);
    [DllImport(efl.Libs.Eina)] internal static extern System.IntPtr
        eina_stringshare_add_length(IntPtr str, UInt32 slen);
    [DllImport(efl.Libs.Eina)] internal static extern void
        eina_stringshare_del(IntPtr str);
    [DllImport(efl.Libs.CustomExports)] internal static extern void
        efl_mono_native_stringshare_del_ref(IntPtr str);
    [DllImport(efl.Libs.CustomExports)] internal 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.
///
/// <para>Since EFL 1.23.</para>
/// </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>
{
    /// <summary>
    /// 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.
    /// <para>Since EFL 1.23.</para>
    /// <see cref="Create(string)"/>
    /// <see cref="implicit operator Stringshare(string)"/>
    /// </summary>
    /// <param name="s">The string to be wrapped.</param>
    private Stringshare(string s)
    {
        Str = s;
    }

    /// <summary>
    /// Auto-implemented property that holds the wrapped string value.
    /// </summary>
    public string Str { get; private set; }

    /// <summary>
    /// 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.
    /// <para>Since EFL 1.23.</para>
    /// <seealso cref="implicit operator Stringshare(string)"/>
    /// </summary>
    /// <param name="s">The string to be wrapped.</param>
    /// <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);
    }

    /// <summary>
    /// Implicit convertion to string.
    /// </summary>
    public static implicit operator string(Stringshare ss)
    {
        if (ReferenceEquals(null, ss))
        {
            return null;
        }

        return ss.Str;
    }

    /// <summary>
    /// Implicit convertion from string to Stringshare.
    /// <para>Since EFL 1.23.</para>
    /// </summary>
    /// <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="Create(string)"/>
    /// </remarks>
    public static implicit operator Stringshare(string s)
    {
        if (ReferenceEquals(null, s))
        {
            return null;
        }

        return new Stringshare(s);
    }

    /// <summary>
    /// Check two Stringshare objects for equality.
    /// <para>Since EFL 1.23.</para>
    /// </summary>
    /// <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);
    }


    /// <summary>
    /// Check two Stringshare objects for inequality.
    /// <para>Since EFL 1.23.</para>
    /// </summary>
    /// <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);
    }

    /// <summary>
    /// Returns the wrapped string.
    /// <para>Since EFL 1.23.</para>
    /// <seealso cref="Str"/>
    /// <seealso cref="Get()"/>
    /// </summary>
    /// <returns>The wrapped string. Same as the property Str.</returns>
    public override string ToString()
    {
        return Str;
    }

    /// <summary>
    /// Override of GetHashCode for consistency with user-defined equality methods.
    /// <para>Since EFL 1.23.</para>
    /// </summary>
    /// <returns>
    /// The wrapped string hash code.
    /// </returns>
    public override int GetHashCode()
    {
        return Str.GetHashCode();
    }

    /// <summary>
    /// Check the given object for equality.
    /// <para>Since EFL 1.23.</para>
    /// </summary>
    /// <param name="other">The string to be compare to.</param>
    /// <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);
    }

    /// <summary>
    /// Check the given Stringshare for equality.
    /// <para>Since EFL 1.23.</para>
    /// </summary>
    /// <param name="other">The string share to compare to.</param>
    /// <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;
    }

    /// <summary>
    /// Check the given Stringshare for equality.
    /// <para>Since EFL 1.23.</para>
    /// </summary>
    /// <param name="other">The string to compare to.</param>
    /// <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;
    }

    /// <summary>
    /// Get the wrapped string.
    /// <para>Since EFL 1.23.</para>
    /// <seealso cref="Str"/>
    /// <seealso cref="ToString()"/>
    /// </summary>
    /// <returns>The wrapped string. Same as the property Str.</returns>
    public string Get()
    {
        return Str;
    }
}

}