150 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			150 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| 
								 | 
							
								#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
							 |