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   typedef std::pair<V*, V*> kv;
28 
node_iterator_valuenode_iterator_value29   node_iterator_value() : kv(), pNode(0) {}
node_iterator_valuenode_iterator_value30   explicit node_iterator_value(V& rhs) : kv(), pNode(&rhs) {}
node_iterator_valuenode_iterator_value31   explicit node_iterator_value(V& key, V& value) : kv(&key, &value), pNode(0) {}
32 
33   V& operator*() const { return *pNode; }
34   V& operator->() const { return *pNode; }
35 
36   V* pNode;
37 };
38 
39 typedef std::vector<node*> node_seq;
40 typedef std::vector<std::pair<node*, node*>> node_map;
41 
42 template <typename V>
43 struct node_iterator_type {
44   typedef node_seq::iterator seq;
45   typedef node_map::iterator map;
46 };
47 
48 template <typename V>
49 struct node_iterator_type<const V> {
50   typedef node_seq::const_iterator seq;
51   typedef node_map::const_iterator map;
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   typedef typename node_iterator_type<V>::seq SeqIter;
69   typedef typename node_iterator_type<V>::map MapIter;
70   using iterator_category = std::forward_iterator_tag;
71   using value_type = node_iterator_value<V>;
72   using difference_type = std::ptrdiff_t;
73   using pointer = node_iterator_value<V>*;
74   using reference = node_iterator_value<V>&;
75 
76   node_iterator_base()
77       : 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   bool operator==(const node_iterator_base<W>& rhs) const {
105     if (m_type != rhs.m_type)
106       return false;
107 
108     switch (m_type) {
109       case iterator_type::NoneType:
110         return true;
111       case iterator_type::Sequence:
112         return m_seqIt == rhs.m_seqIt;
113       case iterator_type::Map:
114         return m_mapIt == rhs.m_mapIt;
115     }
116     return true;
117   }
118 
119   template <typename W>
120   bool operator!=(const node_iterator_base<W>& rhs) const {
121     return !(*this == rhs);
122   }
123 
124   node_iterator_base<V>& operator++() {
125     switch (m_type) {
126       case iterator_type::NoneType:
127         break;
128       case iterator_type::Sequence:
129         ++m_seqIt;
130         break;
131       case iterator_type::Map:
132         ++m_mapIt;
133         m_mapIt = increment_until_defined(m_mapIt);
134         break;
135     }
136     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   value_type operator*() const {
146     switch (m_type) {
147       case iterator_type::NoneType:
148         return value_type();
149       case iterator_type::Sequence:
150         return value_type(**m_seqIt);
151       case iterator_type::Map:
152         return value_type(*m_mapIt->first, *m_mapIt->second);
153     }
154     return value_type();
155   }
156 
157   proxy operator->() const { return proxy(**this); }
158 
159   MapIter increment_until_defined(MapIter it) {
160     while (it != m_mapEnd && !is_defined(it))
161       ++it;
162     return it;
163   }
164 
165   bool is_defined(MapIter it) const {
166     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 typedef node_iterator_base<node> node_iterator;
177 typedef node_iterator_base<const node> const_node_iterator;
178 }
179 }
180 
181 #endif  // VALUE_DETAIL_NODE_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
182