/** * json_node_copy: * @node: a #JsonNode * * Copies @node. If the node contains complex data types then the reference * count of the objects is increased. * * Return value: (transfer full): the copied #JsonNode */ JsonNode * json_node_copy (JsonNode *node) { JsonNode *copy; g_return_val_if_fail (node != NULL, NULL); copy = g_slice_new0 (JsonNode); copy->type = node->type; switch (copy->type) { case JSON_NODE_OBJECT: copy->data.object = json_node_dup_object (node); break; case JSON_NODE_ARRAY: copy->data.array = json_node_dup_array (node); break; case JSON_NODE_VALUE: if (node->data.value) copy->data.value = json_value_ref (node->data.value); break; case JSON_NODE_NULL: break; default: g_assert_not_reached (); } return copy; }
/** * json_node_copy: * @node: a #JsonNode * * Copies @node. If the node contains complex data types, their reference * counts are increased, regardless of whether the node is mutable or * immutable. * * The copy will be immutable if, and only if, @node is immutable. However, * there should be no need to copy an immutable node. * * Return value: (transfer full): the copied #JsonNode */ JsonNode * json_node_copy (JsonNode *node) { JsonNode *copy; g_return_val_if_fail (JSON_NODE_IS_VALID (node), NULL); copy = json_node_alloc (); copy->type = node->type; copy->immutable = node->immutable; if (node->immutable) g_debug ("Copying immutable JsonNode %p", node); switch (copy->type) { case JSON_NODE_OBJECT: copy->data.object = json_node_dup_object (node); break; case JSON_NODE_ARRAY: copy->data.array = json_node_dup_array (node); break; case JSON_NODE_VALUE: if (node->data.value) copy->data.value = json_value_ref (node->data.value); break; case JSON_NODE_NULL: break; default: g_assert_not_reached (); } return copy; }
/* Params utils */ static gboolean melo_jsonrpc_add_node (JsonNode *node, JsonObject *schema, JsonObject *obj, JsonArray *array) { GType vtype = G_TYPE_INVALID; const gchar *s_name; const gchar *s_type; JsonNodeType type; /* Get name and type from schema */ s_name = json_object_get_string_member (schema, "name"); s_type = json_object_get_string_member (schema, "type"); if (!s_name || !s_type) return FALSE; /* Get type */ type = json_node_get_node_type (node); if (type == JSON_NODE_VALUE) vtype = json_node_get_value_type (node); /* Check type: * We check only first letter of the type string. */ switch (s_type[0]) { case 'b': /* Boolean: check type */ if (vtype != G_TYPE_BOOLEAN) return FALSE; /* Add to object / array */ if (obj || array) { gboolean v; v = json_node_get_boolean (node); if (obj) json_object_set_boolean_member (obj, s_name, v); else json_array_add_boolean_element (array, v); break; } break; case 'i': /* Integer: check type */ if (vtype != G_TYPE_INT64) return FALSE; /* Add to object / array */ if (obj || array) { gint64 v; v = json_node_get_int (node); if (obj) json_object_set_int_member (obj, s_name, v); else json_array_add_int_element (array, v); } break; case 'd': /* Double: check type */ if (vtype != G_TYPE_DOUBLE) return FALSE; /* Add to object / array */ if (obj || array) { gdouble v; v = json_node_get_double (node); if (obj) json_object_set_double_member (obj, s_name, v); else json_array_add_double_element (array, v); } break; case 's': /* String: check type */ if (vtype != G_TYPE_STRING) return FALSE; /* Add to object / array */ if (obj || array) { const gchar *v; v = json_node_get_string (node); if (obj) json_object_set_string_member (obj, s_name, v); else json_array_add_string_element (array, v); } break; case 'o': /* Object: check type */ if (type != JSON_NODE_OBJECT) return FALSE; /* Add to object / array */ if (obj || array) { JsonObject *v; v = json_node_dup_object (node); if (obj) json_object_set_object_member (obj, s_name, v); else json_array_add_object_element (array, v); } break; case 'a': /* Array: check type */ if (type != JSON_NODE_ARRAY) return FALSE; /* Add to object / array */ if (obj || array) { JsonArray *v; v = json_node_dup_array (node); if (obj) json_object_set_array_member (obj, s_name, v); else json_array_add_array_element (array, v); } break; default: return FALSE; } return TRUE; }
/** * melo_jsonrpc_register_methods: * @group: prefix of the method * @methods: an array of #MeloJSONRPCMethod * @count: the number of methods in @methods * * Register multiple JSON-RPC method named with the same prefix @group. All * final methods will be as "@group.NAME". * * Returns: 0 if all methods have been registered or the number of methods which * has not been registered. */ guint melo_jsonrpc_register_methods (const gchar *group, MeloJSONRPCMethod *methods, guint count) { JsonParser *parser; JsonObject *result; JsonArray *params; JsonNode *node; guint errors = 0, i; gboolean ret; /* Create a parser */ parser = json_parser_new (); /* Register all methods */ for (i = 0; i < count; i++) { /* Generate params schema */ if (json_parser_load_from_data (parser, methods[i].params, -1, NULL)) { /* Convert string to node */ node = json_parser_get_root (parser); /* Node params type must be an array */ if (json_node_get_node_type (node) != JSON_NODE_ARRAY) continue; /* Get array */ params = json_node_dup_array (node); } else params = NULL; /* Generate result schema */ if (json_parser_load_from_data (parser, methods[i].result, -1, NULL)) { /* Convert string to node */ node = json_parser_get_root (parser); /* Node result type must be an object */ if (json_node_get_node_type (node) != JSON_NODE_OBJECT) continue; /* Get array */ result = json_node_dup_object (node); } else result = NULL; /* Register method */ ret = melo_jsonrpc_register_method (group, methods[i].method, params, result, methods[i].callback, methods[i].user_data); /* Failed to register method */ if (!ret) { if (params) json_array_unref (params); if (result) json_object_unref (result); errors++; } } /* Release parser */ g_object_unref (parser); return errors; }