aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorinnokentii <innokentii@yandex-team.com>2023-03-02 13:04:09 +0300
committerinnokentii <innokentii@yandex-team.com>2023-03-02 13:04:09 +0300
commit502e6daf19bdde912acdb7fff06f1e69e9ccfddf (patch)
treefc85748caec9a506aae3d7821b42c2c3d5ac1a46
parented0c1088f25e4078c42314bc9c0d67ac971a0710 (diff)
downloadydb-502e6daf19bdde912acdb7fff06f1e69e9ccfddf.tar.gz
Add multidoc support to fyamlcpp
add multidoc support to libfyaml
-rw-r--r--library/cpp/yaml/fyamlcpp/fyamlcpp.cpp72
-rw-r--r--library/cpp/yaml/fyamlcpp/fyamlcpp.h37
-rw-r--r--library/cpp/yaml/fyamlcpp/fyamlcpp_ut.cpp36
3 files changed, 137 insertions, 8 deletions
diff --git a/library/cpp/yaml/fyamlcpp/fyamlcpp.cpp b/library/cpp/yaml/fyamlcpp/fyamlcpp.cpp
index 42ee6b830d..fc804128e4 100644
--- a/library/cpp/yaml/fyamlcpp/fyamlcpp.cpp
+++ b/library/cpp/yaml/fyamlcpp/fyamlcpp.cpp
@@ -280,6 +280,11 @@ TNode TNodeRef::Copy() const {
return TNode(fy_node_copy(fy_node_document(Node_), Node_));
}
+TNode TNodeRef::Copy(const TDocument& to) const {
+ ENSURE_NODE_NOT_EMPTY(Node_);
+ 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_);
@@ -801,14 +806,77 @@ void TDocument::UnregisterUserDataCleanup() {
fy_document_unregister_meta(Document_.get());
}
+TMark TDocument::BeginMark() const {
+ ENSURE_DOCUMENT_NOT_EMPTY(Document_);
+ auto* fyds = fy_document_get_document_state(Document_.get());
+ auto* mark = fy_document_state_start_mark(fyds);
+ return TMark{
+ mark->input_pos,
+ mark->line,
+ mark->column,
+ };
+}
+
+TMark TDocument::EndMark() const {
+ ENSURE_DOCUMENT_NOT_EMPTY(Document_);
+ auto* fyds = fy_document_get_document_state(Document_.get());
+ auto* mark = fy_document_state_end_mark(fyds);
+ return TMark{
+ mark->input_pos,
+ mark->line,
+ mark->column,
+ };
+}
+
std::unique_ptr<char, void(*)(char*)> TJsonEmitter::EmitToCharArray() const {
std::unique_ptr<char, void(*)(char*)> res(
- fy_emit_document_to_string(
- Document_.Document_.get(),
+ fy_emit_node_to_string(
+ Node_.Node_,
(fy_emitter_cfg_flags)(FYECF_DEFAULT | FYECF_SORT_KEYS | FYECF_MODE_JSON_TP)), &NDetail::FreeChar);
return res;
}
+TParser::TParser(fy_parser* parser, fy_diag* diag)
+ : Parser_(parser, fy_parser_destroy)
+ , Diag_(diag, fy_diag_destroy)
+{}
+
+TParser TParser::Create(const char* stream)
+{
+ fy_diag_cfg dcfg;
+ fy_diag_cfg_default(&dcfg);
+ std::unique_ptr<fy_diag, void(*)(fy_diag*)> diag(fy_diag_create(&dcfg), fy_diag_destroy);
+ fy_diag_set_collect_errors(diag.get(), true);
+ fy_parse_cfg cfg{
+ "",
+ // FYPCF_PARSE_COMMENTS,
+ FYPCF_QUIET,
+ nullptr,
+ diag.get()
+ };
+ auto* parser = fy_parser_create(&cfg);
+ if (!parser) {
+ fy_diag_error* err;
+ void *iter = nullptr;
+ while ((err = fy_diag_errors_iterate(diag.get(), &iter)) != nullptr) {
+ ythrow yexception() << err->file << ":" << err->line << ":" << err->column << " " << err->msg;
+ }
+ }
+
+ fy_parser_set_string(parser, stream, -1);
+
+ return TParser(parser, diag.release());
+}
+
+std::optional<TDocument> TParser::NextDocument() {
+ auto* doc = fy_parse_load_document(Parser_.get());
+ if (!doc) {
+ return std::nullopt;
+ }
+
+ return TDocument(doc, fy_document_get_diag(doc));
+}
+
namespace NDetail {
void RethrowError(fy_diag* diag) {
diff --git a/library/cpp/yaml/fyamlcpp/fyamlcpp.h b/library/cpp/yaml/fyamlcpp/fyamlcpp.h
index 7437b74ef7..5b645a557c 100644
--- a/library/cpp/yaml/fyamlcpp/fyamlcpp.h
+++ b/library/cpp/yaml/fyamlcpp/fyamlcpp.h
@@ -8,6 +8,7 @@
#include <memory>
#include <optional>
+struct fy_parser;
struct fy_node;
struct fy_document;
struct fy_diag;
@@ -67,6 +68,8 @@ class TSequenceIterator;
class TReverseSequenceIterator;
class TSequence;
class TJsonEmitter;
+class TParser;
+struct TMark;
class TDocumentIterator {
friend class TDocument;
@@ -88,6 +91,7 @@ class TNodeRef {
friend class TSequence;
friend class TSequenceIterator;
friend class TReverseSequenceIterator;
+ friend class TJsonEmitter;
TNodeRef(fy_node* node)
: Node_(node)
@@ -112,6 +116,8 @@ public:
TNode Copy() const;
+ TNode Copy(const TDocument& to) const;
+
bool IsAlias() const;
TNodeRef ResolveAlias() const;
@@ -500,7 +506,9 @@ private:
class TDocument {
friend class TNode;
+ friend class TNodeRef;
friend class TJsonEmitter;
+ friend class TParser;
TDocument(fy_document* doc = nullptr, fy_diag* diag = nullptr);
@@ -550,7 +558,6 @@ public:
return it;
}
-
TDocumentNodeIterator end() {
return TDocumentNodeIterator(TNodeRef(nullptr));
}
@@ -559,6 +566,10 @@ public:
std::unique_ptr<char, void(*)(char*)> EmitToCharArray() const;
+ TMark BeginMark() const;
+
+ TMark EndMark() const;
+
private:
std::unique_ptr<fy_document, void(*)(fy_document*)> Document_;
std::unique_ptr<fy_diag, void(*)(fy_diag*)> Diag_;
@@ -578,16 +589,30 @@ private:
class TJsonEmitter {
public:
- TJsonEmitter(const TDocument& doc) : Document_(doc) {}
+ TJsonEmitter(TDocument& doc) : Node_(doc.Root()) {}
+ TJsonEmitter(const TNodeRef& node) : Node_(node) {}
std::unique_ptr<char, void(*)(char*)> EmitToCharArray() const;
private:
- const TDocument& Document_;
+ const TNodeRef Node_;
+};
+
+class TParser {
+ TParser(fy_parser* doc, fy_diag* diag);
+public:
+ static TParser Create(const char* cstr);
+
+ std::optional<TDocument> NextDocument();
+private:
+ std::unique_ptr<fy_parser, void(*)(fy_parser*)> Parser_;
+ std::unique_ptr<fy_diag, void(*)(fy_diag*)> Diag_;
+};
- fy_document* Document() const {
- return Document_.Document_.get();
- }
+struct TMark {
+ size_t InputPos;
+ int Line;
+ int Column;
};
} // namesapce NFyaml
diff --git a/library/cpp/yaml/fyamlcpp/fyamlcpp_ut.cpp b/library/cpp/yaml/fyamlcpp/fyamlcpp_ut.cpp
index f9aab7b011..94093c4157 100644
--- a/library/cpp/yaml/fyamlcpp/fyamlcpp_ut.cpp
+++ b/library/cpp/yaml/fyamlcpp/fyamlcpp_ut.cpp
@@ -50,4 +50,40 @@ test: output
UNIT_ASSERT_VALUES_EQUAL(ss.Str(), "test: output\n");
}
+
+ Y_UNIT_TEST(Parser) {
+ const char *yaml = R"(
+test: a
+---
+test: b
+)";
+ auto parser = NFyaml::TParser::Create(yaml);
+
+ TStringStream ss;
+
+ auto docOpt = parser.NextDocument();
+ UNIT_ASSERT(docOpt);
+ ss << *docOpt;
+ UNIT_ASSERT_VALUES_EQUAL(ss.Str(), "test: a\n");
+ auto beginMark = docOpt->BeginMark();
+ UNIT_ASSERT_VALUES_EQUAL(beginMark.InputPos, 1);
+ auto endMark = docOpt->EndMark();
+ UNIT_ASSERT_VALUES_EQUAL(endMark.InputPos, 12);
+ UNIT_ASSERT_VALUES_EQUAL(TStringBuf(yaml).SubStr(beginMark.InputPos, endMark.InputPos - 4), ss.Str());
+
+ ss.clear();
+
+ auto docOpt2 = parser.NextDocument();
+ UNIT_ASSERT(docOpt2);
+ ss << *docOpt2;
+ UNIT_ASSERT_VALUES_EQUAL(ss.Str(), "---\ntest: b\n");
+ beginMark = docOpt2->BeginMark();
+ UNIT_ASSERT_VALUES_EQUAL(beginMark.InputPos, 9);
+ endMark = docOpt2->EndMark();
+ UNIT_ASSERT_VALUES_EQUAL(endMark.InputPos, 21);
+ UNIT_ASSERT_VALUES_EQUAL(TStringBuf(yaml).SubStr(beginMark.InputPos, endMark.InputPos), ss.Str());
+
+ auto docOpt3 = parser.NextDocument();
+ UNIT_ASSERT(!docOpt3);
+ }
}