Line data Source code
1 : #ifndef VALUE_DETAIL_NODE_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66 2 : #define VALUE_DETAIL_NODE_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66 3 : 4 : #if defined(_MSC_VER) || \ 5 : (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \ 6 : (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 7 : #pragma once 8 : #endif 9 : 10 : #include "yaml-cpp/dll.h" 11 : #include "yaml-cpp/node/ptr.h" 12 : #include <cstddef> 13 : #include <iterator> 14 : #include <memory> 15 : #include <map> 16 : #include <utility> 17 : #include <vector> 18 : 19 : namespace YAML { 20 : namespace detail { 21 : struct iterator_type { 22 : enum value { NoneType, Sequence, Map }; 23 : }; 24 : 25 : template <typename V> 26 : struct node_iterator_value : public std::pair<V*, V*> { 27 : using kv = std::pair<V*, V*>; 28 : 29 0 : node_iterator_value() : kv(), pNode(nullptr) {} 30 30 : explicit node_iterator_value(V& rhs) : kv(), pNode(&rhs) {} 31 2814 : explicit node_iterator_value(V& key, V& value) : kv(&key, &value), pNode(nullptr) {} 32 : 33 30 : V& operator*() const { return *pNode; } 34 : V& operator->() const { return *pNode; } 35 : 36 : V* pNode; 37 : }; 38 : 39 : using node_seq = std::vector<node *>; 40 : using node_map = std::vector<std::pair<node*, node*>>; 41 : 42 : template <typename V> 43 : struct node_iterator_type { 44 : using seq = node_seq::iterator; 45 : using map = node_map::iterator; 46 : }; 47 : 48 : template <typename V> 49 : struct node_iterator_type<const V> { 50 : using seq = node_seq::const_iterator; 51 : using map = node_map::const_iterator; 52 : }; 53 : 54 : template <typename V> 55 : class node_iterator_base { 56 : private: 57 : struct enabler {}; 58 : 59 : struct proxy { 60 : explicit proxy(const node_iterator_value<V>& x) : m_ref(x) {} 61 : node_iterator_value<V>* operator->() { return std::addressof(m_ref); } 62 : operator node_iterator_value<V>*() { return std::addressof(m_ref); } 63 : 64 : node_iterator_value<V> m_ref; 65 : }; 66 : 67 : public: 68 : using iterator_category = std::forward_iterator_tag; 69 : using value_type = node_iterator_value<V>; 70 : using difference_type = std::ptrdiff_t; 71 : using pointer = node_iterator_value<V>*; 72 : using reference = node_iterator_value<V>; 73 : using SeqIter = typename node_iterator_type<V>::seq; 74 : using MapIter = typename node_iterator_type<V>::map; 75 : 76 12 : node_iterator_base() 77 12 : : m_type(iterator_type::NoneType), m_seqIt(), m_mapIt(), m_mapEnd() {} 78 : explicit node_iterator_base(SeqIter seqIt) 79 : : m_type(iterator_type::Sequence), 80 : m_seqIt(seqIt), 81 : m_mapIt(), 82 : m_mapEnd() {} 83 : explicit node_iterator_base(MapIter mapIt, MapIter mapEnd) 84 : : m_type(iterator_type::Map), 85 : m_seqIt(), 86 : m_mapIt(mapIt), 87 : m_mapEnd(mapEnd) { 88 : m_mapIt = increment_until_defined(m_mapIt); 89 : } 90 : 91 : template <typename W> 92 : node_iterator_base(const node_iterator_base<W>& rhs, 93 : typename std::enable_if<std::is_convertible<W*, V*>::value, 94 : enabler>::type = enabler()) 95 : : m_type(rhs.m_type), 96 : m_seqIt(rhs.m_seqIt), 97 : m_mapIt(rhs.m_mapIt), 98 : m_mapEnd(rhs.m_mapEnd) {} 99 : 100 : template <typename> 101 : friend class node_iterator_base; 102 : 103 : template <typename W> 104 3963 : bool operator==(const node_iterator_base<W>& rhs) const { 105 3963 : if (m_type != rhs.m_type) 106 0 : return false; 107 : 108 3963 : switch (m_type) { 109 6 : case iterator_type::NoneType: 110 6 : return true; 111 140 : case iterator_type::Sequence: 112 140 : return m_seqIt == rhs.m_seqIt; 113 3817 : case iterator_type::Map: 114 3817 : return m_mapIt == rhs.m_mapIt; 115 : } 116 0 : return true; 117 : } 118 : 119 : template <typename W> 120 3963 : bool operator!=(const node_iterator_base<W>& rhs) const { 121 3963 : return !(*this == rhs); 122 : } 123 : 124 2844 : node_iterator_base<V>& operator++() { 125 2844 : switch (m_type) { 126 0 : case iterator_type::NoneType: 127 0 : break; 128 30 : case iterator_type::Sequence: 129 30 : ++m_seqIt; 130 30 : break; 131 2814 : case iterator_type::Map: 132 2814 : ++m_mapIt; 133 2814 : m_mapIt = increment_until_defined(m_mapIt); 134 2814 : break; 135 : } 136 2844 : return *this; 137 : } 138 : 139 : node_iterator_base<V> operator++(int) { 140 : node_iterator_base<V> iterator_pre(*this); 141 : ++(*this); 142 : return iterator_pre; 143 : } 144 : 145 2844 : value_type operator*() const { 146 2844 : switch (m_type) { 147 0 : case iterator_type::NoneType: 148 0 : return value_type(); 149 30 : case iterator_type::Sequence: 150 30 : return value_type(**m_seqIt); 151 2814 : case iterator_type::Map: 152 2814 : return value_type(*m_mapIt->first, *m_mapIt->second); 153 : } 154 0 : return value_type(); 155 : } 156 : 157 : proxy operator->() const { return proxy(**this); } 158 : 159 2814 : MapIter increment_until_defined(MapIter it) { 160 2814 : while (it != m_mapEnd && !is_defined(it)) 161 0 : ++it; 162 2814 : return it; 163 : } 164 : 165 1811 : bool is_defined(MapIter it) const { 166 1811 : return it->first->is_defined() && it->second->is_defined(); 167 : } 168 : 169 : private: 170 : typename iterator_type::value m_type; 171 : 172 : SeqIter m_seqIt; 173 : MapIter m_mapIt, m_mapEnd; 174 : }; 175 : 176 : using node_iterator = node_iterator_base<node>; 177 : using const_node_iterator = node_iterator_base<const node>; 178 : } 179 : } 180 : 181 : #endif // VALUE_DETAIL_NODE_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66