use yaml for messages
This commit is contained in:
		
							
								
								
									
										93
									
								
								libs/yaml-cpp/src/aliascontent.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										93
									
								
								libs/yaml-cpp/src/aliascontent.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,93 @@
 | 
			
		||||
#include "aliascontent.h"
 | 
			
		||||
 | 
			
		||||
namespace YAML
 | 
			
		||||
{
 | 
			
		||||
	AliasContent::AliasContent(Content* pNodeContent)
 | 
			
		||||
		: m_pRef(pNodeContent)
 | 
			
		||||
	{
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Content *AliasContent::Clone() const
 | 
			
		||||
	{
 | 
			
		||||
		return 0; // TODO: how to clone an alias?
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void AliasContent::Parse(Scanner * /*pScanner*/, ParserState& /*state*/)
 | 
			
		||||
	{
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void AliasContent::Write(Emitter&) const
 | 
			
		||||
	{
 | 
			
		||||
		// no content (just an alias)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	bool AliasContent::GetBegin(std::vector <Node *>::const_iterator& i) const
 | 
			
		||||
	{
 | 
			
		||||
		return m_pRef->GetBegin(i);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	bool AliasContent::GetBegin(std::map <Node *, Node *, ltnode>::const_iterator& i) const
 | 
			
		||||
	{
 | 
			
		||||
		return m_pRef->GetBegin(i);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	bool AliasContent::GetEnd(std::vector <Node *>::const_iterator& i) const
 | 
			
		||||
	{
 | 
			
		||||
		return m_pRef->GetEnd(i);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	bool AliasContent::GetEnd(std::map <Node *, Node *, ltnode>::const_iterator& i) const
 | 
			
		||||
	{
 | 
			
		||||
		return m_pRef->GetEnd(i);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Node* AliasContent::GetNode(std::size_t n) const
 | 
			
		||||
	{
 | 
			
		||||
		return m_pRef->GetNode(n);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	std::size_t AliasContent::GetSize() const
 | 
			
		||||
	{
 | 
			
		||||
		return m_pRef->GetSize();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	bool AliasContent::IsScalar() const
 | 
			
		||||
	{
 | 
			
		||||
		return m_pRef->IsScalar();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	bool AliasContent::IsMap() const
 | 
			
		||||
	{
 | 
			
		||||
		return m_pRef->IsMap();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	bool AliasContent::IsSequence() const
 | 
			
		||||
	{
 | 
			
		||||
		return m_pRef->IsSequence();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	bool AliasContent::GetScalar(std::string& scalar) const
 | 
			
		||||
	{
 | 
			
		||||
		return m_pRef->GetScalar(scalar);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	int AliasContent::Compare(Content *pContent)
 | 
			
		||||
	{
 | 
			
		||||
		return m_pRef->Compare(pContent);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	int AliasContent::Compare(Scalar *pScalar)
 | 
			
		||||
	{
 | 
			
		||||
		return m_pRef->Compare(pScalar);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	int AliasContent::Compare(Sequence *pSequence)
 | 
			
		||||
	{
 | 
			
		||||
		return m_pRef->Compare(pSequence);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	int AliasContent::Compare(Map *pMap)
 | 
			
		||||
	{
 | 
			
		||||
		return m_pRef->Compare(pMap);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										43
									
								
								libs/yaml-cpp/src/aliascontent.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								libs/yaml-cpp/src/aliascontent.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,43 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#ifndef ALIASCONTENT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
 | 
			
		||||
#define ALIASCONTENT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include "content.h"
 | 
			
		||||
 | 
			
		||||
namespace YAML
 | 
			
		||||
{
 | 
			
		||||
	class AliasContent : public Content
 | 
			
		||||
	{
 | 
			
		||||
	public:
 | 
			
		||||
		AliasContent(Content *pNodeContent);
 | 
			
		||||
		
 | 
			
		||||
		virtual Content *Clone() const;
 | 
			
		||||
 | 
			
		||||
		virtual void Parse(Scanner* pScanner, ParserState& state);
 | 
			
		||||
		virtual void Write(Emitter&) const;
 | 
			
		||||
 | 
			
		||||
		virtual bool GetBegin(std::vector <Node *>::const_iterator&) const;
 | 
			
		||||
		virtual bool GetBegin(std::map <Node *, Node *, ltnode>::const_iterator&) const;
 | 
			
		||||
		virtual bool GetEnd(std::vector <Node *>::const_iterator&) const;
 | 
			
		||||
		virtual bool GetEnd(std::map <Node *, Node *, ltnode>::const_iterator&) const;
 | 
			
		||||
		virtual Node* GetNode(std::size_t) const;
 | 
			
		||||
		virtual std::size_t GetSize() const;
 | 
			
		||||
		virtual bool IsScalar() const;
 | 
			
		||||
		virtual bool IsMap() const;
 | 
			
		||||
		virtual bool IsSequence() const;
 | 
			
		||||
 | 
			
		||||
		virtual bool GetScalar(std::string& s) const;
 | 
			
		||||
 | 
			
		||||
		virtual int Compare(Content *);
 | 
			
		||||
		virtual int Compare(Scalar *);
 | 
			
		||||
		virtual int Compare(Sequence *);
 | 
			
		||||
		virtual int Compare(Map *);
 | 
			
		||||
 | 
			
		||||
	private:
 | 
			
		||||
		Content* m_pRef;
 | 
			
		||||
	};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // ALIASCONTENT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
 | 
			
		||||
							
								
								
									
										57
									
								
								libs/yaml-cpp/src/content.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								libs/yaml-cpp/src/content.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,57 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#ifndef CONTENT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
 | 
			
		||||
#define CONTENT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <map>
 | 
			
		||||
#include "parserstate.h"
 | 
			
		||||
#include "exceptions.h"
 | 
			
		||||
#include "ltnode.h"
 | 
			
		||||
 | 
			
		||||
namespace YAML
 | 
			
		||||
{
 | 
			
		||||
	class Scanner;
 | 
			
		||||
	class Parser;
 | 
			
		||||
	class Node;
 | 
			
		||||
	class Scalar;
 | 
			
		||||
	class Sequence;
 | 
			
		||||
	class Map;
 | 
			
		||||
	class Emitter;
 | 
			
		||||
 | 
			
		||||
	class Content
 | 
			
		||||
	{
 | 
			
		||||
	public:
 | 
			
		||||
		Content() {}
 | 
			
		||||
		virtual ~Content() {}
 | 
			
		||||
		
 | 
			
		||||
		virtual Content *Clone() const = 0;
 | 
			
		||||
 | 
			
		||||
		virtual void Parse(Scanner *pScanner, ParserState& state) = 0;
 | 
			
		||||
		virtual void Write(Emitter& out) const = 0;
 | 
			
		||||
 | 
			
		||||
		virtual bool GetBegin(std::vector <Node *>::const_iterator&) const { return false; }
 | 
			
		||||
		virtual bool GetBegin(std::map <Node *, Node *, ltnode>::const_iterator&) const { return false; }
 | 
			
		||||
		virtual bool GetEnd(std::vector <Node *>::const_iterator&) const { return false; }
 | 
			
		||||
		virtual bool GetEnd(std::map <Node *, Node *, ltnode>::const_iterator&) const { return false; }
 | 
			
		||||
		virtual Node *GetNode(std::size_t) const { return 0; }
 | 
			
		||||
		virtual std::size_t GetSize() const { return 0; }
 | 
			
		||||
		virtual bool IsScalar() const { return false; }
 | 
			
		||||
		virtual bool IsMap() const { return false; }
 | 
			
		||||
		virtual bool IsSequence() const { return false; }
 | 
			
		||||
 | 
			
		||||
		// extraction
 | 
			
		||||
		virtual bool GetScalar(std::string&) const { return false; }
 | 
			
		||||
 | 
			
		||||
		// ordering
 | 
			
		||||
		virtual int Compare(Content *) { return 0; }
 | 
			
		||||
		virtual int Compare(Scalar *) { return 0; }
 | 
			
		||||
		virtual int Compare(Sequence *) { return 0; }
 | 
			
		||||
		virtual int Compare(Map *) { return 0; }
 | 
			
		||||
 | 
			
		||||
	protected:
 | 
			
		||||
	};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // CONTENT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
 | 
			
		||||
							
								
								
									
										89
									
								
								libs/yaml-cpp/src/conversion.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								libs/yaml-cpp/src/conversion.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,89 @@
 | 
			
		||||
#include "conversion.h"
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
 | 
			
		||||
////////////////////////////////////////////////////////////////
 | 
			
		||||
// Specializations for converting a string to specific types
 | 
			
		||||
 | 
			
		||||
namespace
 | 
			
		||||
{
 | 
			
		||||
	// we're not gonna mess with the mess that is all the isupper/etc. functions
 | 
			
		||||
	bool IsLower(char ch) { return 'a' <= ch && ch <= 'z'; }
 | 
			
		||||
	bool IsUpper(char ch) { return 'A' <= ch && ch <= 'Z'; }
 | 
			
		||||
	char ToLower(char ch) { return IsUpper(ch) ? ch + 'a' - 'A' : ch; }
 | 
			
		||||
 | 
			
		||||
	std::string tolower(const std::string& str)
 | 
			
		||||
	{
 | 
			
		||||
		std::string s(str);
 | 
			
		||||
		std::transform(s.begin(), s.end(), s.begin(), ToLower);
 | 
			
		||||
		return s;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	template <typename T>
 | 
			
		||||
	bool IsEntirely(const std::string& str, T func)
 | 
			
		||||
	{
 | 
			
		||||
		for(std::size_t i=0;i<str.size();i++)
 | 
			
		||||
			if(!func(str[i]))
 | 
			
		||||
				return false;
 | 
			
		||||
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// IsFlexibleCase
 | 
			
		||||
	// . Returns true if 'str' is:
 | 
			
		||||
	//   . UPPERCASE
 | 
			
		||||
	//   . lowercase
 | 
			
		||||
	//   . Capitalized
 | 
			
		||||
	bool IsFlexibleCase(const std::string& str)
 | 
			
		||||
	{
 | 
			
		||||
		if(str.empty())
 | 
			
		||||
			return true;
 | 
			
		||||
 | 
			
		||||
		if(IsEntirely(str, IsLower))
 | 
			
		||||
			return true;
 | 
			
		||||
 | 
			
		||||
		bool firstcaps = IsUpper(str[0]);
 | 
			
		||||
		std::string rest = str.substr(1);
 | 
			
		||||
		return firstcaps && (IsEntirely(rest, IsLower) || IsEntirely(rest, IsUpper));
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
namespace YAML
 | 
			
		||||
{
 | 
			
		||||
	bool Convert(const std::string& input, bool& b)
 | 
			
		||||
	{
 | 
			
		||||
		// we can't use iostream bool extraction operators as they don't
 | 
			
		||||
		// recognize all possible values in the table below (taken from
 | 
			
		||||
		// http://yaml.org/type/bool.html)
 | 
			
		||||
		static const struct {
 | 
			
		||||
			std::string truename, falsename;
 | 
			
		||||
		} names[] = {
 | 
			
		||||
			{ "y", "n" },
 | 
			
		||||
			{ "yes", "no" },
 | 
			
		||||
			{ "true", "false" },
 | 
			
		||||
			{ "on", "off" },
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
		if(!IsFlexibleCase(input))
 | 
			
		||||
			return false;
 | 
			
		||||
 | 
			
		||||
		for(unsigned i=0;i<sizeof(names)/sizeof(names[0]);i++) {
 | 
			
		||||
			if(names[i].truename == tolower(input)) {
 | 
			
		||||
				b = true;
 | 
			
		||||
				return true;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if(names[i].falsename == tolower(input)) {
 | 
			
		||||
				b = false;
 | 
			
		||||
				return true;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	bool Convert(const std::string& input, _Null& /*output*/)
 | 
			
		||||
	{
 | 
			
		||||
		return input.empty() || input == "~" || input == "null" || input == "Null" || input == "NULL";
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										687
									
								
								libs/yaml-cpp/src/emitter.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										687
									
								
								libs/yaml-cpp/src/emitter.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,687 @@
 | 
			
		||||
#include "emitter.h"
 | 
			
		||||
#include "emitterstate.h"
 | 
			
		||||
#include "emitterutils.h"
 | 
			
		||||
#include "indentation.h"
 | 
			
		||||
#include "exceptions.h"
 | 
			
		||||
#include <sstream>
 | 
			
		||||
 | 
			
		||||
namespace YAML
 | 
			
		||||
{	
 | 
			
		||||
	Emitter::Emitter(): m_pState(new EmitterState)
 | 
			
		||||
	{
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	Emitter::~Emitter()
 | 
			
		||||
	{
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	const char *Emitter::c_str() const
 | 
			
		||||
	{
 | 
			
		||||
		return m_stream.str();
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	unsigned Emitter::size() const
 | 
			
		||||
	{
 | 
			
		||||
		return m_stream.pos();
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	// state checking
 | 
			
		||||
	bool Emitter::good() const
 | 
			
		||||
	{
 | 
			
		||||
		return m_pState->good();
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	const std::string Emitter::GetLastError() const
 | 
			
		||||
	{
 | 
			
		||||
		return m_pState->GetLastError();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// global setters
 | 
			
		||||
	bool Emitter::SetOutputCharset(EMITTER_MANIP value)
 | 
			
		||||
	{
 | 
			
		||||
		return m_pState->SetOutputCharset(value, GLOBAL);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	bool Emitter::SetStringFormat(EMITTER_MANIP value)
 | 
			
		||||
	{
 | 
			
		||||
		return m_pState->SetStringFormat(value, GLOBAL);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	bool Emitter::SetBoolFormat(EMITTER_MANIP value)
 | 
			
		||||
	{
 | 
			
		||||
		bool ok = false;
 | 
			
		||||
		if(m_pState->SetBoolFormat(value, GLOBAL))
 | 
			
		||||
			ok = true;
 | 
			
		||||
		if(m_pState->SetBoolCaseFormat(value, GLOBAL))
 | 
			
		||||
			ok = true;
 | 
			
		||||
		if(m_pState->SetBoolLengthFormat(value, GLOBAL))
 | 
			
		||||
			ok = true;
 | 
			
		||||
		return ok;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	bool Emitter::SetIntBase(EMITTER_MANIP value)
 | 
			
		||||
	{
 | 
			
		||||
		return m_pState->SetIntFormat(value, GLOBAL);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	bool Emitter::SetSeqFormat(EMITTER_MANIP value)
 | 
			
		||||
	{
 | 
			
		||||
		return m_pState->SetFlowType(GT_SEQ, value, GLOBAL);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	bool Emitter::SetMapFormat(EMITTER_MANIP value)
 | 
			
		||||
	{
 | 
			
		||||
		bool ok = false;
 | 
			
		||||
		if(m_pState->SetFlowType(GT_MAP, value, GLOBAL))
 | 
			
		||||
			ok = true;
 | 
			
		||||
		if(m_pState->SetMapKeyFormat(value, GLOBAL))
 | 
			
		||||
			ok = true;
 | 
			
		||||
		return ok;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	bool Emitter::SetIndent(unsigned n)
 | 
			
		||||
	{
 | 
			
		||||
		return m_pState->SetIndent(n, GLOBAL);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	bool Emitter::SetPreCommentIndent(unsigned n)
 | 
			
		||||
	{
 | 
			
		||||
		return m_pState->SetPreCommentIndent(n, GLOBAL);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	bool Emitter::SetPostCommentIndent(unsigned n)
 | 
			
		||||
	{
 | 
			
		||||
		return m_pState->SetPostCommentIndent(n, GLOBAL);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// SetLocalValue
 | 
			
		||||
	// . Either start/end a group, or set a modifier locally
 | 
			
		||||
	Emitter& Emitter::SetLocalValue(EMITTER_MANIP value)
 | 
			
		||||
	{
 | 
			
		||||
		if(!good())
 | 
			
		||||
			return *this;
 | 
			
		||||
		
 | 
			
		||||
		switch(value) {
 | 
			
		||||
			case BeginSeq:
 | 
			
		||||
				EmitBeginSeq();
 | 
			
		||||
				break;
 | 
			
		||||
			case EndSeq:
 | 
			
		||||
				EmitEndSeq();
 | 
			
		||||
				break;
 | 
			
		||||
			case BeginMap:
 | 
			
		||||
				EmitBeginMap();
 | 
			
		||||
				break;
 | 
			
		||||
			case EndMap:
 | 
			
		||||
				EmitEndMap();
 | 
			
		||||
				break;
 | 
			
		||||
			case Key:
 | 
			
		||||
				EmitKey();
 | 
			
		||||
				break;
 | 
			
		||||
			case Value:
 | 
			
		||||
				EmitValue();
 | 
			
		||||
				break;
 | 
			
		||||
			default:
 | 
			
		||||
				m_pState->SetLocalValue(value);
 | 
			
		||||
				break;
 | 
			
		||||
		}
 | 
			
		||||
		return *this;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	Emitter& Emitter::SetLocalIndent(const _Indent& indent)
 | 
			
		||||
	{
 | 
			
		||||
		m_pState->SetIndent(indent.value, LOCAL);
 | 
			
		||||
		return *this;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// GotoNextPreAtomicState
 | 
			
		||||
	// . Runs the state machine, emitting if necessary, and returns 'true' if done (i.e., ready to emit an atom)
 | 
			
		||||
	bool Emitter::GotoNextPreAtomicState()
 | 
			
		||||
	{
 | 
			
		||||
		if(!good())
 | 
			
		||||
			return true;
 | 
			
		||||
		
 | 
			
		||||
		unsigned curIndent = m_pState->GetCurIndent();
 | 
			
		||||
		
 | 
			
		||||
		EMITTER_STATE curState = m_pState->GetCurState();
 | 
			
		||||
		switch(curState) {
 | 
			
		||||
				// document-level
 | 
			
		||||
			case ES_WAITING_FOR_DOC:
 | 
			
		||||
				m_stream << "---";
 | 
			
		||||
				m_pState->RequireSeparation();
 | 
			
		||||
				m_pState->SwitchState(ES_WRITING_DOC);
 | 
			
		||||
				return true;
 | 
			
		||||
			case ES_WRITING_DOC:
 | 
			
		||||
				return true;
 | 
			
		||||
				
 | 
			
		||||
				// block sequence
 | 
			
		||||
			case ES_WAITING_FOR_BLOCK_SEQ_ENTRY:
 | 
			
		||||
				m_stream << IndentTo(curIndent) << "-";
 | 
			
		||||
				m_pState->RequireSeparation();
 | 
			
		||||
				m_pState->SwitchState(ES_WRITING_BLOCK_SEQ_ENTRY);
 | 
			
		||||
				return true;
 | 
			
		||||
			case ES_WRITING_BLOCK_SEQ_ENTRY:
 | 
			
		||||
				return true;
 | 
			
		||||
			case ES_DONE_WITH_BLOCK_SEQ_ENTRY:
 | 
			
		||||
				m_stream << '\n';
 | 
			
		||||
				m_pState->SwitchState(ES_WAITING_FOR_BLOCK_SEQ_ENTRY);
 | 
			
		||||
				return false;
 | 
			
		||||
				
 | 
			
		||||
				// flow sequence
 | 
			
		||||
			case ES_WAITING_FOR_FLOW_SEQ_ENTRY:
 | 
			
		||||
				m_pState->SwitchState(ES_WRITING_FLOW_SEQ_ENTRY);
 | 
			
		||||
				return true;
 | 
			
		||||
			case ES_WRITING_FLOW_SEQ_ENTRY:
 | 
			
		||||
				return true;
 | 
			
		||||
			case ES_DONE_WITH_FLOW_SEQ_ENTRY:
 | 
			
		||||
				m_stream << ',';
 | 
			
		||||
				m_pState->RequireSeparation();
 | 
			
		||||
				m_pState->SwitchState(ES_WAITING_FOR_FLOW_SEQ_ENTRY);
 | 
			
		||||
				return false;
 | 
			
		||||
				
 | 
			
		||||
				// block map
 | 
			
		||||
			case ES_WAITING_FOR_BLOCK_MAP_ENTRY:
 | 
			
		||||
				m_pState->SetError(ErrorMsg::EXPECTED_KEY_TOKEN);
 | 
			
		||||
				return true;
 | 
			
		||||
			case ES_WAITING_FOR_BLOCK_MAP_KEY:
 | 
			
		||||
				if(m_pState->CurrentlyInLongKey()) {
 | 
			
		||||
					m_stream << IndentTo(curIndent) << '?';
 | 
			
		||||
					m_pState->RequireSeparation();
 | 
			
		||||
				}
 | 
			
		||||
				m_pState->SwitchState(ES_WRITING_BLOCK_MAP_KEY);
 | 
			
		||||
				return true;
 | 
			
		||||
			case ES_WRITING_BLOCK_MAP_KEY:
 | 
			
		||||
				return true;
 | 
			
		||||
			case ES_DONE_WITH_BLOCK_MAP_KEY:
 | 
			
		||||
				m_pState->SetError(ErrorMsg::EXPECTED_VALUE_TOKEN);
 | 
			
		||||
				return true;
 | 
			
		||||
			case ES_WAITING_FOR_BLOCK_MAP_VALUE:
 | 
			
		||||
				if(m_pState->CurrentlyInLongKey())
 | 
			
		||||
					m_stream << IndentTo(curIndent);
 | 
			
		||||
				m_stream << ':';
 | 
			
		||||
				m_pState->RequireSeparation();
 | 
			
		||||
				m_pState->SwitchState(ES_WRITING_BLOCK_MAP_VALUE);
 | 
			
		||||
				return true;
 | 
			
		||||
			case ES_WRITING_BLOCK_MAP_VALUE:
 | 
			
		||||
				return true;
 | 
			
		||||
			case ES_DONE_WITH_BLOCK_MAP_VALUE:
 | 
			
		||||
				m_pState->SetError(ErrorMsg::EXPECTED_KEY_TOKEN);
 | 
			
		||||
				return true;
 | 
			
		||||
				
 | 
			
		||||
				// flow map
 | 
			
		||||
			case ES_WAITING_FOR_FLOW_MAP_ENTRY:
 | 
			
		||||
				m_pState->SetError(ErrorMsg::EXPECTED_KEY_TOKEN);
 | 
			
		||||
				return true;
 | 
			
		||||
			case ES_WAITING_FOR_FLOW_MAP_KEY:
 | 
			
		||||
				m_pState->SwitchState(ES_WRITING_FLOW_MAP_KEY);
 | 
			
		||||
				if(m_pState->CurrentlyInLongKey()) {
 | 
			
		||||
					EmitSeparationIfNecessary();
 | 
			
		||||
					m_stream << '?';
 | 
			
		||||
					m_pState->RequireSeparation();
 | 
			
		||||
				}
 | 
			
		||||
				return true;
 | 
			
		||||
			case ES_WRITING_FLOW_MAP_KEY:
 | 
			
		||||
				return true;
 | 
			
		||||
			case ES_DONE_WITH_FLOW_MAP_KEY:
 | 
			
		||||
				m_pState->SetError(ErrorMsg::EXPECTED_VALUE_TOKEN);
 | 
			
		||||
				return true;
 | 
			
		||||
			case ES_WAITING_FOR_FLOW_MAP_VALUE:
 | 
			
		||||
				m_stream << ':';
 | 
			
		||||
				m_pState->RequireSeparation();
 | 
			
		||||
				m_pState->SwitchState(ES_WRITING_FLOW_MAP_VALUE);
 | 
			
		||||
				return true;
 | 
			
		||||
			case ES_WRITING_FLOW_MAP_VALUE:
 | 
			
		||||
				return true;
 | 
			
		||||
			case ES_DONE_WITH_FLOW_MAP_VALUE:
 | 
			
		||||
				m_pState->SetError(ErrorMsg::EXPECTED_KEY_TOKEN);
 | 
			
		||||
				return true;
 | 
			
		||||
			default:
 | 
			
		||||
				assert(false);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		assert(false);
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	// PreAtomicWrite
 | 
			
		||||
	// . Depending on the emitter state, write to the stream to get it
 | 
			
		||||
	//   in position to do an atomic write (e.g., scalar, sequence, or map)
 | 
			
		||||
	void Emitter::PreAtomicWrite()
 | 
			
		||||
	{
 | 
			
		||||
		if(!good())
 | 
			
		||||
			return;
 | 
			
		||||
		
 | 
			
		||||
		while(!GotoNextPreAtomicState())
 | 
			
		||||
			;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	// PostAtomicWrite
 | 
			
		||||
	// . Clean up
 | 
			
		||||
	void Emitter::PostAtomicWrite()
 | 
			
		||||
	{
 | 
			
		||||
		if(!good())
 | 
			
		||||
			return;
 | 
			
		||||
		
 | 
			
		||||
		EMITTER_STATE curState = m_pState->GetCurState();
 | 
			
		||||
		switch(curState) {
 | 
			
		||||
				// document-level
 | 
			
		||||
			case ES_WRITING_DOC:
 | 
			
		||||
				m_pState->SwitchState(ES_DONE_WITH_DOC);
 | 
			
		||||
				break;
 | 
			
		||||
 | 
			
		||||
				// block seq
 | 
			
		||||
			case ES_WRITING_BLOCK_SEQ_ENTRY:
 | 
			
		||||
				m_pState->SwitchState(ES_DONE_WITH_BLOCK_SEQ_ENTRY);
 | 
			
		||||
				break;
 | 
			
		||||
				
 | 
			
		||||
				// flow seq
 | 
			
		||||
			case ES_WRITING_FLOW_SEQ_ENTRY:
 | 
			
		||||
				m_pState->SwitchState(ES_DONE_WITH_FLOW_SEQ_ENTRY);
 | 
			
		||||
				break;
 | 
			
		||||
				
 | 
			
		||||
				// block map
 | 
			
		||||
			case ES_WRITING_BLOCK_MAP_KEY:
 | 
			
		||||
				m_pState->SwitchState(ES_DONE_WITH_BLOCK_MAP_KEY);
 | 
			
		||||
				break;
 | 
			
		||||
			case ES_WRITING_BLOCK_MAP_VALUE:
 | 
			
		||||
				m_pState->SwitchState(ES_DONE_WITH_BLOCK_MAP_VALUE);
 | 
			
		||||
				break;
 | 
			
		||||
				
 | 
			
		||||
				// flow map
 | 
			
		||||
			case ES_WRITING_FLOW_MAP_KEY:
 | 
			
		||||
				m_pState->SwitchState(ES_DONE_WITH_FLOW_MAP_KEY);
 | 
			
		||||
				break;
 | 
			
		||||
			case ES_WRITING_FLOW_MAP_VALUE:
 | 
			
		||||
				m_pState->SwitchState(ES_DONE_WITH_FLOW_MAP_VALUE);
 | 
			
		||||
				break;
 | 
			
		||||
			default:
 | 
			
		||||
				assert(false);
 | 
			
		||||
		};
 | 
			
		||||
				
 | 
			
		||||
		m_pState->ClearModifiedSettings();
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	// EmitSeparationIfNecessary
 | 
			
		||||
	void Emitter::EmitSeparationIfNecessary()
 | 
			
		||||
	{
 | 
			
		||||
		if(!good())
 | 
			
		||||
			return;
 | 
			
		||||
		
 | 
			
		||||
		if(m_pState->RequiresSeparation())
 | 
			
		||||
			m_stream << ' ';
 | 
			
		||||
		m_pState->UnsetSeparation();
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	// EmitBeginSeq
 | 
			
		||||
	void Emitter::EmitBeginSeq()
 | 
			
		||||
	{
 | 
			
		||||
		if(!good())
 | 
			
		||||
			return;
 | 
			
		||||
		
 | 
			
		||||
		// must have a long key if we're emitting a sequence
 | 
			
		||||
		m_pState->StartLongKey();
 | 
			
		||||
		
 | 
			
		||||
		PreAtomicWrite();
 | 
			
		||||
		
 | 
			
		||||
		EMITTER_STATE curState = m_pState->GetCurState();
 | 
			
		||||
		EMITTER_MANIP flowType = m_pState->GetFlowType(GT_SEQ);
 | 
			
		||||
		if(flowType == Block) {
 | 
			
		||||
			if(curState == ES_WRITING_BLOCK_SEQ_ENTRY ||
 | 
			
		||||
			   curState == ES_WRITING_BLOCK_MAP_KEY || curState == ES_WRITING_BLOCK_MAP_VALUE ||
 | 
			
		||||
			   curState == ES_WRITING_DOC
 | 
			
		||||
			) {
 | 
			
		||||
				m_stream << "\n";
 | 
			
		||||
				m_pState->UnsetSeparation();
 | 
			
		||||
			}
 | 
			
		||||
			m_pState->PushState(ES_WAITING_FOR_BLOCK_SEQ_ENTRY);
 | 
			
		||||
		} else if(flowType == Flow) {
 | 
			
		||||
			EmitSeparationIfNecessary();
 | 
			
		||||
			m_stream << "[";
 | 
			
		||||
			m_pState->PushState(ES_WAITING_FOR_FLOW_SEQ_ENTRY);
 | 
			
		||||
		} else
 | 
			
		||||
			assert(false);
 | 
			
		||||
 | 
			
		||||
		m_pState->BeginGroup(GT_SEQ);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	// EmitEndSeq
 | 
			
		||||
	void Emitter::EmitEndSeq()
 | 
			
		||||
	{
 | 
			
		||||
		if(!good())
 | 
			
		||||
			return;
 | 
			
		||||
		
 | 
			
		||||
		if(m_pState->GetCurGroupType() != GT_SEQ)
 | 
			
		||||
			return m_pState->SetError(ErrorMsg::UNEXPECTED_END_SEQ);
 | 
			
		||||
		
 | 
			
		||||
		EMITTER_STATE curState = m_pState->GetCurState();
 | 
			
		||||
		FLOW_TYPE flowType = m_pState->GetCurGroupFlowType();
 | 
			
		||||
		if(flowType == FT_BLOCK) {
 | 
			
		||||
			// Note: block sequences are *not* allowed to be empty, but we convert it
 | 
			
		||||
			//       to a flow sequence if it is
 | 
			
		||||
			assert(curState == ES_DONE_WITH_BLOCK_SEQ_ENTRY || curState == ES_WAITING_FOR_BLOCK_SEQ_ENTRY);
 | 
			
		||||
			if(curState == ES_WAITING_FOR_BLOCK_SEQ_ENTRY) {
 | 
			
		||||
				// Note: only one of these will actually output anything for a given situation
 | 
			
		||||
				EmitSeparationIfNecessary();
 | 
			
		||||
				unsigned curIndent = m_pState->GetCurIndent();
 | 
			
		||||
				m_stream << IndentTo(curIndent);
 | 
			
		||||
 | 
			
		||||
				m_stream << "[]";
 | 
			
		||||
			}
 | 
			
		||||
		} else if(flowType == FT_FLOW) {
 | 
			
		||||
			// Note: flow sequences are allowed to be empty
 | 
			
		||||
			assert(curState == ES_DONE_WITH_FLOW_SEQ_ENTRY || curState == ES_WAITING_FOR_FLOW_SEQ_ENTRY);
 | 
			
		||||
			m_stream << "]";
 | 
			
		||||
		} else
 | 
			
		||||
			assert(false);
 | 
			
		||||
		
 | 
			
		||||
		m_pState->PopState();
 | 
			
		||||
		m_pState->EndGroup(GT_SEQ);
 | 
			
		||||
 | 
			
		||||
		PostAtomicWrite();
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	// EmitBeginMap
 | 
			
		||||
	void Emitter::EmitBeginMap()
 | 
			
		||||
	{
 | 
			
		||||
		if(!good())
 | 
			
		||||
			return;
 | 
			
		||||
		
 | 
			
		||||
		// must have a long key if we're emitting a map
 | 
			
		||||
		m_pState->StartLongKey();
 | 
			
		||||
 | 
			
		||||
		PreAtomicWrite();
 | 
			
		||||
 | 
			
		||||
		EMITTER_STATE curState = m_pState->GetCurState();
 | 
			
		||||
		EMITTER_MANIP flowType = m_pState->GetFlowType(GT_MAP);
 | 
			
		||||
		if(flowType == Block) {
 | 
			
		||||
			if(curState == ES_WRITING_BLOCK_SEQ_ENTRY ||
 | 
			
		||||
			   curState == ES_WRITING_BLOCK_MAP_KEY || curState == ES_WRITING_BLOCK_MAP_VALUE ||
 | 
			
		||||
			   curState == ES_WRITING_DOC
 | 
			
		||||
			) {
 | 
			
		||||
				m_stream << "\n";
 | 
			
		||||
				m_pState->UnsetSeparation();
 | 
			
		||||
			}
 | 
			
		||||
			m_pState->PushState(ES_WAITING_FOR_BLOCK_MAP_ENTRY);
 | 
			
		||||
		} else if(flowType == Flow) {
 | 
			
		||||
			EmitSeparationIfNecessary();
 | 
			
		||||
			m_stream << "{";
 | 
			
		||||
			m_pState->PushState(ES_WAITING_FOR_FLOW_MAP_ENTRY);
 | 
			
		||||
		} else
 | 
			
		||||
			assert(false);
 | 
			
		||||
		
 | 
			
		||||
		m_pState->BeginGroup(GT_MAP);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	// EmitEndMap
 | 
			
		||||
	void Emitter::EmitEndMap()
 | 
			
		||||
	{
 | 
			
		||||
		if(!good())
 | 
			
		||||
			return;
 | 
			
		||||
		
 | 
			
		||||
		if(m_pState->GetCurGroupType() != GT_MAP)
 | 
			
		||||
			return m_pState->SetError(ErrorMsg::UNEXPECTED_END_MAP);
 | 
			
		||||
 | 
			
		||||
		EMITTER_STATE curState = m_pState->GetCurState();
 | 
			
		||||
		FLOW_TYPE flowType = m_pState->GetCurGroupFlowType();
 | 
			
		||||
		if(flowType == FT_BLOCK) {
 | 
			
		||||
			// Note: block sequences are *not* allowed to be empty, but we convert it
 | 
			
		||||
			//       to a flow sequence if it is
 | 
			
		||||
			assert(curState == ES_DONE_WITH_BLOCK_MAP_VALUE || curState == ES_WAITING_FOR_BLOCK_MAP_ENTRY);
 | 
			
		||||
			if(curState == ES_WAITING_FOR_BLOCK_MAP_ENTRY) {
 | 
			
		||||
				// Note: only one of these will actually output anything for a given situation
 | 
			
		||||
				EmitSeparationIfNecessary();
 | 
			
		||||
				unsigned curIndent = m_pState->GetCurIndent();
 | 
			
		||||
				m_stream << IndentTo(curIndent);
 | 
			
		||||
				m_stream << "{}";
 | 
			
		||||
			}
 | 
			
		||||
		} else if(flowType == FT_FLOW) {
 | 
			
		||||
			// Note: flow maps are allowed to be empty
 | 
			
		||||
			assert(curState == ES_DONE_WITH_FLOW_MAP_VALUE || curState == ES_WAITING_FOR_FLOW_MAP_ENTRY);
 | 
			
		||||
			m_stream << "}";
 | 
			
		||||
		} else
 | 
			
		||||
			assert(false);
 | 
			
		||||
		
 | 
			
		||||
		m_pState->PopState();
 | 
			
		||||
		m_pState->EndGroup(GT_MAP);
 | 
			
		||||
		
 | 
			
		||||
		PostAtomicWrite();
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	// EmitKey
 | 
			
		||||
	void Emitter::EmitKey()
 | 
			
		||||
	{
 | 
			
		||||
		if(!good())
 | 
			
		||||
			return;
 | 
			
		||||
		
 | 
			
		||||
		EMITTER_STATE curState = m_pState->GetCurState();
 | 
			
		||||
		FLOW_TYPE flowType = m_pState->GetCurGroupFlowType();
 | 
			
		||||
		if(curState != ES_WAITING_FOR_BLOCK_MAP_ENTRY && curState != ES_DONE_WITH_BLOCK_MAP_VALUE
 | 
			
		||||
		   && curState != ES_WAITING_FOR_FLOW_MAP_ENTRY && curState != ES_DONE_WITH_FLOW_MAP_VALUE)
 | 
			
		||||
			return m_pState->SetError(ErrorMsg::UNEXPECTED_KEY_TOKEN);
 | 
			
		||||
 | 
			
		||||
		if(flowType == FT_BLOCK) {
 | 
			
		||||
			if(curState == ES_DONE_WITH_BLOCK_MAP_VALUE)
 | 
			
		||||
				m_stream << '\n';
 | 
			
		||||
			unsigned curIndent = m_pState->GetCurIndent();
 | 
			
		||||
			m_stream << IndentTo(curIndent);
 | 
			
		||||
			m_pState->SwitchState(ES_WAITING_FOR_BLOCK_MAP_KEY);
 | 
			
		||||
		} else if(flowType == FT_FLOW) {
 | 
			
		||||
			if(curState == ES_DONE_WITH_FLOW_MAP_VALUE) {
 | 
			
		||||
				m_stream << ',';
 | 
			
		||||
				m_pState->RequireSeparation();
 | 
			
		||||
			}
 | 
			
		||||
			m_pState->SwitchState(ES_WAITING_FOR_FLOW_MAP_KEY);
 | 
			
		||||
		} else
 | 
			
		||||
			assert(false);
 | 
			
		||||
		
 | 
			
		||||
		if(m_pState->GetMapKeyFormat() == LongKey)
 | 
			
		||||
			m_pState->StartLongKey();
 | 
			
		||||
		else if(m_pState->GetMapKeyFormat() == Auto)
 | 
			
		||||
			m_pState->StartSimpleKey();
 | 
			
		||||
		else
 | 
			
		||||
			assert(false);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	// EmitValue
 | 
			
		||||
	void Emitter::EmitValue()
 | 
			
		||||
	{
 | 
			
		||||
		if(!good())
 | 
			
		||||
			return;
 | 
			
		||||
 | 
			
		||||
		EMITTER_STATE curState = m_pState->GetCurState();
 | 
			
		||||
		FLOW_TYPE flowType = m_pState->GetCurGroupFlowType();
 | 
			
		||||
		if(curState != ES_DONE_WITH_BLOCK_MAP_KEY && curState != ES_DONE_WITH_FLOW_MAP_KEY)
 | 
			
		||||
			return m_pState->SetError(ErrorMsg::UNEXPECTED_VALUE_TOKEN);
 | 
			
		||||
 | 
			
		||||
		if(flowType == FT_BLOCK) {
 | 
			
		||||
			if(m_pState->CurrentlyInLongKey())
 | 
			
		||||
				m_stream << '\n';
 | 
			
		||||
			m_pState->SwitchState(ES_WAITING_FOR_BLOCK_MAP_VALUE);
 | 
			
		||||
		} else if(flowType == FT_FLOW) {
 | 
			
		||||
			m_pState->SwitchState(ES_WAITING_FOR_FLOW_MAP_VALUE);
 | 
			
		||||
		} else
 | 
			
		||||
			assert(false);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// *******************************************************************************************
 | 
			
		||||
	// overloads of Write
 | 
			
		||||
	
 | 
			
		||||
	Emitter& Emitter::Write(const std::string& str)
 | 
			
		||||
	{
 | 
			
		||||
		if(!good())
 | 
			
		||||
			return *this;
 | 
			
		||||
		
 | 
			
		||||
		// literal scalars must use long keys
 | 
			
		||||
		if(m_pState->GetStringFormat() == Literal && m_pState->GetCurGroupFlowType() != FT_FLOW)
 | 
			
		||||
			m_pState->StartLongKey();
 | 
			
		||||
		
 | 
			
		||||
		PreAtomicWrite();
 | 
			
		||||
		EmitSeparationIfNecessary();
 | 
			
		||||
		
 | 
			
		||||
		bool escapeNonAscii = m_pState->GetOutputCharset() == EscapeNonAscii;
 | 
			
		||||
		EMITTER_MANIP strFmt = m_pState->GetStringFormat();
 | 
			
		||||
		FLOW_TYPE flowType = m_pState->GetCurGroupFlowType();
 | 
			
		||||
		unsigned curIndent = m_pState->GetCurIndent();
 | 
			
		||||
 | 
			
		||||
		switch(strFmt) {
 | 
			
		||||
			case Auto:
 | 
			
		||||
				Utils::WriteString(m_stream, str, flowType == FT_FLOW, escapeNonAscii);
 | 
			
		||||
				break;
 | 
			
		||||
			case SingleQuoted:
 | 
			
		||||
				if(!Utils::WriteSingleQuotedString(m_stream, str)) {
 | 
			
		||||
					m_pState->SetError(ErrorMsg::SINGLE_QUOTED_CHAR);
 | 
			
		||||
					return *this;
 | 
			
		||||
				}
 | 
			
		||||
				break;
 | 
			
		||||
			case DoubleQuoted:
 | 
			
		||||
				Utils::WriteDoubleQuotedString(m_stream, str, escapeNonAscii);
 | 
			
		||||
				break;
 | 
			
		||||
			case Literal:
 | 
			
		||||
				if(flowType == FT_FLOW)
 | 
			
		||||
					Utils::WriteString(m_stream, str, flowType == FT_FLOW, escapeNonAscii);
 | 
			
		||||
				else
 | 
			
		||||
					Utils::WriteLiteralString(m_stream, str, curIndent + m_pState->GetIndent());
 | 
			
		||||
				break;
 | 
			
		||||
			default:
 | 
			
		||||
				assert(false);
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		PostAtomicWrite();
 | 
			
		||||
		return *this;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	void Emitter::PreWriteIntegralType(std::stringstream& str)
 | 
			
		||||
	{
 | 
			
		||||
		PreAtomicWrite();
 | 
			
		||||
		EmitSeparationIfNecessary();
 | 
			
		||||
		
 | 
			
		||||
		EMITTER_MANIP intFmt = m_pState->GetIntFormat();
 | 
			
		||||
		switch(intFmt) {
 | 
			
		||||
			case Dec:
 | 
			
		||||
				str << std::dec;
 | 
			
		||||
				break;
 | 
			
		||||
			case Hex:
 | 
			
		||||
				str << std::hex;
 | 
			
		||||
				break;
 | 
			
		||||
				case Oct:
 | 
			
		||||
				str << std::oct;
 | 
			
		||||
				break;
 | 
			
		||||
			default:
 | 
			
		||||
				assert(false);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	void Emitter::PostWriteIntegralType(const std::stringstream& str)
 | 
			
		||||
	{
 | 
			
		||||
		m_stream << str.str();
 | 
			
		||||
		PostAtomicWrite();
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	Emitter& Emitter::Write(bool b)
 | 
			
		||||
	{
 | 
			
		||||
		if(!good())
 | 
			
		||||
			return *this;
 | 
			
		||||
		
 | 
			
		||||
		PreAtomicWrite();
 | 
			
		||||
		EmitSeparationIfNecessary();
 | 
			
		||||
		
 | 
			
		||||
		// set up all possible bools to write
 | 
			
		||||
		struct BoolName { std::string trueName, falseName; };
 | 
			
		||||
		struct BoolFormatNames { BoolName upper, lower, camel; };
 | 
			
		||||
		struct BoolTypes { BoolFormatNames yesNo, trueFalse, onOff; };
 | 
			
		||||
		
 | 
			
		||||
		static const BoolTypes boolTypes = {
 | 
			
		||||
			{ { "YES", "NO" }, { "yes", "no" }, { "Yes", "No" } },
 | 
			
		||||
			{ { "TRUE", "FALSE" }, { "true", "false" }, { "True", "False" } },
 | 
			
		||||
			{ { "ON", "OFF" }, { "on", "off" }, { "On", "Off" } }
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
		// select the right one
 | 
			
		||||
		EMITTER_MANIP boolFmt = m_pState->GetBoolFormat();
 | 
			
		||||
		EMITTER_MANIP boolLengthFmt = m_pState->GetBoolLengthFormat();
 | 
			
		||||
		EMITTER_MANIP boolCaseFmt = m_pState->GetBoolCaseFormat();
 | 
			
		||||
		
 | 
			
		||||
		const BoolFormatNames& fmtNames = (boolFmt == YesNoBool ? boolTypes.yesNo : boolFmt == TrueFalseBool ? boolTypes.trueFalse : boolTypes.onOff);
 | 
			
		||||
		const BoolName& boolName = (boolCaseFmt == UpperCase ? fmtNames.upper : boolCaseFmt == LowerCase ? fmtNames.lower : fmtNames.camel);
 | 
			
		||||
		const std::string& name = (b ? boolName.trueName : boolName.falseName);
 | 
			
		||||
		
 | 
			
		||||
		// and say it!
 | 
			
		||||
		// TODO: should we disallow writing OnOffBool with ShortBool? (it'll just print "o" for both, which is silly)
 | 
			
		||||
		if(boolLengthFmt == ShortBool)
 | 
			
		||||
			m_stream << name[0];
 | 
			
		||||
		else
 | 
			
		||||
			m_stream << name;
 | 
			
		||||
		
 | 
			
		||||
		PostAtomicWrite();
 | 
			
		||||
		return *this;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Emitter& Emitter::Write(const _Alias& alias)
 | 
			
		||||
	{
 | 
			
		||||
		if(!good())
 | 
			
		||||
			return *this;
 | 
			
		||||
		
 | 
			
		||||
		PreAtomicWrite();
 | 
			
		||||
		EmitSeparationIfNecessary();
 | 
			
		||||
		if(!Utils::WriteAlias(m_stream, alias.content)) {
 | 
			
		||||
			m_pState->SetError(ErrorMsg::INVALID_ALIAS);
 | 
			
		||||
			return *this;
 | 
			
		||||
		}
 | 
			
		||||
		PostAtomicWrite();
 | 
			
		||||
		return *this;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	Emitter& Emitter::Write(const _Anchor& anchor)
 | 
			
		||||
	{
 | 
			
		||||
		if(!good())
 | 
			
		||||
			return *this;
 | 
			
		||||
		
 | 
			
		||||
		PreAtomicWrite();
 | 
			
		||||
		EmitSeparationIfNecessary();
 | 
			
		||||
		if(!Utils::WriteAnchor(m_stream, anchor.content)) {
 | 
			
		||||
			m_pState->SetError(ErrorMsg::INVALID_ANCHOR);
 | 
			
		||||
			return *this;
 | 
			
		||||
		}
 | 
			
		||||
		m_pState->RequireSeparation();
 | 
			
		||||
		// Note: no PostAtomicWrite() because we need another value for this node
 | 
			
		||||
		return *this;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	Emitter& Emitter::Write(const _Tag& tag)
 | 
			
		||||
	{
 | 
			
		||||
		if(!good())
 | 
			
		||||
			return *this;
 | 
			
		||||
		
 | 
			
		||||
		PreAtomicWrite();
 | 
			
		||||
		EmitSeparationIfNecessary();
 | 
			
		||||
		if(!Utils::WriteTag(m_stream, tag.content)) {
 | 
			
		||||
			m_pState->SetError(ErrorMsg::INVALID_TAG);
 | 
			
		||||
			return *this;
 | 
			
		||||
		}
 | 
			
		||||
		m_pState->RequireSeparation();
 | 
			
		||||
		// Note: no PostAtomicWrite() because we need another value for this node
 | 
			
		||||
		return *this;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Emitter& Emitter::Write(const _Comment& comment)
 | 
			
		||||
	{
 | 
			
		||||
		if(!good())
 | 
			
		||||
			return *this;
 | 
			
		||||
		
 | 
			
		||||
		m_stream << Indentation(m_pState->GetPreCommentIndent());
 | 
			
		||||
		Utils::WriteComment(m_stream, comment.content, m_pState->GetPostCommentIndent());
 | 
			
		||||
		return *this;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Emitter& Emitter::Write(const _Null& /*null*/)
 | 
			
		||||
	{
 | 
			
		||||
		if(!good())
 | 
			
		||||
			return *this;
 | 
			
		||||
		
 | 
			
		||||
		PreAtomicWrite();
 | 
			
		||||
		EmitSeparationIfNecessary();
 | 
			
		||||
		m_stream << "~";
 | 
			
		||||
		PostAtomicWrite();
 | 
			
		||||
		return *this;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										277
									
								
								libs/yaml-cpp/src/emitterstate.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										277
									
								
								libs/yaml-cpp/src/emitterstate.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,277 @@
 | 
			
		||||
#include "emitterstate.h"
 | 
			
		||||
#include "exceptions.h"
 | 
			
		||||
 | 
			
		||||
namespace YAML
 | 
			
		||||
{
 | 
			
		||||
	EmitterState::EmitterState(): m_isGood(true), m_curIndent(0), m_requiresSeparation(false)
 | 
			
		||||
	{
 | 
			
		||||
		// start up
 | 
			
		||||
		m_stateStack.push(ES_WAITING_FOR_DOC);
 | 
			
		||||
		
 | 
			
		||||
		// set default global manipulators
 | 
			
		||||
		m_charset.set(EmitNonAscii);
 | 
			
		||||
		m_strFmt.set(Auto);
 | 
			
		||||
		m_boolFmt.set(TrueFalseBool);
 | 
			
		||||
		m_boolLengthFmt.set(LongBool);
 | 
			
		||||
		m_boolCaseFmt.set(LowerCase);
 | 
			
		||||
		m_intFmt.set(Dec);
 | 
			
		||||
		m_indent.set(2);
 | 
			
		||||
		m_preCommentIndent.set(2);
 | 
			
		||||
		m_postCommentIndent.set(1);
 | 
			
		||||
		m_seqFmt.set(Block);
 | 
			
		||||
		m_mapFmt.set(Block);
 | 
			
		||||
		m_mapKeyFmt.set(Auto);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	EmitterState::~EmitterState()
 | 
			
		||||
	{
 | 
			
		||||
		while(!m_groups.empty())
 | 
			
		||||
			_PopGroup();
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	std::auto_ptr <EmitterState::Group> EmitterState::_PopGroup()
 | 
			
		||||
	{
 | 
			
		||||
		if(m_groups.empty())
 | 
			
		||||
			return std::auto_ptr <Group> (0);
 | 
			
		||||
		
 | 
			
		||||
		std::auto_ptr <Group> pGroup(m_groups.top());
 | 
			
		||||
		m_groups.pop();
 | 
			
		||||
		return pGroup;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// SetLocalValue
 | 
			
		||||
	// . We blindly tries to set all possible formatters to this value
 | 
			
		||||
	// . Only the ones that make sense will be accepted
 | 
			
		||||
	void EmitterState::SetLocalValue(EMITTER_MANIP value)
 | 
			
		||||
	{
 | 
			
		||||
		SetOutputCharset(value, LOCAL);
 | 
			
		||||
		SetStringFormat(value, LOCAL);
 | 
			
		||||
		SetBoolFormat(value, LOCAL);
 | 
			
		||||
		SetBoolCaseFormat(value, LOCAL);
 | 
			
		||||
		SetBoolLengthFormat(value, LOCAL);
 | 
			
		||||
		SetIntFormat(value, LOCAL);
 | 
			
		||||
		SetFlowType(GT_SEQ, value, LOCAL);
 | 
			
		||||
		SetFlowType(GT_MAP, value, LOCAL);
 | 
			
		||||
		SetMapKeyFormat(value, LOCAL);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	void EmitterState::BeginGroup(GROUP_TYPE type)
 | 
			
		||||
	{
 | 
			
		||||
		unsigned lastIndent = (m_groups.empty() ? 0 : m_groups.top()->indent);
 | 
			
		||||
		m_curIndent += lastIndent;
 | 
			
		||||
		
 | 
			
		||||
		std::auto_ptr <Group> pGroup(new Group(type));
 | 
			
		||||
		
 | 
			
		||||
		// transfer settings (which last until this group is done)
 | 
			
		||||
		pGroup->modifiedSettings = m_modifiedSettings;
 | 
			
		||||
 | 
			
		||||
		// set up group
 | 
			
		||||
		pGroup->flow = GetFlowType(type);
 | 
			
		||||
		pGroup->indent = GetIndent();
 | 
			
		||||
		pGroup->usingLongKey = (GetMapKeyFormat() == LongKey ? true : false);
 | 
			
		||||
 | 
			
		||||
		m_groups.push(pGroup.release());
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	void EmitterState::EndGroup(GROUP_TYPE type)
 | 
			
		||||
	{
 | 
			
		||||
		if(m_groups.empty())
 | 
			
		||||
			return SetError(ErrorMsg::UNMATCHED_GROUP_TAG);
 | 
			
		||||
		
 | 
			
		||||
		// get rid of the current group
 | 
			
		||||
		{
 | 
			
		||||
			std::auto_ptr <Group> pFinishedGroup = _PopGroup();
 | 
			
		||||
			if(pFinishedGroup->type != type)
 | 
			
		||||
				return SetError(ErrorMsg::UNMATCHED_GROUP_TAG);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// reset old settings
 | 
			
		||||
		unsigned lastIndent = (m_groups.empty() ? 0 : m_groups.top()->indent);
 | 
			
		||||
		assert(m_curIndent >= lastIndent);
 | 
			
		||||
		m_curIndent -= lastIndent;
 | 
			
		||||
		
 | 
			
		||||
		// some global settings that we changed may have been overridden
 | 
			
		||||
		// by a local setting we just popped, so we need to restore them
 | 
			
		||||
		m_globalModifiedSettings.restore();
 | 
			
		||||
	}
 | 
			
		||||
		
 | 
			
		||||
	GROUP_TYPE EmitterState::GetCurGroupType() const
 | 
			
		||||
	{
 | 
			
		||||
		if(m_groups.empty())
 | 
			
		||||
			return GT_NONE;
 | 
			
		||||
		
 | 
			
		||||
		return m_groups.top()->type;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	FLOW_TYPE EmitterState::GetCurGroupFlowType() const
 | 
			
		||||
	{
 | 
			
		||||
		if(m_groups.empty())
 | 
			
		||||
			return FT_NONE;
 | 
			
		||||
		
 | 
			
		||||
		return (m_groups.top()->flow == Flow ? FT_FLOW : FT_BLOCK);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	bool EmitterState::CurrentlyInLongKey()
 | 
			
		||||
	{
 | 
			
		||||
		if(m_groups.empty())
 | 
			
		||||
			return false;
 | 
			
		||||
		return m_groups.top()->usingLongKey;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	void EmitterState::StartLongKey()
 | 
			
		||||
	{
 | 
			
		||||
		if(!m_groups.empty())
 | 
			
		||||
			m_groups.top()->usingLongKey = true;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	void EmitterState::StartSimpleKey()
 | 
			
		||||
	{
 | 
			
		||||
		if(!m_groups.empty())
 | 
			
		||||
			m_groups.top()->usingLongKey = false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void EmitterState::ClearModifiedSettings()
 | 
			
		||||
	{
 | 
			
		||||
		m_modifiedSettings.clear();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	bool EmitterState::SetOutputCharset(EMITTER_MANIP value, FMT_SCOPE scope)
 | 
			
		||||
	{
 | 
			
		||||
		switch(value) {
 | 
			
		||||
			case EmitNonAscii:
 | 
			
		||||
			case EscapeNonAscii:
 | 
			
		||||
				_Set(m_charset, value, scope);
 | 
			
		||||
				return true;
 | 
			
		||||
			default:
 | 
			
		||||
				return false;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	bool EmitterState::SetStringFormat(EMITTER_MANIP value, FMT_SCOPE scope)
 | 
			
		||||
	{
 | 
			
		||||
		switch(value) {
 | 
			
		||||
			case Auto:
 | 
			
		||||
			case SingleQuoted:
 | 
			
		||||
			case DoubleQuoted:
 | 
			
		||||
			case Literal:
 | 
			
		||||
				_Set(m_strFmt, value, scope);
 | 
			
		||||
				return true;
 | 
			
		||||
			default:
 | 
			
		||||
				return false;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	bool EmitterState::SetBoolFormat(EMITTER_MANIP value, FMT_SCOPE scope)
 | 
			
		||||
	{
 | 
			
		||||
		switch(value) {
 | 
			
		||||
			case OnOffBool:
 | 
			
		||||
			case TrueFalseBool:
 | 
			
		||||
			case YesNoBool:
 | 
			
		||||
				_Set(m_boolFmt, value, scope);
 | 
			
		||||
				return true;
 | 
			
		||||
			default:
 | 
			
		||||
				return false;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	bool EmitterState::SetBoolLengthFormat(EMITTER_MANIP value, FMT_SCOPE scope)
 | 
			
		||||
	{
 | 
			
		||||
		switch(value) {
 | 
			
		||||
			case LongBool:
 | 
			
		||||
			case ShortBool:
 | 
			
		||||
				_Set(m_boolLengthFmt, value, scope);
 | 
			
		||||
				return true;
 | 
			
		||||
			default:
 | 
			
		||||
				return false;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	bool EmitterState::SetBoolCaseFormat(EMITTER_MANIP value, FMT_SCOPE scope)
 | 
			
		||||
	{
 | 
			
		||||
		switch(value) {
 | 
			
		||||
			case UpperCase:
 | 
			
		||||
			case LowerCase:
 | 
			
		||||
			case CamelCase:
 | 
			
		||||
				_Set(m_boolCaseFmt, value, scope);
 | 
			
		||||
				return true;
 | 
			
		||||
			default:
 | 
			
		||||
				return false;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	bool EmitterState::SetIntFormat(EMITTER_MANIP value, FMT_SCOPE scope)
 | 
			
		||||
	{
 | 
			
		||||
		switch(value) {
 | 
			
		||||
			case Dec:
 | 
			
		||||
			case Hex:
 | 
			
		||||
			case Oct:
 | 
			
		||||
				_Set(m_intFmt, value, scope);
 | 
			
		||||
				return true;
 | 
			
		||||
			default:
 | 
			
		||||
				return false;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	bool EmitterState::SetIndent(unsigned value, FMT_SCOPE scope)
 | 
			
		||||
	{
 | 
			
		||||
		if(value == 0)
 | 
			
		||||
			return false;
 | 
			
		||||
		
 | 
			
		||||
		_Set(m_indent, value, scope);
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	bool EmitterState::SetPreCommentIndent(unsigned value, FMT_SCOPE scope)
 | 
			
		||||
	{
 | 
			
		||||
		if(value == 0)
 | 
			
		||||
			return false;
 | 
			
		||||
		
 | 
			
		||||
		_Set(m_preCommentIndent, value, scope);
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	bool EmitterState::SetPostCommentIndent(unsigned value, FMT_SCOPE scope)
 | 
			
		||||
	{
 | 
			
		||||
		if(value == 0)
 | 
			
		||||
			return false;
 | 
			
		||||
		
 | 
			
		||||
		_Set(m_postCommentIndent, value, scope);
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	bool EmitterState::SetFlowType(GROUP_TYPE groupType, EMITTER_MANIP value, FMT_SCOPE scope)
 | 
			
		||||
	{
 | 
			
		||||
		switch(value) {
 | 
			
		||||
			case Block:
 | 
			
		||||
			case Flow:
 | 
			
		||||
				_Set(groupType == GT_SEQ ? m_seqFmt : m_mapFmt, value, scope);
 | 
			
		||||
				return true;
 | 
			
		||||
			default:
 | 
			
		||||
				return false;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	EMITTER_MANIP EmitterState::GetFlowType(GROUP_TYPE groupType) const
 | 
			
		||||
	{
 | 
			
		||||
		// force flow style if we're currently in a flow
 | 
			
		||||
		FLOW_TYPE flowType = GetCurGroupFlowType();
 | 
			
		||||
		if(flowType == FT_FLOW)
 | 
			
		||||
			return Flow;
 | 
			
		||||
		
 | 
			
		||||
		// otherwise, go with what's asked of use
 | 
			
		||||
		return (groupType == GT_SEQ ? m_seqFmt.get() : m_mapFmt.get());
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	bool EmitterState::SetMapKeyFormat(EMITTER_MANIP value, FMT_SCOPE scope)
 | 
			
		||||
	{
 | 
			
		||||
		switch(value) {
 | 
			
		||||
			case Auto:
 | 
			
		||||
			case LongKey:
 | 
			
		||||
				_Set(m_mapKeyFmt, value, scope);
 | 
			
		||||
				return true;
 | 
			
		||||
			default:
 | 
			
		||||
				return false;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										205
									
								
								libs/yaml-cpp/src/emitterstate.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										205
									
								
								libs/yaml-cpp/src/emitterstate.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,205 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#ifndef EMITTERSTATE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
 | 
			
		||||
#define EMITTERSTATE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include "setting.h"
 | 
			
		||||
#include "emittermanip.h"
 | 
			
		||||
#include <cassert>
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <stack>
 | 
			
		||||
#include <memory>
 | 
			
		||||
 | 
			
		||||
namespace YAML
 | 
			
		||||
{
 | 
			
		||||
	enum FMT_SCOPE {
 | 
			
		||||
		LOCAL,
 | 
			
		||||
		GLOBAL
 | 
			
		||||
	};
 | 
			
		||||
	
 | 
			
		||||
	enum GROUP_TYPE {
 | 
			
		||||
		GT_NONE,
 | 
			
		||||
		GT_SEQ,
 | 
			
		||||
		GT_MAP
 | 
			
		||||
	};
 | 
			
		||||
	
 | 
			
		||||
	enum FLOW_TYPE {
 | 
			
		||||
		FT_NONE,
 | 
			
		||||
		FT_FLOW,
 | 
			
		||||
		FT_BLOCK
 | 
			
		||||
	};
 | 
			
		||||
	
 | 
			
		||||
	enum NODE_STATE {
 | 
			
		||||
		NS_START,
 | 
			
		||||
		NS_READY_FOR_ATOM,
 | 
			
		||||
		NS_END
 | 
			
		||||
	};
 | 
			
		||||
	
 | 
			
		||||
	enum EMITTER_STATE {
 | 
			
		||||
		ES_WAITING_FOR_DOC,
 | 
			
		||||
		ES_WRITING_DOC,
 | 
			
		||||
		ES_DONE_WITH_DOC,
 | 
			
		||||
		
 | 
			
		||||
		// block seq
 | 
			
		||||
		ES_WAITING_FOR_BLOCK_SEQ_ENTRY,
 | 
			
		||||
		ES_WRITING_BLOCK_SEQ_ENTRY,
 | 
			
		||||
		ES_DONE_WITH_BLOCK_SEQ_ENTRY,
 | 
			
		||||
		
 | 
			
		||||
		// flow seq
 | 
			
		||||
		ES_WAITING_FOR_FLOW_SEQ_ENTRY,
 | 
			
		||||
		ES_WRITING_FLOW_SEQ_ENTRY,
 | 
			
		||||
		ES_DONE_WITH_FLOW_SEQ_ENTRY,
 | 
			
		||||
		
 | 
			
		||||
		// block map
 | 
			
		||||
		ES_WAITING_FOR_BLOCK_MAP_ENTRY,
 | 
			
		||||
		ES_WAITING_FOR_BLOCK_MAP_KEY,
 | 
			
		||||
		ES_WRITING_BLOCK_MAP_KEY,
 | 
			
		||||
		ES_DONE_WITH_BLOCK_MAP_KEY,
 | 
			
		||||
		ES_WAITING_FOR_BLOCK_MAP_VALUE,
 | 
			
		||||
		ES_WRITING_BLOCK_MAP_VALUE,
 | 
			
		||||
		ES_DONE_WITH_BLOCK_MAP_VALUE,
 | 
			
		||||
		
 | 
			
		||||
		// flow map
 | 
			
		||||
		ES_WAITING_FOR_FLOW_MAP_ENTRY,
 | 
			
		||||
		ES_WAITING_FOR_FLOW_MAP_KEY,
 | 
			
		||||
		ES_WRITING_FLOW_MAP_KEY,
 | 
			
		||||
		ES_DONE_WITH_FLOW_MAP_KEY,
 | 
			
		||||
		ES_WAITING_FOR_FLOW_MAP_VALUE,
 | 
			
		||||
		ES_WRITING_FLOW_MAP_VALUE,
 | 
			
		||||
		ES_DONE_WITH_FLOW_MAP_VALUE
 | 
			
		||||
	};
 | 
			
		||||
	
 | 
			
		||||
	class EmitterState
 | 
			
		||||
	{
 | 
			
		||||
	public:
 | 
			
		||||
		EmitterState();
 | 
			
		||||
		~EmitterState();
 | 
			
		||||
		
 | 
			
		||||
		// basic state checking
 | 
			
		||||
		bool good() const { return m_isGood; }
 | 
			
		||||
		const std::string GetLastError() const { return m_lastError; }
 | 
			
		||||
		void SetError(const std::string& error) { m_isGood = false; m_lastError = error; }
 | 
			
		||||
		
 | 
			
		||||
		// main state of the machine
 | 
			
		||||
		EMITTER_STATE GetCurState() const { return m_stateStack.top(); }
 | 
			
		||||
		void SwitchState(EMITTER_STATE state) { PopState(); PushState(state); }
 | 
			
		||||
		void PushState(EMITTER_STATE state) { m_stateStack.push(state); }
 | 
			
		||||
		void PopState() { m_stateStack.pop(); }
 | 
			
		||||
		
 | 
			
		||||
		void SetLocalValue(EMITTER_MANIP value);
 | 
			
		||||
		
 | 
			
		||||
		// group handling
 | 
			
		||||
		void BeginGroup(GROUP_TYPE type);
 | 
			
		||||
		void EndGroup(GROUP_TYPE type);
 | 
			
		||||
		
 | 
			
		||||
		GROUP_TYPE GetCurGroupType() const;
 | 
			
		||||
		FLOW_TYPE GetCurGroupFlowType() const;
 | 
			
		||||
		int GetCurIndent() const { return m_curIndent; }
 | 
			
		||||
		
 | 
			
		||||
		bool CurrentlyInLongKey();
 | 
			
		||||
		void StartLongKey();
 | 
			
		||||
		void StartSimpleKey();
 | 
			
		||||
 | 
			
		||||
		bool RequiresSeparation() const { return m_requiresSeparation; }
 | 
			
		||||
		void RequireSeparation() { m_requiresSeparation = true; }
 | 
			
		||||
		void UnsetSeparation() { m_requiresSeparation = false; }
 | 
			
		||||
 | 
			
		||||
		void ClearModifiedSettings();
 | 
			
		||||
 | 
			
		||||
		// formatters
 | 
			
		||||
		bool SetOutputCharset(EMITTER_MANIP value, FMT_SCOPE scope);
 | 
			
		||||
		EMITTER_MANIP GetOutputCharset() const { return m_charset.get(); }
 | 
			
		||||
 | 
			
		||||
		bool SetStringFormat(EMITTER_MANIP value, FMT_SCOPE scope);
 | 
			
		||||
		EMITTER_MANIP GetStringFormat() const { return m_strFmt.get(); }
 | 
			
		||||
		
 | 
			
		||||
		bool SetBoolFormat(EMITTER_MANIP value, FMT_SCOPE scope);
 | 
			
		||||
		EMITTER_MANIP GetBoolFormat() const { return m_boolFmt.get(); }
 | 
			
		||||
 | 
			
		||||
		bool SetBoolLengthFormat(EMITTER_MANIP value, FMT_SCOPE scope);
 | 
			
		||||
		EMITTER_MANIP GetBoolLengthFormat() const { return m_boolLengthFmt.get(); }
 | 
			
		||||
 | 
			
		||||
		bool SetBoolCaseFormat(EMITTER_MANIP value, FMT_SCOPE scope);
 | 
			
		||||
		EMITTER_MANIP GetBoolCaseFormat() const { return m_boolCaseFmt.get(); }
 | 
			
		||||
 | 
			
		||||
		bool SetIntFormat(EMITTER_MANIP value, FMT_SCOPE scope);
 | 
			
		||||
		EMITTER_MANIP GetIntFormat() const { return m_intFmt.get(); }
 | 
			
		||||
 | 
			
		||||
		bool SetIndent(unsigned value, FMT_SCOPE scope);
 | 
			
		||||
		int GetIndent() const { return m_indent.get(); }
 | 
			
		||||
		
 | 
			
		||||
		bool SetPreCommentIndent(unsigned value, FMT_SCOPE scope);
 | 
			
		||||
		int GetPreCommentIndent() const { return m_preCommentIndent.get(); }
 | 
			
		||||
		bool SetPostCommentIndent(unsigned value, FMT_SCOPE scope);
 | 
			
		||||
		int GetPostCommentIndent() const { return m_postCommentIndent.get(); }
 | 
			
		||||
		
 | 
			
		||||
		bool SetFlowType(GROUP_TYPE groupType, EMITTER_MANIP value, FMT_SCOPE scope);
 | 
			
		||||
		EMITTER_MANIP GetFlowType(GROUP_TYPE groupType) const;
 | 
			
		||||
		
 | 
			
		||||
		bool SetMapKeyFormat(EMITTER_MANIP value, FMT_SCOPE scope);
 | 
			
		||||
		EMITTER_MANIP GetMapKeyFormat() const { return m_mapKeyFmt.get(); }
 | 
			
		||||
		
 | 
			
		||||
	private:
 | 
			
		||||
		template <typename T>
 | 
			
		||||
		void _Set(Setting<T>& fmt, T value, FMT_SCOPE scope);
 | 
			
		||||
		
 | 
			
		||||
	private:
 | 
			
		||||
		// basic state ok?
 | 
			
		||||
		bool m_isGood;
 | 
			
		||||
		std::string m_lastError;
 | 
			
		||||
		
 | 
			
		||||
		// other state
 | 
			
		||||
		std::stack <EMITTER_STATE> m_stateStack;
 | 
			
		||||
		
 | 
			
		||||
		Setting <EMITTER_MANIP> m_charset;
 | 
			
		||||
		Setting <EMITTER_MANIP> m_strFmt;
 | 
			
		||||
		Setting <EMITTER_MANIP> m_boolFmt;
 | 
			
		||||
		Setting <EMITTER_MANIP> m_boolLengthFmt;
 | 
			
		||||
		Setting <EMITTER_MANIP> m_boolCaseFmt;
 | 
			
		||||
		Setting <EMITTER_MANIP> m_intFmt;
 | 
			
		||||
		Setting <unsigned> m_indent;
 | 
			
		||||
		Setting <unsigned> m_preCommentIndent, m_postCommentIndent;
 | 
			
		||||
		Setting <EMITTER_MANIP> m_seqFmt;
 | 
			
		||||
		Setting <EMITTER_MANIP> m_mapFmt;
 | 
			
		||||
		Setting <EMITTER_MANIP> m_mapKeyFmt;
 | 
			
		||||
		
 | 
			
		||||
		SettingChanges m_modifiedSettings;
 | 
			
		||||
		SettingChanges m_globalModifiedSettings;
 | 
			
		||||
		
 | 
			
		||||
		struct Group {
 | 
			
		||||
			Group(GROUP_TYPE type_): type(type_), usingLongKey(false), indent(0) {}
 | 
			
		||||
			
 | 
			
		||||
			GROUP_TYPE type;
 | 
			
		||||
			EMITTER_MANIP flow;
 | 
			
		||||
			bool usingLongKey;
 | 
			
		||||
			int indent;
 | 
			
		||||
			
 | 
			
		||||
			SettingChanges modifiedSettings;
 | 
			
		||||
		};
 | 
			
		||||
		
 | 
			
		||||
		std::auto_ptr <Group> _PopGroup();
 | 
			
		||||
		
 | 
			
		||||
		std::stack <Group *> m_groups;
 | 
			
		||||
		unsigned m_curIndent;
 | 
			
		||||
		bool m_requiresSeparation;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	template <typename T>
 | 
			
		||||
	void EmitterState::_Set(Setting<T>& fmt, T value, FMT_SCOPE scope) {
 | 
			
		||||
		switch(scope) {
 | 
			
		||||
			case LOCAL:
 | 
			
		||||
				m_modifiedSettings.push(fmt.set(value));
 | 
			
		||||
				break;
 | 
			
		||||
			case GLOBAL:
 | 
			
		||||
				fmt.set(value);
 | 
			
		||||
				m_globalModifiedSettings.push(fmt.set(value));  // this pushes an identity set, so when we restore,
 | 
			
		||||
				                                                // it restores to the value here, and not the previous one
 | 
			
		||||
				break;
 | 
			
		||||
			default:
 | 
			
		||||
				assert(false);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // EMITTERSTATE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
 | 
			
		||||
							
								
								
									
										316
									
								
								libs/yaml-cpp/src/emitterutils.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										316
									
								
								libs/yaml-cpp/src/emitterutils.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,316 @@
 | 
			
		||||
#include "emitterutils.h"
 | 
			
		||||
#include "exp.h"
 | 
			
		||||
#include "indentation.h"
 | 
			
		||||
#include "exceptions.h"
 | 
			
		||||
#include "stringsource.h"
 | 
			
		||||
#include <sstream>
 | 
			
		||||
#include <iomanip>
 | 
			
		||||
 | 
			
		||||
namespace YAML
 | 
			
		||||
{
 | 
			
		||||
	namespace Utils
 | 
			
		||||
	{
 | 
			
		||||
		namespace {
 | 
			
		||||
			enum {REPLACEMENT_CHARACTER = 0xFFFD};
 | 
			
		||||
 | 
			
		||||
			bool IsAnchorChar(int ch) { // test for ns-anchor-char
 | 
			
		||||
				switch (ch) {
 | 
			
		||||
					case ',': case '[': case ']': case '{': case '}': // c-flow-indicator
 | 
			
		||||
					case ' ': case '\t': // s-white
 | 
			
		||||
					case 0xFEFF: // c-byte-order-mark
 | 
			
		||||
					case 0xA: case 0xD: // b-char
 | 
			
		||||
						return false;
 | 
			
		||||
					case 0x85:
 | 
			
		||||
						return true;
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				if (ch < 0x20)
 | 
			
		||||
					return false;
 | 
			
		||||
 | 
			
		||||
				if (ch < 0x7E)
 | 
			
		||||
					return true;
 | 
			
		||||
 | 
			
		||||
				if (ch < 0xA0)
 | 
			
		||||
					return false;
 | 
			
		||||
				if (ch >= 0xD800 && ch <= 0xDFFF)
 | 
			
		||||
					return false;
 | 
			
		||||
				if ((ch & 0xFFFE) == 0xFFFE)
 | 
			
		||||
					return false;
 | 
			
		||||
				if ((ch >= 0xFDD0) && (ch <= 0xFDEF))
 | 
			
		||||
					return false;
 | 
			
		||||
				if (ch > 0x10FFFF)
 | 
			
		||||
					return false;
 | 
			
		||||
 | 
			
		||||
				return true;
 | 
			
		||||
			}
 | 
			
		||||
			
 | 
			
		||||
			int Utf8BytesIndicated(char ch) {
 | 
			
		||||
				int byteVal = static_cast<unsigned char>(ch);
 | 
			
		||||
				switch (byteVal >> 4) {
 | 
			
		||||
					case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
 | 
			
		||||
						return 1;
 | 
			
		||||
					case 12: case 13:
 | 
			
		||||
						return 2;
 | 
			
		||||
					case 14:
 | 
			
		||||
						return 3;
 | 
			
		||||
					case 15:
 | 
			
		||||
						return 4;
 | 
			
		||||
					default:
 | 
			
		||||
					  return -1;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			bool IsTrailingByte(char ch) {
 | 
			
		||||
				return (ch & 0xC0) == 0x80;
 | 
			
		||||
			}
 | 
			
		||||
			
 | 
			
		||||
			bool GetNextCodePointAndAdvance(int& codePoint, std::string::const_iterator& first, std::string::const_iterator last) {
 | 
			
		||||
				if (first == last)
 | 
			
		||||
					return false;
 | 
			
		||||
				
 | 
			
		||||
				int nBytes = Utf8BytesIndicated(*first);
 | 
			
		||||
				if (nBytes < 1) {
 | 
			
		||||
					// Bad lead byte
 | 
			
		||||
					++first;
 | 
			
		||||
					codePoint = REPLACEMENT_CHARACTER;
 | 
			
		||||
					return true;
 | 
			
		||||
				}
 | 
			
		||||
				
 | 
			
		||||
				if (nBytes == 1) {
 | 
			
		||||
					codePoint = *first++;
 | 
			
		||||
					return true;
 | 
			
		||||
				}
 | 
			
		||||
				
 | 
			
		||||
				// Gather bits from trailing bytes
 | 
			
		||||
				codePoint = static_cast<unsigned char>(*first) & ~(0xFF << (7 - nBytes));
 | 
			
		||||
				++first;
 | 
			
		||||
				--nBytes;
 | 
			
		||||
				for (; nBytes > 0; ++first, --nBytes) {
 | 
			
		||||
					if ((first == last) || !IsTrailingByte(*first)) {
 | 
			
		||||
						codePoint = REPLACEMENT_CHARACTER;
 | 
			
		||||
						break;
 | 
			
		||||
					}
 | 
			
		||||
					codePoint <<= 6;
 | 
			
		||||
					codePoint |= *first & 0x3F;
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				// Check for illegal code points
 | 
			
		||||
				if (codePoint > 0x10FFFF)
 | 
			
		||||
					codePoint = REPLACEMENT_CHARACTER;
 | 
			
		||||
				else if (codePoint >= 0xD800 && codePoint <= 0xDFFF)
 | 
			
		||||
					codePoint = REPLACEMENT_CHARACTER;
 | 
			
		||||
				else if ((codePoint & 0xFFFE) == 0xFFFE)
 | 
			
		||||
					codePoint = REPLACEMENT_CHARACTER;
 | 
			
		||||
				else if (codePoint >= 0xFDD0 && codePoint <= 0xFDEF)
 | 
			
		||||
					codePoint = REPLACEMENT_CHARACTER;
 | 
			
		||||
				return true;
 | 
			
		||||
			}
 | 
			
		||||
			
 | 
			
		||||
			void WriteCodePoint(ostream& out, int codePoint) {
 | 
			
		||||
				if (codePoint < 0 || codePoint > 0x10FFFF) {
 | 
			
		||||
					codePoint = REPLACEMENT_CHARACTER;
 | 
			
		||||
				}
 | 
			
		||||
				if (codePoint < 0x7F) {
 | 
			
		||||
					out << static_cast<char>(codePoint);
 | 
			
		||||
				} else if (codePoint < 0x7FF) {
 | 
			
		||||
					out << static_cast<char>(0xC0 | (codePoint >> 6))
 | 
			
		||||
					    << static_cast<char>(0x80 | (codePoint & 0x3F));
 | 
			
		||||
				} else if (codePoint < 0xFFFF) {
 | 
			
		||||
					out << static_cast<char>(0xE0 | (codePoint >> 12))
 | 
			
		||||
					    << static_cast<char>(0x80 | ((codePoint >> 6) & 0x3F))
 | 
			
		||||
					    << static_cast<char>(0x80 | (codePoint & 0x3F));
 | 
			
		||||
				} else {
 | 
			
		||||
					out << static_cast<char>(0xF0 | (codePoint >> 18))
 | 
			
		||||
					    << static_cast<char>(0x80 | ((codePoint >> 12) & 0x3F))
 | 
			
		||||
					    << static_cast<char>(0x80 | ((codePoint >> 6) & 0x3F))
 | 
			
		||||
					    << static_cast<char>(0x80 | (codePoint & 0x3F));
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			
 | 
			
		||||
			bool IsValidPlainScalar(const std::string& str, bool inFlow, bool allowOnlyAscii) {
 | 
			
		||||
				// first check the start
 | 
			
		||||
				const RegEx& start = (inFlow ? Exp::PlainScalarInFlow() : Exp::PlainScalar());
 | 
			
		||||
				if(!start.Matches(str))
 | 
			
		||||
					return false;
 | 
			
		||||
				
 | 
			
		||||
				// and check the end for plain whitespace (which can't be faithfully kept in a plain scalar)
 | 
			
		||||
				if(!str.empty() && *str.rbegin() == ' ')
 | 
			
		||||
					return false;
 | 
			
		||||
 | 
			
		||||
				// then check until something is disallowed
 | 
			
		||||
				const RegEx& disallowed = (inFlow ? Exp::EndScalarInFlow() : Exp::EndScalar())
 | 
			
		||||
				                          || (Exp::BlankOrBreak() + Exp::Comment())
 | 
			
		||||
				                          || Exp::NotPrintable()
 | 
			
		||||
				                          || Exp::Utf8_ByteOrderMark()
 | 
			
		||||
				                          || Exp::Break()
 | 
			
		||||
				                          || Exp::Tab();
 | 
			
		||||
				StringCharSource buffer(str.c_str(), str.size());
 | 
			
		||||
				while(buffer) {
 | 
			
		||||
					if(disallowed.Matches(buffer))
 | 
			
		||||
						return false;
 | 
			
		||||
					if(allowOnlyAscii && (0x7F < static_cast<unsigned char>(buffer[0]))) 
 | 
			
		||||
						return false;
 | 
			
		||||
					++buffer;
 | 
			
		||||
				}
 | 
			
		||||
				
 | 
			
		||||
				return true;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			void WriteDoubleQuoteEscapeSequence(ostream& out, int codePoint) {
 | 
			
		||||
				static const char hexDigits[] = "0123456789abcdef";
 | 
			
		||||
 | 
			
		||||
				char escSeq[] = "\\U00000000";
 | 
			
		||||
				int digits = 8;
 | 
			
		||||
				if (codePoint < 0xFF) {
 | 
			
		||||
					escSeq[1] = 'x';
 | 
			
		||||
					digits = 2;
 | 
			
		||||
				} else if (codePoint < 0xFFFF) {
 | 
			
		||||
					escSeq[1] = 'u';
 | 
			
		||||
					digits = 4;
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				// Write digits into the escape sequence
 | 
			
		||||
				int i = 2;
 | 
			
		||||
				for (; digits > 0; --digits, ++i) {
 | 
			
		||||
					escSeq[i] = hexDigits[(codePoint >> (4 * (digits - 1))) & 0xF];
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				escSeq[i] = 0; // terminate with NUL character
 | 
			
		||||
				out << escSeq;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			bool WriteAliasName(ostream& out, const std::string& str) {
 | 
			
		||||
				int codePoint;
 | 
			
		||||
				for(std::string::const_iterator i = str.begin();
 | 
			
		||||
					GetNextCodePointAndAdvance(codePoint, i, str.end());
 | 
			
		||||
					)
 | 
			
		||||
				{
 | 
			
		||||
					if (!IsAnchorChar(codePoint))
 | 
			
		||||
						return false;
 | 
			
		||||
 | 
			
		||||
					WriteCodePoint(out, codePoint);
 | 
			
		||||
				}
 | 
			
		||||
				return true;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		bool WriteString(ostream& out, const std::string& str, bool inFlow, bool escapeNonAscii)
 | 
			
		||||
		{
 | 
			
		||||
			if(IsValidPlainScalar(str, inFlow, escapeNonAscii)) {
 | 
			
		||||
				out << str;
 | 
			
		||||
				return true;
 | 
			
		||||
			} else
 | 
			
		||||
				return WriteDoubleQuotedString(out, str, escapeNonAscii);
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		bool WriteSingleQuotedString(ostream& out, const std::string& str)
 | 
			
		||||
		{
 | 
			
		||||
			out << "'";
 | 
			
		||||
			int codePoint;
 | 
			
		||||
			for(std::string::const_iterator i = str.begin();
 | 
			
		||||
				GetNextCodePointAndAdvance(codePoint, i, str.end());
 | 
			
		||||
				) 
 | 
			
		||||
			{
 | 
			
		||||
				if (codePoint == '\n')
 | 
			
		||||
					return false;  // We can't handle a new line and the attendant indentation yet
 | 
			
		||||
 | 
			
		||||
				if (codePoint == '\'')
 | 
			
		||||
					out << "''";
 | 
			
		||||
				else
 | 
			
		||||
					WriteCodePoint(out, codePoint);
 | 
			
		||||
			}
 | 
			
		||||
			out << "'";
 | 
			
		||||
			return true;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		bool WriteDoubleQuotedString(ostream& out, const std::string& str, bool escapeNonAscii)
 | 
			
		||||
		{
 | 
			
		||||
			out << "\"";
 | 
			
		||||
			int codePoint;
 | 
			
		||||
			for(std::string::const_iterator i = str.begin();
 | 
			
		||||
				GetNextCodePointAndAdvance(codePoint, i, str.end());
 | 
			
		||||
				) 
 | 
			
		||||
			{
 | 
			
		||||
				if (codePoint == '\"')
 | 
			
		||||
					out << "\\\"";
 | 
			
		||||
				else if (codePoint == '\\')
 | 
			
		||||
					out << "\\\\";
 | 
			
		||||
				else if (codePoint < 0x20 || (codePoint >= 0x80 && codePoint <= 0xA0)) // Control characters and non-breaking space
 | 
			
		||||
					WriteDoubleQuoteEscapeSequence(out, codePoint);
 | 
			
		||||
				else if (codePoint == 0xFEFF) // Byte order marks (ZWNS) should be escaped (YAML 1.2, sec. 5.2)	
 | 
			
		||||
					WriteDoubleQuoteEscapeSequence(out, codePoint);
 | 
			
		||||
				else if (escapeNonAscii && codePoint > 0x7E)
 | 
			
		||||
					WriteDoubleQuoteEscapeSequence(out, codePoint);
 | 
			
		||||
				else
 | 
			
		||||
					WriteCodePoint(out, codePoint);
 | 
			
		||||
			}
 | 
			
		||||
			out << "\"";
 | 
			
		||||
			return true;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		bool WriteLiteralString(ostream& out, const std::string& str, int indent)
 | 
			
		||||
		{
 | 
			
		||||
			out << "|\n";
 | 
			
		||||
			out << IndentTo(indent);
 | 
			
		||||
			int codePoint;
 | 
			
		||||
			for(std::string::const_iterator i = str.begin();
 | 
			
		||||
				GetNextCodePointAndAdvance(codePoint, i, str.end());
 | 
			
		||||
				)
 | 
			
		||||
			{
 | 
			
		||||
				if (codePoint == '\n')
 | 
			
		||||
				  out << "\n" << IndentTo(indent);
 | 
			
		||||
				else
 | 
			
		||||
				  WriteCodePoint(out, codePoint);
 | 
			
		||||
			}
 | 
			
		||||
			return true;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		bool WriteComment(ostream& out, const std::string& str, int postCommentIndent)
 | 
			
		||||
		{
 | 
			
		||||
			unsigned curIndent = out.col();
 | 
			
		||||
			out << "#" << Indentation(postCommentIndent);
 | 
			
		||||
			int codePoint;
 | 
			
		||||
			for(std::string::const_iterator i = str.begin();
 | 
			
		||||
				GetNextCodePointAndAdvance(codePoint, i, str.end());
 | 
			
		||||
				)
 | 
			
		||||
			{
 | 
			
		||||
				if(codePoint == '\n')
 | 
			
		||||
					out << "\n" << IndentTo(curIndent) << "#" << Indentation(postCommentIndent);
 | 
			
		||||
				else
 | 
			
		||||
					WriteCodePoint(out, codePoint);
 | 
			
		||||
			}
 | 
			
		||||
			return true;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		bool WriteAlias(ostream& out, const std::string& str)
 | 
			
		||||
		{
 | 
			
		||||
			out << "*";
 | 
			
		||||
			return WriteAliasName(out, str);
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		bool WriteAnchor(ostream& out, const std::string& str)
 | 
			
		||||
		{
 | 
			
		||||
			out << "&";
 | 
			
		||||
			return WriteAliasName(out, str);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		bool WriteTag(ostream& out, const std::string& str)
 | 
			
		||||
		{
 | 
			
		||||
			out << "!<";
 | 
			
		||||
			StringCharSource buffer(str.c_str(), str.size());
 | 
			
		||||
			while(buffer) {
 | 
			
		||||
				int n = Exp::URI().Match(buffer);
 | 
			
		||||
				if(n <= 0)
 | 
			
		||||
					return false;
 | 
			
		||||
 | 
			
		||||
				while(--n >= 0) {
 | 
			
		||||
					out << buffer[0];
 | 
			
		||||
					++buffer;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			out << ">";
 | 
			
		||||
			return true;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										25
									
								
								libs/yaml-cpp/src/emitterutils.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								libs/yaml-cpp/src/emitterutils.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,25 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#ifndef EMITTERUTILS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
 | 
			
		||||
#define EMITTERUTILS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include "ostream.h"
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
namespace YAML
 | 
			
		||||
{
 | 
			
		||||
	namespace Utils
 | 
			
		||||
	{
 | 
			
		||||
		bool WriteString(ostream& out, const std::string& str, bool inFlow, bool escapeNonAscii);
 | 
			
		||||
		bool WriteSingleQuotedString(ostream& out, const std::string& str);
 | 
			
		||||
		bool WriteDoubleQuotedString(ostream& out, const std::string& str, bool escapeNonAscii);
 | 
			
		||||
		bool WriteLiteralString(ostream& out, const std::string& str, int indent);
 | 
			
		||||
		bool WriteComment(ostream& out, const std::string& str, int postCommentIndent);
 | 
			
		||||
		bool WriteAlias(ostream& out, const std::string& str);
 | 
			
		||||
		bool WriteAnchor(ostream& out, const std::string& str);
 | 
			
		||||
		bool WriteTag(ostream& out, const std::string& str);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // EMITTERUTILS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
 | 
			
		||||
							
								
								
									
										113
									
								
								libs/yaml-cpp/src/exp.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										113
									
								
								libs/yaml-cpp/src/exp.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,113 @@
 | 
			
		||||
#include "exp.h"
 | 
			
		||||
#include "exceptions.h"
 | 
			
		||||
#include <sstream>
 | 
			
		||||
 | 
			
		||||
namespace YAML
 | 
			
		||||
{
 | 
			
		||||
	namespace Exp
 | 
			
		||||
	{
 | 
			
		||||
		unsigned ParseHex(const std::string& str, const Mark& mark)
 | 
			
		||||
		{
 | 
			
		||||
			unsigned value = 0;
 | 
			
		||||
			for(std::size_t i=0;i<str.size();i++) {
 | 
			
		||||
				char ch = str[i];
 | 
			
		||||
				int digit = 0;
 | 
			
		||||
				if('a' <= ch && ch <= 'f')
 | 
			
		||||
					digit = ch - 'a' + 10;
 | 
			
		||||
				else if('A' <= ch && ch <= 'F')
 | 
			
		||||
					digit = ch - 'A' + 10;
 | 
			
		||||
				else if('0' <= ch && ch <= '9')
 | 
			
		||||
					digit = ch - '0';
 | 
			
		||||
				else
 | 
			
		||||
					throw ParserException(mark, ErrorMsg::INVALID_HEX);
 | 
			
		||||
 | 
			
		||||
				value = (value << 4) + digit;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			return value;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		std::string Str(unsigned ch)
 | 
			
		||||
		{
 | 
			
		||||
			return std::string(1, static_cast<char>(ch));
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Escape
 | 
			
		||||
		// . Translates the next 'codeLength' characters into a hex number and returns the result.
 | 
			
		||||
		// . Throws if it's not actually hex.
 | 
			
		||||
		std::string Escape(Stream& in, int codeLength)
 | 
			
		||||
		{
 | 
			
		||||
			// grab string
 | 
			
		||||
			std::string str;
 | 
			
		||||
			for(int i=0;i<codeLength;i++)
 | 
			
		||||
				str += in.get();
 | 
			
		||||
 | 
			
		||||
			// get the value
 | 
			
		||||
			unsigned value = ParseHex(str, in.mark());
 | 
			
		||||
 | 
			
		||||
			// legal unicode?
 | 
			
		||||
			if((value >= 0xD800 && value <= 0xDFFF) || value > 0x10FFFF) {
 | 
			
		||||
				std::stringstream msg;
 | 
			
		||||
				msg << ErrorMsg::INVALID_UNICODE << value;
 | 
			
		||||
				throw ParserException(in.mark(), msg.str());
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// now break it up into chars
 | 
			
		||||
			if(value <= 0x7F)
 | 
			
		||||
				return Str(value);
 | 
			
		||||
			else if(value <= 0x7FF)
 | 
			
		||||
				return Str(0xC0 + (value >> 6)) + Str(0x80 + (value & 0x3F));
 | 
			
		||||
			else if(value <= 0xFFFF)
 | 
			
		||||
				return Str(0xE0 + (value >> 12)) + Str(0x80 + ((value >> 6) & 0x3F)) + Str(0x80 + (value & 0x3F));
 | 
			
		||||
			else
 | 
			
		||||
				return Str(0xF0 + (value >> 18)) + Str(0x80 + ((value >> 12) & 0x3F)) +
 | 
			
		||||
					Str(0x80 + ((value >> 6) & 0x3F)) + Str(0x80 + (value & 0x3F));
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Escape
 | 
			
		||||
		// . Escapes the sequence starting 'in' (it must begin with a '\' or single quote)
 | 
			
		||||
		//   and returns the result.
 | 
			
		||||
		// . Throws if it's an unknown escape character.
 | 
			
		||||
		std::string Escape(Stream& in)
 | 
			
		||||
		{
 | 
			
		||||
			// eat slash
 | 
			
		||||
			char escape = in.get();
 | 
			
		||||
 | 
			
		||||
			// switch on escape character
 | 
			
		||||
			char ch = in.get();
 | 
			
		||||
 | 
			
		||||
			// first do single quote, since it's easier
 | 
			
		||||
			if(escape == '\'' && ch == '\'')
 | 
			
		||||
				return "\'";
 | 
			
		||||
 | 
			
		||||
			// now do the slash (we're not gonna check if it's a slash - you better pass one!)
 | 
			
		||||
			switch(ch) {
 | 
			
		||||
				case '0': return std::string(1, '\x00');
 | 
			
		||||
				case 'a': return "\x07";
 | 
			
		||||
				case 'b': return "\x08";
 | 
			
		||||
				case 't':
 | 
			
		||||
                case '\t': return "\x09";
 | 
			
		||||
				case 'n': return "\x0A";
 | 
			
		||||
				case 'v': return "\x0B";
 | 
			
		||||
				case 'f': return "\x0C";
 | 
			
		||||
				case 'r': return "\x0D";
 | 
			
		||||
				case 'e': return "\x1B";
 | 
			
		||||
				case ' ': return "\x20";
 | 
			
		||||
				case '\"': return "\"";
 | 
			
		||||
				case '\'': return "\'";
 | 
			
		||||
				case '\\': return "\\";
 | 
			
		||||
				case '/': return "/";
 | 
			
		||||
				case 'N': return "\x85";
 | 
			
		||||
				case '_': return "\xA0";
 | 
			
		||||
				case 'L': return "\xE2\x80\xA8";  // LS (#x2028)
 | 
			
		||||
				case 'P': return "\xE2\x80\xA9";  // PS (#x2029)
 | 
			
		||||
				case 'x': return Escape(in, 2);
 | 
			
		||||
				case 'u': return Escape(in, 4);
 | 
			
		||||
				case 'U': return Escape(in, 8);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			std::stringstream msg;
 | 
			
		||||
			throw ParserException(in.mark(), ErrorMsg::INVALID_ESCAPE + ch);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										190
									
								
								libs/yaml-cpp/src/exp.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										190
									
								
								libs/yaml-cpp/src/exp.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,190 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#ifndef EXP_H_62B23520_7C8E_11DE_8A39_0800200C9A66
 | 
			
		||||
#define EXP_H_62B23520_7C8E_11DE_8A39_0800200C9A66
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include "regex.h"
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <ios>
 | 
			
		||||
#include "stream.h"
 | 
			
		||||
 | 
			
		||||
namespace YAML
 | 
			
		||||
{
 | 
			
		||||
	////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
	// Here we store a bunch of expressions for matching different parts of the file.
 | 
			
		||||
 | 
			
		||||
	namespace Exp
 | 
			
		||||
	{
 | 
			
		||||
		// misc
 | 
			
		||||
		inline const RegEx& Space() {
 | 
			
		||||
			static const RegEx e = RegEx(' ');
 | 
			
		||||
			return e;
 | 
			
		||||
		}
 | 
			
		||||
		inline const RegEx& Tab() {
 | 
			
		||||
			static const RegEx e = RegEx('\t');
 | 
			
		||||
			return e;
 | 
			
		||||
		}
 | 
			
		||||
		inline const RegEx& Blank() {
 | 
			
		||||
			static const RegEx e = Space() || Tab();
 | 
			
		||||
			return e;
 | 
			
		||||
		}
 | 
			
		||||
		inline const RegEx& Break() {
 | 
			
		||||
			static const RegEx e = RegEx('\n') || RegEx("\r\n");
 | 
			
		||||
			return e;
 | 
			
		||||
		}
 | 
			
		||||
		inline const RegEx& BlankOrBreak() {
 | 
			
		||||
			static const RegEx e = Blank() || Break();
 | 
			
		||||
			return e;
 | 
			
		||||
		}
 | 
			
		||||
		inline const RegEx& Digit() {
 | 
			
		||||
			static const RegEx e = RegEx('0', '9');
 | 
			
		||||
			return e;
 | 
			
		||||
		}
 | 
			
		||||
		inline const RegEx& Alpha() {
 | 
			
		||||
			static const RegEx e = RegEx('a', 'z') || RegEx('A', 'Z');
 | 
			
		||||
			return e;
 | 
			
		||||
		}
 | 
			
		||||
		inline const RegEx& AlphaNumeric() {
 | 
			
		||||
			static const RegEx e = Alpha() || Digit();
 | 
			
		||||
			return e;
 | 
			
		||||
		}
 | 
			
		||||
		inline const RegEx& Word() {
 | 
			
		||||
			static const RegEx e = AlphaNumeric() || RegEx('-');
 | 
			
		||||
			return e;
 | 
			
		||||
		}
 | 
			
		||||
		inline const RegEx& Hex() {
 | 
			
		||||
			static const RegEx e = Digit() || RegEx('A', 'F') || RegEx('a', 'f');
 | 
			
		||||
			return e;
 | 
			
		||||
		}
 | 
			
		||||
		// Valid Unicode code points that are not part of c-printable (YAML 1.2, sec. 5.1)
 | 
			
		||||
		inline const RegEx& NotPrintable() {
 | 
			
		||||
			static const RegEx e = RegEx(0) || 
 | 
			
		||||
				RegEx("\x01\x02\x03\x04\x05\x06\x07\x08\x0B\x0C\x7F", REGEX_OR) || 
 | 
			
		||||
				RegEx(0x0E, 0x1F) ||
 | 
			
		||||
				(RegEx('\xC2') + (RegEx('\x80', '\x84') || RegEx('\x86', '\x9F')));
 | 
			
		||||
			return e;
 | 
			
		||||
		}
 | 
			
		||||
		inline const RegEx& Utf8_ByteOrderMark() {
 | 
			
		||||
			static const RegEx e = RegEx("\xEF\xBB\xBF");
 | 
			
		||||
			return e;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// actual tags
 | 
			
		||||
 | 
			
		||||
		inline const RegEx& DocStart() {
 | 
			
		||||
			static const RegEx e = RegEx("---") + (BlankOrBreak() || RegEx());
 | 
			
		||||
			return e;
 | 
			
		||||
		}
 | 
			
		||||
		inline const RegEx& DocEnd() {
 | 
			
		||||
			static const RegEx e = RegEx("...") + (BlankOrBreak() || RegEx());
 | 
			
		||||
			return e;
 | 
			
		||||
		}
 | 
			
		||||
		inline const RegEx& DocIndicator() {
 | 
			
		||||
			static const RegEx e = DocStart() || DocEnd();
 | 
			
		||||
			return e;
 | 
			
		||||
		}
 | 
			
		||||
		inline const RegEx& BlockEntry() {
 | 
			
		||||
			static const RegEx e = RegEx('-') + (BlankOrBreak() || RegEx());
 | 
			
		||||
			return e;
 | 
			
		||||
		}
 | 
			
		||||
		inline const RegEx& Key() {
 | 
			
		||||
			static const RegEx e = RegEx('?');
 | 
			
		||||
			return e;
 | 
			
		||||
		}
 | 
			
		||||
		inline const RegEx& KeyInFlow() {
 | 
			
		||||
			static const RegEx e = RegEx('?') + BlankOrBreak();
 | 
			
		||||
			return e;
 | 
			
		||||
		}
 | 
			
		||||
		inline const RegEx& Value() {
 | 
			
		||||
			static const RegEx e = RegEx(':') + (BlankOrBreak() || RegEx());
 | 
			
		||||
			return e;
 | 
			
		||||
		}
 | 
			
		||||
		inline const RegEx& ValueInFlow() {
 | 
			
		||||
			static const RegEx e = RegEx(':') + (BlankOrBreak() || RegEx(",}", REGEX_OR));
 | 
			
		||||
			return e;
 | 
			
		||||
		}
 | 
			
		||||
		inline const RegEx& ValueInJSONFlow() {
 | 
			
		||||
			static const RegEx e = RegEx(':');
 | 
			
		||||
			return e;
 | 
			
		||||
		}
 | 
			
		||||
		inline const RegEx Comment() {
 | 
			
		||||
			static const RegEx e = RegEx('#');
 | 
			
		||||
			return e;
 | 
			
		||||
		}
 | 
			
		||||
		inline const RegEx& AnchorEnd() {
 | 
			
		||||
			static const RegEx e = RegEx("?:,]}%@`", REGEX_OR) || BlankOrBreak();
 | 
			
		||||
			return e;
 | 
			
		||||
		}
 | 
			
		||||
		inline const RegEx& URI() {
 | 
			
		||||
			static const RegEx e = Word() || RegEx("#;/?:@&=+$,_.!~*'()[]", REGEX_OR) || (RegEx('%') + Hex() + Hex());
 | 
			
		||||
			return e;
 | 
			
		||||
		}
 | 
			
		||||
		inline const RegEx& Tag() {
 | 
			
		||||
			static const RegEx e = Word() || RegEx("#;/?:@&=+$_.~*'", REGEX_OR) || (RegEx('%') + Hex() + Hex());
 | 
			
		||||
			return e;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Plain scalar rules:
 | 
			
		||||
		// . Cannot start with a blank.
 | 
			
		||||
		// . Can never start with any of , [ ] { } # & * ! | > \' \" % @ `
 | 
			
		||||
		// . In the block context - ? : must be not be followed with a space.
 | 
			
		||||
		// . In the flow context ? is illegal and : and - must not be followed with a space.
 | 
			
		||||
		inline const RegEx& PlainScalar() {
 | 
			
		||||
			static const RegEx e = !(BlankOrBreak() || RegEx(",[]{}#&*!|>\'\"%@`", REGEX_OR) || (RegEx("-?:", REGEX_OR) + Blank()));
 | 
			
		||||
			return e;
 | 
			
		||||
		}
 | 
			
		||||
		inline const RegEx& PlainScalarInFlow() {
 | 
			
		||||
			static const RegEx e = !(BlankOrBreak() || RegEx("?,[]{}#&*!|>\'\"%@`", REGEX_OR) || (RegEx("-:", REGEX_OR) + Blank()));
 | 
			
		||||
			return e;
 | 
			
		||||
		}
 | 
			
		||||
		inline const RegEx& EndScalar() {
 | 
			
		||||
			static const RegEx e = RegEx(':') + (BlankOrBreak() || RegEx());
 | 
			
		||||
			return e;
 | 
			
		||||
		}
 | 
			
		||||
		inline const RegEx& EndScalarInFlow() {
 | 
			
		||||
			static const RegEx e = (RegEx(':') + (BlankOrBreak() || RegEx(",]}", REGEX_OR))) || RegEx(",?[]{}", REGEX_OR);
 | 
			
		||||
			return e;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		inline const RegEx& EscSingleQuote() {
 | 
			
		||||
			static const RegEx e = RegEx("\'\'");
 | 
			
		||||
			return e;
 | 
			
		||||
		}
 | 
			
		||||
		inline const RegEx& EscBreak() {
 | 
			
		||||
			static const RegEx e = RegEx('\\') + Break();
 | 
			
		||||
			return e;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		inline const RegEx& ChompIndicator() {
 | 
			
		||||
			static const RegEx e = RegEx("+-", REGEX_OR);
 | 
			
		||||
			return e;
 | 
			
		||||
		}
 | 
			
		||||
		inline const RegEx& Chomp() {
 | 
			
		||||
			static const RegEx e = (ChompIndicator() + Digit()) || (Digit() + ChompIndicator()) || ChompIndicator() || Digit();
 | 
			
		||||
			return e;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// and some functions
 | 
			
		||||
		std::string Escape(Stream& in);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	namespace Keys
 | 
			
		||||
	{
 | 
			
		||||
		const char Directive = '%';
 | 
			
		||||
		const char FlowSeqStart = '[';
 | 
			
		||||
		const char FlowSeqEnd = ']';
 | 
			
		||||
		const char FlowMapStart = '{';
 | 
			
		||||
		const char FlowMapEnd = '}';
 | 
			
		||||
		const char FlowEntry = ',';
 | 
			
		||||
		const char Alias = '*';
 | 
			
		||||
		const char Anchor = '&';
 | 
			
		||||
		const char Tag = '!';
 | 
			
		||||
		const char LiteralScalar = '|';
 | 
			
		||||
		const char FoldedScalar = '>';
 | 
			
		||||
		const char VerbatimTagStart = '<';
 | 
			
		||||
		const char VerbatimTagEnd = '>';
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // EXP_H_62B23520_7C8E_11DE_8A39_0800200C9A66
 | 
			
		||||
							
								
								
									
										36
									
								
								libs/yaml-cpp/src/indentation.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								libs/yaml-cpp/src/indentation.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,36 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#ifndef INDENTATION_H_62B23520_7C8E_11DE_8A39_0800200C9A66
 | 
			
		||||
#define INDENTATION_H_62B23520_7C8E_11DE_8A39_0800200C9A66
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include "ostream.h"
 | 
			
		||||
#include <iostream>
 | 
			
		||||
 | 
			
		||||
namespace YAML
 | 
			
		||||
{
 | 
			
		||||
	struct Indentation {
 | 
			
		||||
		Indentation(unsigned n_): n(n_) {}
 | 
			
		||||
		unsigned n;
 | 
			
		||||
	};
 | 
			
		||||
	
 | 
			
		||||
	inline ostream& operator << (ostream& out, const Indentation& indent) {
 | 
			
		||||
		for(unsigned i=0;i<indent.n;i++)
 | 
			
		||||
			out << ' ';
 | 
			
		||||
		return out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	struct IndentTo {
 | 
			
		||||
		IndentTo(unsigned n_): n(n_) {}
 | 
			
		||||
		unsigned n;
 | 
			
		||||
	};
 | 
			
		||||
	
 | 
			
		||||
	inline ostream& operator << (ostream& out, const IndentTo& indent) {
 | 
			
		||||
		while(out.col() < indent.n)
 | 
			
		||||
			out << ' ';
 | 
			
		||||
		return out;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif // INDENTATION_H_62B23520_7C8E_11DE_8A39_0800200C9A66
 | 
			
		||||
							
								
								
									
										107
									
								
								libs/yaml-cpp/src/iterator.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										107
									
								
								libs/yaml-cpp/src/iterator.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,107 @@
 | 
			
		||||
#include "node.h"
 | 
			
		||||
#include "exceptions.h"
 | 
			
		||||
#include "iterpriv.h"
 | 
			
		||||
 | 
			
		||||
namespace YAML
 | 
			
		||||
{
 | 
			
		||||
	Iterator::Iterator(): m_pData(0)
 | 
			
		||||
	{
 | 
			
		||||
		m_pData = new IterPriv;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Iterator::Iterator(IterPriv *pData): m_pData(pData)
 | 
			
		||||
	{
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Iterator::Iterator(const Iterator& rhs): m_pData(0)
 | 
			
		||||
	{
 | 
			
		||||
		m_pData = new IterPriv(*rhs.m_pData);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Iterator& Iterator::operator = (const Iterator& rhs)
 | 
			
		||||
	{
 | 
			
		||||
		if(this == &rhs)
 | 
			
		||||
			return *this;
 | 
			
		||||
 | 
			
		||||
		delete m_pData;
 | 
			
		||||
		m_pData = new IterPriv(*rhs.m_pData);
 | 
			
		||||
		return *this;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Iterator::~Iterator()
 | 
			
		||||
	{
 | 
			
		||||
		delete m_pData;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Iterator& Iterator::operator ++ ()
 | 
			
		||||
	{
 | 
			
		||||
		if(m_pData->type == IterPriv::IT_SEQ)
 | 
			
		||||
			++m_pData->seqIter;
 | 
			
		||||
		else if(m_pData->type == IterPriv::IT_MAP)
 | 
			
		||||
			++m_pData->mapIter;
 | 
			
		||||
 | 
			
		||||
		return *this;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Iterator Iterator::operator ++ (int)
 | 
			
		||||
	{
 | 
			
		||||
		Iterator temp = *this;
 | 
			
		||||
 | 
			
		||||
		if(m_pData->type == IterPriv::IT_SEQ)
 | 
			
		||||
			++m_pData->seqIter;
 | 
			
		||||
		else if(m_pData->type == IterPriv::IT_MAP)
 | 
			
		||||
			++m_pData->mapIter;
 | 
			
		||||
 | 
			
		||||
		return temp;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	const Node& Iterator::operator * () const
 | 
			
		||||
	{
 | 
			
		||||
		if(m_pData->type == IterPriv::IT_SEQ)
 | 
			
		||||
			return **m_pData->seqIter;
 | 
			
		||||
 | 
			
		||||
		throw BadDereference();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	const Node *Iterator::operator -> () const
 | 
			
		||||
	{
 | 
			
		||||
		if(m_pData->type == IterPriv::IT_SEQ)
 | 
			
		||||
			return *m_pData->seqIter;
 | 
			
		||||
 | 
			
		||||
		throw BadDereference();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	const Node& Iterator::first() const
 | 
			
		||||
	{
 | 
			
		||||
		if(m_pData->type == IterPriv::IT_MAP)
 | 
			
		||||
			return *m_pData->mapIter->first;
 | 
			
		||||
 | 
			
		||||
		throw BadDereference();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	const Node& Iterator::second() const
 | 
			
		||||
	{
 | 
			
		||||
		if(m_pData->type == IterPriv::IT_MAP)
 | 
			
		||||
			return *m_pData->mapIter->second;
 | 
			
		||||
 | 
			
		||||
		throw BadDereference();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	bool operator == (const Iterator& it, const Iterator& jt)
 | 
			
		||||
	{
 | 
			
		||||
		if(it.m_pData->type != jt.m_pData->type)
 | 
			
		||||
			return false;
 | 
			
		||||
 | 
			
		||||
		if(it.m_pData->type == IterPriv::IT_SEQ)
 | 
			
		||||
			return it.m_pData->seqIter == jt.m_pData->seqIter;
 | 
			
		||||
		else if(it.m_pData->type == IterPriv::IT_MAP)
 | 
			
		||||
			return it.m_pData->mapIter == jt.m_pData->mapIter;
 | 
			
		||||
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	bool operator != (const Iterator& it, const Iterator& jt)
 | 
			
		||||
	{
 | 
			
		||||
		return !(it == jt);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										31
									
								
								libs/yaml-cpp/src/iterpriv.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								libs/yaml-cpp/src/iterpriv.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,31 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#ifndef ITERPRIV_H_62B23520_7C8E_11DE_8A39_0800200C9A66
 | 
			
		||||
#define ITERPRIV_H_62B23520_7C8E_11DE_8A39_0800200C9A66
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include "ltnode.h"
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <map>
 | 
			
		||||
 | 
			
		||||
namespace YAML
 | 
			
		||||
{
 | 
			
		||||
	class Node;
 | 
			
		||||
 | 
			
		||||
	// IterPriv
 | 
			
		||||
	// . The implementation for iterators - essentially a union of sequence and map iterators.
 | 
			
		||||
	struct IterPriv
 | 
			
		||||
	{
 | 
			
		||||
		IterPriv(): type(IT_NONE) {}
 | 
			
		||||
		IterPriv(std::vector <Node *>::const_iterator it): type(IT_SEQ), seqIter(it) {}
 | 
			
		||||
		IterPriv(std::map <Node *, Node *, ltnode>::const_iterator it): type(IT_MAP), mapIter(it) {}
 | 
			
		||||
 | 
			
		||||
		enum ITER_TYPE { IT_NONE, IT_SEQ, IT_MAP };
 | 
			
		||||
		ITER_TYPE type;
 | 
			
		||||
 | 
			
		||||
		std::vector <Node *>::const_iterator seqIter;
 | 
			
		||||
		std::map <Node *, Node *, ltnode>::const_iterator mapIter;
 | 
			
		||||
	};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // ITERPRIV_H_62B23520_7C8E_11DE_8A39_0800200C9A66
 | 
			
		||||
							
								
								
									
										16
									
								
								libs/yaml-cpp/src/ltnode.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								libs/yaml-cpp/src/ltnode.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,16 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#ifndef LTNODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
 | 
			
		||||
#define LTNODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
namespace YAML
 | 
			
		||||
{
 | 
			
		||||
	class Node;
 | 
			
		||||
 | 
			
		||||
	struct ltnode {
 | 
			
		||||
		bool operator()(const Node *pNode1, const Node *pNode2) const;
 | 
			
		||||
	};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // LTNODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
 | 
			
		||||
							
								
								
									
										238
									
								
								libs/yaml-cpp/src/map.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										238
									
								
								libs/yaml-cpp/src/map.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,238 @@
 | 
			
		||||
#include "map.h"
 | 
			
		||||
#include "node.h"
 | 
			
		||||
#include "scanner.h"
 | 
			
		||||
#include "token.h"
 | 
			
		||||
#include "exceptions.h"
 | 
			
		||||
#include "emitter.h"
 | 
			
		||||
 | 
			
		||||
namespace YAML
 | 
			
		||||
{
 | 
			
		||||
	Map::Map()
 | 
			
		||||
	{
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	Map::Map(const node_map& data)
 | 
			
		||||
	{
 | 
			
		||||
		for(node_map::const_iterator it=data.begin();it!=data.end();++it) {
 | 
			
		||||
			std::auto_ptr<Node> pKey = it->first->Clone();
 | 
			
		||||
			std::auto_ptr<Node> pValue = it->second->Clone();
 | 
			
		||||
			AddEntry(pKey, pValue);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Map::~Map()
 | 
			
		||||
	{
 | 
			
		||||
		Clear();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void Map::Clear()
 | 
			
		||||
	{
 | 
			
		||||
		for(node_map::const_iterator it=m_data.begin();it!=m_data.end();++it) {
 | 
			
		||||
			delete it->first;
 | 
			
		||||
			delete it->second;
 | 
			
		||||
		}
 | 
			
		||||
		m_data.clear();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Content *Map::Clone() const
 | 
			
		||||
	{
 | 
			
		||||
		return new Map(m_data);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	bool Map::GetBegin(std::map <Node *, Node *, ltnode>::const_iterator& it) const
 | 
			
		||||
	{
 | 
			
		||||
		it = m_data.begin();
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	bool Map::GetEnd(std::map <Node *, Node *, ltnode>::const_iterator& it) const
 | 
			
		||||
	{
 | 
			
		||||
		it = m_data.end();
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	std::size_t Map::GetSize() const
 | 
			
		||||
	{
 | 
			
		||||
		return m_data.size();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void Map::Parse(Scanner *pScanner, ParserState& state)
 | 
			
		||||
	{
 | 
			
		||||
		Clear();
 | 
			
		||||
 | 
			
		||||
		// split based on start token
 | 
			
		||||
		switch(pScanner->peek().type) {
 | 
			
		||||
			case Token::BLOCK_MAP_START: ParseBlock(pScanner, state); break;
 | 
			
		||||
			case Token::FLOW_MAP_START: ParseFlow(pScanner, state); break;
 | 
			
		||||
			case Token::KEY: ParseCompact(pScanner, state); break;
 | 
			
		||||
			case Token::VALUE: ParseCompactWithNoKey(pScanner, state); break;
 | 
			
		||||
			default: break;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void Map::ParseBlock(Scanner *pScanner, ParserState& state)
 | 
			
		||||
	{
 | 
			
		||||
		// eat start token
 | 
			
		||||
		pScanner->pop();
 | 
			
		||||
		state.PushCollectionType(ParserState::BLOCK_MAP);
 | 
			
		||||
 | 
			
		||||
		while(1) {
 | 
			
		||||
			if(pScanner->empty())
 | 
			
		||||
				throw ParserException(Mark::null(), ErrorMsg::END_OF_MAP);
 | 
			
		||||
 | 
			
		||||
			Token token = pScanner->peek();
 | 
			
		||||
			if(token.type != Token::KEY && token.type != Token::VALUE && token.type != Token::BLOCK_MAP_END)
 | 
			
		||||
				throw ParserException(token.mark, ErrorMsg::END_OF_MAP);
 | 
			
		||||
 | 
			
		||||
			if(token.type == Token::BLOCK_MAP_END) {
 | 
			
		||||
				pScanner->pop();
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			std::auto_ptr <Node> pKey(new Node), pValue(new Node);
 | 
			
		||||
			
 | 
			
		||||
			// grab key (if non-null)
 | 
			
		||||
			if(token.type == Token::KEY) {
 | 
			
		||||
				pScanner->pop();
 | 
			
		||||
				pKey->Parse(pScanner, state);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// now grab value (optional)
 | 
			
		||||
			if(!pScanner->empty() && pScanner->peek().type == Token::VALUE) {
 | 
			
		||||
				pScanner->pop();
 | 
			
		||||
				pValue->Parse(pScanner, state);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			AddEntry(pKey, pValue);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		state.PopCollectionType(ParserState::BLOCK_MAP);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void Map::ParseFlow(Scanner *pScanner, ParserState& state)
 | 
			
		||||
	{
 | 
			
		||||
		// eat start token
 | 
			
		||||
		pScanner->pop();
 | 
			
		||||
		state.PushCollectionType(ParserState::FLOW_MAP);
 | 
			
		||||
 | 
			
		||||
		while(1) {
 | 
			
		||||
			if(pScanner->empty())
 | 
			
		||||
				throw ParserException(Mark::null(), ErrorMsg::END_OF_MAP_FLOW);
 | 
			
		||||
 | 
			
		||||
			Token& token = pScanner->peek();
 | 
			
		||||
			// first check for end
 | 
			
		||||
			if(token.type == Token::FLOW_MAP_END) {
 | 
			
		||||
				pScanner->pop();
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
			
 | 
			
		||||
			std::auto_ptr <Node> pKey(new Node), pValue(new Node);
 | 
			
		||||
 | 
			
		||||
			// grab key (if non-null)
 | 
			
		||||
			if(token.type == Token::KEY) {
 | 
			
		||||
				pScanner->pop();
 | 
			
		||||
				pKey->Parse(pScanner, state);
 | 
			
		||||
			}
 | 
			
		||||
			
 | 
			
		||||
			// now grab value (optional)
 | 
			
		||||
			if(!pScanner->empty() && pScanner->peek().type == Token::VALUE) {
 | 
			
		||||
				pScanner->pop();
 | 
			
		||||
				pValue->Parse(pScanner, state);
 | 
			
		||||
			}
 | 
			
		||||
			
 | 
			
		||||
			// now eat the separator (or could be a map end, which we ignore - but if it's neither, then it's a bad node)
 | 
			
		||||
			Token& nextToken = pScanner->peek();
 | 
			
		||||
			if(nextToken.type == Token::FLOW_ENTRY)
 | 
			
		||||
				pScanner->pop();
 | 
			
		||||
			else if(nextToken.type != Token::FLOW_MAP_END)
 | 
			
		||||
				throw ParserException(nextToken.mark, ErrorMsg::END_OF_MAP_FLOW);
 | 
			
		||||
 | 
			
		||||
			AddEntry(pKey, pValue);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		state.PopCollectionType(ParserState::FLOW_MAP);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// ParseCompact
 | 
			
		||||
	// . Single "key: value" pair in a flow sequence
 | 
			
		||||
	void Map::ParseCompact(Scanner *pScanner, ParserState& state)
 | 
			
		||||
	{
 | 
			
		||||
		state.PushCollectionType(ParserState::COMPACT_MAP);
 | 
			
		||||
		std::auto_ptr <Node> pKey(new Node), pValue(new Node);
 | 
			
		||||
 | 
			
		||||
		// grab key
 | 
			
		||||
		pScanner->pop();
 | 
			
		||||
		pKey->Parse(pScanner, state);
 | 
			
		||||
			
 | 
			
		||||
		// now grab value (optional)
 | 
			
		||||
		if(!pScanner->empty() && pScanner->peek().type == Token::VALUE) {
 | 
			
		||||
			pScanner->pop();
 | 
			
		||||
			pValue->Parse(pScanner, state);
 | 
			
		||||
		}
 | 
			
		||||
			
 | 
			
		||||
		AddEntry(pKey, pValue);
 | 
			
		||||
		state.PopCollectionType(ParserState::COMPACT_MAP);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	// ParseCompactWithNoKey
 | 
			
		||||
	// . Single ": value" pair in a flow sequence
 | 
			
		||||
	void Map::ParseCompactWithNoKey(Scanner *pScanner, ParserState& state)
 | 
			
		||||
	{
 | 
			
		||||
		state.PushCollectionType(ParserState::COMPACT_MAP);
 | 
			
		||||
		std::auto_ptr <Node> pKey(new Node), pValue(new Node);
 | 
			
		||||
 | 
			
		||||
		// grab value
 | 
			
		||||
		pScanner->pop();
 | 
			
		||||
		pValue->Parse(pScanner, state);
 | 
			
		||||
 | 
			
		||||
		AddEntry(pKey, pValue);
 | 
			
		||||
		state.PopCollectionType(ParserState::COMPACT_MAP);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	void Map::AddEntry(std::auto_ptr<Node> pKey, std::auto_ptr<Node> pValue)
 | 
			
		||||
	{
 | 
			
		||||
		node_map::const_iterator it = m_data.find(pKey.get());
 | 
			
		||||
		if(it != m_data.end())
 | 
			
		||||
			return;
 | 
			
		||||
		
 | 
			
		||||
		m_data[pKey.release()] = pValue.release();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void Map::Write(Emitter& out) const
 | 
			
		||||
	{
 | 
			
		||||
		out << BeginMap;
 | 
			
		||||
		for(node_map::const_iterator it=m_data.begin();it!=m_data.end();++it)
 | 
			
		||||
			out << Key << *it->first << Value << *it->second;
 | 
			
		||||
		out << EndMap;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	int Map::Compare(Content *pContent)
 | 
			
		||||
	{
 | 
			
		||||
		return -pContent->Compare(this);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	int Map::Compare(Map *pMap)
 | 
			
		||||
	{
 | 
			
		||||
		node_map::const_iterator it = m_data.begin(), jt = pMap->m_data.begin();
 | 
			
		||||
		while(1) {
 | 
			
		||||
			if(it == m_data.end()) {
 | 
			
		||||
				if(jt == pMap->m_data.end())
 | 
			
		||||
					return 0;
 | 
			
		||||
				else
 | 
			
		||||
					return -1;
 | 
			
		||||
			}
 | 
			
		||||
			if(jt == pMap->m_data.end())
 | 
			
		||||
				return 1;
 | 
			
		||||
 | 
			
		||||
			int cmp = it->first->Compare(*jt->first);
 | 
			
		||||
			if(cmp != 0)
 | 
			
		||||
				return cmp;
 | 
			
		||||
 | 
			
		||||
			cmp = it->second->Compare(*jt->second);
 | 
			
		||||
			if(cmp != 0)
 | 
			
		||||
				return cmp;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										55
									
								
								libs/yaml-cpp/src/map.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								libs/yaml-cpp/src/map.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,55 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#ifndef MAP_H_62B23520_7C8E_11DE_8A39_0800200C9A66
 | 
			
		||||
#define MAP_H_62B23520_7C8E_11DE_8A39_0800200C9A66
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include "content.h"
 | 
			
		||||
#include <map>
 | 
			
		||||
#include <memory>
 | 
			
		||||
 | 
			
		||||
namespace YAML
 | 
			
		||||
{
 | 
			
		||||
	class Node;
 | 
			
		||||
 | 
			
		||||
	class Map: public Content
 | 
			
		||||
	{
 | 
			
		||||
	private:
 | 
			
		||||
		typedef std::map <Node *, Node *, ltnode> node_map;
 | 
			
		||||
 | 
			
		||||
	public:
 | 
			
		||||
		Map();
 | 
			
		||||
		Map(const node_map& data);
 | 
			
		||||
		virtual ~Map();
 | 
			
		||||
 | 
			
		||||
		void Clear();
 | 
			
		||||
		virtual Content *Clone() const;
 | 
			
		||||
 | 
			
		||||
		virtual bool GetBegin(std::map <Node *, Node *, ltnode>::const_iterator& it) const;
 | 
			
		||||
		virtual bool GetEnd(std::map <Node *, Node *, ltnode>::const_iterator& it) const;
 | 
			
		||||
		virtual std::size_t GetSize() const;
 | 
			
		||||
		virtual void Parse(Scanner *pScanner, ParserState& state);
 | 
			
		||||
		virtual void Write(Emitter& out) const;
 | 
			
		||||
 | 
			
		||||
		virtual bool IsMap() const { return true; }
 | 
			
		||||
 | 
			
		||||
		// ordering
 | 
			
		||||
		virtual int Compare(Content *pContent);
 | 
			
		||||
		virtual int Compare(Scalar *) { return 1; }
 | 
			
		||||
		virtual int Compare(Sequence *) { return 1; }
 | 
			
		||||
		virtual int Compare(Map *pMap);
 | 
			
		||||
 | 
			
		||||
	private:
 | 
			
		||||
		void ParseBlock(Scanner *pScanner, ParserState& state);
 | 
			
		||||
		void ParseFlow(Scanner *pScanner, ParserState& state);
 | 
			
		||||
		void ParseCompact(Scanner *pScanner, ParserState& state);
 | 
			
		||||
		void ParseCompactWithNoKey(Scanner *pScanner, ParserState& state);
 | 
			
		||||
		
 | 
			
		||||
		void AddEntry(std::auto_ptr<Node> pKey, std::auto_ptr<Node> pValue);
 | 
			
		||||
 | 
			
		||||
	private:
 | 
			
		||||
		node_map m_data;
 | 
			
		||||
	};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // MAP_H_62B23520_7C8E_11DE_8A39_0800200C9A66
 | 
			
		||||
							
								
								
									
										303
									
								
								libs/yaml-cpp/src/node.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										303
									
								
								libs/yaml-cpp/src/node.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,303 @@
 | 
			
		||||
#include "node.h"
 | 
			
		||||
#include "token.h"
 | 
			
		||||
#include "scanner.h"
 | 
			
		||||
#include "content.h"
 | 
			
		||||
#include "parser.h"
 | 
			
		||||
#include "scalar.h"
 | 
			
		||||
#include "sequence.h"
 | 
			
		||||
#include "map.h"
 | 
			
		||||
#include "aliascontent.h"
 | 
			
		||||
#include "iterpriv.h"
 | 
			
		||||
#include "emitter.h"
 | 
			
		||||
#include "tag.h"
 | 
			
		||||
#include <stdexcept>
 | 
			
		||||
 | 
			
		||||
namespace YAML
 | 
			
		||||
{
 | 
			
		||||
	// the ordering!
 | 
			
		||||
	bool ltnode::operator ()(const Node *pNode1, const Node *pNode2) const
 | 
			
		||||
	{
 | 
			
		||||
		return *pNode1 < *pNode2;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Node::Node(): m_pContent(0), m_alias(false), m_pIdentity(this), m_referenced(true)
 | 
			
		||||
	{
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Node::Node(const Mark& mark, const std::string& anchor, const std::string& tag, const Content *pContent)
 | 
			
		||||
	: m_mark(mark), m_anchor(anchor), m_tag(tag), m_pContent(0), m_alias(false), m_pIdentity(this), m_referenced(false)
 | 
			
		||||
	{
 | 
			
		||||
		if(pContent)
 | 
			
		||||
			m_pContent = pContent->Clone();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Node::~Node()
 | 
			
		||||
	{
 | 
			
		||||
		Clear();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void Node::Clear()
 | 
			
		||||
	{
 | 
			
		||||
		delete m_pContent;
 | 
			
		||||
		m_pContent = 0;
 | 
			
		||||
		m_alias = false;
 | 
			
		||||
		m_referenced = false;
 | 
			
		||||
		m_anchor.clear();
 | 
			
		||||
		m_tag.clear();
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	std::auto_ptr<Node> Node::Clone() const
 | 
			
		||||
	{
 | 
			
		||||
		if(m_alias)
 | 
			
		||||
			throw std::runtime_error("yaml-cpp: Can't clone alias");  // TODO: what to do about aliases?
 | 
			
		||||
		
 | 
			
		||||
		return std::auto_ptr<Node> (new Node(m_mark, m_anchor, m_tag, m_pContent));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void Node::Parse(Scanner *pScanner, ParserState& state)
 | 
			
		||||
	{
 | 
			
		||||
		Clear();
 | 
			
		||||
 | 
			
		||||
		// an empty node *is* a possibility
 | 
			
		||||
		if(pScanner->empty())
 | 
			
		||||
			return;
 | 
			
		||||
 | 
			
		||||
		// save location
 | 
			
		||||
		m_mark = pScanner->peek().mark;
 | 
			
		||||
		
 | 
			
		||||
		// special case: a value node by itself must be a map, with no header
 | 
			
		||||
		if(pScanner->peek().type == Token::VALUE) {
 | 
			
		||||
			m_pContent = new Map;
 | 
			
		||||
			m_pContent->Parse(pScanner, state);
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		ParseHeader(pScanner, state);
 | 
			
		||||
 | 
			
		||||
		// is this an alias? if so, its contents are an alias to
 | 
			
		||||
		// a previously defined anchor
 | 
			
		||||
		if(m_alias) {
 | 
			
		||||
			// the scanner throws an exception if it doesn't know this anchor name
 | 
			
		||||
			const Node *pReferencedNode = pScanner->Retrieve(m_anchor);
 | 
			
		||||
			m_pIdentity = pReferencedNode;
 | 
			
		||||
 | 
			
		||||
			// mark the referenced node for the sake of the client code
 | 
			
		||||
			pReferencedNode->m_referenced = true;
 | 
			
		||||
 | 
			
		||||
			// use of an Alias object keeps the referenced content from
 | 
			
		||||
			// being deleted twice
 | 
			
		||||
			Content *pAliasedContent = pReferencedNode->m_pContent;
 | 
			
		||||
			if(pAliasedContent)
 | 
			
		||||
				m_pContent = new AliasContent(pAliasedContent);
 | 
			
		||||
			
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// now split based on what kind of node we should be
 | 
			
		||||
		switch(pScanner->peek().type) {
 | 
			
		||||
			case Token::SCALAR:
 | 
			
		||||
				m_pContent = new Scalar;
 | 
			
		||||
				break;
 | 
			
		||||
			case Token::FLOW_SEQ_START:
 | 
			
		||||
			case Token::BLOCK_SEQ_START:
 | 
			
		||||
				m_pContent = new Sequence;
 | 
			
		||||
				break;
 | 
			
		||||
			case Token::FLOW_MAP_START:
 | 
			
		||||
			case Token::BLOCK_MAP_START:
 | 
			
		||||
				m_pContent = new Map;
 | 
			
		||||
				break;
 | 
			
		||||
			case Token::KEY:
 | 
			
		||||
				// compact maps can only go in a flow sequence
 | 
			
		||||
				if(state.GetCurCollectionType() == ParserState::FLOW_SEQ)
 | 
			
		||||
					m_pContent = new Map;
 | 
			
		||||
				break;
 | 
			
		||||
			default:
 | 
			
		||||
				break;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Have to save anchor before parsing to allow for aliases as
 | 
			
		||||
		// contained node (recursive structure)
 | 
			
		||||
		if(!m_anchor.empty())
 | 
			
		||||
			pScanner->Save(m_anchor, this);
 | 
			
		||||
 | 
			
		||||
		if(m_pContent)
 | 
			
		||||
			m_pContent->Parse(pScanner, state);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// ParseHeader
 | 
			
		||||
	// . Grabs any tag, alias, or anchor tokens and deals with them.
 | 
			
		||||
	void Node::ParseHeader(Scanner *pScanner, ParserState& state)
 | 
			
		||||
	{
 | 
			
		||||
		while(1) {
 | 
			
		||||
			if(pScanner->empty())
 | 
			
		||||
				return;
 | 
			
		||||
 | 
			
		||||
			switch(pScanner->peek().type) {
 | 
			
		||||
				case Token::TAG: ParseTag(pScanner, state); break;
 | 
			
		||||
				case Token::ANCHOR: ParseAnchor(pScanner, state); break;
 | 
			
		||||
				case Token::ALIAS: ParseAlias(pScanner, state); break;
 | 
			
		||||
				default: return;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void Node::ParseTag(Scanner *pScanner, ParserState& state)
 | 
			
		||||
	{
 | 
			
		||||
		Token& token = pScanner->peek();
 | 
			
		||||
		if(m_tag != "")
 | 
			
		||||
			throw ParserException(token.mark, ErrorMsg::MULTIPLE_TAGS);
 | 
			
		||||
 | 
			
		||||
		Tag tag(token);
 | 
			
		||||
		m_tag = tag.Translate(state);
 | 
			
		||||
		pScanner->pop();
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	void Node::ParseAnchor(Scanner *pScanner, ParserState& /*state*/)
 | 
			
		||||
	{
 | 
			
		||||
		Token& token = pScanner->peek();
 | 
			
		||||
		if(m_anchor != "")
 | 
			
		||||
			throw ParserException(token.mark, ErrorMsg::MULTIPLE_ANCHORS);
 | 
			
		||||
 | 
			
		||||
		m_anchor = token.value;
 | 
			
		||||
		m_alias = false;
 | 
			
		||||
		pScanner->pop();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void Node::ParseAlias(Scanner *pScanner, ParserState& /*state*/)
 | 
			
		||||
	{
 | 
			
		||||
		Token& token = pScanner->peek();
 | 
			
		||||
		if(m_anchor != "")
 | 
			
		||||
			throw ParserException(token.mark, ErrorMsg::MULTIPLE_ALIASES);
 | 
			
		||||
		if(m_tag != "")
 | 
			
		||||
			throw ParserException(token.mark, ErrorMsg::ALIAS_CONTENT);
 | 
			
		||||
 | 
			
		||||
		m_anchor = token.value;
 | 
			
		||||
		m_alias = true;
 | 
			
		||||
		pScanner->pop();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	CONTENT_TYPE Node::GetType() const
 | 
			
		||||
	{
 | 
			
		||||
		if(!m_pContent)
 | 
			
		||||
			return CT_NONE;
 | 
			
		||||
 | 
			
		||||
		if(m_pContent->IsScalar())
 | 
			
		||||
			return CT_SCALAR;
 | 
			
		||||
		else if(m_pContent->IsSequence())
 | 
			
		||||
			return CT_SEQUENCE;
 | 
			
		||||
		else if(m_pContent->IsMap())
 | 
			
		||||
			return CT_MAP;
 | 
			
		||||
			
 | 
			
		||||
		return CT_NONE;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// begin
 | 
			
		||||
	// Returns an iterator to the beginning of this (sequence or map).
 | 
			
		||||
	Iterator Node::begin() const
 | 
			
		||||
	{
 | 
			
		||||
		if(!m_pContent)
 | 
			
		||||
			return Iterator();
 | 
			
		||||
 | 
			
		||||
		std::vector <Node *>::const_iterator seqIter;
 | 
			
		||||
		if(m_pContent->GetBegin(seqIter))
 | 
			
		||||
			return Iterator(new IterPriv(seqIter));
 | 
			
		||||
 | 
			
		||||
		std::map <Node *, Node *, ltnode>::const_iterator mapIter;
 | 
			
		||||
		if(m_pContent->GetBegin(mapIter))
 | 
			
		||||
			return Iterator(new IterPriv(mapIter));
 | 
			
		||||
 | 
			
		||||
		return Iterator();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// end
 | 
			
		||||
	// . Returns an iterator to the end of this (sequence or map).
 | 
			
		||||
	Iterator Node::end() const
 | 
			
		||||
	{
 | 
			
		||||
		if(!m_pContent)
 | 
			
		||||
			return Iterator();
 | 
			
		||||
 | 
			
		||||
		std::vector <Node *>::const_iterator seqIter;
 | 
			
		||||
		if(m_pContent->GetEnd(seqIter))
 | 
			
		||||
			return Iterator(new IterPriv(seqIter));
 | 
			
		||||
 | 
			
		||||
		std::map <Node *, Node *, ltnode>::const_iterator mapIter;
 | 
			
		||||
		if(m_pContent->GetEnd(mapIter))
 | 
			
		||||
			return Iterator(new IterPriv(mapIter));
 | 
			
		||||
 | 
			
		||||
		return Iterator();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// size
 | 
			
		||||
	// . Returns the size of this node, if it's a sequence node.
 | 
			
		||||
	// . Otherwise, returns zero.
 | 
			
		||||
	std::size_t Node::size() const
 | 
			
		||||
	{
 | 
			
		||||
		if(!m_pContent)
 | 
			
		||||
			return 0;
 | 
			
		||||
 | 
			
		||||
		return m_pContent->GetSize();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	const Node *Node::FindAtIndex(std::size_t i) const
 | 
			
		||||
	{
 | 
			
		||||
		if(!m_pContent)
 | 
			
		||||
			return 0;
 | 
			
		||||
		
 | 
			
		||||
		return m_pContent->GetNode(i);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	bool Node::GetScalar(std::string& s) const
 | 
			
		||||
	{
 | 
			
		||||
		if(!m_pContent) {
 | 
			
		||||
			if(m_tag.empty())
 | 
			
		||||
				s = "~";
 | 
			
		||||
			else
 | 
			
		||||
				s = "";
 | 
			
		||||
			return true;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		return m_pContent->GetScalar(s);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Emitter& operator << (Emitter& out, const Node& node)
 | 
			
		||||
	{
 | 
			
		||||
		// write anchor/alias
 | 
			
		||||
		if(node.m_anchor != "") {
 | 
			
		||||
			if(node.m_alias)
 | 
			
		||||
				out << Alias(node.m_anchor);
 | 
			
		||||
			else
 | 
			
		||||
				out << Anchor(node.m_anchor);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if(node.m_tag != "")
 | 
			
		||||
			out << VerbatimTag(node.m_tag);
 | 
			
		||||
 | 
			
		||||
		// write content
 | 
			
		||||
		if(node.m_pContent)
 | 
			
		||||
			node.m_pContent->Write(out);
 | 
			
		||||
		else if(!node.m_alias)
 | 
			
		||||
			out << Null;
 | 
			
		||||
 | 
			
		||||
		return out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	int Node::Compare(const Node& rhs) const
 | 
			
		||||
	{
 | 
			
		||||
		// Step 1: no content is the smallest
 | 
			
		||||
		if(!m_pContent) {
 | 
			
		||||
			if(rhs.m_pContent)
 | 
			
		||||
				return -1;
 | 
			
		||||
			else
 | 
			
		||||
				return 0;
 | 
			
		||||
		}
 | 
			
		||||
		if(!rhs.m_pContent)
 | 
			
		||||
			return 1;
 | 
			
		||||
 | 
			
		||||
		return m_pContent->Compare(rhs.m_pContent);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	bool operator < (const Node& n1, const Node& n2)
 | 
			
		||||
	{
 | 
			
		||||
		return n1.Compare(n2) < 0;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										12
									
								
								libs/yaml-cpp/src/null.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								libs/yaml-cpp/src/null.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
			
		||||
#include "null.h"
 | 
			
		||||
#include "node.h"
 | 
			
		||||
 | 
			
		||||
namespace YAML
 | 
			
		||||
{
 | 
			
		||||
	_Null Null;
 | 
			
		||||
 | 
			
		||||
	bool IsNull(const Node& node)
 | 
			
		||||
	{
 | 
			
		||||
		return node.Read(Null);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										64
									
								
								libs/yaml-cpp/src/ostream.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								libs/yaml-cpp/src/ostream.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,64 @@
 | 
			
		||||
#include "ostream.h"
 | 
			
		||||
#include <cstring>
 | 
			
		||||
 | 
			
		||||
namespace YAML
 | 
			
		||||
{
 | 
			
		||||
	ostream::ostream(): m_buffer(0), m_pos(0), m_size(0), m_row(0), m_col(0)
 | 
			
		||||
	{
 | 
			
		||||
		reserve(1024);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	ostream::~ostream()
 | 
			
		||||
	{
 | 
			
		||||
		delete [] m_buffer;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	void ostream::reserve(unsigned size)
 | 
			
		||||
	{
 | 
			
		||||
		if(size <= m_size)
 | 
			
		||||
			return;
 | 
			
		||||
		
 | 
			
		||||
		char *newBuffer = new char[size];
 | 
			
		||||
		std::memset(newBuffer, 0, size * sizeof(char));
 | 
			
		||||
		std::memcpy(newBuffer, m_buffer, m_size * sizeof(char));
 | 
			
		||||
		delete [] m_buffer;
 | 
			
		||||
		m_buffer = newBuffer;
 | 
			
		||||
		m_size = size;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	void ostream::put(char ch)
 | 
			
		||||
	{
 | 
			
		||||
		if(m_pos >= m_size - 1)   // an extra space for the NULL terminator
 | 
			
		||||
			reserve(m_size * 2);
 | 
			
		||||
		
 | 
			
		||||
		m_buffer[m_pos] = ch;
 | 
			
		||||
		m_pos++;
 | 
			
		||||
		
 | 
			
		||||
		if(ch == '\n') {
 | 
			
		||||
			m_row++;
 | 
			
		||||
			m_col = 0;
 | 
			
		||||
		} else
 | 
			
		||||
			m_col++;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ostream& operator << (ostream& out, const char *str)
 | 
			
		||||
	{
 | 
			
		||||
		std::size_t length = std::strlen(str);
 | 
			
		||||
		for(std::size_t i=0;i<length;i++)
 | 
			
		||||
			out.put(str[i]);
 | 
			
		||||
		return out;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	ostream& operator << (ostream& out, const std::string& str)
 | 
			
		||||
	{
 | 
			
		||||
		for(std::size_t i=0;i<str.size();i++)
 | 
			
		||||
			out.put(str[i]);
 | 
			
		||||
		return out;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	ostream& operator << (ostream& out, char ch)
 | 
			
		||||
	{
 | 
			
		||||
		out.put(ch);
 | 
			
		||||
		return out;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										155
									
								
								libs/yaml-cpp/src/parser.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										155
									
								
								libs/yaml-cpp/src/parser.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,155 @@
 | 
			
		||||
#include "parser.h"
 | 
			
		||||
#include "scanner.h"
 | 
			
		||||
#include "token.h"
 | 
			
		||||
#include "exceptions.h"
 | 
			
		||||
#include "parserstate.h"
 | 
			
		||||
#include <sstream>
 | 
			
		||||
#include <cstdio>
 | 
			
		||||
 | 
			
		||||
namespace YAML
 | 
			
		||||
{
 | 
			
		||||
	Parser::Parser()
 | 
			
		||||
	{
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	Parser::Parser(std::istream& in)
 | 
			
		||||
	{
 | 
			
		||||
		Load(in);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Parser::~Parser()
 | 
			
		||||
	{
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Parser::operator bool() const
 | 
			
		||||
	{
 | 
			
		||||
		return m_pScanner.get() && !m_pScanner->empty();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void Parser::Load(std::istream& in)
 | 
			
		||||
	{
 | 
			
		||||
		m_pScanner.reset(new Scanner(in));
 | 
			
		||||
		m_pState.reset(new ParserState);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// GetNextDocument
 | 
			
		||||
	// . Reads the next document in the queue (of tokens).
 | 
			
		||||
	// . Throws a ParserException on error.
 | 
			
		||||
	bool Parser::GetNextDocument(Node& document)
 | 
			
		||||
	{
 | 
			
		||||
		if(!m_pScanner.get())
 | 
			
		||||
			return false;
 | 
			
		||||
		
 | 
			
		||||
		// clear node
 | 
			
		||||
		document.Clear();
 | 
			
		||||
 | 
			
		||||
		// first read directives
 | 
			
		||||
		ParseDirectives();
 | 
			
		||||
 | 
			
		||||
		// we better have some tokens in the queue
 | 
			
		||||
		if(m_pScanner->empty())
 | 
			
		||||
			return false;
 | 
			
		||||
 | 
			
		||||
		// first eat doc start (optional)
 | 
			
		||||
		if(m_pScanner->peek().type == Token::DOC_START)
 | 
			
		||||
			m_pScanner->pop();
 | 
			
		||||
 | 
			
		||||
		// now parse our root node
 | 
			
		||||
		document.Parse(m_pScanner.get(), *m_pState);
 | 
			
		||||
 | 
			
		||||
		// and finally eat any doc ends we see
 | 
			
		||||
		while(!m_pScanner->empty() && m_pScanner->peek().type == Token::DOC_END)
 | 
			
		||||
			m_pScanner->pop();
 | 
			
		||||
 | 
			
		||||
		// clear anchors from the scanner, which are no longer relevant
 | 
			
		||||
		m_pScanner->ClearAnchors();
 | 
			
		||||
		
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// ParseDirectives
 | 
			
		||||
	// . Reads any directives that are next in the queue.
 | 
			
		||||
	void Parser::ParseDirectives()
 | 
			
		||||
	{
 | 
			
		||||
		bool readDirective = false;
 | 
			
		||||
 | 
			
		||||
		while(1) {
 | 
			
		||||
			if(m_pScanner->empty())
 | 
			
		||||
				break;
 | 
			
		||||
 | 
			
		||||
			Token& token = m_pScanner->peek();
 | 
			
		||||
			if(token.type != Token::DIRECTIVE)
 | 
			
		||||
				break;
 | 
			
		||||
 | 
			
		||||
			// we keep the directives from the last document if none are specified;
 | 
			
		||||
			// but if any directives are specific, then we reset them
 | 
			
		||||
			if(!readDirective)
 | 
			
		||||
				m_pState.reset(new ParserState);
 | 
			
		||||
 | 
			
		||||
			readDirective = true;
 | 
			
		||||
			HandleDirective(token);
 | 
			
		||||
			m_pScanner->pop();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void Parser::HandleDirective(const Token& token)
 | 
			
		||||
	{
 | 
			
		||||
		if(token.value == "YAML")
 | 
			
		||||
			HandleYamlDirective(token);
 | 
			
		||||
		else if(token.value == "TAG")
 | 
			
		||||
			HandleTagDirective(token);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// HandleYamlDirective
 | 
			
		||||
	// . Should be of the form 'major.minor' (like a version number)
 | 
			
		||||
	void Parser::HandleYamlDirective(const Token& token)
 | 
			
		||||
	{
 | 
			
		||||
		if(token.params.size() != 1)
 | 
			
		||||
			throw ParserException(token.mark, ErrorMsg::YAML_DIRECTIVE_ARGS);
 | 
			
		||||
		
 | 
			
		||||
		if(!m_pState->version.isDefault)
 | 
			
		||||
			throw ParserException(token.mark, ErrorMsg::REPEATED_YAML_DIRECTIVE);
 | 
			
		||||
 | 
			
		||||
		std::stringstream str(token.params[0]);
 | 
			
		||||
		str >> m_pState->version.major;
 | 
			
		||||
		str.get();
 | 
			
		||||
		str >> m_pState->version.minor;
 | 
			
		||||
		if(!str || str.peek() != EOF)
 | 
			
		||||
			throw ParserException(token.mark, ErrorMsg::YAML_VERSION + token.params[0]);
 | 
			
		||||
 | 
			
		||||
		if(m_pState->version.major > 1)
 | 
			
		||||
			throw ParserException(token.mark, ErrorMsg::YAML_MAJOR_VERSION);
 | 
			
		||||
 | 
			
		||||
		m_pState->version.isDefault = false;
 | 
			
		||||
		// TODO: warning on major == 1, minor > 2?
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// HandleTagDirective
 | 
			
		||||
	// . Should be of the form 'handle prefix', where 'handle' is converted to 'prefix' in the file.
 | 
			
		||||
	void Parser::HandleTagDirective(const Token& token)
 | 
			
		||||
	{
 | 
			
		||||
		if(token.params.size() != 2)
 | 
			
		||||
			throw ParserException(token.mark, ErrorMsg::TAG_DIRECTIVE_ARGS);
 | 
			
		||||
 | 
			
		||||
		const std::string& handle = token.params[0];
 | 
			
		||||
		const std::string& prefix = token.params[1];
 | 
			
		||||
		if(m_pState->tags.find(handle) != m_pState->tags.end())
 | 
			
		||||
			throw ParserException(token.mark, ErrorMsg::REPEATED_TAG_DIRECTIVE);
 | 
			
		||||
		
 | 
			
		||||
		m_pState->tags[handle] = prefix;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void Parser::PrintTokens(std::ostream& out)
 | 
			
		||||
	{
 | 
			
		||||
		if(!m_pScanner.get())
 | 
			
		||||
			return;
 | 
			
		||||
		
 | 
			
		||||
		while(1) {
 | 
			
		||||
			if(m_pScanner->empty())
 | 
			
		||||
				break;
 | 
			
		||||
 | 
			
		||||
			out << m_pScanner->peek() << "\n";
 | 
			
		||||
			m_pScanner->pop();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										24
									
								
								libs/yaml-cpp/src/parserstate.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								libs/yaml-cpp/src/parserstate.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,24 @@
 | 
			
		||||
#include "parserstate.h"
 | 
			
		||||
 | 
			
		||||
namespace YAML
 | 
			
		||||
{
 | 
			
		||||
	ParserState::ParserState()
 | 
			
		||||
	{
 | 
			
		||||
		// version
 | 
			
		||||
		version.isDefault = true;
 | 
			
		||||
		version.major = 1;
 | 
			
		||||
		version.minor = 2;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	const std::string ParserState::TranslateTagHandle(const std::string& handle) const
 | 
			
		||||
	{
 | 
			
		||||
		std::map <std::string, std::string>::const_iterator it = tags.find(handle);
 | 
			
		||||
		if(it == tags.end()) {
 | 
			
		||||
			if(handle == "!!")
 | 
			
		||||
				return "tag:yaml.org,2002:";
 | 
			
		||||
			return handle;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return it->second;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										37
									
								
								libs/yaml-cpp/src/parserstate.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								libs/yaml-cpp/src/parserstate.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,37 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#ifndef PARSERSTATE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
 | 
			
		||||
#define PARSERSTATE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <map>
 | 
			
		||||
#include <stack>
 | 
			
		||||
#include <cassert>
 | 
			
		||||
 | 
			
		||||
namespace YAML
 | 
			
		||||
{
 | 
			
		||||
	struct Version {
 | 
			
		||||
		bool isDefault;
 | 
			
		||||
		int major, minor;
 | 
			
		||||
	};
 | 
			
		||||
	
 | 
			
		||||
	struct ParserState
 | 
			
		||||
	{
 | 
			
		||||
		enum COLLECTION_TYPE { NONE, BLOCK_MAP, BLOCK_SEQ, FLOW_MAP, FLOW_SEQ, COMPACT_MAP };
 | 
			
		||||
		
 | 
			
		||||
		ParserState();
 | 
			
		||||
 | 
			
		||||
		const std::string TranslateTagHandle(const std::string& handle) const;
 | 
			
		||||
		COLLECTION_TYPE GetCurCollectionType() const { if(collectionStack.empty()) return NONE; return collectionStack.top(); }
 | 
			
		||||
		
 | 
			
		||||
		void PushCollectionType(COLLECTION_TYPE type) { collectionStack.push(type); }
 | 
			
		||||
		void PopCollectionType(COLLECTION_TYPE type) { assert(type == GetCurCollectionType()); collectionStack.pop(); }
 | 
			
		||||
	
 | 
			
		||||
		Version version;
 | 
			
		||||
		std::map <std::string, std::string> tags;
 | 
			
		||||
		std::stack <COLLECTION_TYPE> collectionStack;
 | 
			
		||||
	};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // PARSERSTATE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
 | 
			
		||||
							
								
								
									
										60
									
								
								libs/yaml-cpp/src/regex.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								libs/yaml-cpp/src/regex.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,60 @@
 | 
			
		||||
#include "regex.h"
 | 
			
		||||
 | 
			
		||||
namespace YAML
 | 
			
		||||
{
 | 
			
		||||
	// constructors
 | 
			
		||||
	RegEx::RegEx(): m_op(REGEX_EMPTY)
 | 
			
		||||
	{
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	RegEx::RegEx(REGEX_OP op): m_op(op)
 | 
			
		||||
	{
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	RegEx::RegEx(char ch): m_op(REGEX_MATCH), m_a(ch)
 | 
			
		||||
	{
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	RegEx::RegEx(char a, char z): m_op(REGEX_RANGE), m_a(a), m_z(z)
 | 
			
		||||
	{
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	RegEx::RegEx(const std::string& str, REGEX_OP op): m_op(op)
 | 
			
		||||
	{
 | 
			
		||||
		for(std::size_t i=0;i<str.size();i++)
 | 
			
		||||
			m_params.push_back(RegEx(str[i]));
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	// combination constructors
 | 
			
		||||
	RegEx operator ! (const RegEx& ex)
 | 
			
		||||
	{
 | 
			
		||||
		RegEx ret(REGEX_NOT);
 | 
			
		||||
		ret.m_params.push_back(ex);
 | 
			
		||||
		return ret;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	RegEx operator || (const RegEx& ex1, const RegEx& ex2)
 | 
			
		||||
	{
 | 
			
		||||
		RegEx ret(REGEX_OR);
 | 
			
		||||
		ret.m_params.push_back(ex1);
 | 
			
		||||
		ret.m_params.push_back(ex2);
 | 
			
		||||
		return ret;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	RegEx operator && (const RegEx& ex1, const RegEx& ex2)
 | 
			
		||||
	{
 | 
			
		||||
		RegEx ret(REGEX_AND);
 | 
			
		||||
		ret.m_params.push_back(ex1);
 | 
			
		||||
		ret.m_params.push_back(ex2);
 | 
			
		||||
		return ret;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	RegEx operator + (const RegEx& ex1, const RegEx& ex2)
 | 
			
		||||
	{
 | 
			
		||||
		RegEx ret(REGEX_SEQ);
 | 
			
		||||
		ret.m_params.push_back(ex1);
 | 
			
		||||
		ret.m_params.push_back(ex2);
 | 
			
		||||
		return ret;
 | 
			
		||||
	}	
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										65
									
								
								libs/yaml-cpp/src/regex.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								libs/yaml-cpp/src/regex.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,65 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#ifndef REGEX_H_62B23520_7C8E_11DE_8A39_0800200C9A66
 | 
			
		||||
#define REGEX_H_62B23520_7C8E_11DE_8A39_0800200C9A66
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
namespace YAML
 | 
			
		||||
{
 | 
			
		||||
	class Stream;
 | 
			
		||||
 | 
			
		||||
	enum REGEX_OP { REGEX_EMPTY, REGEX_MATCH, REGEX_RANGE, REGEX_OR, REGEX_AND, REGEX_NOT, REGEX_SEQ };
 | 
			
		||||
 | 
			
		||||
	// simplified regular expressions
 | 
			
		||||
	// . Only straightforward matches (no repeated characters)
 | 
			
		||||
	// . Only matches from start of string
 | 
			
		||||
	class RegEx
 | 
			
		||||
	{
 | 
			
		||||
	public:
 | 
			
		||||
		RegEx();
 | 
			
		||||
		RegEx(char ch);
 | 
			
		||||
		RegEx(char a, char z);
 | 
			
		||||
		RegEx(const std::string& str, REGEX_OP op = REGEX_SEQ);
 | 
			
		||||
		~RegEx() {}
 | 
			
		||||
 | 
			
		||||
		friend RegEx operator ! (const RegEx& ex);
 | 
			
		||||
		friend RegEx operator || (const RegEx& ex1, const RegEx& ex2);
 | 
			
		||||
		friend RegEx operator && (const RegEx& ex1, const RegEx& ex2);
 | 
			
		||||
		friend RegEx operator + (const RegEx& ex1, const RegEx& ex2);
 | 
			
		||||
		
 | 
			
		||||
		bool Matches(char ch) const;
 | 
			
		||||
		bool Matches(const std::string& str) const;
 | 
			
		||||
		bool Matches(const Stream& in) const;
 | 
			
		||||
		template <typename Source> bool Matches(const Source& source) const;
 | 
			
		||||
 | 
			
		||||
		int Match(const std::string& str) const;
 | 
			
		||||
		int Match(const Stream& in) const;
 | 
			
		||||
		template <typename Source> int Match(const Source& source) const;
 | 
			
		||||
 | 
			
		||||
	private:
 | 
			
		||||
		RegEx(REGEX_OP op);
 | 
			
		||||
		
 | 
			
		||||
		template <typename Source> bool IsValidSource(const Source& source) const;
 | 
			
		||||
		template <typename Source> int MatchUnchecked(const Source& source) const;
 | 
			
		||||
 | 
			
		||||
		template <typename Source> int MatchOpEmpty(const Source& source) const;
 | 
			
		||||
		template <typename Source> int MatchOpMatch(const Source& source) const;
 | 
			
		||||
		template <typename Source> int MatchOpRange(const Source& source) const;
 | 
			
		||||
		template <typename Source> int MatchOpOr(const Source& source) const;
 | 
			
		||||
		template <typename Source> int MatchOpAnd(const Source& source) const;
 | 
			
		||||
		template <typename Source> int MatchOpNot(const Source& source) const;
 | 
			
		||||
		template <typename Source> int MatchOpSeq(const Source& source) const;
 | 
			
		||||
 | 
			
		||||
	private:
 | 
			
		||||
		REGEX_OP m_op;
 | 
			
		||||
		char m_a, m_z;
 | 
			
		||||
		std::vector <RegEx> m_params;
 | 
			
		||||
	};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#include "regeximpl.h"
 | 
			
		||||
 | 
			
		||||
#endif // REGEX_H_62B23520_7C8E_11DE_8A39_0800200C9A66
 | 
			
		||||
							
								
								
									
										178
									
								
								libs/yaml-cpp/src/regeximpl.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										178
									
								
								libs/yaml-cpp/src/regeximpl.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,178 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#ifndef REGEXIMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
 | 
			
		||||
#define REGEXIMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include "stream.h"
 | 
			
		||||
#include "stringsource.h"
 | 
			
		||||
#include "streamcharsource.h"
 | 
			
		||||
 | 
			
		||||
namespace YAML
 | 
			
		||||
{
 | 
			
		||||
	// query matches
 | 
			
		||||
	inline bool RegEx::Matches(char ch) const {
 | 
			
		||||
		std::string str;
 | 
			
		||||
		str += ch;
 | 
			
		||||
		return Matches(str);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	inline bool RegEx::Matches(const std::string& str) const {
 | 
			
		||||
		return Match(str) >= 0;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	inline bool RegEx::Matches(const Stream& in) const {
 | 
			
		||||
		return Match(in) >= 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	template <typename Source>
 | 
			
		||||
	inline bool RegEx::Matches(const Source& source) const {
 | 
			
		||||
		return Match(source) >= 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Match
 | 
			
		||||
	// . Matches the given string against this regular expression.
 | 
			
		||||
	// . Returns the number of characters matched.
 | 
			
		||||
	// . Returns -1 if no characters were matched (the reason for
 | 
			
		||||
	//   not returning zero is that we may have an empty regex
 | 
			
		||||
	//   which is ALWAYS successful at matching zero characters).
 | 
			
		||||
	// . REMEMBER that we only match from the start of the buffer!	
 | 
			
		||||
	inline int RegEx::Match(const std::string& str) const
 | 
			
		||||
	{
 | 
			
		||||
		StringCharSource source(str.c_str(), str.size());
 | 
			
		||||
		return Match(source);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	inline int RegEx::Match(const Stream& in) const
 | 
			
		||||
	{
 | 
			
		||||
		StreamCharSource source(in);
 | 
			
		||||
		return Match(source);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	template <typename Source>
 | 
			
		||||
	inline bool RegEx::IsValidSource(const Source& source) const
 | 
			
		||||
	{
 | 
			
		||||
		return source;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	template<>
 | 
			
		||||
	inline bool RegEx::IsValidSource<StringCharSource>(const StringCharSource&source) const
 | 
			
		||||
	{
 | 
			
		||||
		return source || m_op == REGEX_EMPTY;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	template <typename Source>
 | 
			
		||||
	inline int RegEx::Match(const Source& source) const
 | 
			
		||||
	{
 | 
			
		||||
		return IsValidSource(source) ? MatchUnchecked(source) : -1;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	template <typename Source>
 | 
			
		||||
	inline int RegEx::MatchUnchecked(const Source& source) const
 | 
			
		||||
	{
 | 
			
		||||
		switch(m_op) {
 | 
			
		||||
			case REGEX_EMPTY:
 | 
			
		||||
				return MatchOpEmpty(source);
 | 
			
		||||
			case REGEX_MATCH:
 | 
			
		||||
				return MatchOpMatch(source);
 | 
			
		||||
			case REGEX_RANGE:
 | 
			
		||||
				return MatchOpRange(source);
 | 
			
		||||
			case REGEX_OR:
 | 
			
		||||
				return MatchOpOr(source);
 | 
			
		||||
			case REGEX_AND:
 | 
			
		||||
				return MatchOpAnd(source);
 | 
			
		||||
			case REGEX_NOT:
 | 
			
		||||
				return MatchOpNot(source);
 | 
			
		||||
			case REGEX_SEQ:
 | 
			
		||||
				return MatchOpSeq(source);
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	//////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
	// Operators
 | 
			
		||||
	// Note: the convention MatchOp*<Source> is that we can assume IsSourceValid(source).
 | 
			
		||||
	//       So we do all our checks *before* we call these functions
 | 
			
		||||
	
 | 
			
		||||
	// EmptyOperator
 | 
			
		||||
	template <typename Source>
 | 
			
		||||
	inline int RegEx::MatchOpEmpty(const Source& source) const {
 | 
			
		||||
		return source[0] == Stream::eof() ? 0 : -1;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	template <>
 | 
			
		||||
	inline int RegEx::MatchOpEmpty<StringCharSource>(const StringCharSource& source) const {
 | 
			
		||||
		return !source ? 0 : -1;  // the empty regex only is successful on the empty string
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// MatchOperator
 | 
			
		||||
	template <typename Source>
 | 
			
		||||
	inline int RegEx::MatchOpMatch(const Source& source) const {
 | 
			
		||||
		if(source[0] != m_a)
 | 
			
		||||
			return -1;
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	// RangeOperator
 | 
			
		||||
	template <typename Source>
 | 
			
		||||
	inline int RegEx::MatchOpRange(const Source& source) const {
 | 
			
		||||
		if(m_a > source[0] || m_z < source[0])
 | 
			
		||||
			return -1;
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	// OrOperator
 | 
			
		||||
	template <typename Source>
 | 
			
		||||
	inline int RegEx::MatchOpOr(const Source& source) const {
 | 
			
		||||
		for(std::size_t i=0;i<m_params.size();i++) {
 | 
			
		||||
			int n = m_params[i].MatchUnchecked(source);
 | 
			
		||||
			if(n >= 0)
 | 
			
		||||
				return n;
 | 
			
		||||
		}
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	// AndOperator
 | 
			
		||||
	// Note: 'AND' is a little funny, since we may be required to match things
 | 
			
		||||
	//       of different lengths. If we find a match, we return the length of
 | 
			
		||||
	//       the FIRST entry on the list.
 | 
			
		||||
	template <typename Source>
 | 
			
		||||
	inline int RegEx::MatchOpAnd(const Source& source) const {
 | 
			
		||||
		int first = -1;
 | 
			
		||||
		for(std::size_t i=0;i<m_params.size();i++) {
 | 
			
		||||
			int n = m_params[i].MatchUnchecked(source);
 | 
			
		||||
			if(n == -1)
 | 
			
		||||
				return -1;
 | 
			
		||||
			if(i == 0)
 | 
			
		||||
				first = n;
 | 
			
		||||
		}
 | 
			
		||||
		return first;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	// NotOperator
 | 
			
		||||
	template <typename Source>
 | 
			
		||||
	inline int RegEx::MatchOpNot(const Source& source) const {
 | 
			
		||||
		if(m_params.empty())
 | 
			
		||||
			return -1;
 | 
			
		||||
		if(m_params[0].MatchUnchecked(source) >= 0)
 | 
			
		||||
			return -1;
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	// SeqOperator
 | 
			
		||||
	template <typename Source>
 | 
			
		||||
	inline int RegEx::MatchOpSeq(const Source& source) const {
 | 
			
		||||
		int offset = 0;
 | 
			
		||||
		for(std::size_t i=0;i<m_params.size();i++) {
 | 
			
		||||
			int n = m_params[i].Match(source + offset); // note Match, not MatchUnchecked because we need to check validity after the offset
 | 
			
		||||
			if(n == -1)
 | 
			
		||||
				return -1;
 | 
			
		||||
			offset += n;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		return offset;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // REGEXIMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
 | 
			
		||||
							
								
								
									
										54
									
								
								libs/yaml-cpp/src/scalar.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								libs/yaml-cpp/src/scalar.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,54 @@
 | 
			
		||||
#include "scalar.h"
 | 
			
		||||
#include "scanner.h"
 | 
			
		||||
#include "token.h"
 | 
			
		||||
#include "exceptions.h"
 | 
			
		||||
#include "node.h"
 | 
			
		||||
#include "emitter.h"
 | 
			
		||||
 | 
			
		||||
namespace YAML
 | 
			
		||||
{
 | 
			
		||||
	Scalar::Scalar()
 | 
			
		||||
	{
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Scalar::Scalar(const std::string& data): m_data(data)
 | 
			
		||||
	{
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Scalar::~Scalar()
 | 
			
		||||
	{
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Content *Scalar::Clone() const
 | 
			
		||||
	{
 | 
			
		||||
		return new Scalar(m_data);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void Scalar::Parse(Scanner *pScanner, ParserState& /*state*/)
 | 
			
		||||
	{
 | 
			
		||||
		Token& token = pScanner->peek();
 | 
			
		||||
		m_data = token.value;
 | 
			
		||||
		pScanner->pop();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void Scalar::Write(Emitter& out) const
 | 
			
		||||
	{
 | 
			
		||||
		out << m_data;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	int Scalar::Compare(Content *pContent)
 | 
			
		||||
	{
 | 
			
		||||
		return -pContent->Compare(this);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	int Scalar::Compare(Scalar *pScalar)
 | 
			
		||||
	{
 | 
			
		||||
		if(m_data < pScalar->m_data)
 | 
			
		||||
			return -1;
 | 
			
		||||
		else if(m_data > pScalar->m_data)
 | 
			
		||||
			return 1;
 | 
			
		||||
		else
 | 
			
		||||
			return 0;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										44
									
								
								libs/yaml-cpp/src/scalar.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								libs/yaml-cpp/src/scalar.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,44 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#ifndef SCALAR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
 | 
			
		||||
#define SCALAR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include "content.h"
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
namespace YAML
 | 
			
		||||
{
 | 
			
		||||
	class Scalar: public Content
 | 
			
		||||
	{
 | 
			
		||||
	public:
 | 
			
		||||
		Scalar();
 | 
			
		||||
		Scalar(const std::string& data);
 | 
			
		||||
		virtual ~Scalar();
 | 
			
		||||
 | 
			
		||||
		virtual Content *Clone() const;
 | 
			
		||||
 | 
			
		||||
		virtual void Parse(Scanner *pScanner, ParserState& state);
 | 
			
		||||
		virtual void Write(Emitter& out) const;
 | 
			
		||||
 | 
			
		||||
		virtual bool IsScalar() const { return true; }
 | 
			
		||||
 | 
			
		||||
		// extraction
 | 
			
		||||
		virtual bool GetScalar(std::string& scalar) const {
 | 
			
		||||
			scalar = m_data;
 | 
			
		||||
			return true;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// ordering
 | 
			
		||||
		virtual int Compare(Content *pContent);
 | 
			
		||||
		virtual int Compare(Scalar *pScalar);
 | 
			
		||||
		virtual int Compare(Sequence *) { return -1; }
 | 
			
		||||
		virtual int Compare(Map *) { return -1; }
 | 
			
		||||
 | 
			
		||||
	protected:
 | 
			
		||||
		std::string m_data;
 | 
			
		||||
	};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // SCALAR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										423
									
								
								libs/yaml-cpp/src/scanner.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										423
									
								
								libs/yaml-cpp/src/scanner.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,423 @@
 | 
			
		||||
#include "scanner.h"
 | 
			
		||||
#include "token.h"
 | 
			
		||||
#include "exceptions.h"
 | 
			
		||||
#include "exp.h"
 | 
			
		||||
#include <cassert>
 | 
			
		||||
#include <memory>
 | 
			
		||||
 | 
			
		||||
namespace YAML
 | 
			
		||||
{
 | 
			
		||||
	Scanner::Scanner(std::istream& in)
 | 
			
		||||
		: INPUT(in), m_startedStream(false), m_endedStream(false), m_simpleKeyAllowed(false), m_canBeJSONFlow(false)
 | 
			
		||||
	{
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Scanner::~Scanner()
 | 
			
		||||
	{
 | 
			
		||||
		for(unsigned i=0;i<m_indentRefs.size();i++)
 | 
			
		||||
			delete m_indentRefs[i];
 | 
			
		||||
		m_indentRefs.clear();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// empty
 | 
			
		||||
	// . Returns true if there are no more tokens to be read
 | 
			
		||||
	bool Scanner::empty()
 | 
			
		||||
	{
 | 
			
		||||
		EnsureTokensInQueue();
 | 
			
		||||
		return m_tokens.empty();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// pop
 | 
			
		||||
	// . Simply removes the next token on the queue.
 | 
			
		||||
	void Scanner::pop()
 | 
			
		||||
	{
 | 
			
		||||
		EnsureTokensInQueue();
 | 
			
		||||
		if(!m_tokens.empty()) {
 | 
			
		||||
			// Saved anchors shouldn't survive popping the document end marker
 | 
			
		||||
			if (m_tokens.front().type == Token::DOC_END) {
 | 
			
		||||
				ClearAnchors();
 | 
			
		||||
			}
 | 
			
		||||
			m_tokens.pop();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// peek
 | 
			
		||||
	// . Returns (but does not remove) the next token on the queue.
 | 
			
		||||
	Token& Scanner::peek()
 | 
			
		||||
	{
 | 
			
		||||
		EnsureTokensInQueue();
 | 
			
		||||
		assert(!m_tokens.empty());  // should we be asserting here? I mean, we really just be checking
 | 
			
		||||
		                            // if it's empty before peeking.
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
		static Token *pLast = 0;
 | 
			
		||||
		if(pLast != &m_tokens.front())
 | 
			
		||||
			std::cerr << "peek: " << m_tokens.front() << "\n";
 | 
			
		||||
		pLast = &m_tokens.front();
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
		return m_tokens.front();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// EnsureTokensInQueue
 | 
			
		||||
	// . Scan until there's a valid token at the front of the queue,
 | 
			
		||||
	//   or we're sure the queue is empty.
 | 
			
		||||
	void Scanner::EnsureTokensInQueue()
 | 
			
		||||
	{
 | 
			
		||||
		while(1) {
 | 
			
		||||
			if(!m_tokens.empty()) {
 | 
			
		||||
				Token& token = m_tokens.front();
 | 
			
		||||
 | 
			
		||||
				// if this guy's valid, then we're done
 | 
			
		||||
				if(token.status == Token::VALID)
 | 
			
		||||
					return;
 | 
			
		||||
 | 
			
		||||
				// here's where we clean up the impossible tokens
 | 
			
		||||
				if(token.status == Token::INVALID) {
 | 
			
		||||
					m_tokens.pop();
 | 
			
		||||
					continue;
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				// note: what's left are the unverified tokens
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// no token? maybe we've actually finished
 | 
			
		||||
			if(m_endedStream)
 | 
			
		||||
				return;
 | 
			
		||||
 | 
			
		||||
			// no? then scan...
 | 
			
		||||
			ScanNextToken();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// ScanNextToken
 | 
			
		||||
	// . The main scanning function; here we branch out and
 | 
			
		||||
	//   scan whatever the next token should be.
 | 
			
		||||
	void Scanner::ScanNextToken()
 | 
			
		||||
	{
 | 
			
		||||
		if(m_endedStream)
 | 
			
		||||
			return;
 | 
			
		||||
 | 
			
		||||
		if(!m_startedStream)
 | 
			
		||||
			return StartStream();
 | 
			
		||||
 | 
			
		||||
		// get rid of whitespace, etc. (in between tokens it should be irrelevent)
 | 
			
		||||
		ScanToNextToken();
 | 
			
		||||
 | 
			
		||||
		// maybe need to end some blocks
 | 
			
		||||
		PopIndentToHere();
 | 
			
		||||
 | 
			
		||||
		// *****
 | 
			
		||||
		// And now branch based on the next few characters!
 | 
			
		||||
		// *****
 | 
			
		||||
		
 | 
			
		||||
		// end of stream
 | 
			
		||||
		if(!INPUT)
 | 
			
		||||
			return EndStream();
 | 
			
		||||
 | 
			
		||||
		if(INPUT.column() == 0 && INPUT.peek() == Keys::Directive)
 | 
			
		||||
			return ScanDirective();
 | 
			
		||||
 | 
			
		||||
		// document token
 | 
			
		||||
		if(INPUT.column() == 0 && Exp::DocStart().Matches(INPUT))
 | 
			
		||||
			return ScanDocStart();
 | 
			
		||||
 | 
			
		||||
		if(INPUT.column() == 0 && Exp::DocEnd().Matches(INPUT))
 | 
			
		||||
			return ScanDocEnd();
 | 
			
		||||
 | 
			
		||||
		// flow start/end/entry
 | 
			
		||||
		if(INPUT.peek() == Keys::FlowSeqStart || INPUT.peek() == Keys::FlowMapStart)
 | 
			
		||||
			return ScanFlowStart();
 | 
			
		||||
 | 
			
		||||
		if(INPUT.peek() == Keys::FlowSeqEnd || INPUT.peek() == Keys::FlowMapEnd)
 | 
			
		||||
			return ScanFlowEnd();
 | 
			
		||||
	
 | 
			
		||||
		if(INPUT.peek() == Keys::FlowEntry)
 | 
			
		||||
			return ScanFlowEntry();
 | 
			
		||||
 | 
			
		||||
		// block/map stuff
 | 
			
		||||
		if(Exp::BlockEntry().Matches(INPUT))
 | 
			
		||||
			return ScanBlockEntry();
 | 
			
		||||
 | 
			
		||||
		if((InBlockContext() ? Exp::Key() : Exp::KeyInFlow()).Matches(INPUT))
 | 
			
		||||
			return ScanKey();
 | 
			
		||||
 | 
			
		||||
		if(GetValueRegex().Matches(INPUT))
 | 
			
		||||
			return ScanValue();
 | 
			
		||||
 | 
			
		||||
		// alias/anchor
 | 
			
		||||
		if(INPUT.peek() == Keys::Alias || INPUT.peek() == Keys::Anchor)
 | 
			
		||||
			return ScanAnchorOrAlias();
 | 
			
		||||
 | 
			
		||||
		// tag
 | 
			
		||||
		if(INPUT.peek() == Keys::Tag)
 | 
			
		||||
			return ScanTag();
 | 
			
		||||
 | 
			
		||||
		// special scalars
 | 
			
		||||
		if(InBlockContext() && (INPUT.peek() == Keys::LiteralScalar || INPUT.peek() == Keys::FoldedScalar))
 | 
			
		||||
			return ScanBlockScalar();
 | 
			
		||||
 | 
			
		||||
		if(INPUT.peek() == '\'' || INPUT.peek() == '\"')
 | 
			
		||||
			return ScanQuotedScalar();
 | 
			
		||||
 | 
			
		||||
		// plain scalars
 | 
			
		||||
		if((InBlockContext() ? Exp::PlainScalar() : Exp::PlainScalarInFlow()).Matches(INPUT))
 | 
			
		||||
			return ScanPlainScalar();
 | 
			
		||||
 | 
			
		||||
		// don't know what it is!
 | 
			
		||||
		throw ParserException(INPUT.mark(), ErrorMsg::UNKNOWN_TOKEN);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// ScanToNextToken
 | 
			
		||||
	// . Eats input until we reach the next token-like thing.
 | 
			
		||||
	void Scanner::ScanToNextToken()
 | 
			
		||||
	{
 | 
			
		||||
		while(1) {
 | 
			
		||||
			// first eat whitespace
 | 
			
		||||
			while(INPUT && IsWhitespaceToBeEaten(INPUT.peek())) {
 | 
			
		||||
				if(InBlockContext() && Exp::Tab().Matches(INPUT))
 | 
			
		||||
					m_simpleKeyAllowed = false;
 | 
			
		||||
				INPUT.eat(1);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// then eat a comment
 | 
			
		||||
			if(Exp::Comment().Matches(INPUT)) {
 | 
			
		||||
				// eat until line break
 | 
			
		||||
				while(INPUT && !Exp::Break().Matches(INPUT))
 | 
			
		||||
					INPUT.eat(1);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// if it's NOT a line break, then we're done!
 | 
			
		||||
			if(!Exp::Break().Matches(INPUT))
 | 
			
		||||
				break;
 | 
			
		||||
 | 
			
		||||
			// otherwise, let's eat the line break and keep going
 | 
			
		||||
			int n = Exp::Break().Match(INPUT);
 | 
			
		||||
			INPUT.eat(n);
 | 
			
		||||
 | 
			
		||||
			// oh yeah, and let's get rid of that simple key
 | 
			
		||||
			InvalidateSimpleKey();
 | 
			
		||||
 | 
			
		||||
			// new line - we may be able to accept a simple key now
 | 
			
		||||
			if(InBlockContext())
 | 
			
		||||
				m_simpleKeyAllowed = true;
 | 
			
		||||
        }
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	///////////////////////////////////////////////////////////////////////
 | 
			
		||||
	// Misc. helpers
 | 
			
		||||
 | 
			
		||||
	// IsWhitespaceToBeEaten
 | 
			
		||||
	// . We can eat whitespace if it's a space or tab
 | 
			
		||||
	// . Note: originally tabs in block context couldn't be eaten
 | 
			
		||||
	//         "where a simple key could be allowed
 | 
			
		||||
	//         (i.e., not at the beginning of a line, or following '-', '?', or ':')"
 | 
			
		||||
	//   I think this is wrong, since tabs can be non-content whitespace; it's just
 | 
			
		||||
	//   that they can't contribute to indentation, so once you've seen a tab in a
 | 
			
		||||
	//   line, you can't start a simple key
 | 
			
		||||
	bool Scanner::IsWhitespaceToBeEaten(char ch)
 | 
			
		||||
	{
 | 
			
		||||
		if(ch == ' ')
 | 
			
		||||
			return true;
 | 
			
		||||
 | 
			
		||||
		if(ch == '\t')
 | 
			
		||||
			return true;
 | 
			
		||||
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// GetValueRegex
 | 
			
		||||
	// . Get the appropriate regex to check if it's a value token
 | 
			
		||||
	const RegEx& Scanner::GetValueRegex() const
 | 
			
		||||
	{
 | 
			
		||||
		if(InBlockContext())
 | 
			
		||||
			return Exp::Value();
 | 
			
		||||
		
 | 
			
		||||
		return m_canBeJSONFlow ? Exp::ValueInJSONFlow() : Exp::ValueInFlow();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// StartStream
 | 
			
		||||
	// . Set the initial conditions for starting a stream.
 | 
			
		||||
	void Scanner::StartStream()
 | 
			
		||||
	{
 | 
			
		||||
		m_startedStream = true;
 | 
			
		||||
		m_simpleKeyAllowed = true;
 | 
			
		||||
		IndentMarker *pIndent = new IndentMarker(-1, IndentMarker::NONE);
 | 
			
		||||
		m_indentRefs.push_back(pIndent);
 | 
			
		||||
		m_indents.push(pIndent);
 | 
			
		||||
		m_anchors.clear();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// EndStream
 | 
			
		||||
	// . Close out the stream, finish up, etc.
 | 
			
		||||
	void Scanner::EndStream()
 | 
			
		||||
	{
 | 
			
		||||
		// force newline
 | 
			
		||||
		if(INPUT.column() > 0)
 | 
			
		||||
			INPUT.ResetColumn();
 | 
			
		||||
 | 
			
		||||
		PopAllIndents();
 | 
			
		||||
		PopAllSimpleKeys();
 | 
			
		||||
 | 
			
		||||
		m_simpleKeyAllowed = false;
 | 
			
		||||
		m_endedStream = true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Token *Scanner::PushToken(Token::TYPE type)
 | 
			
		||||
	{
 | 
			
		||||
		m_tokens.push(Token(type, INPUT.mark()));
 | 
			
		||||
		return &m_tokens.back();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Token::TYPE Scanner::GetStartTokenFor(IndentMarker::INDENT_TYPE type) const
 | 
			
		||||
	{
 | 
			
		||||
		switch(type) {
 | 
			
		||||
			case IndentMarker::SEQ: return Token::BLOCK_SEQ_START;
 | 
			
		||||
			case IndentMarker::MAP: return Token::BLOCK_MAP_START;
 | 
			
		||||
			case IndentMarker::NONE: assert(false); break;
 | 
			
		||||
		}
 | 
			
		||||
		assert(false);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// PushIndentTo
 | 
			
		||||
	// . Pushes an indentation onto the stack, and enqueues the
 | 
			
		||||
	//   proper token (sequence start or mapping start).
 | 
			
		||||
	// . Returns the indent marker it generates (if any).
 | 
			
		||||
	Scanner::IndentMarker *Scanner::PushIndentTo(int column, IndentMarker::INDENT_TYPE type)
 | 
			
		||||
	{
 | 
			
		||||
		// are we in flow?
 | 
			
		||||
		if(InFlowContext())
 | 
			
		||||
			return 0;
 | 
			
		||||
		
 | 
			
		||||
		std::auto_ptr<IndentMarker> pIndent(new IndentMarker(column, type));
 | 
			
		||||
		IndentMarker& indent = *pIndent;
 | 
			
		||||
		const IndentMarker& lastIndent = *m_indents.top();
 | 
			
		||||
 | 
			
		||||
		// is this actually an indentation?
 | 
			
		||||
		if(indent.column < lastIndent.column)
 | 
			
		||||
			return 0;
 | 
			
		||||
		if(indent.column == lastIndent.column && !(indent.type == IndentMarker::SEQ && lastIndent.type == IndentMarker::MAP))
 | 
			
		||||
			return 0;
 | 
			
		||||
 | 
			
		||||
		// push a start token
 | 
			
		||||
		indent.pStartToken = PushToken(GetStartTokenFor(type));
 | 
			
		||||
 | 
			
		||||
		// and then the indent
 | 
			
		||||
		m_indents.push(&indent);
 | 
			
		||||
		m_indentRefs.push_back(pIndent.release());
 | 
			
		||||
		return m_indentRefs.back();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// PopIndentToHere
 | 
			
		||||
	// . Pops indentations off the stack until we reach the current indentation level,
 | 
			
		||||
	//   and enqueues the proper token each time.
 | 
			
		||||
	// . Then pops all invalid indentations off.
 | 
			
		||||
	void Scanner::PopIndentToHere()
 | 
			
		||||
	{
 | 
			
		||||
		// are we in flow?
 | 
			
		||||
		if(InFlowContext())
 | 
			
		||||
			return;
 | 
			
		||||
 | 
			
		||||
		// now pop away
 | 
			
		||||
		while(!m_indents.empty()) {
 | 
			
		||||
			const IndentMarker& indent = *m_indents.top();
 | 
			
		||||
			if(indent.column < INPUT.column())
 | 
			
		||||
				break;
 | 
			
		||||
			if(indent.column == INPUT.column() && !(indent.type == IndentMarker::SEQ && !Exp::BlockEntry().Matches(INPUT)))
 | 
			
		||||
				break;
 | 
			
		||||
				
 | 
			
		||||
			PopIndent();
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		while(!m_indents.empty() && m_indents.top()->status == IndentMarker::INVALID)
 | 
			
		||||
			PopIndent();
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	// PopAllIndents
 | 
			
		||||
	// . Pops all indentations (except for the base empty one) off the stack,
 | 
			
		||||
	//   and enqueues the proper token each time.
 | 
			
		||||
	void Scanner::PopAllIndents()
 | 
			
		||||
	{
 | 
			
		||||
		// are we in flow?
 | 
			
		||||
		if(InFlowContext())
 | 
			
		||||
			return;
 | 
			
		||||
 | 
			
		||||
		// now pop away
 | 
			
		||||
		while(!m_indents.empty()) {
 | 
			
		||||
			const IndentMarker& indent = *m_indents.top();
 | 
			
		||||
			if(indent.type == IndentMarker::NONE)
 | 
			
		||||
				break;
 | 
			
		||||
			
 | 
			
		||||
			PopIndent();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	// PopIndent
 | 
			
		||||
	// . Pops a single indent, pushing the proper token
 | 
			
		||||
	void Scanner::PopIndent()
 | 
			
		||||
	{
 | 
			
		||||
		const IndentMarker& indent = *m_indents.top();
 | 
			
		||||
		m_indents.pop();
 | 
			
		||||
 | 
			
		||||
		if(indent.status != IndentMarker::VALID) {
 | 
			
		||||
			InvalidateSimpleKey();
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		if(indent.type == IndentMarker::SEQ)
 | 
			
		||||
			m_tokens.push(Token(Token::BLOCK_SEQ_END, INPUT.mark()));
 | 
			
		||||
		else if(indent.type == IndentMarker::MAP)
 | 
			
		||||
			m_tokens.push(Token(Token::BLOCK_MAP_END, INPUT.mark()));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// GetTopIndent
 | 
			
		||||
	int Scanner::GetTopIndent() const
 | 
			
		||||
	{
 | 
			
		||||
		if(m_indents.empty())
 | 
			
		||||
			return 0;
 | 
			
		||||
		return m_indents.top()->column;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Save
 | 
			
		||||
	// . Saves a pointer to the Node object referenced by a particular anchor
 | 
			
		||||
	//   name.
 | 
			
		||||
	void Scanner::Save(const std::string& anchor, Node* value)
 | 
			
		||||
	{
 | 
			
		||||
		m_anchors[anchor] = value;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Retrieve
 | 
			
		||||
	// . Retrieves a pointer previously saved for an anchor name.
 | 
			
		||||
	// . Throws an exception if the anchor has not been defined.
 | 
			
		||||
	const Node *Scanner::Retrieve(const std::string& anchor) const
 | 
			
		||||
	{
 | 
			
		||||
		typedef std::map<std::string, const Node *> map;
 | 
			
		||||
 | 
			
		||||
		map::const_iterator itNode = m_anchors.find(anchor);
 | 
			
		||||
 | 
			
		||||
		if(m_anchors.end() == itNode)
 | 
			
		||||
			ThrowParserException(ErrorMsg::UNKNOWN_ANCHOR);
 | 
			
		||||
 | 
			
		||||
		return itNode->second;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// ThrowParserException
 | 
			
		||||
	// . Throws a ParserException with the current token location
 | 
			
		||||
	//   (if available).
 | 
			
		||||
	// . Does not parse any more tokens.
 | 
			
		||||
	void Scanner::ThrowParserException(const std::string& msg) const
 | 
			
		||||
	{
 | 
			
		||||
		Mark mark = Mark::null();
 | 
			
		||||
		if(!m_tokens.empty()) {
 | 
			
		||||
			const Token& token = m_tokens.front();
 | 
			
		||||
			mark = token.mark;
 | 
			
		||||
		}
 | 
			
		||||
		throw ParserException(mark, msg);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void Scanner::ClearAnchors()
 | 
			
		||||
	{
 | 
			
		||||
		m_anchors.clear();
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										135
									
								
								libs/yaml-cpp/src/scanner.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										135
									
								
								libs/yaml-cpp/src/scanner.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,135 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#ifndef SCANNER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
 | 
			
		||||
#define SCANNER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include <ios>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <queue>
 | 
			
		||||
#include <stack>
 | 
			
		||||
#include <set>
 | 
			
		||||
#include <map>
 | 
			
		||||
#include "stream.h"
 | 
			
		||||
#include "token.h"
 | 
			
		||||
 | 
			
		||||
namespace YAML
 | 
			
		||||
{
 | 
			
		||||
	class Node;
 | 
			
		||||
	class RegEx;
 | 
			
		||||
 | 
			
		||||
	class Scanner
 | 
			
		||||
	{
 | 
			
		||||
	public:
 | 
			
		||||
		Scanner(std::istream& in);
 | 
			
		||||
		~Scanner();
 | 
			
		||||
 | 
			
		||||
		// token queue management (hopefully this looks kinda stl-ish)
 | 
			
		||||
		bool empty();
 | 
			
		||||
		void pop();
 | 
			
		||||
		Token& peek();
 | 
			
		||||
 | 
			
		||||
		// anchor management
 | 
			
		||||
		void Save(const std::string& anchor, Node* value);
 | 
			
		||||
		const Node *Retrieve(const std::string& anchor) const;
 | 
			
		||||
		void ClearAnchors();
 | 
			
		||||
 | 
			
		||||
	private:
 | 
			
		||||
		struct IndentMarker {
 | 
			
		||||
			enum INDENT_TYPE { MAP, SEQ, NONE };
 | 
			
		||||
			enum STATUS { VALID, INVALID, UNKNOWN };
 | 
			
		||||
			IndentMarker(int column_, INDENT_TYPE type_): column(column_), type(type_), status(VALID), pStartToken(0) {}
 | 
			
		||||
		
 | 
			
		||||
			int column;
 | 
			
		||||
			INDENT_TYPE type;
 | 
			
		||||
			STATUS status;
 | 
			
		||||
			Token *pStartToken;
 | 
			
		||||
		};
 | 
			
		||||
		
 | 
			
		||||
		enum FLOW_MARKER { FLOW_MAP, FLOW_SEQ };
 | 
			
		||||
	
 | 
			
		||||
	private:	
 | 
			
		||||
		// scanning
 | 
			
		||||
		void EnsureTokensInQueue();
 | 
			
		||||
		void ScanNextToken();
 | 
			
		||||
		void ScanToNextToken();
 | 
			
		||||
		void StartStream();
 | 
			
		||||
		void EndStream();
 | 
			
		||||
		Token *PushToken(Token::TYPE type);
 | 
			
		||||
		
 | 
			
		||||
		bool InFlowContext() const { return !m_flows.empty(); }
 | 
			
		||||
		bool InBlockContext() const { return m_flows.empty(); }
 | 
			
		||||
		int GetFlowLevel() const { return m_flows.size(); }
 | 
			
		||||
		
 | 
			
		||||
		Token::TYPE GetStartTokenFor(IndentMarker::INDENT_TYPE type) const;
 | 
			
		||||
		IndentMarker *PushIndentTo(int column, IndentMarker::INDENT_TYPE type);
 | 
			
		||||
		void PopIndentToHere();
 | 
			
		||||
		void PopAllIndents();
 | 
			
		||||
		void PopIndent();
 | 
			
		||||
		int GetTopIndent() const;
 | 
			
		||||
 | 
			
		||||
		// checking input
 | 
			
		||||
		bool CanInsertPotentialSimpleKey() const;
 | 
			
		||||
		bool ExistsActiveSimpleKey() const;
 | 
			
		||||
		void InsertPotentialSimpleKey();
 | 
			
		||||
		void InvalidateSimpleKey();
 | 
			
		||||
		bool VerifySimpleKey();
 | 
			
		||||
		void PopAllSimpleKeys();
 | 
			
		||||
		
 | 
			
		||||
		void ThrowParserException(const std::string& msg) const;
 | 
			
		||||
 | 
			
		||||
		bool IsWhitespaceToBeEaten(char ch);
 | 
			
		||||
		const RegEx& GetValueRegex() const;
 | 
			
		||||
 | 
			
		||||
		struct SimpleKey {
 | 
			
		||||
			SimpleKey(const Mark& mark_, int flowLevel_);
 | 
			
		||||
 | 
			
		||||
			void Validate();
 | 
			
		||||
			void Invalidate();
 | 
			
		||||
			
 | 
			
		||||
			Mark mark;
 | 
			
		||||
			int flowLevel;
 | 
			
		||||
			IndentMarker *pIndent;
 | 
			
		||||
			Token *pMapStart, *pKey;
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
		// and the tokens
 | 
			
		||||
		void ScanDirective();
 | 
			
		||||
		void ScanDocStart();
 | 
			
		||||
		void ScanDocEnd();
 | 
			
		||||
		void ScanBlockSeqStart();
 | 
			
		||||
		void ScanBlockMapSTart();
 | 
			
		||||
		void ScanBlockEnd();
 | 
			
		||||
		void ScanBlockEntry();
 | 
			
		||||
		void ScanFlowStart();
 | 
			
		||||
		void ScanFlowEnd();
 | 
			
		||||
		void ScanFlowEntry();
 | 
			
		||||
		void ScanKey();
 | 
			
		||||
		void ScanValue();
 | 
			
		||||
		void ScanAnchorOrAlias();
 | 
			
		||||
		void ScanTag();
 | 
			
		||||
		void ScanPlainScalar();
 | 
			
		||||
		void ScanQuotedScalar();
 | 
			
		||||
		void ScanBlockScalar();
 | 
			
		||||
 | 
			
		||||
	private:
 | 
			
		||||
		// the stream
 | 
			
		||||
		Stream INPUT;
 | 
			
		||||
 | 
			
		||||
		// the output (tokens)
 | 
			
		||||
		std::queue <Token> m_tokens;
 | 
			
		||||
 | 
			
		||||
		// state info
 | 
			
		||||
		bool m_startedStream, m_endedStream;
 | 
			
		||||
		bool m_simpleKeyAllowed;
 | 
			
		||||
		bool m_canBeJSONFlow;
 | 
			
		||||
		std::stack <SimpleKey> m_simpleKeys;
 | 
			
		||||
		std::stack <IndentMarker *> m_indents;
 | 
			
		||||
		std::vector <IndentMarker *> m_indentRefs; // for "garbage collection"
 | 
			
		||||
		std::stack <FLOW_MARKER> m_flows;
 | 
			
		||||
		std::map <std::string, const Node *> m_anchors;
 | 
			
		||||
	};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // SCANNER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										188
									
								
								libs/yaml-cpp/src/scanscalar.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										188
									
								
								libs/yaml-cpp/src/scanscalar.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,188 @@
 | 
			
		||||
#include "scanscalar.h"
 | 
			
		||||
#include "scanner.h"
 | 
			
		||||
#include "exp.h"
 | 
			
		||||
#include "exceptions.h"
 | 
			
		||||
#include "token.h"
 | 
			
		||||
 | 
			
		||||
namespace YAML
 | 
			
		||||
{
 | 
			
		||||
	// ScanScalar
 | 
			
		||||
	// . This is where the scalar magic happens.
 | 
			
		||||
	//
 | 
			
		||||
	// . We do the scanning in three phases:
 | 
			
		||||
	//   1. Scan until newline
 | 
			
		||||
	//   2. Eat newline
 | 
			
		||||
	//   3. Scan leading blanks.
 | 
			
		||||
	//
 | 
			
		||||
	// . Depending on the parameters given, we store or stop
 | 
			
		||||
	//   and different places in the above flow.
 | 
			
		||||
	std::string ScanScalar(Stream& INPUT, ScanScalarParams& params)
 | 
			
		||||
	{
 | 
			
		||||
		bool foundNonEmptyLine = false;
 | 
			
		||||
		bool pastOpeningBreak = (params.fold == FOLD_FLOW);
 | 
			
		||||
		bool emptyLine = false, moreIndented = false;
 | 
			
		||||
		int foldedNewlineCount = 0;
 | 
			
		||||
		bool foldedNewlineStartedMoreIndented = false;
 | 
			
		||||
		std::string scalar;
 | 
			
		||||
		params.leadingSpaces = false;
 | 
			
		||||
 | 
			
		||||
		while(INPUT) {
 | 
			
		||||
			// ********************************
 | 
			
		||||
			// Phase #1: scan until line ending
 | 
			
		||||
			
 | 
			
		||||
			std::size_t lastNonWhitespaceChar = scalar.size();
 | 
			
		||||
			bool escapedNewline = false;
 | 
			
		||||
			while(!params.end.Matches(INPUT) && !Exp::Break().Matches(INPUT)) {
 | 
			
		||||
				if(!INPUT)
 | 
			
		||||
					break;
 | 
			
		||||
 | 
			
		||||
				// document indicator?
 | 
			
		||||
				if(INPUT.column() == 0 && Exp::DocIndicator().Matches(INPUT)) {
 | 
			
		||||
					if(params.onDocIndicator == BREAK)
 | 
			
		||||
						break;
 | 
			
		||||
					else if(params.onDocIndicator == THROW)
 | 
			
		||||
						throw ParserException(INPUT.mark(), ErrorMsg::DOC_IN_SCALAR);
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				foundNonEmptyLine = true;
 | 
			
		||||
				pastOpeningBreak = true;
 | 
			
		||||
 | 
			
		||||
				// escaped newline? (only if we're escaping on slash)
 | 
			
		||||
				if(params.escape == '\\' && Exp::EscBreak().Matches(INPUT)) {
 | 
			
		||||
					// eat escape character and get out (but preserve trailing whitespace!)
 | 
			
		||||
					INPUT.get();
 | 
			
		||||
					lastNonWhitespaceChar = scalar.size();
 | 
			
		||||
					escapedNewline = true;
 | 
			
		||||
					break;
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				// escape this?
 | 
			
		||||
				if(INPUT.peek() == params.escape) {
 | 
			
		||||
					scalar += Exp::Escape(INPUT);
 | 
			
		||||
					lastNonWhitespaceChar = scalar.size();
 | 
			
		||||
					continue;
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				// otherwise, just add the damn character
 | 
			
		||||
				char ch = INPUT.get();
 | 
			
		||||
				scalar += ch;
 | 
			
		||||
				if(ch != ' ' && ch != '\t')
 | 
			
		||||
					lastNonWhitespaceChar = scalar.size();
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// eof? if we're looking to eat something, then we throw
 | 
			
		||||
			if(!INPUT) {
 | 
			
		||||
				if(params.eatEnd)
 | 
			
		||||
					throw ParserException(INPUT.mark(), ErrorMsg::EOF_IN_SCALAR);
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// doc indicator?
 | 
			
		||||
			if(params.onDocIndicator == BREAK && INPUT.column() == 0 && Exp::DocIndicator().Matches(INPUT))
 | 
			
		||||
				break;
 | 
			
		||||
 | 
			
		||||
			// are we done via character match?
 | 
			
		||||
			int n = params.end.Match(INPUT);
 | 
			
		||||
			if(n >= 0) {
 | 
			
		||||
				if(params.eatEnd)
 | 
			
		||||
					INPUT.eat(n);
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
			
 | 
			
		||||
			// do we remove trailing whitespace?
 | 
			
		||||
			if(params.fold == FOLD_FLOW)
 | 
			
		||||
				scalar.erase(lastNonWhitespaceChar);
 | 
			
		||||
			
 | 
			
		||||
			// ********************************
 | 
			
		||||
			// Phase #2: eat line ending
 | 
			
		||||
			n = Exp::Break().Match(INPUT);
 | 
			
		||||
			INPUT.eat(n);
 | 
			
		||||
 | 
			
		||||
			// ********************************
 | 
			
		||||
			// Phase #3: scan initial spaces
 | 
			
		||||
 | 
			
		||||
			// first the required indentation
 | 
			
		||||
			while(INPUT.peek() == ' ' && (INPUT.column() < params.indent || (params.detectIndent && !foundNonEmptyLine)))
 | 
			
		||||
				INPUT.eat(1);
 | 
			
		||||
 | 
			
		||||
			// update indent if we're auto-detecting
 | 
			
		||||
			if(params.detectIndent && !foundNonEmptyLine)
 | 
			
		||||
				params.indent = std::max(params.indent, INPUT.column());
 | 
			
		||||
 | 
			
		||||
			// and then the rest of the whitespace
 | 
			
		||||
			while(Exp::Blank().Matches(INPUT)) {
 | 
			
		||||
				// we check for tabs that masquerade as indentation
 | 
			
		||||
				if(INPUT.peek() == '\t'&& INPUT.column() < params.indent && params.onTabInIndentation == THROW)
 | 
			
		||||
					throw ParserException(INPUT.mark(), ErrorMsg::TAB_IN_INDENTATION);
 | 
			
		||||
 | 
			
		||||
				if(!params.eatLeadingWhitespace)
 | 
			
		||||
					break;
 | 
			
		||||
 | 
			
		||||
				INPUT.eat(1);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// was this an empty line?
 | 
			
		||||
			bool nextEmptyLine = Exp::Break().Matches(INPUT);
 | 
			
		||||
			bool nextMoreIndented = Exp::Blank().Matches(INPUT);
 | 
			
		||||
			if(params.fold == FOLD_BLOCK && foldedNewlineCount == 0 && nextEmptyLine)
 | 
			
		||||
				foldedNewlineStartedMoreIndented = moreIndented;
 | 
			
		||||
 | 
			
		||||
			// for block scalars, we always start with a newline, so we should ignore it (not fold or keep)
 | 
			
		||||
			if(pastOpeningBreak) {
 | 
			
		||||
				switch(params.fold) {
 | 
			
		||||
					case DONT_FOLD:
 | 
			
		||||
						scalar += "\n";
 | 
			
		||||
						break;
 | 
			
		||||
					case FOLD_BLOCK:
 | 
			
		||||
						if(!emptyLine && !nextEmptyLine && !moreIndented && !nextMoreIndented && INPUT.column() >= params.indent)
 | 
			
		||||
							scalar += " ";
 | 
			
		||||
						else if(nextEmptyLine)
 | 
			
		||||
							foldedNewlineCount++;
 | 
			
		||||
						else
 | 
			
		||||
							scalar += "\n";
 | 
			
		||||
						
 | 
			
		||||
						if(!nextEmptyLine && foldedNewlineCount > 0) {
 | 
			
		||||
							scalar += std::string(foldedNewlineCount - 1, '\n');
 | 
			
		||||
							if(foldedNewlineStartedMoreIndented || nextMoreIndented)
 | 
			
		||||
								scalar += "\n";
 | 
			
		||||
							foldedNewlineCount = 0;
 | 
			
		||||
						}
 | 
			
		||||
						break;
 | 
			
		||||
					case FOLD_FLOW:
 | 
			
		||||
						if(nextEmptyLine)
 | 
			
		||||
							scalar += "\n";
 | 
			
		||||
						else if(!emptyLine && !nextEmptyLine && !escapedNewline)
 | 
			
		||||
							scalar += " ";
 | 
			
		||||
						break;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			emptyLine = nextEmptyLine;
 | 
			
		||||
			moreIndented = nextMoreIndented;
 | 
			
		||||
			pastOpeningBreak = true;
 | 
			
		||||
 | 
			
		||||
			// are we done via indentation?
 | 
			
		||||
			if(!emptyLine && INPUT.column() < params.indent) {
 | 
			
		||||
				params.leadingSpaces = true;
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// post-processing
 | 
			
		||||
		if(params.trimTrailingSpaces) {
 | 
			
		||||
			std::size_t pos = scalar.find_last_not_of(' ');
 | 
			
		||||
			if(pos < scalar.size())
 | 
			
		||||
				scalar.erase(pos + 1);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if(params.chomp == STRIP || params.chomp == CLIP) {
 | 
			
		||||
			std::size_t pos = scalar.find_last_not_of('\n');
 | 
			
		||||
			if(params.chomp == CLIP && pos + 1 < scalar.size())
 | 
			
		||||
				scalar.erase(pos + 2);
 | 
			
		||||
			else if(params.chomp == STRIP && pos < scalar.size())
 | 
			
		||||
				scalar.erase(pos + 1);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return scalar;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										43
									
								
								libs/yaml-cpp/src/scanscalar.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								libs/yaml-cpp/src/scanscalar.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,43 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#ifndef SCANSCALAR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
 | 
			
		||||
#define SCANSCALAR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include <string>
 | 
			
		||||
#include "regex.h"
 | 
			
		||||
#include "stream.h"
 | 
			
		||||
 | 
			
		||||
namespace YAML
 | 
			
		||||
{
 | 
			
		||||
	enum CHOMP { STRIP = -1, CLIP, KEEP };
 | 
			
		||||
	enum ACTION { NONE, BREAK, THROW };
 | 
			
		||||
	enum FOLD { DONT_FOLD, FOLD_BLOCK, FOLD_FLOW };
 | 
			
		||||
 | 
			
		||||
	struct ScanScalarParams {
 | 
			
		||||
		ScanScalarParams(): eatEnd(false), indent(0), detectIndent(false), eatLeadingWhitespace(0), escape(0), fold(DONT_FOLD),
 | 
			
		||||
			trimTrailingSpaces(0), chomp(CLIP), onDocIndicator(NONE), onTabInIndentation(NONE), leadingSpaces(false) {}
 | 
			
		||||
 | 
			
		||||
		// input:
 | 
			
		||||
		RegEx end;                      // what condition ends this scalar?
 | 
			
		||||
		bool eatEnd;                    // should we eat that condition when we see it?
 | 
			
		||||
		int indent;                     // what level of indentation should be eaten and ignored?
 | 
			
		||||
		bool detectIndent;              // should we try to autodetect the indent?
 | 
			
		||||
		bool eatLeadingWhitespace;      // should we continue eating this delicious indentation after 'indent' spaces?
 | 
			
		||||
		char escape;                    // what character do we escape on (i.e., slash or single quote) (0 for none)
 | 
			
		||||
		FOLD fold;                      // how do we fold line ends?
 | 
			
		||||
		bool trimTrailingSpaces;        // do we remove all trailing spaces (at the very end)
 | 
			
		||||
		CHOMP chomp;                    // do we strip, clip, or keep trailing newlines (at the very end)
 | 
			
		||||
		                                //   Note: strip means kill all, clip means keep at most one, keep means keep all
 | 
			
		||||
		ACTION onDocIndicator;          // what do we do if we see a document indicator?
 | 
			
		||||
		ACTION onTabInIndentation;      // what do we do if we see a tab where we should be seeing indentation spaces
 | 
			
		||||
 | 
			
		||||
		// output:
 | 
			
		||||
		bool leadingSpaces;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	std::string ScanScalar(Stream& INPUT, ScanScalarParams& info);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // SCANSCALAR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										84
									
								
								libs/yaml-cpp/src/scantag.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								libs/yaml-cpp/src/scantag.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,84 @@
 | 
			
		||||
#include "scanner.h"
 | 
			
		||||
#include "regex.h"
 | 
			
		||||
#include "exp.h"
 | 
			
		||||
#include "exceptions.h"
 | 
			
		||||
 | 
			
		||||
namespace YAML
 | 
			
		||||
{
 | 
			
		||||
	const std::string ScanVerbatimTag(Stream& INPUT)
 | 
			
		||||
	{
 | 
			
		||||
		std::string tag;
 | 
			
		||||
		
 | 
			
		||||
		// eat the start character
 | 
			
		||||
		INPUT.get();
 | 
			
		||||
		
 | 
			
		||||
		while(INPUT) {
 | 
			
		||||
			if(INPUT.peek() == Keys::VerbatimTagEnd) {
 | 
			
		||||
				// eat the end character
 | 
			
		||||
				INPUT.get();
 | 
			
		||||
				return tag;
 | 
			
		||||
			}
 | 
			
		||||
		
 | 
			
		||||
			int n = Exp::URI().Match(INPUT);
 | 
			
		||||
			if(n <= 0)
 | 
			
		||||
				break;
 | 
			
		||||
			
 | 
			
		||||
			tag += INPUT.get(n);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		throw ParserException(INPUT.mark(), ErrorMsg::END_OF_VERBATIM_TAG);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	const std::string ScanTagHandle(Stream& INPUT, bool& canBeHandle)
 | 
			
		||||
	{
 | 
			
		||||
		std::string tag;
 | 
			
		||||
		canBeHandle = true;
 | 
			
		||||
		Mark firstNonWordChar;
 | 
			
		||||
		
 | 
			
		||||
		while(INPUT) {
 | 
			
		||||
			if(INPUT.peek() == Keys::Tag) {
 | 
			
		||||
				if(!canBeHandle)
 | 
			
		||||
					throw ParserException(firstNonWordChar, ErrorMsg::CHAR_IN_TAG_HANDLE);
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			int n = 0;
 | 
			
		||||
			if(canBeHandle) {
 | 
			
		||||
				n = Exp::Word().Match(INPUT);
 | 
			
		||||
				if(n <= 0) {
 | 
			
		||||
					canBeHandle = false;
 | 
			
		||||
					firstNonWordChar = INPUT.mark();
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			
 | 
			
		||||
			if(!canBeHandle)
 | 
			
		||||
				n = Exp::Tag().Match(INPUT);
 | 
			
		||||
 | 
			
		||||
			if(n <= 0)
 | 
			
		||||
				break;
 | 
			
		||||
			
 | 
			
		||||
			tag += INPUT.get(n);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return tag;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	const std::string ScanTagSuffix(Stream& INPUT)
 | 
			
		||||
	{
 | 
			
		||||
		std::string tag;
 | 
			
		||||
		
 | 
			
		||||
		while(INPUT) {
 | 
			
		||||
			int n = Exp::Tag().Match(INPUT);
 | 
			
		||||
			if(n <= 0)
 | 
			
		||||
				break;
 | 
			
		||||
			
 | 
			
		||||
			tag += INPUT.get(n);
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		if(tag.empty())
 | 
			
		||||
			throw ParserException(INPUT.mark(), ErrorMsg::TAG_WITH_NO_SUFFIX);
 | 
			
		||||
		
 | 
			
		||||
		return tag;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										18
									
								
								libs/yaml-cpp/src/scantag.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								libs/yaml-cpp/src/scantag.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,18 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#ifndef SCANTAG_H_62B23520_7C8E_11DE_8A39_0800200C9A66
 | 
			
		||||
#define SCANTAG_H_62B23520_7C8E_11DE_8A39_0800200C9A66
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include <string>
 | 
			
		||||
#include "stream.h"
 | 
			
		||||
 | 
			
		||||
namespace YAML
 | 
			
		||||
{
 | 
			
		||||
	const std::string ScanVerbatimTag(Stream& INPUT);
 | 
			
		||||
	const std::string ScanTagHandle(Stream& INPUT, bool& canBeHandle);
 | 
			
		||||
	const std::string ScanTagSuffix(Stream& INPUT);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // SCANTAG_H_62B23520_7C8E_11DE_8A39_0800200C9A66
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										434
									
								
								libs/yaml-cpp/src/scantoken.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										434
									
								
								libs/yaml-cpp/src/scantoken.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,434 @@
 | 
			
		||||
#include "scanner.h"
 | 
			
		||||
#include "token.h"
 | 
			
		||||
#include "exceptions.h"
 | 
			
		||||
#include "exp.h"
 | 
			
		||||
#include "scanscalar.h"
 | 
			
		||||
#include "scantag.h"
 | 
			
		||||
#include "tag.h"
 | 
			
		||||
#include <sstream>
 | 
			
		||||
 | 
			
		||||
namespace YAML
 | 
			
		||||
{
 | 
			
		||||
	///////////////////////////////////////////////////////////////////////
 | 
			
		||||
	// Specialization for scanning specific tokens
 | 
			
		||||
 | 
			
		||||
	// Directive
 | 
			
		||||
	// . Note: no semantic checking is done here (that's for the parser to do)
 | 
			
		||||
	void Scanner::ScanDirective()
 | 
			
		||||
	{
 | 
			
		||||
		std::string name;
 | 
			
		||||
		std::vector <std::string> params;
 | 
			
		||||
 | 
			
		||||
		// pop indents and simple keys
 | 
			
		||||
		PopAllIndents();
 | 
			
		||||
		PopAllSimpleKeys();
 | 
			
		||||
 | 
			
		||||
		m_simpleKeyAllowed = false;
 | 
			
		||||
		m_canBeJSONFlow = false;
 | 
			
		||||
 | 
			
		||||
		// store pos and eat indicator
 | 
			
		||||
		Token token(Token::DIRECTIVE, INPUT.mark());
 | 
			
		||||
		INPUT.eat(1);
 | 
			
		||||
 | 
			
		||||
		// read name
 | 
			
		||||
		while(INPUT && !Exp::BlankOrBreak().Matches(INPUT))
 | 
			
		||||
			token.value += INPUT.get();
 | 
			
		||||
 | 
			
		||||
		// read parameters
 | 
			
		||||
		while(1) {
 | 
			
		||||
			// first get rid of whitespace
 | 
			
		||||
			while(Exp::Blank().Matches(INPUT))
 | 
			
		||||
				INPUT.eat(1);
 | 
			
		||||
 | 
			
		||||
			// break on newline or comment
 | 
			
		||||
			if(!INPUT || Exp::Break().Matches(INPUT) || Exp::Comment().Matches(INPUT))
 | 
			
		||||
				break;
 | 
			
		||||
 | 
			
		||||
			// now read parameter
 | 
			
		||||
			std::string param;
 | 
			
		||||
			while(INPUT && !Exp::BlankOrBreak().Matches(INPUT))
 | 
			
		||||
				param += INPUT.get();
 | 
			
		||||
 | 
			
		||||
			token.params.push_back(param);
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		m_tokens.push(token);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// DocStart
 | 
			
		||||
	void Scanner::ScanDocStart()
 | 
			
		||||
	{
 | 
			
		||||
		PopAllIndents();
 | 
			
		||||
		PopAllSimpleKeys();
 | 
			
		||||
		m_simpleKeyAllowed = false;
 | 
			
		||||
		m_canBeJSONFlow = false;
 | 
			
		||||
 | 
			
		||||
		// eat
 | 
			
		||||
		Mark mark = INPUT.mark();
 | 
			
		||||
		INPUT.eat(3);
 | 
			
		||||
		m_tokens.push(Token(Token::DOC_START, mark));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// DocEnd
 | 
			
		||||
	void Scanner::ScanDocEnd()
 | 
			
		||||
	{
 | 
			
		||||
		PopAllIndents();
 | 
			
		||||
		PopAllSimpleKeys();
 | 
			
		||||
		m_simpleKeyAllowed = false;
 | 
			
		||||
		m_canBeJSONFlow = false;
 | 
			
		||||
 | 
			
		||||
		// eat
 | 
			
		||||
		Mark mark = INPUT.mark();
 | 
			
		||||
		INPUT.eat(3);
 | 
			
		||||
		m_tokens.push(Token(Token::DOC_END, mark));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// FlowStart
 | 
			
		||||
	void Scanner::ScanFlowStart()
 | 
			
		||||
	{
 | 
			
		||||
		// flows can be simple keys
 | 
			
		||||
		InsertPotentialSimpleKey();
 | 
			
		||||
		m_simpleKeyAllowed = true;
 | 
			
		||||
		m_canBeJSONFlow = false;
 | 
			
		||||
 | 
			
		||||
		// eat
 | 
			
		||||
		Mark mark = INPUT.mark();
 | 
			
		||||
		char ch = INPUT.get();
 | 
			
		||||
		FLOW_MARKER flowType = (ch == Keys::FlowSeqStart ? FLOW_SEQ : FLOW_MAP);
 | 
			
		||||
		m_flows.push(flowType);
 | 
			
		||||
		Token::TYPE type = (flowType == FLOW_SEQ ? Token::FLOW_SEQ_START : Token::FLOW_MAP_START);
 | 
			
		||||
		m_tokens.push(Token(type, mark));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// FlowEnd
 | 
			
		||||
	void Scanner::ScanFlowEnd()
 | 
			
		||||
	{
 | 
			
		||||
		if(InBlockContext())
 | 
			
		||||
			throw ParserException(INPUT.mark(), ErrorMsg::FLOW_END);
 | 
			
		||||
 | 
			
		||||
		// we might have a solo entry in the flow context
 | 
			
		||||
		if(InFlowContext()) {
 | 
			
		||||
			if(m_flows.top() == FLOW_MAP && VerifySimpleKey())
 | 
			
		||||
				m_tokens.push(Token(Token::VALUE, INPUT.mark()));
 | 
			
		||||
			else if(m_flows.top() == FLOW_SEQ)
 | 
			
		||||
				InvalidateSimpleKey();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		m_simpleKeyAllowed = false;
 | 
			
		||||
		m_canBeJSONFlow = true;
 | 
			
		||||
 | 
			
		||||
		// eat
 | 
			
		||||
		Mark mark = INPUT.mark();
 | 
			
		||||
		char ch = INPUT.get();
 | 
			
		||||
 | 
			
		||||
		// check that it matches the start
 | 
			
		||||
		FLOW_MARKER flowType = (ch == Keys::FlowSeqEnd ? FLOW_SEQ : FLOW_MAP);
 | 
			
		||||
		if(m_flows.top() != flowType)
 | 
			
		||||
			throw ParserException(mark, ErrorMsg::FLOW_END);
 | 
			
		||||
		m_flows.pop();
 | 
			
		||||
		
 | 
			
		||||
		Token::TYPE type = (flowType ? Token::FLOW_SEQ_END : Token::FLOW_MAP_END);
 | 
			
		||||
		m_tokens.push(Token(type, mark));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// FlowEntry
 | 
			
		||||
	void Scanner::ScanFlowEntry()
 | 
			
		||||
	{
 | 
			
		||||
		// we might have a solo entry in the flow context
 | 
			
		||||
		if(InFlowContext()) {
 | 
			
		||||
			if(m_flows.top() == FLOW_MAP && VerifySimpleKey())
 | 
			
		||||
				m_tokens.push(Token(Token::VALUE, INPUT.mark()));
 | 
			
		||||
			else if(m_flows.top() == FLOW_SEQ)
 | 
			
		||||
				InvalidateSimpleKey();
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		m_simpleKeyAllowed = true;
 | 
			
		||||
		m_canBeJSONFlow = false;
 | 
			
		||||
 | 
			
		||||
		// eat
 | 
			
		||||
		Mark mark = INPUT.mark();
 | 
			
		||||
		INPUT.eat(1);
 | 
			
		||||
		m_tokens.push(Token(Token::FLOW_ENTRY, mark));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// BlockEntry
 | 
			
		||||
	void Scanner::ScanBlockEntry()
 | 
			
		||||
	{
 | 
			
		||||
		// we better be in the block context!
 | 
			
		||||
		if(InFlowContext())
 | 
			
		||||
			throw ParserException(INPUT.mark(), ErrorMsg::BLOCK_ENTRY);
 | 
			
		||||
 | 
			
		||||
		// can we put it here?
 | 
			
		||||
		if(!m_simpleKeyAllowed)
 | 
			
		||||
			throw ParserException(INPUT.mark(), ErrorMsg::BLOCK_ENTRY);
 | 
			
		||||
 | 
			
		||||
		PushIndentTo(INPUT.column(), IndentMarker::SEQ);
 | 
			
		||||
		m_simpleKeyAllowed = true;
 | 
			
		||||
		m_canBeJSONFlow = false;
 | 
			
		||||
 | 
			
		||||
		// eat
 | 
			
		||||
		Mark mark = INPUT.mark();
 | 
			
		||||
		INPUT.eat(1);
 | 
			
		||||
		m_tokens.push(Token(Token::BLOCK_ENTRY, mark));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Key
 | 
			
		||||
	void Scanner::ScanKey()
 | 
			
		||||
	{
 | 
			
		||||
		// handle keys diffently in the block context (and manage indents)
 | 
			
		||||
		if(InBlockContext()) {
 | 
			
		||||
			if(!m_simpleKeyAllowed)
 | 
			
		||||
				throw ParserException(INPUT.mark(), ErrorMsg::MAP_KEY);
 | 
			
		||||
 | 
			
		||||
			PushIndentTo(INPUT.column(), IndentMarker::MAP);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// can only put a simple key here if we're in block context
 | 
			
		||||
		m_simpleKeyAllowed = InBlockContext();
 | 
			
		||||
 | 
			
		||||
		// eat
 | 
			
		||||
		Mark mark = INPUT.mark();
 | 
			
		||||
		INPUT.eat(1);
 | 
			
		||||
		m_tokens.push(Token(Token::KEY, mark));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Value
 | 
			
		||||
	void Scanner::ScanValue()
 | 
			
		||||
	{
 | 
			
		||||
		// and check that simple key
 | 
			
		||||
		bool isSimpleKey = VerifySimpleKey();
 | 
			
		||||
		m_canBeJSONFlow = false;
 | 
			
		||||
		
 | 
			
		||||
		if(isSimpleKey) {
 | 
			
		||||
			// can't follow a simple key with another simple key (dunno why, though - it seems fine)
 | 
			
		||||
			m_simpleKeyAllowed = false;
 | 
			
		||||
		} else {
 | 
			
		||||
			// handle values diffently in the block context (and manage indents)
 | 
			
		||||
			if(InBlockContext()) {
 | 
			
		||||
				if(!m_simpleKeyAllowed)
 | 
			
		||||
					throw ParserException(INPUT.mark(), ErrorMsg::MAP_VALUE);
 | 
			
		||||
 | 
			
		||||
				PushIndentTo(INPUT.column(), IndentMarker::MAP);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// can only put a simple key here if we're in block context
 | 
			
		||||
			m_simpleKeyAllowed = InBlockContext();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// eat
 | 
			
		||||
		Mark mark = INPUT.mark();
 | 
			
		||||
		INPUT.eat(1);
 | 
			
		||||
		m_tokens.push(Token(Token::VALUE, mark));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// AnchorOrAlias
 | 
			
		||||
	void Scanner::ScanAnchorOrAlias()
 | 
			
		||||
	{
 | 
			
		||||
		bool alias;
 | 
			
		||||
		std::string name;
 | 
			
		||||
 | 
			
		||||
		// insert a potential simple key
 | 
			
		||||
		InsertPotentialSimpleKey();
 | 
			
		||||
		m_simpleKeyAllowed = false;
 | 
			
		||||
		m_canBeJSONFlow = false;
 | 
			
		||||
 | 
			
		||||
		// eat the indicator
 | 
			
		||||
		Mark mark = INPUT.mark();
 | 
			
		||||
		char indicator = INPUT.get();
 | 
			
		||||
		alias = (indicator == Keys::Alias);
 | 
			
		||||
 | 
			
		||||
		// now eat the content
 | 
			
		||||
		while(Exp::AlphaNumeric().Matches(INPUT))
 | 
			
		||||
			name += INPUT.get();
 | 
			
		||||
 | 
			
		||||
		// we need to have read SOMETHING!
 | 
			
		||||
		if(name.empty())
 | 
			
		||||
			throw ParserException(INPUT.mark(), alias ? ErrorMsg::ALIAS_NOT_FOUND : ErrorMsg::ANCHOR_NOT_FOUND);
 | 
			
		||||
 | 
			
		||||
		// and needs to end correctly
 | 
			
		||||
		if(INPUT && !Exp::AnchorEnd().Matches(INPUT))
 | 
			
		||||
			throw ParserException(INPUT.mark(), alias ? ErrorMsg::CHAR_IN_ALIAS : ErrorMsg::CHAR_IN_ANCHOR);
 | 
			
		||||
 | 
			
		||||
		// and we're done
 | 
			
		||||
		Token token(alias ? Token::ALIAS : Token::ANCHOR, mark);
 | 
			
		||||
		token.value = name;
 | 
			
		||||
		m_tokens.push(token);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Tag
 | 
			
		||||
	void Scanner::ScanTag()
 | 
			
		||||
	{
 | 
			
		||||
		// insert a potential simple key
 | 
			
		||||
		InsertPotentialSimpleKey();
 | 
			
		||||
		m_simpleKeyAllowed = false;
 | 
			
		||||
		m_canBeJSONFlow = false;
 | 
			
		||||
 | 
			
		||||
		Token token(Token::TAG, INPUT.mark());
 | 
			
		||||
 | 
			
		||||
		// eat the indicator
 | 
			
		||||
		INPUT.get();
 | 
			
		||||
		
 | 
			
		||||
		if(INPUT && INPUT.peek() == Keys::VerbatimTagStart){
 | 
			
		||||
			std::string tag = ScanVerbatimTag(INPUT);
 | 
			
		||||
 | 
			
		||||
			token.value = tag;
 | 
			
		||||
			token.data = Tag::VERBATIM;
 | 
			
		||||
		} else {
 | 
			
		||||
			bool canBeHandle;
 | 
			
		||||
			token.value = ScanTagHandle(INPUT, canBeHandle);
 | 
			
		||||
			token.data = (token.value.empty() ? Tag::SECONDARY_HANDLE : Tag::PRIMARY_HANDLE);
 | 
			
		||||
			
 | 
			
		||||
			// is there a suffix?
 | 
			
		||||
			if(canBeHandle && INPUT.peek() == Keys::Tag) {
 | 
			
		||||
				// eat the indicator
 | 
			
		||||
				INPUT.get();
 | 
			
		||||
				token.params.push_back(ScanTagSuffix(INPUT));
 | 
			
		||||
				token.data = Tag::NAMED_HANDLE;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		m_tokens.push(token);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// PlainScalar
 | 
			
		||||
	void Scanner::ScanPlainScalar()
 | 
			
		||||
	{
 | 
			
		||||
		std::string scalar;
 | 
			
		||||
 | 
			
		||||
		// set up the scanning parameters
 | 
			
		||||
		ScanScalarParams params;
 | 
			
		||||
		params.end = (InFlowContext() ? Exp::EndScalarInFlow() : Exp::EndScalar()) || (Exp::BlankOrBreak() + Exp::Comment());
 | 
			
		||||
		params.eatEnd = false;
 | 
			
		||||
		params.indent = (InFlowContext() ? 0 : GetTopIndent() + 1);
 | 
			
		||||
		params.fold = FOLD_FLOW;
 | 
			
		||||
		params.eatLeadingWhitespace = true;
 | 
			
		||||
		params.trimTrailingSpaces = true;
 | 
			
		||||
		params.chomp = STRIP;
 | 
			
		||||
		params.onDocIndicator = BREAK;
 | 
			
		||||
		params.onTabInIndentation = THROW;
 | 
			
		||||
 | 
			
		||||
		// insert a potential simple key
 | 
			
		||||
		InsertPotentialSimpleKey();
 | 
			
		||||
 | 
			
		||||
		Mark mark = INPUT.mark();
 | 
			
		||||
		scalar = ScanScalar(INPUT, params);
 | 
			
		||||
 | 
			
		||||
		// can have a simple key only if we ended the scalar by starting a new line
 | 
			
		||||
		m_simpleKeyAllowed = params.leadingSpaces;
 | 
			
		||||
		m_canBeJSONFlow = false;
 | 
			
		||||
 | 
			
		||||
		// finally, check and see if we ended on an illegal character
 | 
			
		||||
		//if(Exp::IllegalCharInScalar.Matches(INPUT))
 | 
			
		||||
		//	throw ParserException(INPUT.mark(), ErrorMsg::CHAR_IN_SCALAR);
 | 
			
		||||
 | 
			
		||||
		Token token(Token::SCALAR, mark);
 | 
			
		||||
		token.value = scalar;
 | 
			
		||||
		m_tokens.push(token);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// QuotedScalar
 | 
			
		||||
	void Scanner::ScanQuotedScalar()
 | 
			
		||||
	{
 | 
			
		||||
		std::string scalar;
 | 
			
		||||
 | 
			
		||||
		// peek at single or double quote (don't eat because we need to preserve (for the time being) the input position)
 | 
			
		||||
		char quote = INPUT.peek();
 | 
			
		||||
		bool single = (quote == '\'');
 | 
			
		||||
 | 
			
		||||
		// setup the scanning parameters
 | 
			
		||||
		ScanScalarParams params;
 | 
			
		||||
		params.end = (single ? RegEx(quote) && !Exp::EscSingleQuote() : RegEx(quote));
 | 
			
		||||
		params.eatEnd = true;
 | 
			
		||||
		params.escape = (single ? '\'' : '\\');
 | 
			
		||||
		params.indent = 0;
 | 
			
		||||
		params.fold = FOLD_FLOW;
 | 
			
		||||
		params.eatLeadingWhitespace = true;
 | 
			
		||||
		params.trimTrailingSpaces = false;
 | 
			
		||||
		params.chomp = CLIP;
 | 
			
		||||
		params.onDocIndicator = THROW;
 | 
			
		||||
 | 
			
		||||
		// insert a potential simple key
 | 
			
		||||
		InsertPotentialSimpleKey();
 | 
			
		||||
 | 
			
		||||
		Mark mark = INPUT.mark();
 | 
			
		||||
 | 
			
		||||
		// now eat that opening quote
 | 
			
		||||
		INPUT.get();
 | 
			
		||||
		
 | 
			
		||||
		// and scan
 | 
			
		||||
		scalar = ScanScalar(INPUT, params);
 | 
			
		||||
		m_simpleKeyAllowed = false;
 | 
			
		||||
		m_canBeJSONFlow = true;
 | 
			
		||||
 | 
			
		||||
		Token token(Token::SCALAR, mark);
 | 
			
		||||
		token.value = scalar;
 | 
			
		||||
		m_tokens.push(token);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// BlockScalarToken
 | 
			
		||||
	// . These need a little extra processing beforehand.
 | 
			
		||||
	// . We need to scan the line where the indicator is (this doesn't count as part of the scalar),
 | 
			
		||||
	//   and then we need to figure out what level of indentation we'll be using.
 | 
			
		||||
	void Scanner::ScanBlockScalar()
 | 
			
		||||
	{
 | 
			
		||||
		std::string scalar;
 | 
			
		||||
 | 
			
		||||
		ScanScalarParams params;
 | 
			
		||||
		params.indent = 1;
 | 
			
		||||
		params.detectIndent = true;
 | 
			
		||||
 | 
			
		||||
		// eat block indicator ('|' or '>')
 | 
			
		||||
		Mark mark = INPUT.mark();
 | 
			
		||||
		char indicator = INPUT.get();
 | 
			
		||||
		params.fold = (indicator == Keys::FoldedScalar ? FOLD_BLOCK : DONT_FOLD);
 | 
			
		||||
 | 
			
		||||
		// eat chomping/indentation indicators
 | 
			
		||||
		params.chomp = CLIP;
 | 
			
		||||
		int n = Exp::Chomp().Match(INPUT);
 | 
			
		||||
		for(int i=0;i<n;i++) {
 | 
			
		||||
			char ch = INPUT.get();
 | 
			
		||||
			if(ch == '+')
 | 
			
		||||
				params.chomp = KEEP;
 | 
			
		||||
			else if(ch == '-')
 | 
			
		||||
				params.chomp = STRIP;
 | 
			
		||||
			else if(Exp::Digit().Matches(ch)) {
 | 
			
		||||
				if(ch == '0')
 | 
			
		||||
					throw ParserException(INPUT.mark(), ErrorMsg::ZERO_INDENT_IN_BLOCK);
 | 
			
		||||
 | 
			
		||||
				params.indent = ch - '0';
 | 
			
		||||
				params.detectIndent = false;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// now eat whitespace
 | 
			
		||||
		while(Exp::Blank().Matches(INPUT))
 | 
			
		||||
			INPUT.eat(1);
 | 
			
		||||
 | 
			
		||||
		// and comments to the end of the line
 | 
			
		||||
		if(Exp::Comment().Matches(INPUT))
 | 
			
		||||
			while(INPUT && !Exp::Break().Matches(INPUT))
 | 
			
		||||
				INPUT.eat(1);
 | 
			
		||||
 | 
			
		||||
		// if it's not a line break, then we ran into a bad character inline
 | 
			
		||||
		if(INPUT && !Exp::Break().Matches(INPUT))
 | 
			
		||||
			throw ParserException(INPUT.mark(), ErrorMsg::CHAR_IN_BLOCK);
 | 
			
		||||
 | 
			
		||||
		// set the initial indentation
 | 
			
		||||
		if(GetTopIndent() >= 0)
 | 
			
		||||
			params.indent += GetTopIndent();
 | 
			
		||||
 | 
			
		||||
		params.eatLeadingWhitespace = false;
 | 
			
		||||
		params.trimTrailingSpaces = false;
 | 
			
		||||
		params.onTabInIndentation = THROW;
 | 
			
		||||
 | 
			
		||||
		scalar = ScanScalar(INPUT, params);
 | 
			
		||||
 | 
			
		||||
		// simple keys always ok after block scalars (since we're gonna start a new line anyways)
 | 
			
		||||
		m_simpleKeyAllowed = true;
 | 
			
		||||
		m_canBeJSONFlow = false;
 | 
			
		||||
 | 
			
		||||
		Token token(Token::SCALAR, mark);
 | 
			
		||||
		token.value = scalar;
 | 
			
		||||
		m_tokens.push(token);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										169
									
								
								libs/yaml-cpp/src/sequence.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										169
									
								
								libs/yaml-cpp/src/sequence.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,169 @@
 | 
			
		||||
#include "sequence.h"
 | 
			
		||||
#include "node.h"
 | 
			
		||||
#include "scanner.h"
 | 
			
		||||
#include "token.h"
 | 
			
		||||
#include "emitter.h"
 | 
			
		||||
#include <stdexcept>
 | 
			
		||||
 | 
			
		||||
namespace YAML
 | 
			
		||||
{
 | 
			
		||||
	Sequence::Sequence()
 | 
			
		||||
	{
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Sequence::Sequence(const std::vector<Node *>& data)
 | 
			
		||||
	{
 | 
			
		||||
		for(std::size_t i=0;i<data.size();i++)
 | 
			
		||||
			m_data.push_back(data[i]->Clone().release());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Sequence::~Sequence()
 | 
			
		||||
	{
 | 
			
		||||
		Clear();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void Sequence::Clear()
 | 
			
		||||
	{
 | 
			
		||||
		for(std::size_t i=0;i<m_data.size();i++)
 | 
			
		||||
			delete m_data[i];
 | 
			
		||||
		m_data.clear();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Content *Sequence::Clone() const
 | 
			
		||||
	{
 | 
			
		||||
		return new Sequence(m_data);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	bool Sequence::GetBegin(std::vector <Node *>::const_iterator& it) const
 | 
			
		||||
	{
 | 
			
		||||
		it = m_data.begin();
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	bool Sequence::GetEnd(std::vector <Node *>::const_iterator& it) const
 | 
			
		||||
	{
 | 
			
		||||
		it = m_data.end();
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Node *Sequence::GetNode(std::size_t i) const
 | 
			
		||||
	{
 | 
			
		||||
		if(i < m_data.size())
 | 
			
		||||
			return m_data[i];
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	std::size_t Sequence::GetSize() const
 | 
			
		||||
	{
 | 
			
		||||
		return m_data.size();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void Sequence::Parse(Scanner *pScanner, ParserState& state)
 | 
			
		||||
	{
 | 
			
		||||
		Clear();
 | 
			
		||||
 | 
			
		||||
		// split based on start token
 | 
			
		||||
		switch(pScanner->peek().type) {
 | 
			
		||||
			case Token::BLOCK_SEQ_START: ParseBlock(pScanner, state); break;
 | 
			
		||||
			case Token::FLOW_SEQ_START: ParseFlow(pScanner, state); break;
 | 
			
		||||
			default: break;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void Sequence::ParseBlock(Scanner *pScanner, ParserState& state)
 | 
			
		||||
	{
 | 
			
		||||
		// eat start token
 | 
			
		||||
		pScanner->pop();
 | 
			
		||||
		state.PushCollectionType(ParserState::BLOCK_SEQ);
 | 
			
		||||
 | 
			
		||||
		while(1) {
 | 
			
		||||
			if(pScanner->empty())
 | 
			
		||||
				throw ParserException(Mark::null(), ErrorMsg::END_OF_SEQ);
 | 
			
		||||
 | 
			
		||||
			Token token = pScanner->peek();
 | 
			
		||||
			if(token.type != Token::BLOCK_ENTRY && token.type != Token::BLOCK_SEQ_END)
 | 
			
		||||
				throw ParserException(token.mark, ErrorMsg::END_OF_SEQ);
 | 
			
		||||
 | 
			
		||||
			pScanner->pop();
 | 
			
		||||
			if(token.type == Token::BLOCK_SEQ_END)
 | 
			
		||||
				break;
 | 
			
		||||
 | 
			
		||||
			Node *pNode = new Node;
 | 
			
		||||
			m_data.push_back(pNode);
 | 
			
		||||
			
 | 
			
		||||
			// check for null
 | 
			
		||||
			if(!pScanner->empty()) {
 | 
			
		||||
				const Token& token = pScanner->peek();
 | 
			
		||||
				if(token.type == Token::BLOCK_ENTRY || token.type == Token::BLOCK_SEQ_END)
 | 
			
		||||
					continue;
 | 
			
		||||
			}
 | 
			
		||||
			
 | 
			
		||||
			pNode->Parse(pScanner, state);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		state.PopCollectionType(ParserState::BLOCK_SEQ);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void Sequence::ParseFlow(Scanner *pScanner, ParserState& state)
 | 
			
		||||
	{
 | 
			
		||||
		// eat start token
 | 
			
		||||
		pScanner->pop();
 | 
			
		||||
		state.PushCollectionType(ParserState::FLOW_SEQ);
 | 
			
		||||
 | 
			
		||||
		while(1) {
 | 
			
		||||
			if(pScanner->empty())
 | 
			
		||||
				throw ParserException(Mark::null(), ErrorMsg::END_OF_SEQ_FLOW);
 | 
			
		||||
 | 
			
		||||
			// first check for end
 | 
			
		||||
			if(pScanner->peek().type == Token::FLOW_SEQ_END) {
 | 
			
		||||
				pScanner->pop();
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// then read the node
 | 
			
		||||
			Node *pNode = new Node;
 | 
			
		||||
			m_data.push_back(pNode);
 | 
			
		||||
			pNode->Parse(pScanner, state);
 | 
			
		||||
 | 
			
		||||
			// now eat the separator (or could be a sequence end, which we ignore - but if it's neither, then it's a bad node)
 | 
			
		||||
			Token& token = pScanner->peek();
 | 
			
		||||
			if(token.type == Token::FLOW_ENTRY)
 | 
			
		||||
				pScanner->pop();
 | 
			
		||||
			else if(token.type != Token::FLOW_SEQ_END)
 | 
			
		||||
				throw ParserException(token.mark, ErrorMsg::END_OF_SEQ_FLOW);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		state.PopCollectionType(ParserState::FLOW_SEQ);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void Sequence::Write(Emitter& out) const
 | 
			
		||||
	{
 | 
			
		||||
		out << BeginSeq;
 | 
			
		||||
		for(std::size_t i=0;i<m_data.size();i++)
 | 
			
		||||
			out << *m_data[i];
 | 
			
		||||
		out << EndSeq;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	int Sequence::Compare(Content *pContent)
 | 
			
		||||
	{
 | 
			
		||||
		return -pContent->Compare(this);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	int Sequence::Compare(Sequence *pSeq)
 | 
			
		||||
	{
 | 
			
		||||
		std::size_t n = m_data.size(), m = pSeq->m_data.size();
 | 
			
		||||
		if(n < m)
 | 
			
		||||
			return -1;
 | 
			
		||||
		else if(n > m)
 | 
			
		||||
			return 1;
 | 
			
		||||
 | 
			
		||||
		for(std::size_t i=0;i<n;i++) {
 | 
			
		||||
			int cmp = m_data[i]->Compare(*pSeq->m_data[i]);
 | 
			
		||||
			if(cmp != 0)
 | 
			
		||||
				return cmp;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										49
									
								
								libs/yaml-cpp/src/sequence.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								libs/yaml-cpp/src/sequence.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,49 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#ifndef SEQUENCE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
 | 
			
		||||
#define SEQUENCE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include "content.h"
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
namespace YAML
 | 
			
		||||
{
 | 
			
		||||
	class Node;
 | 
			
		||||
 | 
			
		||||
	class Sequence: public Content
 | 
			
		||||
	{
 | 
			
		||||
	public:
 | 
			
		||||
		Sequence();
 | 
			
		||||
		Sequence(const std::vector<Node *>& data);
 | 
			
		||||
		virtual ~Sequence();
 | 
			
		||||
 | 
			
		||||
		void Clear();
 | 
			
		||||
		virtual Content *Clone() const;
 | 
			
		||||
 | 
			
		||||
		virtual bool GetBegin(std::vector <Node *>::const_iterator& it) const;
 | 
			
		||||
		virtual bool GetEnd(std::vector <Node *>::const_iterator& it) const;
 | 
			
		||||
		virtual Node *GetNode(std::size_t i) const;
 | 
			
		||||
		virtual std::size_t GetSize() const;
 | 
			
		||||
 | 
			
		||||
		virtual void Parse(Scanner *pScanner, ParserState& state);
 | 
			
		||||
		virtual void Write(Emitter& out) const;
 | 
			
		||||
 | 
			
		||||
		virtual bool IsSequence() const { return true; }
 | 
			
		||||
 | 
			
		||||
		// ordering
 | 
			
		||||
		virtual int Compare(Content *pContent);
 | 
			
		||||
		virtual int Compare(Scalar *) { return 1; }
 | 
			
		||||
		virtual int Compare(Sequence *pSeq);
 | 
			
		||||
		virtual int Compare(Map *) { return -1; }
 | 
			
		||||
 | 
			
		||||
	private:
 | 
			
		||||
		void ParseBlock(Scanner *pScanner, ParserState& state);
 | 
			
		||||
		void ParseFlow(Scanner *pScanner, ParserState& state);
 | 
			
		||||
 | 
			
		||||
	protected:
 | 
			
		||||
		std::vector <Node *> m_data;
 | 
			
		||||
	};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // SEQUENCE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
 | 
			
		||||
							
								
								
									
										103
									
								
								libs/yaml-cpp/src/setting.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								libs/yaml-cpp/src/setting.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,103 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#ifndef SETTING_H_62B23520_7C8E_11DE_8A39_0800200C9A66
 | 
			
		||||
#define SETTING_H_62B23520_7C8E_11DE_8A39_0800200C9A66
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include <memory>
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include "noncopyable.h"
 | 
			
		||||
 | 
			
		||||
namespace YAML
 | 
			
		||||
{
 | 
			
		||||
	class SettingChangeBase;
 | 
			
		||||
	
 | 
			
		||||
	template <typename T>
 | 
			
		||||
	class Setting
 | 
			
		||||
	{
 | 
			
		||||
	public:
 | 
			
		||||
		Setting(): m_value() {}
 | 
			
		||||
		
 | 
			
		||||
		const T get() const { return m_value; }
 | 
			
		||||
		std::auto_ptr <SettingChangeBase> set(const T& value);
 | 
			
		||||
		void restore(const Setting<T>& oldSetting) {
 | 
			
		||||
			m_value = oldSetting.get();
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
	private:
 | 
			
		||||
		T m_value;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	class SettingChangeBase
 | 
			
		||||
	{
 | 
			
		||||
	public:
 | 
			
		||||
		virtual ~SettingChangeBase() {}
 | 
			
		||||
		virtual void pop() = 0;
 | 
			
		||||
	};
 | 
			
		||||
	
 | 
			
		||||
	template <typename T>
 | 
			
		||||
	class SettingChange: public SettingChangeBase
 | 
			
		||||
	{
 | 
			
		||||
	public:
 | 
			
		||||
		SettingChange(Setting<T> *pSetting): m_pCurSetting(pSetting) {
 | 
			
		||||
			// copy old setting to save its state
 | 
			
		||||
			m_oldSetting = *pSetting;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		virtual void pop() {
 | 
			
		||||
			m_pCurSetting->restore(m_oldSetting);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	private:
 | 
			
		||||
		Setting<T> *m_pCurSetting;
 | 
			
		||||
		Setting<T> m_oldSetting;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	template <typename T>
 | 
			
		||||
	inline std::auto_ptr <SettingChangeBase> Setting<T>::set(const T& value) {
 | 
			
		||||
		std::auto_ptr <SettingChangeBase> pChange(new SettingChange<T> (this));
 | 
			
		||||
		m_value = value;
 | 
			
		||||
		return pChange;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	class SettingChanges: private noncopyable
 | 
			
		||||
	{
 | 
			
		||||
	public:
 | 
			
		||||
		SettingChanges() {}
 | 
			
		||||
		~SettingChanges() { clear(); }
 | 
			
		||||
		
 | 
			
		||||
		void clear() {
 | 
			
		||||
			restore();
 | 
			
		||||
			
 | 
			
		||||
			for(setting_changes::const_iterator it=m_settingChanges.begin();it!=m_settingChanges.end();++it)
 | 
			
		||||
				delete *it;
 | 
			
		||||
			m_settingChanges.clear();
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		void restore() {
 | 
			
		||||
			for(setting_changes::const_iterator it=m_settingChanges.begin();it!=m_settingChanges.end();++it)
 | 
			
		||||
				(*it)->pop();
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		void push(std::auto_ptr <SettingChangeBase> pSettingChange) {
 | 
			
		||||
			m_settingChanges.push_back(pSettingChange.release());
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		// like std::auto_ptr - assignment is transfer of ownership
 | 
			
		||||
		SettingChanges& operator = (SettingChanges& rhs) {
 | 
			
		||||
			if(this == &rhs)
 | 
			
		||||
				return *this;
 | 
			
		||||
			
 | 
			
		||||
			clear();
 | 
			
		||||
			m_settingChanges = rhs.m_settingChanges;
 | 
			
		||||
			rhs.m_settingChanges.clear();
 | 
			
		||||
			return *this;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
	private:
 | 
			
		||||
		typedef std::vector <SettingChangeBase *> setting_changes;
 | 
			
		||||
		setting_changes m_settingChanges;
 | 
			
		||||
	};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // SETTING_H_62B23520_7C8E_11DE_8A39_0800200C9A66
 | 
			
		||||
							
								
								
									
										139
									
								
								libs/yaml-cpp/src/simplekey.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										139
									
								
								libs/yaml-cpp/src/simplekey.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,139 @@
 | 
			
		||||
#include "scanner.h"
 | 
			
		||||
#include "token.h"
 | 
			
		||||
#include "exceptions.h"
 | 
			
		||||
#include "exp.h"
 | 
			
		||||
 | 
			
		||||
namespace YAML
 | 
			
		||||
{
 | 
			
		||||
	Scanner::SimpleKey::SimpleKey(const Mark& mark_, int flowLevel_)
 | 
			
		||||
		: mark(mark_), flowLevel(flowLevel_), pIndent(0), pMapStart(0), pKey(0)
 | 
			
		||||
	{
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void Scanner::SimpleKey::Validate()
 | 
			
		||||
	{
 | 
			
		||||
		// Note: pIndent will *not* be garbage here;
 | 
			
		||||
		//       we "garbage collect" them so we can
 | 
			
		||||
		//       always refer to them
 | 
			
		||||
		if(pIndent)
 | 
			
		||||
			pIndent->status = IndentMarker::VALID;
 | 
			
		||||
		if(pMapStart)
 | 
			
		||||
			pMapStart->status = Token::VALID;
 | 
			
		||||
		if(pKey)
 | 
			
		||||
			pKey->status = Token::VALID;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void Scanner::SimpleKey::Invalidate()
 | 
			
		||||
	{
 | 
			
		||||
		if(pIndent)
 | 
			
		||||
			pIndent->status = IndentMarker::INVALID;
 | 
			
		||||
		if(pMapStart)
 | 
			
		||||
			pMapStart->status = Token::INVALID;
 | 
			
		||||
		if(pKey)
 | 
			
		||||
			pKey->status = Token::INVALID;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	// CanInsertPotentialSimpleKey
 | 
			
		||||
	bool Scanner::CanInsertPotentialSimpleKey() const
 | 
			
		||||
	{
 | 
			
		||||
		if(!m_simpleKeyAllowed)
 | 
			
		||||
			return false;
 | 
			
		||||
 | 
			
		||||
		return !ExistsActiveSimpleKey();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// ExistsActiveSimpleKey
 | 
			
		||||
	// . Returns true if there's a potential simple key at our flow level
 | 
			
		||||
	//   (there's allowed at most one per flow level, i.e., at the start of the flow start token)
 | 
			
		||||
	bool Scanner::ExistsActiveSimpleKey() const
 | 
			
		||||
	{
 | 
			
		||||
		if(m_simpleKeys.empty())
 | 
			
		||||
			return false;
 | 
			
		||||
		
 | 
			
		||||
		const SimpleKey& key = m_simpleKeys.top();
 | 
			
		||||
		return key.flowLevel == GetFlowLevel();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// InsertPotentialSimpleKey
 | 
			
		||||
	// . If we can, add a potential simple key to the queue,
 | 
			
		||||
	//   and save it on a stack.
 | 
			
		||||
	void Scanner::InsertPotentialSimpleKey()
 | 
			
		||||
	{
 | 
			
		||||
		if(!CanInsertPotentialSimpleKey())
 | 
			
		||||
			return;
 | 
			
		||||
		
 | 
			
		||||
		SimpleKey key(INPUT.mark(), GetFlowLevel());
 | 
			
		||||
 | 
			
		||||
		// first add a map start, if necessary
 | 
			
		||||
		if(InBlockContext()) {
 | 
			
		||||
			key.pIndent = PushIndentTo(INPUT.column(), IndentMarker::MAP);
 | 
			
		||||
			if(key.pIndent) {
 | 
			
		||||
				key.pIndent->status = IndentMarker::UNKNOWN;
 | 
			
		||||
				key.pMapStart = key.pIndent->pStartToken;
 | 
			
		||||
				key.pMapStart->status = Token::UNVERIFIED;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// then add the (now unverified) key
 | 
			
		||||
		m_tokens.push(Token(Token::KEY, INPUT.mark()));
 | 
			
		||||
		key.pKey = &m_tokens.back();
 | 
			
		||||
		key.pKey->status = Token::UNVERIFIED;
 | 
			
		||||
 | 
			
		||||
		m_simpleKeys.push(key);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// InvalidateSimpleKey
 | 
			
		||||
	// . Automatically invalidate the simple key in our flow level
 | 
			
		||||
	void Scanner::InvalidateSimpleKey()
 | 
			
		||||
	{
 | 
			
		||||
		if(m_simpleKeys.empty())
 | 
			
		||||
			return;
 | 
			
		||||
		
 | 
			
		||||
		// grab top key
 | 
			
		||||
		SimpleKey& key = m_simpleKeys.top();
 | 
			
		||||
		if(key.flowLevel != GetFlowLevel())
 | 
			
		||||
			return;
 | 
			
		||||
		
 | 
			
		||||
		key.Invalidate();
 | 
			
		||||
		m_simpleKeys.pop();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// VerifySimpleKey
 | 
			
		||||
	// . Determines whether the latest simple key to be added is valid,
 | 
			
		||||
	//   and if so, makes it valid.
 | 
			
		||||
	bool Scanner::VerifySimpleKey()
 | 
			
		||||
	{
 | 
			
		||||
		if(m_simpleKeys.empty())
 | 
			
		||||
			return false;
 | 
			
		||||
 | 
			
		||||
		// grab top key
 | 
			
		||||
		SimpleKey key = m_simpleKeys.top();
 | 
			
		||||
 | 
			
		||||
		// only validate if we're in the correct flow level
 | 
			
		||||
		if(key.flowLevel != GetFlowLevel())
 | 
			
		||||
			return false;
 | 
			
		||||
 | 
			
		||||
		m_simpleKeys.pop();
 | 
			
		||||
 | 
			
		||||
		bool isValid = true;
 | 
			
		||||
 | 
			
		||||
		// needs to be less than 1024 characters and inline
 | 
			
		||||
		if(INPUT.line() != key.mark.line || INPUT.pos() - key.mark.pos > 1024)
 | 
			
		||||
			isValid = false;
 | 
			
		||||
 | 
			
		||||
		// invalidate key
 | 
			
		||||
		if(isValid)
 | 
			
		||||
			key.Validate();
 | 
			
		||||
		else
 | 
			
		||||
			key.Invalidate();
 | 
			
		||||
 | 
			
		||||
		return isValid;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void Scanner::PopAllSimpleKeys()
 | 
			
		||||
	{
 | 
			
		||||
		while(!m_simpleKeys.empty())
 | 
			
		||||
			m_simpleKeys.pop();
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										454
									
								
								libs/yaml-cpp/src/stream.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										454
									
								
								libs/yaml-cpp/src/stream.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,454 @@
 | 
			
		||||
#include "stream.h"
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include "exp.h"
 | 
			
		||||
 | 
			
		||||
#ifndef YAML_PREFETCH_SIZE
 | 
			
		||||
#define YAML_PREFETCH_SIZE 2048
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define S_ARRAY_SIZE( A ) (sizeof(A)/sizeof(*(A)))
 | 
			
		||||
#define S_ARRAY_END( A ) ((A) + S_ARRAY_SIZE(A))
 | 
			
		||||
 | 
			
		||||
#define CP_REPLACEMENT_CHARACTER (0xFFFD)
 | 
			
		||||
 | 
			
		||||
namespace YAML
 | 
			
		||||
{
 | 
			
		||||
	enum UtfIntroState {
 | 
			
		||||
		uis_start,
 | 
			
		||||
		uis_utfbe_b1,
 | 
			
		||||
		uis_utf32be_b2,
 | 
			
		||||
		uis_utf32be_bom3,
 | 
			
		||||
		uis_utf32be,
 | 
			
		||||
		uis_utf16be,
 | 
			
		||||
		uis_utf16be_bom1,
 | 
			
		||||
		uis_utfle_bom1,
 | 
			
		||||
		uis_utf16le_bom2,
 | 
			
		||||
		uis_utf32le_bom3,
 | 
			
		||||
		uis_utf16le,
 | 
			
		||||
		uis_utf32le,
 | 
			
		||||
		uis_utf8_imp,
 | 
			
		||||
		uis_utf16le_imp,
 | 
			
		||||
		uis_utf32le_imp3,
 | 
			
		||||
		uis_utf8_bom1,
 | 
			
		||||
		uis_utf8_bom2,
 | 
			
		||||
		uis_utf8,
 | 
			
		||||
		uis_error
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	enum UtfIntroCharType {
 | 
			
		||||
		uict00,
 | 
			
		||||
		uictBB,
 | 
			
		||||
		uictBF,
 | 
			
		||||
		uictEF,
 | 
			
		||||
		uictFE,
 | 
			
		||||
		uictFF,
 | 
			
		||||
		uictAscii,
 | 
			
		||||
		uictOther,
 | 
			
		||||
		uictMax
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	static bool s_introFinalState[] = {
 | 
			
		||||
		false, //uis_start
 | 
			
		||||
		false, //uis_utfbe_b1
 | 
			
		||||
		false, //uis_utf32be_b2
 | 
			
		||||
		false, //uis_utf32be_bom3
 | 
			
		||||
		true,  //uis_utf32be
 | 
			
		||||
		true,  //uis_utf16be
 | 
			
		||||
		false, //uis_utf16be_bom1
 | 
			
		||||
		false, //uis_utfle_bom1
 | 
			
		||||
		false, //uis_utf16le_bom2
 | 
			
		||||
		false, //uis_utf32le_bom3
 | 
			
		||||
		true,  //uis_utf16le
 | 
			
		||||
		true,  //uis_utf32le
 | 
			
		||||
		false, //uis_utf8_imp
 | 
			
		||||
		false, //uis_utf16le_imp
 | 
			
		||||
		false, //uis_utf32le_imp3
 | 
			
		||||
		false, //uis_utf8_bom1
 | 
			
		||||
		false, //uis_utf8_bom2
 | 
			
		||||
		true,  //uis_utf8
 | 
			
		||||
		true,  //uis_error
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	static UtfIntroState s_introTransitions[][uictMax] = {
 | 
			
		||||
		// uict00,           uictBB,           uictBF,           uictEF,           uictFE,           uictFF,           uictAscii,        uictOther
 | 
			
		||||
		  {uis_utfbe_b1,     uis_utf8,         uis_utf8,         uis_utf8_bom1,    uis_utf16be_bom1, uis_utfle_bom1,   uis_utf8_imp,     uis_utf8},
 | 
			
		||||
		  {uis_utf32be_b2,   uis_utf8,         uis_utf8,         uis_utf8,         uis_utf8,         uis_utf8,         uis_utf16be,      uis_utf8},
 | 
			
		||||
		  {uis_utf32be,      uis_utf8,         uis_utf8,         uis_utf8,         uis_utf32be_bom3, uis_utf8,         uis_utf8,         uis_utf8},
 | 
			
		||||
		  {uis_utf8,         uis_utf8,         uis_utf8,         uis_utf8,         uis_utf8,         uis_utf32be,      uis_utf8,         uis_utf8},
 | 
			
		||||
		  {uis_utf32be,      uis_utf32be,      uis_utf32be,      uis_utf32be,      uis_utf32be,      uis_utf32be,      uis_utf32be,      uis_utf32be},
 | 
			
		||||
		  {uis_utf16be,      uis_utf16be,      uis_utf16be,      uis_utf16be,      uis_utf16be,      uis_utf16be,      uis_utf16be,      uis_utf16be},
 | 
			
		||||
		  {uis_utf8,         uis_utf8,         uis_utf8,         uis_utf8,         uis_utf8,         uis_utf16be,      uis_utf8,         uis_utf8},
 | 
			
		||||
		  {uis_utf8,         uis_utf8,         uis_utf8,         uis_utf8,         uis_utf16le_bom2, uis_utf8,         uis_utf8,         uis_utf8},
 | 
			
		||||
		  {uis_utf32le_bom3, uis_utf16le,      uis_utf16le,      uis_utf16le,      uis_utf16le,      uis_utf16le,      uis_utf16le,      uis_utf16le},
 | 
			
		||||
		  {uis_utf32le,      uis_utf16le,      uis_utf16le,      uis_utf16le,      uis_utf16le,      uis_utf16le,      uis_utf16le,      uis_utf16le},
 | 
			
		||||
		  {uis_utf16le,      uis_utf16le,      uis_utf16le,      uis_utf16le,      uis_utf16le,      uis_utf16le,      uis_utf16le,      uis_utf16le},
 | 
			
		||||
		  {uis_utf32le,      uis_utf32le,      uis_utf32le,      uis_utf32le,      uis_utf32le,      uis_utf32le,      uis_utf32le,      uis_utf32le},
 | 
			
		||||
		  {uis_utf16le_imp,  uis_utf8,         uis_utf8,         uis_utf8,         uis_utf8,         uis_utf8,         uis_utf8,         uis_utf8},
 | 
			
		||||
		  {uis_utf32le_imp3, uis_utf16le,      uis_utf16le,      uis_utf16le,      uis_utf16le,      uis_utf16le,      uis_utf16le,      uis_utf16le},
 | 
			
		||||
		  {uis_utf32le,      uis_utf16le,      uis_utf16le,      uis_utf16le,      uis_utf16le,      uis_utf16le,      uis_utf16le,      uis_utf16le},
 | 
			
		||||
		  {uis_utf8,         uis_utf8_bom2,    uis_utf8,         uis_utf8,         uis_utf8,         uis_utf8,         uis_utf8,         uis_utf8},
 | 
			
		||||
		  {uis_utf8,         uis_utf8,         uis_utf8,         uis_utf8,         uis_utf8,         uis_utf8,         uis_utf8,         uis_utf8},
 | 
			
		||||
		  {uis_utf8,         uis_utf8,         uis_utf8,         uis_utf8,         uis_utf8,         uis_utf8,         uis_utf8,         uis_utf8},
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	static char s_introUngetCount[][uictMax] = {
 | 
			
		||||
		// uict00, uictBB, uictBF, uictEF, uictFE, uictFF, uictAscii, uictOther
 | 
			
		||||
		  {0,      1,      1,      0,      0,      0,      0,         1},
 | 
			
		||||
		  {0,      2,      2,      2,      2,      2,      2,         2},
 | 
			
		||||
		  {3,      3,      3,      3,      0,      3,      3,         3},
 | 
			
		||||
		  {4,      4,      4,      4,      4,      0,      4,         4},
 | 
			
		||||
		  {1,      1,      1,      1,      1,      1,      1,         1},
 | 
			
		||||
		  {1,      1,      1,      1,      1,      1,      1,         1},
 | 
			
		||||
		  {2,      2,      2,      2,      2,      0,      2,         2},
 | 
			
		||||
		  {2,      2,      2,      2,      0,      2,      2,         2},
 | 
			
		||||
		  {0,      1,      1,      1,      1,      1,      1,         1},
 | 
			
		||||
		  {0,      2,      2,      2,      2,      2,      2,         2},
 | 
			
		||||
		  {1,      1,      1,      1,      1,      1,      1,         1},
 | 
			
		||||
		  {1,      1,      1,      1,      1,      1,      1,         1},
 | 
			
		||||
		  {0,      2,      2,      2,      2,      2,      2,         2},
 | 
			
		||||
		  {0,      3,      3,      3,      3,      3,      3,         3},
 | 
			
		||||
		  {4,      4,      4,      4,      4,      4,      4,         4},
 | 
			
		||||
		  {2,      0,      2,      2,      2,      2,      2,         2},
 | 
			
		||||
		  {3,      3,      0,      3,      3,      3,      3,         3},
 | 
			
		||||
		  {1,      1,      1,      1,      1,      1,      1,         1},
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	inline UtfIntroCharType IntroCharTypeOf(std::istream::int_type ch)
 | 
			
		||||
	{
 | 
			
		||||
		if (std::istream::traits_type::eof() == ch) {
 | 
			
		||||
			return uictOther;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		switch (ch) {
 | 
			
		||||
		case 0: return uict00;
 | 
			
		||||
		case 0xBB: return uictBB;
 | 
			
		||||
		case 0xBF: return uictBF;
 | 
			
		||||
		case 0xEF: return uictEF;
 | 
			
		||||
		case 0xFE: return uictFE;
 | 
			
		||||
		case 0xFF: return uictFF;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if ((ch > 0) && (ch < 0xFF)) {
 | 
			
		||||
			return uictAscii;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return uictOther;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	inline char Utf8Adjust(unsigned long ch, unsigned char lead_bits, unsigned char rshift)
 | 
			
		||||
	{
 | 
			
		||||
		const unsigned char header = ((1 << lead_bits) - 1) << (8 - lead_bits);
 | 
			
		||||
		const unsigned char mask = (0xFF >> (lead_bits + 1));
 | 
			
		||||
		return static_cast<char>(static_cast<unsigned char>(
 | 
			
		||||
			header | ((ch >> rshift) & mask)
 | 
			
		||||
			));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	inline void QueueUnicodeCodepoint(std::deque<char>& q, unsigned long ch)
 | 
			
		||||
	{
 | 
			
		||||
		// We are not allowed to queue the Stream::eof() codepoint, so
 | 
			
		||||
		// replace it with CP_REPLACEMENT_CHARACTER
 | 
			
		||||
		if (static_cast<unsigned long>(Stream::eof()) == ch)
 | 
			
		||||
		{
 | 
			
		||||
			ch = CP_REPLACEMENT_CHARACTER;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (ch < 0x80)
 | 
			
		||||
		{
 | 
			
		||||
			q.push_back(Utf8Adjust(ch, 0, 0));
 | 
			
		||||
		}
 | 
			
		||||
		else if (ch < 0x800)
 | 
			
		||||
		{
 | 
			
		||||
			q.push_back(Utf8Adjust(ch, 2, 6));
 | 
			
		||||
			q.push_back(Utf8Adjust(ch, 1, 0));
 | 
			
		||||
		}
 | 
			
		||||
		else if (ch < 0x10000)
 | 
			
		||||
		{
 | 
			
		||||
			q.push_back(Utf8Adjust(ch, 3, 12));
 | 
			
		||||
			q.push_back(Utf8Adjust(ch, 1, 6));
 | 
			
		||||
			q.push_back(Utf8Adjust(ch, 1, 0));
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			q.push_back(Utf8Adjust(ch, 4, 18));
 | 
			
		||||
			q.push_back(Utf8Adjust(ch, 1, 12));
 | 
			
		||||
			q.push_back(Utf8Adjust(ch, 1, 6));
 | 
			
		||||
			q.push_back(Utf8Adjust(ch, 1, 0));
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Stream::Stream(std::istream& input)
 | 
			
		||||
		: m_input(input), m_nPushedBack(0),
 | 
			
		||||
		m_pPrefetched(new unsigned char[YAML_PREFETCH_SIZE]), 
 | 
			
		||||
		m_nPrefetchedAvailable(0), m_nPrefetchedUsed(0)
 | 
			
		||||
	{
 | 
			
		||||
		typedef std::istream::traits_type char_traits;
 | 
			
		||||
 | 
			
		||||
		if(!input)
 | 
			
		||||
			return;
 | 
			
		||||
 | 
			
		||||
		// Determine (or guess) the character-set by reading the BOM, if any.  See
 | 
			
		||||
		// the YAML specification for the determination algorithm.
 | 
			
		||||
		char_traits::int_type intro[4];
 | 
			
		||||
		int nIntroUsed = 0;
 | 
			
		||||
		UtfIntroState state = uis_start;
 | 
			
		||||
		for (; !s_introFinalState[state]; ) {
 | 
			
		||||
			std::istream::int_type ch = input.get();
 | 
			
		||||
			intro[nIntroUsed++] = ch;
 | 
			
		||||
			UtfIntroCharType charType = IntroCharTypeOf(ch);
 | 
			
		||||
			UtfIntroState newState = s_introTransitions[state][charType];
 | 
			
		||||
			int nUngets = s_introUngetCount[state][charType];
 | 
			
		||||
			if (nUngets > 0) {
 | 
			
		||||
				for (; nUngets > 0; --nUngets) {
 | 
			
		||||
					if (char_traits::eof() != intro[--nIntroUsed]) {
 | 
			
		||||
						m_bufPushback[m_nPushedBack++] = 
 | 
			
		||||
							char_traits::to_char_type(intro[nIntroUsed]);
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			state = newState;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		switch (state) {
 | 
			
		||||
		case uis_utf8: m_charSet = utf8; break;
 | 
			
		||||
		case uis_utf16le: m_charSet = utf16le; break;
 | 
			
		||||
		case uis_utf16be: m_charSet = utf16be; break;
 | 
			
		||||
		case uis_utf32le: m_charSet = utf32le; break;
 | 
			
		||||
		case uis_utf32be: m_charSet = utf32be; break;
 | 
			
		||||
		default: m_charSet = utf8; break;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		ReadAheadTo(0);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Stream::~Stream()
 | 
			
		||||
	{
 | 
			
		||||
		delete[] m_pPrefetched;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	char Stream::peek() const
 | 
			
		||||
	{
 | 
			
		||||
		if (m_readahead.empty())
 | 
			
		||||
		{
 | 
			
		||||
			return Stream::eof();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return m_readahead[0];
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	Stream::operator bool() const
 | 
			
		||||
	{
 | 
			
		||||
		return m_input.good() || (!m_readahead.empty() && m_readahead[0] != Stream::eof());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// get
 | 
			
		||||
	// . Extracts a character from the stream and updates our position
 | 
			
		||||
	char Stream::get()
 | 
			
		||||
	{
 | 
			
		||||
		char ch = peek();
 | 
			
		||||
		AdvanceCurrent();
 | 
			
		||||
		m_mark.column++;
 | 
			
		||||
		
 | 
			
		||||
		if(ch == '\n') {
 | 
			
		||||
			m_mark.column = 0;
 | 
			
		||||
			m_mark.line++;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		return ch;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// get
 | 
			
		||||
	// . Extracts 'n' characters from the stream and updates our position
 | 
			
		||||
	std::string Stream::get(int n)
 | 
			
		||||
	{
 | 
			
		||||
		std::string ret;
 | 
			
		||||
		ret.reserve(n);
 | 
			
		||||
		for(int i=0;i<n;i++)
 | 
			
		||||
			ret += get();
 | 
			
		||||
		return ret;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// eat
 | 
			
		||||
	// . Eats 'n' characters and updates our position.
 | 
			
		||||
	void Stream::eat(int n)
 | 
			
		||||
	{
 | 
			
		||||
		for(int i=0;i<n;i++)
 | 
			
		||||
			get();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void Stream::AdvanceCurrent()
 | 
			
		||||
	{
 | 
			
		||||
		if (!m_readahead.empty())
 | 
			
		||||
		{
 | 
			
		||||
			m_readahead.pop_front();
 | 
			
		||||
			m_mark.pos++;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		ReadAheadTo(0);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	bool Stream::_ReadAheadTo(size_t i) const
 | 
			
		||||
	{
 | 
			
		||||
		while (m_input.good() && (m_readahead.size() <= i))
 | 
			
		||||
		{
 | 
			
		||||
			switch (m_charSet)
 | 
			
		||||
			{
 | 
			
		||||
			case utf8: StreamInUtf8(); break;
 | 
			
		||||
			case utf16le: StreamInUtf16(); break;
 | 
			
		||||
			case utf16be: StreamInUtf16(); break;
 | 
			
		||||
			case utf32le: StreamInUtf32(); break;
 | 
			
		||||
			case utf32be: StreamInUtf32(); break;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		// signal end of stream
 | 
			
		||||
		if(!m_input.good())
 | 
			
		||||
			m_readahead.push_back(Stream::eof());
 | 
			
		||||
 | 
			
		||||
		return m_readahead.size() > i;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void Stream::StreamInUtf8() const
 | 
			
		||||
	{
 | 
			
		||||
		unsigned char b = GetNextByte();
 | 
			
		||||
		if (m_input.good())
 | 
			
		||||
		{
 | 
			
		||||
			m_readahead.push_back(b);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void Stream::StreamInUtf16() const
 | 
			
		||||
	{
 | 
			
		||||
		unsigned long ch = 0;
 | 
			
		||||
		unsigned char bytes[2];
 | 
			
		||||
		int nBigEnd = (m_charSet == utf16be) ? 0 : 1;
 | 
			
		||||
 | 
			
		||||
		bytes[0] = GetNextByte();
 | 
			
		||||
		bytes[1] = GetNextByte();
 | 
			
		||||
		if (!m_input.good())
 | 
			
		||||
		{
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
		ch = (static_cast<unsigned long>(bytes[nBigEnd]) << 8) |
 | 
			
		||||
			static_cast<unsigned long>(bytes[1 ^ nBigEnd]);
 | 
			
		||||
 | 
			
		||||
		if (ch >= 0xDC00 && ch < 0xE000)
 | 
			
		||||
		{
 | 
			
		||||
			// Trailing (low) surrogate...ugh, wrong order
 | 
			
		||||
			QueueUnicodeCodepoint(m_readahead, CP_REPLACEMENT_CHARACTER);
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
		else if (ch >= 0xD800 && ch < 0xDC00)
 | 
			
		||||
		{
 | 
			
		||||
			// ch is a leading (high) surrogate
 | 
			
		||||
 | 
			
		||||
			// Four byte UTF-8 code point
 | 
			
		||||
 | 
			
		||||
			// Read the trailing (low) surrogate
 | 
			
		||||
			for (;;)
 | 
			
		||||
			{
 | 
			
		||||
				bytes[0] = GetNextByte();
 | 
			
		||||
				bytes[1] = GetNextByte();
 | 
			
		||||
				if (!m_input.good())
 | 
			
		||||
				{
 | 
			
		||||
					QueueUnicodeCodepoint(m_readahead, CP_REPLACEMENT_CHARACTER);
 | 
			
		||||
					return;
 | 
			
		||||
				}
 | 
			
		||||
				unsigned long chLow = (static_cast<unsigned long>(bytes[nBigEnd]) << 8) |
 | 
			
		||||
					static_cast<unsigned long>(bytes[1 ^ nBigEnd]);
 | 
			
		||||
				if (chLow < 0xDC00 || ch >= 0xE000)
 | 
			
		||||
				{
 | 
			
		||||
					// Trouble...not a low surrogate.  Dump a REPLACEMENT CHARACTER into the stream.
 | 
			
		||||
					QueueUnicodeCodepoint(m_readahead, CP_REPLACEMENT_CHARACTER);
 | 
			
		||||
 | 
			
		||||
					// Deal with the next UTF-16 unit
 | 
			
		||||
					if (chLow < 0xD800 || ch >= 0xE000)
 | 
			
		||||
					{
 | 
			
		||||
						// Easiest case: queue the codepoint and return
 | 
			
		||||
						QueueUnicodeCodepoint(m_readahead, ch);
 | 
			
		||||
						return;
 | 
			
		||||
					}
 | 
			
		||||
					else
 | 
			
		||||
					{
 | 
			
		||||
						// Start the loop over with the new high surrogate
 | 
			
		||||
						ch = chLow;
 | 
			
		||||
						continue;
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				// Select the payload bits from the high surrogate
 | 
			
		||||
				ch &= 0x3FF;
 | 
			
		||||
				ch <<= 10;
 | 
			
		||||
 | 
			
		||||
				// Include bits from low surrogate
 | 
			
		||||
				ch |= (chLow & 0x3FF);
 | 
			
		||||
 | 
			
		||||
				// Add the surrogacy offset
 | 
			
		||||
				ch += 0x10000;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		QueueUnicodeCodepoint(m_readahead, ch);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	inline char* ReadBuffer(unsigned char* pBuffer)
 | 
			
		||||
	{
 | 
			
		||||
		return reinterpret_cast<char*>(pBuffer);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	unsigned char Stream::GetNextByte() const
 | 
			
		||||
	{
 | 
			
		||||
		if (m_nPushedBack)
 | 
			
		||||
		{
 | 
			
		||||
			return m_bufPushback[--m_nPushedBack];
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (m_nPrefetchedUsed >= m_nPrefetchedAvailable)
 | 
			
		||||
		{
 | 
			
		||||
			std::streambuf *pBuf = m_input.rdbuf();
 | 
			
		||||
			m_nPrefetchedAvailable = pBuf->sgetn(ReadBuffer(m_pPrefetched), 
 | 
			
		||||
				YAML_PREFETCH_SIZE);
 | 
			
		||||
			m_nPrefetchedUsed = 0;
 | 
			
		||||
			if (!m_nPrefetchedAvailable)
 | 
			
		||||
			{
 | 
			
		||||
				m_input.setstate(std::ios_base::eofbit);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (0 == m_nPrefetchedAvailable)
 | 
			
		||||
			{
 | 
			
		||||
				return 0;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return m_pPrefetched[m_nPrefetchedUsed++];
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void Stream::StreamInUtf32() const
 | 
			
		||||
	{
 | 
			
		||||
		static int indexes[2][4] = {
 | 
			
		||||
			{3, 2, 1, 0},
 | 
			
		||||
			{0, 1, 2, 3}
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
		unsigned long ch = 0;
 | 
			
		||||
		unsigned char bytes[4];
 | 
			
		||||
		int* pIndexes = (m_charSet == utf32be) ? indexes[1] : indexes[0];
 | 
			
		||||
 | 
			
		||||
		bytes[0] = GetNextByte();
 | 
			
		||||
		bytes[1] = GetNextByte();
 | 
			
		||||
		bytes[2] = GetNextByte();
 | 
			
		||||
		bytes[3] = GetNextByte();
 | 
			
		||||
		if (!m_input.good())
 | 
			
		||||
		{
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		for (int i = 0; i < 4; ++i)
 | 
			
		||||
		{
 | 
			
		||||
			ch <<= 8;
 | 
			
		||||
			ch |= bytes[pIndexes[i]];
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		QueueUnicodeCodepoint(m_readahead, ch);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										80
									
								
								libs/yaml-cpp/src/stream.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								libs/yaml-cpp/src/stream.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,80 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#ifndef STREAM_H_62B23520_7C8E_11DE_8A39_0800200C9A66
 | 
			
		||||
#define STREAM_H_62B23520_7C8E_11DE_8A39_0800200C9A66
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include "noncopyable.h"
 | 
			
		||||
#include "mark.h"
 | 
			
		||||
#include <deque>
 | 
			
		||||
#include <ios>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <set>
 | 
			
		||||
 | 
			
		||||
namespace YAML
 | 
			
		||||
{
 | 
			
		||||
	static const size_t MAX_PARSER_PUSHBACK = 8;
 | 
			
		||||
 | 
			
		||||
	class Stream: private noncopyable
 | 
			
		||||
	{
 | 
			
		||||
	public:
 | 
			
		||||
		friend class StreamCharSource;
 | 
			
		||||
		
 | 
			
		||||
		Stream(std::istream& input);
 | 
			
		||||
		~Stream();
 | 
			
		||||
 | 
			
		||||
		operator bool() const;
 | 
			
		||||
		bool operator !() const { return !static_cast <bool>(*this); }
 | 
			
		||||
 | 
			
		||||
		char peek() const;
 | 
			
		||||
		char get();
 | 
			
		||||
		std::string get(int n);
 | 
			
		||||
		void eat(int n = 1);
 | 
			
		||||
 | 
			
		||||
		static char eof() { return 0x04; }
 | 
			
		||||
		
 | 
			
		||||
		const Mark mark() const { return m_mark; }
 | 
			
		||||
		int pos() const { return m_mark.pos; }
 | 
			
		||||
		int line() const { return m_mark.line; }
 | 
			
		||||
		int column() const { return m_mark.column; }
 | 
			
		||||
		void ResetColumn() { m_mark.column = 0; }
 | 
			
		||||
 | 
			
		||||
	private:
 | 
			
		||||
		enum CharacterSet {utf8, utf16le, utf16be, utf32le, utf32be};
 | 
			
		||||
 | 
			
		||||
		std::istream& m_input;
 | 
			
		||||
		Mark m_mark;
 | 
			
		||||
		
 | 
			
		||||
		CharacterSet m_charSet;
 | 
			
		||||
		unsigned char m_bufPushback[MAX_PARSER_PUSHBACK];
 | 
			
		||||
		mutable size_t m_nPushedBack;
 | 
			
		||||
		mutable std::deque<char> m_readahead;
 | 
			
		||||
		unsigned char* const m_pPrefetched;
 | 
			
		||||
		mutable size_t m_nPrefetchedAvailable;
 | 
			
		||||
		mutable size_t m_nPrefetchedUsed;
 | 
			
		||||
		
 | 
			
		||||
		void AdvanceCurrent();
 | 
			
		||||
		char CharAt(size_t i) const;
 | 
			
		||||
		bool ReadAheadTo(size_t i) const;
 | 
			
		||||
		bool _ReadAheadTo(size_t i) const;
 | 
			
		||||
		void StreamInUtf8() const;
 | 
			
		||||
		void StreamInUtf16() const;
 | 
			
		||||
		void StreamInUtf32() const;
 | 
			
		||||
		unsigned char GetNextByte() const;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	// CharAt
 | 
			
		||||
	// . Unchecked access
 | 
			
		||||
	inline char Stream::CharAt(size_t i) const {
 | 
			
		||||
		return m_readahead[i];
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	inline bool Stream::ReadAheadTo(size_t i) const {
 | 
			
		||||
		if(m_readahead.size() > i)
 | 
			
		||||
			return true;
 | 
			
		||||
		return _ReadAheadTo(i);
 | 
			
		||||
	}	
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // STREAM_H_62B23520_7C8E_11DE_8A39_0800200C9A66
 | 
			
		||||
							
								
								
									
										46
									
								
								libs/yaml-cpp/src/streamcharsource.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								libs/yaml-cpp/src/streamcharsource.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,46 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#ifndef STREAMCHARSOURCE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
 | 
			
		||||
#define STREAMCHARSOURCE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include "noncopyable.h"
 | 
			
		||||
#include <cstddef>
 | 
			
		||||
 | 
			
		||||
namespace YAML
 | 
			
		||||
{
 | 
			
		||||
	class StreamCharSource
 | 
			
		||||
	{
 | 
			
		||||
	public:
 | 
			
		||||
		StreamCharSource(const Stream& stream): m_offset(0), m_stream(stream) {}
 | 
			
		||||
		StreamCharSource(const StreamCharSource& source): m_offset(source.m_offset), m_stream(source.m_stream) {}
 | 
			
		||||
		~StreamCharSource() {}
 | 
			
		||||
 | 
			
		||||
		operator bool() const;
 | 
			
		||||
		char operator [] (std::size_t i) const { return m_stream.CharAt(m_offset + i); }
 | 
			
		||||
		bool operator !() const { return !static_cast<bool>(*this); }
 | 
			
		||||
 | 
			
		||||
		const StreamCharSource operator + (int i) const;
 | 
			
		||||
			
 | 
			
		||||
	private:
 | 
			
		||||
		std::size_t m_offset;
 | 
			
		||||
		const Stream& m_stream;
 | 
			
		||||
 | 
			
		||||
		StreamCharSource& operator = (const StreamCharSource&); // non-assignable
 | 
			
		||||
	};
 | 
			
		||||
	
 | 
			
		||||
	inline StreamCharSource::operator bool() const {
 | 
			
		||||
		return m_stream.ReadAheadTo(m_offset);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	inline const StreamCharSource StreamCharSource::operator + (int i) const {
 | 
			
		||||
		StreamCharSource source(*this);
 | 
			
		||||
		if(static_cast<int> (source.m_offset) + i >= 0)
 | 
			
		||||
			source.m_offset += i;
 | 
			
		||||
		else
 | 
			
		||||
			source.m_offset = 0;
 | 
			
		||||
		return source;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // STREAMCHARSOURCE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
 | 
			
		||||
							
								
								
									
										45
									
								
								libs/yaml-cpp/src/stringsource.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								libs/yaml-cpp/src/stringsource.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,45 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#ifndef STRINGSOURCE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
 | 
			
		||||
#define STRINGSOURCE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include <cstddef>
 | 
			
		||||
 | 
			
		||||
namespace YAML
 | 
			
		||||
{
 | 
			
		||||
	class StringCharSource
 | 
			
		||||
	{
 | 
			
		||||
	public:
 | 
			
		||||
		StringCharSource(const char *str, std::size_t size): m_str(str), m_size(size), m_offset(0) {}
 | 
			
		||||
 | 
			
		||||
		operator bool() const { return m_offset < m_size; }
 | 
			
		||||
		char operator [] (std::size_t i) const { return m_str[m_offset + i]; }
 | 
			
		||||
		bool operator !() const { return !static_cast<bool>(*this); }
 | 
			
		||||
 | 
			
		||||
		const StringCharSource operator + (int i) const {
 | 
			
		||||
			StringCharSource source(*this);
 | 
			
		||||
			if(static_cast<int> (source.m_offset) + i >= 0)
 | 
			
		||||
				source.m_offset += i;
 | 
			
		||||
			else
 | 
			
		||||
				source.m_offset = 0;
 | 
			
		||||
			return source;
 | 
			
		||||
		}
 | 
			
		||||
			
 | 
			
		||||
		StringCharSource& operator ++ () {
 | 
			
		||||
			++m_offset;
 | 
			
		||||
			return *this;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		StringCharSource& operator += (std::size_t offset) {
 | 
			
		||||
			m_offset += offset;
 | 
			
		||||
			return *this;
 | 
			
		||||
		}
 | 
			
		||||
	private:
 | 
			
		||||
		const char *m_str;
 | 
			
		||||
		std::size_t m_size;
 | 
			
		||||
		std::size_t m_offset;
 | 
			
		||||
	};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // STRINGSOURCE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
 | 
			
		||||
							
								
								
									
										50
									
								
								libs/yaml-cpp/src/tag.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								libs/yaml-cpp/src/tag.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,50 @@
 | 
			
		||||
#include "tag.h"
 | 
			
		||||
#include "token.h"
 | 
			
		||||
#include "parserstate.h"
 | 
			
		||||
#include <cassert>
 | 
			
		||||
 | 
			
		||||
namespace YAML
 | 
			
		||||
{
 | 
			
		||||
	Tag::Tag(const Token& token): type(static_cast<TYPE>(token.data))
 | 
			
		||||
	{
 | 
			
		||||
		switch(type) {
 | 
			
		||||
			case VERBATIM:
 | 
			
		||||
				value = token.value;
 | 
			
		||||
				break;
 | 
			
		||||
			case PRIMARY_HANDLE:
 | 
			
		||||
				value = token.value;
 | 
			
		||||
				break;
 | 
			
		||||
			case SECONDARY_HANDLE:
 | 
			
		||||
				value = token.value;
 | 
			
		||||
				break;
 | 
			
		||||
			case NAMED_HANDLE:
 | 
			
		||||
				handle = token.value;
 | 
			
		||||
				value = token.params[0];
 | 
			
		||||
				break;
 | 
			
		||||
			case NON_SPECIFIC:
 | 
			
		||||
				break;
 | 
			
		||||
			default:
 | 
			
		||||
				assert(false);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	const std::string Tag::Translate(const ParserState& state)
 | 
			
		||||
	{
 | 
			
		||||
		switch(type) {
 | 
			
		||||
			case VERBATIM:
 | 
			
		||||
				return value;
 | 
			
		||||
			case PRIMARY_HANDLE:
 | 
			
		||||
				return state.TranslateTagHandle("!") + value;
 | 
			
		||||
			case SECONDARY_HANDLE:
 | 
			
		||||
				return state.TranslateTagHandle("!!") + value;
 | 
			
		||||
			case NAMED_HANDLE:
 | 
			
		||||
				return state.TranslateTagHandle("!" + handle + "!") + value;
 | 
			
		||||
			case NON_SPECIFIC:
 | 
			
		||||
				// TODO:
 | 
			
		||||
				return "!";
 | 
			
		||||
			default:
 | 
			
		||||
				assert(false);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										26
									
								
								libs/yaml-cpp/src/tag.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								libs/yaml-cpp/src/tag.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,26 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#ifndef TAG_H_62B23520_7C8E_11DE_8A39_0800200C9A66
 | 
			
		||||
#define TAG_H_62B23520_7C8E_11DE_8A39_0800200C9A66
 | 
			
		||||
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
namespace YAML
 | 
			
		||||
{
 | 
			
		||||
	struct Token;
 | 
			
		||||
	struct ParserState;
 | 
			
		||||
 | 
			
		||||
	struct Tag {
 | 
			
		||||
		enum TYPE {
 | 
			
		||||
			VERBATIM, PRIMARY_HANDLE, SECONDARY_HANDLE, NAMED_HANDLE, NON_SPECIFIC
 | 
			
		||||
		};
 | 
			
		||||
		
 | 
			
		||||
		Tag(const Token& token);
 | 
			
		||||
		const std::string Translate(const ParserState& state);
 | 
			
		||||
		
 | 
			
		||||
		TYPE type;
 | 
			
		||||
		std::string handle, value;
 | 
			
		||||
	};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // TAG_H_62B23520_7C8E_11DE_8A39_0800200C9A66
 | 
			
		||||
							
								
								
									
										82
									
								
								libs/yaml-cpp/src/token.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								libs/yaml-cpp/src/token.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,82 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#ifndef TOKEN_H_62B23520_7C8E_11DE_8A39_0800200C9A66
 | 
			
		||||
#define TOKEN_H_62B23520_7C8E_11DE_8A39_0800200C9A66
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include "mark.h"
 | 
			
		||||
#include <ios>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
namespace YAML
 | 
			
		||||
{
 | 
			
		||||
	const std::string TokenNames[] = {
 | 
			
		||||
		"DIRECTIVE",
 | 
			
		||||
		"DOC_START",
 | 
			
		||||
		"DOC_END",
 | 
			
		||||
		"BLOCK_SEQ_START",
 | 
			
		||||
		"BLOCK_MAP_START",
 | 
			
		||||
		"BLOCK_SEQ_END",
 | 
			
		||||
		"BLOCK_MAP_END",
 | 
			
		||||
		"BLOCK_ENTRY",
 | 
			
		||||
		"FLOW_SEQ_START",
 | 
			
		||||
		"FLOW_MAP_START",
 | 
			
		||||
		"FLOW_SEQ_END",
 | 
			
		||||
		"FLOW_MAP_END",
 | 
			
		||||
		"FLOW_MAP_COMPACT",
 | 
			
		||||
		"FLOW_ENTRY",
 | 
			
		||||
		"KEY",
 | 
			
		||||
		"VALUE",
 | 
			
		||||
		"ANCHOR",
 | 
			
		||||
		"ALIAS",
 | 
			
		||||
		"TAG",
 | 
			
		||||
		"SCALAR"
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	struct Token {
 | 
			
		||||
		// enums
 | 
			
		||||
		enum STATUS { VALID, INVALID, UNVERIFIED };
 | 
			
		||||
		enum TYPE {
 | 
			
		||||
			DIRECTIVE,
 | 
			
		||||
			DOC_START,
 | 
			
		||||
			DOC_END,
 | 
			
		||||
			BLOCK_SEQ_START,
 | 
			
		||||
			BLOCK_MAP_START,
 | 
			
		||||
			BLOCK_SEQ_END,
 | 
			
		||||
			BLOCK_MAP_END,
 | 
			
		||||
			BLOCK_ENTRY,
 | 
			
		||||
			FLOW_SEQ_START,
 | 
			
		||||
			FLOW_MAP_START,
 | 
			
		||||
			FLOW_SEQ_END,
 | 
			
		||||
			FLOW_MAP_END,
 | 
			
		||||
			FLOW_MAP_COMPACT,
 | 
			
		||||
			FLOW_ENTRY,
 | 
			
		||||
			KEY,
 | 
			
		||||
			VALUE,
 | 
			
		||||
			ANCHOR,
 | 
			
		||||
			ALIAS,
 | 
			
		||||
			TAG,
 | 
			
		||||
			SCALAR
 | 
			
		||||
		};
 | 
			
		||||
				
 | 
			
		||||
		// data
 | 
			
		||||
		Token(TYPE type_, const Mark& mark_): status(VALID), type(type_), mark(mark_), data(0) {}
 | 
			
		||||
 | 
			
		||||
		friend std::ostream& operator << (std::ostream& out, const Token& token) {
 | 
			
		||||
			out << TokenNames[token.type] << std::string(": ") << token.value;
 | 
			
		||||
			for(std::size_t i=0;i<token.params.size();i++)
 | 
			
		||||
				out << std::string(" ") << token.params[i];
 | 
			
		||||
			return out;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		STATUS status;
 | 
			
		||||
		TYPE type;
 | 
			
		||||
		Mark mark;
 | 
			
		||||
		std::string value;
 | 
			
		||||
		std::vector <std::string> params;
 | 
			
		||||
		int data;
 | 
			
		||||
	};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // TOKEN_H_62B23520_7C8E_11DE_8A39_0800200C9A66
 | 
			
		||||
		Reference in New Issue
	
	Block a user