graphbuilder.h 4.57 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#ifndef GRAPHBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define GRAPHBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66

#include <string>

namespace YAML
{
  struct Mark;
  
  // GraphBuilderInterface
  // . Abstraction of node creation
  // . pParentNode is always NULL or the return value of one of the NewXXX()
  //   functions.
  class GraphBuilderInterface
  {
  public:
    // Create and return a new node with a null value.
    virtual void *NewNull(const std::string& tag, 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 = NULL;
      Sequence* pSeq = NULL;
      Node* pNode = NULL;
      
      // Type consistency checks
      pNode = pMap;
      pNode = pSeq;
    }
    
    GraphBuilderInterface& AsBuilderInterface() {return *this;}
    
    virtual void *NewNull(const std::string& tag, void* pParentNode) {
      return CheckType<Node>(m_impl.NewNull(tag, 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);}
  };
}

#endif // GRAPHBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66