diff options
author | jansenin <jansenin@yandex-team.com> | 2023-08-02 16:09:05 +0300 |
---|---|---|
committer | jansenin <jansenin@yandex-team.com> | 2023-08-02 16:09:05 +0300 |
commit | c0ca04d62a4ae68bf09193c3a9941d28bf343028 (patch) | |
tree | 39e0e887276bda21e6de99275b9c6e74c8b444d4 /library/cpp/yaml/fyamlcpp/fyamlcpp.cpp | |
parent | c1e8ecaf762b945d005bd42ed005e44c1604346d (diff) | |
download | ydb-c0ca04d62a4ae68bf09193c3a9941d28bf343028.tar.gz |
Add TNodeOps class, that contains common functionality of TNodeRef and TNode
Diffstat (limited to 'library/cpp/yaml/fyamlcpp/fyamlcpp.cpp')
-rw-r--r-- | library/cpp/yaml/fyamlcpp/fyamlcpp.cpp | 554 |
1 files changed, 279 insertions, 275 deletions
diff --git a/library/cpp/yaml/fyamlcpp/fyamlcpp.cpp b/library/cpp/yaml/fyamlcpp/fyamlcpp.cpp index 8f9321a2529..37ead183501 100644 --- a/library/cpp/yaml/fyamlcpp/fyamlcpp.cpp +++ b/library/cpp/yaml/fyamlcpp/fyamlcpp.cpp @@ -6,9 +6,6 @@ namespace NFyaml { -#define ENSURE_NODE_NOT_EMPTY(NODE) Y_ENSURE_EX(NODE, TFyamlEx("Expected non-empty Node")) -#define ENSURE_DOCUMENT_NOT_EMPTY(NODE) Y_ENSURE_EX(NODE, TFyamlEx("Expected non-empty Document")) - const char* zstr = ""; enum class EErrorType { @@ -262,276 +259,12 @@ TDocumentIterator::TDocumentIterator(fy_document_iterator* iterator) : Iterator_(iterator, fy_document_iterator_destroy) {} -TNode TNodeRef::CreateReference() const { - ENSURE_NODE_NOT_EMPTY(Node_); - return TNode(fy_node_create_reference(Node_)); -} - -TNode TNodeRef::Copy() const { - ENSURE_NODE_NOT_EMPTY(Node_); - return TNode(fy_node_copy(fy_node_document(Node_), Node_)); -} - -TNode TNodeRef::Copy(TDocument& to) const { - ENSURE_NODE_NOT_EMPTY(Node_); - auto* fromDoc = fy_node_document(Node_); - auto& fromUserdata = *reinterpret_cast<THashSet<TSimpleSharedPtr<TString>, TStringPtrHashT>*>(fy_document_get_userdata(fromDoc)); - auto& toUserdata = *reinterpret_cast<THashSet<TSimpleSharedPtr<TString>, TStringPtrHashT>*>(fy_document_get_userdata(to.Document_.get())); - toUserdata.insert(fromUserdata.begin(), fromUserdata.end()); - return TNode(fy_node_copy(to.Document_.get(), Node_)); -} - -TString TNodeRef::Path() const { - ENSURE_NODE_NOT_EMPTY(Node_); - char* path = fy_node_get_path(Node_); - - if (path) { - TString str(path); - free(path); - return str; - } - - return {}; -} - -ENodeType TNodeRef::Type() const { - ENSURE_NODE_NOT_EMPTY(Node_); - return static_cast<ENodeType>(fy_node_get_type(Node_)); -} - -bool TNodeRef::IsAlias() const { - ENSURE_NODE_NOT_EMPTY(Node_); - return fy_node_is_alias(Node_); -} - -TNodeRef TNodeRef::ResolveAlias() const { - ENSURE_NODE_NOT_EMPTY(Node_); - Y_VERIFY_DEBUG(IsAlias()); - return TNodeRef(fy_node_resolve_alias(Node_)); -} - -TString TNodeRef::Scalar() const { - ENSURE_NODE_NOT_EMPTY(Node_); - Y_ENSURE_EX(fy_node_is_scalar(Node_), ({ - TStringStream ss; - ss << "Node is not Scalar: " << Path(); - TFyamlEx(ss.Str()); - })); - size_t size; - const char* text = fy_node_get_scalar(Node_, &size); - return TString(text, size); -} - -TMark TNodeRef::BeginMark() const { - ENSURE_NODE_NOT_EMPTY(Node_); - std::unique_ptr<fy_document_iterator, void(*)(fy_document_iterator*)> it( - fy_document_iterator_create(), - &fy_document_iterator_destroy); - fy_document_iterator_node_start(it.get(), Node_); - auto deleter = [&](fy_event* fye){ fy_document_iterator_event_free(it.get(), fye); }; - std::unique_ptr<fy_event, decltype(deleter)> ev( - fy_document_iterator_body_next(it.get()), - deleter); - auto* mark = fy_event_start_mark(ev.get()); - - if (!mark) { - ythrow TFyamlEx("can't get begin mark for a node"); - } - - return TMark{ - mark->input_pos, - mark->line, - mark->column, - }; -} - -bool IsComplexType(ENodeType type) { - return type == ENodeType::Mapping || type == ENodeType::Sequence; -} - -fy_event_type GetOpenEventType(ENodeType type) { - switch(type) { - case ENodeType::Mapping: - return FYET_MAPPING_START; - case ENodeType::Sequence: - return FYET_SEQUENCE_START; - default: - Y_FAIL("Not a brackets type"); - } -} - -fy_event_type GetCloseEventType(ENodeType type) { - switch(type) { - case ENodeType::Mapping: - return FYET_MAPPING_END; - case ENodeType::Sequence: - return FYET_SEQUENCE_END; - default: - Y_FAIL("Not a brackets type"); - } -} - -TMark TNodeRef::EndMark() const { - ENSURE_NODE_NOT_EMPTY(Node_); - std::unique_ptr<fy_document_iterator, void(*)(fy_document_iterator*)> it( - fy_document_iterator_create(), - &fy_document_iterator_destroy); - fy_document_iterator_node_start(it.get(), Node_); - - auto deleter = [&](fy_event* fye){ fy_document_iterator_event_free(it.get(), fye); }; - std::unique_ptr<fy_event, decltype(deleter)> prevEv( - nullptr, - deleter); - std::unique_ptr<fy_event, decltype(deleter)> ev( - fy_document_iterator_body_next(it.get()), - deleter); - - if (IsComplexType(Type())) { - int openBrackets = 0; - if (ev->type == GetOpenEventType(Type())) { - ++openBrackets; - } - if (ev->type == GetCloseEventType(Type())) { - --openBrackets; - } - while (ev->type != GetCloseEventType(Type()) || openBrackets != 0) { - std::unique_ptr<fy_event, decltype(deleter)> cur( - fy_document_iterator_body_next(it.get()), - deleter); - if (cur == nullptr) { - break; - } - if (cur->type == GetOpenEventType(Type())) { - ++openBrackets; - } - if (cur->type == GetCloseEventType(Type())) { - --openBrackets; - } - if (fy_event_get_node_style(cur.get()) != FYNS_BLOCK) { - prevEv.reset(ev.release()); - ev.reset(cur.release()); - } - } - } - - auto* mark = fy_event_end_mark(ev.get()); - - if (!mark && prevEv) { - mark = fy_event_end_mark(prevEv.get()); - } - - if (!mark) { - ythrow TFyamlEx("can't get end mark for a node"); - } - - return TMark{ - mark->input_pos, - mark->line, - mark->column, - }; -} - -TMapping TNodeRef::Map() const { - ENSURE_NODE_NOT_EMPTY(Node_); - Y_ENSURE_EX(fy_node_is_mapping(Node_), ({ - TStringStream ss; - ss << "Node is not Mapping: " << Path(); - TFyamlEx(ss.Str()); - })); - return TMapping(*this); -} - -TSequence TNodeRef::Sequence() const { - ENSURE_NODE_NOT_EMPTY(Node_); - Y_ENSURE_EX(fy_node_is_sequence(Node_), ({ - TStringStream ss; - ss << "Node is not Sequence: " << Path(); - TFyamlEx(ss.Str()); - })); - return TSequence(*this); -} - -void TNodeRef::Insert(const TNodeRef& node) { - ENSURE_NODE_NOT_EMPTY(Node_); - NDetail::RethrowOnError(fy_node_insert(Node_, node.Node_), Node_); -} - -std::optional<TString> TNodeRef::Tag() const { - ENSURE_NODE_NOT_EMPTY(Node_); - size_t len = 0; - const char* tag = fy_node_get_tag(Node_, &len); - - if (tag) { - return TString(tag, len); - } - - return std::nullopt; -} - -void TNodeRef::SetTag(const TString& tag) { - ENSURE_NODE_NOT_EMPTY(Node_); - auto* str = new TString(std::move(tag)); - auto* data = new NDetail::TUserDataHolder(UserData(), str); - SetUserData(data); - NDetail::RethrowOnError(fy_node_set_tag(Node_, str->c_str(), str->length()), Node_); -} - -bool TNodeRef::RemoveTag() { - ENSURE_NODE_NOT_EMPTY(Node_); - bool ret = fy_node_remove_tag(Node_); - ClearUserData(); - return ret; -} - -bool TNodeRef::HasAnchor() const { - ENSURE_NODE_NOT_EMPTY(Node_); - return fy_node_get_anchor(Node_) != nullptr; -} - -void TNodeRef::SetAnchor(const TString& anchor) { - auto* str = new TString(anchor); - auto* data = new NDetail::TUserDataHolder(UserData(), str); - SetUserData(data); - NDetail::RethrowOnError(fy_node_set_anchor(Node_, str->c_str(), str->length()), Node_); -} - -bool TNodeRef::DeepEqual(const TNodeRef& other) { - ENSURE_NODE_NOT_EMPTY(Node_); - ENSURE_NODE_NOT_EMPTY(other.Node_); - return fy_node_compare(Node_, other.Node_); -} - -std::unique_ptr<char, void(*)(char*)> TNodeRef::EmitToCharArray() const { - std::unique_ptr<char, void(*)(char*)> res( - fy_emit_node_to_string( - Node_, - (fy_emitter_cfg_flags)(FYECF_DEFAULT)), &NDetail::FreeChar); - return res; -} - -void TNodeRef::SetStyle(ENodeStyle style) { - ENSURE_NODE_NOT_EMPTY(Node_); - fy_node_set_style(Node_, (enum fy_node_style)style); -} - -ENodeStyle TNodeRef::Style() const { - ENSURE_NODE_NOT_EMPTY(Node_); - return (ENodeStyle)fy_node_get_style(Node_); -} - -void TNodeRef::SetUserData(NDetail::IBasicUserData* data) { - ENSURE_NODE_NOT_EMPTY(Node_); - fy_node_set_meta(Node_, data); -} +TNodeRef::TNodeRef(fy_node* node) + : Node_(node) +{} -NDetail::IBasicUserData* TNodeRef::UserData() const { - ENSURE_NODE_NOT_EMPTY(Node_); - return reinterpret_cast<NDetail::IBasicUserData* >(fy_node_get_meta(Node_)); -} - -void TNodeRef::ClearUserData() { - ENSURE_NODE_NOT_EMPTY(Node_); - fy_node_clear_meta(Node_); +fy_node* TNodeRef::NodeRawPointer() const { + return Node_; } TNode& TNode::operator=(fy_node* node) { @@ -903,7 +636,7 @@ void TDocument::InsertAt(const char* path, const TNodeRef& node) { TNodeRef TDocument::Buildf(const char* content) { ENSURE_DOCUMENT_NOT_EMPTY(Document_); - return fy_node_build_from_string(Document_.get(), content, strlen(content)); + return TNodeRef(fy_node_build_from_string(Document_.get(), content, strlen(content))); } void TDocument::Resolve() { @@ -936,7 +669,7 @@ void TDocument::SetParent(const TDocument& doc) { TNodeRef TDocument::Root() { ENSURE_DOCUMENT_NOT_EMPTY(Document_); - return fy_document_root(Document_.get()); + return TNodeRef(fy_document_root(Document_.get())); } void TDocument::SetRoot(const TNodeRef& node) { @@ -1039,6 +772,266 @@ std::optional<TDocument> TParser::NextDocument() { namespace NDetail { +fy_node* TNodeOpsBase::CreateReference(fy_node* node) const { + ENSURE_NODE_NOT_EMPTY(node); + return fy_node_create_reference(node); +} + +fy_node* TNodeOpsBase::Copy(fy_node* node) const { + ENSURE_NODE_NOT_EMPTY(node); + return fy_node_copy(fy_node_document(node), node); +} + +fy_node* TNodeOpsBase::Copy(fy_node* node, fy_document* to) const { + ENSURE_NODE_NOT_EMPTY(node); + auto* fromDoc = fy_node_document(node); + auto& fromUserdata = *reinterpret_cast<THashSet<TSimpleSharedPtr<TString>, TStringPtrHashT>*>(fy_document_get_userdata(fromDoc)); + auto& toUserdata = *reinterpret_cast<THashSet<TSimpleSharedPtr<TString>, TStringPtrHashT>*>(fy_document_get_userdata(to)); + toUserdata.insert(fromUserdata.begin(), fromUserdata.end()); + return fy_node_copy(to, node); +} + +TString TNodeOpsBase::Path(fy_node* node) const { + ENSURE_NODE_NOT_EMPTY(node); + char* path = fy_node_get_path(node); + + if (path) { + TString str(path); + free(path); + return str; + } + + return {}; +} + +ENodeType TNodeOpsBase::Type(fy_node* node) const { + ENSURE_NODE_NOT_EMPTY(node); + return static_cast<ENodeType>(fy_node_get_type(node)); +} + +bool TNodeOpsBase::IsAlias(fy_node* node) const { + ENSURE_NODE_NOT_EMPTY(node); + return fy_node_is_alias(node); +} + +fy_node* TNodeOpsBase::ResolveAlias(fy_node* node) const { + ENSURE_NODE_NOT_EMPTY(node); + Y_VERIFY_DEBUG(IsAlias(node)); + return fy_node_resolve_alias(node); +} + +TString TNodeOpsBase::Scalar(fy_node* node) const { + ENSURE_NODE_NOT_EMPTY(node); + Y_ENSURE_EX(fy_node_is_scalar(node), TFyamlEx() << "Node is not Scalar: " << Path(node)); + size_t size; + const char* text = fy_node_get_scalar(node, &size); + return TString(text, size); +} + +TMark TNodeOpsBase::BeginMark(fy_node* node) const { + ENSURE_NODE_NOT_EMPTY(node); + std::unique_ptr<fy_document_iterator, void(*)(fy_document_iterator*)> it( + fy_document_iterator_create(), + &fy_document_iterator_destroy); + fy_document_iterator_node_start(it.get(), node); + auto deleter = [&](fy_event* fye){ fy_document_iterator_event_free(it.get(), fye); }; + std::unique_ptr<fy_event, decltype(deleter)> ev( + fy_document_iterator_body_next(it.get()), + deleter); + auto* mark = fy_event_start_mark(ev.get()); + + if (!mark) { + ythrow yexception() << "can't get begin mark for a node"; + } + + return TMark{ + mark->input_pos, + mark->line, + mark->column, + }; +} + +namespace { + +fy_event_type GetOpenEventType(ENodeType type) { + switch(type) { + case ENodeType::Mapping: + return FYET_MAPPING_START; + case ENodeType::Sequence: + return FYET_SEQUENCE_START; + default: + Y_FAIL("Not a brackets type"); + } +} + +fy_event_type GetCloseEventType(ENodeType type) { + switch(type) { + case ENodeType::Mapping: + return FYET_MAPPING_END; + case ENodeType::Sequence: + return FYET_SEQUENCE_END; + default: + Y_FAIL("Not a brackets type"); + } +} + +} // anonymous namespace + +TMark TNodeOpsBase::EndMark(fy_node* node) const { + ENSURE_NODE_NOT_EMPTY(node); + std::unique_ptr<fy_document_iterator, void(*)(fy_document_iterator*)> it( + fy_document_iterator_create(), + &fy_document_iterator_destroy); + fy_document_iterator_node_start(it.get(), node); + + auto deleter = [&](fy_event* fye){ fy_document_iterator_event_free(it.get(), fye); }; + std::unique_ptr<fy_event, decltype(deleter)> prevEv( + nullptr, + deleter); + std::unique_ptr<fy_event, decltype(deleter)> ev( + fy_document_iterator_body_next(it.get()), + deleter); + + if (IsComplexType(Type(node))) { + int openBrackets = 0; + if (ev->type == GetOpenEventType(Type(node))) { + ++openBrackets; + } + if (ev->type == GetCloseEventType(Type(node))) { + --openBrackets; + } + while (ev->type != GetCloseEventType(Type(node)) || openBrackets != 0) { + std::unique_ptr<fy_event, decltype(deleter)> cur( + fy_document_iterator_body_next(it.get()), + deleter); + if (cur == nullptr) { + break; + } + if (cur->type == GetOpenEventType(Type(node))) { + ++openBrackets; + } + if (cur->type == GetCloseEventType(Type(node))) { + --openBrackets; + } + if (fy_event_get_node_style(cur.get()) != FYNS_BLOCK) { + prevEv.reset(ev.release()); + ev.reset(cur.release()); + } + } + } + + auto* mark = fy_event_end_mark(ev.get()); + + if (!mark && prevEv) { + mark = fy_event_end_mark(prevEv.get()); + } + + if (!mark) { + ythrow yexception() << "can't get end mark for a node"; + } + + return TMark{ + mark->input_pos, + mark->line, + mark->column, + }; +} + +fy_node* TNodeOpsBase::Map(fy_node* node) const { + ENSURE_NODE_NOT_EMPTY(node); + Y_ENSURE_EX(fy_node_is_mapping(node), TFyamlEx() << "Node is not Mapping: " << Path(node)); + return node; +} + +fy_node* TNodeOpsBase::Sequence(fy_node* node) const { + ENSURE_NODE_NOT_EMPTY(node); + Y_ENSURE_EX(fy_node_is_sequence(node), TFyamlEx() << "Node is not Sequence: " << Path(node)); + return node; +} + +void TNodeOpsBase::Insert(fy_node* thisNode, fy_node* node) { + ENSURE_NODE_NOT_EMPTY(node); + RethrowOnError(fy_node_insert(thisNode, node), thisNode); +} + +std::optional<TString> TNodeOpsBase::Tag(fy_node* node) const { + ENSURE_NODE_NOT_EMPTY(node); + size_t len = 0; + const char* tag = fy_node_get_tag(node, &len); + + if (tag) { + return TString(tag, len); + } + + return std::nullopt; +} + +void TNodeOpsBase::SetTag(fy_node* node, const TString& tag) { + ENSURE_NODE_NOT_EMPTY(node); + auto* str = new TString(std::move(tag)); + auto* data = new TUserDataHolder(UserData(node), str); + SetUserData(node, data); + RethrowOnError(fy_node_set_tag(node, str->c_str(), str->length()), node); +} + +bool TNodeOpsBase::RemoveTag(fy_node* node) { + ENSURE_NODE_NOT_EMPTY(node); + bool ret = fy_node_remove_tag(node); + ClearUserData(node); + return ret; +} + +bool TNodeOpsBase::HasAnchor(fy_node* node) const { + ENSURE_NODE_NOT_EMPTY(node); + return fy_node_get_anchor(node) != nullptr; +} + +void TNodeOpsBase::SetAnchor(fy_node* node, const TString& anchor) { + auto* str = new TString(anchor); + auto* data = new TUserDataHolder(UserData(node), str); + SetUserData(node, data); + RethrowOnError(fy_node_set_anchor(node, str->c_str(), str->length()), node); +} + +bool TNodeOpsBase::DeepEqual(fy_node* thisNode, fy_node* other) { + ENSURE_NODE_NOT_EMPTY(thisNode); + ENSURE_NODE_NOT_EMPTY(other); + return fy_node_compare(thisNode, other); +} + +std::unique_ptr<char, void(*)(char*)> TNodeOpsBase::EmitToCharArray(fy_node* node) const { + std::unique_ptr<char, void(*)(char*)> res( + fy_emit_node_to_string( + node, + (fy_emitter_cfg_flags)(FYECF_DEFAULT)), &FreeChar); + return res; +} + +void TNodeOpsBase::SetStyle(fy_node* node, ENodeStyle style) { + ENSURE_NODE_NOT_EMPTY(node); + fy_node_set_style(node, (enum fy_node_style)style); +} + +ENodeStyle TNodeOpsBase::Style(fy_node* node) const { + ENSURE_NODE_NOT_EMPTY(node); + return (ENodeStyle)fy_node_get_style(node); +} + +void TNodeOpsBase::SetUserData(fy_node* node, IBasicUserData* data) { + ENSURE_NODE_NOT_EMPTY(node); + fy_node_set_meta(node, data); +} + +IBasicUserData* TNodeOpsBase::UserData(fy_node* node) const { + ENSURE_NODE_NOT_EMPTY(node); + return reinterpret_cast<IBasicUserData* >(fy_node_get_meta(node)); +} + +void TNodeOpsBase::ClearUserData(fy_node* node) { + ENSURE_NODE_NOT_EMPTY(node); + fy_node_clear_meta(node); +} + void ThrowAllExceptionsIfAny(fy_diag* diag) { void* iter = nullptr; fy_diag_error* err = fy_diag_errors_iterate(diag, &iter); @@ -1093,11 +1086,14 @@ void RethrowOnError(bool isError, fy_diag* diag) { RethrowError(diag); } - void FreeChar(char* mem) { free(mem); } +bool IsComplexType(ENodeType type) { + return type == ENodeType::Mapping || type == ENodeType::Sequence; +} + } // namespace NDetail } // namespace NFyaml @@ -1116,3 +1112,11 @@ template <> void Out<NFyaml::TJsonEmitter>(IOutputStream& out, const NFyaml::TJsonEmitter& value) { out << value.EmitToCharArray().get(); } + +bool operator==(const fy_node* node1, const NFyaml::NDetail::TNodeOps<NFyaml::TNodeRef>& node2) { + return node2.Node() == node1; +} + +bool operator==(const fy_node* node1, const NFyaml::NDetail::TNodeOps<NFyaml::TNode>& node2) { + return node2.Node() == node1; +} |