diff --git a/include/yaml-cpp/value/detail/node.h b/include/yaml-cpp/value/detail/node.h index 9b48c4a..ed736fa 100644 --- a/include/yaml-cpp/value/detail/node.h +++ b/include/yaml-cpp/value/detail/node.h @@ -18,34 +18,28 @@ namespace YAML class node { public: - node(); + node(): m_pData(new node_data) {} + + ValueType::value type() const { return m_pData->type(); } - ValueType::value type() const; - void assign_data(const node& rhs); - void set_scalar(const std::string& data); + void set_data(const node& rhs) { m_pData = rhs.m_pData; } + + void set_type(ValueType::value type) { m_pData->set_type(type); } + void set_null() { m_pData->set_null(); } + void set_scalar(const std::string& scalar) { m_pData->set_scalar(scalar); } + // indexing + template shared_node operator[](const Key& key) const { return (static_cast(*m_pData))[key]; } + template shared_node operator[](const Key& key) { return (*m_pData)[key]; } + template bool remove(const Key& key) { return m_pData->remove(key); } + + shared_node operator[](shared_node pKey) const { return (static_cast(*m_pData))[pKey]; } + shared_node operator[](shared_node pKey) { return (*m_pData)[pKey]; } + bool remove(shared_node pKey) { return m_pData->remove(pKey); } + private: shared_node_data m_pData; }; - - inline node::node() - { - } - - inline ValueType::value node::type() const - { - return m_pData ? m_pData->type() : ValueType::Null; - } - - inline void node::assign_data(const node& rhs) - { - m_pData = rhs.m_pData; - } - - inline void node::set_scalar(const std::string& data) - { - m_pData.reset(new node_data(data)); - } } } diff --git a/include/yaml-cpp/value/detail/node_data.h b/include/yaml-cpp/value/detail/node_data.h index b9395b7..61c7907 100644 --- a/include/yaml-cpp/value/detail/node_data.h +++ b/include/yaml-cpp/value/detail/node_data.h @@ -9,7 +9,8 @@ #include "yaml-cpp/dll.h" #include "yaml-cpp/value/type.h" #include "yaml-cpp/value/ptr.h" -#include +#include +#include #include namespace YAML @@ -19,12 +20,29 @@ namespace YAML class node_data { public: - explicit node_data(const std::string& scalar); + node_data(); - ValueType::value type() const { return m_type; } - const std::string scalar() const { return m_data; } + void set_type(ValueType::value type); + void set_null(); + void set_scalar(const std::string& scalar); + + ValueType::value type() const { return m_isDefined ? m_type : ValueType::Undefined; } + const std::string scalar() const { return m_scalar; } + + // indexing + template shared_node operator[](const Key& key) const; + template shared_node operator[](const Key& key); + template bool remove(const Key& key); + + shared_node operator[](shared_node pKey) const; + shared_node operator[](shared_node pKey); + bool remove(shared_node pKey); private: + void convert_sequence_to_map(); + + private: + bool m_isDefined; ValueType::value m_type; // scalar @@ -36,7 +54,7 @@ namespace YAML // map typedef std::pair kv_pair; - typedef std::vector node_map; + typedef std::list node_map; node_map m_map; }; } diff --git a/include/yaml-cpp/value/impl.h b/include/yaml-cpp/value/impl.h index ddcf1a6..8527c69 100644 --- a/include/yaml-cpp/value/impl.h +++ b/include/yaml-cpp/value/impl.h @@ -12,28 +12,37 @@ namespace YAML { - inline Value::Value(): m_pMemory(new detail::memory_holder) + inline Value::Value(): m_pMemory(new detail::memory_holder), m_pNode(m_pMemory->create_node()) { - EnsureNodeExists(); + m_pNode->set_null(); + } + + inline Value::Value(ValueType::value type): m_pMemory(new detail::memory_holder), m_pNode(m_pMemory->create_node()) + { + m_pNode->set_type(type); } template - inline Value::Value(const T& rhs): m_pMemory(new detail::memory_holder) + inline Value::Value(const T& rhs): m_pMemory(new detail::memory_holder), m_pNode(m_pMemory->create_node()) { Assign(rhs); } - inline Value::Value(const Value& rhs): m_pNode(rhs.m_pNode), m_pMemory(rhs.m_pMemory) + inline Value::Value(const Value& rhs): m_pMemory(rhs.m_pMemory), m_pNode(rhs.m_pNode) { } + inline Value::Value(detail::shared_node pNode, detail::shared_memory_holder pMemory): m_pMemory(pMemory), m_pNode(pNode) + { + } + inline Value::~Value() { } inline ValueType::value Value::Type() const { - return m_pNode ? m_pNode->type() : ValueType::Undefined; + return m_pNode->type(); } // access @@ -63,19 +72,16 @@ namespace YAML template<> inline void Value::Assign(const std::string& rhs) { - EnsureNodeExists(); m_pNode->set_scalar(rhs); } inline void Value::Assign(const char *rhs) { - EnsureNodeExists(); m_pNode->set_scalar(rhs); } inline void Value::Assign(char *rhs) { - EnsureNodeExists(); m_pNode->set_scalar(rhs); } @@ -86,20 +92,10 @@ namespace YAML AssignNode(rhs); return *this; } - - void Value::EnsureNodeExists() - { - if(!m_pNode) - m_pNode = m_pMemory->create_node(); - } - + void Value::AssignData(const Value& rhs) { - EnsureNodeExists(); - if(!rhs.m_pNode) - throw std::runtime_error("Tried to assign an undefined value"); - - m_pNode->assign_data(*rhs.m_pNode); + m_pNode->set_data(*rhs.m_pNode); m_pMemory->merge(*rhs.m_pMemory); } @@ -139,64 +135,68 @@ namespace YAML template inline const Value Value::operator[](const Key& key) const { - return Value(); + detail::shared_node pValue = (static_cast(*m_pNode))[key]; + return Value(pValue, m_pMemory); } template inline Value Value::operator[](const Key& key) { - return Value(); + detail::shared_node pValue = (*m_pNode)[key]; + return Value(pValue, m_pMemory); } template inline bool Value::remove(const Key& key) { - return false; + return m_pNode->remove(key); } inline const Value Value::operator[](const Value& key) const { - return Value(); + detail::shared_node pValue = (static_cast(*m_pNode))[*key.m_pNode]; + return Value(pValue, m_pMemory); } inline Value Value::operator[](const Value& key) { - return Value(); + detail::shared_node pValue = (*m_pNode)[*key.m_pNode]; + return Value(pValue, m_pMemory); } inline bool Value::remove(const Value& key) { - return false; + return m_pNode->remove(*key.m_pNode); } inline const Value Value::operator[](const char *key) const { - return Value(); + return operator[](std::string(key)); } inline Value Value::operator[](const char *key) { - return Value(); + return operator[](std::string(key)); } inline bool Value::remove(const char *key) { - return false; + return m_pNode->remove(std::string(key)); } inline const Value Value::operator[](char *key) const { - return Value(); + return operator[](static_cast(key)); } inline Value Value::operator[](char *key) { - return Value(); + return operator[](static_cast(key)); } inline bool Value::remove(char *key) { - return false; + return remove(static_cast(key)); } // free functions diff --git a/include/yaml-cpp/value/value.h b/include/yaml-cpp/value/value.h index e1ae370..e9bbee9 100644 --- a/include/yaml-cpp/value/value.h +++ b/include/yaml-cpp/value/value.h @@ -59,17 +59,18 @@ namespace YAML bool remove(char *key); private: + explicit Value(detail::shared_node pNode, detail::shared_memory_holder pMemory); + template void Assign(const T& rhs); void Assign(const char *rhs); void Assign(char *rhs); - void EnsureNodeExists(); void AssignData(const Value& rhs); void AssignNode(const Value& rhs); private: - detail::shared_node m_pNode; detail::shared_memory_holder m_pMemory; + detail::shared_node m_pNode; }; int compare(const Value& lhs, const Value& rhs); diff --git a/src/value/detail/node_data.cpp b/src/value/detail/node_data.cpp index dc79a75..11ed462 100644 --- a/src/value/detail/node_data.cpp +++ b/src/value/detail/node_data.cpp @@ -1,11 +1,132 @@ #include "yaml-cpp/value/detail/node_data.h" +#include "yaml-cpp/value/detail/node.h" +#include namespace YAML { namespace detail { - node_data::node_data(const std::string& scalar): m_type(ValueType::Scalar), m_scalar(scalar) + node_data::node_data(): m_isDefined(false), m_type(ValueType::Null) { } + + void node_data::set_type(ValueType::value type) + { + if(type == ValueType::Undefined) { + m_type = type; + m_isDefined = false; + return; + } + + + m_isDefined = true; + if(type == m_type) + return; + + m_type = type; + + switch(m_type) { + case ValueType::Null: + break; + case ValueType::Scalar: + m_scalar.clear(); + break; + case ValueType::Sequence: + m_sequence.clear(); + break; + case ValueType::Map: + m_map.clear(); + break; + case ValueType::Undefined: + assert(false); + break; + } + } + + void node_data::set_null() + { + m_isDefined = true; + m_type = ValueType::Null; + } + + void node_data::set_scalar(const std::string& scalar) + { + m_isDefined = true; + m_type = ValueType::Scalar; + m_scalar = scalar; + } + + // indexing + shared_node node_data::operator[](shared_node pKey) const + { + if(m_type != ValueType::Map) + return shared_node(new node); + + for(node_map::const_iterator it=m_map.begin();it!=m_map.end();++it) { + if(it->first == pKey) + return it->second; + } + + return shared_node(new node); + } + + shared_node node_data::operator[](shared_node pKey) + { + switch(m_type) { + case ValueType::Undefined: + case ValueType::Null: + case ValueType::Scalar: + m_type = ValueType::Map; + m_map.clear(); + break; + case ValueType::Sequence: + convert_sequence_to_map(); + break; + case ValueType::Map: + break; + } + + for(node_map::const_iterator it=m_map.begin();it!=m_map.end();++it) { + if(it->first == pKey) + return it->second; + } + + shared_node pValue(new node); + m_map.push_back(kv_pair(pKey, pValue)); + return pValue; + } + + bool node_data::remove(shared_node pKey) + { + if(m_type != ValueType::Map) + return false; + + for(node_map::iterator it=m_map.begin();it!=m_map.end();++it) { + if(it->first == pKey) { + m_map.erase(it); + return true; + } + } + + return false; + } + + void node_data::convert_sequence_to_map() + { + assert(m_type == ValueType::Sequence); + + m_map.clear(); + for(std::size_t i=0;iset_scalar(stream.str()); + m_map.push_back(kv_pair(pKey, m_sequence[i])); + } + + m_sequence.clear(); + m_type = ValueType::Map; + } } }