1 #ifndef NODE_DETAIL_IMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
2 #define NODE_DETAIL_IMPL_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/node/detail/node.h"
11 #include "yaml-cpp/node/detail/node_data.h"
12 #include <type_traits>
13 
14 namespace YAML {
15 namespace detail {
16 template <typename Key, typename Enable = void>
17 struct get_idx {
getget_idx18   static node* get(const std::vector<node*>& /* sequence */,
19                    const Key& /* key */, shared_memory_holder /* pMemory */) {
20     return 0;
21   }
22 };
23 
24 template <typename Key>
25 struct get_idx<Key,
26                typename std::enable_if<std::is_unsigned<Key>::value &&
27                                        !std::is_same<Key, bool>::value>::type> {
28   static node* get(const std::vector<node*>& sequence, const Key& key,
29                    shared_memory_holder /* pMemory */) {
30     return key < sequence.size() ? sequence[key] : 0;
31   }
32 
33   static node* get(std::vector<node*>& sequence, const Key& key,
34                    shared_memory_holder pMemory) {
35     if (key > sequence.size() || (key > 0 && !sequence[key - 1]->is_defined()))
36       return 0;
37     if (key == sequence.size())
38       sequence.push_back(&pMemory->create_node());
39     return sequence[key];
40   }
41 };
42 
43 template <typename Key>
44 struct get_idx<Key, typename std::enable_if<std::is_signed<Key>::value>::type> {
45   static node* get(const std::vector<node*>& sequence, const Key& key,
46                    shared_memory_holder pMemory) {
47     return key >= 0 ? get_idx<std::size_t>::get(
48                           sequence, static_cast<std::size_t>(key), pMemory)
49                     : 0;
50   }
51   static node* get(std::vector<node*>& sequence, const Key& key,
52                    shared_memory_holder pMemory) {
53     return key >= 0 ? get_idx<std::size_t>::get(
54                           sequence, static_cast<std::size_t>(key), pMemory)
55                     : 0;
56   }
57 };
58 
59 template <typename Key, typename Enable = void>
60 struct remove_idx {
61   static bool remove(std::vector<node*>&, const Key&) { return false; }
62 };
63 
64 template <typename Key>
65 struct remove_idx<
66     Key, typename std::enable_if<std::is_unsigned<Key>::value &&
67                                  !std::is_same<Key, bool>::value>::type> {
68 
69   static bool remove(std::vector<node*>& sequence, const Key& key) {
70     if (key >= sequence.size()) {
71       return false;
72     } else {
73       sequence.erase(sequence.begin() + key);
74       return true;
75     }
76   }
77 };
78 
79 template <typename Key>
80 struct remove_idx<Key,
81                   typename std::enable_if<std::is_signed<Key>::value>::type> {
82 
83   static bool remove(std::vector<node*>& sequence, const Key& key) {
84     return key >= 0 ? remove_idx<std::size_t>::remove(
85                           sequence, static_cast<std::size_t>(key))
86                     : false;
87   }
88 };
89 
90 template <typename T>
91 inline bool node::equals(const T& rhs, shared_memory_holder pMemory) {
92   T lhs;
93   if (convert<T>::decode(Node(*this, pMemory), lhs)) {
94     return lhs == rhs;
95   }
96   return false;
97 }
98 
99 inline bool node::equals(const char* rhs, shared_memory_holder pMemory) {
100   return equals<std::string>(rhs, pMemory);
101 }
102 
103 // indexing
104 template <typename Key>
105 inline node* node_data::get(const Key& key,
106                             shared_memory_holder pMemory) const {
107   switch (m_type) {
108     case NodeType::Map:
109       break;
110     case NodeType::Undefined:
111     case NodeType::Null:
112       return NULL;
113     case NodeType::Sequence:
114       if (node* pNode = get_idx<Key>::get(m_sequence, key, pMemory))
115         return pNode;
116       return NULL;
117     case NodeType::Scalar:
118       throw BadSubscript();
119   }
120 
121   for (node_map::const_iterator it = m_map.begin(); it != m_map.end(); ++it) {
122     if (it->first->equals(key, pMemory)) {
123       return it->second;
124     }
125   }
126 
127   return NULL;
128 }
129 
130 template <typename Key>
131 inline node& node_data::get(const Key& key, shared_memory_holder pMemory) {
132   switch (m_type) {
133     case NodeType::Map:
134       break;
135     case NodeType::Undefined:
136     case NodeType::Null:
137     case NodeType::Sequence:
138       if (node* pNode = get_idx<Key>::get(m_sequence, key, pMemory)) {
139         m_type = NodeType::Sequence;
140         return *pNode;
141       }
142 
143       convert_to_map(pMemory);
144       break;
145     case NodeType::Scalar:
146       throw BadSubscript();
147   }
148 
149   for (node_map::const_iterator it = m_map.begin(); it != m_map.end(); ++it) {
150     if (it->first->equals(key, pMemory)) {
151       return *it->second;
152     }
153   }
154 
155   node& k = convert_to_node(key, pMemory);
156   node& v = pMemory->create_node();
157   insert_map_pair(k, v);
158   return v;
159 }
160 
161 template <typename Key>
162 inline bool node_data::remove(const Key& key, shared_memory_holder pMemory) {
163   if (m_type == NodeType::Sequence) {
164     return remove_idx<Key>::remove(m_sequence, key);
165   } else if (m_type == NodeType::Map) {
166     kv_pairs::iterator it = m_undefinedPairs.begin();
167     while (it != m_undefinedPairs.end()) {
168       kv_pairs::iterator jt = std::next(it);
169       if (it->first->equals(key, pMemory)) {
170         m_undefinedPairs.erase(it);
171       }
172       it = jt;
173     }
174 
175     for (node_map::iterator iter = m_map.begin(); iter != m_map.end(); ++iter) {
176       if (iter->first->equals(key, pMemory)) {
177         m_map.erase(iter);
178         return true;
179       }
180     }
181   }
182 
183   return false;
184 }
185 
186 // map
187 template <typename Key, typename Value>
188 inline void node_data::force_insert(const Key& key, const Value& value,
189                                     shared_memory_holder pMemory) {
190   switch (m_type) {
191     case NodeType::Map:
192       break;
193     case NodeType::Undefined:
194     case NodeType::Null:
195     case NodeType::Sequence:
196       convert_to_map(pMemory);
197       break;
198     case NodeType::Scalar:
199       throw BadInsert();
200   }
201 
202   node& k = convert_to_node(key, pMemory);
203   node& v = convert_to_node(value, pMemory);
204   insert_map_pair(k, v);
205 }
206 
207 template <typename T>
208 inline node& node_data::convert_to_node(const T& rhs,
209                                         shared_memory_holder pMemory) {
210   Node value = convert<T>::encode(rhs);
211   value.EnsureNodeExists();
212   pMemory->merge(*value.m_pMemory);
213   return *value.m_pNode;
214 }
215 }
216 }
217 
218 #endif  // NODE_DETAIL_IMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
219