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