Initial Import
[profile/ivi/json-glib.git] / json-glib / json-array.c
1 /* json-array.c - JSON array implementation
2  * 
3  * This file is part of JSON-GLib
4  * Copyright (C) 2007  OpenedHand Ltd.
5  * Copyright (C) 2009  Intel Corp.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library. If not, see <http://www.gnu.org/licenses/>.
19  *
20  * Author:
21  *   Emmanuele Bassi  <ebassi@linux.intel.com>
22  */
23
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27
28 #include "json-types-private.h"
29
30 /**
31  * SECTION:json-array
32  * @short_description: a JSON array representation
33  *
34  * #JsonArray is the representation of the array type inside JSON. It contains
35  * #JsonNode<!-- -->s, which may contain fundamental types, other arrays or
36  * objects.
37  *
38  * Since arrays can be expensive, they are reference counted. You can control
39  * the lifetime of a #JsonArray using json_array_ref() and json_array_unref().
40  *
41  * To append an element, use json_array_add_element().
42  * To extract an element at a given index, use json_array_get_element().
43  * To retrieve the entire array in list form, use json_array_get_elements().
44  * To retrieve the length of the array, use json_array_get_length().
45  */
46
47 G_DEFINE_BOXED_TYPE (JsonArray, json_array, json_array_ref, json_array_unref);
48
49 /**
50  * json_array_new:
51  *
52  * Creates a new #JsonArray.
53  *
54  * Return value: the newly created #JsonArray
55  */
56 JsonArray *
57 json_array_new (void)
58 {
59   JsonArray *array;
60
61   array = g_slice_new (JsonArray);
62
63   array->ref_count = 1;
64   array->elements = g_ptr_array_new ();
65
66   return array;
67 }
68
69 /**
70  * json_array_sized_new:
71  * @n_elements: number of slots to pre-allocate
72  *
73  * Creates a new #JsonArray with @n_elements slots already allocated.
74  *
75  * Return value: the newly created #JsonArray
76  */
77 JsonArray *
78 json_array_sized_new (guint n_elements)
79 {
80   JsonArray *array;
81
82   array = g_slice_new (JsonArray);
83   
84   array->ref_count = 1;
85   array->elements = g_ptr_array_sized_new (n_elements);
86
87   return array;
88 }
89
90 /**
91  * json_array_ref:
92  * @array: a #JsonArray
93  *
94  * Increase by one the reference count of a #JsonArray.
95  *
96  * Return value: the passed #JsonArray, with the reference count
97  *   increased by one.
98  */
99 JsonArray *
100 json_array_ref (JsonArray *array)
101 {
102   g_return_val_if_fail (array != NULL, NULL);
103   g_return_val_if_fail (array->ref_count > 0, NULL);
104
105   g_atomic_int_add (&array->ref_count, 1);
106
107   return array;
108 }
109
110 /**
111  * json_array_unref:
112  * @array: a #JsonArray
113  *
114  * Decreases by one the reference count of a #JsonArray. If the
115  * reference count reaches zero, the array is destroyed and all
116  * its allocated resources are freed.
117  */
118 void
119 json_array_unref (JsonArray *array)
120 {
121   g_return_if_fail (array != NULL);
122   g_return_if_fail (array->ref_count > 0);
123
124   if (g_atomic_int_dec_and_test (&array->ref_count))
125     {
126       guint i;
127
128       for (i = 0; i < array->elements->len; i++)
129         json_node_free (g_ptr_array_index (array->elements, i));
130
131       g_ptr_array_free (array->elements, TRUE);
132       array->elements = NULL;
133
134       g_slice_free (JsonArray, array);
135     }
136 }
137
138 /**
139  * json_array_get_elements:
140  * @array: a #JsonArray
141  *
142  * Gets the elements of a #JsonArray as a list of #JsonNode<!-- -->s.
143  *
144  * Return value: (element-type JsonNode) (transfer container): a #GList
145  *   containing the elements of the array. The contents of the list are
146  *   owned by the array and should never be modified or freed. Use
147  *   g_list_free() on the returned list when done using it
148  */
149 GList *
150 json_array_get_elements (JsonArray *array)
151 {
152   GList *retval;
153   guint i;
154
155   g_return_val_if_fail (array != NULL, NULL);
156
157   retval = NULL;
158   for (i = 0; i < array->elements->len; i++)
159     retval = g_list_prepend (retval,
160                              g_ptr_array_index (array->elements, i));
161
162   return g_list_reverse (retval);
163 }
164
165 /**
166  * json_array_dup_element:
167  * @array: a #JsonArray
168  * @index_: the index of the element to retrieve
169  *
170  * Retrieves a copy of the #JsonNode containing the value of the
171  * element at @index_ inside a #JsonArray
172  *
173  * Return value: (transfer full): a copy of the #JsonNode at the requested
174  *   index. Use json_node_free() when done.
175  *
176  * Since: 0.6
177  */
178 JsonNode *
179 json_array_dup_element (JsonArray *array,
180                         guint      index_)
181 {
182   JsonNode *retval;
183
184   g_return_val_if_fail (array != NULL, NULL);
185   g_return_val_if_fail (index_ < array->elements->len, NULL);
186
187   retval = json_array_get_element (array, index_);
188   if (!retval)
189     return NULL;
190
191   return json_node_copy (retval);
192 }
193
194 /**
195  * json_array_get_element:
196  * @array: a #JsonArray
197  * @index_: the index of the element to retrieve
198  * 
199  * Retrieves the #JsonNode containing the value of the element at @index_
200  * inside a #JsonArray.
201  *
202  * Return value: (transfer none): a pointer to the #JsonNode at the requested index
203  */
204 JsonNode *
205 json_array_get_element (JsonArray *array,
206                         guint      index_)
207 {
208   g_return_val_if_fail (array != NULL, NULL);
209   g_return_val_if_fail (index_ < array->elements->len, NULL);
210
211   return g_ptr_array_index (array->elements, index_);
212 }
213
214 /**
215  * json_array_get_int_element:
216  * @array: a #JsonArray
217  * @index_: the index of the element to retrieve
218  *
219  * Conveniently retrieves the integer value of the element at @index_
220  * inside @array
221  *
222  * See also: json_array_get_element(), json_node_get_int()
223  *
224  * Return value: the integer value
225  *
226  * Since: 0.8
227  */
228 gint64
229 json_array_get_int_element (JsonArray *array,
230                             guint      index_)
231 {
232   JsonNode *node;
233
234   g_return_val_if_fail (array != NULL, 0);
235   g_return_val_if_fail (index_ < array->elements->len, 0);
236
237   node = g_ptr_array_index (array->elements, index_);
238   g_return_val_if_fail (node != NULL, 0);
239   g_return_val_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_VALUE, 0);
240
241   return json_node_get_int (node);
242 }
243
244 /**
245  * json_array_get_double_element:
246  * @array: a #JsonArray
247  * @index_: the index of the element to retrieve
248  *
249  * Conveniently retrieves the floating point value of the element at
250  * @index_ inside @array
251  *
252  * See also: json_array_get_element(), json_node_get_double()
253  *
254  * Return value: the floating point value
255  *
256  * Since: 0.8
257  */
258 gdouble
259 json_array_get_double_element (JsonArray *array,
260                                guint      index_)
261 {
262   JsonNode *node;
263
264   g_return_val_if_fail (array != NULL, 0.0);
265   g_return_val_if_fail (index_ < array->elements->len, 0.0);
266
267   node = g_ptr_array_index (array->elements, index_);
268   g_return_val_if_fail (node != NULL, 0.0);
269   g_return_val_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_VALUE, 0.0);
270
271   return json_node_get_double (node);
272 }
273
274 /**
275  * json_array_get_boolean_element:
276  * @array: a #JsonArray
277  * @index_: the index of the element to retrieve
278  *
279  * Conveniently retrieves the boolean value of the element at @index_
280  * inside @array
281  *
282  * See also: json_array_get_element(), json_node_get_boolean()
283  *
284  * Return value: the integer value
285  *
286  * Since: 0.8
287  */
288 gboolean
289 json_array_get_boolean_element (JsonArray *array,
290                                 guint      index_)
291 {
292   JsonNode *node;
293
294   g_return_val_if_fail (array != NULL, FALSE);
295   g_return_val_if_fail (index_ < array->elements->len, FALSE);
296
297   node = g_ptr_array_index (array->elements, index_);
298   g_return_val_if_fail (node != NULL, FALSE);
299   g_return_val_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_VALUE, FALSE);
300
301   return json_node_get_boolean (node);
302 }
303
304 /**
305  * json_array_get_string_element:
306  * @array: a #JsonArray
307  * @index_: the index of the element to retrieve
308  *
309  * Conveniently retrieves the string value of the element at @index_
310  * inside @array
311  *
312  * See also: json_array_get_element(), json_node_get_string()
313  *
314  * Return value: the string value; the returned string is owned by
315  *   the #JsonArray and should not be modified or freed
316  *
317  * Since: 0.8
318  */
319 const gchar *
320 json_array_get_string_element (JsonArray *array,
321                                guint      index_)
322 {
323   JsonNode *node;
324
325   g_return_val_if_fail (array != NULL, NULL);
326   g_return_val_if_fail (index_ < array->elements->len, NULL);
327
328   node = g_ptr_array_index (array->elements, index_);
329   g_return_val_if_fail (node != NULL, NULL);
330   g_return_val_if_fail (JSON_NODE_HOLDS_VALUE (node) || JSON_NODE_HOLDS_NULL (node), NULL);
331
332   if (JSON_NODE_HOLDS_NULL (node))
333     return NULL;
334
335   return json_node_get_string (node);
336 }
337
338 /**
339  * json_array_get_null_element:
340  * @array: a #JsonArray
341  * @index_: the index of the element to retrieve
342  *
343  * Conveniently retrieves whether the element at @index_ is set to null
344  *
345  * See also: json_array_get_element(), JSON_NODE_TYPE(), %JSON_NODE_NULL
346  *
347  * Return value: %TRUE if the element is null
348  *
349  * Since: 0.8
350  */
351 gboolean
352 json_array_get_null_element (JsonArray *array,
353                              guint      index_)
354 {
355   JsonNode *node;
356
357   g_return_val_if_fail (array != NULL, FALSE);
358   g_return_val_if_fail (index_ < array->elements->len, FALSE);
359
360   node = g_ptr_array_index (array->elements, index_);
361   g_return_val_if_fail (node != NULL, FALSE);
362
363   return JSON_NODE_TYPE (node) == JSON_NODE_NULL;
364 }
365
366 /**
367  * json_array_get_array_element:
368  * @array: a #JsonArray
369  * @index_: the index of the element to retrieve
370  *
371  * Conveniently retrieves the array from the element at @index_
372  * inside @array
373  *
374  * See also: json_array_get_element(), json_node_get_array()
375  *
376  * Return value: (transfer none): the array
377  *
378  * Since: 0.8
379  */
380 JsonArray *
381 json_array_get_array_element (JsonArray *array,
382                               guint      index_)
383 {
384   JsonNode *node;
385
386   g_return_val_if_fail (array != NULL, NULL);
387   g_return_val_if_fail (index_ < array->elements->len, NULL);
388
389   node = g_ptr_array_index (array->elements, index_);
390   g_return_val_if_fail (node != NULL, NULL);
391   g_return_val_if_fail (JSON_NODE_HOLDS_ARRAY (node) || JSON_NODE_HOLDS_NULL (node), NULL);
392
393   if (JSON_NODE_HOLDS_NULL (node))
394     return NULL;
395
396   return json_node_get_array (node);
397 }
398
399 /**
400  * json_array_get_object_element:
401  * @array: a #JsonArray
402  * @index_: the index of the element to retrieve
403  *
404  * Conveniently retrieves the object from the element at @index_
405  * inside @array
406  *
407  * See also: json_array_get_element(), json_node_get_object()
408  *
409  * Return value: (transfer none): the object
410  *
411  * Since: 0.8
412  */
413 JsonObject *
414 json_array_get_object_element (JsonArray *array,
415                                guint      index_)
416 {
417   JsonNode *node;
418
419   g_return_val_if_fail (array != NULL, NULL);
420   g_return_val_if_fail (index_ < array->elements->len, NULL);
421
422   node = g_ptr_array_index (array->elements, index_);
423   g_return_val_if_fail (node != NULL, NULL);
424   g_return_val_if_fail (JSON_NODE_HOLDS_OBJECT (node) || JSON_NODE_HOLDS_NULL (node), NULL);
425
426   if (JSON_NODE_HOLDS_NULL (node))
427     return NULL;
428
429   return json_node_get_object (node);
430 }
431
432 /**
433  * json_array_get_length:
434  * @array: a #JsonArray
435  *
436  * Retrieves the length of a #JsonArray
437  *
438  * Return value: the length of the array
439  */
440 guint
441 json_array_get_length (JsonArray *array)
442 {
443   g_return_val_if_fail (array != NULL, 0);
444
445   return array->elements->len;
446 }
447
448 /**
449  * json_array_add_element:
450  * @array: a #JsonArray
451  * @node: (transfer full): a #JsonNode
452  *
453  * Appends @node inside @array. The array will take ownership of the
454  * #JsonNode.
455  */
456 void
457 json_array_add_element (JsonArray *array,
458                         JsonNode  *node)
459 {
460   g_return_if_fail (array != NULL);
461   g_return_if_fail (node != NULL);
462
463   g_ptr_array_add (array->elements, node);
464 }
465
466 /**
467  * json_array_add_int_element:
468  * @array: a #JsonArray
469  * @value: an integer value
470  *
471  * Conveniently adds an integer @value into @array
472  *
473  * See also: json_array_add_element(), json_node_set_int()
474  *
475  * Since: 0.8
476  */
477 void
478 json_array_add_int_element (JsonArray *array,
479                             gint64     value)
480 {
481   JsonNode *node;
482
483   g_return_if_fail (array != NULL);
484
485   node = json_node_new (JSON_NODE_VALUE);
486   json_node_set_int (node, value);
487
488   g_ptr_array_add (array->elements, node);
489 }
490
491 /**
492  * json_array_add_double_element:
493  * @array: a #JsonArray
494  * @value: a floating point value
495  *
496  * Conveniently adds a floating point @value into @array
497  *
498  * See also: json_array_add_element(), json_node_set_double()
499  *
500  * Since: 0.8
501  */
502 void
503 json_array_add_double_element (JsonArray *array,
504                                gdouble    value)
505 {
506   JsonNode *node;
507
508   g_return_if_fail (array != NULL);
509
510   node = json_node_new (JSON_NODE_VALUE);
511   json_node_set_double (node, value);
512
513   g_ptr_array_add (array->elements, node);
514 }
515
516 /**
517  * json_array_add_boolean_element:
518  * @array: a #JsonArray
519  * @value: a boolean value
520  *
521  * Conveniently adds a boolean @value into @array
522  *
523  * See also: json_array_add_element(), json_node_set_boolean()
524  *
525  * Since: 0.8
526  */
527 void
528 json_array_add_boolean_element (JsonArray *array,
529                                 gboolean   value)
530 {
531   JsonNode *node;
532
533   g_return_if_fail (array != NULL);
534
535   node = json_node_new (JSON_NODE_VALUE);
536   json_node_set_boolean (node, value);
537
538   g_ptr_array_add (array->elements, node);
539 }
540
541 /**
542  * json_array_add_string_element:
543  * @array: a #JsonArray
544  * @value: a string value
545  *
546  * Conveniently adds a string @value into @array
547  *
548  * See also: json_array_add_element(), json_node_set_string()
549  *
550  * Since: 0.8
551  */
552 void
553 json_array_add_string_element (JsonArray   *array,
554                                const gchar *value)
555 {
556   JsonNode *node;
557
558   g_return_if_fail (array != NULL);
559   g_return_if_fail (value != NULL);
560
561   if (value != NULL)
562     {
563       node = json_node_new (JSON_NODE_VALUE);
564       json_node_set_string (node, value);
565     }
566   else
567     node = json_node_new (JSON_NODE_NULL);
568
569   g_ptr_array_add (array->elements, node);
570 }
571
572 /**
573  * json_array_add_null_element:
574  * @array: a #JsonArray
575  *
576  * Conveniently adds a null element into @array
577  *
578  * See also: json_array_add_element(), %JSON_NODE_NULL
579  *
580  * Since: 0.8
581  */
582 void
583 json_array_add_null_element (JsonArray *array)
584 {
585   JsonNode *node;
586
587   g_return_if_fail (array != NULL);
588
589   node = json_node_new (JSON_NODE_NULL);
590
591   g_ptr_array_add (array->elements, node);
592 }
593
594 /**
595  * json_array_add_array_element:
596  * @array: a #JsonArray
597  * @value: (transfer full): a #JsonArray
598  *
599  * Conveniently adds an array into @array. The @array takes ownership
600  * of the newly added #JsonArray
601  *
602  * See also: json_array_add_element(), json_node_take_array()
603  *
604  * Since: 0.8
605  */
606 void
607 json_array_add_array_element (JsonArray *array,
608                               JsonArray *value)
609 {
610   JsonNode *node;
611
612   g_return_if_fail (array != NULL);
613   g_return_if_fail (value != NULL);
614
615   if (value != NULL)
616     {
617       node = json_node_new (JSON_NODE_ARRAY);
618       json_node_take_array (node, value);
619     }
620   else
621     node = json_node_new (JSON_NODE_NULL);
622
623   g_ptr_array_add (array->elements, node);
624 }
625
626 /**
627  * json_array_add_object_element:
628  * @array: a #JsonArray
629  * @value: (transfer full): a #JsonObject
630  *
631  * Conveniently adds an object into @array. The @array takes ownership
632  * of the newly added #JsonObject
633  *
634  * See also: json_array_add_element(), json_node_take_object()
635  *
636  * Since: 0.8
637  */
638 void
639 json_array_add_object_element (JsonArray  *array,
640                                JsonObject *value)
641 {
642   JsonNode *node;
643
644   g_return_if_fail (array != NULL);
645   g_return_if_fail (value != NULL);
646
647   if (value != NULL)
648     {
649       node = json_node_new (JSON_NODE_OBJECT);
650       json_node_take_object (node, value);
651     }
652   else
653     node = json_node_new (JSON_NODE_NULL);
654
655   g_ptr_array_add (array->elements, node);
656 }
657
658 /**
659  * json_array_remove_element:
660  * @array: a #JsonArray
661  * @index_: the position of the element to be removed
662  *
663  * Removes the #JsonNode inside @array at @index_ freeing its allocated
664  * resources.
665  */
666 void
667 json_array_remove_element (JsonArray *array,
668                            guint      index_)
669 {
670   g_return_if_fail (array != NULL);
671   g_return_if_fail (index_ < array->elements->len);
672
673   json_node_free (g_ptr_array_remove_index (array->elements, index_));
674 }
675
676 /**
677  * json_array_foreach_element:
678  * @array: a #JsonArray
679  * @func: (scope call): the function to be called on each element
680  * @data: (closure): data to be passed to the function
681  *
682  * Iterates over all elements of @array and calls @func on
683  * each one of them.
684  *
685  * It is safe to change the value of a #JsonNode of the @array
686  * from within the iterator @func, but it is not safe to add or
687  * remove elements from the @array.
688  *
689  * Since: 0.8
690  */
691 void
692 json_array_foreach_element (JsonArray        *array,
693                             JsonArrayForeach  func,
694                             gpointer          data)
695 {
696   gint i;
697
698   g_return_if_fail (array != NULL);
699   g_return_if_fail (func != NULL);
700
701   for (i = 0; i < array->elements->len; i++)
702     {
703       JsonNode *element_node;
704
705       element_node = g_ptr_array_index (array->elements, i);
706
707       (* func) (array, i, element_node, data);
708     }
709 }