diff options
author | Devtools Arcadia <arcadia-devtools@yandex-team.ru> | 2022-02-07 18:08:42 +0300 |
---|---|---|
committer | Devtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net> | 2022-02-07 18:08:42 +0300 |
commit | 1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch) | |
tree | e26c9fed0de5d9873cce7e00bc214573dc2195b7 /library/cpp/yson/node/node_visitor.cpp | |
download | ydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz |
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'library/cpp/yson/node/node_visitor.cpp')
-rw-r--r-- | library/cpp/yson/node/node_visitor.cpp | 152 |
1 files changed, 152 insertions, 0 deletions
diff --git a/library/cpp/yson/node/node_visitor.cpp b/library/cpp/yson/node/node_visitor.cpp new file mode 100644 index 0000000000..899fbfa02a --- /dev/null +++ b/library/cpp/yson/node/node_visitor.cpp @@ -0,0 +1,152 @@ +#include "node_visitor.h" + +#include <util/generic/algorithm.h> +#include <util/string/printf.h> + +namespace NYT { + +//////////////////////////////////////////////////////////////////////////////// + +namespace { + +template <typename Fun> +void Iterate(const TNode::TMapType& nodeMap, bool sortByKey, Fun action) +{ + if (sortByKey) { + TVector<TNode::TMapType::const_iterator> 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 std::pair<TString, TNode>& 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_FAIL("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 std::pair<TString, TNode>& 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 |