Line data Source code
1 : #include "gelektra-key.h"
2 : #include <kdbprivate.h>
3 : #include <string.h>
4 :
5 : enum
6 : {
7 : PROP_0,
8 : PROP_KEY_NAME, ///< property to get the name of the key
9 : PROP_KEY_BASENAME,
10 : PROP_KEY_FULLNAME,
11 : N_PROPERTIES
12 : };
13 :
14 145 : G_DEFINE_TYPE (GElektraKey, gelektra_key, G_TYPE_OBJECT)
15 : static Key * gelektra_key_swap (GElektraKey * key, Key * newkey);
16 :
17 68 : static void gelektra_key_init (GElektraKey * self)
18 : {
19 : /* initialize the object */
20 68 : self->key = keyNew (NULL);
21 68 : keyIncRef (self->key);
22 68 : }
23 :
24 0 : static void gelektra_key_set_property (GObject * object, guint property_id, const GValue * value ELEKTRA_UNUSED, GParamSpec * pspec)
25 : {
26 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
27 0 : }
28 :
29 6 : static void gelektra_key_get_property (GObject * object, guint property_id, GValue * value, GParamSpec * pspec)
30 : {
31 6 : GElektraKey * self = GELEKTRA_KEY (object);
32 :
33 6 : switch (property_id)
34 : {
35 : case PROP_KEY_NAME:
36 4 : g_value_set_string (value, keyName (self->key));
37 4 : break;
38 : case PROP_KEY_BASENAME:
39 1 : g_value_set_string (value, keyBaseName (self->key));
40 1 : break;
41 : case PROP_KEY_FULLNAME:
42 : {
43 1 : gssize size = keyGetFullNameSize (self->key);
44 1 : if (size == 0)
45 0 : g_value_set_static_string (value, "");
46 1 : else if (size > 0)
47 : {
48 1 : gchar * val = g_malloc0 (size);
49 1 : keyGetFullName (self->key, &val[0], size);
50 1 : g_value_take_string (value, val);
51 : }
52 : else
53 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
54 : }
55 : break;
56 : default:
57 : /* We don't have any other property... */
58 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
59 0 : break;
60 : }
61 6 : }
62 :
63 68 : static void gelektra_key_finalize (GObject * object)
64 : {
65 68 : GElektraKey * self = GELEKTRA_KEY (object);
66 :
67 68 : keyDecRef (self->key);
68 68 : keyDel (self->key);
69 :
70 : /* Always chain up to the parent class; as with dispose(), finalize()
71 : * is guaranteed to exist on the parent's class virtual function table
72 : */
73 68 : G_OBJECT_CLASS (gelektra_key_parent_class)->finalize (object);
74 68 : }
75 :
76 : static GParamSpec * obj_properties[N_PROPERTIES] = {
77 : NULL,
78 : };
79 :
80 3 : static void gelektra_key_class_init (GElektraKeyClass * klass)
81 : {
82 3 : GObjectClass * gobject_class = G_OBJECT_CLASS (klass);
83 :
84 3 : gobject_class->set_property = gelektra_key_set_property;
85 3 : gobject_class->get_property = gelektra_key_get_property;
86 3 : gobject_class->finalize = gelektra_key_finalize;
87 :
88 3 : obj_properties[PROP_KEY_NAME] = g_param_spec_string ("name", "Keyname", "The name of the key", NULL, G_PARAM_READWRITE);
89 :
90 3 : obj_properties[PROP_KEY_BASENAME] =
91 3 : g_param_spec_string ("basename", "Basename", "The basename of the key", NULL, G_PARAM_READWRITE);
92 :
93 3 : obj_properties[PROP_KEY_FULLNAME] =
94 3 : g_param_spec_string ("fullname", "Fullname", "Get key full name, including the user domain name", NULL, G_PARAM_READABLE);
95 :
96 3 : g_object_class_install_properties (gobject_class, N_PROPERTIES, obj_properties);
97 3 : }
98 :
99 :
100 : /*
101 : * Methods
102 : */
103 :
104 : /* constructor */
105 : /**
106 : * gelektra_key_new: (skip)
107 : * @name valid name of a key or NULL
108 : * @... optional parameters closed by GELEKTRA_KEY_END, see keyNew
109 : *
110 : * Returns: A new #GElektraKey
111 : * see keyNew
112 : */
113 65 : GElektraKey * gelektra_key_new (const gchar * name, ...)
114 : {
115 : va_list va;
116 :
117 65 : GElektraKey * key = g_object_new (GELEKTRA_TYPE_KEY, NULL);
118 65 : if (name)
119 : {
120 24 : va_start (va, name);
121 24 : keyVInit (key->key, name, va);
122 24 : keyIncRef (key->key); // keyVInit cleared the refcount
123 24 : va_end (va);
124 : }
125 65 : return key;
126 : }
127 :
128 : /**
129 : * gelektra_key_make: (skip)
130 : * @key: The underlying key
131 : *
132 : * Returns: (transfer full): A new #GElektraKey holding the ownership of @key
133 : */
134 41 : GElektraKey * gelektra_key_make (Key * key)
135 : {
136 41 : if (key == NULL) return NULL;
137 38 : GElektraKey * ret = gelektra_key_new (NULL);
138 38 : Key * old = gelektra_key_swap (ret, key);
139 38 : keyDel (old);
140 38 : return ret;
141 : }
142 :
143 : /**
144 : * gelektra_key_gi_make: (constructor)
145 : * @key: A #GElektraKey
146 : *
147 : * Returns: (transfer full): A new #GElektraKey holding the ownership of @key
148 : *
149 : * \note This is for GObject Introspection.
150 : * \note Do NOT use! Use gelektra_key_make instead
151 : */
152 0 : GElektraKey * gelektra_key_gi_make (GElektraKey * key)
153 : {
154 0 : return (key != NULL) ? gelektra_key_make (key->key) : NULL;
155 : }
156 :
157 : /* initialization */
158 0 : static void gelektra_key_gi_init_va (GElektraKey * key, const gchar * name, ...)
159 : {
160 0 : if (!name) return;
161 : va_list va;
162 0 : va_start (va, name);
163 0 : keyVInit (key->key, name, va);
164 0 : keyIncRef (key->key); // keyVInit cleared the refcount
165 0 : va_end (va);
166 : }
167 :
168 : /**
169 : * gelektra_key_gi_init
170 : * @name valid name of a key or NULL
171 : * @flags see usage of KEY_FLAGS in keyNew
172 : * @value: (nullable): key value
173 : * @data: (array length=data_size zero-terminated=0) (element-type guint8) (nullable): binary key value
174 : * @data_size: size of the input data
175 : *
176 : * \note This is for GObject Introspection.
177 : * \note Do NOT use! Use gelektra_key_new instead
178 : */
179 0 : void gelektra_key_gi_init (GElektraKey * key, const gchar * name, int flags, const gchar * value, const void * data, gsize data_size)
180 : {
181 0 : gelektra_key_gi_init_va (key, name, KEY_FLAGS, flags, KEY_SIZE, (flags & KEY_BINARY) ? data_size : 0, KEY_VALUE,
182 0 : (flags & KEY_BINARY) ? data : value, KEY_END);
183 0 : }
184 :
185 : /* reference handling */
186 1 : gssize gelektra_key_incref (GElektraKey * key)
187 : {
188 1 : return keyIncRef (key->key);
189 : }
190 :
191 1 : gssize gelektra_key_decref (GElektraKey * key)
192 : {
193 1 : return keyDecRef (key->key);
194 : }
195 :
196 13 : gssize gelektra_key_getref (const GElektraKey * key)
197 : {
198 13 : return keyGetRef (key->key);
199 : }
200 :
201 : /* basic methods */
202 : /**
203 : * gelektra_key_dup:
204 : * @key: A #GElektraKey
205 : *
206 : * Returns: (transfer full): A duplicated #GElektraKey
207 : * see keyDup
208 : */
209 2 : GElektraKey * gelektra_key_dup (const GElektraKey * key)
210 : {
211 2 : return gelektra_key_make (keyDup (key->key));
212 : }
213 :
214 : /**
215 : * gelektra_key_copy: (skip)
216 : * see keyCopy
217 : */
218 1 : gint gelektra_key_copy (const GElektraKey * key, GElektraKey * dest)
219 : {
220 1 : return keyCopy (dest->key, key->key);
221 : }
222 :
223 1 : gint gelektra_key_clear (GElektraKey * key)
224 : {
225 1 : return keyClear (key->key);
226 : }
227 :
228 : /**
229 : * gelektra_key_swap: (skip)
230 : * @key: A #GElektraKey
231 : * @newkey: The new underlying key
232 : *
233 : * Returns: The old underlying key
234 : *
235 : * \note #GElektraKey also swaps ownership of the underlying keys
236 : */
237 : static Key * gelektra_key_swap (GElektraKey * key, Key * newkey)
238 : {
239 38 : keyDecRef (key->key);
240 38 : Key * oldkey = key->key;
241 38 : key->key = newkey;
242 38 : keyIncRef (key->key);
243 : return oldkey;
244 : }
245 :
246 : /* operators */
247 2 : gboolean gelektra_key_equal (const GElektraKey * key, const GElektraKey * other)
248 : {
249 2 : return keyCmp (key->key, other->key) == 0;
250 : }
251 :
252 10 : gint gelektra_key_cmp (const GElektraKey * key, const GElektraKey * other)
253 : {
254 10 : return keyCmp (key->key, other->key);
255 : }
256 :
257 : /* name manipulation */
258 1 : gssize gelektra_key_setname (GElektraKey * key, const char * name)
259 : {
260 1 : return keySetName (key->key, name);
261 : }
262 :
263 1 : gssize gelektra_key_setbasename (GElektraKey * key, const char * basename)
264 : {
265 1 : return keySetBaseName (key->key, basename);
266 : }
267 :
268 0 : gssize gelektra_key_addbasename (GElektraKey * key, const char * basename)
269 : {
270 0 : return keyAddBaseName (key->key, basename);
271 : }
272 :
273 1 : gssize gelektra_key_getnamesize (const GElektraKey * key)
274 : {
275 1 : return keyGetNameSize (key->key);
276 : }
277 :
278 1 : gssize gelektra_key_getbasenamesize (const GElektraKey * key)
279 : {
280 1 : return keyGetBaseNameSize (key->key);
281 : }
282 :
283 1 : gssize gelektra_key_getfullnamesize (const GElektraKey * key)
284 : {
285 1 : return keyGetFullNameSize (key->key);
286 : }
287 :
288 : /* value operations */
289 2 : gssize gelektra_key_setstring (GElektraKey * key, const gchar * value)
290 : {
291 2 : return keySetString (key->key, value);
292 : }
293 :
294 : /**
295 : * gelektra_key_getstring: (skip)
296 : * see keyGetString
297 : */
298 1 : gssize gelektra_key_getstring (const GElektraKey * key, gchar * out, gsize size)
299 : {
300 1 : return keyGetString (key->key, out, size);
301 : }
302 :
303 : /**
304 : * gelektra_key_gi_getstring:
305 : * @key: A #GElektraKey
306 : *
307 : * Returns: (transfer full): a copy of the key value
308 : *
309 : * \note This is for GObject Introspection.
310 : * \note Do NOT use! Use gelektra_key_getstring instead
311 : */
312 1 : gchar * gelektra_key_gi_getstring (const GElektraKey * key)
313 : {
314 1 : gssize size = keyGetValueSize (key->key);
315 1 : if (size <= 0) return NULL;
316 :
317 1 : gchar * data = g_malloc0 (size);
318 1 : if (keyGetString (key->key, data, size) <= 0)
319 : {
320 0 : g_free (data);
321 0 : return NULL;
322 : }
323 : return data;
324 : }
325 :
326 : /**
327 : * gelektra_key_setbinary:
328 : * @key: A #GElektraKey
329 : * @data: (array length=size zero-terminated=0) (element-type guint8): binary data
330 : * @size: size of the input data
331 : */
332 1 : gssize gelektra_key_setbinary (GElektraKey * key, const void * data, gsize size)
333 : {
334 1 : return keySetBinary (key->key, data, size);
335 : }
336 :
337 : /**
338 : * gelektra_key_getbinary: (skip)
339 : * see keyGetBinary
340 : */
341 1 : gssize gelektra_key_getbinary (const GElektraKey * key, void * out, gsize size)
342 : {
343 1 : return keyGetBinary (key->key, out, size);
344 : }
345 :
346 :
347 : /**
348 : * gelektra_key_gi_getbinary:
349 : * @key: A #GElektraKey
350 : * @data_size: size of the returned data
351 : *
352 : * Returns: (array length=data_size zero-terminated=0) (element-type guint8) (transfer full): binary data
353 : *
354 : * \note This is for GObject Introspection.
355 : * \note Do NOT use! Use gelektra_key_getbinary instead
356 : */
357 1 : void * gelektra_key_gi_getbinary (const GElektraKey * key, gssize * data_size)
358 : {
359 1 : *data_size = 0;
360 1 : gssize size = keyGetValueSize (key->key);
361 1 : if (size <= 0) return NULL;
362 :
363 1 : void * data = g_malloc0 (size);
364 1 : if ((*data_size = keyGetBinary (key->key, data, size)) <= 0)
365 : {
366 0 : g_free (data);
367 0 : return NULL;
368 : }
369 : return data;
370 : }
371 :
372 : /**
373 : * gelektra_key_getvalue: (skip)
374 : * @key: A #GElektraKey
375 : *
376 : * Returns: see keyValue
377 : */
378 6 : const void * gelektra_key_getvalue (const GElektraKey * key)
379 : {
380 6 : return keyValue (key->key);
381 : }
382 :
383 2 : gssize gelektra_key_getvaluesize (const GElektraKey * key)
384 : {
385 2 : return keyGetValueSize (key->key);
386 : }
387 :
388 : /**
389 : * gelektra_key_getfunc: (skip)
390 : * @key: A #GElektraKey
391 : *
392 : * Returns: a function pointer stored with gelektra_key_setbinary
393 : */
394 0 : gelektra_func_t gelektra_key_getfunc (const GElektraKey * key)
395 : {
396 : union
397 : {
398 : gelektra_func_t f;
399 : void * v;
400 : } data;
401 :
402 0 : if (keyGetBinary (key->key, &data.v, sizeof (data)) == sizeof (data)) return data.f;
403 : return NULL;
404 : }
405 :
406 : /* metadata */
407 1 : gssize gelektra_key_setmeta (GElektraKey * key, const gchar * name, const gchar * value)
408 : {
409 1 : return keySetMeta (key->key, name, value);
410 : }
411 :
412 1 : gboolean gelektra_key_hasmeta (const GElektraKey * key, const gchar * name)
413 : {
414 1 : return (keyValue (keyGetMeta (key->key, name)) != NULL);
415 : }
416 :
417 : /**
418 : * gelektra_key_getmeta:
419 : * @key: A #GElektraKey
420 : * @name: the name of the meta information
421 : *
422 : * Returns: (transfer full): A #GElektraKey holding the meta information
423 : * see keyGetMeta
424 : */
425 4 : GElektraKey * gelektra_key_getmeta (const GElektraKey * key, const gchar * name)
426 : {
427 4 : return gelektra_key_make ((Key *) keyGetMeta (key->key, name));
428 : }
429 :
430 1 : gint gelektra_key_copymeta (const GElektraKey * key, GElektraKey * dest, const gchar * name)
431 : {
432 1 : return keyCopyMeta (dest->key, key->key, name);
433 : }
434 :
435 1 : gint gelektra_key_copyallmeta (const GElektraKey * key, GElektraKey * dest)
436 : {
437 1 : return keyCopyAllMeta (dest->key, key->key);
438 : }
439 :
440 1 : gint gelektra_key_rewindmeta (GElektraKey * key)
441 : {
442 1 : return keyRewindMeta (key->key);
443 : }
444 :
445 : /**
446 : * gelektra_key_nextmeta:
447 : * @key: A #GElektraKey
448 : *
449 : * Returns: (transfer full): A #GElektraKey holding the next meta information
450 : * see keyCurrentMeta
451 : */
452 10 : GElektraKey * gelektra_key_nextmeta (GElektraKey * key)
453 : {
454 10 : return gelektra_key_make ((Key *) keyNextMeta (key->key));
455 : }
456 :
457 : /**
458 : * gelektra_key_currentmeta:
459 : * @key: A #GElektraKey
460 : *
461 : * Returns: (transfer full): A #GElektraKey holding the current meta information
462 : * see keyCurrentMeta
463 : */
464 9 : GElektraKey * gelektra_key_currentmeta (const GElektraKey * key)
465 : {
466 9 : return gelektra_key_make ((Key *) keyCurrentMeta (key->key));
467 : }
468 :
469 : /* validating */
470 1 : gboolean gelektra_key_isnull (const GElektraKey * key)
471 : {
472 1 : return key->key == NULL;
473 : }
474 :
475 15 : gboolean gelektra_key_isvalid (const GElektraKey * key)
476 : {
477 15 : return keyGetNameSize (key->key) > 1;
478 : }
479 :
480 2 : gboolean gelektra_key_issystem (const GElektraKey * key)
481 : {
482 2 : return !strncmp (keyName (key->key), "system", sizeof ("system") - 1);
483 : }
484 :
485 2 : gboolean gelektra_key_isuser (const GElektraKey * key)
486 : {
487 2 : return !strncmp (keyName (key->key), "user", sizeof ("user") - 1);
488 : }
489 :
490 2 : gboolean gelektra_key_isstring (const GElektraKey * key)
491 : {
492 2 : return keyIsString (key->key);
493 : }
494 :
495 2 : gboolean gelektra_key_isbinary (const GElektraKey * key)
496 : {
497 2 : return keyIsBinary (key->key);
498 : }
499 :
500 1 : gboolean gelektra_key_isinactive (const GElektraKey * key)
501 : {
502 1 : return keyIsInactive (key->key);
503 : }
504 :
505 1 : gboolean gelektra_key_isbelow (const GElektraKey * key, const GElektraKey * other)
506 : {
507 1 : return keyIsBelow (other->key, key->key);
508 : }
509 :
510 2 : gboolean gelektra_key_isbeloworsame (const GElektraKey * key, const GElektraKey * other)
511 : {
512 2 : return keyIsBelowOrSame (other->key, key->key);
513 : }
514 :
515 1 : gboolean gelektra_key_isdirectbelow (const GElektraKey * key, const GElektraKey * other)
516 : {
517 1 : return keyIsDirectBelow (other->key, key->key);
518 : }
|