|
@@ -0,0 +1,149 @@
|
|
|
+#ifndef GRAPHBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
|
|
+#define GRAPHBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
|
|
+
|
|
|
+#if defined(_MSC_VER) || \
|
|
|
+ (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
|
|
+ (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
|
|
+#pragma once
|
|
|
+#endif
|
|
|
+
|
|
|
+#include "yaml-cpp/mark.h"
|
|
|
+#include <string>
|
|
|
+
|
|
|
+namespace YAML {
|
|
|
+class Parser;
|
|
|
+
|
|
|
+// GraphBuilderInterface
|
|
|
+// . Abstraction of node creation
|
|
|
+// . pParentNode is always nullptr or the return value of one of the NewXXX()
|
|
|
+// functions.
|
|
|
+class GraphBuilderInterface {
|
|
|
+ public:
|
|
|
+ virtual ~GraphBuilderInterface() = 0;
|
|
|
+
|
|
|
+ // Create and return a new node with a null value.
|
|
|
+ virtual void *NewNull(const Mark &mark, void *pParentNode) = 0;
|
|
|
+
|
|
|
+ // Create and return a new node with the given tag and value.
|
|
|
+ virtual void *NewScalar(const Mark &mark, const std::string &tag,
|
|
|
+ void *pParentNode, const std::string &value) = 0;
|
|
|
+
|
|
|
+ // Create and return a new sequence node
|
|
|
+ virtual void *NewSequence(const Mark &mark, const std::string &tag,
|
|
|
+ void *pParentNode) = 0;
|
|
|
+
|
|
|
+ // Add pNode to pSequence. pNode was created with one of the NewXxx()
|
|
|
+ // functions and pSequence with NewSequence().
|
|
|
+ virtual void AppendToSequence(void *pSequence, void *pNode) = 0;
|
|
|
+
|
|
|
+ // Note that no moew entries will be added to pSequence
|
|
|
+ virtual void SequenceComplete(void *pSequence) { (void)pSequence; }
|
|
|
+
|
|
|
+ // Create and return a new map node
|
|
|
+ virtual void *NewMap(const Mark &mark, const std::string &tag,
|
|
|
+ void *pParentNode) = 0;
|
|
|
+
|
|
|
+ // Add the pKeyNode => pValueNode mapping to pMap. pKeyNode and pValueNode
|
|
|
+ // were created with one of the NewXxx() methods and pMap with NewMap().
|
|
|
+ virtual void AssignInMap(void *pMap, void *pKeyNode, void *pValueNode) = 0;
|
|
|
+
|
|
|
+ // Note that no more assignments will be made in pMap
|
|
|
+ virtual void MapComplete(void *pMap) { (void)pMap; }
|
|
|
+
|
|
|
+ // Return the node that should be used in place of an alias referencing
|
|
|
+ // pNode (pNode by default)
|
|
|
+ virtual void *AnchorReference(const Mark &mark, void *pNode) {
|
|
|
+ (void)mark;
|
|
|
+ return pNode;
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+// Typesafe wrapper for GraphBuilderInterface. Assumes that Impl defines
|
|
|
+// Node, Sequence, and Map types. Sequence and Map must derive from Node
|
|
|
+// (unless Node is defined as void). Impl must also implement function with
|
|
|
+// all of the same names as the virtual functions in GraphBuilderInterface
|
|
|
+// -- including the ones with default implementations -- but with the
|
|
|
+// prototypes changed to accept an explicit Node*, Sequence*, or Map* where
|
|
|
+// appropriate.
|
|
|
+template <class Impl>
|
|
|
+class GraphBuilder : public GraphBuilderInterface {
|
|
|
+ public:
|
|
|
+ typedef typename Impl::Node Node;
|
|
|
+ typedef typename Impl::Sequence Sequence;
|
|
|
+ typedef typename Impl::Map Map;
|
|
|
+
|
|
|
+ GraphBuilder(Impl &impl) : m_impl(impl) {
|
|
|
+ Map *pMap = nullptr;
|
|
|
+ Sequence *pSeq = nullptr;
|
|
|
+ Node *pNode = nullptr;
|
|
|
+
|
|
|
+ // Type consistency checks
|
|
|
+ pNode = pMap;
|
|
|
+ pNode = pSeq;
|
|
|
+ }
|
|
|
+
|
|
|
+ GraphBuilderInterface &AsBuilderInterface() { return *this; }
|
|
|
+
|
|
|
+ virtual void *NewNull(const Mark &mark, void *pParentNode) {
|
|
|
+ return CheckType<Node>(m_impl.NewNull(mark, AsNode(pParentNode)));
|
|
|
+ }
|
|
|
+
|
|
|
+ virtual void *NewScalar(const Mark &mark, const std::string &tag,
|
|
|
+ void *pParentNode, const std::string &value) {
|
|
|
+ return CheckType<Node>(
|
|
|
+ m_impl.NewScalar(mark, tag, AsNode(pParentNode), value));
|
|
|
+ }
|
|
|
+
|
|
|
+ virtual void *NewSequence(const Mark &mark, const std::string &tag,
|
|
|
+ void *pParentNode) {
|
|
|
+ return CheckType<Sequence>(
|
|
|
+ m_impl.NewSequence(mark, tag, AsNode(pParentNode)));
|
|
|
+ }
|
|
|
+ virtual void AppendToSequence(void *pSequence, void *pNode) {
|
|
|
+ m_impl.AppendToSequence(AsSequence(pSequence), AsNode(pNode));
|
|
|
+ }
|
|
|
+ virtual void SequenceComplete(void *pSequence) {
|
|
|
+ m_impl.SequenceComplete(AsSequence(pSequence));
|
|
|
+ }
|
|
|
+
|
|
|
+ virtual void *NewMap(const Mark &mark, const std::string &tag,
|
|
|
+ void *pParentNode) {
|
|
|
+ return CheckType<Map>(m_impl.NewMap(mark, tag, AsNode(pParentNode)));
|
|
|
+ }
|
|
|
+ virtual void AssignInMap(void *pMap, void *pKeyNode, void *pValueNode) {
|
|
|
+ m_impl.AssignInMap(AsMap(pMap), AsNode(pKeyNode), AsNode(pValueNode));
|
|
|
+ }
|
|
|
+ virtual void MapComplete(void *pMap) { m_impl.MapComplete(AsMap(pMap)); }
|
|
|
+
|
|
|
+ virtual void *AnchorReference(const Mark &mark, void *pNode) {
|
|
|
+ return CheckType<Node>(m_impl.AnchorReference(mark, AsNode(pNode)));
|
|
|
+ }
|
|
|
+
|
|
|
+ private:
|
|
|
+ Impl &m_impl;
|
|
|
+
|
|
|
+ // Static check for pointer to T
|
|
|
+ template <class T, class U>
|
|
|
+ static T *CheckType(U *p) {
|
|
|
+ return p;
|
|
|
+ }
|
|
|
+
|
|
|
+ static Node *AsNode(void *pNode) { return static_cast<Node *>(pNode); }
|
|
|
+ static Sequence *AsSequence(void *pSeq) {
|
|
|
+ return static_cast<Sequence *>(pSeq);
|
|
|
+ }
|
|
|
+ static Map *AsMap(void *pMap) { return static_cast<Map *>(pMap); }
|
|
|
+};
|
|
|
+
|
|
|
+void *BuildGraphOfNextDocument(Parser &parser,
|
|
|
+ GraphBuilderInterface &graphBuilder);
|
|
|
+
|
|
|
+template <class Impl>
|
|
|
+typename Impl::Node *BuildGraphOfNextDocument(Parser &parser, Impl &impl) {
|
|
|
+ GraphBuilder<Impl> graphBuilder(impl);
|
|
|
+ return static_cast<typename Impl::Node *>(
|
|
|
+ BuildGraphOfNextDocument(parser, graphBuilder));
|
|
|
+}
|
|
|
+}
|
|
|
+
|
|
|
+#endif // GRAPHBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|