[json-glib] Add JsonReader
- From: Emmanuele Bassi <ebassi src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [json-glib] Add JsonReader
- Date: Thu, 12 Aug 2010 14:38:38 +0000 (UTC)
commit 10e5a1d38113b7b6e7c71da76ff11219baf1022d
Author: Emmanuele Bassi <ebassi linux intel com>
Date: Thu Aug 12 15:29:41 2010 +0100
Add JsonReader
JsonReader is a simple, cursor-based API for parsing a JSON DOM. It is
similar, in spirit, to the XmlReader API provided by various platforms
and XML parsing libraries.
.gitignore | 1 +
json-glib/Makefile.am | 2 +
json-glib/json-glib.h | 3 +
json-glib/json-reader.c | 779 +++++++++++++++++++++++++++++++++++++++++
json-glib/json-reader.h | 142 ++++++++
json-glib/tests/Makefile.am | 10 +-
json-glib/tests/reader-test.c | 101 ++++++
7 files changed, 1035 insertions(+), 3 deletions(-)
---
diff --git a/.gitignore b/.gitignore
index 1119e48..b7fed56 100644
--- a/.gitignore
+++ b/.gitignore
@@ -41,6 +41,7 @@ json-glib.pc
/json-glib/tests/object-test
/json-glib/tests/node-test
/json-glib/tests/parser-test
+/json-glib/tests/reader-test
libtool
ltmain.sh
missing
diff --git a/json-glib/Makefile.am b/json-glib/Makefile.am
index e4d24e1..6340cbf 100644
--- a/json-glib/Makefile.am
+++ b/json-glib/Makefile.am
@@ -34,6 +34,7 @@ source_h = \
$(top_srcdir)/json-glib/json-generator.h \
$(top_srcdir)/json-glib/json-gobject.h \
$(top_srcdir)/json-glib/json-parser.h \
+ $(top_srcdir)/json-glib/json-reader.h \
$(top_srcdir)/json-glib/json-types.h \
$(NULL)
@@ -54,6 +55,7 @@ source_c = \
$(srcdir)/json-node.c \
$(srcdir)/json-object.c \
$(srcdir)/json-parser.c \
+ $(srcdir)/json-reader.c \
$(srcdir)/json-scanner.c \
$(srcdir)/json-serializable.c \
$(NULL)
diff --git a/json-glib/json-glib.h b/json-glib/json-glib.h
index 9c3d6f0..7a4d783 100644
--- a/json-glib/json-glib.h
+++ b/json-glib/json-glib.h
@@ -27,10 +27,13 @@
#define __JSON_GLIB_INSIDE__
#include <json-glib/json-types.h>
+
#include <json-glib/json-builder.h>
#include <json-glib/json-generator.h>
#include <json-glib/json-parser.h>
+#include <json-glib/json-reader.h>
#include <json-glib/json-version.h>
+
#include <json-glib/json-enum-types.h>
#include <json-glib/json-gobject.h>
diff --git a/json-glib/json-reader.c b/json-glib/json-reader.c
new file mode 100644
index 0000000..adc859e
--- /dev/null
+++ b/json-glib/json-reader.c
@@ -0,0 +1,779 @@
+/* json-reader.h - JSON cursor parser
+ *
+ * This file is part of JSON-GLib
+ * Copyright (C) 2010 Intel Corp.
+ *
+ * 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>
+ */
+
+/**
+ * SECTION:json-reader
+ * @Title: JsonReader
+ * @short_description: A cursor-based parser
+ *
+ * #JsonReader provides a simple, cursor-based API for parsing a JSON DOM. It
+ * is similar, in spirit, to the XML Reader API.
+ *
+ * In case of error, #JsonReader will be set in an error state; all subsequent
+ * calls will simply be ignored until a function that resets the error state is
+ * called, e.g.:
+ *
+ * |[
+ * /* ask for the 7th element; if the element does not exist, the
+ * * reader will be put in an error state
+ * */
+ * json_reader_read_element (reader, 6);
+ *
+ * /* in case of error, this will return NULL, otherwise it will
+ * * return the value of the element
+ * */
+ * str = json_reader_get_value_string (value);
+ *
+ * /* this function resets the error state if any was set */
+ * json_reader_end_element (reader);
+ * ]|
+ *
+ * If you want to detect the error state as soon as possible, you can use
+ * json_reader_get_error():
+ *
+ * |[
+ * /* like the example above, but in this case we print out the
+ * * error immediately
+ * */
+ * if (!json_reader_read_element (reader, 6))
+ * {
+ * const GError *error = json_reader_get_error (error);
+ * g_print ("Unable to read the element: %s", error->message);
+ * }
+ * ]|
+ *
+ * #JsonReader is available since JSON-GLib 0.12.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+
+#include "json-reader.h"
+
+#include "json-types-private.h"
+
+#include "json-debug.h"
+#include "json-parser.h"
+
+#define json_reader_return_if_error_set(r) G_STMT_START { \
+ if (((JsonReader *) (r))->priv->error != NULL) \
+ return; } G_STMT_END
+
+#define json_reader_return_val_if_error_set(r,v) G_STMT_START { \
+ if (((JsonReader *) (r))->priv->error != NULL) \
+ return (v); } G_STMT_END
+
+struct _JsonReaderPrivate
+{
+ JsonParser *parser;
+
+ JsonNode *root;
+
+ JsonNode *current_node;
+ JsonNode *previous_node;
+
+ GError *error;
+};
+
+G_DEFINE_TYPE (JsonReader, json_reader, G_TYPE_OBJECT);
+
+static void
+json_reader_dispose (GObject *gobject)
+{
+ JsonReaderPrivate *priv = JSON_READER (gobject)->priv;
+
+ if (priv->parser != NULL)
+ {
+ g_object_unref (priv->parser);
+
+ priv->parser = NULL;
+ priv->root = NULL;
+ priv->current_node = NULL;
+ priv->previous_node = NULL;
+ }
+
+ if (priv->error != NULL)
+ g_clear_error (&priv->error);
+
+ G_OBJECT_CLASS (json_reader_parent_class)->dispose (gobject);
+}
+
+static void
+json_reader_class_init (JsonReaderClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ g_type_class_add_private (klass, sizeof (JsonReaderPrivate));
+
+ gobject_class->dispose = json_reader_dispose;
+}
+
+static void
+json_reader_init (JsonReader *self)
+{
+ self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, JSON_TYPE_READER,
+ JsonReaderPrivate);
+
+ self->priv->parser = json_parser_new ();
+}
+
+GQuark
+json_reader_error_quark (void)
+{
+ return g_quark_from_static_string ("json-reader-error");
+}
+
+/**
+ * json_reader_new:
+ *
+ * Creates a new #JsonReader instance
+ *
+ * Return value: the newly created #JsonReader. Use g_object_unref() to
+ * release the allocated resources when done
+ *
+ * Since: 0.12
+ */
+JsonReader *
+json_reader_new (void)
+{
+ return g_object_new (JSON_TYPE_READER, NULL);
+}
+
+/**
+ * json_reader_load_from_data:
+ * @reader: a #JsonReader
+ * @data: the data to be parsed
+ * @length: the length of @data, or -1
+ * @error: return location for a #GError, or %NULL
+ *
+ * Loads a JSON string and parses it.
+ *
+ * If @reader already contained a JSON DOM, it will be reset.
+ *
+ * Return value: %TRUE if the data was successfully parsed, and %FALSE
+ * otherwise. In case of failure, the #GError will be set accordingly
+ *
+ * Since: 0.12
+ */
+gboolean
+json_reader_load_from_data (JsonReader *reader,
+ const gchar *data,
+ gssize length,
+ GError **error)
+{
+ JsonReaderPrivate *priv;
+ GError *internal_error;
+ gboolean retval;
+
+ g_return_val_if_fail (JSON_IS_READER (reader), FALSE);
+
+ priv = reader->priv;
+
+ if (priv->root != NULL)
+ {
+ priv->root = NULL;
+
+ priv->current_node = NULL;
+ priv->previous_node = NULL;
+ }
+
+ if (priv->error != NULL)
+ g_clear_error (&priv->error);
+
+ internal_error = NULL;
+ retval = json_parser_load_from_data (priv->parser, data, length, &internal_error);
+ if (retval)
+ {
+ priv->root = json_parser_get_root (priv->parser);
+
+ priv->current_node = priv->root;
+ priv->previous_node = NULL;
+
+ priv->error = NULL;
+ }
+ else
+ {
+ priv->error = g_error_copy (internal_error);
+ g_propagate_error (error, internal_error);
+ }
+
+ return retval;
+}
+
+/*
+ * json_reader_unset_error:
+ * @reader: a #JsonReader
+ *
+ * Unsets the error state of @reader, if set
+ */
+static inline void
+json_reader_unset_error (JsonReader *reader)
+{
+ if (reader->priv->error != NULL)
+ g_clear_error (&(reader->priv->error));
+}
+
+/*
+ * json_reader_ser_error:
+ * @reader: a #JsonReader
+ * @error_code: the #JsonReaderError code for the error
+ * @error_fmt: format string
+ * @Varargs: list of arguments for the @error_fmt string
+ *
+ * Sets the error state of @reader using the given error code
+ * and string
+ *
+ * Return value: %FALSE, to be used to return immediately from
+ * the caller function
+ */
+static gboolean
+json_reader_set_error (JsonReader *reader,
+ JsonReaderError error_code,
+ const gchar *error_fmt,
+ ...)
+{
+ JsonReaderPrivate *priv = reader->priv;
+ va_list args;
+ gchar *error_msg;
+
+ if (priv->error != NULL)
+ g_clear_error (&priv->error);
+
+ va_start (args, error_fmt);
+ error_msg = g_strdup_vprintf (error_fmt, args);
+ va_end (args);
+
+ g_set_error_literal (&priv->error, JSON_READER_ERROR,
+ error_code,
+ error_msg);
+
+ g_free (error_msg);
+
+ return FALSE;
+}
+
+/**
+ * json_reader_get_error:
+ * @reader: a #JsonReader
+ *
+ * Retrieves the #GError currently set on @reader, if the #JsonReader
+ * is in error state
+ *
+ * Return value: (transfer none): the pointer to the error, or %NULL
+ *
+ * Since: 0.12
+ */
+G_CONST_RETURN GError *
+json_reader_get_error (JsonReader *reader)
+{
+ g_return_val_if_fail (JSON_IS_READER (reader), FALSE);
+
+ return reader->priv->error;
+}
+
+/**
+ * json_reader_is_array:
+ * @reader: a #JsonReader
+ *
+ * Checks whether the @reader is currently on an array
+ *
+ * Return value: %TRUE if the #JsonReader is on an array, and %FALSE
+ * otherwise
+ *
+ * Since: 0.12
+ */
+gboolean
+json_reader_is_array (JsonReader *reader)
+{
+ g_return_val_if_fail (JSON_IS_READER (reader), FALSE);
+ json_reader_return_val_if_error_set (reader, FALSE);
+
+ if (reader->priv->current_node == NULL)
+ return FALSE;
+
+ return JSON_NODE_HOLDS_ARRAY (reader->priv->current_node);
+}
+
+/**
+ * json_reader_is_object:
+ * @reader: a #JsonReader
+ *
+ * Checks whether the @reader is currently on an object
+ *
+ * Return value: %TRUE if the #JsonReader is on an object, and %FALSE
+ * otherwise
+ *
+ * Since: 0.12
+ */
+gboolean
+json_reader_is_object (JsonReader *reader)
+{
+ g_return_val_if_fail (JSON_IS_READER (reader), FALSE);
+ json_reader_return_val_if_error_set (reader, FALSE);
+
+ if (reader->priv->current_node == NULL)
+ return FALSE;
+
+ return JSON_NODE_HOLDS_OBJECT (reader->priv->current_node);
+}
+
+/**
+ * json_reader_is_value:
+ * @reader: a #JsonReader
+ *
+ * Checks whether the @reader is currently on a value
+ *
+ * Return value: %TRUE if the #JsonReader is on a value, and %FALSE
+ * otherwise
+ *
+ * Since: 0.12
+ */
+gboolean
+json_reader_is_value (JsonReader *reader)
+{
+ g_return_val_if_fail (JSON_IS_READER (reader), FALSE);
+ json_reader_return_val_if_error_set (reader, FALSE);
+
+ if (reader->priv->current_node == NULL)
+ return FALSE;
+
+ return JSON_NODE_HOLDS_VALUE (reader->priv->current_node);
+}
+
+/**
+ * json_reader_read_element:
+ * @reader: a #JsonReader
+ * @index_: the index of the element
+ *
+ * Advances the cursor of @reader to the element @index_ of array at the
+ * current position.
+ *
+ * You can use the json_reader_get_value* family of functions to retrieve
+ * the value of the element; for instance:
+ *
+ * |[
+ * json_reader_read_element (reader, 0);
+ * int_value = json_reader_get_value_int (reader);
+ * ]|
+ *
+ * After reading the value, json_reader_end_element() should be called to
+ * reposition the cursor inside the #JsonReader, e.g.:
+ *
+ * |[
+ * json_reader_read_element (reader, 1);
+ * str_value = json_reader_get_value_string (reader);
+ * json_reader_end_element (reader);
+ *
+ * json_reader_read_element (reader, 2);
+ * str_value = json_reader_get_value_string (reader);
+ * json_reader_end_element (reader);
+ * ]|
+ *
+ * If @reader is not currently on an array, or if the @index_ is bigger than
+ * the size of the array, the #JsonReader will be put in an error state until
+ * json_reader_end_element() is called.
+ *
+ * Return value: %TRUE on success, and %FALSE otherwise
+ *
+ * Since: 0.12
+ */
+gboolean
+json_reader_read_element (JsonReader *reader,
+ guint index_)
+{
+ JsonReaderPrivate *priv;
+ JsonArray *array;
+
+ g_return_val_if_fail (JSON_READER (reader), FALSE);
+ json_reader_return_val_if_error_set (reader, FALSE);
+
+ priv = reader->priv;
+
+ if (priv->current_node == NULL)
+ priv->current_node = priv->root;
+
+ if (!JSON_NODE_HOLDS_ARRAY (priv->current_node))
+ return json_reader_set_error (reader, JSON_READER_ERROR_NO_ARRAY,
+ "The current node is of type '%s', but "
+ "an array was expected.",
+ json_node_type_name (priv->current_node));
+
+ array = json_node_get_array (priv->current_node);
+ if (index_ >= json_array_get_length (array))
+ return json_reader_set_error (reader, JSON_READER_ERROR_INVALID_INDEX,
+ "The index '%d' is greater than the size "
+ "of the array at the current position.",
+ index_);
+
+ priv->previous_node = priv->current_node;
+ priv->current_node = json_array_get_element (array, index_);
+
+ return TRUE;
+}
+
+/**
+ * json_reader_end_element:
+ * @reader: a #JsonReader
+ *
+ * Moves the cursor back to the previous node after being positioned
+ * inside an array
+ *
+ * This function resets the error state of @reader, if any was set
+ *
+ * Since: 0.12
+ */
+void
+json_reader_end_element (JsonReader *reader)
+{
+ JsonReaderPrivate *priv;
+ JsonNode *tmp;
+
+ g_return_if_fail (JSON_IS_READER (reader));
+
+ json_reader_unset_error (reader);
+
+ priv = reader->priv;
+
+ if (priv->previous_node != NULL)
+ tmp = json_node_get_parent (priv->previous_node);
+ else
+ tmp = NULL;
+
+ priv->current_node = priv->previous_node;
+ priv->previous_node = tmp;
+}
+
+/**
+ * json_reader_count_elements:
+ * @reader: a #JsonReader
+ *
+ * Counts the elements of the current position, if @reader is
+ * positioned on an array
+ *
+ * Return value: the number of elements, or -1. In case of failure
+ * the #JsonReader is set in an error state
+ *
+ * Since: 0.12
+ */
+gint
+json_reader_count_elements (JsonReader *reader)
+{
+ JsonReaderPrivate *priv;
+
+ g_return_val_if_fail (JSON_IS_READER (reader), -1);
+
+ priv = reader->priv;
+
+ if (priv->current_node == NULL)
+ return -1;
+
+ if (!JSON_NODE_HOLDS_ARRAY (priv->current_node))
+ return -1;
+
+ return json_array_get_length (json_node_get_array (priv->current_node));
+}
+
+/**
+ * json_reader_read_member:
+ * @reader: a #JsonReader
+ * @member_name: the name of the member to read
+ *
+ * Advances the cursor of @reader to the @member_name of the object at the
+ * current position.
+ *
+ * You can use the json_reader_get_value* family of functions to retrieve
+ * the value of the member; for instance:
+ *
+ * |[
+ * json_reader_read_member (reader, "width");
+ * width = json_reader_get_value_int (reader);
+ * ]|
+ *
+ * After reading the value, json_reader_end_member() should be called to
+ * reposition the cursor inside the #JsonReader, e.g.:
+ *
+ * |[
+ * json_reader_read_member (reader, "author");
+ * author = json_reader_get_value_string (reader);
+ * json_reader_end_element (reader);
+ *
+ * json_reader_read_element (reader, "title");
+ * title = json_reader_get_value_string (reader);
+ * json_reader_end_element (reader);
+ * ]|
+ *
+ * If @reader is not currently on an object, or if the @member_name is not
+ * defined in the object, the #JsonReader will be put in an error state until
+ * json_reader_end_member() is called.
+ *
+ * Return value: %TRUE on success, and %FALSE otherwise
+ *
+ * Since: 0.12
+ */
+gboolean
+json_reader_read_member (JsonReader *reader,
+ const gchar *member_name)
+{
+ JsonReaderPrivate *priv;
+ JsonObject *object;
+
+ g_return_val_if_fail (JSON_READER (reader), FALSE);
+ g_return_val_if_fail (member_name != NULL, FALSE);
+ json_reader_return_val_if_error_set (reader, FALSE);
+
+ priv = reader->priv;
+
+ if (priv->current_node == NULL)
+ priv->current_node = priv->root;
+
+ if (!JSON_NODE_HOLDS_OBJECT (priv->current_node))
+ return json_reader_set_error (reader, JSON_READER_ERROR_NO_OBJECT,
+ "The current node is of type '%s', but "
+ "an object was expected.",
+ json_node_type_name (priv->current_node));
+
+ object = json_node_get_object (priv->current_node);
+ if (!json_object_has_member (object, member_name))
+ return json_reader_set_error (reader, JSON_READER_ERROR_INVALID_MEMBER,
+ "The member '%s' is not defined in the "
+ "object at the current position.",
+ member_name);
+
+ priv->previous_node = priv->current_node;
+ priv->current_node = json_object_get_member (object, member_name);
+
+ return TRUE;
+}
+
+/**
+ * json_reader_end_member:
+ * @reader: a #JsonReader
+ *
+ * Moves the cursor back to the previous node after being positioned
+ * inside an object
+ *
+ * This function resets the error state of @reader, if any was set
+ *
+ * Since: 0.12
+ */
+void
+json_reader_end_member (JsonReader *reader)
+{
+ JsonReaderPrivate *priv;
+ JsonNode *tmp;
+
+ g_return_if_fail (JSON_IS_READER (reader));
+
+ json_reader_unset_error (reader);
+
+ priv = reader->priv;
+
+ if (priv->previous_node != NULL)
+ tmp = json_node_get_parent (priv->previous_node);
+ else
+ tmp = NULL;
+
+ priv->current_node = priv->previous_node;
+ priv->previous_node = tmp;
+}
+
+/**
+ * json_reader_count_members:
+ * @reader: a #JsonReader
+ *
+ * Counts the members of the current position, if @reader is
+ * positioned on an object
+ *
+ * Return value: the number of members, or -1. In case of failure
+ * the #JsonReader is set in an error state
+ *
+ * Since: 0.12
+ */
+gint
+json_reader_count_members (JsonReader *reader)
+{
+ JsonReaderPrivate *priv;
+
+ g_return_val_if_fail (JSON_IS_READER (reader), -1);
+
+ priv = reader->priv;
+
+ if (priv->current_node == NULL)
+ return -1;
+
+ if (!JSON_NODE_HOLDS_OBJECT (priv->current_node))
+ return -1;
+
+ return json_object_get_size (json_node_get_object (priv->current_node));
+}
+
+/**
+ * json_reader_get_value:
+ * @reader: a #JsonReader
+ *
+ * Retrieves the #JsonNode of the current position of @reader
+ *
+ * Return value: (transfer none): a #JsonNode, or %NULL. The returned node
+ * is owned by the #JsonReader and it should not be modified or freed
+ * directly
+ *
+ * Since: 0.12
+ */
+JsonNode *
+json_reader_get_value (JsonReader *reader)
+{
+ g_return_val_if_fail (JSON_IS_READER (reader), NULL);
+ json_reader_return_val_if_error_set (reader, NULL);
+
+ if (reader->priv->current_node == NULL)
+ return NULL;
+
+ if (!JSON_NODE_HOLDS_VALUE (reader->priv->current_node))
+ return NULL;
+
+ return reader->priv->current_node;
+}
+
+/**
+ * json_reader_get_value_int:
+ * @reader: a #JsonReader
+ *
+ * Retrieves the integer value of the current position of @reader
+ *
+ * Return value: the integer value
+ *
+ * Since: 0.12
+ */
+gint64
+json_reader_get_value_int (JsonReader *reader)
+{
+ g_return_val_if_fail (JSON_IS_READER (reader), 0);
+ json_reader_return_val_if_error_set (reader, 0);
+
+ if (reader->priv->current_node == NULL)
+ return 0;
+
+ if (!JSON_NODE_HOLDS_VALUE (reader->priv->current_node))
+ return 0;
+
+ return json_node_get_int (reader->priv->current_node);
+}
+
+/**
+ * json_reader_get_value_double:
+ * @reader: a #JsonReader
+ *
+ * Retrieves the floating point value of the current position of @reader
+ *
+ * Return value: the floating point value
+ *
+ * Since: 0.12
+ */
+gdouble
+json_reader_get_value_double (JsonReader *reader)
+{
+ g_return_val_if_fail (JSON_IS_READER (reader), 0.0);
+ json_reader_return_val_if_error_set (reader, 0.0);
+
+ if (reader->priv->current_node == NULL)
+ return 0.0;
+
+ if (!JSON_NODE_HOLDS_VALUE (reader->priv->current_node))
+ return 0.0;
+
+ return json_node_get_double (reader->priv->current_node);
+}
+
+/**
+ * json_reader_get_value_string:
+ * @reader: a #JsonReader
+ *
+ * Retrieves the string value of the current position of @reader
+ *
+ * Return value: the string value
+ *
+ * Since: 0.12
+ */
+G_CONST_RETURN gchar *
+json_reader_get_value_string (JsonReader *reader)
+{
+ g_return_val_if_fail (JSON_IS_READER (reader), NULL);
+ json_reader_return_val_if_error_set (reader, NULL);
+
+ if (reader->priv->current_node == NULL)
+ return NULL;
+
+ if (!JSON_NODE_HOLDS_VALUE (reader->priv->current_node))
+ return NULL;
+
+ return json_node_get_string (reader->priv->current_node);
+}
+
+/**
+ * json_reader_get_value_boolean:
+ * @reader: a #JsonReader
+ *
+ * Retrieves the boolean value of the current position of @reader
+ *
+ * Return value: the boolean value
+ *
+ * Since: 0.12
+ */
+gboolean
+json_reader_get_value_boolean (JsonReader *reader)
+{
+ g_return_val_if_fail (JSON_IS_READER (reader), FALSE);
+ json_reader_return_val_if_error_set (reader, FALSE);
+
+ if (reader->priv->current_node == NULL)
+ return FALSE;
+
+ if (!JSON_NODE_HOLDS_VALUE (reader->priv->current_node))
+ return FALSE;
+
+ return json_node_get_boolean (reader->priv->current_node);
+}
+
+/**
+ * json_reader_get_value_null:
+ * @reader: a #JsonReader
+ *
+ * Checks whether the value of the current position of @reader is 'null'
+ *
+ * Return value: %TRUE if 'null' is set, and %FALSE otherwise
+ *
+ * Since: 0.12
+ */
+gboolean
+json_reader_get_value_null (JsonReader *reader)
+{
+ g_return_val_if_fail (JSON_IS_READER (reader), FALSE);
+ json_reader_return_val_if_error_set (reader, FALSE);
+
+ if (reader->priv->current_node == NULL)
+ return FALSE;
+
+ return JSON_NODE_HOLDS_NULL (reader->priv->current_node);
+}
diff --git a/json-glib/json-reader.h b/json-glib/json-reader.h
new file mode 100644
index 0000000..a4fb239
--- /dev/null
+++ b/json-glib/json-reader.h
@@ -0,0 +1,142 @@
+/* json-reader.h - JSON cursor parser
+ *
+ * This file is part of JSON-GLib
+ * Copyright (C) 2010 Intel Corp.
+ *
+ * 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>
+ */
+
+#if !defined(__JSON_GLIB_INSIDE__) && !defined(JSON_COMPILATION)
+#error "Only <json-glib/json-glib.h> can be included directly."
+#endif
+
+#ifndef __JSON_READER_H__
+#define __JSON_READER_H__
+
+#include <json-glib/json-types.h>
+
+G_BEGIN_DECLS
+
+#define JSON_TYPE_READER (json_reader_get_type ())
+#define JSON_READER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), JSON_TYPE_READER, JsonReader))
+#define JSON_IS_READER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), JSON_TYPE_READER))
+#define JSON_READER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), JSON_TYPE_READER, JsonReaderClass))
+#define JSON_IS_READER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), JSON_TYPE_READER))
+#define JSON_READER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), JSON_TYPE_READER, JsonReaderClass))
+
+/**
+ * JSON_READER_ERROR:
+ *
+ * Error domain for #JsonReader errors
+ *
+ * Since: 0.12
+ */
+#define JSON_READER_ERROR (json_reader_error_quark ())
+
+typedef struct _JsonReader JsonReader;
+typedef struct _JsonReaderPrivate JsonReaderPrivate;
+typedef struct _JsonReaderClass JsonReaderClass;
+
+/**
+ * JsonReaderError:
+ * @JSON_READER_ERROR_NO_ARRAY: No array found at the current position
+ * @JSON_READER_ERROR_INVALID_INDEX: Index out of bounds
+ * @JSON_READER_ERROR_NO_OBJECT: No object found at the current position
+ * @JSON_READER_ERROR_INVALID_MEMBER: Member not found
+ *
+ * Error codes enumeration for #JsonReader errors
+ *
+ * Since: 0.12
+ */
+typedef enum {
+ JSON_READER_ERROR_NO_ARRAY,
+ JSON_READER_ERROR_INVALID_INDEX,
+ JSON_READER_ERROR_NO_OBJECT,
+ JSON_READER_ERROR_INVALID_MEMBER
+} JsonReaderError;
+
+/**
+ * JsonReader:
+ *
+ * The <structname>JsonReader</structname> structure contains only
+ * private data and should only be accessed using the provided API
+ *
+ * Since: 0.12
+ */
+struct _JsonReader
+{
+ /*< private >*/
+ GObject parent_instance;
+
+ JsonReaderPrivate *priv;
+};
+
+/**
+ * JsonReaderClass:
+ *
+ * The <structname>JsonReaderClass</structname> structure contains only
+ * private data
+ *
+ * Since: 0.12
+ */
+struct _JsonReaderClass
+{
+ /*< private >*/
+ GObjectClass parent_class;
+
+ void (*_json_padding0) (void);
+ void (*_json_padding1) (void);
+ void (*_json_padding2) (void);
+ void (*_json_padding3) (void);
+ void (*_json_padding4) (void);
+};
+
+GQuark json_reader_error_quark (void);
+GType json_reader_get_type (void) G_GNUC_CONST;
+
+JsonReader * json_reader_new (void);
+
+gboolean json_reader_load_from_data (JsonReader *reader,
+ const gchar *data,
+ gssize length,
+ GError **error);
+
+G_CONST_RETURN GError *json_reader_get_error (JsonReader *reader);
+
+gboolean json_reader_is_array (JsonReader *reader);
+gboolean json_reader_read_element (JsonReader *reader,
+ guint index_);
+void json_reader_end_element (JsonReader *reader);
+gint json_reader_count_elements (JsonReader *reader);
+
+gboolean json_reader_is_object (JsonReader *reader);
+gboolean json_reader_read_member (JsonReader *reader,
+ const gchar *member_name);
+void json_reader_end_member (JsonReader *reader);
+gint json_reader_count_members (JsonReader *reader);
+
+gboolean json_reader_is_value (JsonReader *reader);
+JsonNode * json_reader_get_value (JsonReader *reader);
+gint64 json_reader_get_value_int (JsonReader *reader);
+gdouble json_reader_get_value_double (JsonReader *reader);
+G_CONST_RETURN gchar * json_reader_get_value_string (JsonReader *reader);
+gboolean json_reader_get_value_boolean (JsonReader *reader);
+gboolean json_reader_get_value_null (JsonReader *reader);
+
+G_END_DECLS
+
+#endif /* __JSON_READER_H__ */
diff --git a/json-glib/tests/Makefile.am b/json-glib/tests/Makefile.am
index 917b0de..74b7ba0 100644
--- a/json-glib/tests/Makefile.am
+++ b/json-glib/tests/Makefile.am
@@ -37,6 +37,10 @@ TEST_PROGS += generator-test
generator_test_SOURCES = generator-test.c
generator_test_LDADD = $(progs_ldadd)
-TEST_PROGS += builder-test
-builder_test_SOURCES = builder-test.c
-builder_test_LDADD = $(progs_ldadd)
+TEST_PROGS += builder-test
+builder_test_SOURCES = builder-test.c
+builder_test_LDADD = $(progs_ldadd)
+
+TEST_PROGS += reader-test
+reader_test_SOURCES = reader-test.c
+reader_test_LDADD = $(progs_ldadd)
diff --git a/json-glib/tests/reader-test.c b/json-glib/tests/reader-test.c
new file mode 100644
index 0000000..ebd5381
--- /dev/null
+++ b/json-glib/tests/reader-test.c
@@ -0,0 +1,101 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <glib.h>
+
+#include <json-glib/json-glib.h>
+
+static const gchar *test_base_array_data =
+"[ 0, true, null, \"foo\", 3.14, [ false ], { \"bar\" : 42 } ]";
+
+static const gchar *test_base_object_data =
+"{ \"text\" : \"hello, world!\", \"foo\" : \"bar\", \"blah\" : 47 }";
+
+static void
+test_base_object (void)
+{
+ JsonReader *reader = json_reader_new ();
+ GError *error = NULL;
+
+ json_reader_load_from_data (reader, test_base_object_data, -1, &error);
+ g_assert (error == NULL);
+
+ g_assert (json_reader_is_object (reader));
+ g_assert_cmpint (json_reader_count_members (reader), ==, 3);
+
+ g_assert (json_reader_read_member (reader, "foo"));
+ g_assert (json_reader_is_value (reader));
+ g_assert_cmpstr (json_reader_get_value_string (reader), ==, "bar");
+ json_reader_end_member (reader);
+
+ g_assert (!json_reader_read_member (reader, "bar"));
+ g_assert (json_reader_get_error (reader) != NULL);
+ g_assert_error ((GError *) json_reader_get_error (reader),
+ JSON_READER_ERROR,
+ JSON_READER_ERROR_INVALID_MEMBER);
+ json_reader_end_member (reader);
+ g_assert (json_reader_get_error (reader) == NULL);
+
+ g_object_unref (reader);
+}
+
+static void
+test_base_array (void)
+{
+ JsonReader *reader = json_reader_new ();
+ GError *error = NULL;
+
+ json_reader_load_from_data (reader, test_base_array_data, -1, &error);
+ g_assert (error == NULL);
+
+ g_assert (json_reader_is_array (reader));
+ g_assert_cmpint (json_reader_count_elements (reader), ==, 7);
+
+ json_reader_read_element (reader, 0);
+ g_assert (json_reader_is_value (reader));
+ g_assert_cmpint (json_reader_get_value_int (reader), ==, 0);
+ json_reader_end_element (reader);
+
+ json_reader_read_element (reader, 3);
+ g_assert (json_reader_is_value (reader));
+ g_assert_cmpstr (json_reader_get_value_string (reader), ==, "foo");
+ json_reader_end_element (reader);
+
+ json_reader_read_element (reader, 5);
+ g_assert (!json_reader_is_value (reader));
+ g_assert (json_reader_is_array (reader));
+ json_reader_end_element (reader);
+
+ json_reader_read_element (reader, 6);
+ g_assert (json_reader_is_object (reader));
+
+ json_reader_read_member (reader, "bar");
+ g_assert (json_reader_is_value (reader));
+ g_assert_cmpint (json_reader_get_value_int (reader), ==, 42);
+ json_reader_end_member (reader);
+
+ json_reader_end_element (reader);
+
+ g_assert (!json_reader_read_element (reader, 7));
+ g_assert_error ((GError *) json_reader_get_error (reader),
+ JSON_READER_ERROR,
+ JSON_READER_ERROR_INVALID_INDEX);
+ json_reader_end_element (reader);
+ g_assert (json_reader_get_error (reader) == NULL);
+
+ g_object_unref (reader);
+}
+
+int
+main (int argc,
+ char *argv[])
+{
+ g_type_init ();
+ g_test_init (&argc, &argv, NULL);
+ g_test_bug_base ("http://bugzilla.gnome.org/show_bug.cgi?id=");
+
+ g_test_add_func ("/reader/base-array", test_base_array);
+ g_test_add_func ("/reader/base-object", test_base_object);
+
+ return g_test_run ();
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]