Made "field set more than once" check in JSON parser faster.
authorWouter van Oortmerssen <wvo@google.com>
Thu, 4 Sep 2014 18:57:09 +0000 (11:57 -0700)
committerWouter van Oortmerssen <wvo@google.com>
Thu, 4 Sep 2014 23:36:41 +0000 (16:36 -0700)
Change-Id: I3ecc1aa610526c270faa56cc5266f14cd81db247
Tested: on Linux.

include/flatbuffers/idl.h
src/idl_parser.cpp
tests/test.cpp

index 272fd2c..889664b 100644 (file)
@@ -176,11 +176,12 @@ struct Definition {
 };
 
 struct FieldDef : public Definition {
-  FieldDef() : deprecated(false), padding(0) {}
+  FieldDef() : deprecated(false), padding(0), used(false) {}
 
   Value value;
   bool deprecated;
-  size_t padding;  // bytes to always pad after this field
+  size_t padding;  // Bytes to always pad after this field.
+  bool used;       // Used during JSON parsing to check for repeated fields.
 };
 
 struct StructDef : public Definition {
index 4c60fd7..ed4476d 100644 (file)
@@ -457,10 +457,6 @@ uoffset_t Parser::ParseTable(const StructDef &struct_def) {
                             || struct_def.fields.vec[fieldn] != field)) {
        Error("struct field appearing out of order: " + name);
     }
-    for (auto it = field_stack_.rbegin();
-             it != field_stack_.rbegin() + fieldn; ++it) {
-      if (it->second == field) Error("field already set: " + name);
-    }
     Expect(':');
     Value val = field->value;
     ParseAnyValue(val, field);
@@ -469,6 +465,16 @@ uoffset_t Parser::ParseTable(const StructDef &struct_def) {
     if (IsNext('}')) break;
     Expect(',');
   }
+  for (auto it = field_stack_.rbegin();
+           it != field_stack_.rbegin() + fieldn; ++it) {
+    if (it->second->used)
+      Error("field set more than once: " + it->second->name);
+    it->second->used = true;
+  }
+  for (auto it = field_stack_.rbegin();
+           it != field_stack_.rbegin() + fieldn; ++it) {
+    it->second->used = false;
+  }
   if (struct_def.fixed && fieldn != struct_def.fields.vec.size())
     Error("incomplete struct initialization: " + struct_def.name);
   auto start = struct_def.fixed
index 4cd4fd1..118ecb6 100644 (file)
@@ -490,7 +490,7 @@ void ErrorTest() {
   TestError("union Z { X } struct X { Y:int; }", "only tables");
   TestError("table X { Y:[int]; YLength:int; }", "clash");
   TestError("table X { Y:string = 1; }", "scalar");
-  TestError("table X { Y:byte; } root_type X; { Y:1, Y:2 }", "already set");
+  TestError("table X { Y:byte; } root_type X; { Y:1, Y:2 }", "more than once");
 }
 
 // Additional parser testing not covered elsewhere.