| #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 |