/** * json_builder_add_null_value: * @builder: a #JsonBuilder * * If called after json_builder_set_member_name(), sets null as member of the * most recent opened object, otherwise null is added as element of the most * recent opened array. * * See also: json_builder_add_value() * * Return value: (transfer none): the #JsonBuilder, or %NULL if the call was inconsistent */ JsonBuilder * json_builder_add_null_value (JsonBuilder *builder) { JsonBuilderState *state; g_return_val_if_fail (JSON_IS_BUILDER (builder), NULL); g_return_val_if_fail (!g_queue_is_empty (builder->priv->stack), NULL); g_return_val_if_fail (json_builder_is_valid_add_mode (builder), NULL); state = g_queue_peek_head (builder->priv->stack); switch (state->mode) { case JSON_BUILDER_MODE_MEMBER: json_object_set_null_member (state->data.object, state->member_name); g_free (state->member_name); state->member_name = NULL; state->mode = JSON_BUILDER_MODE_OBJECT; break; case JSON_BUILDER_MODE_ARRAY: json_array_add_null_element (state->data.array); break; default: g_assert_not_reached (); } return builder; }
/** * json_builder_reset: * @builder: a #JsonBuilder * * Resets the state of the @builder back to its initial state. */ void json_builder_reset (JsonBuilder *builder) { g_return_if_fail (JSON_IS_BUILDER (builder)); json_builder_free_all_state (builder); }
/** * json_builder_get_root: * @builder: a #JsonBuilder * * Returns the root of the current constructed tree, if the build is complete * (ie: all opened objects, object members and arrays are being closed). * * Return value: (transfer full): the #JsonNode, or %NULL if the build is not complete. * Free the returned value with json_node_free(). */ JsonNode * json_builder_get_root (JsonBuilder *builder) { JsonNode *root = NULL; g_return_val_if_fail (JSON_IS_BUILDER (builder), NULL); if (builder->priv->root) root = json_node_copy (builder->priv->root); return root; }
/** * json_builder_set_member_name: * @builder: a #JsonBuilder * @member_name: the name of the member * * Set the name of the next member in an object. The next call must add a value, * open an object or an array. * * Can be called only if the call is associated to an object. * * Return value: (transfer none): the #JsonBuilder, or %NULL if the call was inconsistent */ JsonBuilder * json_builder_set_member_name (JsonBuilder *builder, const gchar *member_name) { JsonBuilderState *state; g_return_val_if_fail (JSON_IS_BUILDER (builder), NULL); g_return_val_if_fail (member_name != NULL, NULL); g_return_val_if_fail (!g_queue_is_empty (builder->priv->stack), NULL); g_return_val_if_fail (json_builder_current_mode (builder) == JSON_BUILDER_MODE_OBJECT, NULL); state = g_queue_peek_head (builder->priv->stack); state->member_name = g_strdup (member_name); state->mode = JSON_BUILDER_MODE_MEMBER; return builder; }
/** * json_builder_begin_object: * @builder: a #JsonBuilder * * Opens a subobject inside the given @builder. When done adding members to * the subobject, json_builder_end_object() must be called. * * Can be called for first or only if the call is associated to an object member * or an array element. * * Return value: (transfer none): the #JsonBuilder, or %NULL if the call was inconsistent */ JsonBuilder * json_builder_begin_object (JsonBuilder *builder) { JsonObject *object; JsonBuilderState *state; JsonBuilderState *cur_state; g_return_val_if_fail (JSON_IS_BUILDER (builder), NULL); g_return_val_if_fail (builder->priv->root == NULL, NULL); g_return_val_if_fail (g_queue_is_empty (builder->priv->stack) || json_builder_is_valid_add_mode (builder), NULL); object = json_object_new (); cur_state = g_queue_peek_head (builder->priv->stack); if (cur_state) { switch (cur_state->mode) { case JSON_BUILDER_MODE_ARRAY: json_array_add_object_element (cur_state->data.array, json_object_ref (object)); break; case JSON_BUILDER_MODE_MEMBER: json_object_set_object_member (cur_state->data.object, cur_state->member_name, json_object_ref (object)); g_free (cur_state->member_name); cur_state->member_name = NULL; cur_state->mode = JSON_BUILDER_MODE_OBJECT; break; default: g_assert_not_reached (); } } state = g_slice_new (JsonBuilderState); state->data.object = object; state->member_name = NULL; state->mode = JSON_BUILDER_MODE_OBJECT; g_queue_push_head (builder->priv->stack, state); return builder; }
/** * json_builder_end_array: * @builder: a #JsonBuilder * * Closes the subarray inside the given @builder that was opened by the most * recent call to json_builder_begin_array(). * * Cannot be called after json_builder_set_member_name(). * * Return value: (transfer none): the #JsonBuilder, or %NULL if the call was inconsistent */ JsonBuilder * json_builder_end_array (JsonBuilder *builder) { JsonBuilderState *state; g_return_val_if_fail (JSON_IS_BUILDER (builder), NULL); g_return_val_if_fail (!g_queue_is_empty (builder->priv->stack), NULL); g_return_val_if_fail (json_builder_current_mode (builder) == JSON_BUILDER_MODE_ARRAY, NULL); state = g_queue_pop_head (builder->priv->stack); if (g_queue_is_empty (builder->priv->stack)) { builder->priv->root = json_node_new (JSON_NODE_ARRAY); json_node_take_array (builder->priv->root, json_array_ref (state->data.array)); } json_builder_state_free (state); return builder; }
static JsonBuilder * _json_builder_add_gvariant (JsonBuilder *builder, GVariant *value) { g_return_val_if_fail (JSON_IS_BUILDER (builder), builder); g_variant_ref_sink (value); switch (g_variant_classify (value)) { case G_VARIANT_CLASS_BOOLEAN: json_builder_add_boolean_value (builder, g_variant_get_boolean (value)); break; case G_VARIANT_CLASS_BYTE: json_builder_add_int_value (builder, g_variant_get_byte (value)); break; case G_VARIANT_CLASS_INT16: json_builder_add_int_value (builder, g_variant_get_int16 (value)); break; case G_VARIANT_CLASS_UINT16: json_builder_add_int_value (builder, g_variant_get_uint16 (value)); break; case G_VARIANT_CLASS_INT32: json_builder_add_int_value (builder, g_variant_get_int32 (value)); break; case G_VARIANT_CLASS_UINT32: json_builder_add_int_value (builder, g_variant_get_uint32 (value)); break; case G_VARIANT_CLASS_INT64: json_builder_add_int_value (builder, g_variant_get_int64 (value)); break; case G_VARIANT_CLASS_UINT64: json_builder_add_int_value (builder, g_variant_get_uint64 (value)); break; case G_VARIANT_CLASS_HANDLE: json_builder_add_int_value (builder, g_variant_get_handle (value)); break; case G_VARIANT_CLASS_DOUBLE: json_builder_add_double_value (builder, g_variant_get_double (value)); break; case G_VARIANT_CLASS_STRING: /* explicit fall-through */ case G_VARIANT_CLASS_OBJECT_PATH: /* explicit fall-through */ case G_VARIANT_CLASS_SIGNATURE: json_builder_add_string_value (builder, g_variant_get_string (value, NULL)); break; /* TODO: */ case G_VARIANT_CLASS_VARIANT: { GVariant *child; child = g_variant_get_variant (value); _json_builder_add_gvariant (builder, child); g_variant_unref (child); } break; case G_VARIANT_CLASS_MAYBE: g_assert_not_reached (); break; case G_VARIANT_CLASS_ARRAY: { const GVariantType *type; const GVariantType *element_type; type = g_variant_get_type (value); element_type = g_variant_type_element (type); if (g_variant_type_is_dict_entry (element_type)) { GVariantIter iter; GVariant *child; json_builder_begin_object (builder); g_variant_iter_init (&iter, value); while ((child = g_variant_iter_next_value (&iter)) != NULL) { _json_builder_add_gvariant (builder, child); g_variant_unref (child); } json_builder_end_object (builder); } else { GVariantIter iter; GVariant *child; json_builder_begin_array (builder); g_variant_iter_init (&iter, value); while ((child = g_variant_iter_next_value (&iter)) != NULL) { _json_builder_add_gvariant (builder, child); g_variant_unref (child); } json_builder_end_array (builder); } } break; case G_VARIANT_CLASS_TUPLE: { GVariantIter iter; GVariant *child; json_builder_begin_array (builder); g_variant_iter_init (&iter, value); while ((child = g_variant_iter_next_value (&iter)) != NULL) { _json_builder_add_gvariant (builder, child); g_variant_unref (child); } json_builder_end_array (builder); } break; case G_VARIANT_CLASS_DICT_ENTRY: { GVariant *dict_key; GVariant *dict_value; gchar *dict_key_string; dict_key = g_variant_get_child_value (value, 0); dict_value = g_variant_get_child_value (value, 1); if (g_variant_is_of_type (dict_key, G_VARIANT_TYPE("s"))) dict_key_string = g_variant_dup_string (dict_key, NULL); else dict_key_string = g_variant_print (dict_key, FALSE); json_builder_set_member_name (builder, dict_key_string); _json_builder_add_gvariant (builder, dict_value); g_free (dict_key_string); g_variant_unref (dict_key); g_variant_unref (dict_value); } break; } g_variant_unref (value); return builder; }