3 * Purple is the legal property of its developers, whose names are too numerous
4 * to list here. Please refer to the COPYRIGHT file distributed with this
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program 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
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
30 typedef struct _FbJsonValue FbJsonValue
;
51 } FbJsonValuesPrivate
;
56 * Represents a JSON value handler.
61 FbJsonValuesPrivate
*priv
;
64 G_DEFINE_TYPE_WITH_PRIVATE(FbJsonValues
, fb_json_values
, G_TYPE_OBJECT
);
67 fb_json_values_dispose(GObject
*obj
)
70 FbJsonValuesPrivate
*priv
= FB_JSON_VALUES(obj
)->priv
;
72 while (!g_queue_is_empty(priv
->queue
)) {
73 value
= g_queue_pop_head(priv
->queue
);
75 if (G_IS_VALUE(&value
->value
)) {
76 g_value_unset(&value
->value
);
82 if (priv
->array
!= NULL
) {
83 json_array_unref(priv
->array
);
86 if (priv
->error
!= NULL
) {
87 g_error_free(priv
->error
);
90 g_queue_free(priv
->queue
);
94 fb_json_values_class_init(FbJsonValuesClass
*klass
)
96 GObjectClass
*gklass
= G_OBJECT_CLASS(klass
);
98 gklass
->dispose
= fb_json_values_dispose
;
102 fb_json_values_init(FbJsonValues
*values
)
104 FbJsonValuesPrivate
*priv
= fb_json_values_get_instance_private(values
);
108 priv
->queue
= g_queue_new();
112 fb_json_error_quark(void)
116 if (G_UNLIKELY(q
== 0)) {
117 q
= g_quark_from_static_string("fb-json-error-quark");
124 fb_json_bldr_new(JsonNodeType type
)
128 bldr
= json_builder_new();
131 case JSON_NODE_ARRAY
:
132 fb_json_bldr_arr_begin(bldr
, NULL
);
135 case JSON_NODE_OBJECT
:
136 fb_json_bldr_obj_begin(bldr
, NULL
);
147 fb_json_bldr_close(JsonBuilder
*bldr
, JsonNodeType type
, gsize
*size
)
154 case JSON_NODE_ARRAY
:
155 fb_json_bldr_arr_end(bldr
);
158 case JSON_NODE_OBJECT
:
159 fb_json_bldr_obj_end(bldr
);
166 genr
= json_generator_new();
167 root
= json_builder_get_root(bldr
);
169 json_generator_set_root(genr
, root
);
170 ret
= json_generator_to_data(genr
, size
);
172 json_node_free(root
);
173 g_object_unref(genr
);
174 g_object_unref(bldr
);
180 fb_json_bldr_arr_begin(JsonBuilder
*bldr
, const gchar
*name
)
183 json_builder_set_member_name(bldr
, name
);
186 json_builder_begin_array(bldr
);
190 fb_json_bldr_arr_end(JsonBuilder
*bldr
)
192 json_builder_end_array(bldr
);
196 fb_json_bldr_obj_begin(JsonBuilder
*bldr
, const gchar
*name
)
199 json_builder_set_member_name(bldr
, name
);
202 json_builder_begin_object(bldr
);
206 fb_json_bldr_obj_end(JsonBuilder
*bldr
)
208 json_builder_end_object(bldr
);
212 fb_json_bldr_add_bool(JsonBuilder
*bldr
, const gchar
*name
, gboolean value
)
215 json_builder_set_member_name(bldr
, name
);
218 json_builder_add_boolean_value(bldr
, value
);
222 fb_json_bldr_add_dbl(JsonBuilder
*bldr
, const gchar
*name
, gdouble value
)
225 json_builder_set_member_name(bldr
, name
);
228 json_builder_add_double_value(bldr
, value
);
232 fb_json_bldr_add_int(JsonBuilder
*bldr
, const gchar
*name
, gint64 value
)
235 json_builder_set_member_name(bldr
, name
);
238 json_builder_add_int_value(bldr
, value
);
242 fb_json_bldr_add_str(JsonBuilder
*bldr
, const gchar
*name
, const gchar
*value
)
245 json_builder_set_member_name(bldr
, name
);
248 json_builder_add_string_value(bldr
, value
);
252 fb_json_bldr_add_strf(JsonBuilder
*bldr
, const gchar
*name
,
253 const gchar
*format
, ...)
258 va_start(ap
, format
);
259 value
= g_strdup_vprintf(format
, ap
);
262 fb_json_bldr_add_str(bldr
, name
, value
);
267 fb_json_node_new(const gchar
*data
, gssize size
, GError
**error
)
273 g_return_val_if_fail(data
!= NULL
, NULL
);
279 /* Ensure data is null terminated for json-glib < 1.0.2 */
280 slice
= g_strndup(data
, size
);
281 prsr
= json_parser_new();
283 if (!json_parser_load_from_data(prsr
, slice
, size
, error
)) {
284 g_object_unref(prsr
);
289 root
= json_parser_get_root(prsr
);
290 root
= json_node_copy(root
);
292 g_object_unref(prsr
);
298 fb_json_node_get(JsonNode
*root
, const gchar
*expr
, GError
**error
)
306 /* Special case for json-glib < 0.99.2 */
307 if (purple_strequal(expr
, "$")) {
308 return json_node_copy(root
);
311 node
= json_path_query(expr
, root
, &err
);
314 g_propagate_error(error
, err
);
315 json_node_free(node
);
319 rslt
= json_node_get_array(node
);
320 size
= json_array_get_length(rslt
);
323 g_set_error(error
, FB_JSON_ERROR
, FB_JSON_ERROR_NOMATCH
,
324 _("No matches for %s"), expr
);
325 json_node_free(node
);
330 g_set_error(error
, FB_JSON_ERROR
, FB_JSON_ERROR_AMBIGUOUS
,
331 _("Ambiguous matches for %s"), expr
);
332 json_node_free(node
);
336 if (json_array_get_null_element(rslt
, 0)) {
337 g_set_error(error
, FB_JSON_ERROR
, FB_JSON_ERROR_NULL
,
338 _("Null value for %s"), expr
);
339 json_node_free(node
);
343 ret
= json_array_dup_element(rslt
, 0);
344 json_node_free(node
);
349 fb_json_node_get_nth(JsonNode
*root
, guint n
)
355 obj
= json_node_get_object(root
);
356 vals
= json_object_get_values(obj
);
357 ret
= g_list_nth_data(vals
, n
);
364 fb_json_node_get_arr(JsonNode
*root
, const gchar
*expr
, GError
**error
)
369 rslt
= fb_json_node_get(root
, expr
, error
);
375 ret
= json_node_dup_array(rslt
);
376 json_node_free(rslt
);
381 fb_json_node_get_bool(JsonNode
*root
, const gchar
*expr
, GError
**error
)
386 rslt
= fb_json_node_get(root
, expr
, error
);
392 ret
= json_node_get_boolean(rslt
);
393 json_node_free(rslt
);
398 fb_json_node_get_dbl(JsonNode
*root
, const gchar
*expr
, GError
**error
)
403 rslt
= fb_json_node_get(root
, expr
, error
);
409 ret
= json_node_get_double(rslt
);
410 json_node_free(rslt
);
415 fb_json_node_get_int(JsonNode
*root
, const gchar
*expr
, GError
**error
)
420 rslt
= fb_json_node_get(root
, expr
, error
);
426 ret
= json_node_get_int(rslt
);
427 json_node_free(rslt
);
432 fb_json_node_get_str(JsonNode
*root
, const gchar
*expr
, GError
**error
)
437 rslt
= fb_json_node_get(root
, expr
, error
);
443 ret
= json_node_dup_string(rslt
);
444 json_node_free(rslt
);
449 fb_json_values_new(JsonNode
*root
)
451 FbJsonValues
*values
;
452 FbJsonValuesPrivate
*priv
;
454 g_return_val_if_fail(root
!= NULL
, NULL
);
456 values
= g_object_new(FB_TYPE_JSON_VALUES
, NULL
);
464 fb_json_values_add(FbJsonValues
*values
, FbJsonType type
, gboolean required
,
468 FbJsonValuesPrivate
*priv
;
470 g_return_if_fail(values
!= NULL
);
471 g_return_if_fail(expr
!= NULL
);
474 value
= g_new0(FbJsonValue
, 1);
477 value
->required
= required
;
479 g_queue_push_tail(priv
->queue
, value
);
483 fb_json_values_get_root(FbJsonValues
*values
)
485 FbJsonValuesPrivate
*priv
;
488 g_return_val_if_fail(values
!= NULL
, NULL
);
491 if (priv
->array
== NULL
) {
495 g_return_val_if_fail(priv
->index
> 0, NULL
);
496 index
= priv
->index
- 1;
498 if (json_array_get_length(priv
->array
) <= index
) {
502 return json_array_get_element(priv
->array
, index
);
506 fb_json_values_set_array(FbJsonValues
*values
, gboolean required
,
509 FbJsonValuesPrivate
*priv
;
511 g_return_if_fail(values
!= NULL
);
514 priv
->array
= fb_json_node_get_arr(priv
->root
, expr
, &priv
->error
);
515 priv
->isarray
= TRUE
;
517 if ((priv
->error
!= NULL
) && !required
) {
518 g_clear_error(&priv
->error
);
523 fb_json_values_update(FbJsonValues
*values
, GError
**error
)
526 FbJsonValuesPrivate
*priv
;
533 g_return_val_if_fail(values
!= NULL
, FALSE
);
536 if (G_UNLIKELY(priv
->error
!= NULL
)) {
537 g_propagate_error(error
, priv
->error
);
543 if ((priv
->array
== NULL
) ||
544 (json_array_get_length(priv
->array
) <= priv
->index
))
549 root
= json_array_get_element(priv
->array
, priv
->index
++);
554 g_return_val_if_fail(root
!= NULL
, FALSE
);
556 for (l
= priv
->queue
->head
; l
!= NULL
; l
= l
->next
) {
558 node
= fb_json_node_get(root
, value
->expr
, &err
);
560 if (G_IS_VALUE(&value
->value
)) {
561 g_value_unset(&value
->value
);
565 json_node_free(node
);
567 if (value
->required
) {
568 g_propagate_error(error
, err
);
576 type
= json_node_get_value_type(node
);
578 if (G_UNLIKELY(type
!= value
->type
)) {
579 g_set_error(error
, FB_JSON_ERROR
, FB_JSON_ERROR_TYPE
,
580 _("Expected a %s but got a %s for %s"),
581 g_type_name(value
->type
),
584 json_node_free(node
);
588 json_node_get_value(node
, &value
->value
);
589 json_node_free(node
);
592 priv
->next
= priv
->queue
->head
;
597 fb_json_values_next(FbJsonValues
*values
)
600 FbJsonValuesPrivate
*priv
;
602 g_return_val_if_fail(values
!= NULL
, NULL
);
605 g_return_val_if_fail(priv
->next
!= NULL
, NULL
);
606 value
= priv
->next
->data
;
607 priv
->next
= priv
->next
->next
;
609 if (!G_IS_VALUE(&value
->value
)) {
613 return &value
->value
;
617 fb_json_values_next_bool(FbJsonValues
*values
, gboolean defval
)
621 value
= fb_json_values_next(values
);
623 if (G_UNLIKELY(value
== NULL
)) {
627 return g_value_get_boolean(value
);
631 fb_json_values_next_dbl(FbJsonValues
*values
, gdouble defval
)
635 value
= fb_json_values_next(values
);
637 if (G_UNLIKELY(value
== NULL
)) {
641 return g_value_get_double(value
);
645 fb_json_values_next_int(FbJsonValues
*values
, gint64 defval
)
649 value
= fb_json_values_next(values
);
651 if (G_UNLIKELY(value
== NULL
)) {
655 return g_value_get_int64(value
);
659 fb_json_values_next_str(FbJsonValues
*values
, const gchar
*defval
)
663 value
= fb_json_values_next(values
);
665 if (G_UNLIKELY(value
== NULL
)) {
669 return g_value_get_string(value
);
673 fb_json_values_next_str_dup(FbJsonValues
*values
, const gchar
*defval
)
677 value
= fb_json_values_next(values
);
679 if (G_UNLIKELY(value
== NULL
)) {
680 return g_strdup(defval
);
683 return g_value_dup_string(value
);