nodeevents.cpp 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. #include "nodeevents.h"
  2. #include "yaml-cpp/eventhandler.h"
  3. #include "yaml-cpp/mark.h"
  4. #include "yaml-cpp/node/detail/node.h"
  5. #include "yaml-cpp/node/detail/node_iterator.h"
  6. #include "yaml-cpp/node/node.h"
  7. #include "yaml-cpp/node/type.h"
  8. namespace YAML {
  9. void NodeEvents::AliasManager::RegisterReference(const detail::node& node) {
  10. m_anchorByIdentity.insert(std::make_pair(node.ref(), _CreateNewAnchor()));
  11. }
  12. anchor_t NodeEvents::AliasManager::LookupAnchor(
  13. const detail::node& node) const {
  14. auto it = m_anchorByIdentity.find(node.ref());
  15. if (it == m_anchorByIdentity.end())
  16. return 0;
  17. return it->second;
  18. }
  19. NodeEvents::NodeEvents(const Node& node)
  20. : m_pMemory(node.m_pMemory), m_root(node.m_pNode), m_refCount{} {
  21. if (m_root)
  22. Setup(*m_root);
  23. }
  24. void NodeEvents::Setup(const detail::node& node) {
  25. int& refCount = m_refCount[node.ref()];
  26. refCount++;
  27. if (refCount > 1)
  28. return;
  29. if (node.type() == NodeType::Sequence) {
  30. for (auto element : node)
  31. Setup(*element);
  32. } else if (node.type() == NodeType::Map) {
  33. for (auto element : node) {
  34. Setup(*element.first);
  35. Setup(*element.second);
  36. }
  37. }
  38. }
  39. void NodeEvents::Emit(EventHandler& handler) {
  40. AliasManager am;
  41. handler.OnDocumentStart(Mark());
  42. if (m_root)
  43. Emit(*m_root, handler, am);
  44. handler.OnDocumentEnd();
  45. }
  46. void NodeEvents::Emit(const detail::node& node, EventHandler& handler,
  47. AliasManager& am) const {
  48. anchor_t anchor = NullAnchor;
  49. if (IsAliased(node)) {
  50. anchor = am.LookupAnchor(node);
  51. if (anchor) {
  52. handler.OnAlias(Mark(), anchor);
  53. return;
  54. }
  55. am.RegisterReference(node);
  56. anchor = am.LookupAnchor(node);
  57. }
  58. switch (node.type()) {
  59. case NodeType::Undefined:
  60. break;
  61. case NodeType::Null:
  62. handler.OnNull(Mark(), anchor);
  63. break;
  64. case NodeType::Scalar:
  65. handler.OnScalar(Mark(), node.tag(), anchor, node.scalar());
  66. break;
  67. case NodeType::Sequence:
  68. handler.OnSequenceStart(Mark(), node.tag(), anchor, node.style());
  69. for (auto element : node)
  70. Emit(*element, handler, am);
  71. handler.OnSequenceEnd();
  72. break;
  73. case NodeType::Map:
  74. handler.OnMapStart(Mark(), node.tag(), anchor, node.style());
  75. for (auto element : node) {
  76. Emit(*element.first, handler, am);
  77. Emit(*element.second, handler, am);
  78. }
  79. handler.OnMapEnd();
  80. break;
  81. }
  82. }
  83. bool NodeEvents::IsAliased(const detail::node& node) const {
  84. auto it = m_refCount.find(node.ref());
  85. return it != m_refCount.end() && it->second > 1;
  86. }
  87. } // namespace YAML