avro-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From th...@apache.org
Subject svn commit: r1556285 - in /avro/trunk: ./ lang/c++/ lang/c++/impl/ lang/c++/impl/json/ lang/c++/impl/parsing/ lang/c++/jsonschemas/ lang/c++/test/
Date Tue, 07 Jan 2014 17:30:39 GMT
Author: thiru
Date: Tue Jan  7 17:30:38 2014
New Revision: 1556285

URL: http://svn.apache.org/r1556285
Log:
AVRO-1424 ValidatingDecoder hangs on large schema

Added:
    avro/trunk/lang/c++/jsonschemas/large_schema.avsc
    avro/trunk/lang/c++/test/LargeSchemaTests.cc
Modified:
    avro/trunk/CHANGES.txt
    avro/trunk/lang/c++/CMakeLists.txt
    avro/trunk/lang/c++/impl/BinaryEncoder.cc
    avro/trunk/lang/c++/impl/Compiler.cc
    avro/trunk/lang/c++/impl/json/JsonDom.cc
    avro/trunk/lang/c++/impl/json/JsonDom.hh
    avro/trunk/lang/c++/impl/parsing/JsonCodec.cc
    avro/trunk/lang/c++/impl/parsing/ResolvingDecoder.cc
    avro/trunk/lang/c++/impl/parsing/Symbol.hh
    avro/trunk/lang/c++/impl/parsing/ValidatingCodec.cc
    avro/trunk/lang/c++/impl/parsing/ValidatingCodec.hh
    avro/trunk/lang/c++/test/JsonTests.cc

Modified: avro/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/avro/trunk/CHANGES.txt?rev=1556285&r1=1556284&r2=1556285&view=diff
==============================================================================
--- avro/trunk/CHANGES.txt (original)
+++ avro/trunk/CHANGES.txt Tue Jan  7 17:30:38 2014
@@ -103,6 +103,8 @@ Trunk (not yet released)
     AVRO-1405. C: Check for end-of-file correctly.
     (Mika Ristimaki via dcreager)
 
+    AVRO-1424. ValidatingDecoder hangs on large schema (thiru)
+
 Avro 1.7.5 (12 August 2013)
 
   NEW FEATURES

Modified: avro/trunk/lang/c++/CMakeLists.txt
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c%2B%2B/CMakeLists.txt?rev=1556285&r1=1556284&r2=1556285&view=diff
==============================================================================
--- avro/trunk/lang/c++/CMakeLists.txt (original)
+++ avro/trunk/lang/c++/CMakeLists.txt Tue Jan  7 17:30:38 2014
@@ -147,6 +147,7 @@ endmacro (unittest)
 unittest (buffertest)
 unittest (unittest)
 unittest (SchemaTests)
+unittest (LargeSchemaTests)
 unittest (CodecTests)
 unittest (StreamTests)
 unittest (SpecificTests)

Modified: avro/trunk/lang/c++/impl/BinaryEncoder.cc
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c%2B%2B/impl/BinaryEncoder.cc?rev=1556285&r1=1556284&r2=1556285&view=diff
==============================================================================
--- avro/trunk/lang/c++/impl/BinaryEncoder.cc (original)
+++ avro/trunk/lang/c++/impl/BinaryEncoder.cc Tue Jan  7 17:30:38 2014
@@ -28,8 +28,6 @@ using boost::shared_ptr;
 
 class BinaryEncoder : public Encoder {
     StreamWriter out_;
-    uint8_t *next_;
-    uint8_t *end_;
 
     void init(OutputStream& os);
     void flush();

Modified: avro/trunk/lang/c++/impl/Compiler.cc
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c%2B%2B/impl/Compiler.cc?rev=1556285&r1=1556284&r2=1556285&view=diff
==============================================================================
--- avro/trunk/lang/c++/impl/Compiler.cc (original)
+++ avro/trunk/lang/c++/impl/Compiler.cc Tue Jan  7 17:30:38 2014
@@ -32,6 +32,8 @@ using std::map;
 using std::vector;
 
 namespace avro {
+using json::Object;
+using json::Array;
 
 typedef map<Name, NodePtr> SymbolTable;
 
@@ -97,10 +99,10 @@ static NodePtr makeNode(const std::strin
     throw Exception(boost::format("Unknown type: %1%") % n.fullname());
 }
 
-const map<string, Entity>::const_iterator findField(const Entity& e,
-    const map<string, Entity>& m, const string& fieldName)
+const json::Object::const_iterator findField(const Entity& e,
+    const Object& m, const string& fieldName)
 {
-    map<string, Entity>::const_iterator it = m.find(fieldName);
+    Object::const_iterator it = m.find(fieldName);
     if (it == m.end()) {
         throw Exception(boost::format("Missing Json field \"%1%\": %2%") %
             fieldName % e.toString());
@@ -109,21 +111,38 @@ const map<string, Entity>::const_iterato
     }
 }
 
-template<typename T>
-const T& getField(const Entity& e, const map<string, Entity>& m,
-    const string& fieldName)
-{
-    map<string, Entity>::const_iterator it = findField(e, m, fieldName);
-    if (it->second.type() != json::type_traits<T>::type()) {
-        throw Exception(boost::format(
-            "Json field \"%1%\" is not a %2%: %3%") %
-                fieldName % json::type_traits<T>::name() %
-                it->second.toString());
-    } else {
-        return it->second.value<T>();
+template <typename T> void ensureType(const Entity& e, const string& name)
+{
+    if (e.type() != json::type_traits<T>::type()) {
+        throw Exception(boost::format("Json field \"%1%\" is not a %2%: %3%") %
+            name % json::type_traits<T>::name() % e.toString());
     }
 }
 
+const string& getStringField(const Entity& e, const Object& m,
+                             const string& fieldName)
+{
+    Object::const_iterator it = findField(e, m, fieldName);
+    ensureType<string>(it->second, fieldName);
+    return it->second.stringValue();
+}
+
+const Array& getArrayField(const Entity& e, const Object& m,
+                           const string& fieldName)
+{
+    Object::const_iterator it = findField(e, m, fieldName);
+    ensureType<Array >(it->second, fieldName);
+    return it->second.arrayValue();
+}
+
+const int64_t getLongField(const Entity& e, const Object& m,
+                           const string& fieldName)
+{
+    Object::const_iterator it = findField(e, m, fieldName);
+    ensureType<int64_t>(it->second, fieldName);
+    return it->second.longValue();
+}
+    
 struct Field {
     const string& name;
     const NodePtr value;
@@ -132,20 +151,20 @@ struct Field {
 
 static Field makeField(const Entity& e, SymbolTable& st, const string& ns)
 {
-    const map<string, Entity>& m = e.value<map<string, Entity> >();
-    const string& n = getField<string>(e, m, "name");
-    map<string, Entity>::const_iterator it = findField(e, m, "type");
+    const Object& m = e.objectValue();
+    const string& n = getStringField(e, m, "name");
+    Object::const_iterator it = findField(e, m, "type");
     return Field(n, makeNode(it->second, st, ns));
 }
 
 static NodePtr makeRecordNode(const Entity& e,
-    const Name& name, const map<string, Entity>& m, SymbolTable& st, const string& ns)
+    const Name& name, const Object& m, SymbolTable& st, const string& ns)
 {        
-    const vector<Entity>& v = getField<vector<Entity> >(e, m, "fields");
+    const Array& v = getArrayField(e, m, "fields");
     concepts::MultiAttribute<string> fieldNames;
     concepts::MultiAttribute<NodePtr> fieldValues;
     
-    for (vector<Entity>::const_iterator it = v.begin(); it != v.end(); ++it) {
+    for (Array::const_iterator it = v.begin(); it != v.end(); ++it) {
         Field f = makeField(*it, st, ns);
         fieldNames.add(f.name);
         fieldValues.add(f.value);
@@ -155,24 +174,24 @@ static NodePtr makeRecordNode(const Enti
 }
 
 static NodePtr makeEnumNode(const Entity& e,
-    const Name& name, const map<string, Entity>& m)
+    const Name& name, const Object& m)
 {
-    const vector<Entity>& v = getField<vector<Entity> >(e, m, "symbols");
+    const Array& v = getArrayField(e, m, "symbols");
     concepts::MultiAttribute<string> symbols;
-    for (vector<Entity>::const_iterator it = v.begin(); it != v.end(); ++it) {
+    for (Array::const_iterator it = v.begin(); it != v.end(); ++it) {
         if (it->type() != json::etString) {
             throw Exception(boost::format("Enum symbol not a string: %1%") %
                 it->toString());
         }
-        symbols.add(it->value<string>());
+        symbols.add(it->stringValue());
     }
     return NodePtr(new NodeEnum(asSingleAttribute(name), symbols));
 }
 
 static NodePtr makeFixedNode(const Entity& e,
-    const Name& name, const map<string, Entity>& m)
+    const Name& name, const Object& m)
 {
-    int v = static_cast<int>(getField<int64_t>(e, m, "size"));
+    int v = static_cast<int>(getLongField(e, m, "size"));
     if (v <= 0) {
         throw Exception(boost::format("Size for fixed is not positive: ") %
             e.toString());
@@ -181,31 +200,31 @@ static NodePtr makeFixedNode(const Entit
         asSingleAttribute(v)));
 }
 
-static NodePtr makeArrayNode(const Entity& e, const map<string, Entity>& m,
+static NodePtr makeArrayNode(const Entity& e, const Object& m,
     SymbolTable& st, const string& ns)
 {
-    map<string, Entity>::const_iterator it = findField(e, m, "items");
+    Object::const_iterator it = findField(e, m, "items");
     return NodePtr(new NodeArray(asSingleAttribute(
         makeNode(it->second, st, ns))));
 }
 
-static NodePtr makeMapNode(const Entity& e, const map<string, Entity>& m,
+static NodePtr makeMapNode(const Entity& e, const Object& m,
     SymbolTable& st, const string& ns)
 {
-    map<string, Entity>::const_iterator it = findField(e, m, "values");
+    Object::const_iterator it = findField(e, m, "values");
 
     return NodePtr(new NodeMap(asSingleAttribute(
         makeNode(it->second, st, ns))));
 }
 
-static Name getName(const Entity& e, const map<string, Entity>& m, const string& ns)
+static Name getName(const Entity& e, const Object& m, const string& ns)
 {
-    const string& name = getField<string>(e, m, "name");
+    const string& name = getStringField(e, m, "name");
 
     if (isFullName(name)) {
         return Name(name);
     } else {
-        map<string, Entity>::const_iterator it = m.find("namespace");
+        Object::const_iterator it = m.find("namespace");
         if (it != m.end()) {
             if (it->second.type() != json::type_traits<string>::type()) {
                 throw Exception(boost::format(
@@ -213,17 +232,17 @@ static Name getName(const Entity& e, con
                         "namespace" % json::type_traits<string>::name() %
                         it->second.toString());
             }
-            Name result = Name(name, it->second.value<string>());
+            Name result = Name(name, it->second.stringValue());
             return result;
         }
         return Name(name, ns);
     }
 }
 
-static NodePtr makeNode(const Entity& e, const map<string, Entity>& m,
+static NodePtr makeNode(const Entity& e, const Object& m,
     SymbolTable& st, const string& ns)
 {
-    const string& type = getField<string>(e, m, "type");
+    const string& type = getStringField(e, m, "type");
     if (NodePtr result = makePrimitive(type)) {
         return result;
     } else if (type == "record" || type == "error" ||
@@ -251,11 +270,11 @@ static NodePtr makeNode(const Entity& e,
         % e.toString());
 }
 
-static NodePtr makeNode(const Entity& e, const vector<Entity>& m,
+static NodePtr makeNode(const Entity& e, const Array& m,
     SymbolTable& st, const string& ns)
 {
     concepts::MultiAttribute<NodePtr> mm;
-    for (vector<Entity>::const_iterator it = m.begin(); it != m.end(); ++it) {
+    for (Array::const_iterator it = m.begin(); it != m.end(); ++it) {
         mm.add(makeNode(*it, st, ns));
     }
     return NodePtr(new NodeUnion(mm));
@@ -265,11 +284,11 @@ static NodePtr makeNode(const json::Enti
 {
     switch (e.type()) {
     case json::etString:
-        return makeNode(e.value<string>(), st, ns);
+        return makeNode(e.stringValue(), st, ns);
     case json::etObject:
-        return makeNode(e, e.value<map<string, Entity> >(), st, ns);
+        return makeNode(e, e.objectValue(), st, ns);
     case json::etArray:
-        return makeNode(e, e.value<vector<Entity> >(), st, ns);
+        return makeNode(e, e.arrayValue(), st, ns);
     default:
         throw Exception(boost::format("Invalid Avro type: %1%") % e.toString());
     }

Modified: avro/trunk/lang/c++/impl/json/JsonDom.cc
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c%2B%2B/impl/json/JsonDom.cc?rev=1556285&r1=1556284&r2=1556285&view=diff
==============================================================================
--- avro/trunk/lang/c++/impl/json/JsonDom.cc (original)
+++ avro/trunk/lang/c++/impl/json/JsonDom.cc Tue Jan  7 17:30:38 2014
@@ -21,12 +21,29 @@
 #include <stdexcept>
 
 #include <string.h>
+#include <boost/make_shared.hpp>
 
 #include "Stream.hh"
 #include "JsonIO.hh"
 
+using std::string;
+using boost::format;
+
 namespace avro {
 namespace json {
+static const char* typeToString(EntityType t)
+{
+    switch (t) {
+    case etNull: return "null";
+    case etBool: return "bool";
+    case etLong: return "long";
+    case etDouble: return "double";
+    case etString: return "string";
+    case etArray: return "array";
+    case etObject: return "object";
+    default: return "unknown";
+    }
+}
 
 Entity readEntity(JsonParser& p)
 {
@@ -45,13 +62,13 @@ Entity readEntity(JsonParser& p)
         return Entity(p.doubleValue());
     case JsonParser::tkString:
         p.advance();
-        return Entity(p.stringValue());
+        return Entity(boost::make_shared<String>(p.stringValue()));
     case JsonParser::tkArrayStart:
         {
             p.advance();
-            std::vector<Entity> v;
+            boost::shared_ptr<Array> v = boost::make_shared<Array>();
             while (p.peek() != JsonParser::tkArrayEnd) {
-                v.push_back(readEntity(p));
+                v->push_back(readEntity(p));
             }
             p.advance();
             return Entity(v);
@@ -59,12 +76,12 @@ Entity readEntity(JsonParser& p)
     case JsonParser::tkObjectStart:
         {
             p.advance();
-            std::map<std::string, Entity> v;
+            boost::shared_ptr<Object> v = boost::make_shared<Object>();
             while (p.peek() != JsonParser::tkObjectEnd) {
                 p.advance();
                 std::string k = p.stringValue();
                 Entity n = readEntity(p);
-                v.insert(std::make_pair(k, n));
+                v->insert(std::make_pair(k, n));
             }
             p.advance();
             return Entity(v);
@@ -100,22 +117,22 @@ void writeEntity(JsonGenerator& g, const
         g.encodeNull();
         break;
     case etBool:
-        g.encodeBool(n.value<bool>());
+        g.encodeBool(n.boolValue());
         break;
     case etLong:
-        g.encodeNumber(n.value<int64_t>());
+        g.encodeNumber(n.longValue());
         break;
     case etDouble:
-        g.encodeNumber(n.value<double>());
+        g.encodeNumber(n.doubleValue());
         break;
     case etString:
-        g.encodeString(n.value<std::string>());
+        g.encodeString(n.stringValue());
         break;
     case etArray:
         {
             g.arrayStart();
-            const std::vector<Entity>& v = n.value<std::vector<Entity> >();
-            for (std::vector<Entity>::const_iterator it = v.begin();
+            const Array& v = n.arrayValue();
+            for (Array::const_iterator it = v.begin();
                 it != v.end(); ++it) {
                 writeEntity(g, *it);
             }
@@ -125,10 +142,8 @@ void writeEntity(JsonGenerator& g, const
     case etObject:
         {
             g.objectStart();
-            const std::map<std::string, Entity>& v =
-                n.value<std::map<std::string, Entity> >();
-            for (std::map<std::string, Entity>::const_iterator it = v.begin();
-                it != v.end(); ++it) {
+            const Object& v = n.objectValue();
+            for (Object::const_iterator it = v.begin(); it != v.end(); ++it) {
                 g.encodeString(it->first);
                 writeEntity(g, it->second);
             }
@@ -138,6 +153,16 @@ void writeEntity(JsonGenerator& g, const
     }
 }
 
+void Entity::ensureType(EntityType type) const
+{
+    if (type_ != type) {
+        format msg = format("Invalid type. Expected \"%1%\" actual %2%") %
+            typeToString(type) % typeToString(type_);
+        throw Exception(msg);
+    }
+}
+    
+
 std::string Entity::toString() const
 {
     std::auto_ptr<OutputStream> out = memoryOutputStream();

Modified: avro/trunk/lang/c++/impl/json/JsonDom.hh
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c%2B%2B/impl/json/JsonDom.hh?rev=1556285&r1=1556284&r2=1556285&view=diff
==============================================================================
--- avro/trunk/lang/c++/impl/json/JsonDom.hh (original)
+++ avro/trunk/lang/c++/impl/json/JsonDom.hh Tue Jan  7 17:30:38 2014
@@ -19,10 +19,12 @@
 #ifndef avro_json_JsonDom_hh__
 #define avro_json_JsonDom_hh__
 
+#include <iostream>
 #include <stdint.h>
 #include <map>
 #include <string>
 #include <vector>
+#include <boost/shared_ptr.hpp>
 
 #include "boost/any.hpp"
 #include "Config.hh"
@@ -32,7 +34,15 @@ namespace avro {
 class AVRO_DECL InputStream;
 
 namespace json {
-
+class Entity;
+    
+typedef bool Bool;
+typedef int64_t Long;
+typedef double Double;
+typedef std::string String;
+typedef std::vector<Entity> Array;
+typedef std::map<std::string, Entity> Object;
+    
 class AVRO_DECL JsonParser;
 class AVRO_DECL JsonGenerator;
 
@@ -49,32 +59,46 @@ enum EntityType {
 class AVRO_DECL Entity {
     EntityType type_;
     boost::any value_;
+    void ensureType(EntityType) const;
 public:
     Entity() : type_(etNull) { }
-    Entity(bool v) : type_(etBool), value_(v) { }
-    Entity(int64_t v) : type_(etLong), value_(v) { }
-    Entity(double v) : type_(etDouble), value_(v) { }
-    Entity(const std::string& v) : type_(etString), value_(v) { }
-    Entity(const std::vector<Entity> v) : type_(etArray), value_(v) { }
-    Entity(const std::map<std::string, Entity> v) : type_(etObject), value_(v) {
-    }
-
-
+    Entity(Bool v) : type_(etBool), value_(v) { }
+    Entity(Long v) : type_(etLong), value_(v) { }
+    Entity(Double v) : type_(etDouble), value_(v) { }
+    Entity(const boost::shared_ptr<String>& v) : type_(etString), value_(v) { }
+    Entity(const boost::shared_ptr<Array>& v) : type_(etArray), value_(v) { }
+    Entity(const boost::shared_ptr<Object>& v) : type_(etObject), value_(v) { }
+    
     EntityType type() const { return type_; }
 
-    template <typename T>
-    const T& value() const {
-        return *boost::any_cast<T>(&value_);
+    Bool boolValue() const {
+        ensureType(etBool);
+        return boost::any_cast<Bool>(value_);
     }
 
-    template <typename T>
-    T& value() {
-        return *boost::any_cast<T>(&value_);
+    Long longValue() const {
+        ensureType(etLong);
+        return boost::any_cast<Long>(value_);
+    }
+    
+    Double doubleValue() const {
+        ensureType(etDouble);
+        return boost::any_cast<Double>(value_);
     }
 
-    template <typename T>
-    void set(const T& v) {
-        *boost::any_cast<T>(&value_) = v;
+    const String& stringValue() const {
+        ensureType(etString);
+        return **boost::any_cast<boost::shared_ptr<String> >(&value_);
+    }
+    
+    const Array& arrayValue() const {
+        ensureType(etArray);
+        return **boost::any_cast<boost::shared_ptr<Array> >(&value_);
+    }
+
+    const Object& objectValue() const {
+        ensureType(etObject);
+        return **boost::any_cast<boost::shared_ptr<Object> >(&value_);
     }
 
     std::string toString() const;
@@ -84,6 +108,21 @@ template <typename T>
 struct type_traits {
 };
 
+template <> struct type_traits<bool> {
+    static EntityType type() { return etBool; }
+    static const char* name() { return "bool"; }
+};
+
+template <> struct type_traits<int64_t> {
+    static EntityType type() { return etLong; }
+    static const char* name() { return "long"; }
+};
+
+template <> struct type_traits<double> {
+    static EntityType type() { return etDouble; }
+    static const char* name() { return "double"; }
+};
+    
 template <> struct type_traits<std::string> {
     static EntityType type() { return etString; }
     static const char* name() { return "string"; }
@@ -94,9 +133,9 @@ template <> struct type_traits<std::vect
     static const char* name() { return "array"; }
 };
 
-template <> struct type_traits<int64_t> {
-    static EntityType type() { return etLong; }
-    static const char* name() { return "integer"; }
+template <> struct type_traits<std::map<std::string, Entity> > {
+    static EntityType type() { return etObject; }
+    static const char* name() { return "object"; }
 };
 
 AVRO_DECL Entity readEntity(JsonParser& p);

Modified: avro/trunk/lang/c++/impl/parsing/JsonCodec.cc
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c%2B%2B/impl/parsing/JsonCodec.cc?rev=1556285&r1=1556284&r2=1556285&view=diff
==============================================================================
--- avro/trunk/lang/c++/impl/parsing/JsonCodec.cc (original)
+++ avro/trunk/lang/c++/impl/parsing/JsonCodec.cc Tue Jan  7 17:30:38 2014
@@ -42,6 +42,7 @@ namespace avro {
 namespace parsing {
 
 using boost::shared_ptr;
+using boost::make_shared;
 using boost::static_pointer_cast;
 
 using std::map;
@@ -55,8 +56,8 @@ using avro::json::JsonParser;
 using avro::json::JsonGenerator;
 
 class JsonGrammarGenerator : public ValidatingGrammarGenerator {
-    Production doGenerate(const NodePtr& n,
-        std::map<NodePtr, boost::shared_ptr<Production> > &m);
+    ProductionPtr doGenerate(const NodePtr& n,
+        std::map<NodePtr, ProductionPtr> &m);
 };
 
 static std::string nameOf(const NodePtr& n)
@@ -69,8 +70,8 @@ static std::string nameOf(const NodePtr&
     return oss.str();
 }
 
-Production JsonGrammarGenerator::doGenerate(const NodePtr& n,
-    std::map<NodePtr, boost::shared_ptr<Production> > &m) {
+ProductionPtr JsonGrammarGenerator::doGenerate(const NodePtr& n,
+    std::map<NodePtr, ProductionPtr> &m) {
     switch (n->type()) {
     case AVRO_NULL:
     case AVRO_BOOL:
@@ -87,28 +88,24 @@ Production JsonGrammarGenerator::doGener
         return ValidatingGrammarGenerator::doGenerate(n, m);
     case AVRO_RECORD:
         {
-            Production result;
+            ProductionPtr result = make_shared<Production>();
 
             m.erase(n);
 
             size_t c = n->leaves();
-            result.reserve(2 + 2 * c);
-            result.push_back(Symbol::recordStartSymbol());
+            result->reserve(2 + 2 * c);
+            result->push_back(Symbol::recordStartSymbol());
             for (size_t i = 0; i < c; ++i) {
                 const NodePtr& leaf = n->leafAt(i);
-                Production v = doGenerate(leaf, m);
-                result.push_back(Symbol::fieldSymbol(n->nameAt(i)));
-                copy(v.rbegin(), v.rend(), back_inserter(result));
+                ProductionPtr v = doGenerate(leaf, m);
+                result->push_back(Symbol::fieldSymbol(n->nameAt(i)));
+                copy(v->rbegin(), v->rend(), back_inserter(*result));
             }
-            result.push_back(Symbol::recordEndSymbol());
-            reverse(result.begin(), result.end());
+            result->push_back(Symbol::recordEndSymbol());
+            reverse(result->begin(), result->end());
 
-            bool found = m.find(n) != m.end();
-
-            shared_ptr<Production> p = boost::make_shared<Production>(result);
-            m[n] = p;
-
-            return found ? Production(1, Symbol::indirect(p)) : result;
+            m[n] = result;
+            return result;
         }
     case AVRO_ENUM:
         {
@@ -118,18 +115,17 @@ Production JsonGrammarGenerator::doGener
             for (size_t i = 0; i < c; ++i) {
                 nn.push_back(n->nameAt(i));
             }
-            Symbol r[] = {
-                Symbol::nameListSymbol(nn),
-                Symbol::enumSymbol() };
-            Production result(r, r + 2);
-            m[n] = boost::make_shared<Production>(result);
+            ProductionPtr result = make_shared<Production>();
+            result->push_back(Symbol::nameListSymbol(nn));
+            result->push_back(Symbol::enumSymbol());
+            m[n] = result;
             return result;
         }
     case AVRO_UNION:
         {
             size_t c = n->leaves();
 
-            vector<Production> vv;
+            vector<ProductionPtr> vv;
             vv.reserve(c);
 
             vector<string> names;
@@ -137,22 +133,21 @@ Production JsonGrammarGenerator::doGener
 
             for (size_t i = 0; i < c; ++i) {
                 const NodePtr& nn = n->leafAt(i);
-                Production v = doGenerate(nn, m);
+                ProductionPtr v = doGenerate(nn, m);
                 if (nn->type() != AVRO_NULL) {
-                    Production v2;
-                    v2.push_back(Symbol::recordEndSymbol());
-                    copy(v.begin(), v.end(), back_inserter(v2));
+                    ProductionPtr v2 = make_shared<Production>();
+                    v2->push_back(Symbol::recordEndSymbol());
+                    copy(v->begin(), v->end(), back_inserter(*v2));
                     v.swap(v2);
                 }
                 vv.push_back(v);
                 names.push_back(nameOf(nn));
             }
-            Symbol r[] = {
-                Symbol::alternative(vv),
-                Symbol::nameListSymbol(names),
-                Symbol::unionSymbol()
-            };
-            return Production(r, r + 3);
+            ProductionPtr result = make_shared<Production>();
+            result->push_back(Symbol::alternative(vv));
+            result->push_back(Symbol::nameListSymbol(names));
+            result->push_back(Symbol::unionSymbol());
+            return result;
         }
     default:
         throw Exception("Unknown node type");

Modified: avro/trunk/lang/c++/impl/parsing/ResolvingDecoder.cc
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c%2B%2B/impl/parsing/ResolvingDecoder.cc?rev=1556285&r1=1556284&r2=1556285&view=diff
==============================================================================
--- avro/trunk/lang/c++/impl/parsing/ResolvingDecoder.cc (original)
+++ avro/trunk/lang/c++/impl/parsing/ResolvingDecoder.cc Tue Jan  7 17:30:38 2014
@@ -60,15 +60,15 @@ using std::make_pair;
 typedef pair<NodePtr, NodePtr> NodePair;
 
 class ResolvingGrammarGenerator : public ValidatingGrammarGenerator {
-    Production doGenerate2(const NodePtr& writer, const NodePtr& reader,
-        map<NodePair, shared_ptr<Production> > &m,
-        const map<NodePtr, shared_ptr<Production> > &m2);
-    Production resolveRecords(const NodePtr& writer, const NodePtr& reader,
-        map<NodePair, shared_ptr<Production> > &m,
-        const map<NodePtr, shared_ptr<Production> > &m2);
-    Production resolveUnion(const NodePtr& writer, const NodePtr& reader,
-        map<NodePair, shared_ptr<Production> > &m,
-        const map<NodePtr, shared_ptr<Production> > &m2);
+    ProductionPtr doGenerate2(const NodePtr& writer,
+        const NodePtr& reader, map<NodePair, ProductionPtr> &m,
+        const map<NodePtr, ProductionPtr> &m2);
+    ProductionPtr resolveRecords(const NodePtr& writer,
+        const NodePtr& reader, map<NodePair, ProductionPtr> &m,
+        const map<NodePtr, ProductionPtr> &m2);
+    ProductionPtr resolveUnion(const NodePtr& writer,
+        const NodePtr& reader, map<NodePair, ProductionPtr> &m,
+        const map<NodePtr, ProductionPtr> &m2);
 
     static vector<pair<string, size_t> > fields(const NodePtr& n) {
         vector<pair<string, size_t> > result;
@@ -81,8 +81,8 @@ class ResolvingGrammarGenerator : public
 
     static int bestBranch(const NodePtr& writer, const NodePtr& reader);
 
-    Production getWriterProduction(const NodePtr& n,
-        const map<NodePtr, shared_ptr<Production> >& m2);
+    ProductionPtr getWriterProduction(const NodePtr& n,
+        const map<NodePtr, ProductionPtr>& m2);
 
 public:
     Symbol generate(
@@ -91,15 +91,15 @@ public:
 
 Symbol ResolvingGrammarGenerator::generate(
     const ValidSchema& writer, const ValidSchema& reader) {
-    map<NodePtr, shared_ptr<Production> > m2;
+    map<NodePtr, ProductionPtr> m2;
 
     const NodePtr& rr = reader.root();
     const NodePtr& rw = writer.root();
-    Production backup = ValidatingGrammarGenerator::doGenerate(rw, m2);
+    ProductionPtr backup = ValidatingGrammarGenerator::doGenerate(rw, m2);
     fixup(backup, m2);
 
-    map<NodePair, shared_ptr<Production> > m;
-    Production main = doGenerate2(rr, rw, m, m2);
+    map<NodePair, ProductionPtr> m;
+    ProductionPtr main = doGenerate2(rr, rw, m, m2);
     fixup(main, m);
     return Symbol::rootSymbol(main, backup);
 }
@@ -155,22 +155,22 @@ struct equalsFirst
     }
 };
 
-Production ResolvingGrammarGenerator::getWriterProduction(const NodePtr& n,
-    const map<NodePtr, shared_ptr<Production> >& m2)
+ProductionPtr ResolvingGrammarGenerator::getWriterProduction(
+    const NodePtr& n, const map<NodePtr, ProductionPtr>& m2)
 {
     const NodePtr& nn = (n->type() == AVRO_SYMBOLIC) ?
         static_cast<const NodeSymbolic& >(*n).getNode() : n;
-    map<NodePtr, shared_ptr<Production> >::const_iterator it2 = m2.find(nn);
-    return (it2 != m2.end()) ? *(it2->second) :
+    map<NodePtr, ProductionPtr>::const_iterator it2 = m2.find(nn);
+    return (it2 != m2.end()) ? it2->second :
         ValidatingGrammarGenerator::generate(nn);
 }
 
-Production ResolvingGrammarGenerator::resolveRecords(
+ProductionPtr ResolvingGrammarGenerator::resolveRecords(
     const NodePtr& writer, const NodePtr& reader,
-    map<NodePair, shared_ptr<Production> >& m,
-    const map<NodePtr, shared_ptr<Production> >& m2)
+    map<NodePair, ProductionPtr>& m,
+    const map<NodePtr, ProductionPtr>& m2)
 {
-    Production result;
+    ProductionPtr result = make_shared<Production>();
 
     vector<pair<string, size_t> > wf = fields(writer);
     vector<pair<string, size_t> > rf = fields(reader);
@@ -183,18 +183,19 @@ Production ResolvingGrammarGenerator::re
             find_if(rf.begin(), rf.end(),
                 equalsFirst<string, size_t>(it->first));
         if (it2 != rf.end()) {
-            Production p = doGenerate2(writer->leafAt(it->second),
+            ProductionPtr p = doGenerate2(writer->leafAt(it->second),
                 reader->leafAt(it2->second), m, m2);
-            copy(p.rbegin(), p.rend(), back_inserter(result));
+            copy(p->rbegin(), p->rend(), back_inserter(*result));
             fieldOrder.push_back(it2->second);
             rf.erase(it2);
         } else {
-            Production p = getWriterProduction(writer->leafAt(it->second), m2);
-            result.push_back(Symbol::skipStart());
-            if (p.size() == 1) {
-                result.push_back(p[0]);
+            ProductionPtr p = getWriterProduction(
+            writer->leafAt(it->second), m2);
+            result->push_back(Symbol::skipStart());
+            if (p->size() == 1) {
+                result->push_back((*p)[0]);
             } else {
-                result.push_back(Symbol::indirect(boost::make_shared<Production>(p)));
+                result->push_back(Symbol::indirect(p));
             } 
         }
     }
@@ -202,37 +203,36 @@ Production ResolvingGrammarGenerator::re
     if (! rf.empty()) {
         throw Exception("Don't know how to handle excess fields for reader.");
     }
-    reverse(result.begin(), result.end());
-    result.push_back(Symbol::sizeListAction(fieldOrder));
-    result.push_back(Symbol::recordAction());
+    reverse(result->begin(), result->end());
+    result->push_back(Symbol::sizeListAction(fieldOrder));
+    result->push_back(Symbol::recordAction());
 
     return result;
 
 }
 
-Production ResolvingGrammarGenerator::resolveUnion(
+ProductionPtr ResolvingGrammarGenerator::resolveUnion(
     const NodePtr& writer, const NodePtr& reader,
-    map<NodePair, shared_ptr<Production> >& m,
-    const map<NodePtr, shared_ptr<Production> >& m2)
+    map<NodePair, ProductionPtr>& m,
+    const map<NodePtr, ProductionPtr>& m2)
 {
-    vector<Production> v;
+    vector<ProductionPtr> v;
     size_t c = writer->leaves();
     v.reserve(c);
     for (size_t i = 0; i < c; ++i) {
-        Production p = doGenerate2(writer->leafAt(i), reader, m, m2);
+        ProductionPtr p = doGenerate2(writer->leafAt(i), reader, m, m2);
         v.push_back(p);
     }
-    Symbol r[] = {
-        Symbol::alternative(v),
-        Symbol::writerUnionAction()
-    };
-    return Production(r, r + 2);
+    ProductionPtr result = make_shared<Production>();
+    result->push_back(Symbol::alternative(v));
+    result->push_back(Symbol::writerUnionAction());
+    return result;
 }
 
-Production ResolvingGrammarGenerator::doGenerate2(
+ProductionPtr ResolvingGrammarGenerator::doGenerate2(
     const NodePtr& writer, const NodePtr& reader,
-    map<NodePair, shared_ptr<Production> > &m,
-    const map<NodePtr, shared_ptr<Production> > &m2)
+    map<NodePair, ProductionPtr> &m,
+    const map<NodePtr, ProductionPtr> &m2)
 {
     Type writerType = writer->type();
     Type readerType = reader->type();
@@ -240,29 +240,28 @@ Production ResolvingGrammarGenerator::do
     if (writerType == readerType) {
         switch (writerType) {
         case AVRO_NULL:
-            return Production(1, Symbol::nullSymbol());
+            return make_shared<Production>(1, Symbol::nullSymbol());
         case AVRO_BOOL:
-            return Production(1, Symbol::boolSymbol());
+            return make_shared<Production>(1, Symbol::boolSymbol());
         case AVRO_INT:
-            return Production(1, Symbol::intSymbol());
+            return make_shared<Production>(1, Symbol::intSymbol());
         case AVRO_LONG:
-            return Production(1, Symbol::longSymbol());
+            return make_shared<Production>(1, Symbol::longSymbol());
         case AVRO_FLOAT:
-            return Production(1, Symbol::floatSymbol());
+            return make_shared<Production>(1, Symbol::floatSymbol());
         case AVRO_DOUBLE:
-            return Production(1, Symbol::doubleSymbol());
+            return make_shared<Production>(1, Symbol::doubleSymbol());
         case AVRO_STRING:
-            return Production(1, Symbol::stringSymbol());
+            return make_shared<Production>(1, Symbol::stringSymbol());
         case AVRO_BYTES:
-            return Production(1, Symbol::bytesSymbol());
+            return make_shared<Production>(1, Symbol::bytesSymbol());
         case AVRO_FIXED:
             if (writer->name() == reader->name() &&
                 writer->fixedSize() == reader->fixedSize()) {
-                Symbol r[] = {
-                    Symbol::sizeCheckSymbol(reader->fixedSize()),
-                    Symbol::fixedSymbol() };
-                Production result(r, r + 2);
-                m[make_pair(writer, reader)] = boost::make_shared<Production>(result);
+                ProductionPtr result = make_shared<Production>();
+                result->push_back(Symbol::sizeCheckSymbol(reader->fixedSize()));
+                result->push_back(Symbol::fixedSymbol());
+                m[make_pair(writer, reader)] = result;
                 return result;
             }
             break;
@@ -270,53 +269,46 @@ Production ResolvingGrammarGenerator::do
             if (writer->name() == reader->name()) {
                 const pair<NodePtr, NodePtr> key(writer, reader);
                 m.erase(key);
-                Production result = resolveRecords(writer, reader, m, m2);
-
-                const bool found = m.find(key) != m.end();
-
-                shared_ptr<Production> p = boost::make_shared<Production>(result);
-                m[key] = p;
-                return found ? Production(1, Symbol::indirect(p)) : result;
+                ProductionPtr result = resolveRecords(writer, reader, m, m2);
+                m[key] = result;
+                return result;
             }
             break;
 
         case AVRO_ENUM:
             if (writer->name() == reader->name()) {
-                Symbol r[] = {
-                    Symbol::enumAdjustSymbol(writer, reader),
-                    Symbol::enumSymbol(),
-                };
-                Production result(r, r + 2);
-                m[make_pair(writer, reader)] = boost::make_shared<Production>(result);
+                ProductionPtr result = make_shared<Production>();
+                result->push_back(Symbol::enumAdjustSymbol(writer, reader));
+                result->push_back(Symbol::enumSymbol());
+                m[make_pair(writer, reader)] = result;
                 return result;
             }
             break;
 
         case AVRO_ARRAY:
             {
-                Production p = getWriterProduction(writer->leafAt(0), m2);
-                Symbol r[] = {
-                    Symbol::arrayEndSymbol(),
-                    Symbol::repeater(
-                        doGenerate2(writer->leafAt(0), reader->leafAt(0), m, m2),
-                        p, true),
-                    Symbol::arrayStartSymbol() };
-                return Production(r, r + 3);
+                ProductionPtr p = getWriterProduction(writer->leafAt(0), m2);
+                ProductionPtr p2 = doGenerate2(writer->leafAt(0), reader->leafAt(0), m, m2);
+                ProductionPtr result = make_shared<Production>();
+                result->push_back(Symbol::arrayEndSymbol());
+                result->push_back(Symbol::repeater(p2, p, true));
+                result->push_back(Symbol::arrayStartSymbol());
+                return result;
             }
         case AVRO_MAP:
             {
-                Production v = doGenerate2(writer->leafAt(1),
+                ProductionPtr v = doGenerate2(writer->leafAt(1),
                     reader->leafAt(1), m, m2);
-                v.push_back(Symbol::stringSymbol());
+                v->push_back(Symbol::stringSymbol());
 
-                Production v2 = getWriterProduction(writer->leafAt(1), m2);
-                v2.push_back(Symbol::stringSymbol());
+                ProductionPtr v2 = getWriterProduction(writer->leafAt(1), m2);
+                v2->push_back(Symbol::stringSymbol());
 
-                Symbol r[] = {
-                    Symbol::mapEndSymbol(),
-                    Symbol::repeater(v, v2, false),
-                    Symbol::mapStartSymbol() };
-                return Production(r, r + 3);
+                ProductionPtr result = make_shared<Production>();
+                result->push_back(Symbol::mapEndSymbol());
+                result->push_back(Symbol::repeater(v, v2, false));
+                result->push_back(Symbol::mapStartSymbol());
+                return result;
             }
         case AVRO_UNION:
             return resolveUnion(writer, reader, m, m2);
@@ -327,12 +319,12 @@ Production ResolvingGrammarGenerator::do
                 shared_ptr<NodeSymbolic> r =
                     static_pointer_cast<NodeSymbolic>(reader);
                 NodePair p(w->getNode(), r->getNode());
-                map<NodePair, shared_ptr<Production> >::iterator it = m.find(p);
+                map<NodePair, ProductionPtr>::iterator it = m.find(p);
                 if (it != m.end() && it->second) {
-                    return *it->second;
+                    return it->second;
                 } else {
-                    m[p] = shared_ptr<Production>();
-                    return Production(1, Symbol::placeholder(p));
+                    m[p] = ProductionPtr();
+                    return make_shared<Production>(1, Symbol::placeholder(p));
                 }
             }
         default:
@@ -344,13 +336,13 @@ Production ResolvingGrammarGenerator::do
         switch (readerType) {
         case AVRO_LONG:
             if (writerType == AVRO_INT) {
-                return Production(1,
+                return make_shared<Production>(1,
                     Symbol::resolveSymbol(Symbol::sInt, Symbol::sLong));
             }
             break;
         case AVRO_FLOAT:
             if (writerType == AVRO_INT || writerType == AVRO_LONG) {
-                return Production(1,
+                return make_shared<Production>(1,
                     Symbol::resolveSymbol(writerType == AVRO_INT ?
                     Symbol::sInt : Symbol::sLong, Symbol::sFloat));
             }
@@ -358,7 +350,7 @@ Production ResolvingGrammarGenerator::do
         case AVRO_DOUBLE:
             if (writerType == AVRO_INT || writerType == AVRO_LONG
                 || writerType == AVRO_FLOAT) {
-                return Production(1,
+                return make_shared<Production>(1,
                     Symbol::resolveSymbol(writerType == AVRO_INT ?
                     Symbol::sInt : writerType == AVRO_LONG ?
                     Symbol::sLong : Symbol::sFloat, Symbol::sDouble));
@@ -369,12 +361,11 @@ Production ResolvingGrammarGenerator::do
             {
                 int j = bestBranch(writer, reader);
                 if (j >= 0) {
-                    Production p = doGenerate2(writer, reader->leafAt(j), m, m2);
-                    Symbol r[] = {
-                        Symbol::unionAdjustSymbol(j, p),
-                        Symbol::unionSymbol()
-                    };
-                    return Production(r, r + 2);
+                    ProductionPtr p = doGenerate2(writer, reader->leafAt(j), m, m2);
+                    ProductionPtr result = make_shared<Production>();
+                    result->push_back(Symbol::unionAdjustSymbol(j, p));
+                    result->push_back(Symbol::unionSymbol());
+                    return result;
                 }
             }
             break;
@@ -392,7 +383,7 @@ Production ResolvingGrammarGenerator::do
             throw Exception("Unknown node type");
         }
     }
-    return Production(1, Symbol::error(writer, reader));
+    return make_shared<Production>(1, Symbol::error(writer, reader));
 }
 
 class ResolvingDecoderHandler {

Modified: avro/trunk/lang/c++/impl/parsing/Symbol.hh
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c%2B%2B/impl/parsing/Symbol.hh?rev=1556285&r1=1556284&r2=1556285&view=diff
==============================================================================
--- avro/trunk/lang/c++/impl/parsing/Symbol.hh (original)
+++ avro/trunk/lang/c++/impl/parsing/Symbol.hh Tue Jan  7 17:30:38 2014
@@ -21,12 +21,14 @@
 
 #include <vector>
 #include <map>
+#include <set>
 #include <stack>
 #include <sstream>
 
 #include <boost/any.hpp>
 #include <boost/shared_ptr.hpp>
 #include <boost/weak_ptr.hpp>
+#include <boost/make_shared.hpp>
 #include <boost/tuple/tuple.hpp>
 
 #include "Node.hh"
@@ -39,8 +41,9 @@ namespace parsing {
 class Symbol;
 
 typedef std::vector<Symbol> Production;
-typedef boost::tuple<size_t, bool, Production, Production> RepeaterInfo;
-typedef boost::tuple<Production, Production> RootInfo;
+typedef boost::shared_ptr<Production> ProductionPtr;
+typedef boost::tuple<size_t, bool, ProductionPtr, ProductionPtr> RepeaterInfo;
+typedef boost::tuple<ProductionPtr, ProductionPtr> RootInfo;
 
 class Symbol {
 public:
@@ -128,12 +131,13 @@ public:
         return stringValues[k];
     }
 
-    static Symbol rootSymbol(const Production& s)
+    static Symbol rootSymbol(ProductionPtr& s)
     {
-        return Symbol(Symbol::sRoot, RootInfo(s, Production()));
+        return Symbol(Symbol::sRoot, RootInfo(s, boost::make_shared<Production>()));
     }
 
-    static Symbol rootSymbol(const Production& main, const Production& backup)
+    static Symbol rootSymbol(const ProductionPtr& main,
+                             const ProductionPtr& backup)
     {
         return Symbol(Symbol::sRoot, RootInfo(main, backup));
     }
@@ -198,18 +202,21 @@ public:
         return Symbol(sMapEnd);
     }
 
-    static Symbol repeater(const Production& p, bool isArray) {
+    static Symbol repeater(const ProductionPtr& p,
+                           bool isArray) {
         size_t s = 0;
         return Symbol(sRepeater, boost::make_tuple(s, isArray, p, p));
     }
 
-    static Symbol repeater(const Production& read, const Production& skip,
-        bool isArray) {
+    static Symbol repeater(const ProductionPtr& read,
+                           const ProductionPtr& skip,
+                           bool isArray) {
         size_t s = 0;
         return Symbol(sRepeater, boost::make_tuple(s, isArray, read, skip));
     }
 
-    static Symbol alternative(const std::vector<Production>& branches)
+    static Symbol alternative(
+        const std::vector<ProductionPtr>& branches)
     {
         return Symbol(Symbol::sAlternative, branches);
     }
@@ -244,7 +251,7 @@ public:
         return Symbol(sPlaceholder, n);
     }
 
-    static Symbol indirect(const boost::shared_ptr<Production>& p) {
+    static Symbol indirect(const ProductionPtr& p) {
         return Symbol(sIndirect, p);
     }
 
@@ -255,7 +262,8 @@ public:
     static Symbol enumAdjustSymbol(const NodePtr& writer,
         const NodePtr& reader);
 
-    static Symbol unionAdjustSymbol(size_t branch, const Production& p) {
+    static Symbol unionAdjustSymbol(size_t branch,
+                                    const ProductionPtr& p) {
         return Symbol(sUnionAdjust, std::make_pair(branch, p));
     }
 
@@ -280,35 +288,52 @@ public:
 };
 
 template<typename T>
-void fixup(Production& p,
-    const std::map<T, boost::shared_ptr<Production> > &m)
+void fixup(const ProductionPtr& p,
+           const std::map<T, ProductionPtr> &m)
 {
-    for (Production::iterator it = p.begin(); it != p.end(); ++it) {
-        fixup(*it, m);
+    std::set<ProductionPtr> seen;
+    for (Production::iterator it = p->begin(); it != p->end(); ++it) {
+        fixup(*it, m, seen);
+    }
+}
+    
+
+template<typename T>
+void fixup_internal(const ProductionPtr& p,
+                    const std::map<T, ProductionPtr> &m,
+                    std::set<ProductionPtr>& seen)
+{
+    if (seen.find(p) == seen.end()) {
+        seen.insert(p);
+        for (Production::iterator it = p->begin(); it != p->end(); ++it) {
+            fixup(*it, m, seen);
+        }
     }
 }
 
 template<typename T>
-void fixup(Symbol& s, const std::map<T, boost::shared_ptr<Production> > &m)
+void fixup(Symbol& s, const std::map<T, ProductionPtr> &m,
+           std::set<ProductionPtr>& seen)
 {
     switch (s.kind()) {
     case Symbol::sIndirect:
-        fixup(*s.extra<boost::shared_ptr<Production> >(), m);
+        fixup_internal(s.extra<ProductionPtr>(), m, seen);
         break;
     case Symbol::sAlternative:
         {
-            std::vector<Production> *vv = s.extrap<std::vector<Production> >();
-            for (std::vector<Production>::iterator it = vv->begin();
+            const std::vector<ProductionPtr> *vv =
+            s.extrap<std::vector<ProductionPtr> >();
+            for (std::vector<ProductionPtr>::const_iterator it = vv->begin();
                 it != vv->end(); ++it) {
-                fixup(*it, m);
+                fixup_internal(*it, m, seen);
             }
         }
         break;
     case Symbol::sRepeater:
         {
-            RepeaterInfo& ri = *s.extrap<RepeaterInfo>();
-            fixup(boost::tuples::get<2>(ri), m);
-            fixup(boost::tuples::get<3>(ri), m);
+            const RepeaterInfo& ri = *s.extrap<RepeaterInfo>();
+            fixup_internal(boost::tuples::get<2>(ri), m, seen);
+            fixup_internal(boost::tuples::get<3>(ri), m, seen);
         }
     
         break;
@@ -317,7 +342,8 @@ void fixup(Symbol& s, const std::map<T, 
             m.find(s.extra<T>())->second));
         break;
     case Symbol::sUnionAdjust:
-        fixup(s.extrap<std::pair<size_t, Production> >()->second, m);
+        fixup_internal(s.extrap<std::pair<size_t, ProductionPtr> >()->second,
+                       m, seen);
         break;
     default:
         break;
@@ -347,9 +373,9 @@ class SimpleParser {
 
     }
 
-    void append(const Production& ss) {
-        for (Production::const_iterator it = ss.begin();
-            it != ss.end(); ++it) {
+    void append(const ProductionPtr& ss) {
+        for (Production::const_iterator it = ss->begin();
+            it != ss->end(); ++it) {
             parsingStack.push(*it);
         }
     }
@@ -386,18 +412,18 @@ public:
                     continue;
                 case Symbol::sIndirect:
                     {
-                        boost::shared_ptr<Production> pp =
-                            s.extra<boost::shared_ptr<Production> >();
+                        ProductionPtr pp =
+                            s.extra<ProductionPtr>();
                         parsingStack.pop();
-                        append(*pp);
+                        append(pp);
                     }
                     continue;
                 case Symbol::sSymbolic:
                     {
-                        boost::shared_ptr<Production> pp(
+                        ProductionPtr pp(
                             s.extra<boost::weak_ptr<Production> >());
                         parsingStack.pop();
-                        append(*pp);
+                        append(pp);
                     }
                     continue;
                 case Symbol::sRepeater:
@@ -538,18 +564,18 @@ public:
                 break;
             case Symbol::sIndirect:
                 {
-                    boost::shared_ptr<Production> pp =
-                        t.extra<boost::shared_ptr<Production> >();
+                    ProductionPtr pp =
+                        t.extra<ProductionPtr>();
                     parsingStack.pop();
-                    append(*pp);
+                    append(pp);
                 }
                 continue;
             case Symbol::sSymbolic:
                 {
-                    boost::shared_ptr<Production> pp(
+                    ProductionPtr pp(
                         t.extra<boost::weak_ptr<Production> >());
                     parsingStack.pop();
-                    append(*pp);
+                    append(pp);
                 }
                 continue;
             default:
@@ -598,8 +624,8 @@ public:
     size_t unionAdjust() {
         const Symbol& s = parsingStack.top();
         assertMatch(Symbol::sUnionAdjust, s.kind());
-        std::pair<size_t, Production> p = s.extra<std::pair<size_t,
-            Production> >();
+        std::pair<size_t, ProductionPtr> p =
+        s.extra<std::pair<size_t, ProductionPtr> >();
         parsingStack.pop();
         append(p.second);
         return p.first;
@@ -656,7 +682,8 @@ public:
     void selectBranch(size_t n) {
         const Symbol& s = parsingStack.top();
         assertMatch(Symbol::sAlternative, s.kind());
-        std::vector<Production> v = s.extra<std::vector<Production> >();
+        std::vector<ProductionPtr> v =
+        s.extra<std::vector<ProductionPtr> >();
         if (n >= v.size()) {
             throw Exception("Not that many branches");
         }

Modified: avro/trunk/lang/c++/impl/parsing/ValidatingCodec.cc
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c%2B%2B/impl/parsing/ValidatingCodec.cc?rev=1556285&r1=1556284&r2=1556285&view=diff
==============================================================================
--- avro/trunk/lang/c++/impl/parsing/ValidatingCodec.cc (original)
+++ avro/trunk/lang/c++/impl/parsing/ValidatingCodec.cc Tue Jan  7 17:30:38 2014
@@ -38,6 +38,7 @@ namespace parsing {
 using boost::shared_ptr;
 using boost::weak_ptr;
 using boost::static_pointer_cast;
+using boost::make_shared;
 
 using std::map;
 using std::vector;
@@ -47,118 +48,113 @@ using std::reverse;
 using std::ostringstream;
 
 /** Follows the design of Avro Parser in Java. */
-Production ValidatingGrammarGenerator::generate(const NodePtr& n)
+ProductionPtr ValidatingGrammarGenerator::generate(const NodePtr& n)
 {
-    map<NodePtr, shared_ptr<Production> > m;
-    Production result = doGenerate(n, m);
+    map<NodePtr, ProductionPtr> m;
+    ProductionPtr result = doGenerate(n, m);
     fixup(result, m);
     return result;
 }
 
 Symbol ValidatingGrammarGenerator::generate(const ValidSchema& schema)
 {
-    return Symbol::rootSymbol(generate(schema.root()));
+    ProductionPtr r = generate(schema.root());
+    return Symbol::rootSymbol(r);
 }
 
-Production ValidatingGrammarGenerator::doGenerate(const NodePtr& n,
-    map<NodePtr, shared_ptr<Production> > &m) {
+ProductionPtr ValidatingGrammarGenerator::doGenerate(const NodePtr& n,
+    map<NodePtr, ProductionPtr> &m) {
     switch (n->type()) {
     case AVRO_NULL:
-        return Production(1, Symbol::nullSymbol());
+        return make_shared<Production>(1, Symbol::nullSymbol());
     case AVRO_BOOL:
-        return Production(1, Symbol::boolSymbol());
+        return make_shared<Production>(1, Symbol::boolSymbol());
     case AVRO_INT:
-        return Production(1, Symbol::intSymbol());
+        return make_shared<Production>(1, Symbol::intSymbol());
     case AVRO_LONG:
-        return Production(1, Symbol::longSymbol());
+        return make_shared<Production>(1, Symbol::longSymbol());
     case AVRO_FLOAT:
-        return Production(1, Symbol::floatSymbol());
+        return make_shared<Production>(1, Symbol::floatSymbol());
     case AVRO_DOUBLE:
-        return Production(1, Symbol::doubleSymbol());
+        return make_shared<Production>(1, Symbol::doubleSymbol());
     case AVRO_STRING:
-        return Production(1, Symbol::stringSymbol());
+        return make_shared<Production>(1, Symbol::stringSymbol());
     case AVRO_BYTES:
-        return Production(1, Symbol::bytesSymbol());
+        return make_shared<Production>(1, Symbol::bytesSymbol());
     case AVRO_FIXED:
         {
-            Symbol r[] = {
-                Symbol::sizeCheckSymbol(n->fixedSize()),
-                Symbol::fixedSymbol() };
-            Production result(r, r + 2);
-            m[n] = boost::make_shared<Production>(result);
+            ProductionPtr result = make_shared<Production>();
+            result->push_back(Symbol::sizeCheckSymbol(n->fixedSize()));
+            result->push_back(Symbol::fixedSymbol());
+            m[n] = result;
             return result;
         }
-    case AVRO_RECORD: {
-            Production result;
+    case AVRO_RECORD:
+        {
+            ProductionPtr result = make_shared<Production>();
 
             m.erase(n);
             size_t c = n->leaves();
             for (size_t i = 0; i < c; ++i) {
                 const NodePtr& leaf = n->leafAt(i);
-                Production v = doGenerate(leaf, m);
-                copy(v.rbegin(), v.rend(), back_inserter(result));
+                ProductionPtr v = doGenerate(leaf, m);
+                copy(v->rbegin(), v->rend(), back_inserter(*result));
             }
-            reverse(result.begin(), result.end());
-
-            bool found = m.find(n) != m.end();
+            reverse(result->begin(), result->end());
 
-            shared_ptr<Production> p = boost::make_shared<Production>(result);
-            m[n] = p;
-
-            return found ? Production(1, Symbol::indirect(p)) : result;
+            m[n] = result;
+            return result;
         }
     case AVRO_ENUM:
         {
-            Symbol r[] = {
-                Symbol::sizeCheckSymbol(n->names()),
-                Symbol::enumSymbol() };
-            Production result(r, r + 2);
-            m[n] = boost::make_shared<Production>(result);
+            ProductionPtr result = make_shared<Production>();
+            result->push_back(Symbol::sizeCheckSymbol(n->names()));
+            result->push_back(Symbol::enumSymbol());
+            m[n] = result;
             return result;
         }
     case AVRO_ARRAY:
         {
-            Symbol r[] = {
-                Symbol::arrayEndSymbol(),
-                Symbol::repeater(doGenerate(n->leafAt(0), m), true),
-                Symbol::arrayStartSymbol() };
-            return Production(r, r + 3);
+            ProductionPtr result = make_shared<Production>();
+            result->push_back(Symbol::arrayEndSymbol());
+            result->push_back(Symbol::repeater(doGenerate(n->leafAt(0), m), true));
+            result->push_back(Symbol::arrayStartSymbol());
+            return result;
         }
     case AVRO_MAP:
         {
-            Production v = doGenerate(n->leafAt(1), m);
-            v.push_back(Symbol::stringSymbol());
-            Symbol r[] = {
-                Symbol::mapEndSymbol(),
-                Symbol::repeater(v, false),
-                Symbol::mapStartSymbol() };
-            return Production(r, r + 3);
+            ProductionPtr v = doGenerate(n->leafAt(1), m);
+            v->push_back(Symbol::stringSymbol());
+            ProductionPtr result = make_shared<Production>();
+            result->push_back(Symbol::mapEndSymbol());
+            result->push_back(Symbol::repeater(v, false));
+            result->push_back(Symbol::mapStartSymbol());
+            return result;
         }
     case AVRO_UNION:
         {
-            vector<Production> vv;
+            vector<ProductionPtr> vv;
             size_t c = n->leaves();
             vv.reserve(c);
             for (size_t i = 0; i < c; ++i) {
                 vv.push_back(doGenerate(n->leafAt(i), m));
             }
-            Symbol r[] = {
-                Symbol::alternative(vv),
-                Symbol::unionSymbol()
-            };
-            return Production(r, r + 2);
+            ProductionPtr result = make_shared<Production>();
+            result->push_back(Symbol::alternative(vv));
+            result->push_back(Symbol::unionSymbol());
+            return result;
         }
     case AVRO_SYMBOLIC:
         {
             shared_ptr<NodeSymbolic> ns = static_pointer_cast<NodeSymbolic>(n);
             NodePtr nn = ns->getNode();
-            map<NodePtr, shared_ptr<Production> >::iterator it =
+            map<NodePtr, ProductionPtr>::iterator it =
                 m.find(nn);
             if (it != m.end() && it->second) {
-                return *it->second;
+                return it->second;
             } else {
-                m[nn] = shared_ptr<Production>();
-                return Production(1, Symbol::placeholder(nn));
+                m[nn] = ProductionPtr();
+                return make_shared<Production>(1, Symbol::placeholder(nn));
             }
         }
     default:

Modified: avro/trunk/lang/c++/impl/parsing/ValidatingCodec.hh
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c%2B%2B/impl/parsing/ValidatingCodec.hh?rev=1556285&r1=1556284&r2=1556285&view=diff
==============================================================================
--- avro/trunk/lang/c++/impl/parsing/ValidatingCodec.hh (original)
+++ avro/trunk/lang/c++/impl/parsing/ValidatingCodec.hh Tue Jan  7 17:30:38 2014
@@ -33,16 +33,14 @@ namespace parsing {
 class ValidatingGrammarGenerator {
 protected:
     template<typename T>
-    static void doFixup(Production& p,
-        const std::map<T, boost::shared_ptr<Production> > &m);
+    static void doFixup(Production& p, const std::map<T, ProductionPtr> &m);
 
     template<typename T>
-    static void doFixup(Symbol &s,
-        const std::map<T, boost::shared_ptr<Production> > &m);
-    virtual Production doGenerate(const NodePtr& n,
-        std::map<NodePtr, boost::shared_ptr<Production> > &m);
+    static void doFixup(Symbol &s, const std::map<T, ProductionPtr> &m);
+    virtual ProductionPtr doGenerate(const NodePtr& n,
+        std::map<NodePtr, ProductionPtr> &m);
 
-    Production generate(const NodePtr& schema);
+    ProductionPtr generate(const NodePtr& schema);
 public:
     Symbol generate(const ValidSchema& schema);
 

Added: avro/trunk/lang/c++/jsonschemas/large_schema.avsc
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c%2B%2B/jsonschemas/large_schema.avsc?rev=1556285&view=auto
==============================================================================
--- avro/trunk/lang/c++/jsonschemas/large_schema.avsc (added)
+++ avro/trunk/lang/c++/jsonschemas/large_schema.avsc Tue Jan  7 17:30:38 2014
@@ -0,0 +1 @@

[... 3 lines stripped ...]
Modified: avro/trunk/lang/c++/test/JsonTests.cc
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c%2B%2B/test/JsonTests.cc?rev=1556285&r1=1556284&r2=1556285&view=diff
==============================================================================
--- avro/trunk/lang/c++/test/JsonTests.cc (original)
+++ avro/trunk/lang/c++/test/JsonTests.cc Tue Jan  7 17:30:38 2014
@@ -67,26 +67,33 @@ TestData<const char*> stringData[] = {
     { "\"\\/\"", etString, "/" },
 };
 
-template <typename T>
-void testPrimitive(const TestData<T>& d)
+void testBool(const TestData<bool>& d)
 {
     Entity n = loadEntity(d.input);
     BOOST_CHECK_EQUAL(n.type(), d.type);
-    BOOST_CHECK_EQUAL(n.value<T>(), d.value);
+    BOOST_CHECK_EQUAL(n.boolValue(), d.value);
+}
+
+    
+void testLong(const TestData<int64_t>& d)
+{
+    Entity n = loadEntity(d.input);
+    BOOST_CHECK_EQUAL(n.type(), d.type);
+    BOOST_CHECK_EQUAL(n.longValue(), d.value);
 }
 
 void testDouble(const TestData<double>& d)
 {
     Entity n = loadEntity(d.input);
     BOOST_CHECK_EQUAL(n.type(), d.type);
-    BOOST_CHECK_CLOSE(n.value<double>(), d.value, 1e-10);
+    BOOST_CHECK_CLOSE(n.doubleValue(), d.value, 1e-10);
 }
 
 void testString(const TestData<const char*>& d)
 {
     Entity n = loadEntity(d.input);
     BOOST_CHECK_EQUAL(n.type(), d.type);
-    BOOST_CHECK_EQUAL(n.value<std::string>(), d.value);
+    BOOST_CHECK_EQUAL(n.stringValue(), d.value);
 }
 
 static void testNull()
@@ -100,7 +107,7 @@ static void testArray0()
 {
     Entity n = loadEntity("[]");
     BOOST_CHECK_EQUAL(n.type(), etArray);
-    const std::vector<Entity>& a = n.value<std::vector<Entity> >();
+    const Array& a = n.arrayValue();
     BOOST_CHECK_EQUAL(a.size(), 0);
 }
 
@@ -108,30 +115,29 @@ static void testArray1()
 {
     Entity n = loadEntity("[200]");
     BOOST_CHECK_EQUAL(n.type(), etArray);
-    const std::vector<Entity>& a = n.value<std::vector<Entity> >();
+    const Array& a = n.arrayValue();
     BOOST_CHECK_EQUAL(a.size(), 1);
     BOOST_CHECK_EQUAL(a[0].type(), etLong);
-    BOOST_CHECK_EQUAL(a[0].value<int64_t>(), 200ll);
+    BOOST_CHECK_EQUAL(a[0].longValue(), 200ll);
 }
 
 static void testArray2()
 {
     Entity n = loadEntity("[200, \"v100\"]");
     BOOST_CHECK_EQUAL(n.type(), etArray);
-    const std::vector<Entity>& a = n.value<std::vector<Entity> >();
+    const Array& a = n.arrayValue();
     BOOST_CHECK_EQUAL(a.size(), 2);
     BOOST_CHECK_EQUAL(a[0].type(), etLong);
-    BOOST_CHECK_EQUAL(a[0].value<int64_t>(), 200ll);
+    BOOST_CHECK_EQUAL(a[0].longValue(), 200ll);
     BOOST_CHECK_EQUAL(a[1].type(), etString);
-    BOOST_CHECK_EQUAL(a[1].value<std::string>(), "v100");
+    BOOST_CHECK_EQUAL(a[1].stringValue(), "v100");
 }
 
 static void testObject0()
 {
     Entity n = loadEntity("{}");
     BOOST_CHECK_EQUAL(n.type(), etObject);
-    const std::map<std::string, Entity>& m =
-        n.value<std::map<std::string, Entity> >();
+    const Object& m = n.objectValue();
     BOOST_CHECK_EQUAL(m.size(), 0);
 }
 
@@ -139,36 +145,34 @@ static void testObject1()
 {
     Entity n = loadEntity("{\"k1\": 100}");
     BOOST_CHECK_EQUAL(n.type(), etObject);
-    const std::map<std::string, Entity>& m =
-        n.value<std::map<std::string, Entity> >();
+    const Object& m = n.objectValue();
     BOOST_CHECK_EQUAL(m.size(), 1);
     BOOST_CHECK_EQUAL(m.begin()->first, "k1");
     BOOST_CHECK_EQUAL(m.begin()->second.type(), etLong);
-    BOOST_CHECK_EQUAL(m.begin()->second.value<int64_t>(), 100ll);
+    BOOST_CHECK_EQUAL(m.begin()->second.longValue(), 100ll);
 }
 
 static void testObject2()
 {
     Entity n = loadEntity("{\"k1\": 100, \"k2\": [400, \"v0\"]}");
     BOOST_CHECK_EQUAL(n.type(), etObject);
-    const std::map<std::string, Entity>& m =
-        n.value<std::map<std::string, Entity> >();
+    const Object& m = n.objectValue();
     BOOST_CHECK_EQUAL(m.size(), 2);
 
-    std::map<std::string, Entity>::const_iterator it = m.find("k1");
+    Object::const_iterator it = m.find("k1");
     BOOST_CHECK(it != m.end());
     BOOST_CHECK_EQUAL(it->second.type(), etLong);
-    BOOST_CHECK_EQUAL(m.begin()->second.value<int64_t>(), 100ll);
+    BOOST_CHECK_EQUAL(m.begin()->second.longValue(), 100ll);
 
     it = m.find("k2");
     BOOST_CHECK(it != m.end());
     BOOST_CHECK_EQUAL(it->second.type(), etArray);
-    const std::vector<Entity>& a = it->second.value<std::vector<Entity> >();
+    const Array& a = it->second.arrayValue();
     BOOST_CHECK_EQUAL(a.size(), 2);
     BOOST_CHECK_EQUAL(a[0].type(), etLong);
-    BOOST_CHECK_EQUAL(a[0].value<int64_t>(), 400ll);
+    BOOST_CHECK_EQUAL(a[0].longValue(), 400ll);
     BOOST_CHECK_EQUAL(a[1].type(), etString);
-    BOOST_CHECK_EQUAL(a[1].value<std::string>(), "v0");
+    BOOST_CHECK_EQUAL(a[1].stringValue(), "v0");
 }
 
 }
@@ -184,10 +188,10 @@ init_unit_test_suite( int argc, char* ar
     test_suite* ts= BOOST_TEST_SUITE("Avro C++ unit tests for json routines");
 
     ts->add(BOOST_TEST_CASE(&avro::json::testNull));
-    ts->add(BOOST_PARAM_TEST_CASE(&avro::json::testPrimitive<bool>,
+    ts->add(BOOST_PARAM_TEST_CASE(&avro::json::testBool,
         avro::json::boolData,
         avro::json::boolData + COUNTOF(avro::json::boolData)));
-    ts->add(BOOST_PARAM_TEST_CASE(&avro::json::testPrimitive<int64_t>,
+    ts->add(BOOST_PARAM_TEST_CASE(&avro::json::testLong,
         avro::json::longData,
         avro::json::longData + COUNTOF(avro::json::longData)));
     ts->add(BOOST_PARAM_TEST_CASE(&avro::json::testDouble,

Added: avro/trunk/lang/c++/test/LargeSchemaTests.cc
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c%2B%2B/test/LargeSchemaTests.cc?rev=1556285&view=auto
==============================================================================
--- avro/trunk/lang/c++/test/LargeSchemaTests.cc (added)
+++ avro/trunk/lang/c++/test/LargeSchemaTests.cc Tue Jan  7 17:30:38 2014
@@ -0,0 +1,46 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <fstream>
+#include "Compiler.hh"
+#include "ValidSchema.hh"
+#include "Decoder.hh"
+
+#include <boost/test/included/unit_test_framework.hpp>
+#include <boost/test/unit_test.hpp>
+#include <boost/test/parameterized_test.hpp>
+
+void testLargeSchema()
+{
+    std::ifstream in("jsonschemas/large_schema.avsc");
+    avro::ValidSchema vs;
+    avro::compileJsonSchema(in, vs);
+    avro::DecoderPtr d = avro::binaryDecoder();
+    avro::DecoderPtr vd = avro::validatingDecoder(vs, d);
+    avro::DecoderPtr rd = avro::resolvingDecoder(vs, vs, d);
+}
+
+boost::unit_test::test_suite*
+init_unit_test_suite(int argc, char* argv[]) 
+{
+    using namespace boost::unit_test;
+
+    test_suite* ts= BOOST_TEST_SUITE("Avro C++ unit tests for schemas");
+    ts->add(BOOST_TEST_CASE(&testLargeSchema));
+    return ts;
+}



Mime
View raw message