19 #ifndef avro_NodeImpl_hh__
20 #define avro_NodeImpl_hh__
23 #include "GenericDatum.hh"
34 #include "NodeConcepts.hh"
44 class LeafNamesConcept,
53 leafNameAttributes_(),
57 const NameConcept &name,
58 const LeavesConcept &leaves,
59 const LeafNamesConcept &leafNames,
60 const SizeConcept &size) :
Node(type),
64 leafNameAttributes_(leafNames),
65 sizeAttribute_(size) {}
69 const NameConcept &name,
71 const LeavesConcept &leaves,
72 const LeafNamesConcept &leafNames,
73 const SizeConcept &size) :
Node(type),
77 leafNameAttributes_(leafNames),
78 sizeAttribute_(size) {}
81 std::swap(nameAttribute_, impl.nameAttribute_);
82 std::swap(docAttribute_, impl.docAttribute_);
84 std::swap(leafNameAttributes_, impl.leafNameAttributes_);
85 std::swap(sizeAttribute_, impl.sizeAttribute_);
86 std::swap(nameIndex_, impl.nameIndex_);
89 bool hasName()
const override {
91 return NameConcept::hasAttribute;
94 void doSetName(
const Name &name)
override {
95 nameAttribute_.add(name);
98 const Name &name()
const override {
99 return nameAttribute_.get();
102 void doSetDoc(
const std::string &doc)
override {
103 docAttribute_.add(doc);
106 const std::string &getDoc()
const override {
107 return docAttribute_.get();
110 void doAddLeaf(
const NodePtr &newLeaf)
final {
114 size_t leaves()
const override {
118 const NodePtr &leafAt(
size_t index)
const override {
122 void doAddName(
const std::string &name)
override {
123 if (!nameIndex_.add(name, leafNameAttributes_.size())) {
124 throw Exception(boost::format(
"Cannot add duplicate name: %1%") % name);
126 leafNameAttributes_.add(name);
129 size_t names()
const override {
130 return leafNameAttributes_.size();
133 const std::string &nameAt(
size_t index)
const override {
134 return leafNameAttributes_.get(index);
137 bool nameIndex(
const std::string &name,
size_t &index)
const override {
138 return nameIndex_.lookup(name, index);
141 void doSetFixedSize(
size_t size)
override {
142 sizeAttribute_.add(size);
145 size_t fixedSize()
const override {
146 return sizeAttribute_.get();
149 bool isValid()
const override = 0;
151 void printBasicInfo(std::ostream &os)
const override;
153 void setLeafToSymbolic(
size_t index,
const NodePtr &node)
override;
161 const NodePtr &node = reader.leafAt(0);
162 match = resolve(*node);
169 for (
size_t i = 0; i < reader.leaves(); ++i) {
171 const NodePtr &node = reader.leafAt(i);
191 NameConcept nameAttribute_;
197 LeafNamesConcept leafNameAttributes_;
198 SizeConcept sizeAttribute_;
233 void printJson(std::ostream &os,
size_t depth)
const override;
235 bool isValid()
const override {
239 void printDefaultToJson(
const GenericDatum &g, std::ostream &os,
size_t depth)
const override;
243 using NodeWeakPtr = std::weak_ptr<Node>;
253 void printJson(std::ostream &os,
size_t depth)
const override;
255 bool isValid()
const override {
256 return (nameAttribute_.size() == 1);
259 void printDefaultToJson(
const GenericDatum &g, std::ostream &os,
size_t depth)
const override;
262 return (actualNode_.lock() !=
nullptr);
265 NodePtr getNode()
const {
266 NodePtr node = actualNode_.lock();
268 throw Exception(boost::format(
"Could not follow symbol %1%") % name());
273 void setNode(
const NodePtr &node) {
278 NodeWeakPtr actualNode_;
282 std::vector<GenericDatum> defaultValues;
288 std::vector<GenericDatum> dv);
293 defaultValues(std::move(dv)) {
294 for (
size_t i = 0; i < leafNameAttributes_.size(); ++i) {
295 if (!nameIndex_.add(leafNameAttributes_.get(i), i)) {
297 "Cannot add duplicate field: %1%")
298 % leafNameAttributes_.get(i));
304 NodeImplRecord::swap(r);
305 defaultValues.swap(r.defaultValues);
310 void printJson(std::ostream &os,
size_t depth)
const override;
312 bool isValid()
const override {
313 return ((nameAttribute_.size() == 1) && (leafAttributes_.size() == leafNameAttributes_.size()));
316 const GenericDatum &defaultValueAt(
size_t index)
override {
317 return defaultValues[index];
320 void printDefaultToJson(
const GenericDatum &g, std::ostream &os,
size_t depth)
const override;
328 for (
size_t i = 0; i < leafNameAttributes_.size(); ++i) {
329 if (!nameIndex_.add(leafNameAttributes_.get(i), i)) {
330 throw Exception(boost::format(
"Cannot add duplicate enum: %1%") % leafNameAttributes_.get(i));
337 void printJson(std::ostream &os,
size_t depth)
const override;
339 bool isValid()
const override {
341 (nameAttribute_.size() == 1) && (leafNameAttributes_.size() > 0));
344 void printDefaultToJson(
const GenericDatum &g, std::ostream &os,
size_t depth)
const override;
355 void printJson(std::ostream &os,
size_t depth)
const override;
357 bool isValid()
const override {
358 return (leafAttributes_.size() == 1);
361 void printDefaultToJson(
const GenericDatum &g, std::ostream &os,
size_t depth)
const override;
374 std::swap(leafAttributes_.get(0), leafAttributes_.get(1));
379 void printJson(std::ostream &os,
size_t depth)
const override;
381 bool isValid()
const override {
382 return (leafAttributes_.size() == 2);
385 void printDefaultToJson(
const GenericDatum &g, std::ostream &os,
size_t depth)
const override;
396 void printJson(std::ostream &os,
size_t depth)
const override;
398 bool isValid()
const override {
399 std::set<std::string> seen;
400 if (leafAttributes_.size() >= 1) {
401 for (
size_t i = 0; i < leafAttributes_.size(); ++i) {
403 const NodePtr &n = leafAttributes_.get(i);
440 name = n->name().fullname();
442 default:
return false;
444 if (seen.find(name) != seen.end()) {
454 void printDefaultToJson(
const GenericDatum &g, std::ostream &os,
size_t depth)
const override;
465 void printJson(std::ostream &os,
size_t depth)
const override;
467 bool isValid()
const override {
469 (nameAttribute_.size() == 1) && (sizeAttribute_.size() == 1));
472 void printDefaultToJson(
const GenericDatum &g, std::ostream &os,
size_t depth)
const override;
475 template<
class A,
class B,
class C,
class D>
478 if (!B::hasAttribute) {
479 throw Exception(
"Cannot change leaf node for nonexistent leaf");
482 auto &replaceNode =
const_cast<NodePtr &
>(leafAttributes_.get(index));
483 if (replaceNode->name() != node->name()) {
484 throw Exception(
"Symbolic name does not match the name of the schema it references");
487 auto symbol = std::make_shared<NodeSymbolic>();
488 symbol->setName(node->name());
489 symbol->setNode(node);
490 replaceNode = symbol;
493 template<
class A,
class B,
class C,
class D>
495 NodeImpl<A, B, C, D>::printBasicInfo(std::ostream &os)
const {
498 os <<
' ' << nameAttribute_.get();
501 if (D::hasAttribute) {
502 os <<
" " << sizeAttribute_.get();
505 int count = leaves();
506 count = count ? count : names();
507 for (
int i = 0; i < count; ++i) {
508 if (C::hasAttribute) {
509 os <<
"name " << nameAt(i) <<
'\n';
511 if (type() !=
AVRO_SYMBOLIC && leafAttributes_.hasAttribute) {
512 leafAt(i)->printBasicInfo(os);
516 os <<
"end " << type() <<
'\n';
520 inline NodePtr resolveSymbol(
const NodePtr &node) {
522 throw Exception(
"Only symbolic nodes may be resolved");
524 std::shared_ptr<NodeSymbolic> symNode = std::static_pointer_cast<NodeSymbolic>(node);
525 return symNode->getNode();
529 inline std::string intToHex(T i) {
530 std::stringstream stream;
532 << std::setfill(
'0') << std::setw(
sizeof(T))