[json-glib] parser: Return specific error codes



commit 9ce82f8052290f3956c3d80c8739c214da314d42
Author: Emmanuele Bassi <ebassi linux intel com>
Date:   Fri Mar 19 11:04:00 2010 +0000

    parser: Return specific error codes
    
    The JsonScanner error reporting mechanism, which is basically
    GScanner's, sucks beyond belief. In order to report an error code we
    need to store it inside the JsonParser private structure and then use it
    when creating the GError inside the error handler.
    
    This, frankly, is quite stupid.

 json-glib/json-parser.c       |   49 ++++++++++++++++++++++++++++++++--------
 json-glib/json-parser.h       |    8 ++++++
 json-glib/tests/parser-test.c |   18 +++++++-------
 3 files changed, 56 insertions(+), 19 deletions(-)
---
diff --git a/json-glib/json-parser.c b/json-glib/json-parser.c
index 4e22572..8df897e 100644
--- a/json-glib/json-parser.c
+++ b/json-glib/json-parser.c
@@ -1,8 +1,9 @@
 /* json-parser.c - JSON streams parser
  * 
  * This file is part of JSON-GLib
- * Copyright (C) 2007  OpenedHand Ltd.
- * Copyright (C) 2009  Intel Corp.
+ *
+ * Copyright © 2007, 2008, 2009 OpenedHand Ltd
+ * Copyright © 2009, 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
@@ -48,8 +49,7 @@ json_parser_error_quark (void)
   return g_quark_from_static_string ("json-parser-error");
 }
 
-#define JSON_PARSER_GET_PRIVATE(obj) \
-        (G_TYPE_INSTANCE_GET_PRIVATE ((obj), JSON_TYPE_PARSER, JsonParserPrivate))
+#define JSON_PARSER_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), JSON_TYPE_PARSER, JsonParserPrivate))
 
 struct _JsonParserPrivate
 {
@@ -58,6 +58,7 @@ struct _JsonParserPrivate
 
   JsonScanner *scanner;
 
+  JsonParserError error_code;
   GError *last_error;
 
   gchar *variable_name;
@@ -325,6 +326,9 @@ json_parser_init (JsonParser *parser)
   priv->root = NULL;
   priv->current_node = NULL;
 
+  priv->error_code = JSON_PARSER_ERROR_PARSE;
+  priv->last_error = NULL;
+
   priv->has_assignment = FALSE;
   priv->variable_name = NULL;
 
@@ -338,7 +342,8 @@ json_parse_value (JsonParser   *parser,
                   guint         token,
                   JsonNode    **node)
 {
-  JsonNode *current_node = parser->priv->current_node;
+  JsonParserPrivate *priv = parser->priv;
+  JsonNode *current_node = priv->current_node;
   gboolean is_negative = FALSE;
 
   if (token == '-')
@@ -385,11 +390,14 @@ json_parse_value (JsonParser   *parser,
     case JSON_TOKEN_TRUE:
     case JSON_TOKEN_FALSE:
       *node = json_node_new (JSON_NODE_VALUE);
+      JSON_NOTE (PARSER, "node: '%s'",
+                 JSON_TOKEN_TRUE ? "<true>" : "<false>");
       json_node_set_boolean (*node, token == JSON_TOKEN_TRUE ? TRUE : FALSE);
       break;
 
     case JSON_TOKEN_NULL:
       *node = json_node_new (JSON_NODE_NULL);
+      JSON_NOTE (PARSER, "node: <null>");
       break;
 
     default:
@@ -404,7 +412,10 @@ json_parse_value (JsonParser   *parser,
         else if (cur_type == JSON_NODE_OBJECT)
           return G_TOKEN_RIGHT_CURLY;
         else
-          return G_TOKEN_SYMBOL;
+          {
+            priv->error_code = JSON_PARSER_ERROR_INVALID_BAREWORD;
+            return G_TOKEN_SYMBOL;
+          }
       }
     }
 
@@ -475,7 +486,11 @@ json_parse_array (JsonParser  *parser,
               token = json_scanner_get_next_token (scanner);
 
               if (token == G_TOKEN_RIGHT_BRACE)
-                return G_TOKEN_SYMBOL;
+                {
+                  json_array_unref (array);
+                  priv->error_code = JSON_PARSER_ERROR_TRAILING_COMMA;
+                  return G_TOKEN_SYMBOL;
+                }
 
               continue;
             }
@@ -523,7 +538,11 @@ json_parse_array (JsonParser  *parser,
               token = json_scanner_get_next_token (scanner);
 
               if (token == G_TOKEN_RIGHT_BRACE)
-                return G_TOKEN_SYMBOL;
+                {
+                  json_array_unref (array);
+                  priv->error_code = JSON_PARSER_ERROR_TRAILING_COMMA;
+                  return G_TOKEN_SYMBOL;
+                }
 
               continue;
             }
@@ -557,12 +576,14 @@ json_parse_array (JsonParser  *parser,
           if (token == G_TOKEN_RIGHT_BRACE)
             {
               json_array_unref (array);
+              priv->error_code = JSON_PARSER_ERROR_TRAILING_COMMA;
               return G_TOKEN_SYMBOL;
             }
         }
       else if (token != G_TOKEN_RIGHT_BRACE)
         {
           json_array_unref (array);
+          priv->error_code = JSON_PARSER_ERROR_MISSING_COMMA;
           return G_TOKEN_RIGHT_BRACE;
         }
     }
@@ -671,6 +692,7 @@ json_parse_object (JsonParser *parser,
               if (token == G_TOKEN_RIGHT_CURLY)
                 {
                   json_object_unref (object);
+                  priv->error_code = JSON_PARSER_ERROR_TRAILING_COMMA;
                   return G_TOKEN_STRING;
                 }
 
@@ -723,6 +745,7 @@ json_parse_object (JsonParser *parser,
               if (token == G_TOKEN_RIGHT_CURLY)
                 {
                   json_object_unref (object);
+                  priv->error_code = JSON_PARSER_ERROR_TRAILING_COMMA;
                   return G_TOKEN_STRING;
                 }
 
@@ -760,6 +783,7 @@ json_parse_object (JsonParser *parser,
             {
               g_free (name);
               json_object_unref (object);
+              priv->error_code = JSON_PARSER_ERROR_TRAILING_COMMA;
               return G_TOKEN_STRING;
             }
         }
@@ -767,6 +791,7 @@ json_parse_object (JsonParser *parser,
         {
           g_free (name);
           json_object_unref (object);
+          priv->error_code = JSON_PARSER_ERROR_MISSING_COMMA;
           return G_TOKEN_RIGHT_CURLY;
         }
 
@@ -814,7 +839,10 @@ json_parse_statement (JsonParser  *parser,
         /* ... swallow the variable name... */
         next_token = json_scanner_get_next_token (scanner);
         if (next_token != G_TOKEN_IDENTIFIER)
-          return G_TOKEN_IDENTIFIER;
+          {
+            priv->error_code = JSON_PARSER_ERROR_INVALID_BAREWORD;
+            return G_TOKEN_IDENTIFIER;
+          }
 
         name = g_strdup (scanner->value.v_identifier);
 
@@ -852,6 +880,7 @@ json_parse_statement (JsonParser  *parser,
 
     default:
       json_scanner_get_next_token (scanner);
+      priv->error_code = JSON_PARSER_ERROR_INVALID_BAREWORD;
       return G_TOKEN_SYMBOL;
     }
 }
@@ -869,7 +898,7 @@ json_scanner_msg_handler (JsonScanner *scanner,
       GError *error = NULL;
 
       g_set_error (&error, JSON_PARSER_ERROR,
-                   JSON_PARSER_ERROR_PARSE,
+                   priv->error_code,
                    "%s:%d: Parse error: %s",
                    priv->is_filename ? priv->filename : "<none>",
                    scanner->line,
diff --git a/json-glib/json-parser.h b/json-glib/json-parser.h
index 7589464..11bfb89 100644
--- a/json-glib/json-parser.h
+++ b/json-glib/json-parser.h
@@ -49,12 +49,20 @@ typedef struct _JsonParserClass         JsonParserClass;
 /**
  * JsonParserError:
  * @JSON_PARSER_ERROR_PARSE: parse error
+ * @JSON_PARSER_ERROR_TRAILING_COMMA: unexpected trailing comma
+ * @JSON_PARSER_ERROR_MISSING_COMMA: expected comma
+ * @JSON_PARSER_ERROR_INVALID_BAREWORD: invalid bareword
  * @JSON_PARSER_ERROR_UNKNOWN: unknown error
  *
  * Error enumeration for #JsonParser
+ *
+ * This enumeration can be extended at later date
  */
 typedef enum {
   JSON_PARSER_ERROR_PARSE,
+  JSON_PARSER_ERROR_TRAILING_COMMA,
+  JSON_PARSER_ERROR_MISSING_COMMA,
+  JSON_PARSER_ERROR_INVALID_BAREWORD,
   
   JSON_PARSER_ERROR_UNKNOWN
 } JsonParserError;
diff --git a/json-glib/tests/parser-test.c b/json-glib/tests/parser-test.c
index 8f461ef..8fb11b1 100644
--- a/json-glib/tests/parser-test.c
+++ b/json-glib/tests/parser-test.c
@@ -131,14 +131,15 @@ static const struct
 static const struct
 {
   const gchar *str;
+  JsonParserError code;
 } test_invalid[] = {
-  { "test" },
-  { "[ foo, ]" },
-  { "[ true, ]" },
-  { "{ \"foo\" : true \"bar\" : false }" },
-  { "[ true, [ false, ] ]" },
-  { "{ \"foo\" : { \"bar\" : false, } }" },
-  { "[ { }, { }, { }, ]" }
+  { "test", JSON_PARSER_ERROR_INVALID_BAREWORD },
+  { "[ foo, ]", JSON_PARSER_ERROR_INVALID_BAREWORD },
+  { "[ true, ]", JSON_PARSER_ERROR_TRAILING_COMMA },
+  { "{ \"foo\" : true \"bar\" : false }", JSON_PARSER_ERROR_MISSING_COMMA },
+  { "[ true, [ false, ] ]", JSON_PARSER_ERROR_TRAILING_COMMA },
+  { "{ \"foo\" : { \"bar\" : false, } }", JSON_PARSER_ERROR_TRAILING_COMMA },
+  { "[ { }, { }, { }, ]", JSON_PARSER_ERROR_TRAILING_COMMA }
 };
 
 static guint n_test_base_values    = G_N_ELEMENTS (test_base_values);
@@ -671,8 +672,7 @@ test_invalid_json (void)
                                         &error);
 
       g_assert (!res);
-      g_assert (error != NULL);
-      g_assert (error->domain == JSON_PARSER_ERROR);
+      g_assert_error (error, JSON_PARSER_ERROR, test_invalid[i].code);
 
       if (g_test_verbose ())
         g_print ("Error: %s\n", error->message);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]