fyamlcpp.cpp 34 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126
  1. #include "fyamlcpp.h"
  2. #include <contrib/libs/libfyaml/include/libfyaml.h>
  3. #include <util/digest/murmur.h>
  4. namespace NFyaml {
  5. const char* zstr = "";
  6. enum class EErrorType {
  7. Debug = FYET_DEBUG,
  8. Info = FYET_INFO,
  9. Notice = FYET_NOTICE,
  10. Warning = FYET_WARNING,
  11. Error = FYET_ERROR,
  12. Max = FYET_MAX,
  13. };
  14. enum class EErrorModule {
  15. Unknown = FYEM_UNKNOWN,
  16. Atom = FYEM_ATOM,
  17. Scan = FYEM_SCAN,
  18. Parse = FYEM_PARSE,
  19. Doc = FYEM_DOC,
  20. Build = FYEM_BUILD,
  21. Internal = FYEM_INTERNAL,
  22. System = FYEM_SYSTEM,
  23. Max = FYEM_MAX,
  24. };
  25. enum class EParseCfgFlags {
  26. Quiet = FYPCF_QUIET,
  27. CollectDiag = FYPCF_COLLECT_DIAG,
  28. ResolveDocument = FYPCF_RESOLVE_DOCUMENT,
  29. DisableMmapOpt = FYPCF_DISABLE_MMAP_OPT,
  30. DisableRecycling = FYPCF_DISABLE_RECYCLING,
  31. ParseComments = FYPCF_PARSE_COMMENTS,
  32. DisableDepth_limit = FYPCF_DISABLE_DEPTH_LIMIT,
  33. DisableAccelerators = FYPCF_DISABLE_ACCELERATORS,
  34. DisableBuffering = FYPCF_DISABLE_BUFFERING,
  35. DefaultVersionAuto = FYPCF_DEFAULT_VERSION_AUTO,
  36. DefaultVersion1_1 = FYPCF_DEFAULT_VERSION_1_1,
  37. DefaultVersion1_2 = FYPCF_DEFAULT_VERSION_1_2,
  38. DefaultVersion1_3 = FYPCF_DEFAULT_VERSION_1_3,
  39. SloppyFlowIndentation = FYPCF_SLOPPY_FLOW_INDENTATION,
  40. PreferRecursive = FYPCF_PREFER_RECURSIVE,
  41. JsonAuto = FYPCF_JSON_AUTO,
  42. JsonNone = FYPCF_JSON_NONE,
  43. JsonForce = FYPCF_JSON_FORCE,
  44. YpathAliases = FYPCF_YPATH_ALIASES,
  45. AllowDuplicateKeys = FYPCF_ALLOW_DUPLICATE_KEYS,
  46. };
  47. enum class EEventType {
  48. None = FYET_NONE,
  49. StreamStart = FYET_STREAM_START,
  50. StreamEnd = FYET_STREAM_END,
  51. DocumentStart = FYET_DOCUMENT_START,
  52. DocumentEnd = FYET_DOCUMENT_END,
  53. MappingStart = FYET_MAPPING_START,
  54. MappingEnd = FYET_MAPPING_END,
  55. SequenceStart = FYET_SEQUENCE_START,
  56. SequenceEnd = FYET_SEQUENCE_END,
  57. Scalar = FYET_SCALAR,
  58. Alias = FYET_ALIAS,
  59. };
  60. enum class EScalarStyle {
  61. Any = FYSS_ANY,
  62. Plain = FYSS_PLAIN,
  63. SingleQuoted = FYSS_SINGLE_QUOTED,
  64. DoubleQuoted = FYSS_DOUBLE_QUOTED,
  65. Literal = FYSS_LITERAL,
  66. Folded = FYSS_FOLDED,
  67. Max = FYSS_MAX,
  68. };
  69. enum class EEmitterWriteType {
  70. DocumentIndicator = fyewt_document_indicator,
  71. TagDirective = fyewt_tag_directive,
  72. VersionDirective = fyewt_version_directive,
  73. Indent = fyewt_indent,
  74. Indicator = fyewt_indicator,
  75. Whitespace = fyewt_whitespace,
  76. PlainScalar = fyewt_plain_scalar,
  77. SingleQuotedScalar = fyewt_single_quoted_scalar,
  78. DoubleQuotedScalar = fyewt_double_quoted_scalar,
  79. LiteralScalar = fyewt_literal_scalar,
  80. FoldedScalar = fyewt_folded_scalar,
  81. Anchor = fyewt_anchor,
  82. Tag = fyewt_tag,
  83. Linebreak = fyewt_linebreak,
  84. Alias = fyewt_alias,
  85. TerminatingZero = fyewt_terminating_zero,
  86. PlainScalarKey = fyewt_plain_scalar_key,
  87. SingleQuotedScalarKey = fyewt_single_quoted_scalar_key,
  88. DoubleQuotedScalarKey = fyewt_double_quoted_scalar_key,
  89. Comment = fyewt_comment,
  90. };
  91. enum class ECommentPlacement {
  92. Top = fycp_top,
  93. Right = fycp_right,
  94. Bottom = fycp_bottom,
  95. };
  96. enum EEmitterCfgFlags {
  97. SortKeys = FYECF_SORT_KEYS,
  98. OutputComments = FYECF_OUTPUT_COMMENTS,
  99. StripLabels = FYECF_STRIP_LABELS,
  100. StripTags = FYECF_STRIP_TAGS,
  101. StripDoc = FYECF_STRIP_DOC,
  102. NoEndingNewline = FYECF_NO_ENDING_NEWLINE,
  103. StripEmptyKv = FYECF_STRIP_EMPTY_KV,
  104. IndentDefault = FYECF_INDENT_DEFAULT,
  105. Indent1 = FYECF_INDENT_1,
  106. Indent2 = FYECF_INDENT_2,
  107. Indent3 = FYECF_INDENT_3,
  108. Indent4 = FYECF_INDENT_4,
  109. Indent5 = FYECF_INDENT_5,
  110. Indent6 = FYECF_INDENT_6,
  111. Indent7 = FYECF_INDENT_7,
  112. Indent8 = FYECF_INDENT_8,
  113. Indent9 = FYECF_INDENT_9,
  114. WidthDefault = FYECF_WIDTH_DEFAULT,
  115. Width80 = FYECF_WIDTH_80,
  116. Width132 = FYECF_WIDTH_132,
  117. WidthInf = FYECF_WIDTH_INF,
  118. ModeOriginal = FYECF_MODE_ORIGINAL,
  119. ModeBlock = FYECF_MODE_BLOCK,
  120. ModeFlow = FYECF_MODE_FLOW,
  121. ModeFlowOneline = FYECF_MODE_FLOW_ONELINE,
  122. ModeJson = FYECF_MODE_JSON,
  123. ModeJsonTp = FYECF_MODE_JSON_TP,
  124. ModeJsonOneline = FYECF_MODE_JSON_ONELINE,
  125. ModeDejson = FYECF_MODE_DEJSON,
  126. ModePretty = FYECF_MODE_PRETTY,
  127. DocStartMarkAuto = FYECF_DOC_START_MARK_AUTO,
  128. DocStartMarkOff = FYECF_DOC_START_MARK_OFF,
  129. DocStartMarkOn = FYECF_DOC_START_MARK_ON,
  130. DocEndMarkAuto = FYECF_DOC_END_MARK_AUTO,
  131. DocEndMarkOff = FYECF_DOC_END_MARK_OFF,
  132. DocEndMarkOn = FYECF_DOC_END_MARK_ON,
  133. VersionDirAuto = FYECF_VERSION_DIR_AUTO,
  134. VersionDirOff = FYECF_VERSION_DIR_OFF,
  135. VersionDirOn = FYECF_VERSION_DIR_ON,
  136. TagDirAuto = FYECF_TAG_DIR_AUTO,
  137. TagDirOff = FYECF_TAG_DIR_OFF,
  138. TagDirOn = FYECF_TAG_DIR_ON,
  139. Default = FYECF_DEFAULT,
  140. };
  141. enum class ENodeWalkFlags {
  142. DontFollow = FYNWF_DONT_FOLLOW,
  143. Follow = FYNWF_FOLLOW,
  144. PtrYaml = FYNWF_PTR_YAML,
  145. PtrJson = FYNWF_PTR_JSON,
  146. PtrReljson = FYNWF_PTR_RELJSON,
  147. PtrYpath = FYNWF_PTR_YPATH,
  148. UriEncoded = FYNWF_URI_ENCODED,
  149. MaxdepthDefault = FYNWF_MAXDEPTH_DEFAULT,
  150. MarkerDefault = FYNWF_MARKER_DEFAULT,
  151. PtrDefault = FYNWF_PTR_DEFAULT,
  152. };
  153. enum class EPathParseCfgFlags {
  154. Quiet = FYPPCF_QUIET,
  155. DisableRecycling = FYPPCF_DISABLE_RECYCLING,
  156. DisableAccelerators = FYPPCF_DISABLE_ACCELERATORS,
  157. };
  158. enum class EPathExecCfgFlags {
  159. Quiet = FYPXCF_QUIET,
  160. DisableRecycling = FYPXCF_DISABLE_RECYCLING,
  161. DisableAccelerators = FYPXCF_DISABLE_ACCELERATORS,
  162. };
  163. enum class ETokenType {
  164. /* non-content token types */
  165. None = FYTT_NONE,
  166. StreamStart = FYTT_STREAM_START,
  167. StreamEnd = FYTT_STREAM_END,
  168. VersionDirective = FYTT_VERSION_DIRECTIVE,
  169. TagDirective = FYTT_TAG_DIRECTIVE,
  170. DocumentStart = FYTT_DOCUMENT_START,
  171. DocumentEnd = FYTT_DOCUMENT_END,
  172. /* content token types */
  173. BlockSequenceStart = FYTT_BLOCK_SEQUENCE_START,
  174. BlockMappingStart = FYTT_BLOCK_MAPPING_START,
  175. BlockEnd = FYTT_BLOCK_END,
  176. FlowSequenceStart = FYTT_FLOW_SEQUENCE_START,
  177. FlowSequenceEnd = FYTT_FLOW_SEQUENCE_END,
  178. FlowMappingStart = FYTT_FLOW_MAPPING_START,
  179. FlowMappingEnd = FYTT_FLOW_MAPPING_END,
  180. BlockEntry = FYTT_BLOCK_ENTRY,
  181. FlowEntry = FYTT_FLOW_ENTRY,
  182. Key = FYTT_KEY,
  183. Value = FYTT_VALUE,
  184. Alias = FYTT_ALIAS,
  185. Anchor = FYTT_ANCHOR,
  186. Tag = FYTT_TAG,
  187. Scalar = FYTT_SCALAR,
  188. /* special error reporting */
  189. Input_marker = FYTT_INPUT_MARKER,
  190. /* path expression tokens */
  191. PeSlash = FYTT_PE_SLASH,
  192. PeRoot = FYTT_PE_ROOT,
  193. PeThis = FYTT_PE_THIS,
  194. PeParent = FYTT_PE_PARENT,
  195. PeMapKey = FYTT_PE_MAP_KEY,
  196. PeSeqIndex = FYTT_PE_SEQ_INDEX,
  197. PeSeqSlice = FYTT_PE_SEQ_SLICE,
  198. PeScalarFilter = FYTT_PE_SCALAR_FILTER,
  199. PeCollectionFilter = FYTT_PE_COLLECTION_FILTER,
  200. PeSeqFilter = FYTT_PE_SEQ_FILTER,
  201. PeMapFilter = FYTT_PE_MAP_FILTER,
  202. PeUniqueFilter = FYTT_PE_UNIQUE_FILTER,
  203. PeEveryChild = FYTT_PE_EVERY_CHILD,
  204. PeEveryChildR = FYTT_PE_EVERY_CHILD_R,
  205. PeAlias = FYTT_PE_ALIAS,
  206. PeSibling = FYTT_PE_SIBLING,
  207. PeComma = FYTT_PE_COMMA,
  208. PeBarbar = FYTT_PE_BARBAR,
  209. PeAmpamp = FYTT_PE_AMPAMP,
  210. PeLparen = FYTT_PE_LPAREN,
  211. PeRparen = FYTT_PE_RPAREN,
  212. /* comparison operators */
  213. PeEqeq = FYTT_PE_EQEQ,
  214. PeNoteq = FYTT_PE_NOTEQ,
  215. PeLt = FYTT_PE_LT,
  216. PeGt = FYTT_PE_GT,
  217. PeLte = FYTT_PE_LTE,
  218. PeGte = FYTT_PE_GTE,
  219. /* scalar expression tokens */
  220. SePlus = FYTT_SE_PLUS,
  221. SeMinus = FYTT_SE_MINUS,
  222. SeMult = FYTT_SE_MULT,
  223. SeDiv = FYTT_SE_DIV,
  224. PeMethod = FYTT_PE_METHOD,
  225. SeMethod = FYTT_SE_METHOD,
  226. };
  227. enum class EComposerReturn {
  228. OkContinue = FYCR_OK_CONTINUE,
  229. OkStop = FYCR_OK_STOP,
  230. OkStartSkip = FYCR_OK_START_SKIP,
  231. OkStopSkip = FYCR_OK_STOP_SKIP,
  232. Error = FYCR_ERROR,
  233. };
  234. TDocumentIterator::TDocumentIterator(fy_document_iterator* iterator)
  235. : Iterator_(iterator, fy_document_iterator_destroy)
  236. {}
  237. TNodeRef::TNodeRef(fy_node* node)
  238. : Node_(node)
  239. {}
  240. fy_node* TNodeRef::NodeRawPointer() const {
  241. return Node_;
  242. }
  243. TNode& TNode::operator=(fy_node* node) {
  244. Node_.reset(node, fy_node_free);
  245. return *this;
  246. }
  247. TNode::TNode(fy_node* node)
  248. : Node_(node, fy_node_free)
  249. {}
  250. TNodeRef TNodePairRef::Key() const {
  251. ENSURE_NODE_NOT_EMPTY(Pair_);
  252. return TNodeRef(fy_node_pair_key(Pair_));
  253. }
  254. int TNodePairRef::Index(const TNodeRef& node) const {
  255. ENSURE_NODE_NOT_EMPTY(node);
  256. ENSURE_NODE_NOT_EMPTY(Pair_);
  257. return fy_node_mapping_get_pair_index(node.Node_, Pair_);
  258. }
  259. void TNodePairRef::SetKey(const TNodeRef& node) {
  260. ENSURE_NODE_NOT_EMPTY(Pair_);
  261. ENSURE_NODE_NOT_EMPTY(node);
  262. NDetail::RethrowOnError(fy_node_pair_set_key(Pair_, node.Node_), Pair_);
  263. }
  264. TNodeRef TNodePairRef::Value() const {
  265. ENSURE_NODE_NOT_EMPTY(Pair_);
  266. return TNodeRef(fy_node_pair_value(Pair_));
  267. }
  268. void TNodePairRef::SetValue(const TNodeRef& node) {
  269. ENSURE_NODE_NOT_EMPTY(Pair_);
  270. ENSURE_NODE_NOT_EMPTY(node);
  271. NDetail::RethrowOnError(fy_node_pair_set_value(Pair_, node.Node_), Pair_);
  272. }
  273. TMappingIterator::TMappingIterator(const TNodeRef& node, bool end)
  274. : Node_(node)
  275. {
  276. if (!end) {
  277. NodePair_ = TNodePairRef(fy_node_mapping_iterate(Node_.Node_, reinterpret_cast<void**>(&NodePair_.Pair_)));
  278. }
  279. }
  280. TMappingIterator& TMappingIterator::operator++() {
  281. NodePair_ = TNodePairRef(fy_node_mapping_iterate(Node_.Node_, reinterpret_cast<void**>(&NodePair_.Pair_)));
  282. return *this;
  283. }
  284. TReverseMappingIterator::TReverseMappingIterator(const TNodeRef& node, bool end)
  285. : Node_(node)
  286. {
  287. if (!end) {
  288. NodePair_ = TNodePairRef(fy_node_mapping_reverse_iterate(Node_.Node_, reinterpret_cast<void**>(&NodePair_.Pair_)));
  289. }
  290. }
  291. TReverseMappingIterator& TReverseMappingIterator::operator++() {
  292. NodePair_ = TNodePairRef(fy_node_mapping_reverse_iterate(Node_.Node_, reinterpret_cast<void**>(&NodePair_.Pair_)));
  293. return *this;
  294. }
  295. size_t TMapping::size() const {
  296. ENSURE_NODE_NOT_EMPTY(Node_);
  297. return fy_node_mapping_item_count(Node_);
  298. }
  299. size_t TMapping::empty() const {
  300. ENSURE_NODE_NOT_EMPTY(Node_);
  301. return fy_node_mapping_is_empty(Node_);
  302. }
  303. TNodePairRef TMapping::at(int index) const {
  304. ENSURE_NODE_NOT_EMPTY(Node_);
  305. auto res = fy_node_mapping_get_by_index(Node_, index);
  306. Y_ENSURE_EX(res, ({
  307. TStringStream ss;
  308. ss << "No such child: " << Path() << "/" << index;
  309. TFyamlEx(ss.Str());
  310. }));
  311. return TNodePairRef(res);
  312. }
  313. TNodePairRef TMapping::operator[](int index) const {
  314. ENSURE_NODE_NOT_EMPTY(Node_);
  315. return TNodePairRef(fy_node_mapping_get_by_index(Node_, index));
  316. }
  317. TNodeRef TMapping::at(const TString& index) const {
  318. ENSURE_NODE_NOT_EMPTY(Node_);
  319. auto res = fy_node_mapping_lookup_by_string(Node_, index.data(), index.size());
  320. Y_ENSURE_EX(res, ({
  321. TStringStream ss;
  322. ss << "No such child: " << Path() << "/" << index;
  323. TFyamlEx(ss.Str());
  324. }));
  325. return TNodeRef(res);
  326. }
  327. TNodePairRef TMapping::pair_at(const TString& index) const {
  328. ENSURE_NODE_NOT_EMPTY(Node_);
  329. auto res = fy_node_mapping_lookup_pair_by_string(Node_, index.data(), index.size());
  330. Y_ENSURE_EX(res, ({
  331. TStringStream ss;
  332. ss << "No such child: " << Path() << "/" << index;
  333. TFyamlEx(ss.Str());
  334. }));
  335. return TNodePairRef(res);
  336. }
  337. TNodePairRef TMapping::pair_at_opt(const TString& index) const {
  338. ENSURE_NODE_NOT_EMPTY(Node_);
  339. return TNodePairRef(fy_node_mapping_lookup_pair_by_string(Node_, index.data(), index.size()));
  340. }
  341. TNodeRef TMapping::operator[](const TString& index) const {
  342. ENSURE_NODE_NOT_EMPTY(Node_);
  343. return TNodeRef(fy_node_mapping_lookup_by_string(Node_, index.data(), index.size()));
  344. }
  345. TNodeRef TMapping::operator[](const char* str) const {
  346. ENSURE_NODE_NOT_EMPTY(Node_);
  347. TString index(str);
  348. return TNodeRef(fy_node_mapping_lookup_by_string(Node_, index.data(), index.size()));
  349. }
  350. void TMapping::Append(const TNodeRef& key, const TNodeRef& value) {
  351. ENSURE_NODE_NOT_EMPTY(Node_);
  352. ENSURE_NODE_NOT_EMPTY(key);
  353. ENSURE_NODE_NOT_EMPTY(value);
  354. NDetail::RethrowOnError(fy_node_mapping_append(Node_, key.Node_, value.Node_), Node_);
  355. }
  356. void TMapping::Prepend(const TNodeRef& key, const TNodeRef& value) {
  357. ENSURE_NODE_NOT_EMPTY(Node_);
  358. ENSURE_NODE_NOT_EMPTY(key);
  359. ENSURE_NODE_NOT_EMPTY(value);
  360. NDetail::RethrowOnError(fy_node_mapping_prepend(Node_, key.Node_, value.Node_), Node_);
  361. }
  362. void TMapping::Remove(const TNodePairRef& toRemove) {
  363. ENSURE_NODE_NOT_EMPTY(Node_);
  364. ENSURE_NODE_NOT_EMPTY(toRemove);
  365. NDetail::RethrowOnError(fy_node_mapping_remove(Node_, toRemove.Pair_), Node_);
  366. fy_node_free(fy_node_pair_key(toRemove.Pair_));
  367. fy_node_free(fy_node_pair_value(toRemove.Pair_));
  368. free(toRemove.Pair_);
  369. }
  370. bool TMapping::Has(TString key) const {
  371. return fy_node_mapping_lookup_by_string(Node_, key.data(), key.size()) != nullptr;
  372. }
  373. TMappingIterator TMapping::Remove(const TMappingIterator& toRemove) {
  374. ENSURE_NODE_NOT_EMPTY(Node_);
  375. Y_VERIFY_DEBUG(Node_ == toRemove.Node_);
  376. TMappingIterator ret = toRemove;
  377. ++ret;
  378. fy_node_mapping_remove(Node_, toRemove.NodePair_.Pair_);
  379. return ret;
  380. }
  381. void TMapping::Remove(const TNodeRef& key) {
  382. ENSURE_NODE_NOT_EMPTY(Node_);
  383. fy_node_free(fy_node_mapping_remove_by_key(Node_, key.Node_));
  384. }
  385. TSequenceIterator::TSequenceIterator(const TNodeRef& node, bool end)
  386. : Node_(node)
  387. {
  388. if (!end) {
  389. IterNode_ = TNodeRef(fy_node_sequence_iterate(Node_.Node_, &Iter_));
  390. }
  391. }
  392. TSequenceIterator& TSequenceIterator::operator++() {
  393. IterNode_ = TNodeRef(fy_node_sequence_iterate(Node_.Node_, &Iter_));
  394. return *this;
  395. }
  396. void TSequenceIterator::InsertBefore(const TNodeRef& node) {
  397. ENSURE_NODE_NOT_EMPTY(Node_);
  398. ENSURE_NODE_NOT_EMPTY(IterNode_);
  399. ENSURE_NODE_NOT_EMPTY(node);
  400. NDetail::RethrowOnError(fy_node_sequence_insert_before(Node_.Node_, IterNode_.Node_, node.Node_), Node_.Node_);
  401. }
  402. void TSequenceIterator::InsertAfter(const TNodeRef& node) {
  403. ENSURE_NODE_NOT_EMPTY(Node_);
  404. ENSURE_NODE_NOT_EMPTY(IterNode_);
  405. ENSURE_NODE_NOT_EMPTY(node);
  406. NDetail::RethrowOnError(fy_node_sequence_insert_after(Node_.Node_, IterNode_.Node_, node.Node_), Node_.Node_);
  407. }
  408. TReverseSequenceIterator::TReverseSequenceIterator(const TNodeRef& node, bool end)
  409. : Node_(node)
  410. {
  411. if (!end) {
  412. IterNode_ = TNodeRef(fy_node_sequence_reverse_iterate(Node_.Node_, &Iter_));
  413. }
  414. }
  415. TReverseSequenceIterator& TReverseSequenceIterator::operator++() {
  416. IterNode_ = TNodeRef(fy_node_sequence_reverse_iterate(Node_.Node_, &Iter_));
  417. return *this;
  418. }
  419. void TReverseSequenceIterator::InsertBefore(const TNodeRef& node) {
  420. ENSURE_NODE_NOT_EMPTY(Node_);
  421. ENSURE_NODE_NOT_EMPTY(IterNode_);
  422. ENSURE_NODE_NOT_EMPTY(node);
  423. NDetail::RethrowOnError(fy_node_sequence_insert_after(Node_.Node_, IterNode_.Node_, node.Node_), Node_.Node_);
  424. }
  425. void TReverseSequenceIterator::InsertAfter(const TNodeRef& node) {
  426. ENSURE_NODE_NOT_EMPTY(Node_);
  427. ENSURE_NODE_NOT_EMPTY(IterNode_);
  428. ENSURE_NODE_NOT_EMPTY(node);
  429. NDetail::RethrowOnError(fy_node_sequence_insert_before(Node_.Node_, IterNode_.Node_, node.Node_), Node_.Node_);
  430. }
  431. size_t TSequence::size() const {
  432. ENSURE_NODE_NOT_EMPTY(Node_);
  433. return fy_node_sequence_item_count(Node_);
  434. }
  435. size_t TSequence::empty() const {
  436. ENSURE_NODE_NOT_EMPTY(Node_);
  437. return fy_node_sequence_is_empty(Node_);
  438. }
  439. TNodeRef TSequence::at(int index) const {
  440. ENSURE_NODE_NOT_EMPTY(Node_);
  441. auto res = fy_node_sequence_get_by_index(Node_, index);
  442. Y_ENSURE_EX(res, ({
  443. TStringStream ss;
  444. ss << "No such index: " << Path() << "/" << index;
  445. TFyamlEx(ss.Str());
  446. }));
  447. return TNodeRef(res);
  448. }
  449. TNodeRef TSequence::operator[](int index) const {
  450. ENSURE_NODE_NOT_EMPTY(Node_);
  451. return TNodeRef(fy_node_sequence_get_by_index(Node_, index));
  452. }
  453. void TSequence::Append(const TNodeRef& node) {
  454. ENSURE_NODE_NOT_EMPTY(Node_);
  455. ENSURE_NODE_NOT_EMPTY(node);
  456. NDetail::RethrowOnError(fy_node_sequence_append(Node_, node.Node_), Node_);
  457. }
  458. void TSequence::Prepend(const TNodeRef& node) {
  459. ENSURE_NODE_NOT_EMPTY(Node_);
  460. ENSURE_NODE_NOT_EMPTY(node);
  461. NDetail::RethrowOnError(fy_node_sequence_prepend(Node_, node.Node_), Node_);
  462. }
  463. void TSequence::InsertBefore(const TNodeRef& mark, const TNodeRef& node) {
  464. ENSURE_NODE_NOT_EMPTY(Node_);
  465. ENSURE_NODE_NOT_EMPTY(mark);
  466. ENSURE_NODE_NOT_EMPTY(node);
  467. NDetail::RethrowOnError(fy_node_sequence_insert_before(Node_, mark.Node_, node.Node_), Node_);
  468. }
  469. void TSequence::InsertAfter(const TNodeRef& mark, const TNodeRef& node) {
  470. ENSURE_NODE_NOT_EMPTY(Node_);
  471. ENSURE_NODE_NOT_EMPTY(mark);
  472. ENSURE_NODE_NOT_EMPTY(node);
  473. NDetail::RethrowOnError(fy_node_sequence_insert_after(Node_, mark.Node_, node.Node_), Node_);
  474. }
  475. TNode TSequence::Remove(const TNodeRef& toRemove) {
  476. ENSURE_NODE_NOT_EMPTY(Node_);
  477. ENSURE_NODE_NOT_EMPTY(toRemove.Node_);
  478. return TNode(fy_node_sequence_remove(Node_, toRemove.Node_));
  479. }
  480. TSequenceIterator TSequence::Remove(const TSequenceIterator& toRemove) {
  481. ENSURE_NODE_NOT_EMPTY(Node_);
  482. Y_VERIFY_DEBUG(Node_ == toRemove.Node_);
  483. ENSURE_NODE_NOT_EMPTY(toRemove.IterNode_);
  484. TSequenceIterator ret = toRemove;
  485. ++ret;
  486. fy_node_sequence_remove(Node_, toRemove.IterNode_.Node_);
  487. fy_node_free(toRemove.IterNode_.Node_); // TODO add extract
  488. return ret;
  489. }
  490. TReverseSequenceIterator TSequence::Remove(const TReverseSequenceIterator& toRemove) {
  491. ENSURE_NODE_NOT_EMPTY(Node_);
  492. Y_VERIFY_DEBUG(Node_ == toRemove.Node_);
  493. ENSURE_NODE_NOT_EMPTY(toRemove.IterNode_);
  494. TReverseSequenceIterator ret = toRemove;
  495. ++ret;
  496. fy_node_sequence_remove(Node_, toRemove.IterNode_.Node_);
  497. fy_node_free(toRemove.IterNode_.Node_); // TODO add extract
  498. return ret;
  499. }
  500. TDocumentNodeIterator::TDocumentNodeIterator(TNodeRef&& node)
  501. : Node_(node)
  502. {
  503. if (node) {
  504. Iterator_ = {fy_document_iterator_create(), fy_document_iterator_destroy};
  505. fy_document_iterator_node_start(Iterator_.get(), node.Node_);
  506. }
  507. }
  508. TDocumentNodeIterator& TDocumentNodeIterator::operator++() {
  509. Node_ = fy_document_iterator_node_next(Iterator_.get());
  510. return *this;
  511. }
  512. TDocument::TDocument(TString str, fy_document* doc, fy_diag* diag)
  513. : Document_(doc, fy_document_destroy)
  514. , Diag_(diag, fy_diag_destroy)
  515. {
  516. auto* userdata = new THashSet<TSimpleSharedPtr<TString>, TStringPtrHashT>({MakeSimpleShared<TString>(std::move(str))});
  517. fy_document_set_userdata(doc, userdata);
  518. fy_document_register_on_destroy(doc, &DestroyDocumentStrings);
  519. RegisterUserDataCleanup();
  520. }
  521. TDocument::TDocument(fy_document* doc, fy_diag* diag)
  522. : Document_(doc, fy_document_destroy)
  523. , Diag_(diag, fy_diag_destroy)
  524. {
  525. RegisterUserDataCleanup();
  526. }
  527. TDocument TDocument::Parse(TString str) {
  528. const char* cstr = str.empty() ? zstr : str.cbegin();
  529. fy_diag_cfg dcfg;
  530. fy_diag_cfg_default(&dcfg);
  531. std::unique_ptr<fy_diag, void(*)(fy_diag*)> diag(fy_diag_create(&dcfg), fy_diag_destroy);
  532. fy_diag_set_collect_errors(diag.get(), true);
  533. fy_parse_cfg cfg{
  534. "",
  535. // FYPCF_PARSE_COMMENTS,
  536. FYPCF_QUIET,
  537. nullptr,
  538. diag.get()
  539. };
  540. fy_document* doc = fy_document_build_from_string(&cfg, cstr, FY_NT);
  541. if (!doc) {
  542. NDetail::ThrowAllExceptionsIfAny(diag.get());
  543. }
  544. return TDocument(std::move(str), doc, diag.release());
  545. }
  546. TDocument TDocument::Clone() const {
  547. ENSURE_DOCUMENT_NOT_EMPTY(Document_);
  548. fy_document* doc = fy_document_clone(Document_.get());
  549. fy_document_set_userdata(
  550. doc,
  551. new THashSet<TSimpleSharedPtr<TString>, TStringPtrHashT>(
  552. *reinterpret_cast<THashSet<TSimpleSharedPtr<TString>, TStringPtrHashT>*>(fy_document_get_userdata(Document_.get()))
  553. )
  554. );
  555. fy_document_register_on_destroy(doc, &DestroyDocumentStrings);
  556. return TDocument(doc, fy_document_get_diag(doc));
  557. }
  558. void TDocument::InsertAt(const char* path, const TNodeRef& node) {
  559. ENSURE_DOCUMENT_NOT_EMPTY(Document_);
  560. NDetail::RethrowOnError(fy_document_insert_at(Document_.get(), path, FY_NT, node.Node_), Diag_.get());
  561. }
  562. TNodeRef TDocument::Buildf(const char* content) {
  563. ENSURE_DOCUMENT_NOT_EMPTY(Document_);
  564. return TNodeRef(fy_node_build_from_string(Document_.get(), content, strlen(content)));
  565. }
  566. void TDocument::Resolve() {
  567. ENSURE_DOCUMENT_NOT_EMPTY(Document_);
  568. if (fy_document_resolve(Document_.get()) != 0) {
  569. NDetail::ThrowAllExceptionsIfAny(Diag_.get());
  570. }
  571. }
  572. bool TDocument::HasDirectives() {
  573. ENSURE_DOCUMENT_NOT_EMPTY(Document_);
  574. return fy_document_has_directives(Document_.get());
  575. }
  576. bool TDocument::HasExplicitDocumentStart() {
  577. ENSURE_DOCUMENT_NOT_EMPTY(Document_);
  578. return fy_document_has_explicit_document_start(Document_.get());
  579. }
  580. bool TDocument::HasExplicitDocumentEnd() {
  581. ENSURE_DOCUMENT_NOT_EMPTY(Document_);
  582. return fy_document_has_explicit_document_end(Document_.get());
  583. }
  584. void TDocument::SetParent(const TDocument& doc) {
  585. ENSURE_DOCUMENT_NOT_EMPTY(Document_);
  586. ENSURE_DOCUMENT_NOT_EMPTY(doc.Document_);
  587. NDetail::RethrowOnError(fy_document_set_parent(doc.Document_.get(), Document_.release()), Diag_.get());
  588. }
  589. TNodeRef TDocument::Root() {
  590. ENSURE_DOCUMENT_NOT_EMPTY(Document_);
  591. return TNodeRef(fy_document_root(Document_.get()));
  592. }
  593. void TDocument::SetRoot(const TNodeRef& node) {
  594. ENSURE_DOCUMENT_NOT_EMPTY(Document_);
  595. ENSURE_NODE_NOT_EMPTY(node.Node_);
  596. NDetail::RethrowOnError(fy_document_set_root(Document_.get(), node.Node_), Diag_.get());
  597. }
  598. TNodeRef TDocument::CreateAlias(const TString& name) {
  599. ENSURE_DOCUMENT_NOT_EMPTY(Document_);
  600. return TNodeRef(fy_node_create_alias_copy(Document_.get(), name.c_str(), name.length()));
  601. }
  602. std::unique_ptr<char, void(*)(char*)> TDocument::EmitToCharArray() const {
  603. std::unique_ptr<char, void(*)(char*)> res(
  604. fy_emit_document_to_string(
  605. Document_.get(),
  606. (fy_emitter_cfg_flags)(FYECF_DEFAULT | FYECF_MODE_PRETTY | FYECF_OUTPUT_COMMENTS)), &NDetail::FreeChar);
  607. return res;
  608. }
  609. bool TDocument::RegisterUserDataCleanup() {
  610. ENSURE_DOCUMENT_NOT_EMPTY(Document_);
  611. return fy_document_register_meta(Document_.get(), &DestroyUserData, nullptr) == 0;
  612. }
  613. void TDocument::UnregisterUserDataCleanup() {
  614. ENSURE_DOCUMENT_NOT_EMPTY(Document_);
  615. fy_document_unregister_meta(Document_.get());
  616. }
  617. TMark TDocument::BeginMark() const {
  618. ENSURE_DOCUMENT_NOT_EMPTY(Document_);
  619. auto* fyds = fy_document_get_document_state(Document_.get());
  620. auto* mark = fy_document_state_start_mark(fyds);
  621. return TMark{
  622. mark->input_pos,
  623. mark->line,
  624. mark->column,
  625. };
  626. }
  627. TMark TDocument::EndMark() const {
  628. ENSURE_DOCUMENT_NOT_EMPTY(Document_);
  629. auto* fyds = fy_document_get_document_state(Document_.get());
  630. auto* mark = fy_document_state_end_mark(fyds);
  631. return TMark{
  632. mark->input_pos,
  633. mark->line,
  634. mark->column,
  635. };
  636. }
  637. std::unique_ptr<char, void(*)(char*)> TJsonEmitter::EmitToCharArray() const {
  638. std::unique_ptr<char, void(*)(char*)> res(
  639. fy_emit_node_to_string(
  640. Node_.Node_,
  641. (fy_emitter_cfg_flags)(FYECF_DEFAULT | FYECF_SORT_KEYS | FYECF_MODE_JSON_TP)), &NDetail::FreeChar);
  642. return res;
  643. }
  644. TParser::TParser(TString rawStream, fy_parser* parser, fy_diag* diag)
  645. : RawDocumentStream_(std::move(rawStream))
  646. , Parser_(parser, fy_parser_destroy)
  647. , Diag_(diag, fy_diag_destroy)
  648. {}
  649. TParser TParser::Create(TString str)
  650. {
  651. const char* stream = str.empty() ? zstr : str.cbegin();
  652. fy_diag_cfg dcfg;
  653. fy_diag_cfg_default(&dcfg);
  654. std::unique_ptr<fy_diag, void(*)(fy_diag*)> diag(fy_diag_create(&dcfg), fy_diag_destroy);
  655. fy_diag_set_collect_errors(diag.get(), true);
  656. fy_parse_cfg cfg{
  657. "",
  658. // FYPCF_PARSE_COMMENTS,
  659. FYPCF_QUIET,
  660. nullptr,
  661. diag.get()
  662. };
  663. auto* parser = fy_parser_create(&cfg);
  664. if (!parser) {
  665. NDetail::ThrowAllExceptionsIfAny(diag.get());
  666. }
  667. fy_parser_set_string(parser, stream, -1);
  668. return TParser(std::move(str), parser, diag.release());
  669. }
  670. std::optional<TDocument> TParser::NextDocument() {
  671. auto* doc = fy_parse_load_document(Parser_.get());
  672. if (!doc) {
  673. return std::nullopt;
  674. }
  675. return TDocument(RawDocumentStream_, doc, fy_document_get_diag(doc));
  676. }
  677. namespace NDetail {
  678. fy_node* TNodeOpsBase::CreateReference(fy_node* node) const {
  679. ENSURE_NODE_NOT_EMPTY(node);
  680. return fy_node_create_reference(node);
  681. }
  682. fy_node* TNodeOpsBase::Copy(fy_node* node) const {
  683. ENSURE_NODE_NOT_EMPTY(node);
  684. return fy_node_copy(fy_node_document(node), node);
  685. }
  686. fy_node* TNodeOpsBase::Copy(fy_node* node, fy_document* to) const {
  687. ENSURE_NODE_NOT_EMPTY(node);
  688. auto* fromDoc = fy_node_document(node);
  689. auto& fromUserdata = *reinterpret_cast<THashSet<TSimpleSharedPtr<TString>, TStringPtrHashT>*>(fy_document_get_userdata(fromDoc));
  690. auto& toUserdata = *reinterpret_cast<THashSet<TSimpleSharedPtr<TString>, TStringPtrHashT>*>(fy_document_get_userdata(to));
  691. toUserdata.insert(fromUserdata.begin(), fromUserdata.end());
  692. return fy_node_copy(to, node);
  693. }
  694. TString TNodeOpsBase::Path(fy_node* node) const {
  695. ENSURE_NODE_NOT_EMPTY(node);
  696. char* path = fy_node_get_path(node);
  697. if (path) {
  698. TString str(path);
  699. free(path);
  700. return str;
  701. }
  702. return {};
  703. }
  704. ENodeType TNodeOpsBase::Type(fy_node* node) const {
  705. ENSURE_NODE_NOT_EMPTY(node);
  706. return static_cast<ENodeType>(fy_node_get_type(node));
  707. }
  708. bool TNodeOpsBase::IsAlias(fy_node* node) const {
  709. ENSURE_NODE_NOT_EMPTY(node);
  710. return fy_node_is_alias(node);
  711. }
  712. fy_node* TNodeOpsBase::ResolveAlias(fy_node* node) const {
  713. ENSURE_NODE_NOT_EMPTY(node);
  714. Y_VERIFY_DEBUG(IsAlias(node));
  715. return fy_node_resolve_alias(node);
  716. }
  717. TString TNodeOpsBase::Scalar(fy_node* node) const {
  718. ENSURE_NODE_NOT_EMPTY(node);
  719. Y_ENSURE_EX(fy_node_is_scalar(node), TFyamlEx() << "Node is not Scalar: " << Path(node));
  720. size_t size;
  721. const char* text = fy_node_get_scalar(node, &size);
  722. return TString(text, size);
  723. }
  724. TMark TNodeOpsBase::BeginMark(fy_node* node) const {
  725. ENSURE_NODE_NOT_EMPTY(node);
  726. std::unique_ptr<fy_document_iterator, void(*)(fy_document_iterator*)> it(
  727. fy_document_iterator_create(),
  728. &fy_document_iterator_destroy);
  729. fy_document_iterator_node_start(it.get(), node);
  730. auto deleter = [&](fy_event* fye){ fy_document_iterator_event_free(it.get(), fye); };
  731. std::unique_ptr<fy_event, decltype(deleter)> ev(
  732. fy_document_iterator_body_next(it.get()),
  733. deleter);
  734. auto* mark = fy_event_start_mark(ev.get());
  735. if (!mark) {
  736. ythrow yexception() << "can't get begin mark for a node";
  737. }
  738. return TMark{
  739. mark->input_pos,
  740. mark->line,
  741. mark->column,
  742. };
  743. }
  744. namespace {
  745. fy_event_type GetOpenEventType(ENodeType type) {
  746. switch(type) {
  747. case ENodeType::Mapping:
  748. return FYET_MAPPING_START;
  749. case ENodeType::Sequence:
  750. return FYET_SEQUENCE_START;
  751. default:
  752. Y_FAIL("Not a brackets type");
  753. }
  754. }
  755. fy_event_type GetCloseEventType(ENodeType type) {
  756. switch(type) {
  757. case ENodeType::Mapping:
  758. return FYET_MAPPING_END;
  759. case ENodeType::Sequence:
  760. return FYET_SEQUENCE_END;
  761. default:
  762. Y_FAIL("Not a brackets type");
  763. }
  764. }
  765. } // anonymous namespace
  766. TMark TNodeOpsBase::EndMark(fy_node* node) const {
  767. ENSURE_NODE_NOT_EMPTY(node);
  768. std::unique_ptr<fy_document_iterator, void(*)(fy_document_iterator*)> it(
  769. fy_document_iterator_create(),
  770. &fy_document_iterator_destroy);
  771. fy_document_iterator_node_start(it.get(), node);
  772. auto deleter = [&](fy_event* fye){ fy_document_iterator_event_free(it.get(), fye); };
  773. std::unique_ptr<fy_event, decltype(deleter)> prevEv(
  774. nullptr,
  775. deleter);
  776. std::unique_ptr<fy_event, decltype(deleter)> ev(
  777. fy_document_iterator_body_next(it.get()),
  778. deleter);
  779. if (IsComplexType(Type(node))) {
  780. int openBrackets = 0;
  781. if (ev->type == GetOpenEventType(Type(node))) {
  782. ++openBrackets;
  783. }
  784. if (ev->type == GetCloseEventType(Type(node))) {
  785. --openBrackets;
  786. }
  787. while (ev->type != GetCloseEventType(Type(node)) || openBrackets != 0) {
  788. std::unique_ptr<fy_event, decltype(deleter)> cur(
  789. fy_document_iterator_body_next(it.get()),
  790. deleter);
  791. if (cur == nullptr) {
  792. break;
  793. }
  794. if (cur->type == GetOpenEventType(Type(node))) {
  795. ++openBrackets;
  796. }
  797. if (cur->type == GetCloseEventType(Type(node))) {
  798. --openBrackets;
  799. }
  800. if (fy_event_get_node_style(cur.get()) != FYNS_BLOCK) {
  801. prevEv.reset(ev.release());
  802. ev.reset(cur.release());
  803. }
  804. }
  805. }
  806. auto* mark = fy_event_end_mark(ev.get());
  807. if (!mark && prevEv) {
  808. mark = fy_event_end_mark(prevEv.get());
  809. }
  810. if (!mark) {
  811. ythrow yexception() << "can't get end mark for a node";
  812. }
  813. return TMark{
  814. mark->input_pos,
  815. mark->line,
  816. mark->column,
  817. };
  818. }
  819. fy_node* TNodeOpsBase::Map(fy_node* node) const {
  820. ENSURE_NODE_NOT_EMPTY(node);
  821. Y_ENSURE_EX(fy_node_is_mapping(node), TFyamlEx() << "Node is not Mapping: " << Path(node));
  822. return node;
  823. }
  824. fy_node* TNodeOpsBase::Sequence(fy_node* node) const {
  825. ENSURE_NODE_NOT_EMPTY(node);
  826. Y_ENSURE_EX(fy_node_is_sequence(node), TFyamlEx() << "Node is not Sequence: " << Path(node));
  827. return node;
  828. }
  829. void TNodeOpsBase::Insert(fy_node* thisNode, fy_node* node) {
  830. ENSURE_NODE_NOT_EMPTY(node);
  831. RethrowOnError(fy_node_insert(thisNode, node), thisNode);
  832. }
  833. std::optional<TString> TNodeOpsBase::Tag(fy_node* node) const {
  834. ENSURE_NODE_NOT_EMPTY(node);
  835. size_t len = 0;
  836. const char* tag = fy_node_get_tag(node, &len);
  837. if (tag) {
  838. return TString(tag, len);
  839. }
  840. return std::nullopt;
  841. }
  842. void TNodeOpsBase::SetTag(fy_node* node, const TString& tag) {
  843. ENSURE_NODE_NOT_EMPTY(node);
  844. auto* str = new TString(std::move(tag));
  845. auto* data = new TUserDataHolder(UserData(node), str);
  846. SetUserData(node, data);
  847. RethrowOnError(fy_node_set_tag(node, str->c_str(), str->length()), node);
  848. }
  849. bool TNodeOpsBase::RemoveTag(fy_node* node) {
  850. ENSURE_NODE_NOT_EMPTY(node);
  851. bool ret = fy_node_remove_tag(node);
  852. ClearUserData(node);
  853. return ret;
  854. }
  855. bool TNodeOpsBase::HasAnchor(fy_node* node) const {
  856. ENSURE_NODE_NOT_EMPTY(node);
  857. return fy_node_get_anchor(node) != nullptr;
  858. }
  859. void TNodeOpsBase::SetAnchor(fy_node* node, const TString& anchor) {
  860. auto* str = new TString(anchor);
  861. auto* data = new TUserDataHolder(UserData(node), str);
  862. SetUserData(node, data);
  863. RethrowOnError(fy_node_set_anchor(node, str->c_str(), str->length()), node);
  864. }
  865. bool TNodeOpsBase::DeepEqual(fy_node* thisNode, fy_node* other) {
  866. ENSURE_NODE_NOT_EMPTY(thisNode);
  867. ENSURE_NODE_NOT_EMPTY(other);
  868. return fy_node_compare(thisNode, other);
  869. }
  870. std::unique_ptr<char, void(*)(char*)> TNodeOpsBase::EmitToCharArray(fy_node* node) const {
  871. std::unique_ptr<char, void(*)(char*)> res(
  872. fy_emit_node_to_string(
  873. node,
  874. (fy_emitter_cfg_flags)(FYECF_DEFAULT)), &FreeChar);
  875. return res;
  876. }
  877. void TNodeOpsBase::SetStyle(fy_node* node, ENodeStyle style) {
  878. ENSURE_NODE_NOT_EMPTY(node);
  879. fy_node_set_style(node, (enum fy_node_style)style);
  880. }
  881. ENodeStyle TNodeOpsBase::Style(fy_node* node) const {
  882. ENSURE_NODE_NOT_EMPTY(node);
  883. return (ENodeStyle)fy_node_get_style(node);
  884. }
  885. void TNodeOpsBase::SetUserData(fy_node* node, IBasicUserData* data) {
  886. ENSURE_NODE_NOT_EMPTY(node);
  887. fy_node_set_meta(node, data);
  888. }
  889. IBasicUserData* TNodeOpsBase::UserData(fy_node* node) const {
  890. ENSURE_NODE_NOT_EMPTY(node);
  891. return reinterpret_cast<IBasicUserData* >(fy_node_get_meta(node));
  892. }
  893. void TNodeOpsBase::ClearUserData(fy_node* node) {
  894. ENSURE_NODE_NOT_EMPTY(node);
  895. fy_node_clear_meta(node);
  896. }
  897. void ThrowAllExceptionsIfAny(fy_diag* diag) {
  898. void* iter = nullptr;
  899. fy_diag_error* err = fy_diag_errors_iterate(diag, &iter);
  900. if (err != nullptr) {
  901. TStringStream ss;
  902. ss << err->line << ":" << err->column << " " << err->msg;
  903. TFyamlEx ex(ss.Str());
  904. while ((err = fy_diag_errors_iterate(diag, &iter)) != nullptr) {
  905. TStringStream ss;
  906. ss << err->line << ":" << err->column << " " << err->msg;
  907. ex.AddError(ss.Str());
  908. }
  909. ythrow ex;
  910. }
  911. }
  912. void RethrowError(fy_diag* diag) {
  913. void *iter = nullptr;
  914. fy_diag_error* err;
  915. TStringStream ss;
  916. while ((err = fy_diag_errors_iterate(diag, &iter)) != nullptr) {
  917. ss << err->line << ":" << err->column << " " << err->msg << "\n";
  918. }
  919. ythrow TFyamlEx(ss.Str());
  920. }
  921. void RethrowOnError(bool isError, fy_node* node) {
  922. if (!isError) {
  923. return;
  924. }
  925. std::unique_ptr<fy_diag, void(*)(fy_diag*)> diag(fy_document_get_diag(fy_node_document(node)), fy_diag_unref);
  926. RethrowError(diag.get());
  927. }
  928. void RethrowOnError(bool isError, fy_node_pair* pair) {
  929. if (!isError) {
  930. return;
  931. }
  932. std::unique_ptr<fy_diag, void(*)(fy_diag*)> diag(fy_document_get_diag(fy_node_document(fy_node_pair_key(pair))), fy_diag_unref);
  933. RethrowError(diag.get());
  934. }
  935. void RethrowOnError(bool isError, fy_diag* diag) {
  936. if (!isError) {
  937. return;
  938. }
  939. RethrowError(diag);
  940. }
  941. void FreeChar(char* mem) {
  942. free(mem);
  943. }
  944. bool IsComplexType(ENodeType type) {
  945. return type == ENodeType::Mapping || type == ENodeType::Sequence;
  946. }
  947. } // namespace NDetail
  948. } // namespace NFyaml
  949. template <>
  950. void Out<NFyaml::TDocument>(IOutputStream& out, const NFyaml::TDocument& value) {
  951. out << value.EmitToCharArray().get();
  952. }
  953. template <>
  954. void Out<NFyaml::TNodeRef>(IOutputStream& out, const NFyaml::TNodeRef& value) {
  955. out << value.EmitToCharArray().get();
  956. }
  957. template <>
  958. void Out<NFyaml::TJsonEmitter>(IOutputStream& out, const NFyaml::TJsonEmitter& value) {
  959. out << value.EmitToCharArray().get();
  960. }
  961. bool operator==(const fy_node* node1, const NFyaml::NDetail::TNodeOps<NFyaml::TNodeRef>& node2) {
  962. return node2.Node() == node1;
  963. }
  964. bool operator==(const fy_node* node1, const NFyaml::NDetail::TNodeOps<NFyaml::TNode>& node2) {
  965. return node2.Node() == node1;
  966. }