diff options
| author | Emmanuele Bassi <ebassi@gnome.org> | 2012-06-30 13:22:47 +0100 |
|---|---|---|
| committer | Emmanuele Bassi <ebassi@gnome.org> | 2012-06-30 13:22:47 +0100 |
| commit | 7bd24bd628df97d216436e03237fc27f85a6aa8b (patch) | |
| tree | c01c1abef6d0a1938c696a477801caaa4615ce04 | |
| parent | a62619788bbcc9035fb36e58308b28829f5650d3 (diff) | |
| download | json-glib-7bd24bd628df97d216436e03237fc27f85a6aa8b.tar.gz | |
Add JsonValue
Given its ECMAScript inheritance, JSON allows only four types of values:
- integer numbers
- floating point numbers
- booleans
- strings
We can efficiently represent a JSON value using a simple, reference
counted structure, that behaves similarly to GValue but without the
baggage of the whole type system.
For the time being, we should keep the whole JsonValue internal: we
already specify typed public accessors, so there's no need to complicate
the API any further.
| -rw-r--r-- | json-glib/Makefile.am | 5 | ||||
| -rw-r--r-- | json-glib/json-types-private.h | 78 | ||||
| -rw-r--r-- | json-glib/json-value.c | 216 |
3 files changed, 296 insertions, 3 deletions
diff --git a/json-glib/Makefile.am b/json-glib/Makefile.am index ee658ee..f2ee4ef 100644 --- a/json-glib/Makefile.am +++ b/json-glib/Makefile.am @@ -31,11 +31,11 @@ source_h = \ $(top_srcdir)/json-glib/json-builder.h \ $(top_srcdir)/json-glib/json-generator.h \ $(top_srcdir)/json-glib/json-gobject.h \ + $(top_srcdir)/json-glib/json-gvariant.h \ $(top_srcdir)/json-glib/json-parser.h \ $(top_srcdir)/json-glib/json-path.h \ $(top_srcdir)/json-glib/json-reader.h \ $(top_srcdir)/json-glib/json-types.h \ - $(top_srcdir)/json-glib/json-gvariant.h \ $(NULL) source_h_private = \ @@ -52,6 +52,7 @@ source_c = \ $(srcdir)/json-gboxed.c \ $(srcdir)/json-generator.c \ $(srcdir)/json-gobject.c \ + $(srcdir)/json-gvariant.c \ $(srcdir)/json-node.c \ $(srcdir)/json-object.c \ $(srcdir)/json-parser.c \ @@ -59,7 +60,7 @@ source_c = \ $(srcdir)/json-reader.c \ $(srcdir)/json-scanner.c \ $(srcdir)/json-serializable.c \ - $(srcdir)/json-gvariant.c \ + $(srcdir)/json-value.c \ $(NULL) # glib-mkenums rules diff --git a/json-glib/json-types-private.h b/json-glib/json-types-private.h index e7f73f2..8a572bc 100644 --- a/json-glib/json-types-private.h +++ b/json-glib/json-types-private.h @@ -28,6 +28,17 @@ G_BEGIN_DECLS +typedef struct _JsonValue JsonValue; + +typedef enum { + JSON_VALUE_INVALID = 0, + JSON_VALUE_INT, + JSON_VALUE_DOUBLE, + JSON_VALUE_BOOLEAN, + JSON_VALUE_STRING, + JSON_VALUE_NULL +} JsonValueType; + struct _JsonNode { /*< private >*/ @@ -42,6 +53,31 @@ struct _JsonNode JsonNode *parent; }; +#define JSON_VALUE_INIT { JSON_VALUE_INVALID, 1, { 0 } } +#define JSON_VALUE_INIT_TYPE(t) { (t), 1, { 0 } } +#define JSON_VALUE_IS_VALID(v) ((v) != NULL && (v)->type != JSON_VALUE_INVALID) +#define JSON_VALUE_HOLDS(v,t) ((v) != NULL && (v)->type == (t)) +#define JSON_VALUE_HOLDS_INT(v) (JSON_VALUE_HOLDS((v), JSON_VALUE_INT)) +#define JSON_VALUE_HOLDS_DOUBLE(v) (JSON_VALUE_HOLDS((v), JSON_VALUE_DOUBLE)) +#define JSON_VALUE_HOLDS_BOOLEAN(v) (JSON_VALUE_HOLDS((v), JSON_VALUE_BOOLEAN)) +#define JSON_VALUE_HOLDS_STRING(v) (JSON_VALUE_HOLDS((v), JSON_VALUE_STRING)) +#define JSON_VALUE_HOLDS_NULL(v) (JSON_VALUE_HOLDS((v), JSON_VALUE_NULL)) +#define JSON_VALUE_TYPE(v) (json_value_type((v))) + +struct _JsonValue +{ + JsonValueType type; + + volatile gint ref_count; + + union { + gint64 v_int; + gdouble v_double; + gboolean v_bool; + gchar *v_str; + } data; +}; + struct _JsonArray { GPtrArray *elements; @@ -59,7 +95,47 @@ struct _JsonObject volatile gint ref_count; }; -const gchar *json_node_type_get_name (JsonNodeType node_type); +G_GNUC_INTERNAL +const gchar * json_node_type_get_name (JsonNodeType node_type); +G_GNUC_INTERNAL +const gchar * json_value_type_get_name (JsonValueType value_type); + +G_GNUC_INTERNAL +GType json_value_type (const JsonValue *value); + +G_GNUC_INTERNAL +JsonValue * json_value_alloc (void); +G_GNUC_INTERNAL +JsonValue * json_value_init (JsonValue *value, + JsonValueType value_type); +G_GNUC_INTERNAL +JsonValue * json_value_ref (JsonValue *value); +G_GNUC_INTERNAL +void json_value_unref (JsonValue *value); +G_GNUC_INTERNAL +void json_value_unset (JsonValue *value); +G_GNUC_INTERNAL +void json_value_free (JsonValue *value); +G_GNUC_INTERNAL +void json_value_set_int (JsonValue *value, + gint64 v_int); +G_GNUC_INTERNAL +gint64 json_value_get_int (const JsonValue *value); +G_GNUC_INTERNAL +void json_value_set_double (JsonValue *value, + gdouble v_double); +G_GNUC_INTERNAL +gdouble json_value_get_double (const JsonValue *value); +G_GNUC_INTERNAL +void json_value_set_boolean (JsonValue *value, + gboolean v_bool); +G_GNUC_INTERNAL +gboolean json_value_get_boolean (const JsonValue *value); +G_GNUC_INTERNAL +void json_value_set_string (JsonValue *value, + const gchar *v_str); +G_GNUC_INTERNAL +const gchar * json_value_get_string (const JsonValue *value); G_END_DECLS diff --git a/json-glib/json-value.c b/json-glib/json-value.c new file mode 100644 index 0000000..7e9babd --- /dev/null +++ b/json-glib/json-value.c @@ -0,0 +1,216 @@ +/* json-value.c - JSON value container + * + * This file is part of JSON-GLib + * Copyright (C) 2012 Emmanuele Bassi <ebassi@gnome.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see <http://www.gnu.org/licenses/>. + * + * Author: + * Emmanuele Bassi <ebassi@linux.intel.com> + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <glib.h> + +#include "json-types-private.h" + +const gchar * +json_value_type_get_name (JsonValueType value_type) +{ + switch (value_type) + { + case JSON_VALUE_INVALID: + return "Unset"; + + case JSON_VALUE_INT: + return "Integer"; + + case JSON_VALUE_DOUBLE: + return "Floating Point"; + + case JSON_VALUE_BOOLEAN: + return "Boolean"; + + case JSON_VALUE_STRING: + return "String"; + + case JSON_VALUE_NULL: + return "Null"; + } + + return "Undefined"; +} + +GType +json_value_type (const JsonValue *value) +{ + switch (value->type) + { + case JSON_VALUE_INVALID: + return G_TYPE_INVALID; + + case JSON_VALUE_INT: + return G_TYPE_INT64; + + case JSON_VALUE_DOUBLE: + return G_TYPE_DOUBLE; + + case JSON_VALUE_BOOLEAN: + return G_TYPE_BOOLEAN; + + case JSON_VALUE_STRING: + return G_TYPE_STRING; + + case JSON_VALUE_NULL: + return G_TYPE_INVALID; + } + + return G_TYPE_INVALID; +} + +JsonValue * +json_value_alloc (void) +{ + JsonValue *res = g_slice_new0 (JsonValue); + + res->ref_count = 1; + + return res; +} + +JsonValue * +json_value_init (JsonValue *value, + JsonValueType value_type) +{ + g_return_val_if_fail (value != NULL, NULL); + + if (value->type != JSON_VALUE_INVALID) + json_value_unset (value); + + value->type = value_type; + + return value; +} + +JsonValue * +json_value_ref (JsonValue *value) +{ + g_return_val_if_fail (value != NULL, NULL); + + g_atomic_int_add (&value->ref_count, 1); + + return value; +} + +void +json_value_unref (JsonValue *value) +{ + g_return_if_fail (value != NULL); + + if (g_atomic_int_dec_and_test (&value->ref_count)) + json_value_free (value); +} + +void +json_value_unset (JsonValue *value) +{ + g_return_if_fail (value != NULL); + + switch (value->type) + { + case JSON_VALUE_INVALID: + break; + + case JSON_VALUE_INT: + value->data.v_int = 0; + break; + + case JSON_VALUE_DOUBLE: + value->data.v_double = 0.0; + break; + + case JSON_VALUE_BOOLEAN: + value->data.v_bool = FALSE; + break; + + case JSON_VALUE_STRING: + g_free (value->data.v_str); + value->data.v_str = NULL; + break; + + case JSON_VALUE_NULL: + break; + } +} + +void +json_value_free (JsonValue *value) +{ + if (G_LIKELY (value != NULL)) + { + json_value_unset (value); + g_slice_free (JsonValue, value); + } +} + +#define _JSON_VALUE_DEFINE_SET(Type,EType,CType,VField) \ +void \ +json_value_set_##Type (JsonValue *value, CType VField) \ +{ \ + g_return_if_fail (JSON_VALUE_IS_VALID (value)); \ + g_return_if_fail (JSON_VALUE_HOLDS (value, JSON_VALUE_##EType)); \ +\ + value->data.VField = VField; \ +\ +} + +#define _JSON_VALUE_DEFINE_GET(Type,EType,CType,VField) \ +CType \ +json_value_get_##Type (const JsonValue *value) \ +{ \ + g_return_val_if_fail (JSON_VALUE_IS_VALID (value), 0); \ + g_return_val_if_fail (JSON_VALUE_HOLDS (value, JSON_VALUE_##EType), 0); \ +\ + return value->data.VField; \ +} + +#define _JSON_VALUE_DEFINE_SET_GET(Type,EType,CType,VField) \ +_JSON_VALUE_DEFINE_SET(Type,EType,CType,VField) \ +_JSON_VALUE_DEFINE_GET(Type,EType,CType,VField) + +_JSON_VALUE_DEFINE_SET_GET(int, INT, gint64, v_int) + +_JSON_VALUE_DEFINE_SET_GET(double, DOUBLE, gdouble, v_double) + +_JSON_VALUE_DEFINE_SET_GET(boolean, BOOLEAN, gboolean, v_bool) + +void +json_value_set_string (JsonValue *value, + const gchar *v_str) +{ + g_return_if_fail (JSON_VALUE_IS_VALID (value)); + g_return_if_fail (JSON_VALUE_HOLDS_STRING (value)); + + g_free (value->data.v_str); + value->data.v_str = g_strdup (v_str); +} + +_JSON_VALUE_DEFINE_GET(string, STRING, const gchar *, v_str) + +#undef _JSON_VALUE_DEFINE_SET_GET +#undef _JSON_VALUE_DEFINE_GET +#undef _JSON_VALUE_DEFINE_SET |
