mirror of
https://github.com/loot/yaml-cpp.git
synced 2026-07-27 14:13:42 -07:00
Merged r366:387 from the jbeder-event-api branch
This commit is contained in:
@@ -0,0 +1,38 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef ALIASMANAGER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
#define ALIASMANAGER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
|
#include "anchor.h"
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
namespace YAML
|
||||||
|
{
|
||||||
|
class Node;
|
||||||
|
|
||||||
|
class AliasManager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
AliasManager();
|
||||||
|
|
||||||
|
void RegisterReference(const Node& node);
|
||||||
|
|
||||||
|
const Node *LookupReference(const Node& node) const;
|
||||||
|
anchor_t LookupAnchor(const Node& node) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const Node *_LookupReference(const Node& oldIdentity) const;
|
||||||
|
anchor_t _CreateNewAnchor();
|
||||||
|
|
||||||
|
private:
|
||||||
|
typedef std::map<const Node*, const Node*> NodeByNode;
|
||||||
|
NodeByNode m_newIdentityByOldIdentity;
|
||||||
|
|
||||||
|
typedef std::map<const Node*, anchor_t> AnchorByIdentity;
|
||||||
|
AnchorByIdentity m_anchorByIdentity;
|
||||||
|
|
||||||
|
anchor_t m_curAnchor;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // ALIASMANAGER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef ANCHOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
#define ANCHOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
|
namespace YAML
|
||||||
|
{
|
||||||
|
typedef std::size_t anchor_t;
|
||||||
|
const anchor_t NullAnchor = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // ANCHOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef EMITFROMEVENTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
#define EMITFROMEVENTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
|
#include "eventhandler.h"
|
||||||
|
#include <stack>
|
||||||
|
|
||||||
|
namespace YAML
|
||||||
|
{
|
||||||
|
class Emitter;
|
||||||
|
|
||||||
|
class EmitFromEvents: public EventHandler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
EmitFromEvents(Emitter& emitter);
|
||||||
|
|
||||||
|
virtual void OnDocumentStart(const Mark& mark);
|
||||||
|
virtual void OnDocumentEnd();
|
||||||
|
|
||||||
|
virtual void OnNull(const std::string& tag, anchor_t anchor);
|
||||||
|
virtual void OnAlias(const Mark& mark, anchor_t anchor);
|
||||||
|
virtual void OnScalar(const Mark& mark, const std::string& tag, anchor_t anchor, const std::string& value);
|
||||||
|
|
||||||
|
virtual void OnSequenceStart(const Mark& mark, const std::string& tag, anchor_t anchor);
|
||||||
|
virtual void OnSequenceEnd();
|
||||||
|
|
||||||
|
virtual void OnMapStart(const Mark& mark, const std::string& tag, anchor_t anchor);
|
||||||
|
virtual void OnMapEnd();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void BeginNode();
|
||||||
|
void EmitProps(const std::string& tag, anchor_t anchor);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Emitter& m_emitter;
|
||||||
|
|
||||||
|
struct State { enum value { WaitingForSequenceEntry, WaitingForKey, WaitingForValue }; };
|
||||||
|
std::stack<State::value> m_stateStack;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // EMITFROMEVENTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef EVENTHANDLER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
#define EVENTHANDLER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
|
#include "anchor.h"
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace YAML
|
||||||
|
{
|
||||||
|
struct Mark;
|
||||||
|
|
||||||
|
class EventHandler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~EventHandler() {}
|
||||||
|
|
||||||
|
virtual void OnDocumentStart(const Mark& mark) = 0;
|
||||||
|
virtual void OnDocumentEnd() = 0;
|
||||||
|
|
||||||
|
virtual void OnNull(const std::string& tag, anchor_t anchor) = 0;
|
||||||
|
virtual void OnAlias(const Mark& mark, anchor_t anchor) = 0;
|
||||||
|
virtual void OnScalar(const Mark& mark, const std::string& tag, anchor_t anchor, const std::string& value) = 0;
|
||||||
|
|
||||||
|
virtual void OnSequenceStart(const Mark& mark, const std::string& tag, anchor_t anchor) = 0;
|
||||||
|
virtual void OnSequenceEnd() = 0;
|
||||||
|
|
||||||
|
virtual void OnMapStart(const Mark& mark, const std::string& tag, anchor_t anchor) = 0;
|
||||||
|
virtual void OnMapEnd() = 0;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // EVENTHANDLER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
+16
-13
@@ -17,10 +17,12 @@
|
|||||||
|
|
||||||
namespace YAML
|
namespace YAML
|
||||||
{
|
{
|
||||||
|
class AliasManager;
|
||||||
class Content;
|
class Content;
|
||||||
class Scanner;
|
class Scanner;
|
||||||
class Emitter;
|
class Emitter;
|
||||||
struct ParserState;
|
class EventHandler;
|
||||||
|
struct NodeProperties;
|
||||||
|
|
||||||
enum CONTENT_TYPE { CT_NONE, CT_SCALAR, CT_SEQUENCE, CT_MAP };
|
enum CONTENT_TYPE { CT_NONE, CT_SCALAR, CT_SEQUENCE, CT_MAP };
|
||||||
|
|
||||||
@@ -32,9 +34,18 @@ namespace YAML
|
|||||||
|
|
||||||
void Clear();
|
void Clear();
|
||||||
std::auto_ptr<Node> Clone() const;
|
std::auto_ptr<Node> Clone() const;
|
||||||
void Parse(Scanner *pScanner, ParserState& state);
|
void EmitEvents(EventHandler& eventHandler) const;
|
||||||
|
void EmitEvents(AliasManager& am, EventHandler& eventHandler) const;
|
||||||
|
|
||||||
CONTENT_TYPE GetType() const;
|
void Init(CONTENT_TYPE type, const Mark& mark, const std::string& tag);
|
||||||
|
void InitNull(const std::string& tag);
|
||||||
|
void InitAlias(const Mark& mark, const Node& identity);
|
||||||
|
|
||||||
|
void SetData(const std::string& data);
|
||||||
|
void Append(std::auto_ptr<Node> pNode);
|
||||||
|
void Insert(std::auto_ptr<Node> pKey, std::auto_ptr<Node> pValue);
|
||||||
|
|
||||||
|
CONTENT_TYPE GetType() const { return m_type; }
|
||||||
|
|
||||||
// file location of start of this node
|
// file location of start of this node
|
||||||
const Mark GetMark() const { return m_mark; }
|
const Mark GetMark() const { return m_mark; }
|
||||||
@@ -98,18 +109,10 @@ namespace YAML
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
const Node *FindValueForKey(const T& key) const;
|
const Node *FindValueForKey(const T& key) const;
|
||||||
|
|
||||||
// helper for cloning
|
|
||||||
Node(const Mark& mark, const std::string& anchor, const std::string& tag, const Content *pContent);
|
|
||||||
|
|
||||||
// helpers for parsing
|
|
||||||
void ParseHeader(Scanner *pScanner, ParserState& state);
|
|
||||||
void ParseTag(Scanner *pScanner, ParserState& state);
|
|
||||||
void ParseAnchor(Scanner *pScanner, ParserState& state);
|
|
||||||
void ParseAlias(Scanner *pScanner, ParserState& state);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Mark m_mark;
|
Mark m_mark;
|
||||||
std::string m_anchor, m_tag;
|
std::string m_tag;
|
||||||
|
CONTENT_TYPE m_type;
|
||||||
Content *m_pContent;
|
Content *m_pContent;
|
||||||
bool m_alias;
|
bool m_alias;
|
||||||
const Node *m_pIdentity;
|
const Node *m_pIdentity;
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef NODEPROPERTIES_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
#define NODEPROPERTIES_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
|
namespace YAML
|
||||||
|
{
|
||||||
|
struct NodeProperties {
|
||||||
|
std::string tag;
|
||||||
|
std::string anchor;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // NODEPROPERTIES_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
+8
-7
@@ -4,19 +4,18 @@
|
|||||||
#define PARSER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#define PARSER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
|
|
||||||
#include "node.h"
|
|
||||||
#include "noncopyable.h"
|
#include "noncopyable.h"
|
||||||
#include <ios>
|
#include <ios>
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
#include <map>
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML
|
||||||
{
|
{
|
||||||
class Scanner;
|
struct Directives;
|
||||||
struct ParserState;
|
struct Mark;
|
||||||
struct Token;
|
struct Token;
|
||||||
|
class EventHandler;
|
||||||
|
class Node;
|
||||||
|
class Scanner;
|
||||||
|
|
||||||
class Parser: private noncopyable
|
class Parser: private noncopyable
|
||||||
{
|
{
|
||||||
@@ -28,6 +27,8 @@ namespace YAML
|
|||||||
operator bool() const;
|
operator bool() const;
|
||||||
|
|
||||||
void Load(std::istream& in);
|
void Load(std::istream& in);
|
||||||
|
bool HandleNextDocument(EventHandler& eventHandler);
|
||||||
|
|
||||||
bool GetNextDocument(Node& document);
|
bool GetNextDocument(Node& document);
|
||||||
void PrintTokens(std::ostream& out);
|
void PrintTokens(std::ostream& out);
|
||||||
|
|
||||||
@@ -39,7 +40,7 @@ namespace YAML
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
std::auto_ptr<Scanner> m_pScanner;
|
std::auto_ptr<Scanner> m_pScanner;
|
||||||
std::auto_ptr<ParserState> m_pState;
|
std::auto_ptr<Directives> m_pDirectives;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+6
-16
@@ -2,25 +2,10 @@
|
|||||||
|
|
||||||
namespace YAML
|
namespace YAML
|
||||||
{
|
{
|
||||||
AliasContent::AliasContent(Content* pNodeContent)
|
AliasContent::AliasContent(Content* pNodeContent): m_pRef(pNodeContent)
|
||||||
: m_pRef(pNodeContent)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Content *AliasContent::Clone() const
|
|
||||||
{
|
|
||||||
return 0; // TODO: how to clone an alias?
|
|
||||||
}
|
|
||||||
|
|
||||||
void AliasContent::Parse(Scanner * /*pScanner*/, ParserState& /*state*/)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void AliasContent::Write(Emitter&) const
|
|
||||||
{
|
|
||||||
// no content (just an alias)
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AliasContent::GetBegin(std::vector <Node *>::const_iterator& i) const
|
bool AliasContent::GetBegin(std::vector <Node *>::const_iterator& i) const
|
||||||
{
|
{
|
||||||
return m_pRef->GetBegin(i);
|
return m_pRef->GetBegin(i);
|
||||||
@@ -71,6 +56,11 @@ namespace YAML
|
|||||||
return m_pRef->GetScalar(scalar);
|
return m_pRef->GetScalar(scalar);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AliasContent::EmitEvents(AliasManager& am, EventHandler& eventHandler, const Mark& mark, const std::string& tag, anchor_t anchor) const
|
||||||
|
{
|
||||||
|
m_pRef->EmitEvents(am, eventHandler, mark, tag, anchor);
|
||||||
|
}
|
||||||
|
|
||||||
int AliasContent::Compare(Content *pContent)
|
int AliasContent::Compare(Content *pContent)
|
||||||
{
|
{
|
||||||
return m_pRef->Compare(pContent);
|
return m_pRef->Compare(pContent);
|
||||||
|
|||||||
+1
-5
@@ -13,11 +13,6 @@ namespace YAML
|
|||||||
public:
|
public:
|
||||||
AliasContent(Content *pNodeContent);
|
AliasContent(Content *pNodeContent);
|
||||||
|
|
||||||
virtual Content *Clone() const;
|
|
||||||
|
|
||||||
virtual void Parse(Scanner* pScanner, ParserState& state);
|
|
||||||
virtual void Write(Emitter&) const;
|
|
||||||
|
|
||||||
virtual bool GetBegin(std::vector <Node *>::const_iterator&) const;
|
virtual bool GetBegin(std::vector <Node *>::const_iterator&) const;
|
||||||
virtual bool GetBegin(std::map <Node *, Node *, ltnode>::const_iterator&) const;
|
virtual bool GetBegin(std::map <Node *, Node *, ltnode>::const_iterator&) const;
|
||||||
virtual bool GetEnd(std::vector <Node *>::const_iterator&) const;
|
virtual bool GetEnd(std::vector <Node *>::const_iterator&) const;
|
||||||
@@ -29,6 +24,7 @@ namespace YAML
|
|||||||
virtual bool IsSequence() const;
|
virtual bool IsSequence() const;
|
||||||
|
|
||||||
virtual bool GetScalar(std::string& s) const;
|
virtual bool GetScalar(std::string& s) const;
|
||||||
|
virtual void EmitEvents(AliasManager& am, EventHandler& eventHandler, const Mark& mark, const std::string& tag, anchor_t anchor) const;
|
||||||
|
|
||||||
virtual int Compare(Content *);
|
virtual int Compare(Content *);
|
||||||
virtual int Compare(Scalar *);
|
virtual int Compare(Scalar *);
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
#include "aliasmanager.h"
|
||||||
|
#include "node.h"
|
||||||
|
#include <cassert>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
namespace YAML
|
||||||
|
{
|
||||||
|
AliasManager::AliasManager(): m_curAnchor(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void AliasManager::RegisterReference(const Node& node)
|
||||||
|
{
|
||||||
|
const Node *pIdentity = node.Identity();
|
||||||
|
m_newIdentityByOldIdentity.insert(std::make_pair(pIdentity, &node));
|
||||||
|
m_anchorByIdentity.insert(std::make_pair(&node, _CreateNewAnchor()));
|
||||||
|
}
|
||||||
|
|
||||||
|
const Node *AliasManager::LookupReference(const Node& node) const
|
||||||
|
{
|
||||||
|
const Node *pIdentity = node.Identity();
|
||||||
|
return _LookupReference(*pIdentity);
|
||||||
|
}
|
||||||
|
|
||||||
|
anchor_t AliasManager::LookupAnchor(const Node& node) const
|
||||||
|
{
|
||||||
|
AnchorByIdentity::const_iterator it = m_anchorByIdentity.find(&node);
|
||||||
|
if(it == m_anchorByIdentity.end())
|
||||||
|
assert(false); // TODO: throw
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Node *AliasManager::_LookupReference(const Node& oldIdentity) const
|
||||||
|
{
|
||||||
|
NodeByNode::const_iterator it = m_newIdentityByOldIdentity.find(&oldIdentity);
|
||||||
|
if(it == m_newIdentityByOldIdentity.end())
|
||||||
|
return 0;
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
anchor_t AliasManager::_CreateNewAnchor()
|
||||||
|
{
|
||||||
|
return ++m_curAnchor;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef COLLECTIONSTACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
#define COLLECTIONSTACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
|
|
||||||
|
#include <stack>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
namespace YAML
|
||||||
|
{
|
||||||
|
struct CollectionType {
|
||||||
|
enum value { None, BlockMap, BlockSeq, FlowMap, FlowSeq, CompactMap };
|
||||||
|
};
|
||||||
|
|
||||||
|
class CollectionStack
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CollectionType::value GetCurCollectionType() const {
|
||||||
|
if(collectionStack.empty())
|
||||||
|
return CollectionType::None;
|
||||||
|
return collectionStack.top();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PushCollectionType(CollectionType::value type) { collectionStack.push(type); }
|
||||||
|
void PopCollectionType(CollectionType::value type) { assert(type == GetCurCollectionType()); collectionStack.pop(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::stack<CollectionType::value> collectionStack;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // COLLECTIONSTACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
#include "content.h"
|
||||||
|
#include "node.h"
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
namespace YAML
|
||||||
|
{
|
||||||
|
void Content::SetData(const std::string&)
|
||||||
|
{
|
||||||
|
assert(false); // TODO: throw
|
||||||
|
}
|
||||||
|
|
||||||
|
void Content::Append(std::auto_ptr<Node>)
|
||||||
|
{
|
||||||
|
assert(false); // TODO: throw
|
||||||
|
}
|
||||||
|
|
||||||
|
void Content::Insert(std::auto_ptr<Node>, std::auto_ptr<Node>)
|
||||||
|
{
|
||||||
|
assert(false); // TODO: throw
|
||||||
|
}
|
||||||
|
}
|
||||||
+15
-12
@@ -4,21 +4,24 @@
|
|||||||
#define CONTENT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#define CONTENT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
|
|
||||||
#include <vector>
|
#include "anchor.h"
|
||||||
#include <map>
|
|
||||||
#include "parserstate.h"
|
|
||||||
#include "exceptions.h"
|
#include "exceptions.h"
|
||||||
#include "ltnode.h"
|
#include "ltnode.h"
|
||||||
|
#include <map>
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML
|
||||||
{
|
{
|
||||||
class Scanner;
|
struct Mark;
|
||||||
class Parser;
|
struct NodeProperties;
|
||||||
|
class AliasManager;
|
||||||
|
class EventHandler;
|
||||||
|
class Map;
|
||||||
class Node;
|
class Node;
|
||||||
class Scalar;
|
class Scalar;
|
||||||
|
class Scanner;
|
||||||
class Sequence;
|
class Sequence;
|
||||||
class Map;
|
|
||||||
class Emitter;
|
|
||||||
|
|
||||||
class Content
|
class Content
|
||||||
{
|
{
|
||||||
@@ -26,11 +29,6 @@ namespace YAML
|
|||||||
Content() {}
|
Content() {}
|
||||||
virtual ~Content() {}
|
virtual ~Content() {}
|
||||||
|
|
||||||
virtual Content *Clone() const = 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; }
|
virtual bool GetBegin(std::vector <Node *>::const_iterator&) const { return false; }
|
||||||
virtual bool GetBegin(std::map <Node *, Node *, ltnode>::const_iterator&) const { return false; }
|
virtual bool GetBegin(std::map <Node *, Node *, ltnode>::const_iterator&) const { return false; }
|
||||||
virtual bool GetEnd(std::vector <Node *>::const_iterator&) const { return false; }
|
virtual bool GetEnd(std::vector <Node *>::const_iterator&) const { return false; }
|
||||||
@@ -41,6 +39,11 @@ namespace YAML
|
|||||||
virtual bool IsMap() const { return false; }
|
virtual bool IsMap() const { return false; }
|
||||||
virtual bool IsSequence() const { return false; }
|
virtual bool IsSequence() const { return false; }
|
||||||
|
|
||||||
|
virtual void SetData(const std::string& data);
|
||||||
|
virtual void Append(std::auto_ptr<Node> pNode);
|
||||||
|
virtual void Insert(std::auto_ptr<Node> pKey, std::auto_ptr<Node> pValue);
|
||||||
|
virtual void EmitEvents(AliasManager& am, EventHandler& eventHandler, const Mark& mark, const std::string& tag, anchor_t anchor) const = 0;
|
||||||
|
|
||||||
// extraction
|
// extraction
|
||||||
virtual bool GetScalar(std::string&) const { return false; }
|
virtual bool GetScalar(std::string&) const { return false; }
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
#include "parserstate.h"
|
#include "directives.h"
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML
|
||||||
{
|
{
|
||||||
ParserState::ParserState()
|
Directives::Directives()
|
||||||
{
|
{
|
||||||
// version
|
// version
|
||||||
version.isDefault = true;
|
version.isDefault = true;
|
||||||
@@ -10,7 +10,7 @@ namespace YAML
|
|||||||
version.minor = 2;
|
version.minor = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string ParserState::TranslateTagHandle(const std::string& handle) const
|
const std::string Directives::TranslateTagHandle(const std::string& handle) const
|
||||||
{
|
{
|
||||||
std::map <std::string, std::string>::const_iterator it = tags.find(handle);
|
std::map <std::string, std::string>::const_iterator it = tags.find(handle);
|
||||||
if(it == tags.end()) {
|
if(it == tags.end()) {
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef DIRECTIVES_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
#define DIRECTIVES_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
namespace YAML
|
||||||
|
{
|
||||||
|
struct Version {
|
||||||
|
bool isDefault;
|
||||||
|
int major, minor;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Directives {
|
||||||
|
Directives();
|
||||||
|
|
||||||
|
const std::string TranslateTagHandle(const std::string& handle) const;
|
||||||
|
|
||||||
|
Version version;
|
||||||
|
std::map<std::string, std::string> tags;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // DIRECTIVES_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
@@ -0,0 +1,106 @@
|
|||||||
|
#include "emitfromevents.h"
|
||||||
|
#include "emitter.h"
|
||||||
|
#include "null.h"
|
||||||
|
#include <cassert>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
std::string ToString(YAML::anchor_t anchor) {
|
||||||
|
std::stringstream stream;
|
||||||
|
stream << anchor;
|
||||||
|
return stream.str();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace YAML
|
||||||
|
{
|
||||||
|
EmitFromEvents::EmitFromEvents(Emitter& emitter): m_emitter(emitter)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitFromEvents::OnDocumentStart(const Mark&)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitFromEvents::OnDocumentEnd()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitFromEvents::OnNull(const std::string& tag, anchor_t anchor)
|
||||||
|
{
|
||||||
|
BeginNode();
|
||||||
|
EmitProps(tag, anchor);
|
||||||
|
if(tag.empty())
|
||||||
|
m_emitter << Null;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitFromEvents::OnAlias(const Mark&, anchor_t anchor)
|
||||||
|
{
|
||||||
|
BeginNode();
|
||||||
|
m_emitter << Alias(ToString(anchor));
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitFromEvents::OnScalar(const Mark&, const std::string& tag, anchor_t anchor, const std::string& value)
|
||||||
|
{
|
||||||
|
BeginNode();
|
||||||
|
EmitProps(tag, anchor);
|
||||||
|
m_emitter << value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitFromEvents::OnSequenceStart(const Mark&, const std::string& tag, anchor_t anchor)
|
||||||
|
{
|
||||||
|
BeginNode();
|
||||||
|
EmitProps(tag, anchor);
|
||||||
|
m_emitter << BeginSeq;
|
||||||
|
m_stateStack.push(State::WaitingForSequenceEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitFromEvents::OnSequenceEnd()
|
||||||
|
{
|
||||||
|
m_emitter << EndSeq;
|
||||||
|
assert(m_stateStack.top() == State::WaitingForSequenceEntry);
|
||||||
|
m_stateStack.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitFromEvents::OnMapStart(const Mark&, const std::string& tag, anchor_t anchor)
|
||||||
|
{
|
||||||
|
BeginNode();
|
||||||
|
EmitProps(tag, anchor);
|
||||||
|
m_emitter << BeginMap;
|
||||||
|
m_stateStack.push(State::WaitingForKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitFromEvents::OnMapEnd()
|
||||||
|
{
|
||||||
|
m_emitter << EndMap;
|
||||||
|
assert(m_stateStack.top() == State::WaitingForKey);
|
||||||
|
m_stateStack.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitFromEvents::BeginNode()
|
||||||
|
{
|
||||||
|
if(m_stateStack.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch(m_stateStack.top()) {
|
||||||
|
case State::WaitingForKey:
|
||||||
|
m_emitter << Key;
|
||||||
|
m_stateStack.top() = State::WaitingForValue;
|
||||||
|
break;
|
||||||
|
case State::WaitingForValue:
|
||||||
|
m_emitter << Value;
|
||||||
|
m_stateStack.top() = State::WaitingForKey;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitFromEvents::EmitProps(const std::string& tag, anchor_t anchor)
|
||||||
|
{
|
||||||
|
if(!tag.empty())
|
||||||
|
m_emitter << VerbatimTag(tag);
|
||||||
|
if(anchor)
|
||||||
|
m_emitter << Anchor(ToString(anchor));
|
||||||
|
}
|
||||||
|
}
|
||||||
+9
-156
@@ -1,9 +1,7 @@
|
|||||||
#include "map.h"
|
#include "map.h"
|
||||||
#include "node.h"
|
#include "node.h"
|
||||||
#include "scanner.h"
|
#include "eventhandler.h"
|
||||||
#include "token.h"
|
|
||||||
#include "exceptions.h"
|
#include "exceptions.h"
|
||||||
#include "emitter.h"
|
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML
|
||||||
{
|
{
|
||||||
@@ -11,15 +9,6 @@ namespace YAML
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Map::Map(const node_map& data)
|
|
||||||
{
|
|
||||||
for(node_map::const_iterator it=data.begin();it!=data.end();++it) {
|
|
||||||
std::auto_ptr<Node> pKey = it->first->Clone();
|
|
||||||
std::auto_ptr<Node> pValue = it->second->Clone();
|
|
||||||
AddEntry(pKey, pValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Map::~Map()
|
Map::~Map()
|
||||||
{
|
{
|
||||||
Clear();
|
Clear();
|
||||||
@@ -34,11 +23,6 @@ namespace YAML
|
|||||||
m_data.clear();
|
m_data.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
Content *Map::Clone() const
|
|
||||||
{
|
|
||||||
return new Map(m_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Map::GetBegin(std::map <Node *, Node *, ltnode>::const_iterator& it) const
|
bool Map::GetBegin(std::map <Node *, Node *, ltnode>::const_iterator& it) const
|
||||||
{
|
{
|
||||||
it = m_data.begin();
|
it = m_data.begin();
|
||||||
@@ -56,140 +40,7 @@ namespace YAML
|
|||||||
return m_data.size();
|
return m_data.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Map::Parse(Scanner *pScanner, ParserState& state)
|
void Map::Insert(std::auto_ptr<Node> pKey, std::auto_ptr<Node> pValue)
|
||||||
{
|
|
||||||
Clear();
|
|
||||||
|
|
||||||
// split based on start token
|
|
||||||
switch(pScanner->peek().type) {
|
|
||||||
case Token::BLOCK_MAP_START: ParseBlock(pScanner, state); break;
|
|
||||||
case Token::FLOW_MAP_START: ParseFlow(pScanner, state); break;
|
|
||||||
case Token::KEY: ParseCompact(pScanner, state); break;
|
|
||||||
case Token::VALUE: ParseCompactWithNoKey(pScanner, state); break;
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Map::ParseBlock(Scanner *pScanner, ParserState& state)
|
|
||||||
{
|
|
||||||
// eat start token
|
|
||||||
pScanner->pop();
|
|
||||||
state.PushCollectionType(ParserState::BLOCK_MAP);
|
|
||||||
|
|
||||||
while(1) {
|
|
||||||
if(pScanner->empty())
|
|
||||||
throw ParserException(Mark::null(), ErrorMsg::END_OF_MAP);
|
|
||||||
|
|
||||||
Token token = pScanner->peek();
|
|
||||||
if(token.type != Token::KEY && token.type != Token::VALUE && token.type != Token::BLOCK_MAP_END)
|
|
||||||
throw ParserException(token.mark, ErrorMsg::END_OF_MAP);
|
|
||||||
|
|
||||||
if(token.type == Token::BLOCK_MAP_END) {
|
|
||||||
pScanner->pop();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::auto_ptr <Node> pKey(new Node), pValue(new Node);
|
|
||||||
|
|
||||||
// grab key (if non-null)
|
|
||||||
if(token.type == Token::KEY) {
|
|
||||||
pScanner->pop();
|
|
||||||
pKey->Parse(pScanner, state);
|
|
||||||
}
|
|
||||||
|
|
||||||
// now grab value (optional)
|
|
||||||
if(!pScanner->empty() && pScanner->peek().type == Token::VALUE) {
|
|
||||||
pScanner->pop();
|
|
||||||
pValue->Parse(pScanner, state);
|
|
||||||
}
|
|
||||||
|
|
||||||
AddEntry(pKey, pValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
state.PopCollectionType(ParserState::BLOCK_MAP);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Map::ParseFlow(Scanner *pScanner, ParserState& state)
|
|
||||||
{
|
|
||||||
// eat start token
|
|
||||||
pScanner->pop();
|
|
||||||
state.PushCollectionType(ParserState::FLOW_MAP);
|
|
||||||
|
|
||||||
while(1) {
|
|
||||||
if(pScanner->empty())
|
|
||||||
throw ParserException(Mark::null(), ErrorMsg::END_OF_MAP_FLOW);
|
|
||||||
|
|
||||||
Token& token = pScanner->peek();
|
|
||||||
// first check for end
|
|
||||||
if(token.type == Token::FLOW_MAP_END) {
|
|
||||||
pScanner->pop();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::auto_ptr <Node> pKey(new Node), pValue(new Node);
|
|
||||||
|
|
||||||
// grab key (if non-null)
|
|
||||||
if(token.type == Token::KEY) {
|
|
||||||
pScanner->pop();
|
|
||||||
pKey->Parse(pScanner, state);
|
|
||||||
}
|
|
||||||
|
|
||||||
// now grab value (optional)
|
|
||||||
if(!pScanner->empty() && pScanner->peek().type == Token::VALUE) {
|
|
||||||
pScanner->pop();
|
|
||||||
pValue->Parse(pScanner, state);
|
|
||||||
}
|
|
||||||
|
|
||||||
// now eat the separator (or could be a map end, which we ignore - but if it's neither, then it's a bad node)
|
|
||||||
Token& nextToken = pScanner->peek();
|
|
||||||
if(nextToken.type == Token::FLOW_ENTRY)
|
|
||||||
pScanner->pop();
|
|
||||||
else if(nextToken.type != Token::FLOW_MAP_END)
|
|
||||||
throw ParserException(nextToken.mark, ErrorMsg::END_OF_MAP_FLOW);
|
|
||||||
|
|
||||||
AddEntry(pKey, pValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
state.PopCollectionType(ParserState::FLOW_MAP);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParseCompact
|
|
||||||
// . Single "key: value" pair in a flow sequence
|
|
||||||
void Map::ParseCompact(Scanner *pScanner, ParserState& state)
|
|
||||||
{
|
|
||||||
state.PushCollectionType(ParserState::COMPACT_MAP);
|
|
||||||
std::auto_ptr <Node> pKey(new Node), pValue(new Node);
|
|
||||||
|
|
||||||
// grab key
|
|
||||||
pScanner->pop();
|
|
||||||
pKey->Parse(pScanner, state);
|
|
||||||
|
|
||||||
// now grab value (optional)
|
|
||||||
if(!pScanner->empty() && pScanner->peek().type == Token::VALUE) {
|
|
||||||
pScanner->pop();
|
|
||||||
pValue->Parse(pScanner, state);
|
|
||||||
}
|
|
||||||
|
|
||||||
AddEntry(pKey, pValue);
|
|
||||||
state.PopCollectionType(ParserState::COMPACT_MAP);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParseCompactWithNoKey
|
|
||||||
// . Single ": value" pair in a flow sequence
|
|
||||||
void Map::ParseCompactWithNoKey(Scanner *pScanner, ParserState& state)
|
|
||||||
{
|
|
||||||
state.PushCollectionType(ParserState::COMPACT_MAP);
|
|
||||||
std::auto_ptr <Node> pKey(new Node), pValue(new Node);
|
|
||||||
|
|
||||||
// grab value
|
|
||||||
pScanner->pop();
|
|
||||||
pValue->Parse(pScanner, state);
|
|
||||||
|
|
||||||
AddEntry(pKey, pValue);
|
|
||||||
state.PopCollectionType(ParserState::COMPACT_MAP);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Map::AddEntry(std::auto_ptr<Node> pKey, std::auto_ptr<Node> pValue)
|
|
||||||
{
|
{
|
||||||
node_map::const_iterator it = m_data.find(pKey.get());
|
node_map::const_iterator it = m_data.find(pKey.get());
|
||||||
if(it != m_data.end())
|
if(it != m_data.end())
|
||||||
@@ -198,12 +49,14 @@ namespace YAML
|
|||||||
m_data[pKey.release()] = pValue.release();
|
m_data[pKey.release()] = pValue.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Map::Write(Emitter& out) const
|
void Map::EmitEvents(AliasManager& am, EventHandler& eventHandler, const Mark& mark, const std::string& tag, anchor_t anchor) const
|
||||||
{
|
{
|
||||||
out << BeginMap;
|
eventHandler.OnMapStart(mark, tag, anchor);
|
||||||
for(node_map::const_iterator it=m_data.begin();it!=m_data.end();++it)
|
for(node_map::const_iterator it=m_data.begin();it!=m_data.end();++it) {
|
||||||
out << Key << *it->first << Value << *it->second;
|
it->first->EmitEvents(am, eventHandler);
|
||||||
out << EndMap;
|
it->second->EmitEvents(am, eventHandler);
|
||||||
|
}
|
||||||
|
eventHandler.OnMapEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
int Map::Compare(Content *pContent)
|
int Map::Compare(Content *pContent)
|
||||||
|
|||||||
@@ -19,17 +19,16 @@ namespace YAML
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
Map();
|
Map();
|
||||||
Map(const node_map& data);
|
|
||||||
virtual ~Map();
|
virtual ~Map();
|
||||||
|
|
||||||
void Clear();
|
void Clear();
|
||||||
virtual Content *Clone() const;
|
|
||||||
|
|
||||||
virtual bool GetBegin(std::map <Node *, Node *, ltnode>::const_iterator& it) const;
|
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 bool GetEnd(std::map <Node *, Node *, ltnode>::const_iterator& it) const;
|
||||||
virtual std::size_t GetSize() const;
|
virtual std::size_t GetSize() const;
|
||||||
virtual void Parse(Scanner *pScanner, ParserState& state);
|
|
||||||
virtual void Write(Emitter& out) const;
|
virtual void Insert(std::auto_ptr<Node> pKey, std::auto_ptr<Node> pValue);
|
||||||
|
virtual void EmitEvents(AliasManager& am, EventHandler& eventHandler, const Mark& mark, const std::string& tag, anchor_t anchor) const;
|
||||||
|
|
||||||
virtual bool IsMap() const { return true; }
|
virtual bool IsMap() const { return true; }
|
||||||
|
|
||||||
@@ -39,14 +38,6 @@ namespace YAML
|
|||||||
virtual int Compare(Sequence *) { return 1; }
|
virtual int Compare(Sequence *) { return 1; }
|
||||||
virtual int Compare(Map *pMap);
|
virtual int Compare(Map *pMap);
|
||||||
|
|
||||||
private:
|
|
||||||
void ParseBlock(Scanner *pScanner, ParserState& state);
|
|
||||||
void ParseFlow(Scanner *pScanner, ParserState& state);
|
|
||||||
void ParseCompact(Scanner *pScanner, ParserState& state);
|
|
||||||
void ParseCompactWithNoKey(Scanner *pScanner, ParserState& state);
|
|
||||||
|
|
||||||
void AddEntry(std::auto_ptr<Node> pKey, std::auto_ptr<Node> pValue);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
node_map m_data;
|
node_map m_data;
|
||||||
};
|
};
|
||||||
|
|||||||
+87
-148
@@ -1,15 +1,20 @@
|
|||||||
#include "node.h"
|
#include "node.h"
|
||||||
#include "token.h"
|
|
||||||
#include "scanner.h"
|
|
||||||
#include "content.h"
|
|
||||||
#include "parser.h"
|
|
||||||
#include "scalar.h"
|
|
||||||
#include "sequence.h"
|
|
||||||
#include "map.h"
|
|
||||||
#include "aliascontent.h"
|
#include "aliascontent.h"
|
||||||
#include "iterpriv.h"
|
#include "aliasmanager.h"
|
||||||
|
#include "content.h"
|
||||||
|
#include "emitfromevents.h"
|
||||||
#include "emitter.h"
|
#include "emitter.h"
|
||||||
|
#include "eventhandler.h"
|
||||||
|
#include "iterpriv.h"
|
||||||
|
#include "map.h"
|
||||||
|
#include "nodebuilder.h"
|
||||||
|
#include "nodeproperties.h"
|
||||||
|
#include "scalar.h"
|
||||||
|
#include "scanner.h"
|
||||||
|
#include "sequence.h"
|
||||||
#include "tag.h"
|
#include "tag.h"
|
||||||
|
#include "token.h"
|
||||||
|
#include <cassert>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML
|
||||||
@@ -20,17 +25,10 @@ namespace YAML
|
|||||||
return *pNode1 < *pNode2;
|
return *pNode1 < *pNode2;
|
||||||
}
|
}
|
||||||
|
|
||||||
Node::Node(): m_pContent(0), m_alias(false), m_pIdentity(this), m_referenced(true)
|
Node::Node(): m_type(CT_NONE), m_pContent(0), m_alias(false), m_pIdentity(this), m_referenced(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Node::Node(const Mark& mark, const std::string& anchor, const std::string& tag, const Content *pContent)
|
|
||||||
: m_mark(mark), m_anchor(anchor), m_tag(tag), m_pContent(0), m_alias(false), m_pIdentity(this), m_referenced(false)
|
|
||||||
{
|
|
||||||
if(pContent)
|
|
||||||
m_pContent = pContent->Clone();
|
|
||||||
}
|
|
||||||
|
|
||||||
Node::~Node()
|
Node::~Node()
|
||||||
{
|
{
|
||||||
Clear();
|
Clear();
|
||||||
@@ -39,156 +37,112 @@ namespace YAML
|
|||||||
void Node::Clear()
|
void Node::Clear()
|
||||||
{
|
{
|
||||||
delete m_pContent;
|
delete m_pContent;
|
||||||
|
m_type = CT_NONE;
|
||||||
m_pContent = 0;
|
m_pContent = 0;
|
||||||
m_alias = false;
|
m_alias = false;
|
||||||
m_referenced = false;
|
m_referenced = false;
|
||||||
m_anchor.clear();
|
|
||||||
m_tag.clear();
|
m_tag.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::auto_ptr<Node> Node::Clone() const
|
std::auto_ptr<Node> Node::Clone() const
|
||||||
{
|
{
|
||||||
if(m_alias)
|
std::auto_ptr<Node> pNode(new Node);
|
||||||
throw std::runtime_error("yaml-cpp: Can't clone alias"); // TODO: what to do about aliases?
|
NodeBuilder nodeBuilder(*pNode);
|
||||||
|
EmitEvents(nodeBuilder);
|
||||||
return std::auto_ptr<Node> (new Node(m_mark, m_anchor, m_tag, m_pContent));
|
return pNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Node::Parse(Scanner *pScanner, ParserState& state)
|
void Node::EmitEvents(EventHandler& eventHandler) const
|
||||||
|
{
|
||||||
|
eventHandler.OnDocumentStart(m_mark);
|
||||||
|
AliasManager am;
|
||||||
|
EmitEvents(am, eventHandler);
|
||||||
|
eventHandler.OnDocumentEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Node::EmitEvents(AliasManager& am, EventHandler& eventHandler) const
|
||||||
|
{
|
||||||
|
anchor_t anchor = NullAnchor;
|
||||||
|
if(m_referenced || m_alias) {
|
||||||
|
if(const Node *pOther = am.LookupReference(*this)) {
|
||||||
|
eventHandler.OnAlias(m_mark, am.LookupAnchor(*pOther));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
am.RegisterReference(*this);
|
||||||
|
anchor = am.LookupAnchor(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(m_pContent)
|
||||||
|
m_pContent->EmitEvents(am, eventHandler, m_mark, GetTag(), anchor);
|
||||||
|
else
|
||||||
|
eventHandler.OnNull(GetTag(), anchor);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Node::Init(CONTENT_TYPE type, const Mark& mark, const std::string& tag)
|
||||||
{
|
{
|
||||||
Clear();
|
Clear();
|
||||||
|
m_mark = mark;
|
||||||
|
m_type = type;
|
||||||
|
m_tag = tag;
|
||||||
|
m_alias = false;
|
||||||
|
m_pIdentity = this;
|
||||||
|
m_referenced = false;
|
||||||
|
|
||||||
// an empty node *is* a possibility
|
switch(type) {
|
||||||
if(pScanner->empty())
|
case CT_SCALAR:
|
||||||
return;
|
|
||||||
|
|
||||||
// save location
|
|
||||||
m_mark = pScanner->peek().mark;
|
|
||||||
|
|
||||||
// special case: a value node by itself must be a map, with no header
|
|
||||||
if(pScanner->peek().type == Token::VALUE) {
|
|
||||||
m_pContent = new Map;
|
|
||||||
m_pContent->Parse(pScanner, state);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ParseHeader(pScanner, state);
|
|
||||||
|
|
||||||
// is this an alias? if so, its contents are an alias to
|
|
||||||
// a previously defined anchor
|
|
||||||
if(m_alias) {
|
|
||||||
// the scanner throws an exception if it doesn't know this anchor name
|
|
||||||
const Node *pReferencedNode = pScanner->Retrieve(m_anchor);
|
|
||||||
m_pIdentity = pReferencedNode;
|
|
||||||
|
|
||||||
// mark the referenced node for the sake of the client code
|
|
||||||
pReferencedNode->m_referenced = true;
|
|
||||||
|
|
||||||
// use of an Alias object keeps the referenced content from
|
|
||||||
// being deleted twice
|
|
||||||
Content *pAliasedContent = pReferencedNode->m_pContent;
|
|
||||||
if(pAliasedContent)
|
|
||||||
m_pContent = new AliasContent(pAliasedContent);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// now split based on what kind of node we should be
|
|
||||||
switch(pScanner->peek().type) {
|
|
||||||
case Token::SCALAR:
|
|
||||||
m_pContent = new Scalar;
|
m_pContent = new Scalar;
|
||||||
break;
|
break;
|
||||||
case Token::FLOW_SEQ_START:
|
case CT_SEQUENCE:
|
||||||
case Token::BLOCK_SEQ_START:
|
|
||||||
m_pContent = new Sequence;
|
m_pContent = new Sequence;
|
||||||
break;
|
break;
|
||||||
case Token::FLOW_MAP_START:
|
case CT_MAP:
|
||||||
case Token::BLOCK_MAP_START:
|
|
||||||
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;
|
m_pContent = new Map;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
m_pContent = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Have to save anchor before parsing to allow for aliases as
|
|
||||||
// contained node (recursive structure)
|
|
||||||
if(!m_anchor.empty())
|
|
||||||
pScanner->Save(m_anchor, this);
|
|
||||||
|
|
||||||
if(m_pContent)
|
|
||||||
m_pContent->Parse(pScanner, state);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseHeader
|
void Node::InitNull(const std::string& tag)
|
||||||
// . Grabs any tag, alias, or anchor tokens and deals with them.
|
|
||||||
void Node::ParseHeader(Scanner *pScanner, ParserState& state)
|
|
||||||
{
|
{
|
||||||
while(1) {
|
Clear();
|
||||||
if(pScanner->empty())
|
m_tag = tag;
|
||||||
return;
|
|
||||||
|
|
||||||
switch(pScanner->peek().type) {
|
|
||||||
case Token::TAG: ParseTag(pScanner, state); break;
|
|
||||||
case Token::ANCHOR: ParseAnchor(pScanner, state); break;
|
|
||||||
case Token::ALIAS: ParseAlias(pScanner, state); break;
|
|
||||||
default: return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Node::ParseTag(Scanner *pScanner, ParserState& state)
|
|
||||||
{
|
|
||||||
Token& token = pScanner->peek();
|
|
||||||
if(m_tag != "")
|
|
||||||
throw ParserException(token.mark, ErrorMsg::MULTIPLE_TAGS);
|
|
||||||
|
|
||||||
Tag tag(token);
|
|
||||||
m_tag = tag.Translate(state);
|
|
||||||
pScanner->pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Node::ParseAnchor(Scanner *pScanner, ParserState& /*state*/)
|
|
||||||
{
|
|
||||||
Token& token = pScanner->peek();
|
|
||||||
if(m_anchor != "")
|
|
||||||
throw ParserException(token.mark, ErrorMsg::MULTIPLE_ANCHORS);
|
|
||||||
|
|
||||||
m_anchor = token.value;
|
|
||||||
m_alias = false;
|
m_alias = false;
|
||||||
pScanner->pop();
|
m_pIdentity = this;
|
||||||
|
m_referenced = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Node::ParseAlias(Scanner *pScanner, ParserState& /*state*/)
|
void Node::InitAlias(const Mark& mark, const Node& identity)
|
||||||
{
|
{
|
||||||
Token& token = pScanner->peek();
|
Clear();
|
||||||
if(m_anchor != "")
|
m_mark = mark;
|
||||||
throw ParserException(token.mark, ErrorMsg::MULTIPLE_ALIASES);
|
|
||||||
if(m_tag != "")
|
|
||||||
throw ParserException(token.mark, ErrorMsg::ALIAS_CONTENT);
|
|
||||||
|
|
||||||
m_anchor = token.value;
|
|
||||||
m_alias = true;
|
m_alias = true;
|
||||||
pScanner->pop();
|
m_pIdentity = &identity;
|
||||||
|
if(identity.m_pContent) {
|
||||||
|
m_pContent = new AliasContent(identity.m_pContent);
|
||||||
|
m_type = identity.GetType();
|
||||||
|
}
|
||||||
|
identity.m_referenced = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
CONTENT_TYPE Node::GetType() const
|
void Node::SetData(const std::string& data)
|
||||||
{
|
{
|
||||||
if(!m_pContent)
|
assert(m_pContent); // TODO: throw
|
||||||
return CT_NONE;
|
m_pContent->SetData(data);
|
||||||
|
}
|
||||||
|
|
||||||
if(m_pContent->IsScalar())
|
void Node::Append(std::auto_ptr<Node> pNode)
|
||||||
return CT_SCALAR;
|
{
|
||||||
else if(m_pContent->IsSequence())
|
assert(m_pContent); // TODO: throw
|
||||||
return CT_SEQUENCE;
|
m_pContent->Append(pNode);
|
||||||
else if(m_pContent->IsMap())
|
}
|
||||||
return CT_MAP;
|
|
||||||
|
|
||||||
return CT_NONE;
|
void Node::Insert(std::auto_ptr<Node> pKey, std::auto_ptr<Node> pValue)
|
||||||
|
{
|
||||||
|
assert(m_pContent); // TODO: throw
|
||||||
|
m_pContent->Insert(pKey, pValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
// begin
|
// begin
|
||||||
@@ -261,23 +215,8 @@ namespace YAML
|
|||||||
|
|
||||||
Emitter& operator << (Emitter& out, const Node& node)
|
Emitter& operator << (Emitter& out, const Node& node)
|
||||||
{
|
{
|
||||||
// write anchor/alias
|
EmitFromEvents emitFromEvents(out);
|
||||||
if(node.m_anchor != "") {
|
node.EmitEvents(emitFromEvents);
|
||||||
if(node.m_alias)
|
|
||||||
out << Alias(node.m_anchor);
|
|
||||||
else
|
|
||||||
out << Anchor(node.m_anchor);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(node.m_tag != "")
|
|
||||||
out << VerbatimTag(node.m_tag);
|
|
||||||
|
|
||||||
// write content
|
|
||||||
if(node.m_pContent)
|
|
||||||
node.m_pContent->Write(out);
|
|
||||||
else if(!node.m_alias)
|
|
||||||
out << Null;
|
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,142 @@
|
|||||||
|
#include "nodebuilder.h"
|
||||||
|
#include "mark.h"
|
||||||
|
#include "node.h"
|
||||||
|
#include "nodeproperties.h"
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
namespace YAML
|
||||||
|
{
|
||||||
|
NodeBuilder::NodeBuilder(Node& root): m_root(root), m_initializedRoot(false), m_finished(false)
|
||||||
|
{
|
||||||
|
m_root.Clear();
|
||||||
|
m_anchors.push_back(0); // since the anchors start at 1
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeBuilder::~NodeBuilder()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void NodeBuilder::OnDocumentStart(const Mark&)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void NodeBuilder::OnDocumentEnd()
|
||||||
|
{
|
||||||
|
assert(m_finished);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NodeBuilder::OnNull(const std::string& tag, anchor_t anchor)
|
||||||
|
{
|
||||||
|
Node& node = Push(anchor);
|
||||||
|
node.InitNull(tag);
|
||||||
|
Pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void NodeBuilder::OnAlias(const Mark& mark, anchor_t anchor)
|
||||||
|
{
|
||||||
|
Node& node = Push();
|
||||||
|
node.InitAlias(mark, *m_anchors[anchor]);
|
||||||
|
Pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void NodeBuilder::OnScalar(const Mark& mark, const std::string& tag, anchor_t anchor, const std::string& value)
|
||||||
|
{
|
||||||
|
Node& node = Push(anchor);
|
||||||
|
node.Init(CT_SCALAR, mark, tag);
|
||||||
|
node.SetData(value);
|
||||||
|
Pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void NodeBuilder::OnSequenceStart(const Mark& mark, const std::string& tag, anchor_t anchor)
|
||||||
|
{
|
||||||
|
Node& node = Push(anchor);
|
||||||
|
node.Init(CT_SEQUENCE, mark, tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NodeBuilder::OnSequenceEnd()
|
||||||
|
{
|
||||||
|
Pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void NodeBuilder::OnMapStart(const Mark& mark, const std::string& tag, anchor_t anchor)
|
||||||
|
{
|
||||||
|
Node& node = Push(anchor);
|
||||||
|
node.Init(CT_MAP, mark, tag);
|
||||||
|
m_didPushKey.push(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NodeBuilder::OnMapEnd()
|
||||||
|
{
|
||||||
|
m_didPushKey.pop();
|
||||||
|
Pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
Node& NodeBuilder::Push(anchor_t anchor)
|
||||||
|
{
|
||||||
|
Node& node = Push();
|
||||||
|
RegisterAnchor(anchor, node);
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
Node& NodeBuilder::Push()
|
||||||
|
{
|
||||||
|
if(!m_initializedRoot) {
|
||||||
|
m_initializedRoot = true;
|
||||||
|
return m_root;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::auto_ptr<Node> pNode(new Node);
|
||||||
|
m_stack.push(pNode);
|
||||||
|
return m_stack.top();
|
||||||
|
}
|
||||||
|
|
||||||
|
Node& NodeBuilder::Top()
|
||||||
|
{
|
||||||
|
return m_stack.empty() ? m_root : m_stack.top();
|
||||||
|
}
|
||||||
|
|
||||||
|
void NodeBuilder::Pop()
|
||||||
|
{
|
||||||
|
assert(!m_finished);
|
||||||
|
if(m_stack.empty()) {
|
||||||
|
m_finished = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::auto_ptr<Node> pNode = m_stack.pop();
|
||||||
|
Insert(pNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NodeBuilder::Insert(std::auto_ptr<Node> pNode)
|
||||||
|
{
|
||||||
|
Node& node = Top();
|
||||||
|
switch(node.GetType()) {
|
||||||
|
case CT_SEQUENCE:
|
||||||
|
node.Append(pNode);
|
||||||
|
break;
|
||||||
|
case CT_MAP:
|
||||||
|
assert(!m_didPushKey.empty());
|
||||||
|
if(m_didPushKey.top()) {
|
||||||
|
assert(!m_pendingKeys.empty());
|
||||||
|
|
||||||
|
std::auto_ptr<Node> pKey = m_pendingKeys.pop();
|
||||||
|
node.Insert(pKey, pNode);
|
||||||
|
m_didPushKey.top() = false;
|
||||||
|
} else {
|
||||||
|
m_pendingKeys.push(pNode);
|
||||||
|
m_didPushKey.top() = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void NodeBuilder::RegisterAnchor(anchor_t anchor, const Node& node)
|
||||||
|
{
|
||||||
|
if(anchor) {
|
||||||
|
assert(anchor == m_anchors.size());
|
||||||
|
m_anchors.push_back(&node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user