mirror of
https://github.com/jbeder/yaml-cpp.git
synced 2025-09-09 12:41:17 +00:00
Fixed bug with block maps with null value (the next key was being read as the value)
This commit is contained in:
@@ -12,7 +12,7 @@ namespace YAML
|
||||
return 0; // TODO: how to clone an alias?
|
||||
}
|
||||
|
||||
void AliasContent::Parse(Scanner * /*pScanner*/, const ParserState& /*state*/)
|
||||
void AliasContent::Parse(Scanner * /*pScanner*/, ParserState& /*state*/)
|
||||
{
|
||||
}
|
||||
|
||||
|
@@ -15,7 +15,7 @@ namespace YAML
|
||||
|
||||
virtual Content *Clone() const;
|
||||
|
||||
virtual void Parse(Scanner* pScanner, const ParserState& state);
|
||||
virtual void Parse(Scanner* pScanner, ParserState& state);
|
||||
virtual void Write(Emitter&) const;
|
||||
|
||||
virtual bool GetBegin(std::vector <Node *>::const_iterator&) const;
|
||||
|
@@ -28,7 +28,7 @@ namespace YAML
|
||||
|
||||
virtual Content *Clone() const = 0;
|
||||
|
||||
virtual void Parse(Scanner *pScanner, const ParserState& state) = 0;
|
||||
virtual void Parse(Scanner *pScanner, ParserState& state) = 0;
|
||||
virtual void Write(Emitter& out) const = 0;
|
||||
|
||||
virtual bool GetBegin(std::vector <Node *>::const_iterator&) const { return false; }
|
||||
|
20
src/map.cpp
20
src/map.cpp
@@ -57,7 +57,7 @@ namespace YAML
|
||||
return m_data.size();
|
||||
}
|
||||
|
||||
void Map::Parse(Scanner *pScanner, const ParserState& state)
|
||||
void Map::Parse(Scanner *pScanner, ParserState& state)
|
||||
{
|
||||
Clear();
|
||||
|
||||
@@ -71,10 +71,11 @@ namespace YAML
|
||||
}
|
||||
}
|
||||
|
||||
void Map::ParseBlock(Scanner *pScanner, const ParserState& state)
|
||||
void Map::ParseBlock(Scanner *pScanner, ParserState& state)
|
||||
{
|
||||
// eat start token
|
||||
pScanner->pop();
|
||||
state.PushCollectionType(ParserState::BLOCK_MAP);
|
||||
|
||||
while(1) {
|
||||
if(pScanner->empty())
|
||||
@@ -106,12 +107,15 @@ namespace YAML
|
||||
// assign the map with the actual pointers
|
||||
m_data[pKey.release()] = pValue.release();
|
||||
}
|
||||
|
||||
state.PopCollectionType(ParserState::BLOCK_MAP);
|
||||
}
|
||||
|
||||
void Map::ParseFlow(Scanner *pScanner, const ParserState& state)
|
||||
void Map::ParseFlow(Scanner *pScanner, ParserState& state)
|
||||
{
|
||||
// eat start token
|
||||
pScanner->pop();
|
||||
state.PushCollectionType(ParserState::FLOW_MAP);
|
||||
|
||||
while(1) {
|
||||
if(pScanner->empty())
|
||||
@@ -148,12 +152,15 @@ namespace YAML
|
||||
// assign the map with the actual pointers
|
||||
m_data[pKey.release()] = pValue.release();
|
||||
}
|
||||
|
||||
state.PopCollectionType(ParserState::FLOW_MAP);
|
||||
}
|
||||
|
||||
// ParseCompact
|
||||
// . Single "key: value" pair in a flow sequence
|
||||
void Map::ParseCompact(Scanner *pScanner, const ParserState& state)
|
||||
void Map::ParseCompact(Scanner *pScanner, ParserState& state)
|
||||
{
|
||||
state.PushCollectionType(ParserState::COMPACT_MAP);
|
||||
std::auto_ptr <Node> pKey(new Node), pValue(new Node);
|
||||
|
||||
// grab key
|
||||
@@ -168,12 +175,14 @@ namespace YAML
|
||||
|
||||
// assign the map with the actual pointers
|
||||
m_data[pKey.release()] = pValue.release();
|
||||
state.PopCollectionType(ParserState::COMPACT_MAP);
|
||||
}
|
||||
|
||||
// ParseCompactWithNoKey
|
||||
// . Single ": value" pair in a flow sequence
|
||||
void Map::ParseCompactWithNoKey(Scanner *pScanner, const ParserState& state)
|
||||
void Map::ParseCompactWithNoKey(Scanner *pScanner, ParserState& state)
|
||||
{
|
||||
state.PushCollectionType(ParserState::COMPACT_MAP);
|
||||
std::auto_ptr <Node> pKey(new Node), pValue(new Node);
|
||||
|
||||
// grab value
|
||||
@@ -182,6 +191,7 @@ namespace YAML
|
||||
|
||||
// assign the map with the actual pointers
|
||||
m_data[pKey.release()] = pValue.release();
|
||||
state.PopCollectionType(ParserState::COMPACT_MAP);
|
||||
}
|
||||
|
||||
void Map::Write(Emitter& out) const
|
||||
|
10
src/map.h
10
src/map.h
@@ -27,7 +27,7 @@ namespace YAML
|
||||
virtual bool GetBegin(std::map <Node *, Node *, ltnode>::const_iterator& it) const;
|
||||
virtual bool GetEnd(std::map <Node *, Node *, ltnode>::const_iterator& it) const;
|
||||
virtual std::size_t GetSize() const;
|
||||
virtual void Parse(Scanner *pScanner, const ParserState& state);
|
||||
virtual void Parse(Scanner *pScanner, ParserState& state);
|
||||
virtual void Write(Emitter& out) const;
|
||||
|
||||
virtual bool IsMap() const { return true; }
|
||||
@@ -39,10 +39,10 @@ namespace YAML
|
||||
virtual int Compare(Map *pMap);
|
||||
|
||||
private:
|
||||
void ParseBlock(Scanner *pScanner, const ParserState& state);
|
||||
void ParseFlow(Scanner *pScanner, const ParserState& state);
|
||||
void ParseCompact(Scanner *pScanner, const ParserState& state);
|
||||
void ParseCompactWithNoKey(Scanner *pScanner, const ParserState& state);
|
||||
void ParseBlock(Scanner *pScanner, ParserState& state);
|
||||
void ParseFlow(Scanner *pScanner, ParserState& state);
|
||||
void ParseCompact(Scanner *pScanner, ParserState& state);
|
||||
void ParseCompactWithNoKey(Scanner *pScanner, ParserState& state);
|
||||
|
||||
private:
|
||||
node_map m_data;
|
||||
|
19
src/node.cpp
19
src/node.cpp
@@ -54,7 +54,7 @@ namespace YAML
|
||||
return std::auto_ptr<Node> (new Node(m_mark, m_anchor, m_tag, m_pContent));
|
||||
}
|
||||
|
||||
void Node::Parse(Scanner *pScanner, const ParserState& state)
|
||||
void Node::Parse(Scanner *pScanner, ParserState& state)
|
||||
{
|
||||
Clear();
|
||||
|
||||
@@ -104,13 +104,14 @@ namespace YAML
|
||||
break;
|
||||
case Token::FLOW_MAP_START:
|
||||
case Token::BLOCK_MAP_START:
|
||||
case Token::KEY:
|
||||
m_pContent = new Map;
|
||||
break;
|
||||
case Token::KEY:
|
||||
// compact maps can only go in a flow sequence
|
||||
if(state.GetCurCollectionType() == ParserState::FLOW_SEQ)
|
||||
m_pContent = new Map;
|
||||
break;
|
||||
default:
|
||||
// std::stringstream str;
|
||||
// str << TokenNames[pScanner->peek().type];
|
||||
// throw std::runtime_error(str.str());
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -125,7 +126,7 @@ namespace YAML
|
||||
|
||||
// ParseHeader
|
||||
// . Grabs any tag, alias, or anchor tokens and deals with them.
|
||||
void Node::ParseHeader(Scanner *pScanner, const ParserState& state)
|
||||
void Node::ParseHeader(Scanner *pScanner, ParserState& state)
|
||||
{
|
||||
while(1) {
|
||||
if(pScanner->empty())
|
||||
@@ -140,7 +141,7 @@ namespace YAML
|
||||
}
|
||||
}
|
||||
|
||||
void Node::ParseTag(Scanner *pScanner, const ParserState& state)
|
||||
void Node::ParseTag(Scanner *pScanner, ParserState& state)
|
||||
{
|
||||
Token& token = pScanner->peek();
|
||||
if(m_tag != "")
|
||||
@@ -151,7 +152,7 @@ namespace YAML
|
||||
pScanner->pop();
|
||||
}
|
||||
|
||||
void Node::ParseAnchor(Scanner *pScanner, const ParserState& /*state*/)
|
||||
void Node::ParseAnchor(Scanner *pScanner, ParserState& /*state*/)
|
||||
{
|
||||
Token& token = pScanner->peek();
|
||||
if(m_anchor != "")
|
||||
@@ -162,7 +163,7 @@ namespace YAML
|
||||
pScanner->pop();
|
||||
}
|
||||
|
||||
void Node::ParseAlias(Scanner *pScanner, const ParserState& /*state*/)
|
||||
void Node::ParseAlias(Scanner *pScanner, ParserState& /*state*/)
|
||||
{
|
||||
Token& token = pScanner->peek();
|
||||
if(m_anchor != "")
|
||||
|
@@ -6,6 +6,8 @@
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <stack>
|
||||
#include <cassert>
|
||||
|
||||
namespace YAML
|
||||
{
|
||||
@@ -16,11 +18,19 @@ namespace YAML
|
||||
|
||||
struct ParserState
|
||||
{
|
||||
enum COLLECTION_TYPE { NONE, BLOCK_MAP, BLOCK_SEQ, FLOW_MAP, FLOW_SEQ, COMPACT_MAP };
|
||||
|
||||
ParserState();
|
||||
|
||||
const std::string TranslateTagHandle(const std::string& handle) const;
|
||||
COLLECTION_TYPE GetCurCollectionType() const { if(collectionStack.empty()) return NONE; return collectionStack.top(); }
|
||||
|
||||
void PushCollectionType(COLLECTION_TYPE type) { collectionStack.push(type); }
|
||||
void PopCollectionType(COLLECTION_TYPE type) { assert(type == GetCurCollectionType()); collectionStack.pop(); }
|
||||
|
||||
Version version;
|
||||
std::map <std::string, std::string> tags;
|
||||
std::stack <COLLECTION_TYPE> collectionStack;
|
||||
};
|
||||
}
|
||||
|
||||
|
@@ -24,7 +24,7 @@ namespace YAML
|
||||
return new Scalar(m_data);
|
||||
}
|
||||
|
||||
void Scalar::Parse(Scanner *pScanner, const ParserState& /*state*/)
|
||||
void Scalar::Parse(Scanner *pScanner, ParserState& /*state*/)
|
||||
{
|
||||
Token& token = pScanner->peek();
|
||||
m_data = token.value;
|
||||
|
@@ -18,7 +18,7 @@ namespace YAML
|
||||
|
||||
virtual Content *Clone() const;
|
||||
|
||||
virtual void Parse(Scanner *pScanner, const ParserState& state);
|
||||
virtual void Parse(Scanner *pScanner, ParserState& state);
|
||||
virtual void Write(Emitter& out) const;
|
||||
|
||||
virtual bool IsScalar() const { return true; }
|
||||
|
@@ -59,7 +59,7 @@ namespace YAML
|
||||
return m_data.size();
|
||||
}
|
||||
|
||||
void Sequence::Parse(Scanner *pScanner, const ParserState& state)
|
||||
void Sequence::Parse(Scanner *pScanner, ParserState& state)
|
||||
{
|
||||
Clear();
|
||||
|
||||
@@ -71,10 +71,11 @@ namespace YAML
|
||||
}
|
||||
}
|
||||
|
||||
void Sequence::ParseBlock(Scanner *pScanner, const ParserState& state)
|
||||
void Sequence::ParseBlock(Scanner *pScanner, ParserState& state)
|
||||
{
|
||||
// eat start token
|
||||
pScanner->pop();
|
||||
state.PushCollectionType(ParserState::BLOCK_SEQ);
|
||||
|
||||
while(1) {
|
||||
if(pScanner->empty())
|
||||
@@ -100,12 +101,15 @@ namespace YAML
|
||||
|
||||
pNode->Parse(pScanner, state);
|
||||
}
|
||||
|
||||
state.PopCollectionType(ParserState::BLOCK_SEQ);
|
||||
}
|
||||
|
||||
void Sequence::ParseFlow(Scanner *pScanner, const ParserState& state)
|
||||
void Sequence::ParseFlow(Scanner *pScanner, ParserState& state)
|
||||
{
|
||||
// eat start token
|
||||
pScanner->pop();
|
||||
state.PushCollectionType(ParserState::FLOW_SEQ);
|
||||
|
||||
while(1) {
|
||||
if(pScanner->empty())
|
||||
@@ -129,6 +133,8 @@ namespace YAML
|
||||
else if(token.type != Token::FLOW_SEQ_END)
|
||||
throw ParserException(token.mark, ErrorMsg::END_OF_SEQ_FLOW);
|
||||
}
|
||||
|
||||
state.PopCollectionType(ParserState::FLOW_SEQ);
|
||||
}
|
||||
|
||||
void Sequence::Write(Emitter& out) const
|
||||
|
@@ -26,7 +26,7 @@ namespace YAML
|
||||
virtual Node *GetNode(std::size_t i) const;
|
||||
virtual std::size_t GetSize() const;
|
||||
|
||||
virtual void Parse(Scanner *pScanner, const ParserState& state);
|
||||
virtual void Parse(Scanner *pScanner, ParserState& state);
|
||||
virtual void Write(Emitter& out) const;
|
||||
|
||||
virtual bool IsSequence() const { return true; }
|
||||
@@ -38,8 +38,8 @@ namespace YAML
|
||||
virtual int Compare(Map *) { return -1; }
|
||||
|
||||
private:
|
||||
void ParseBlock(Scanner *pScanner, const ParserState& state);
|
||||
void ParseFlow(Scanner *pScanner, const ParserState& state);
|
||||
void ParseBlock(Scanner *pScanner, ParserState& state);
|
||||
void ParseFlow(Scanner *pScanner, ParserState& state);
|
||||
|
||||
protected:
|
||||
std::vector <Node *> m_data;
|
||||
|
Reference in New Issue
Block a user