diff --git a/include/node.h b/include/node.h index 5ee1273..9b6eb22 100644 --- a/include/node.h +++ b/include/node.h @@ -40,7 +40,7 @@ namespace YAML // accessors Iterator begin() const; Iterator end() const; - unsigned size() const; + std::size_t size() const; // extraction of scalars bool GetScalar(std::string& s) const; @@ -55,19 +55,17 @@ namespace YAML template friend void operator >> (const Node& node, T& value); - // just for maps + // retrieval for maps and sequences template const Node *FindValue(const T& key) const; - const Node *FindValue(const char *key) const; - + template const Node& operator [] (const T& key) const; + + // specific to maps + const Node *FindValue(const char *key) const; const Node& operator [] (const char *key) const; - // just for sequences - const Node& operator [] (unsigned u) const; - const Node& operator [] (int i) const; - // for anchors/aliases const Node *Identity() const { return m_pIdentity; } bool IsAlias() const { return m_alias; } @@ -81,10 +79,17 @@ namespace YAML friend bool operator < (const Node& n1, const Node& n2); private: + // helper for sequences + template friend struct _FindFromNodeAtIndex; + const Node *FindAtIndex(std::size_t i) const; + // helper for maps template const Node& GetValue(const T& key) const; - + + template + const Node *FindValueForKey(const T& key) const; + // helpers for parsing void ParseHeader(Scanner *pScanner, const ParserState& state); void ParseTag(Scanner *pScanner, const ParserState& state); diff --git a/include/nodeimpl.h b/include/nodeimpl.h index 606a5be..f513fd5 100644 --- a/include/nodeimpl.h +++ b/include/nodeimpl.h @@ -4,6 +4,8 @@ #define NODEIMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#include "nodeutil.h" + namespace YAML { // implementation of templated things @@ -31,9 +33,18 @@ namespace YAML template inline const Node *Node::FindValue(const T& key) const { - if(!m_pContent) - return 0; - + switch(GetType()) { + case CT_MAP: + return FindValueForKey(key); + case CT_SEQUENCE: + return FindFromNodeAtIndex(*this, key); + default: + return 0; + } + } + + template + inline const Node *Node::FindValueForKey(const T& key) const { for(Iterator it=begin();it!=end();++it) { T t; if(it.first().Read(t)) { @@ -45,24 +56,16 @@ namespace YAML return 0; } - inline const Node *Node::FindValue(const char *key) const { - return FindValue(std::string(key)); - } - template inline const Node& Node::GetValue(const T& key) const { if(!m_pContent) throw BadDereference(); - for(Iterator it=begin();it!=end();++it) { - T t; - if(it.first().Read(t)) { - if(key == t) - return it.second(); - } - } - - throw MakeTypedKeyNotFound(m_mark, key); + const Node *pValue = FindValue(key); + if(!pValue) + throw MakeTypedKeyNotFound(m_mark, key); + + return *pValue; } template @@ -70,6 +73,10 @@ namespace YAML return GetValue(key); } + inline const Node *Node::FindValue(const char *key) const { + return FindValue(std::string(key)); + } + inline const Node& Node::operator [] (const char *key) const { return GetValue(std::string(key)); } diff --git a/include/nodeutil.h b/include/nodeutil.h new file mode 100644 index 0000000..eb2956f --- /dev/null +++ b/include/nodeutil.h @@ -0,0 +1,60 @@ +#pragma once + +#ifndef NODEUTIL_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#define NODEUTIL_H_62B23520_7C8E_11DE_8A39_0800200C9A66 + + +namespace YAML +{ + template + struct is_same_type { + enum { value = false }; + }; + + template + struct is_same_type { + enum { value = true }; + }; + + template + struct is_index_type_with_check { + enum { value = false }; + }; + + template <> struct is_index_type_with_check { enum { value = true }; }; + +#define MAKE_INDEX_TYPE(Type) \ + template <> struct is_index_type_with_check::value> { enum { value = true }; } + + MAKE_INDEX_TYPE(int); + MAKE_INDEX_TYPE(unsigned); + MAKE_INDEX_TYPE(short); + MAKE_INDEX_TYPE(unsigned short); + MAKE_INDEX_TYPE(long); + MAKE_INDEX_TYPE(unsigned long); + +#undef MAKE_INDEX_TYPE; + + template + struct is_index_type: public is_index_type_with_check {}; + + // messing around with template stuff to get the right overload for operator [] for a sequence + template + struct _FindFromNodeAtIndex { + const Node *pRet; + _FindFromNodeAtIndex(const Node&, const T&): pRet(0) {} + }; + + template + struct _FindFromNodeAtIndex { + const Node *pRet; + _FindFromNodeAtIndex(const Node& node, const T& key): pRet(node.FindAtIndex(static_cast(key))) {} + }; + + template + inline const Node *FindFromNodeAtIndex(const Node& node, const T& key) { + return _FindFromNodeAtIndex::value>(node, key).pRet; + } +} + +#endif // NODEUTIL_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/src/aliascontent.cpp b/src/aliascontent.cpp index 9f98571..7d49b71 100644 --- a/src/aliascontent.cpp +++ b/src/aliascontent.cpp @@ -37,12 +37,12 @@ namespace YAML return m_pRef->GetEnd(i); } - Node* AliasContent::GetNode(unsigned n) const + Node* AliasContent::GetNode(std::size_t n) const { return m_pRef->GetNode(n); } - unsigned AliasContent::GetSize() const + std::size_t AliasContent::GetSize() const { return m_pRef->GetSize(); } diff --git a/src/aliascontent.h b/src/aliascontent.h index e19f1d1..e6448fe 100644 --- a/src/aliascontent.h +++ b/src/aliascontent.h @@ -20,8 +20,8 @@ namespace YAML virtual bool GetBegin(std::map ::const_iterator&) const; virtual bool GetEnd(std::vector ::const_iterator&) const; virtual bool GetEnd(std::map ::const_iterator&) const; - virtual Node* GetNode(unsigned) const; - virtual unsigned GetSize() const; + virtual Node* GetNode(std::size_t) const; + virtual std::size_t GetSize() const; virtual bool IsScalar() const; virtual bool IsMap() const; virtual bool IsSequence() const; diff --git a/src/content.h b/src/content.h index b9cd311..1574691 100644 --- a/src/content.h +++ b/src/content.h @@ -33,8 +33,8 @@ namespace YAML virtual bool GetBegin(std::map ::const_iterator&) const { return false; } virtual bool GetEnd(std::vector ::const_iterator&) const { return false; } virtual bool GetEnd(std::map ::const_iterator&) const { return false; } - virtual Node *GetNode(unsigned) const { return 0; } - virtual unsigned GetSize() const { return 0; } + virtual Node *GetNode(std::size_t) const { return 0; } + virtual std::size_t GetSize() const { return 0; } virtual bool IsScalar() const { return false; } virtual bool IsMap() const { return false; } virtual bool IsSequence() const { return false; } diff --git a/src/conversion.cpp b/src/conversion.cpp index 904efb0..fa199bb 100644 --- a/src/conversion.cpp +++ b/src/conversion.cpp @@ -22,7 +22,7 @@ namespace template bool IsEntirely(const std::string& str, T func) { - for(unsigned i=0;ipop(); } @@ -209,7 +209,7 @@ namespace YAML // size // . Returns the size of this node, if it's a sequence node. // . Otherwise, returns zero. - unsigned Node::size() const + std::size_t Node::size() const { if(!m_pContent) return 0; @@ -217,28 +217,12 @@ namespace YAML return m_pContent->GetSize(); } - const Node& Node::operator [] (unsigned u) const + const Node *Node::FindAtIndex(std::size_t i) const { if(!m_pContent) - throw BadDereference(); - - Node *pNode = m_pContent->GetNode(u); - if(pNode) - return *pNode; - - return GetValue(u); - } - - const Node& Node::operator [] (int i) const - { - if(!m_pContent) - throw BadDereference(); - - Node *pNode = m_pContent->GetNode(i); - if(pNode) - return *pNode; - - return GetValue(i); + return 0; + + return m_pContent->GetNode(i); } bool Node::GetScalar(std::string& s) const diff --git a/src/ostream.cpp b/src/ostream.cpp index 9f75684..463a450 100644 --- a/src/ostream.cpp +++ b/src/ostream.cpp @@ -43,8 +43,8 @@ namespace YAML ostream& operator << (ostream& out, const char *str) { - unsigned length = std::strlen(str); - for(unsigned i=0;i inline int RegEx::MatchOpOr(const Source& source) const { - for(unsigned i=0;i= 0) return n; @@ -140,7 +140,7 @@ namespace YAML template inline int RegEx::MatchOpAnd(const Source& source) const { int first = -1; - for(unsigned i=0;i inline int RegEx::MatchOpSeq(const Source& source) const { int offset = 0; - for(unsigned i=0;im_data.size(); + std::size_t n = m_data.size(), m = pSeq->m_data.size(); if(n < m) return -1; else if(n > m) return 1; - for(unsigned i=0;iCompare(*pSeq->m_data[i]); if(cmp != 0) return cmp; diff --git a/src/sequence.h b/src/sequence.h index c7e0828..f158882 100644 --- a/src/sequence.h +++ b/src/sequence.h @@ -20,8 +20,8 @@ namespace YAML void Clear(); virtual bool GetBegin(std::vector ::const_iterator& it) const; virtual bool GetEnd(std::vector ::const_iterator& it) const; - virtual Node *GetNode(unsigned i) const; - virtual unsigned GetSize() const; + virtual Node *GetNode(std::size_t i) const; + virtual std::size_t GetSize() const; virtual void Parse(Scanner *pScanner, const ParserState& state); virtual void Write(Emitter& out) const; diff --git a/src/token.h b/src/token.h index 3c5fb58..060861a 100644 --- a/src/token.h +++ b/src/token.h @@ -59,7 +59,7 @@ namespace YAML friend std::ostream& operator << (std::ostream& out, const Token& token) { out << TokenNames[token.type] << std::string(": ") << token.value; - for(unsigned i=0;i