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