#ifndef VALUE_DETAIL_NODE_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define VALUE_DETAIL_NODE_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #if defined(_MSC_VER) || \ (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \ (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 #pragma once #endif #include "yaml-cpp/dll.h" #include "yaml-cpp/node/ptr.h" #include #include #include #include #include #include namespace YAML { namespace detail { struct iterator_type { enum value { NoneType, Sequence, Map }; }; template struct node_iterator_value : public std::pair { using kv = std::pair; node_iterator_value() : kv(), pNode(nullptr) {} explicit node_iterator_value(V& rhs) : kv(), pNode(&rhs) {} explicit node_iterator_value(V& key, V& value) : kv(&key, &value), pNode(nullptr) {} V& operator*() const { return *pNode; } V& operator->() const { return *pNode; } V* pNode; }; using node_seq = std::vector; using node_map = std::vector>; template struct node_iterator_type { using seq = node_seq::iterator; using map = node_map::iterator; }; template struct node_iterator_type { using seq = node_seq::const_iterator; using map = node_map::const_iterator; }; template class node_iterator_base { private: struct enabler {}; struct proxy { explicit proxy(const node_iterator_value& x) : m_ref(x) {} node_iterator_value* operator->() { return std::addressof(m_ref); } operator node_iterator_value*() { return std::addressof(m_ref); } node_iterator_value m_ref; }; public: using iterator_category = std::forward_iterator_tag; using value_type = node_iterator_value; using difference_type = std::ptrdiff_t; using pointer = node_iterator_value*; using reference = node_iterator_value; using SeqIter = typename node_iterator_type::seq; using MapIter = typename node_iterator_type::map; node_iterator_base() : m_type(iterator_type::NoneType), m_seqIt(), m_mapIt(), m_mapEnd() {} explicit node_iterator_base(SeqIter seqIt) : m_type(iterator_type::Sequence), m_seqIt(seqIt), m_mapIt(), m_mapEnd() {} explicit node_iterator_base(MapIter mapIt, MapIter mapEnd) : m_type(iterator_type::Map), m_seqIt(), m_mapIt(mapIt), m_mapEnd(mapEnd) { m_mapIt = increment_until_defined(m_mapIt); } template node_iterator_base(const node_iterator_base& rhs, typename std::enable_if::value, enabler>::type = enabler()) : m_type(rhs.m_type), m_seqIt(rhs.m_seqIt), m_mapIt(rhs.m_mapIt), m_mapEnd(rhs.m_mapEnd) {} template friend class node_iterator_base; template bool operator==(const node_iterator_base& rhs) const { if (m_type != rhs.m_type) return false; switch (m_type) { case iterator_type::NoneType: return true; case iterator_type::Sequence: return m_seqIt == rhs.m_seqIt; case iterator_type::Map: return m_mapIt == rhs.m_mapIt; } return true; } template bool operator!=(const node_iterator_base& rhs) const { return !(*this == rhs); } node_iterator_base& operator++() { switch (m_type) { case iterator_type::NoneType: break; case iterator_type::Sequence: ++m_seqIt; break; case iterator_type::Map: ++m_mapIt; m_mapIt = increment_until_defined(m_mapIt); break; } return *this; } node_iterator_base operator++(int) { node_iterator_base iterator_pre(*this); ++(*this); return iterator_pre; } value_type operator*() const { switch (m_type) { case iterator_type::NoneType: return value_type(); case iterator_type::Sequence: return value_type(**m_seqIt); case iterator_type::Map: return value_type(*m_mapIt->first, *m_mapIt->second); } return value_type(); } proxy operator->() const { return proxy(**this); } MapIter increment_until_defined(MapIter it) { while (it != m_mapEnd && !is_defined(it)) ++it; return it; } bool is_defined(MapIter it) const { return it->first->is_defined() && it->second->is_defined(); } private: typename iterator_type::value m_type; SeqIter m_seqIt; MapIter m_mapIt, m_mapEnd; }; using node_iterator = node_iterator_base; using const_node_iterator = node_iterator_base; } } #endif // VALUE_DETAIL_NODE_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66