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