#include "node_visitor.h" #include #include namespace NYT { //////////////////////////////////////////////////////////////////////////////// namespace { template void Iterate(const TNode::TMapType& nodeMap, bool sortByKey, Fun action) { if (sortByKey) { TVector iterators; for (auto it = nodeMap.begin(); it != nodeMap.end(); ++it) { iterators.push_back(it); } SortBy(iterators, [](TNode::TMapType::const_iterator it) { return it->first; }); for (const auto& it : iterators) { action(*it); } } else { ForEach(nodeMap.begin(), nodeMap.end(), action); } } } // namespace //////////////////////////////////////////////////////////////////////////////// TNodeVisitor::TNodeVisitor(NYson::IYsonConsumer* consumer, bool sortMapKeys) : Consumer_(consumer) , SortMapKeys_(sortMapKeys) { } void TNodeVisitor::Visit(const TNode& node) { VisitAny(node); } void TNodeVisitor::VisitAny(const TNode& node) { if (node.HasAttributes()) { Consumer_->OnBeginAttributes(); Iterate(node.GetAttributes().AsMap(), SortMapKeys_, [&](const auto& item) { Consumer_->OnKeyedItem(item.first); if (item.second.IsUndefined()) { ythrow TNode::TTypeError() << "unable to visit attribute value of type " << TNode::EType::Undefined << "; attribute name: `" << item.first << '\'' ; } VisitAny(item.second); }); Consumer_->OnEndAttributes(); } switch (node.GetType()) { case TNode::String: VisitString(node); break; case TNode::Int64: VisitInt64(node); break; case TNode::Uint64: VisitUint64(node); break; case TNode::Double: VisitDouble(node); break; case TNode::Bool: VisitBool(node); break; case TNode::List: VisitList(node.AsList()); break; case TNode::Map: VisitMap(node.AsMap()); break; case TNode::Null: VisitEntity(); break; case TNode::Undefined: ythrow TNode::TTypeError() << "unable to visit TNode of type " << node.GetType(); default: Y_ABORT("Unexpected type: %d", node.GetType()); } } void TNodeVisitor::VisitString(const TNode& node) { Consumer_->OnStringScalar(node.AsString()); } void TNodeVisitor::VisitInt64(const TNode& node) { Consumer_->OnInt64Scalar(node.AsInt64()); } void TNodeVisitor::VisitUint64(const TNode& node) { Consumer_->OnUint64Scalar(node.AsUint64()); } void TNodeVisitor::VisitDouble(const TNode& node) { Consumer_->OnDoubleScalar(node.AsDouble()); } void TNodeVisitor::VisitBool(const TNode& node) { Consumer_->OnBooleanScalar(node.AsBool()); } void TNodeVisitor::VisitList(const TNode::TListType& nodeList) { Consumer_->OnBeginList(); size_t index = 0; for (const auto& item : nodeList) { Consumer_->OnListItem(); if (item.IsUndefined()) { ythrow TNode::TTypeError() << "unable to visit list node child of type " << TNode::EType::Undefined << "; list index: " << index; } VisitAny(item); ++index; } Consumer_->OnEndList(); } void TNodeVisitor::VisitMap(const TNode::TMapType& nodeMap) { Consumer_->OnBeginMap(); Iterate(nodeMap, SortMapKeys_, [&](const auto& item) { Consumer_->OnKeyedItem(item.first); if (item.second.IsUndefined()) { ythrow TNode::TTypeError() << "unable to visit map node child of type " << TNode::EType::Undefined << "; map key: `" << item.first << '\'' ; } VisitAny(item.second); }); Consumer_->OnEndMap(); } void TNodeVisitor::VisitEntity() { Consumer_->OnEntity(); } //////////////////////////////////////////////////////////////////////////////// } // namespace NYT