From 11f25386100ce50e114ec52d5487027af2912ebf Mon Sep 17 00:00:00 2001 From: Wouter van Oortmerssen Date: Thu, 4 Sep 2014 11:57:09 -0700 Subject: [PATCH] Made "field set more than once" check in JSON parser faster. Change-Id: I3ecc1aa610526c270faa56cc5266f14cd81db247 Tested: on Linux. --- include/flatbuffers/idl.h | 5 +++-- src/idl_parser.cpp | 14 ++++++++++---- tests/test.cpp | 2 +- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/include/flatbuffers/idl.h b/include/flatbuffers/idl.h index 272fd2cae..889664b8a 100644 --- a/include/flatbuffers/idl.h +++ b/include/flatbuffers/idl.h @@ -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 { diff --git a/src/idl_parser.cpp b/src/idl_parser.cpp index 4c60fd7d7..ed4476dba 100644 --- a/src/idl_parser.cpp +++ b/src/idl_parser.cpp @@ -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 diff --git a/tests/test.cpp b/tests/test.cpp index 4cd4fd1e5..118ecb6cb 100644 --- a/tests/test.cpp +++ b/tests/test.cpp @@ -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.