diff options
| author | jansenin <[email protected]> | 2023-08-02 16:09:05 +0300 | 
|---|---|---|
| committer | jansenin <[email protected]> | 2023-08-02 16:09:05 +0300 | 
| commit | c0ca04d62a4ae68bf09193c3a9941d28bf343028 (patch) | |
| tree | 39e0e887276bda21e6de99275b9c6e74c8b444d4 /library/cpp | |
| parent | c1e8ecaf762b945d005bd42ed005e44c1604346d (diff) | |
Add TNodeOps class, that contains common functionality of TNodeRef and TNode
Diffstat (limited to 'library/cpp')
| -rw-r--r-- | library/cpp/yaml/fyamlcpp/fyamlcpp.cpp | 554 | ||||
| -rw-r--r-- | library/cpp/yaml/fyamlcpp/fyamlcpp.h | 400 | ||||
| -rw-r--r-- | library/cpp/yaml/fyamlcpp/fyamlcpp_ut.cpp | 4 | 
3 files changed, 601 insertions, 357 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; +} diff --git a/library/cpp/yaml/fyamlcpp/fyamlcpp.h b/library/cpp/yaml/fyamlcpp/fyamlcpp.h index a6bdf569274..cb622bd146e 100644 --- a/library/cpp/yaml/fyamlcpp/fyamlcpp.h +++ b/library/cpp/yaml/fyamlcpp/fyamlcpp.h @@ -10,6 +10,9 @@  #include <memory>  #include <optional> +#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") +  struct fy_parser;  struct fy_node;  struct fy_document; @@ -19,6 +22,18 @@ struct fy_node_pair;  extern "C" struct fy_node *fy_node_buildf(struct fy_document *fyd, const char *fmt, ...);  namespace NFyaml { +    namespace NDetail { +        template <class T> +        class TNodeOps; +    } +    class TNodeRef; +    class TNode; +} + +bool operator==(const fy_node* node1, const NFyaml::NDetail::TNodeOps<NFyaml::TNodeRef>& node2); +bool operator==(const fy_node* node1, const NFyaml::NDetail::TNodeOps<NFyaml::TNode>& node2); + +namespace NFyaml {  struct TStringPtrHashT {      size_t operator()(const TSimpleSharedPtr<TString>& str) const { @@ -81,6 +96,20 @@ enum class ENodeStyle {      Alias,  }; +class TNodeRef; +class TDocumentIterator; +class TDocument; +class TNode; +class TMappingIterator; +class TReverseMappingIterator; +class TMapping; +class TSequenceIterator; +class TReverseSequenceIterator; +class TSequence; +class TJsonEmitter; +class TParser; +struct TMark; +  namespace NDetail {  class IBasicUserData { @@ -113,60 +142,76 @@ void RethrowOnError(bool isError, fy_diag* diag);  void FreeChar(char* mem); -} // namespace NDetail +bool IsComplexType(ENodeType type); -class TNodeRef; -class TDocumentIterator; -class TDocument; -class TNode; -class TMappingIterator; -class TReverseMappingIterator; -class TMapping; -class TSequenceIterator; -class TReverseSequenceIterator; -class TSequence; -class TJsonEmitter; -class TParser; -struct TMark; +class TNodeOpsBase { +protected: +    TString Path(fy_node* node) const; -class TDocumentIterator { -    friend class TDocument; -public: -    TDocumentIterator(fy_document_iterator* iterator = nullptr); +    ENodeType Type(fy_node* node) const; -protected: -    std::unique_ptr<fy_document_iterator, void(*)(fy_document_iterator*)> Iterator_; -}; +    fy_node* Copy(fy_node* node) const; -class TNodeRef { -    friend class TDocument; -    friend class TDocumentNodeIterator; -    friend class TNode; -    friend class TMapping; -    friend class TMappingIterator; -    friend class TReverseMappingIterator; -    friend class TNodePairRef; -    friend class TSequence; -    friend class TSequenceIterator; -    friend class TReverseSequenceIterator; -    friend class TJsonEmitter; +    fy_node* Copy(fy_node* node, fy_document* to) const; -    TNodeRef(fy_node* node) -        : Node_(node) -    {} +    bool IsAlias(fy_node* node) const; -public: -    TNodeRef() = default; +    fy_node* ResolveAlias(fy_node* node) const; -    TNodeRef(const TNodeRef& other) { Node_ = other.Node_; } +    fy_node* CreateReference(fy_node* node) const; -    TNodeRef& operator=(const TNodeRef& other) { Node_ = other.Node_; return *this; } +    fy_node* Sequence(fy_node* node) const; -    TNodeRef& operator=(fy_node* node) { Node_ = node; return *this; } +    fy_node* Map(fy_node* node) const; + +    TString Scalar(fy_node* node) const; + +    TMark BeginMark(fy_node* node) const; + +    TMark EndMark(fy_node* node) const; + +    void Insert(fy_node* thisNode, fy_node* node); + +    std::optional<TString> Tag(fy_node* node) const; -    bool operator==(const TNodeRef& other) const { return Node_ == other.Node_; } +    void SetTag(fy_node* node, const TString& tag); -    explicit operator bool() const { return Node_ != nullptr; } +    bool RemoveTag(fy_node* node); + +    bool HasAnchor(fy_node* node) const; + +    void SetAnchor(fy_node* node, const TString& anchor); + +    bool DeepEqual(fy_node* thisNode, fy_node* other); + +    std::unique_ptr<char, void(*)(char*)> EmitToCharArray(fy_node* node) const; + +    void SetStyle(fy_node* node, ENodeStyle style); + +    ENodeStyle Style(fy_node* node) const; + +protected: +    void SetUserData(fy_node* node, NDetail::IBasicUserData* data); + +    NDetail::IBasicUserData* UserData(fy_node* node) const; + +    void ClearUserData(fy_node* node); +}; + +template <class T> +class TNodeOps : public TNodeOpsBase { +friend class ::NFyaml::TNodeRef; + +public: +    template <class OtherT> +    bool operator==(const TNodeOps<OtherT>& other) const { return Node() == other.Node(); } + +    bool operator==(const fy_node* node) const { return Node() == node; } + +    friend bool ::operator==(const fy_node* node1, const TNodeOps<NFyaml::TNodeRef>& node2); +    friend bool ::operator==(const fy_node* node1, const TNodeOps<NFyaml::TNode>& node2); + +    explicit operator bool() const { return Node() != nullptr; }      TString Path() const; @@ -194,7 +239,7 @@ public:      void Insert(const TNodeRef& node); -    bool Empty() const { return Node_ == nullptr; } +    bool Empty() const { return Node() == nullptr; }      std::optional<TString> Tag() const; @@ -215,41 +260,93 @@ public:      ENodeStyle Style() const;  protected: -    fy_node* Node_ = nullptr; +    const T& AsDerived() const; + +    fy_node* Node() const; + +    fy_node* Node();      void SetUserData(NDetail::IBasicUserData* data); +      NDetail::IBasicUserData* UserData() const; +      void ClearUserData();  }; -class TNode { +} // namespace NDetail + +class TDocumentIterator { +    friend class TDocument; +public: +    explicit TDocumentIterator(fy_document_iterator* iterator = nullptr); + +protected: +    std::unique_ptr<fy_document_iterator, void(*)(fy_document_iterator*)> Iterator_; +}; + +class TNodeRef : public NDetail::TNodeOps<TNodeRef> { +    friend class TNodeOps<TNodeRef>; +    friend class TNodeOpsBase;      friend class TDocument;      friend class TDocumentNodeIterator; -    friend class TNodeRef; +    friend class TMapping; +    friend class TMappingIterator; +    friend class TReverseMappingIterator; +    friend class TNodePairRef;      friend class TSequence; +    friend class TSequenceIterator; +    friend class TReverseSequenceIterator; +    friend class TJsonEmitter; -    TNode& operator=(fy_node* node);  public: -    TNode(fy_node* node = nullptr); +    TNodeRef() = default; + +    template <class T> +    TNodeRef(const TNodeOps<T>& other) : Node_(other.Node()) {} + +    explicit TNodeRef(const TNodeRef& other) : Node_(other.Node_) {} + +    TNodeRef(fy_node* node); + +    TNodeRef& operator=(const TNodeRef& other) { Node_ = other.Node_; return *this; } + +    TNodeRef& operator=(fy_node* node) { Node_ = node; return *this; } + +protected: +    fy_node* Node_ = nullptr; -    bool operator==(const TNode& other) const { return Node_ == other.Node_; } +private: +    fy_node* NodeRawPointer() const; +}; + +class TNode : public NDetail::TNodeOps<TNode> { +    friend class TNodeOps<TNode>; + +public: +    TNode(fy_node* node = nullptr); -    explicit operator bool() { return Node_ != nullptr; } +    template <class T> +    explicit TNode(const TNodeOps<T>& other) : Node_(other.Node_) {} -    TNodeRef Ref() { return TNodeRef(Node_.get()); } +    TNodeRef Ref() { return TNodeRef(*this); }  private:      std::shared_ptr<fy_node> Node_; + +    TNode& operator=(fy_node* node); + +    fy_node* NodeRawPointer() const { +        return Node_.get(); +    }  };  class TNodePairRef { -    friend class TMappingIterator; -    friend class TReverseMappingIterator; -    friend class TMapping; +friend class TMappingIterator; +friend class TReverseMappingIterator; +friend class TMapping; +  public: -    TNodePairRef(fy_node_pair* pair = nullptr) -        : Pair_(pair) -    {} +    TNodePairRef(fy_node_pair* pair = nullptr) : Pair_(pair) {}      bool operator==(const TNodePairRef& other) const { return Pair_ == other.Pair_; } @@ -272,7 +369,7 @@ private:  class TMappingIterator {      friend class TMapping;  public: -    TMappingIterator(const TNodeRef& node, bool end = false); +    explicit TMappingIterator(const TNodeRef& node, bool end = false);      TMappingIterator(const TMappingIterator& other) {          Node_ = other.Node_; @@ -307,7 +404,7 @@ private:  class TReverseMappingIterator {      friend class TMapping;  public: -    TReverseMappingIterator(const TNodeRef& node, bool end = false); +    explicit TReverseMappingIterator(const TNodeRef& node, bool end = false);      TReverseMappingIterator(const TReverseMappingIterator& other) {          Node_ = other.Node_; @@ -343,26 +440,27 @@ private:  class TMapping : public TNodeRef {  public: -    explicit TMapping(const TNodeRef& node) +    template <class T> +    explicit TMapping(const TNodeOps<T>& node)          : TNodeRef(node)      {          Y_VERIFY_DEBUG(Type() == ENodeType::Mapping);      }      TMappingIterator begin() const { -        return TMappingIterator(Node_); +        return TMappingIterator(*this);      }      TMappingIterator end() const { -        return TMappingIterator(Node_, true); +        return TMappingIterator(*this, true);      }      TReverseMappingIterator rbegin() const { -        return TReverseMappingIterator(Node_); +        return TReverseMappingIterator(*this);      }      TReverseMappingIterator rend() const { -        return TReverseMappingIterator(Node_, true); +        return TReverseMappingIterator(*this, true);      }      size_t size() const; @@ -397,7 +495,7 @@ public:  class TSequenceIterator {      friend class TSequence;  public: -    TSequenceIterator(const TNodeRef& node, bool end = false); +    explicit TSequenceIterator(const TNodeRef& node, bool end = false);      TSequenceIterator(const TSequenceIterator& other) {          Node_ = other.Node_; @@ -443,7 +541,7 @@ private:  class TReverseSequenceIterator {      friend class TSequence;  public: -    TReverseSequenceIterator(const TNodeRef& node, bool end = false); +    explicit TReverseSequenceIterator(const TNodeRef& node, bool end = false);      TReverseSequenceIterator(const TReverseSequenceIterator& other) {          Node_ = other.Node_; @@ -495,19 +593,19 @@ public:      }      TSequenceIterator begin() const { -        return TSequenceIterator(Node_); +        return TSequenceIterator(*this);      }      TSequenceIterator end() const { -        return TSequenceIterator(Node_, true); +        return TSequenceIterator(*this, true);      }      TReverseSequenceIterator rbegin() const { -        return TReverseSequenceIterator(Node_); +        return TReverseSequenceIterator(*this);      }      TReverseSequenceIterator rend() const { -        return TReverseSequenceIterator(Node_, true); +        return TReverseSequenceIterator(*this, true);      }      size_t size() const; @@ -537,7 +635,7 @@ class TDocumentNodeIterator      : public TDocumentIterator  {  public: -    TDocumentNodeIterator(TNodeRef&& node); +    explicit TDocumentNodeIterator(TNodeRef&& node);      TDocumentNodeIterator(const TDocumentNodeIterator& other)          : TDocumentIterator(other.Iterator_.get()) @@ -573,14 +671,12 @@ private:  };  class TDocument { -    friend class TNode; -    friend class TNodeRef; -    friend class TJsonEmitter; +    friend class NDetail::TNodeOps<TNodeRef>; +    friend class NDetail::TNodeOps<TNode>;      friend class TParser; -    friend class TMapping; -    TDocument(TString str, fy_document* doc = nullptr, fy_diag* diag = nullptr); -    TDocument(fy_document* doc = nullptr, fy_diag* diag = nullptr); +    explicit TDocument(TString str, fy_document* doc = nullptr, fy_diag* diag = nullptr); +    explicit TDocument(fy_document* doc = nullptr, fy_diag* diag = nullptr);  public:      TDocument(TDocument&& other) @@ -667,8 +763,8 @@ private:  class TJsonEmitter {  public: -    TJsonEmitter(TDocument& doc) : Node_(doc.Root()) {} -    TJsonEmitter(const TNodeRef& node) : Node_(node) {} +    explicit TJsonEmitter(TDocument& doc) : Node_(doc.Root()) {} +    explicit TJsonEmitter(const TNodeRef& node) : Node_(node) {}      std::unique_ptr<char, void(*)(char*)> EmitToCharArray() const; @@ -694,4 +790,148 @@ struct TMark {      int Column;  }; +namespace NDetail { + +template <class T> +TNode TNodeOps<T>::CreateReference() const { +    return TNode(TNodeOpsBase::CreateReference(Node())); +} + +template <class T> +TNode TNodeOps<T>::Copy() const { +    return TNode(TNodeOpsBase::Copy(Node())); +} + +template <class T> +TNode TNodeOps<T>::Copy(TDocument& to) const { +    return TNode(TNodeOpsBase::Copy(Node(), to.Document_.get())); +} + +template <class T> +TString TNodeOps<T>::Path() const { +    return TNodeOpsBase::Path(Node()); +} + +template <class T> +ENodeType TNodeOps<T>::Type() const { +    return TNodeOpsBase::Type(Node()); +} + +template <class T> +bool TNodeOps<T>::IsAlias() const { +    return TNodeOpsBase::IsAlias(Node()); +} + +template <class T> +TNodeRef TNodeOps<T>::ResolveAlias() const { +    return TNodeRef(TNodeOpsBase::ResolveAlias(Node())); +} + +template <class T> +TString TNodeOps<T>::Scalar() const { +    return TNodeOpsBase::Scalar(Node()); +} + +template <class T> +TMark TNodeOps<T>::BeginMark() const { +    return TNodeOpsBase::BeginMark(Node()); +} + +template <class T> +TMark TNodeOps<T>::EndMark() const { +    return TNodeOpsBase::EndMark(Node()); +} + +template <class T> +TMapping TNodeOps<T>::Map() const { +    return TMapping(TNodeRef(TNodeOpsBase::Map(Node()))); +} + +template <class T> +TSequence TNodeOps<T>::Sequence() const { +    return TSequence(TNodeRef(TNodeOpsBase::Sequence(Node()))); +} + +template <class T> +void TNodeOps<T>::Insert(const TNodeRef& node) { +    return TNodeOpsBase::Insert(Node(), node.Node_); +} + +template <class T> +std::optional<TString> TNodeOps<T>::Tag() const { +    return TNodeOpsBase::Tag(Node()); +} + +template <class T> +void TNodeOps<T>::SetTag(const TString& tag) { +    return TNodeOpsBase::SetTag(Node(), tag); +} + +template <class T> +bool TNodeOps<T>::RemoveTag() { +    return TNodeOpsBase::RemoveTag(Node()); +} + +template <class T> +bool TNodeOps<T>::HasAnchor() const { +    return TNodeOpsBase::HasAnchor(Node()); +} + +template <class T> +void TNodeOps<T>::SetAnchor(const TString& anchor) { +    return TNodeOpsBase::SetAnchor(Node(), anchor); +} + +template <class T> +bool TNodeOps<T>::DeepEqual(const TNodeRef& other) { +    return TNodeOpsBase::DeepEqual(Node(), other.Node_); +} + +template <class T> +std::unique_ptr<char, void(*)(char*)> TNodeOps<T>::EmitToCharArray() const { +    return TNodeOpsBase::EmitToCharArray(Node()); +} + +template <class T> +void TNodeOps<T>::SetStyle(ENodeStyle style) { +    return TNodeOpsBase::SetStyle(Node(), style); +} + +template <class T> +ENodeStyle TNodeOps<T>::Style() const { +    return TNodeOpsBase::Style(Node()); +} + +template <class T> +const T& TNodeOps<T>::AsDerived() const { +    return static_cast<const T&>(*this); +} + +template <class T> +fy_node* TNodeOps<T>::Node() const { +    return AsDerived().NodeRawPointer(); +} + +template <class T> +fy_node* TNodeOps<T>::Node() { +    return AsDerived().NodeRawPointer(); +} + +template <class T> +void TNodeOps<T>::SetUserData(IBasicUserData* data) { +    return TNodeOpsBase::SetUserData(Node(), data); +} + +template <class T> +IBasicUserData* TNodeOps<T>::UserData() const { +    return TNodeOpsBase::UserData(Node()); +} + +template <class T> +void TNodeOps<T>::ClearUserData() { +    return TNodeOpsBase::ClearUserData(Node()); +} + +} // namespace NDetail +  } // namesapce NFyaml diff --git a/library/cpp/yaml/fyamlcpp/fyamlcpp_ut.cpp b/library/cpp/yaml/fyamlcpp/fyamlcpp_ut.cpp index 67e918a2978..041a7028b33 100644 --- a/library/cpp/yaml/fyamlcpp/fyamlcpp_ut.cpp +++ b/library/cpp/yaml/fyamlcpp/fyamlcpp_ut.cpp @@ -162,8 +162,8 @@ x: b                  auto docNodeRef = doc->Root().Map().at("test");                  auto node1 = item1NodeRef.Copy(*doc);                  auto node2 = item2NodeRef.Copy(*doc); -                docNodeRef.Sequence().Append(node1.Ref()); -                docNodeRef.Sequence().Append(node2.Ref()); +                docNodeRef.Sequence().Append(node1); +                docNodeRef.Sequence().Append(node2);                  item1.reset();                  item2.reset();              } | 
