summaryrefslogtreecommitdiffstats
path: root/yaml-cpp/include/yaml-cpp/contrib/graphbuilder.h
blob: 6739a12b5cc1b3d0520906eef643b6e8c0b123a2 (plain)
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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#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 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 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 = NULL;
      Sequence* pSeq = NULL;
      Node* pNode = NULL;
      
      // 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