json: Correct position tracking in JSON parser implementations.
authorBen Pfaff <blp@nicira.com>
Thu, 26 Apr 2012 16:48:28 +0000 (09:48 -0700)
committerBen Pfaff <blp@nicira.com>
Thu, 26 Apr 2012 16:48:28 +0000 (09:48 -0700)
When json_lex_input() returns false, the parser does not consume the byte
passed in.  That byte will get processed again in the next iteration of
the json_parser_feed() loop.  Therefore, until now, this code has
double-counted bytes that cause a false return from json_lex_input().

This fixes the problem.  Every input byte is now counted only once.

Signed-off-by: Ben Pfaff <blp@nicira.com>
lib/json.c
python/ovs/json.py
tests/ovsdb-log.at

index 37bdece5c1b1555fa9087c9ba9360f83d7dc6f64..d514a90dd202c847d8254a840eeee909b3a98ee3 100644 (file)
@@ -908,14 +908,6 @@ json_lex_input(struct json_parser *p, unsigned char c)
 {
     struct json_token token;
 
-    p->byte_number++;
-    if (c == '\n') {
-        p->column_number = 0;
-        p->line_number++;
-    } else {
-        p->column_number++;
-    }
-
     switch (p->lex_state) {
     case JSON_LEX_START:
         switch (c) {
@@ -1092,6 +1084,13 @@ json_parser_feed(struct json_parser *p, const char *input, size_t n)
     size_t i;
     for (i = 0; !p->done && i < n; ) {
         if (json_lex_input(p, input[i])) {
+            p->byte_number++;
+            if (input[i] == '\n') {
+                p->column_number = 0;
+                p->line_number++;
+            } else {
+                p->column_number++;
+            }
             i++;
         }
     }
index 417d2316a2d4404bbdb70ae3c757f911283487d1..fa5fd154840f4910cddb16da801e073c24ae5092 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright (c) 2010, 2011 Nicira Networks
+# Copyright (c) 2010, 2011, 2012 Nicira Networks
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -420,13 +420,6 @@ class Parser(object):
         return True
 
     def __lex_input(self, c):
-        self.byte_number += 1
-        if c == '\n':
-            self.column_number = 0
-            self.line_number += 1
-        else:
-            self.column_number += 1
-
         eat = self.lex_state(self, c)
         assert eat is True or eat is False
         return eat
@@ -557,7 +550,16 @@ class Parser(object):
         while True:
             if self.done or i >= len(s):
                 return i
-            if self.__lex_input(s[i]):
+
+            c = s[i]
+            if self.__lex_input(c):
+                self.byte_number += 1
+                if c == '\n':
+                    self.column_number = 0
+                    self.line_number += 1
+                else:
+                    self.column_number += 1
+
                 i += 1
 
     def is_done(self):
index bd061105a2745e5d0a99134ca1133cc5543d362a..055dc70c520e4f3e441ef9e8c2a7053309558491 100644 (file)
@@ -266,7 +266,7 @@ AT_CHECK(
 file: read: [0]
 file: read: [1]
 file: read: [2]
-file: read failed: syntax error: file: 5 bytes starting at offset 228 are not valid JSON (line 1, column 0, byte 5: syntax error at beginning of input)
+file: read failed: syntax error: file: 5 bytes starting at offset 228 are not valid JSON (line 0, column 4, byte 4: syntax error at beginning of input)
 file: write:["replacement data"] successful
 ]], [ignore])
 AT_CHECK(