1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3 * Copyright (C) 2016 Red Hat, Inc. (www.redhat.com)
4 *
5 * This library is free software: you can redistribute it and/or modify it
6 * under the terms of the GNU Lesser General Public License as published by
7 * the Free Software Foundation.
8 *
9 * This library is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
12 * for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public License
15 * along with this library. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 #include "evolution-data-server-config.h"
19
20 #include <stdio.h>
21 #include <string.h>
22
23 #include "camel-named-flags.h"
24
G_DEFINE_BOXED_TYPE(CamelNamedFlags,camel_named_flags,camel_named_flags_copy,camel_named_flags_free)25 G_DEFINE_BOXED_TYPE (CamelNamedFlags,
26 camel_named_flags,
27 camel_named_flags_copy,
28 camel_named_flags_free)
29
30 /**
31 * camel_named_flags_new:
32 *
33 * Creates a new #CamelNamedFlags.
34 *
35 * Returns: (transfer full): A newly allocated #CamelNamedFlags.
36 * Free it with camel_named_flags_free() when done with it.
37 *
38 * Since: 3.24
39 **/
40 CamelNamedFlags *
41 camel_named_flags_new (void)
42 {
43 return (CamelNamedFlags *) g_ptr_array_new_with_free_func (g_free);
44 }
45
46 /**
47 * camel_named_flags_new_sized:
48 * @reserve_size: an array size to reserve
49 *
50 * Created a new #CamelNamedFlags, which has reserved @reserve_size
51 * elements. This value doesn't influence the camel_named_flags_get_length(),
52 * which returns zero on the array returned from this function.
53 *
54 * Returns: (transfer full): A newly allocated #CamelNameValueArray.
55 * Free it with camel_named_flags_free() when done with it.
56 *
57 * See: camel_name_value_array_new, camel_name_value_array_copy
58 *
59 * Since: 3.24
60 **/
61 CamelNamedFlags *
camel_named_flags_new_sized(guint reserve_size)62 camel_named_flags_new_sized (guint reserve_size)
63 {
64 return (CamelNamedFlags *) g_ptr_array_new_full (reserve_size, g_free);
65 }
66
67 /**
68 * camel_named_flags_copy:
69 * @named_flags: (nullable): a #CamelNamedFlags
70 *
71 * Creates a copy of the @named_flags and returns it.
72 *
73 * Returns: (transfer full): A newly allocated #CamelNamedFlags.
74 * Free it with camel_named_flags_free() when done with it.
75 *
76 * Since: 3.24
77 **/
78 CamelNamedFlags *
camel_named_flags_copy(const CamelNamedFlags * named_flags)79 camel_named_flags_copy (const CamelNamedFlags *named_flags)
80 {
81 const GPtrArray *src = (const GPtrArray *) named_flags;
82 GPtrArray *arr;
83 guint ii;
84
85 if (!src)
86 return NULL;
87
88 arr = (GPtrArray *) camel_named_flags_new_sized (src->len);
89 for (ii = 0; ii < src->len; ii++) {
90 const gchar *name = g_ptr_array_index (src, ii);
91
92 if (name && *name)
93 g_ptr_array_add (arr, g_strdup (name));
94 }
95
96 return (CamelNamedFlags *) arr;
97 }
98
99 /**
100 * camel_named_flags_free:
101 * @named_flags: (nullable): a #CamelNamedFlags, or %NULL
102 *
103 * Frees memory associated iwth the @named_flags. Does nothing,
104 * if @named_flags is %NULL.
105 *
106 * Since: 3.24
107 **/
108 void
camel_named_flags_free(CamelNamedFlags * named_flags)109 camel_named_flags_free (CamelNamedFlags *named_flags)
110 {
111 if (named_flags)
112 g_ptr_array_unref ((GPtrArray *) named_flags);
113 }
114
115 static guint
camel_named_flags_find(const CamelNamedFlags * named_flags,const gchar * name)116 camel_named_flags_find (const CamelNamedFlags *named_flags,
117 const gchar *name)
118 {
119 GPtrArray *arr = (GPtrArray *) named_flags;
120 guint ii;
121
122 g_return_val_if_fail (named_flags != NULL, (guint) -1);
123 g_return_val_if_fail (name != NULL, (guint) -1);
124
125 for (ii = 0; ii < arr->len; ii++) {
126 const gchar *nm = g_ptr_array_index (arr, ii);
127
128 if (g_strcmp0 (nm, name) == 0)
129 return ii;
130 }
131
132 return (guint) -1;
133 }
134
135 /**
136 * camel_named_flags_insert:
137 * @named_flags: a #CamelNamedFlags
138 * @name: name of the flag
139 *
140 * Inserts a flag named @name into the @named_flags, if it is not included
141 * already (comparing case sensitively), or does nothing otherwise.
142 *
143 * Returns: %TRUE the flag named @name was inserted; %FALSE otherwise.
144 *
145 * Since: 3.24
146 **/
147 gboolean
camel_named_flags_insert(CamelNamedFlags * named_flags,const gchar * name)148 camel_named_flags_insert (CamelNamedFlags *named_flags,
149 const gchar *name)
150 {
151 GPtrArray *arr = (GPtrArray *) named_flags;
152 guint index;
153
154 g_return_val_if_fail (named_flags != NULL, FALSE);
155 g_return_val_if_fail (name != NULL, FALSE);
156
157 index = camel_named_flags_find (named_flags, name);
158
159 /* already there */
160 if (index != (guint) -1)
161 return FALSE;
162
163 g_ptr_array_add (arr, g_strdup (name));
164
165 return TRUE;
166 }
167
168 /**
169 * camel_named_flags_remove:
170 * @named_flags: a #CamelNamedFlags
171 * @name: name of the flag
172 *
173 * Removes a flag named @name from the @named_flags.
174 *
175 * Returns: %TRUE when the @named_flags contained a flag named @name,
176 * comparing case sensitively, and it was removed; %FALSE otherwise.
177 *
178 * Since: 3.24
179 **/
180 gboolean
camel_named_flags_remove(CamelNamedFlags * named_flags,const gchar * name)181 camel_named_flags_remove (CamelNamedFlags *named_flags,
182 const gchar *name)
183 {
184 GPtrArray *arr = (GPtrArray *) named_flags;
185 guint index;
186
187 g_return_val_if_fail (named_flags != NULL, FALSE);
188 g_return_val_if_fail (name != NULL, FALSE);
189
190 index = camel_named_flags_find (named_flags, name);
191
192 /* not there */
193 if (index == (guint) -1)
194 return FALSE;
195
196 g_ptr_array_remove_index (arr, index);
197
198 return TRUE;
199 }
200
201 /**
202 * camel_named_flags_contains:
203 * @named_flags: a #CamelNamedFlags
204 * @name: name of the flag
205 *
206 * Returns: Whether the @named_flags contains a flag named @name,
207 * comparing case sensitively.
208 *
209 * Since: 3.24
210 **/
211 gboolean
camel_named_flags_contains(const CamelNamedFlags * named_flags,const gchar * name)212 camel_named_flags_contains (const CamelNamedFlags *named_flags,
213 const gchar *name)
214 {
215 g_return_val_if_fail (named_flags != NULL, FALSE);
216 g_return_val_if_fail (name != NULL, FALSE);
217
218 return camel_named_flags_find (named_flags, name) != (guint) -1;
219 }
220
221 /**
222 * camel_named_flags_clear:
223 * @named_flags: a #CamelNamedFlags
224 *
225 * Removes all the elements of the array.
226 *
227 * Since: 3.24
228 **/
229 void
camel_named_flags_clear(CamelNamedFlags * named_flags)230 camel_named_flags_clear (CamelNamedFlags *named_flags)
231 {
232 GPtrArray *arr = (GPtrArray *) named_flags;
233
234 g_return_if_fail (named_flags != NULL);
235
236 if (arr->len)
237 g_ptr_array_remove_range (arr, 0, arr->len);
238 }
239
240 /**
241 * camel_named_flags_get_length:
242 * @named_flags: (nullable): a #CamelNamedFlags
243 *
244 * Returns: Length of the array, aka how many named flags are stored there.
245 *
246 * Since: 3.24
247 **/
248 guint
camel_named_flags_get_length(const CamelNamedFlags * named_flags)249 camel_named_flags_get_length (const CamelNamedFlags *named_flags)
250 {
251 const GPtrArray *arr = (const GPtrArray *) named_flags;
252
253 if (!named_flags)
254 return 0;
255
256 return arr->len;
257 }
258
259 /**
260 * camel_named_flags_get:
261 * @named_flags: a #CamelNamedFlags
262 * @index: an index of an element
263 *
264 * Returns: (transfer none) (nullable): Name of the flag in at the given @index,
265 * or %NULL on error.
266 *
267 * Since: 3.24
268 **/
269 const gchar *
camel_named_flags_get(const CamelNamedFlags * named_flags,guint index)270 camel_named_flags_get (const CamelNamedFlags *named_flags,
271 guint index)
272 {
273 const GPtrArray *arr = (const GPtrArray *) named_flags;
274
275 g_return_val_if_fail (named_flags != NULL, NULL);
276
277 if (index >= camel_named_flags_get_length (named_flags))
278 return NULL;
279
280 return g_ptr_array_index (arr, index);
281 }
282
283 /**
284 * camel_named_flags_equal:
285 * @named_flags_a: (nullable): the first #CamelNamedFlags
286 * @named_flags_b: (nullable): the second #CamelNamedFlags
287 *
288 * Compares content of the two #CamelNamedFlags and returns whether
289 * they equal. Note this is an expensive operation for large sets.
290 *
291 * Returns: Whether the two #CamelNamedFlags have the same content.
292 *
293 * Since: 3.24
294 **/
295 gboolean
camel_named_flags_equal(const CamelNamedFlags * named_flags_a,const CamelNamedFlags * named_flags_b)296 camel_named_flags_equal (const CamelNamedFlags *named_flags_a,
297 const CamelNamedFlags *named_flags_b)
298 {
299 guint ii, len;
300
301 if (named_flags_a == named_flags_b)
302 return TRUE;
303
304 if (!named_flags_a || !named_flags_b)
305 return camel_named_flags_get_length (named_flags_a) == camel_named_flags_get_length (named_flags_b);
306
307 len = camel_named_flags_get_length (named_flags_a);
308 if (len != camel_named_flags_get_length (named_flags_b))
309 return FALSE;
310
311 for (ii = 0; ii < len; ii++) {
312 if (!camel_named_flags_contains (named_flags_a, camel_named_flags_get (named_flags_b, ii)))
313 return FALSE;
314 }
315
316 return TRUE;
317 }
318