aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjansenin <jansenin@yandex-team.com>2023-08-02 16:09:05 +0300
committerjansenin <jansenin@yandex-team.com>2023-08-02 16:09:05 +0300
commitc0ca04d62a4ae68bf09193c3a9941d28bf343028 (patch)
tree39e0e887276bda21e6de99275b9c6e74c8b444d4
parentc1e8ecaf762b945d005bd42ed005e44c1604346d (diff)
downloadydb-c0ca04d62a4ae68bf09193c3a9941d28bf343028.tar.gz
Add TNodeOps class, that contains common functionality of TNodeRef and TNode
-rw-r--r--library/cpp/yaml/fyamlcpp/fyamlcpp.cpp554
-rw-r--r--library/cpp/yaml/fyamlcpp/fyamlcpp.h400
-rw-r--r--library/cpp/yaml/fyamlcpp/fyamlcpp_ut.cpp4
3 files changed, 601 insertions, 357 deletions
diff --git a/library/cpp/yaml/fyamlcpp/fyamlcpp.cpp b/library/cpp/yaml/fyamlcpp/fyamlcpp.cpp
index 8f9321a252..37ead18350 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 a6bdf56927..cb622bd146 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 67e918a297..041a7028b3 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();
}