You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@avro.apache.org by th...@apache.org on 2012/05/20 18:51:46 UTC
svn commit: r1340768 - in /avro/trunk: ./ lang/c++/ lang/c++/api/
lang/c++/impl/ lang/c++/jsonschemas/ lang/c++/test/
Author: thiru
Date: Sun May 20 16:51:44 2012
New Revision: 1340768
URL: http://svn.apache.org/viewvc?rev=1340768&view=rev
Log:
AVRO-1026. Add namespace support to C++
Added:
avro/trunk/lang/c++/jsonschemas/tweet
Modified:
avro/trunk/CHANGES.txt
avro/trunk/lang/c++/CMakeLists.txt
avro/trunk/lang/c++/api/Config.hh
avro/trunk/lang/c++/api/Node.hh
avro/trunk/lang/c++/api/NodeConcepts.hh
avro/trunk/lang/c++/api/NodeImpl.hh
avro/trunk/lang/c++/api/Schema.hh
avro/trunk/lang/c++/impl/Compiler.cc
avro/trunk/lang/c++/impl/Node.cc
avro/trunk/lang/c++/impl/NodeImpl.cc
avro/trunk/lang/c++/impl/Schema.cc
avro/trunk/lang/c++/impl/ValidSchema.cc
avro/trunk/lang/c++/impl/Validator.cc
avro/trunk/lang/c++/impl/avrogencpp.cc
avro/trunk/lang/c++/test/AvrogencppTests.cc
avro/trunk/lang/c++/test/unittest.cc
Modified: avro/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/avro/trunk/CHANGES.txt?rev=1340768&r1=1340767&r2=1340768&view=diff
==============================================================================
--- avro/trunk/CHANGES.txt (original)
+++ avro/trunk/CHANGES.txt Sun May 20 16:51:44 2012
@@ -48,6 +48,7 @@ Avro 1.7.0 (unreleased)
AVRO-1095. C++ compiler warns about control reaching end of doAdavance (in JsonIO.cc) which returns something other than void. (thiru)
+ AVRO-1026. Add namespace support to C++. (Keh-Li Sheng via thiru)
BUG FIXES
AVRO-1045. Java: Fix a bug in GenericData#deepCopy() of ByteBuffer values.
Modified: avro/trunk/lang/c++/CMakeLists.txt
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c%2B%2B/CMakeLists.txt?rev=1340768&r1=1340767&r2=1340768&view=diff
==============================================================================
--- avro/trunk/lang/c++/CMakeLists.txt (original)
+++ avro/trunk/lang/c++/CMakeLists.txt Sun May 20 16:51:44 2012
@@ -124,6 +124,7 @@ endmacro (gen)
gen (bigrecord testgen)
gen (bigrecord2 testgen2)
+gen (tweet testgen3)
gen (union_array_union uau)
gen (union_map_union umu)
gen (union_conflict uc)
@@ -158,7 +159,7 @@ if (CYGWIN OR NOT WIN32)
add_dependencies (testgentest testgen testgen2)
endif()
-add_dependencies (AvrogencppTests bigrecord_hh bigrecord2_hh
+add_dependencies (AvrogencppTests bigrecord_hh bigrecord2_hh tweet_hh
union_array_union_hh union_map_union_hh union_conflict_hh
recursive_hh reuse_hh circulardep_hh)
Modified: avro/trunk/lang/c++/api/Config.hh
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c%2B%2B/api/Config.hh?rev=1340768&r1=1340767&r2=1340768&view=diff
==============================================================================
--- avro/trunk/lang/c++/api/Config.hh (original)
+++ avro/trunk/lang/c++/api/Config.hh Sun May 20 16:51:44 2012
@@ -22,6 +22,8 @@
// Windows DLL suport
#ifdef _WIN32
+#pragma warning (disable: 4275 4251)
+
#if defined(AVRO_DYN_LINK)
#ifdef AVRO_SOURCE
# define AVRO_DECL __declspec(dllexport)
Modified: avro/trunk/lang/c++/api/Node.hh
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c%2B%2B/api/Node.hh?rev=1340768&r1=1340767&r2=1340768&view=diff
==============================================================================
--- avro/trunk/lang/c++/api/Node.hh (original)
+++ avro/trunk/lang/c++/api/Node.hh Sun May 20 16:51:44 2012
@@ -19,11 +19,12 @@
#ifndef avro_Node_hh__
#define avro_Node_hh__
+#include "Config.hh"
+
#include <cassert>
#include <boost/noncopyable.hpp>
#include <boost/shared_ptr.hpp>
-#include "Config.hh"
#include "Exception.hh"
#include "Types.hh"
#include "SchemaResolution.hh"
@@ -34,6 +35,39 @@ class Node;
typedef boost::shared_ptr<Node> NodePtr;
+class AVRO_DECL Name {
+ std::string ns_;
+ std::string simpleName_;
+public:
+ Name() { }
+ Name(const std::string& fullname);
+ Name(const std::string& simpleName, const std::string& ns) : ns_(ns), simpleName_(simpleName) { check(); }
+
+ const std::string fullname() const;
+ const std::string& ns() const { return ns_; }
+ const std::string& simpleName() const { return simpleName_; }
+
+ void ns(const std::string& n) { ns_ = n; }
+ void simpleName(const std::string& n) { simpleName_ = n; }
+ void fullname(const std::string& n);
+
+ bool operator < (const Name& n) const;
+ void check() const;
+ bool operator == (const Name& n) const;
+ bool operator != (const Name& n) const { return !((*this) == n); }
+ void clear() {
+ ns_.clear();
+ simpleName_.clear();
+ }
+ operator std::string() const {
+ return fullname();
+ }
+};
+
+inline
+std::ostream& operator << (std::ostream& os, const Name& n) {
+ return os << n.fullname();
+}
/// Node is the building block for parse trees. Each node represents an avro
/// type. Compound types have leaf nodes that represent the types they are
@@ -75,12 +109,12 @@ class AVRO_DECL Node : private boost::no
virtual bool hasName() const = 0;
- void setName(const std::string &name) {
+ void setName(const Name &name) {
checkLock();
checkName(name);
doSetName(name);
}
- virtual const std::string &name() const = 0;
+ virtual const Name &name() const = 0;
void addLeaf(const NodePtr &newLeaf) {
checkLock();
@@ -122,9 +156,11 @@ class AVRO_DECL Node : private boost::no
}
}
- void checkName(const std::string &name) const;
+ virtual void checkName(const Name &name) const {
+ name.check();
+ }
- virtual void doSetName(const std::string &name) = 0;
+ virtual void doSetName(const Name &name) = 0;
virtual void doAddLeaf(const NodePtr &newLeaf) = 0;
virtual void doAddName(const std::string &name) = 0;
virtual void doSetFixedSize(int size) = 0;
Modified: avro/trunk/lang/c++/api/NodeConcepts.hh
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c%2B%2B/api/NodeConcepts.hh?rev=1340768&r1=1340767&r2=1340768&view=diff
==============================================================================
--- avro/trunk/lang/c++/api/NodeConcepts.hh (original)
+++ avro/trunk/lang/c++/api/NodeConcepts.hh Sun May 20 16:51:44 2012
@@ -19,9 +19,10 @@
#ifndef avro_NodeConcepts_hh__
#define avro_NodeConcepts_hh__
+#include "Config.hh"
+
#include <vector>
#include <map>
-#include "Config.hh"
#include "Exception.hh"
namespace avro {
@@ -72,6 +73,13 @@ struct NoAttribute
return empty;
}
+ Attribute &get(size_t index = 0) {
+ // There must be an get function for the generic NodeImpl, but the
+ // Node APIs ensure that it is never called, the throw here is
+ // just in case
+ throw Exception("This type does not have attribute");
+ }
+
};
template<typename Attribute>
@@ -79,47 +87,45 @@ struct SingleAttribute
{
static const bool hasAttribute = true;
- SingleAttribute() : attr_(), size_(0)
+ SingleAttribute() : attr_()
{ }
- SingleAttribute(const Attribute& a) : attr_(a), size_(1) { }
+ SingleAttribute(const Attribute& a) : attr_(a) { }
// copy constructing from another single attribute is allowed
SingleAttribute(const SingleAttribute<Attribute> &rhs) :
- attr_(rhs.attr_), size_(rhs.size_)
+ attr_(rhs.attr_)
{ }
// copy constructing from a no attribute is allowed
SingleAttribute(const NoAttribute<Attribute> &rhs) :
- attr_(), size_(0)
+ attr_()
{ }
size_t size() const {
- return size_;
+ return 1;
}
void add(const Attribute &attr) {
- if(size_ == 0) {
- size_ = 1;
- }
- else {
- throw Exception("SingleAttribute can only be set once");
- }
attr_ = attr;
}
const Attribute &get(size_t index = 0) const {
- if(index != 0) {
+ if (index != 0) {
throw Exception("SingleAttribute has only 1 value");
}
return attr_;
}
- private:
+ Attribute &get(size_t index = 0) {
+ if (index != 0) {
+ throw Exception("SingleAttribute has only 1 value");
+ }
+ return attr_;
+ }
+private:
template<typename T> friend struct MultiAttribute;
-
Attribute attr_;
- int size_;
};
template<typename Attribute>
Modified: avro/trunk/lang/c++/api/NodeImpl.hh
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c%2B%2B/api/NodeImpl.hh?rev=1340768&r1=1340767&r2=1340768&view=diff
==============================================================================
--- avro/trunk/lang/c++/api/NodeImpl.hh (original)
+++ avro/trunk/lang/c++/api/NodeImpl.hh Sun May 20 16:51:44 2012
@@ -19,11 +19,12 @@
#ifndef avro_NodeImpl_hh__
#define avro_NodeImpl_hh__
+#include "Config.hh"
+
#include <limits>
#include <set>
#include <boost/weak_ptr.hpp>
-#include "Config.hh"
#include "Node.hh"
#include "NodeConcepts.hh"
@@ -71,15 +72,16 @@ class NodeImpl : public Node
std::swap(sizeAttribute_, impl.sizeAttribute_);
std::swap(nameIndex_, impl.nameIndex_);
}
+
bool hasName() const {
return NameConcept::hasAttribute;
}
- void doSetName(const std::string &name) {
+ void doSetName(const Name &name) {
nameAttribute_.add(name);
}
- const std::string &name() const {
+ const Name &name() const {
return nameAttribute_.get();
}
@@ -96,7 +98,7 @@ class NodeImpl : public Node
}
void doAddName(const std::string &name) {
- if(! nameIndex_.add(name, leafNameAttributes_.size())) {
+ if (! nameIndex_.add(name, leafNameAttributes_.size())) {
throw Exception(boost::format("Cannot add duplicate name: %1%") % name);
}
leafNameAttributes_.add(name);
@@ -128,7 +130,42 @@ class NodeImpl : public Node
void setLeafToSymbolic(int index, const NodePtr &node);
- SchemaResolution furtherResolution(const Node &node) const;
+ SchemaResolution furtherResolution(const Node &reader) const {
+ SchemaResolution match = RESOLVE_NO_MATCH;
+
+ if (reader.type() == AVRO_SYMBOLIC) {
+
+ // resolve the symbolic type, and check again
+ const NodePtr &node = reader.leafAt(0);
+ match = resolve(*node);
+ }
+ else if(reader.type() == AVRO_UNION) {
+
+ // in this case, need to see if there is an exact match for the
+ // writer's type, or if not, the first one that can be promoted to a
+ // match
+
+ for(size_t i= 0; i < reader.leaves(); ++i) {
+
+ const NodePtr &node = reader.leafAt(i);
+ SchemaResolution thisMatch = resolve(*node);
+
+ // if matched then the search is done
+ if(thisMatch == RESOLVE_MATCH) {
+ match = thisMatch;
+ break;
+ }
+
+ // thisMatch is either no match, or promotable, this will set match to
+ // promotable if it hasn't been set already
+ if (match == RESOLVE_NO_MATCH) {
+ match = thisMatch;
+ }
+ }
+ }
+
+ return match;
+ }
NameConcept nameAttribute_;
LeavesConcept leafAttributes_;
@@ -137,8 +174,8 @@ class NodeImpl : public Node
concepts::NameIndexConcept<LeafNamesConcept> nameIndex_;
};
-typedef concepts::NoAttribute<std::string> NoName;
-typedef concepts::SingleAttribute<std::string> HasName;
+typedef concepts::NoAttribute<Name> NoName;
+typedef concepts::SingleAttribute<Name> HasName;
typedef concepts::NoAttribute<NodePtr> NoLeaves;
typedef concepts::SingleAttribute<NodePtr> SingleLeaf;
@@ -398,7 +435,7 @@ class AVRO_DECL NodeUnion : public NodeI
case AVRO_UNION:
case AVRO_FIXED:
case AVRO_SYMBOLIC:
- name = n->name();
+ name = n->name().fullname();
break;
default:
return false;
@@ -465,8 +502,9 @@ NodeImpl<A,B,C,D>::printBasicInfo(std::o
{
os << type();
if(hasName()) {
- os << " " << nameAttribute_.get();
+ os << ' ' << nameAttribute_.get();
}
+
if(D::hasAttribute) {
os << " " << sizeAttribute_.get();
}
Modified: avro/trunk/lang/c++/api/Schema.hh
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c%2B%2B/api/Schema.hh?rev=1340768&r1=1340767&r2=1340768&view=diff
==============================================================================
--- avro/trunk/lang/c++/api/Schema.hh (original)
+++ avro/trunk/lang/c++/api/Schema.hh Sun May 20 16:51:44 2012
@@ -133,7 +133,7 @@ public:
class AVRO_DECL SymbolicSchema : public Schema {
public:
- SymbolicSchema(const std::string& name, const NodePtr& link);
+ SymbolicSchema(const Name& name, const NodePtr& link);
};
} // namespace avro
Modified: avro/trunk/lang/c++/impl/Compiler.cc
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c%2B%2B/impl/Compiler.cc?rev=1340768&r1=1340767&r2=1340768&view=diff
==============================================================================
--- avro/trunk/lang/c++/impl/Compiler.cc (original)
+++ avro/trunk/lang/c++/impl/Compiler.cc Sun May 20 16:51:44 2012
@@ -15,6 +15,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+#include <sstream>
#include "Compiler.hh"
#include "Types.hh"
@@ -32,7 +33,7 @@ using std::vector;
namespace avro {
-typedef map<string, NodePtr> SymbolTable;
+typedef map<Name, NodePtr> SymbolTable;
using json::Entity;
@@ -61,7 +62,7 @@ static NodePtr makePrimitive(const std::
}
}
-static NodePtr makeNode(const json::Entity& e, SymbolTable& st);
+static NodePtr makeNode(const json::Entity& e, SymbolTable& st, const string& ns);
template <typename T>
concepts::SingleAttribute<T> asSingleAttribute(const T& t)
@@ -71,17 +72,29 @@ concepts::SingleAttribute<T> asSingleAtt
return n;
}
-static NodePtr makeNode(const std::string& t, SymbolTable& st)
+static bool isFullName(const string& s)
+{
+ return s.find('.') != string::npos;
+}
+
+static Name getName(const string& name, const string& ns)
+{
+ return (isFullName(name)) ? Name(name) : Name(name, ns);
+}
+
+static NodePtr makeNode(const std::string& t, SymbolTable& st, const string& ns)
{
NodePtr result = makePrimitive(t);
if (result) {
return result;
}
- map<string, NodePtr>::const_iterator it = st.find(t);
+ Name n = getName(t, ns);
+
+ map<Name, NodePtr>::const_iterator it = st.find(n);
if (it != st.end()) {
- return NodePtr(new NodeSymbolic(asSingleAttribute(t), it->second));
+ return NodePtr(new NodeSymbolic(asSingleAttribute(n), it->second));
}
- throw Exception(boost::format("Unknown type: %1%") % t);
+ throw Exception(boost::format("Unknown type: %1%") % n.fullname());
}
const map<string, Entity>::const_iterator findField(const Entity& e,
@@ -117,22 +130,23 @@ struct Field {
Field(const string& n, const NodePtr& v) : name(n), value(v) { }
};
-static Field makeField(const Entity& e, SymbolTable& st)
+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");
- return Field(n, makeNode(it->second, st));
+ return Field(n, makeNode(it->second, st, ns));
}
static NodePtr makeRecordNode(const Entity& e,
- const string& name, const map<string, Entity>& m, SymbolTable& st)
-{
+ const Name& name, const map<string, Entity>& m, SymbolTable& st, const string& ns)
+{
const vector<Entity>& v = getField<vector<Entity> >(e, m, "fields");
concepts::MultiAttribute<string> fieldNames;
concepts::MultiAttribute<NodePtr> fieldValues;
+
for (vector<Entity>::const_iterator it = v.begin(); it != v.end(); ++it) {
- Field f = makeField(*it, st);
+ Field f = makeField(*it, st, ns);
fieldNames.add(f.name);
fieldValues.add(f.value);
}
@@ -141,7 +155,7 @@ static NodePtr makeRecordNode(const Enti
}
static NodePtr makeEnumNode(const Entity& e,
- const string& name, const map<string, Entity>& m)
+ const Name& name, const map<string, Entity>& m)
{
const vector<Entity>& v = getField<vector<Entity> >(e, m, "symbols");
concepts::MultiAttribute<string> symbols;
@@ -156,37 +170,58 @@ static NodePtr makeEnumNode(const Entity
}
static NodePtr makeFixedNode(const Entity& e,
- const string& name, const map<string, Entity>& m)
+ const Name& name, const map<string, Entity>& m)
{
int v = static_cast<int>(getField<int64_t>(e, m, "size"));
if (v <= 0) {
throw Exception(boost::format("Size for fixed is not positive: ") %
e.toString());
}
-
return NodePtr(new NodeFixed(asSingleAttribute(name),
asSingleAttribute(v)));
}
static NodePtr makeArrayNode(const Entity& e, const map<string, Entity>& m,
- SymbolTable& st)
+ SymbolTable& st, const string& ns)
{
map<string, Entity>::const_iterator it = findField(e, m, "items");
return NodePtr(new NodeArray(asSingleAttribute(
- makeNode(it->second, st))));
+ makeNode(it->second, st, ns))));
}
static NodePtr makeMapNode(const Entity& e, const map<string, Entity>& m,
- SymbolTable& st)
+ SymbolTable& st, const string& ns)
{
map<string, Entity>::const_iterator it = findField(e, m, "values");
return NodePtr(new NodeMap(asSingleAttribute(
- makeNode(it->second, st))));
+ makeNode(it->second, st, ns))));
+}
+
+static Name getName(const Entity& e, const map<string, Entity>& m, const string& ns)
+{
+ const string& name = getField<string>(e, m, "name");
+
+ if (isFullName(name)) {
+ return Name(name);
+ } else {
+ map<string, Entity>::const_iterator it = m.find("namespace");
+ if (it != m.end()) {
+ if (it->second.type() != json::type_traits<string>::type()) {
+ throw Exception(boost::format(
+ "Json field \"%1%\" is not a %2%: %3%") %
+ "namespace" % json::type_traits<string>::name() %
+ it->second.toString());
+ }
+ Name result = Name(name, it->second.value<string>());
+ return result;
+ }
+ return Name(name, ns);
+ }
}
static NodePtr makeNode(const Entity& e, const map<string, Entity>& m,
- SymbolTable& st)
+ SymbolTable& st, const string& ns)
{
const string& type = getField<string>(e, m, "type");
if (NodePtr result = makePrimitive(type)) {
@@ -199,48 +234,48 @@ static NodePtr makeNode(const Entity& e,
}
} else if (type == "record" || type == "error" ||
type == "enum" || type == "fixed") {
- const string& name = getField<string>(e, m, "name");
+ Name nm = getName(e, m, ns);
NodePtr result;
if (type == "record" || type == "error") {
result = NodePtr(new NodeRecord());
- st[name] = result;
- NodePtr r = makeRecordNode(e, name, m, st);
+ st[nm] = result;
+ NodePtr r = makeRecordNode(e, nm, m, st, nm.ns());
(boost::dynamic_pointer_cast<NodeRecord>(r))->swap(
*boost::dynamic_pointer_cast<NodeRecord>(result));
} else {
- result = (type == "enum") ? makeEnumNode(e, name, m) :
- makeFixedNode(e, name, m);
- st[name] = result;
+ result = (type == "enum") ? makeEnumNode(e, nm, m) :
+ makeFixedNode(e, nm, m);
+ st[nm] = result;
}
return result;
} else if (type == "array") {
- return makeArrayNode(e, m, st);
+ return makeArrayNode(e, m, st, ns);
} else if (type == "map") {
- return makeMapNode(e, m, st);
+ return makeMapNode(e, m, st, ns);
}
throw Exception(boost::format("Unknown type definition: %1%")
% e.toString());
}
static NodePtr makeNode(const Entity& e, const vector<Entity>& m,
- SymbolTable& st)
+ SymbolTable& st, const string& ns)
{
concepts::MultiAttribute<NodePtr> mm;
for (vector<Entity>::const_iterator it = m.begin(); it != m.end(); ++it) {
- mm.add(makeNode(*it, st));
+ mm.add(makeNode(*it, st, ns));
}
return NodePtr(new NodeUnion(mm));
}
-static NodePtr makeNode(const json::Entity& e, SymbolTable& st)
+static NodePtr makeNode(const json::Entity& e, SymbolTable& st, const string& ns)
{
switch (e.type()) {
case json::etString:
- return makeNode(e.value<string>(), st);
+ return makeNode(e.value<string>(), st, ns);
case json::etObject:
- return makeNode(e, e.value<map<string, Entity> >(), st);
+ return makeNode(e, e.value<map<string, Entity> >(), st, ns);
case json::etArray:
- return makeNode(e, e.value<vector<Entity> >(), st);
+ return makeNode(e, e.value<vector<Entity> >(), st, ns);
default:
throw Exception(boost::format("Invalid Avro type: %1%") % e.toString());
}
@@ -250,7 +285,7 @@ AVRO_DECL ValidSchema compileJsonSchemaF
{
json::Entity e = json::loadEntity(is);
SymbolTable st;
- NodePtr n = makeNode(e, st);
+ NodePtr n = makeNode(e, st, "");
return ValidSchema(n);
}
Modified: avro/trunk/lang/c++/impl/Node.cc
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c%2B%2B/impl/Node.cc?rev=1340768&r1=1340767&r2=1340768&view=diff
==============================================================================
--- avro/trunk/lang/c++/impl/Node.cc (original)
+++ avro/trunk/lang/c++/impl/Node.cc Sun May 20 16:51:44 2012
@@ -25,17 +25,59 @@ using std::string;
Node::~Node()
{ }
-void
-Node::checkName(const std::string &name) const
+Name::Name(const std::string& name)
{
- string::const_iterator it = name.begin();
- if (it != name.end() && (isalpha(*it) || *it == '_')) {
- while ((++it != name.end()) && (isalnum(*it) || *it == '_'));
- if (it == name.end()) {
- return;
- }
+ fullname(name);
+}
+
+const string Name::fullname() const
+{
+ return (ns_.empty()) ? simpleName_ : ns_ + "." + simpleName_;
+}
+
+void Name::fullname(const string& name)
+{
+ string::size_type n = name.find_last_of('.');
+ if (n == string::npos) {
+ simpleName_ = name;
+ ns_.clear();
+ } else {
+ ns_ = name.substr(0, n);
+ simpleName_ = name.substr(n + 1);
}
- throw Exception("Names must match [A-Za-z_][A-Za-z0-9_]*");
+ check();
+}
+
+bool Name::operator < (const Name& n) const
+{
+ return (ns_ < n.ns_) ? true :
+ (n.ns_ < ns_) ? false :
+ (simpleName_ < n.simpleName_);
+}
+
+static bool invalidChar1(char c)
+{
+ return !isalnum(c) && c != '_' && c != '.';
+}
+
+static bool invalidChar2(char c)
+{
+ return !isalnum(c) && c != '_';
+}
+
+void Name::check() const
+{
+ if (! ns_.empty() && (ns_[0] == '.' || ns_[ns_.size() - 1] == '.' || std::find_if(ns_.begin(), ns_.end(), invalidChar1) != ns_.end())) {
+ throw Exception("Invalid namespace: " + ns_);
+ }
+ if (simpleName_.empty() || std::find_if(simpleName_.begin(), simpleName_.end(), invalidChar2) != simpleName_.end()) {
+ throw Exception("Invalid name: " + simpleName_);
+ }
+}
+
+bool Name::operator == (const Name& n) const
+{
+ return ns_ == n.ns_ && simpleName_ == n.simpleName_;
}
} // namespace avro
Modified: avro/trunk/lang/c++/impl/NodeImpl.cc
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c%2B%2B/impl/NodeImpl.cc?rev=1340768&r1=1340767&r2=1340768&view=diff
==============================================================================
--- avro/trunk/lang/c++/impl/NodeImpl.cc (original)
+++ avro/trunk/lang/c++/impl/NodeImpl.cc Sun May 20 16:51:44 2012
@@ -21,47 +21,6 @@
namespace avro {
-
-template < class A, class B, class C, class D >
-SchemaResolution
-NodeImpl<A,B,C,D>::furtherResolution(const Node &reader) const
-{
- SchemaResolution match = RESOLVE_NO_MATCH;
-
- if(reader.type() == AVRO_SYMBOLIC) {
-
- // resolve the symbolic type, and check again
- const NodePtr &node = reader.leafAt(0);
- match = resolve(*node);
- }
- else if(reader.type() == AVRO_UNION) {
-
- // in this case, need to see if there is an exact match for the
- // writer's type, or if not, the first one that can be promoted to a
- // match
-
- for(size_t i= 0; i < reader.leaves(); ++i) {
-
- const NodePtr &node = reader.leafAt(i);
- SchemaResolution thisMatch = resolve(*node);
-
- // if matched then the search is done
- if(thisMatch == RESOLVE_MATCH) {
- match = thisMatch;
- break;
- }
-
- // thisMatch is either no match, or promotable, this will set match to
- // promotable if it hasn't been set already
- if (match == RESOLVE_NO_MATCH) {
- match = thisMatch;
- }
- }
- }
-
- return match;
-}
-
SchemaResolution
NodePrimitive::resolve(const Node &reader) const
{
@@ -216,14 +175,20 @@ NodeSymbolic::printJson(std::ostream &os
os << '\"' << nameAttribute_.get() << '\"';
}
+static void printName(std::ostream& os, const Name& n, int depth)
+{
+ if (!n.ns().empty()) {
+ os << indent(depth) << "\"namespace\": \"" << n.ns() << "\",\n";
+ }
+ os << indent(depth) << "\"name\": \"" << n.simpleName() << "\",\n";
+}
+
void
NodeRecord::printJson(std::ostream &os, int depth) const
{
os << "{\n";
os << indent(++depth) << "\"type\": \"record\",\n";
- if(!nameAttribute_.get().empty()) {
- os << indent(depth) << "\"name\": \"" << nameAttribute_.get() << "\",\n";
- }
+ printName(os, nameAttribute_.get(), depth);
os << indent(depth) << "\"fields\": [\n";
int fields = leafAttributes_.size();
@@ -249,9 +214,7 @@ NodeEnum::printJson(std::ostream &os, in
{
os << "{\n";
os << indent(++depth) << "\"type\": \"enum\",\n";
- if(!nameAttribute_.get().empty()) {
- os << indent(depth) << "\"name\": \"" << nameAttribute_.get() << "\",\n";
- }
+ printName(os, nameAttribute_.get(), depth);
os << indent(depth) << "\"symbols\": [\n";
int names = leafNameAttributes_.size();
@@ -312,7 +275,7 @@ NodeFixed::printJson(std::ostream &os, i
os << "{\n";
os << indent(++depth) << "\"type\": \"fixed\",\n";
os << indent(depth) << "\"size\": " << sizeAttribute_.get() << ",\n";
- os << indent(depth) << "\"name\": \"" << nameAttribute_.get() << "\"\n";
+ printName(os, nameAttribute_.get(), depth);
os << indent(--depth) << '}';
}
Modified: avro/trunk/lang/c++/impl/Schema.cc
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c%2B%2B/impl/Schema.cc?rev=1340768&r1=1340767&r2=1340768&view=diff
==============================================================================
--- avro/trunk/lang/c++/impl/Schema.cc (original)
+++ avro/trunk/lang/c++/impl/Schema.cc Sun May 20 16:51:44 2012
@@ -108,7 +108,7 @@ FixedSchema::FixedSchema(int size, const
node_->setName(name);
}
-SymbolicSchema::SymbolicSchema(const std::string &name, const NodePtr& link) :
+SymbolicSchema::SymbolicSchema(const Name &name, const NodePtr& link) :
Schema(new NodeSymbolic(HasName(name), link))
{
}
Modified: avro/trunk/lang/c++/impl/ValidSchema.cc
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c%2B%2B/impl/ValidSchema.cc?rev=1340768&r1=1340767&r2=1340768&view=diff
==============================================================================
--- avro/trunk/lang/c++/impl/ValidSchema.cc (original)
+++ avro/trunk/lang/c++/impl/ValidSchema.cc Sun May 20 16:51:44 2012
@@ -17,6 +17,7 @@
*/
#include <boost/format.hpp>
+#include <sstream>
#include "ValidSchema.hh"
#include "Schema.hh"
@@ -30,7 +31,7 @@ using boost::static_pointer_cast;
namespace avro {
-typedef std::map<std::string, NodePtr> SymbolMap;
+typedef std::map<Name, NodePtr> SymbolMap;
static bool validate(const NodePtr &node, SymbolMap &symbolMap)
{
@@ -40,7 +41,7 @@ static bool validate(const NodePtr &node
}
if (node->hasName()) {
- const string& nm = node->name();
+ const Name& nm = node->name();
SymbolMap::iterator it = symbolMap.find(nm);
bool found = it != symbolMap.end() && nm == it->first;
Modified: avro/trunk/lang/c++/impl/Validator.cc
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c%2B%2B/impl/Validator.cc?rev=1340768&r1=1340767&r2=1340768&view=diff
==============================================================================
--- avro/trunk/lang/c++/impl/Validator.cc (original)
+++ avro/trunk/lang/c++/impl/Validator.cc Sun May 20 16:51:44 2012
@@ -275,7 +275,7 @@ Validator::getCurrentRecordName(std::str
}
if(idx >= 0 && compoundStack_[idx].node->type() == AVRO_RECORD) {
- name = compoundStack_[idx].node->name();
+ name = compoundStack_[idx].node->name().simpleName();
found = true;
}
return found;
Modified: avro/trunk/lang/c++/impl/avrogencpp.cc
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c%2B%2B/impl/avrogencpp.cc?rev=1340768&r1=1340767&r2=1340768&view=diff
==============================================================================
--- avro/trunk/lang/c++/impl/avrogencpp.cc (original)
+++ avro/trunk/lang/c++/impl/avrogencpp.cc Sun May 20 16:51:44 2012
@@ -117,6 +117,11 @@ public:
void generate(const ValidSchema& schema);
};
+static string decorate(const avro::Name& name)
+{
+ return name.simpleName();
+}
+
string CodeGen::fullname(const string& name) const
{
return ns_.empty() ? name : (ns_ + "::" + name);
@@ -124,13 +129,14 @@ string CodeGen::fullname(const string& n
string CodeGen::generateEnumType(const NodePtr& n)
{
- os_ << "enum " << n->name() << " {\n";
+ string s = decorate(n->name());
+ os_ << "enum " << s << " {\n";
size_t c = n->names();
for (size_t i = 0; i < c; ++i) {
os_ << " " << n->nameAt(i) << ",\n";
}
os_ << "};\n\n";
- return n->name();
+ return s;
}
string CodeGen::cppTypeOf(const NodePtr& n)
@@ -152,7 +158,10 @@ string CodeGen::cppTypeOf(const NodePtr&
return "bool";
case avro::AVRO_RECORD:
case avro::AVRO_ENUM:
- return inNamespace_ ? n->name() : fullname(n->name());
+ {
+ string nm = decorate(n->name());
+ return inNamespace_ ? nm : fullname(nm);
+ }
case avro::AVRO_ARRAY:
return "std::vector<" + cppTypeOf(n->leafAt(0)) + " >";
case avro::AVRO_MAP:
@@ -189,7 +198,7 @@ static string cppNameOf(const NodePtr& n
case avro::AVRO_RECORD:
case avro::AVRO_ENUM:
case avro::AVRO_FIXED:
- return n->name();
+ return decorate(n->name());
case avro::AVRO_ARRAY:
return "array";
case avro::AVRO_MAP:
@@ -214,7 +223,7 @@ string CodeGen::generateRecordType(const
return it->second;
}
- os_ << "struct " << n->name() << " {\n";
+ os_ << "struct " << decorate(n->name()) << " {\n";
if (! noUnion_) {
for (size_t i = 0; i < c; ++i) {
if (n->leafAt(i)->type() == avro::AVRO_UNION) {
@@ -232,7 +241,7 @@ string CodeGen::generateRecordType(const
os_ << ' ' << n->nameAt(i) << ";\n";
}
os_ << "};\n\n";
- return n->name();
+ return decorate(n->name());
}
void makeCanonical(string& s, bool foldCase)
@@ -443,7 +452,7 @@ string CodeGen::generateDeclaration(cons
void CodeGen::generateEnumTraits(const NodePtr& n)
{
- string fn = fullname(n->name());
+ string fn = fullname(decorate(n->name()));
os_ << "template<> struct codec_traits<" << fn << "> {\n"
<< " static void encode(Encoder& e, " << fn << " v) {\n"
<< " e.encodeEnum(v);\n"
@@ -461,7 +470,7 @@ void CodeGen::generateRecordTraits(const
generateTraits(n->leafAt(i));
}
- string fn = fullname(n->name());
+ string fn = fullname(decorate(n->name()));
os_ << "template<> struct codec_traits<" << fn << "> {\n"
<< " static void encode(Encoder& e, const " << fn << "& v) {\n";
Added: avro/trunk/lang/c++/jsonschemas/tweet
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c%2B%2B/jsonschemas/tweet?rev=1340768&view=auto
==============================================================================
--- avro/trunk/lang/c++/jsonschemas/tweet (added)
+++ avro/trunk/lang/c++/jsonschemas/tweet Sun May 20 16:51:44 2012
@@ -0,0 +1,152 @@
+{
+ "type": "record",
+ "name": "AvroTweet",
+ "namespace": "com.bifflabs.grok.model.twitter.avro",
+ "fields": [{
+ "name": "ID",
+ "type": "long"
+ },
+ {
+ "name": "text",
+ "type": "string"
+ },
+ {
+ "name": "authorScreenName",
+ "type": "string"
+ },
+ {
+ "name": "authorProfileImageURL",
+ "type": "string"
+ },
+ {
+ "name": "authorUserID",
+ "type": ["null", "long"]
+ },
+ {
+ "name": "location",
+ "type": ["null", {
+ "type": "record",
+ "name": "AvroPoint",
+ "namespace": "com.bifflabs.grok.model.common.avro",
+ "fields": [{
+ "name": "latitude",
+ "type": "double"
+ },
+ {
+ "name": "longitude",
+ "type": "double"
+ }]
+ }]
+ },
+ {
+ "name": "placeID",
+ "type": ["null", "string"]
+ },
+ {
+ "name": "createdAt",
+ "type": {
+ "type": "record",
+ "name": "AvroDateTime",
+ "namespace": "com.bifflabs.grok.model.common.avro",
+ "fields": [{
+ "name": "dateTimeString",
+ "type": "string"
+ }]
+ }
+ },
+ {
+ "name": "metadata",
+ "type": {
+ "type": "record",
+ "name": "AvroTweetMetadata",
+ "fields": [{
+ "name": "inReplyToScreenName",
+ "type": {
+ "type": "record",
+ "name": "AvroKnowableOptionString",
+ "namespace": "com.bifflabs.grok.model.common.avro",
+ "fields": [{
+ "name": "known",
+ "type": "boolean"
+ },
+ {
+ "name": "data",
+ "type": ["null", "string"]
+ }]
+ }
+ },
+ {
+ "name": "mentionedScreenNames",
+ "type": {
+ "type": "record",
+ "name": "AvroKnowableListString",
+ "namespace": "com.bifflabs.grok.model.common.avro",
+ "fields": [{
+ "name": "known",
+ "type": "boolean"
+ },
+ {
+ "name": "data",
+ "type": {
+ "type": "array",
+ "items": "string"
+ }
+ }]
+ }
+ },
+ {
+ "name": "links",
+ "type": "com.bifflabs.grok.model.common.avro.AvroKnowableListString"
+ },
+ {
+ "name": "hashtags",
+ "type": "com.bifflabs.grok.model.common.avro.AvroKnowableListString"
+ },
+ {
+ "name": "isBareCheckin",
+ "type": {
+ "type": "record",
+ "name": "AvroKnowableBoolean",
+ "namespace": "com.bifflabs.grok.model.common.avro",
+ "fields": [{
+ "name": "known",
+ "type": "boolean"
+ },
+ {
+ "name": "data",
+ "type": "boolean"
+ }]
+ }
+ },
+ {
+ "name": "isBareRetweet",
+ "type": "com.bifflabs.grok.model.common.avro.AvroKnowableBoolean"
+ },
+ {
+ "name": "isRetweet",
+ "type": "com.bifflabs.grok.model.common.avro.AvroKnowableBoolean"
+ },
+ {
+ "name": "venueID",
+ "type": "com.bifflabs.grok.model.common.avro.AvroKnowableOptionString"
+ },
+ {
+ "name": "venuePoint",
+ "type": {
+ "type": "record",
+ "name": "AvroKnowableOptionPoint",
+ "namespace": "com.bifflabs.grok.model.common.avro",
+ "fields": [{
+ "name": "known",
+ "type": "boolean"
+ },
+ {
+ "name": "data",
+ "type": ["null", "AvroPoint"]
+ }]
+ }
+ }
+ ]
+ }
+ }]
+}
\ No newline at end of file
Modified: avro/trunk/lang/c++/test/AvrogencppTests.cc
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c%2B%2B/test/AvrogencppTests.cc?rev=1340768&r1=1340767&r2=1340768&view=diff
==============================================================================
--- avro/trunk/lang/c++/test/AvrogencppTests.cc (original)
+++ avro/trunk/lang/c++/test/AvrogencppTests.cc Sun May 20 16:51:44 2012
@@ -18,6 +18,7 @@
#include "bigrecord.hh"
#include "bigrecord2.hh"
+#include "tweet.hh"
#include "union_array_union.hh"
#include "union_map_union.hh"
#include "union_conflict.hh"
@@ -140,6 +141,21 @@ void testEncoding()
check(t2, t1);
}
+void testNamespace()
+{
+ ValidSchema s;
+ ifstream ifs("jsonschemas/tweet");
+ // basic compilation should work
+ compileJsonSchema(ifs, s);
+ // an AvroPoint was defined and then referred to from within a namespace
+ testgen3::AvroPoint point;
+ point.latitude = 42.3570;
+ point.longitude = -71.1109;
+ // set it in something that referred to it in the schema
+ testgen3::_tweet_Union__1__ twPoint;
+ twPoint.set_AvroPoint(point);
+}
+
void setRecord(uau::r1& r)
{
}
@@ -199,6 +215,7 @@ init_unit_test_suite(int argc, char* arg
ts->add(BOOST_TEST_CASE(testEncoding));
ts->add(BOOST_TEST_CASE(testEncoding2<uau::r1>));
ts->add(BOOST_TEST_CASE(testEncoding2<umu::r1>));
+ ts->add(BOOST_TEST_CASE(testNamespace));
return ts;
}
Modified: avro/trunk/lang/c++/test/unittest.cc
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c%2B%2B/test/unittest.cc?rev=1340768&r1=1340767&r2=1340768&view=diff
==============================================================================
--- avro/trunk/lang/c++/test/unittest.cc (original)
+++ avro/trunk/lang/c++/test/unittest.cc Sun May 20 16:51:44 2012
@@ -481,7 +481,7 @@ struct TestNested
rec.addField("value", LongSchema());
UnionSchema next;
next.addType(NullSchema());
- next.addType(SymbolicSchema("LongList", rec.root()));
+ next.addType(SymbolicSchema(Name("LongList"), rec.root()));
rec.addField("next", next);
rec.addField("end", BoolSchema());