Merge clang-format from core

This commit is contained in:
Jesse Beder
2014-03-22 13:03:18 -05:00
72 changed files with 20508 additions and 20365 deletions

View File

@@ -1,16 +1,17 @@
#ifndef ANCHOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef ANCHOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define ANCHOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define ANCHOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
#include <cstddef> #include <cstddef>
namespace YAML namespace YAML {
{ typedef std::size_t anchor_t;
typedef std::size_t anchor_t; const anchor_t NullAnchor = 0;
const anchor_t NullAnchor = 0;
} }
#endif // ANCHOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #endif // ANCHOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,62 +1,64 @@
#ifndef BASE64_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef BASE64_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define BASE64_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define BASE64_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
#include <string> #include <string>
#include <vector> #include <vector>
namespace YAML namespace YAML {
{ std::string EncodeBase64(const unsigned char *data, std::size_t size);
std::string EncodeBase64(const unsigned char *data, std::size_t size); std::vector<unsigned char> DecodeBase64(const std::string &input);
std::vector<unsigned char> DecodeBase64(const std::string& input);
class Binary { class Binary {
public: public:
Binary(): m_unownedData(0), m_unownedSize(0) {} Binary() : m_unownedData(0), m_unownedSize(0) {}
Binary(const unsigned char *data_, std::size_t size_): m_unownedData(data_), m_unownedSize(size_) {} Binary(const unsigned char *data_, std::size_t size_)
: m_unownedData(data_), m_unownedSize(size_) {}
bool owned() const { return !m_unownedData; } bool owned() const { return !m_unownedData; }
std::size_t size() const { return owned() ? m_data.size() : m_unownedSize; } std::size_t size() const { return owned() ? m_data.size() : m_unownedSize; }
const unsigned char *data() const { return owned() ? &m_data[0] : m_unownedData; } const unsigned char *data() const {
return owned() ? &m_data[0] : m_unownedData;
}
void swap(std::vector<unsigned char>& rhs) { void swap(std::vector<unsigned char> &rhs) {
if(m_unownedData) { if (m_unownedData) {
m_data.swap(rhs); m_data.swap(rhs);
rhs.clear(); rhs.clear();
rhs.resize(m_unownedSize); rhs.resize(m_unownedSize);
std::copy(m_unownedData, m_unownedData + m_unownedSize, &rhs[0]); std::copy(m_unownedData, m_unownedData + m_unownedSize, &rhs[0]);
m_unownedData = 0; m_unownedData = 0;
m_unownedSize = 0; m_unownedSize = 0;
} else { } else {
m_data.swap(rhs); m_data.swap(rhs);
} }
} }
bool operator == (const Binary& rhs) const { bool operator==(const Binary &rhs) const {
const std::size_t s = size(); const std::size_t s = size();
if(s != rhs.size()) if (s != rhs.size())
return false; return false;
const unsigned char *d1 = data(); const unsigned char *d1 = data();
const unsigned char *d2 = rhs.data(); const unsigned char *d2 = rhs.data();
for(std::size_t i=0;i<s;i++) { for (std::size_t i = 0; i < s; i++) {
if(*d1++ != *d2++) if (*d1++ != *d2++)
return false; return false;
} }
return true; return true;
} }
bool operator != (const Binary& rhs) const { bool operator!=(const Binary &rhs) const { return !(*this == rhs); }
return !(*this == rhs);
}
private: private:
std::vector<unsigned char> m_data; std::vector<unsigned char> m_data;
const unsigned char *m_unownedData; const unsigned char *m_unownedData;
std::size_t m_unownedSize; std::size_t m_unownedSize;
}; };
} }
#endif // BASE64_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #endif // BASE64_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,7 +1,9 @@
#ifndef ANCHORDICT_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef ANCHORDICT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define ANCHORDICT_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define ANCHORDICT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
@@ -9,34 +11,27 @@
#include "../anchor.h" #include "../anchor.h"
namespace YAML namespace YAML {
{ /// AnchorDict
/// AnchorDict /// . An object that stores and retrieves values correlating to anchor_t
/// . An object that stores and retrieves values correlating to anchor_t /// values.
/// values. /// . Efficient implementation that can make assumptions about how anchor_t
/// . Efficient implementation that can make assumptions about how anchor_t /// values are assigned by the Parser class.
/// values are assigned by the Parser class. template <class T>
template <class T> class AnchorDict {
class AnchorDict public:
{ void Register(anchor_t anchor, T value) {
public: if (anchor > m_data.size()) {
void Register(anchor_t anchor, T value) m_data.resize(anchor);
{
if (anchor > m_data.size())
{
m_data.resize(anchor);
}
m_data[anchor - 1] = value;
} }
m_data[anchor - 1] = value;
}
T Get(anchor_t anchor) const T Get(anchor_t anchor) const { return m_data[anchor - 1]; }
{
return m_data[anchor - 1];
}
private: private:
std::vector<T> m_data; std::vector<T> m_data;
}; };
} }
#endif // ANCHORDICT_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #endif // ANCHORDICT_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,133 +1,147 @@
#ifndef GRAPHBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef GRAPHBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define GRAPHBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define GRAPHBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
#include "yaml-cpp/mark.h" #include "yaml-cpp/mark.h"
#include <string> #include <string>
namespace YAML namespace YAML {
{ class Parser;
class Parser;
// GraphBuilderInterface // GraphBuilderInterface
// . Abstraction of node creation // . Abstraction of node creation
// . pParentNode is always NULL or the return value of one of the NewXXX() // . pParentNode is always NULL or the return value of one of the NewXXX()
// functions. // functions.
class GraphBuilderInterface class GraphBuilderInterface {
{ public:
public: // Create and return a new node with a null value.
// Create and return a new node with a null value. virtual void *NewNull(const Mark &mark, void *pParentNode) = 0;
virtual void *NewNull(const Mark& mark, void *pParentNode) = 0;
// Create and return a new node with the given tag and value. // Create and return a new node with the given tag and value.
virtual void *NewScalar(const Mark& mark, const std::string& tag, void *pParentNode, const std::string& value) = 0; virtual void *NewScalar(const Mark &mark, const std::string &tag,
void *pParentNode, const std::string &value) = 0;
// Create and return a new sequence node // Create and return a new sequence node
virtual void *NewSequence(const Mark& mark, const std::string& tag, void *pParentNode) = 0; virtual void *NewSequence(const Mark &mark, const std::string &tag,
// Add pNode to pSequence. pNode was created with one of the NewXxx() void *pParentNode) = 0;
// functions and pSequence with NewSequence().
virtual void AppendToSequence(void *pSequence, void *pNode) = 0;
// Note that no moew entries will be added to pSequence
virtual void SequenceComplete(void *pSequence) {(void)pSequence;}
// Create and return a new map node // Add pNode to pSequence. pNode was created with one of the NewXxx()
virtual void *NewMap(const Mark& mark, const std::string& tag, void *pParentNode) = 0; // functions and pSequence with NewSequence().
// Add the pKeyNode => pValueNode mapping to pMap. pKeyNode and pValueNode virtual void AppendToSequence(void *pSequence, void *pNode) = 0;
// were created with one of the NewXxx() methods and pMap with NewMap().
virtual void AssignInMap(void *pMap, void *pKeyNode, void *pValueNode) = 0;
// Note that no more assignments will be made in pMap
virtual void MapComplete(void *pMap) {(void)pMap;}
// Return the node that should be used in place of an alias referencing // Note that no moew entries will be added to pSequence
// pNode (pNode by default) virtual void SequenceComplete(void *pSequence) { (void)pSequence; }
virtual void *AnchorReference(const Mark& mark, void *pNode) {(void)mark; return pNode;}
};
// Typesafe wrapper for GraphBuilderInterface. Assumes that Impl defines // Create and return a new map node
// Node, Sequence, and Map types. Sequence and Map must derive from Node virtual void *NewMap(const Mark &mark, const std::string &tag,
// (unless Node is defined as void). Impl must also implement function with void *pParentNode) = 0;
// all of the same names as the virtual functions in GraphBuilderInterface
// -- including the ones with default implementations -- but with the
// prototypes changed to accept an explicit Node*, Sequence*, or Map* where
// appropriate.
template <class Impl>
class GraphBuilder : public GraphBuilderInterface
{
public:
typedef typename Impl::Node Node;
typedef typename Impl::Sequence Sequence;
typedef typename Impl::Map Map;
GraphBuilder(Impl& impl) : m_impl(impl) // Add the pKeyNode => pValueNode mapping to pMap. pKeyNode and pValueNode
{ // were created with one of the NewXxx() methods and pMap with NewMap().
Map* pMap = NULL; virtual void AssignInMap(void *pMap, void *pKeyNode, void *pValueNode) = 0;
Sequence* pSeq = NULL;
Node* pNode = NULL;
// Type consistency checks // Note that no more assignments will be made in pMap
pNode = pMap; virtual void MapComplete(void *pMap) { (void)pMap; }
pNode = pSeq;
}
GraphBuilderInterface& AsBuilderInterface() {return *this;} // Return the node that should be used in place of an alias referencing
// pNode (pNode by default)
virtual void *NewNull(const Mark& mark, void* pParentNode) { virtual void *AnchorReference(const Mark &mark, void *pNode) {
return CheckType<Node>(m_impl.NewNull(mark, AsNode(pParentNode))); (void)mark;
} return pNode;
virtual void *NewScalar(const Mark& mark, const std::string& tag, void *pParentNode, const std::string& value) {
return CheckType<Node>(m_impl.NewScalar(mark, tag, AsNode(pParentNode), value));
}
virtual void *NewSequence(const Mark& mark, const std::string& tag, void *pParentNode) {
return CheckType<Sequence>(m_impl.NewSequence(mark, tag, AsNode(pParentNode)));
}
virtual void AppendToSequence(void *pSequence, void *pNode) {
m_impl.AppendToSequence(AsSequence(pSequence), AsNode(pNode));
}
virtual void SequenceComplete(void *pSequence) {
m_impl.SequenceComplete(AsSequence(pSequence));
}
virtual void *NewMap(const Mark& mark, const std::string& tag, void *pParentNode) {
return CheckType<Map>(m_impl.NewMap(mark, tag, AsNode(pParentNode)));
}
virtual void AssignInMap(void *pMap, void *pKeyNode, void *pValueNode) {
m_impl.AssignInMap(AsMap(pMap), AsNode(pKeyNode), AsNode(pValueNode));
}
virtual void MapComplete(void *pMap) {
m_impl.MapComplete(AsMap(pMap));
}
virtual void *AnchorReference(const Mark& mark, void *pNode) {
return CheckType<Node>(m_impl.AnchorReference(mark, AsNode(pNode)));
}
private:
Impl& m_impl;
// Static check for pointer to T
template <class T, class U>
static T* CheckType(U* p) {return p;}
static Node *AsNode(void *pNode) {return static_cast<Node*>(pNode);}
static Sequence *AsSequence(void *pSeq) {return static_cast<Sequence*>(pSeq);}
static Map *AsMap(void *pMap) {return static_cast<Map*>(pMap);}
};
void *BuildGraphOfNextDocument(Parser& parser, GraphBuilderInterface& graphBuilder);
template <class Impl>
typename Impl::Node *BuildGraphOfNextDocument(Parser& parser, Impl& impl)
{
GraphBuilder<Impl> graphBuilder(impl);
return static_cast<typename Impl::Node *>(BuildGraphOfNextDocument(
parser, graphBuilder
));
} }
};
// Typesafe wrapper for GraphBuilderInterface. Assumes that Impl defines
// Node, Sequence, and Map types. Sequence and Map must derive from Node
// (unless Node is defined as void). Impl must also implement function with
// all of the same names as the virtual functions in GraphBuilderInterface
// -- including the ones with default implementations -- but with the
// prototypes changed to accept an explicit Node*, Sequence*, or Map* where
// appropriate.
template <class Impl>
class GraphBuilder : public GraphBuilderInterface {
public:
typedef typename Impl::Node Node;
typedef typename Impl::Sequence Sequence;
typedef typename Impl::Map Map;
GraphBuilder(Impl &impl) : m_impl(impl) {
Map *pMap = NULL;
Sequence *pSeq = NULL;
Node *pNode = NULL;
// Type consistency checks
pNode = pMap;
pNode = pSeq;
}
GraphBuilderInterface &AsBuilderInterface() { return *this; }
virtual void *NewNull(const Mark &mark, void *pParentNode) {
return CheckType<Node>(m_impl.NewNull(mark, AsNode(pParentNode)));
}
virtual void *NewScalar(const Mark &mark, const std::string &tag,
void *pParentNode, const std::string &value) {
return CheckType<Node>(
m_impl.NewScalar(mark, tag, AsNode(pParentNode), value));
}
virtual void *NewSequence(const Mark &mark, const std::string &tag,
void *pParentNode) {
return CheckType<Sequence>(
m_impl.NewSequence(mark, tag, AsNode(pParentNode)));
}
virtual void AppendToSequence(void *pSequence, void *pNode) {
m_impl.AppendToSequence(AsSequence(pSequence), AsNode(pNode));
}
virtual void SequenceComplete(void *pSequence) {
m_impl.SequenceComplete(AsSequence(pSequence));
}
virtual void *NewMap(const Mark &mark, const std::string &tag,
void *pParentNode) {
return CheckType<Map>(m_impl.NewMap(mark, tag, AsNode(pParentNode)));
}
virtual void AssignInMap(void *pMap, void *pKeyNode, void *pValueNode) {
m_impl.AssignInMap(AsMap(pMap), AsNode(pKeyNode), AsNode(pValueNode));
}
virtual void MapComplete(void *pMap) { m_impl.MapComplete(AsMap(pMap)); }
virtual void *AnchorReference(const Mark &mark, void *pNode) {
return CheckType<Node>(m_impl.AnchorReference(mark, AsNode(pNode)));
}
private:
Impl &m_impl;
// Static check for pointer to T
template <class T, class U>
static T *CheckType(U *p) {
return p;
}
static Node *AsNode(void *pNode) { return static_cast<Node *>(pNode); }
static Sequence *AsSequence(void *pSeq) {
return static_cast<Sequence *>(pSeq);
}
static Map *AsMap(void *pMap) { return static_cast<Map *>(pMap); }
};
void *BuildGraphOfNextDocument(Parser &parser,
GraphBuilderInterface &graphBuilder);
template <class Impl>
typename Impl::Node *BuildGraphOfNextDocument(Parser &parser, Impl &impl) {
GraphBuilder<Impl> graphBuilder(impl);
return static_cast<typename Impl::Node *>(
BuildGraphOfNextDocument(parser, graphBuilder));
}
} }
#endif // GRAPHBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #endif // GRAPHBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,28 +1,37 @@
#ifndef DLL_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef DLL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define DLL_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define DLL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
// The following ifdef block is the standard way of creating macros which make exporting // The following ifdef block is the standard way of creating macros which make
// from a DLL simpler. All files within this DLL are compiled with the yaml_cpp_EXPORTS // exporting
// symbol defined on the command line. this symbol should not be defined on any project // from a DLL simpler. All files within this DLL are compiled with the
// that uses this DLL. This way any other project whose source files include this file see // yaml_cpp_EXPORTS
// YAML_CPP_API functions as being imported from a DLL, whereas this DLL sees symbols // symbol defined on the command line. this symbol should not be defined on any
// project
// that uses this DLL. This way any other project whose source files include
// this file see
// YAML_CPP_API functions as being imported from a DLL, whereas this DLL sees
// symbols
// defined with this macro as being exported. // defined with this macro as being exported.
#undef YAML_CPP_API #undef YAML_CPP_API
#ifdef YAML_CPP_DLL // Using or Building YAML-CPP DLL (definition defined manually) #ifdef YAML_CPP_DLL // Using or Building YAML-CPP DLL (definition defined
#ifdef yaml_cpp_EXPORTS // Building YAML-CPP DLL (definition created by CMake or defined manually) // manually)
// #pragma message( "Defining YAML_CPP_API for DLL export" ) #ifdef yaml_cpp_EXPORTS // Building YAML-CPP DLL (definition created by CMake
#define YAML_CPP_API __declspec(dllexport) // or defined manually)
#else // yaml_cpp_EXPORTS // #pragma message( "Defining YAML_CPP_API for DLL export" )
// #pragma message( "Defining YAML_CPP_API for DLL import" ) #define YAML_CPP_API __declspec(dllexport)
#define YAML_CPP_API __declspec(dllimport) #else // yaml_cpp_EXPORTS
#endif // yaml_cpp_EXPORTS // #pragma message( "Defining YAML_CPP_API for DLL import" )
#else //YAML_CPP_DLL #define YAML_CPP_API __declspec(dllimport)
#endif // yaml_cpp_EXPORTS
#else // YAML_CPP_DLL
#define YAML_CPP_API #define YAML_CPP_API
#endif // YAML_CPP_DLL #endif // YAML_CPP_DLL
#endif // DLL_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #endif // DLL_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,45 +1,54 @@
#ifndef EMITFROMEVENTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef EMITFROMEVENTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define EMITFROMEVENTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define EMITFROMEVENTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
#include "yaml-cpp/eventhandler.h" #include "yaml-cpp/eventhandler.h"
#include <stack> #include <stack>
namespace YAML namespace YAML {
{ class Emitter;
class Emitter;
class EmitFromEvents: public EventHandler class EmitFromEvents : public EventHandler {
{ public:
public: EmitFromEvents(Emitter& emitter);
EmitFromEvents(Emitter& emitter);
virtual void OnDocumentStart(const Mark& mark); virtual void OnDocumentStart(const Mark& mark);
virtual void OnDocumentEnd(); virtual void OnDocumentEnd();
virtual void OnNull(const Mark& mark, anchor_t anchor); virtual void OnNull(const Mark& mark, anchor_t anchor);
virtual void OnAlias(const Mark& mark, anchor_t anchor); virtual void OnAlias(const Mark& mark, anchor_t anchor);
virtual void OnScalar(const Mark& mark, const std::string& tag, anchor_t anchor, const std::string& value); virtual void OnScalar(const Mark& mark, const std::string& tag,
anchor_t anchor, const std::string& value);
virtual void OnSequenceStart(const Mark& mark, const std::string& tag, anchor_t anchor); virtual void OnSequenceStart(const Mark& mark, const std::string& tag,
virtual void OnSequenceEnd(); anchor_t anchor);
virtual void OnSequenceEnd();
virtual void OnMapStart(const Mark& mark, const std::string& tag, anchor_t anchor); virtual void OnMapStart(const Mark& mark, const std::string& tag,
virtual void OnMapEnd(); anchor_t anchor);
virtual void OnMapEnd();
private: private:
void BeginNode(); void BeginNode();
void EmitProps(const std::string& tag, anchor_t anchor); void EmitProps(const std::string& tag, anchor_t anchor);
private: private:
Emitter& m_emitter; Emitter& m_emitter;
struct State { enum value { WaitingForSequenceEntry, WaitingForKey, WaitingForValue }; }; struct State {
std::stack<State::value> m_stateStack; enum value {
}; WaitingForSequenceEntry,
WaitingForKey,
WaitingForValue
};
};
std::stack<State::value> m_stateStack;
};
} }
#endif // EMITFROMEVENTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #endif // EMITFROMEVENTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,11 +1,12 @@
#ifndef EMITTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef EMITTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define EMITTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define EMITTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
#include "yaml-cpp/dll.h" #include "yaml-cpp/dll.h"
#include "yaml-cpp/binary.h" #include "yaml-cpp/binary.h"
#include "yaml-cpp/emitterdef.h" #include "yaml-cpp/emitterdef.h"
@@ -17,193 +18,230 @@
#include <string> #include <string>
#include <sstream> #include <sstream>
namespace YAML namespace YAML {
{ class EmitterState;
class EmitterState;
class YAML_CPP_API Emitter: private noncopyable class YAML_CPP_API Emitter : private noncopyable {
{ public:
public: Emitter();
Emitter(); explicit Emitter(std::ostream& stream);
explicit Emitter(std::ostream& stream); ~Emitter();
~Emitter();
// output // output
const char *c_str() const; const char* c_str() const;
std::size_t size() const; std::size_t size() const;
// state checking // state checking
bool good() const; bool good() const;
const std::string GetLastError() const; const std::string GetLastError() const;
// global setters // global setters
bool SetOutputCharset(EMITTER_MANIP value); bool SetOutputCharset(EMITTER_MANIP value);
bool SetStringFormat(EMITTER_MANIP value); bool SetStringFormat(EMITTER_MANIP value);
bool SetBoolFormat(EMITTER_MANIP value); bool SetBoolFormat(EMITTER_MANIP value);
bool SetIntBase(EMITTER_MANIP value); bool SetIntBase(EMITTER_MANIP value);
bool SetSeqFormat(EMITTER_MANIP value); bool SetSeqFormat(EMITTER_MANIP value);
bool SetMapFormat(EMITTER_MANIP value); bool SetMapFormat(EMITTER_MANIP value);
bool SetIndent(unsigned n); bool SetIndent(unsigned n);
bool SetPreCommentIndent(unsigned n); bool SetPreCommentIndent(unsigned n);
bool SetPostCommentIndent(unsigned n); bool SetPostCommentIndent(unsigned n);
bool SetFloatPrecision(unsigned n); bool SetFloatPrecision(unsigned n);
bool SetDoublePrecision(unsigned n); bool SetDoublePrecision(unsigned n);
// local setters // local setters
Emitter& SetLocalValue(EMITTER_MANIP value); Emitter& SetLocalValue(EMITTER_MANIP value);
Emitter& SetLocalIndent(const _Indent& indent); Emitter& SetLocalIndent(const _Indent& indent);
Emitter& SetLocalPrecision(const _Precision& precision); Emitter& SetLocalPrecision(const _Precision& precision);
// overloads of write // overloads of write
Emitter& Write(const std::string& str); Emitter& Write(const std::string& str);
Emitter& Write(bool b); Emitter& Write(bool b);
Emitter& Write(char ch); Emitter& Write(char ch);
Emitter& Write(const _Alias& alias); Emitter& Write(const _Alias& alias);
Emitter& Write(const _Anchor& anchor); Emitter& Write(const _Anchor& anchor);
Emitter& Write(const _Tag& tag); Emitter& Write(const _Tag& tag);
Emitter& Write(const _Comment& comment); Emitter& Write(const _Comment& comment);
Emitter& Write(const _Null& n); Emitter& Write(const _Null& n);
Emitter& Write(const Binary& binary); Emitter& Write(const Binary& binary);
template <typename T> template <typename T>
Emitter& WriteIntegralType(T value); Emitter& WriteIntegralType(T value);
template <typename T> template <typename T>
Emitter& WriteStreamable(T value); Emitter& WriteStreamable(T value);
private: private:
template<typename T> void SetStreamablePrecision(std::stringstream&) {} template <typename T>
unsigned GetFloatPrecision() const; void SetStreamablePrecision(std::stringstream&) {}
unsigned GetDoublePrecision() const; unsigned GetFloatPrecision() const;
unsigned GetDoublePrecision() const;
void PrepareIntegralStream(std::stringstream& stream) const; void PrepareIntegralStream(std::stringstream& stream) const;
void StartedScalar(); void StartedScalar();
private: private:
void EmitBeginDoc(); void EmitBeginDoc();
void EmitEndDoc(); void EmitEndDoc();
void EmitBeginSeq(); void EmitBeginSeq();
void EmitEndSeq(); void EmitEndSeq();
void EmitBeginMap(); void EmitBeginMap();
void EmitEndMap(); void EmitEndMap();
void EmitNewline(); void EmitNewline();
void EmitKindTag(); void EmitKindTag();
void EmitTag(bool verbatim, const _Tag& tag); void EmitTag(bool verbatim, const _Tag& tag);
void PrepareNode(EmitterNodeType::value child); void PrepareNode(EmitterNodeType::value child);
void PrepareTopNode(EmitterNodeType::value child); void PrepareTopNode(EmitterNodeType::value child);
void FlowSeqPrepareNode(EmitterNodeType::value child); void FlowSeqPrepareNode(EmitterNodeType::value child);
void BlockSeqPrepareNode(EmitterNodeType::value child); void BlockSeqPrepareNode(EmitterNodeType::value child);
void FlowMapPrepareNode(EmitterNodeType::value child); void FlowMapPrepareNode(EmitterNodeType::value child);
void FlowMapPrepareLongKey(EmitterNodeType::value child); void FlowMapPrepareLongKey(EmitterNodeType::value child);
void FlowMapPrepareLongKeyValue(EmitterNodeType::value child); void FlowMapPrepareLongKeyValue(EmitterNodeType::value child);
void FlowMapPrepareSimpleKey(EmitterNodeType::value child); void FlowMapPrepareSimpleKey(EmitterNodeType::value child);
void FlowMapPrepareSimpleKeyValue(EmitterNodeType::value child); void FlowMapPrepareSimpleKeyValue(EmitterNodeType::value child);
void BlockMapPrepareNode(EmitterNodeType::value child); void BlockMapPrepareNode(EmitterNodeType::value child);
void BlockMapPrepareLongKey(EmitterNodeType::value child); void BlockMapPrepareLongKey(EmitterNodeType::value child);
void BlockMapPrepareLongKeyValue(EmitterNodeType::value child); void BlockMapPrepareLongKeyValue(EmitterNodeType::value child);
void BlockMapPrepareSimpleKey(EmitterNodeType::value child); void BlockMapPrepareSimpleKey(EmitterNodeType::value child);
void BlockMapPrepareSimpleKeyValue(EmitterNodeType::value child); void BlockMapPrepareSimpleKeyValue(EmitterNodeType::value child);
void SpaceOrIndentTo(bool requireSpace, unsigned indent); void SpaceOrIndentTo(bool requireSpace, unsigned indent);
const char *ComputeFullBoolName(bool b) const; const char* ComputeFullBoolName(bool b) const;
bool CanEmitNewline() const; bool CanEmitNewline() const;
private: private:
std::auto_ptr<EmitterState> m_pState; std::auto_ptr<EmitterState> m_pState;
ostream_wrapper m_stream; ostream_wrapper m_stream;
}; };
template <typename T> template <typename T>
inline Emitter& Emitter::WriteIntegralType(T value) inline Emitter& Emitter::WriteIntegralType(T value) {
{ if (!good())
if(!good()) return *this;
return *this;
PrepareNode(EmitterNodeType::Scalar); PrepareNode(EmitterNodeType::Scalar);
std::stringstream stream; std::stringstream stream;
PrepareIntegralStream(stream); PrepareIntegralStream(stream);
stream << value; stream << value;
m_stream << stream.str(); m_stream << stream.str();
StartedScalar(); StartedScalar();
return *this; return *this;
}
template <typename T>
inline Emitter& Emitter::WriteStreamable(T value)
{
if(!good())
return *this;
PrepareNode(EmitterNodeType::Scalar);
std::stringstream stream;
SetStreamablePrecision<T>(stream);
stream << value;
m_stream << stream.str();
StartedScalar();
return *this;
}
template<>
inline void Emitter::SetStreamablePrecision<float>(std::stringstream& stream)
{
stream.precision(GetFloatPrecision());
}
template<>
inline void Emitter::SetStreamablePrecision<double>(std::stringstream& stream)
{
stream.precision(GetDoublePrecision());
}
// overloads of insertion
inline Emitter& operator << (Emitter& emitter, const std::string& v) { return emitter.Write(v); }
inline Emitter& operator << (Emitter& emitter, bool v) { return emitter.Write(v); }
inline Emitter& operator << (Emitter& emitter, char v) { return emitter.Write(v); }
inline Emitter& operator << (Emitter& emitter, unsigned char v) { return emitter.Write(static_cast<char>(v)); }
inline Emitter& operator << (Emitter& emitter, const _Alias& v) { return emitter.Write(v); }
inline Emitter& operator << (Emitter& emitter, const _Anchor& v) { return emitter.Write(v); }
inline Emitter& operator << (Emitter& emitter, const _Tag& v) { return emitter.Write(v); }
inline Emitter& operator << (Emitter& emitter, const _Comment& v) { return emitter.Write(v); }
inline Emitter& operator << (Emitter& emitter, const _Null& v) { return emitter.Write(v); }
inline Emitter& operator << (Emitter& emitter, const Binary& b) { return emitter.Write(b); }
inline Emitter& operator << (Emitter& emitter, const char *v) { return emitter.Write(std::string(v)); }
inline Emitter& operator << (Emitter& emitter, int v) { return emitter.WriteIntegralType(v); }
inline Emitter& operator << (Emitter& emitter, unsigned int v) { return emitter.WriteIntegralType(v); }
inline Emitter& operator << (Emitter& emitter, short v) { return emitter.WriteIntegralType(v); }
inline Emitter& operator << (Emitter& emitter, unsigned short v) { return emitter.WriteIntegralType(v); }
inline Emitter& operator << (Emitter& emitter, long v) { return emitter.WriteIntegralType(v); }
inline Emitter& operator << (Emitter& emitter, unsigned long v) { return emitter.WriteIntegralType(v); }
inline Emitter& operator << (Emitter& emitter, long long v) { return emitter.WriteIntegralType(v); }
inline Emitter& operator << (Emitter& emitter, unsigned long long v) { return emitter.WriteIntegralType(v); }
inline Emitter& operator << (Emitter& emitter, float v) { return emitter.WriteStreamable(v); }
inline Emitter& operator << (Emitter& emitter, double v) { return emitter.WriteStreamable(v); }
inline Emitter& operator << (Emitter& emitter, EMITTER_MANIP value) {
return emitter.SetLocalValue(value);
}
inline Emitter& operator << (Emitter& emitter, _Indent indent) {
return emitter.SetLocalIndent(indent);
}
inline Emitter& operator << (Emitter& emitter, _Precision precision) {
return emitter.SetLocalPrecision(precision);
}
} }
#endif // EMITTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 template <typename T>
inline Emitter& Emitter::WriteStreamable(T value) {
if (!good())
return *this;
PrepareNode(EmitterNodeType::Scalar);
std::stringstream stream;
SetStreamablePrecision<T>(stream);
stream << value;
m_stream << stream.str();
StartedScalar();
return *this;
}
template <>
inline void Emitter::SetStreamablePrecision<float>(std::stringstream& stream) {
stream.precision(GetFloatPrecision());
}
template <>
inline void Emitter::SetStreamablePrecision<double>(std::stringstream& stream) {
stream.precision(GetDoublePrecision());
}
// overloads of insertion
inline Emitter& operator<<(Emitter& emitter, const std::string& v) {
return emitter.Write(v);
}
inline Emitter& operator<<(Emitter& emitter, bool v) {
return emitter.Write(v);
}
inline Emitter& operator<<(Emitter& emitter, char v) {
return emitter.Write(v);
}
inline Emitter& operator<<(Emitter& emitter, unsigned char v) {
return emitter.Write(static_cast<char>(v));
}
inline Emitter& operator<<(Emitter& emitter, const _Alias& v) {
return emitter.Write(v);
}
inline Emitter& operator<<(Emitter& emitter, const _Anchor& v) {
return emitter.Write(v);
}
inline Emitter& operator<<(Emitter& emitter, const _Tag& v) {
return emitter.Write(v);
}
inline Emitter& operator<<(Emitter& emitter, const _Comment& v) {
return emitter.Write(v);
}
inline Emitter& operator<<(Emitter& emitter, const _Null& v) {
return emitter.Write(v);
}
inline Emitter& operator<<(Emitter& emitter, const Binary& b) {
return emitter.Write(b);
}
inline Emitter& operator<<(Emitter& emitter, const char* v) {
return emitter.Write(std::string(v));
}
inline Emitter& operator<<(Emitter& emitter, int v) {
return emitter.WriteIntegralType(v);
}
inline Emitter& operator<<(Emitter& emitter, unsigned int v) {
return emitter.WriteIntegralType(v);
}
inline Emitter& operator<<(Emitter& emitter, short v) {
return emitter.WriteIntegralType(v);
}
inline Emitter& operator<<(Emitter& emitter, unsigned short v) {
return emitter.WriteIntegralType(v);
}
inline Emitter& operator<<(Emitter& emitter, long v) {
return emitter.WriteIntegralType(v);
}
inline Emitter& operator<<(Emitter& emitter, unsigned long v) {
return emitter.WriteIntegralType(v);
}
inline Emitter& operator<<(Emitter& emitter, long long v) {
return emitter.WriteIntegralType(v);
}
inline Emitter& operator<<(Emitter& emitter, unsigned long long v) {
return emitter.WriteIntegralType(v);
}
inline Emitter& operator<<(Emitter& emitter, float v) {
return emitter.WriteStreamable(v);
}
inline Emitter& operator<<(Emitter& emitter, double v) {
return emitter.WriteStreamable(v);
}
inline Emitter& operator<<(Emitter& emitter, EMITTER_MANIP value) {
return emitter.SetLocalValue(value);
}
inline Emitter& operator<<(Emitter& emitter, _Indent indent) {
return emitter.SetLocalIndent(indent);
}
inline Emitter& operator<<(Emitter& emitter, _Precision precision) {
return emitter.SetLocalPrecision(precision);
}
}
#endif // EMITTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,13 +1,24 @@
#ifndef EMITTERDEF_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef EMITTERDEF_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define EMITTERDEF_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define EMITTERDEF_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
namespace YAML namespace YAML {
{ struct EmitterNodeType {
struct EmitterNodeType { enum value { None, Property, Scalar, FlowSeq, BlockSeq, FlowMap, BlockMap }; }; enum value {
None,
Property,
Scalar,
FlowSeq,
BlockSeq,
FlowMap,
BlockMap
};
};
} }
#endif // EMITTERDEF_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #endif // EMITTERDEF_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,149 +1,141 @@
#ifndef EMITTERMANIP_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef EMITTERMANIP_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define EMITTERMANIP_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define EMITTERMANIP_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
#include <string> #include <string>
namespace YAML namespace YAML {
{ enum EMITTER_MANIP {
enum EMITTER_MANIP { // general manipulators
// general manipulators Auto,
Auto, TagByKind,
TagByKind, Newline,
Newline,
// output character set // output character set
EmitNonAscii, EmitNonAscii,
EscapeNonAscii, EscapeNonAscii,
// string manipulators // string manipulators
// Auto, // duplicate // Auto, // duplicate
SingleQuoted, SingleQuoted,
DoubleQuoted, DoubleQuoted,
Literal, Literal,
// bool manipulators // bool manipulators
YesNoBool, // yes, no YesNoBool, // yes, no
TrueFalseBool, // true, false TrueFalseBool, // true, false
OnOffBool, // on, off OnOffBool, // on, off
UpperCase, // TRUE, N UpperCase, // TRUE, N
LowerCase, // f, yes LowerCase, // f, yes
CamelCase, // No, Off CamelCase, // No, Off
LongBool, // yes, On LongBool, // yes, On
ShortBool, // y, t ShortBool, // y, t
// int manipulators // int manipulators
Dec, Dec,
Hex, Hex,
Oct, Oct,
// document manipulators // document manipulators
BeginDoc, BeginDoc,
EndDoc, EndDoc,
// sequence manipulators // sequence manipulators
BeginSeq, BeginSeq,
EndSeq, EndSeq,
Flow, Flow,
Block, Block,
// map manipulators // map manipulators
BeginMap, BeginMap,
EndMap, EndMap,
Key, Key,
Value, Value,
// Flow, // duplicate // Flow, // duplicate
// Block, // duplicate // Block, // duplicate
// Auto, // duplicate // Auto, // duplicate
LongKey LongKey
}; };
struct _Indent { struct _Indent {
_Indent(int value_): value(value_) {} _Indent(int value_) : value(value_) {}
int value; int value;
}; };
inline _Indent Indent(int value) { inline _Indent Indent(int value) { return _Indent(value); }
return _Indent(value);
}
struct _Alias { struct _Alias {
_Alias(const std::string& content_): content(content_) {} _Alias(const std::string& content_) : content(content_) {}
std::string content; std::string content;
}; };
inline _Alias Alias(const std::string content) { inline _Alias Alias(const std::string content) { return _Alias(content); }
return _Alias(content);
}
struct _Anchor { struct _Anchor {
_Anchor(const std::string& content_): content(content_) {} _Anchor(const std::string& content_) : content(content_) {}
std::string content; std::string content;
}; };
inline _Anchor Anchor(const std::string content) { inline _Anchor Anchor(const std::string content) { return _Anchor(content); }
return _Anchor(content);
}
struct _Tag { struct _Tag {
struct Type { enum value { Verbatim, PrimaryHandle, NamedHandle }; }; struct Type {
enum value {
explicit _Tag(const std::string& prefix_, const std::string& content_, Type::value type_) Verbatim,
: prefix(prefix_), content(content_), type(type_) PrimaryHandle,
{ NamedHandle
}
std::string prefix;
std::string content;
Type::value type;
};
inline _Tag VerbatimTag(const std::string content) {
return _Tag("", content, _Tag::Type::Verbatim);
}
inline _Tag LocalTag(const std::string content) {
return _Tag("", content, _Tag::Type::PrimaryHandle);
}
inline _Tag LocalTag(const std::string& prefix, const std::string content) {
return _Tag(prefix, content, _Tag::Type::NamedHandle);
}
inline _Tag SecondaryTag(const std::string content) {
return _Tag("", content, _Tag::Type::NamedHandle);
}
struct _Comment {
_Comment(const std::string& content_): content(content_) {}
std::string content;
};
inline _Comment Comment(const std::string content) {
return _Comment(content);
}
struct _Precision {
_Precision(int floatPrecision_, int doublePrecision_): floatPrecision(floatPrecision_), doublePrecision(doublePrecision_) {}
int floatPrecision;
int doublePrecision;
}; };
};
inline _Precision FloatPrecision(int n) { explicit _Tag(const std::string& prefix_, const std::string& content_,
return _Precision(n, -1); Type::value type_)
} : prefix(prefix_), content(content_), type(type_) {}
std::string prefix;
std::string content;
Type::value type;
};
inline _Precision DoublePrecision(int n) { inline _Tag VerbatimTag(const std::string content) {
return _Precision(-1, n); return _Tag("", content, _Tag::Type::Verbatim);
}
inline _Precision Precision(int n) {
return _Precision(n, n);
}
} }
#endif // EMITTERMANIP_H_62B23520_7C8E_11DE_8A39_0800200C9A66 inline _Tag LocalTag(const std::string content) {
return _Tag("", content, _Tag::Type::PrimaryHandle);
}
inline _Tag LocalTag(const std::string& prefix, const std::string content) {
return _Tag(prefix, content, _Tag::Type::NamedHandle);
}
inline _Tag SecondaryTag(const std::string content) {
return _Tag("", content, _Tag::Type::NamedHandle);
}
struct _Comment {
_Comment(const std::string& content_) : content(content_) {}
std::string content;
};
inline _Comment Comment(const std::string content) { return _Comment(content); }
struct _Precision {
_Precision(int floatPrecision_, int doublePrecision_)
: floatPrecision(floatPrecision_), doublePrecision(doublePrecision_) {}
int floatPrecision;
int doublePrecision;
};
inline _Precision FloatPrecision(int n) { return _Precision(n, -1); }
inline _Precision DoublePrecision(int n) { return _Precision(-1, n); }
inline _Precision Precision(int n) { return _Precision(n, n); }
}
#endif // EMITTERMANIP_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,36 +1,38 @@
#ifndef EVENTHANDLER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef EVENTHANDLER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define EVENTHANDLER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define EVENTHANDLER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
#include "yaml-cpp/anchor.h" #include "yaml-cpp/anchor.h"
#include <string> #include <string>
namespace YAML namespace YAML {
{ struct Mark;
struct Mark;
class EventHandler class EventHandler {
{ public:
public: virtual ~EventHandler() {}
virtual ~EventHandler() {}
virtual void OnDocumentStart(const Mark& mark) = 0; virtual void OnDocumentStart(const Mark& mark) = 0;
virtual void OnDocumentEnd() = 0; virtual void OnDocumentEnd() = 0;
virtual void OnNull(const Mark& mark, anchor_t anchor) = 0; virtual void OnNull(const Mark& mark, anchor_t anchor) = 0;
virtual void OnAlias(const Mark& mark, anchor_t anchor) = 0; virtual void OnAlias(const Mark& mark, anchor_t anchor) = 0;
virtual void OnScalar(const Mark& mark, const std::string& tag, anchor_t anchor, const std::string& value) = 0; virtual void OnScalar(const Mark& mark, const std::string& tag,
anchor_t anchor, const std::string& value) = 0;
virtual void OnSequenceStart(const Mark& mark, const std::string& tag, anchor_t anchor) = 0; virtual void OnSequenceStart(const Mark& mark, const std::string& tag,
virtual void OnSequenceEnd() = 0; anchor_t anchor) = 0;
virtual void OnSequenceEnd() = 0;
virtual void OnMapStart(const Mark& mark, const std::string& tag, anchor_t anchor) = 0; virtual void OnMapStart(const Mark& mark, const std::string& tag,
virtual void OnMapEnd() = 0; anchor_t anchor) = 0;
}; virtual void OnMapEnd() = 0;
};
} }
#endif // EVENTHANDLER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #endif // EVENTHANDLER_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,26 +1,27 @@
#ifndef MARK_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef MARK_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define MARK_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define MARK_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
#include "yaml-cpp/dll.h" #include "yaml-cpp/dll.h"
namespace YAML namespace YAML {
{ struct YAML_CPP_API Mark {
struct YAML_CPP_API Mark { Mark() : pos(0), line(0), column(0) {}
Mark(): pos(0), line(0), column(0) {}
static const Mark null_mark() { return Mark(-1, -1, -1); } static const Mark null_mark() { return Mark(-1, -1, -1); }
int pos; int pos;
int line, column; int line, column;
private: private:
Mark(int pos_, int line_, int column_): pos(pos_), line(line_), column(column_) {} Mark(int pos_, int line_, int column_)
}; : pos(pos_), line(line_), column(column_) {}
};
} }
#endif // MARK_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #endif // MARK_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,25 +1,25 @@
#ifndef NONCOPYABLE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef NONCOPYABLE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define NONCOPYABLE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define NONCOPYABLE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
#include "yaml-cpp/dll.h" #include "yaml-cpp/dll.h"
namespace YAML namespace YAML {
{ // this is basically boost::noncopyable
// this is basically boost::noncopyable class YAML_CPP_API noncopyable {
class YAML_CPP_API noncopyable protected:
{ noncopyable() {}
protected: ~noncopyable() {}
noncopyable() {}
~noncopyable() {}
private: private:
noncopyable(const noncopyable&); noncopyable(const noncopyable&);
const noncopyable& operator = (const noncopyable&); const noncopyable& operator=(const noncopyable&);
}; };
} }
#endif // NONCOPYABLE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #endif // NONCOPYABLE_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,25 +1,24 @@
#ifndef NULL_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef NULL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define NULL_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define NULL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
#include "yaml-cpp/dll.h" #include "yaml-cpp/dll.h"
namespace YAML namespace YAML {
{ class Node;
class Node;
struct YAML_CPP_API _Null {}; struct YAML_CPP_API _Null {};
inline bool operator == (const _Null&, const _Null&) { return true; } inline bool operator==(const _Null&, const _Null&) { return true; }
inline bool operator != (const _Null&, const _Null&) { return false; } inline bool operator!=(const _Null&, const _Null&) { return false; }
YAML_CPP_API bool IsNull(const Node& node); // old API only YAML_CPP_API bool IsNull(const Node& node); // old API only
extern YAML_CPP_API _Null Null; extern YAML_CPP_API _Null Null;
} }
#endif // NULL_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #endif // NULL_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,69 +1,70 @@
#ifndef OSTREAM_WRAPPER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef OSTREAM_WRAPPER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define OSTREAM_WRAPPER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define OSTREAM_WRAPPER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
#include <string> #include <string>
#include <vector> #include <vector>
namespace YAML namespace YAML {
{ class ostream_wrapper {
class ostream_wrapper public:
{ ostream_wrapper();
public: explicit ostream_wrapper(std::ostream& stream);
ostream_wrapper(); ~ostream_wrapper();
explicit ostream_wrapper(std::ostream& stream);
~ostream_wrapper();
void write(const std::string& str); void write(const std::string& str);
void write(const char *str, std::size_t size); void write(const char* str, std::size_t size);
void set_comment() { m_comment = true; } void set_comment() { m_comment = true; }
const char *str() const { const char* str() const {
if(m_pStream) { if (m_pStream) {
return 0; return 0;
} else { } else {
m_buffer[m_pos] = '\0'; m_buffer[m_pos] = '\0';
return &m_buffer[0]; return &m_buffer[0];
}
}
std::size_t row() const { return m_row; }
std::size_t col() const { return m_col; }
std::size_t pos() const { return m_pos; }
bool comment() const { return m_comment; }
private:
void update_pos(char ch);
private:
mutable std::vector<char> m_buffer;
std::ostream *m_pStream;
std::size_t m_pos;
std::size_t m_row, m_col;
bool m_comment;
};
template<std::size_t N>
inline ostream_wrapper& operator << (ostream_wrapper& stream, const char (&str)[N]) {
stream.write(str, N-1);
return stream;
} }
}
inline ostream_wrapper& operator << (ostream_wrapper& stream, const std::string& str) { std::size_t row() const { return m_row; }
stream.write(str); std::size_t col() const { return m_col; }
return stream; std::size_t pos() const { return m_pos; }
} bool comment() const { return m_comment; }
inline ostream_wrapper& operator << (ostream_wrapper& stream, char ch) { private:
stream.write(&ch, 1); void update_pos(char ch);
return stream;
} private:
mutable std::vector<char> m_buffer;
std::ostream* m_pStream;
std::size_t m_pos;
std::size_t m_row, m_col;
bool m_comment;
};
template <std::size_t N>
inline ostream_wrapper& operator<<(ostream_wrapper& stream,
const char (&str)[N]) {
stream.write(str, N - 1);
return stream;
} }
#endif // OSTREAM_WRAPPER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 inline ostream_wrapper& operator<<(ostream_wrapper& stream,
const std::string& str) {
stream.write(str);
return stream;
}
inline ostream_wrapper& operator<<(ostream_wrapper& stream, char ch) {
stream.write(&ch, 1);
return stream;
}
}
#endif // OSTREAM_WRAPPER_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,51 +1,51 @@
#ifndef STLEMITTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef STLEMITTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define STLEMITTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define STLEMITTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
#include <vector> #include <vector>
#include <list> #include <list>
#include <set> #include <set>
#include <map> #include <map>
namespace YAML namespace YAML {
{ template <typename Seq>
template<typename Seq> inline Emitter& EmitSeq(Emitter& emitter, const Seq& seq) {
inline Emitter& EmitSeq(Emitter& emitter, const Seq& seq) { emitter << BeginSeq;
emitter << BeginSeq; for (typename Seq::const_iterator it = seq.begin(); it != seq.end(); ++it)
for(typename Seq::const_iterator it=seq.begin();it!=seq.end();++it) emitter << *it;
emitter << *it; emitter << EndSeq;
emitter << EndSeq; return emitter;
return emitter;
}
template<typename T>
inline Emitter& operator << (Emitter& emitter, const std::vector<T>& v) {
return EmitSeq(emitter, v);
}
template<typename T>
inline Emitter& operator << (Emitter& emitter, const std::list<T>& v) {
return EmitSeq(emitter, v);
}
template<typename T>
inline Emitter& operator << (Emitter& emitter, const std::set<T>& v) {
return EmitSeq(emitter, v);
}
template <typename K, typename V>
inline Emitter& operator << (Emitter& emitter, const std::map<K, V>& m) {
typedef typename std::map <K, V> map;
emitter << BeginMap;
for(typename map::const_iterator it=m.begin();it!=m.end();++it)
emitter << Key << it->first << Value << it->second;
emitter << EndMap;
return emitter;
}
} }
#endif // STLEMITTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 template <typename T>
inline Emitter& operator<<(Emitter& emitter, const std::vector<T>& v) {
return EmitSeq(emitter, v);
}
template <typename T>
inline Emitter& operator<<(Emitter& emitter, const std::list<T>& v) {
return EmitSeq(emitter, v);
}
template <typename T>
inline Emitter& operator<<(Emitter& emitter, const std::set<T>& v) {
return EmitSeq(emitter, v);
}
template <typename K, typename V>
inline Emitter& operator<<(Emitter& emitter, const std::map<K, V>& m) {
typedef typename std::map<K, V> map;
emitter << BeginMap;
for (typename map::const_iterator it = m.begin(); it != m.end(); ++it)
emitter << Key << it->first << Value << it->second;
emitter << EndMap;
return emitter;
}
}
#endif // STLEMITTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,57 +1,135 @@
#ifndef TRAITS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef TRAITS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define TRAITS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define TRAITS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
namespace YAML {
template <typename>
struct is_numeric {
enum {
value = false
};
};
namespace YAML template <>
{ struct is_numeric<char> {
template <typename> enum {
struct is_numeric { enum { value = false }; }; value = true
};
template <> struct is_numeric <char> { enum { value = true }; }; };
template <> struct is_numeric <unsigned char> { enum { value = true }; }; template <>
template <> struct is_numeric <int> { enum { value = true }; }; struct is_numeric<unsigned char> {
template <> struct is_numeric <unsigned int> { enum { value = true }; }; enum {
template <> struct is_numeric <long int> { enum { value = true }; }; value = true
template <> struct is_numeric <unsigned long int> { enum { value = true }; }; };
template <> struct is_numeric <short int> { enum { value = true }; }; };
template <> struct is_numeric <unsigned short int> { enum { value = true }; }; template <>
struct is_numeric<int> {
enum {
value = true
};
};
template <>
struct is_numeric<unsigned int> {
enum {
value = true
};
};
template <>
struct is_numeric<long int> {
enum {
value = true
};
};
template <>
struct is_numeric<unsigned long int> {
enum {
value = true
};
};
template <>
struct is_numeric<short int> {
enum {
value = true
};
};
template <>
struct is_numeric<unsigned short int> {
enum {
value = true
};
};
#if defined(_MSC_VER) && (_MSC_VER < 1310) #if defined(_MSC_VER) && (_MSC_VER < 1310)
template <> struct is_numeric <__int64> { enum { value = true }; }; template <>
template <> struct is_numeric <unsigned __int64> { enum { value = true }; }; struct is_numeric<__int64> {
enum {
value = true
};
};
template <>
struct is_numeric<unsigned __int64> {
enum {
value = true
};
};
#else #else
template <> struct is_numeric <long long> { enum { value = true }; }; template <>
template <> struct is_numeric <unsigned long long> { enum { value = true }; }; struct is_numeric<long long> {
enum {
value = true
};
};
template <>
struct is_numeric<unsigned long long> {
enum {
value = true
};
};
#endif #endif
template <> struct is_numeric <float> { enum { value = true }; }; template <>
template <> struct is_numeric <double> { enum { value = true }; }; struct is_numeric<float> {
template <> struct is_numeric <long double> { enum { value = true }; }; enum {
value = true
};
};
template <>
struct is_numeric<double> {
enum {
value = true
};
};
template <>
struct is_numeric<long double> {
enum {
value = true
};
};
template <bool, class T = void> template <bool, class T = void>
struct enable_if_c { struct enable_if_c {
typedef T type; typedef T type;
}; };
template <class T> template <class T>
struct enable_if_c<false, T> {}; struct enable_if_c<false, T> {};
template <class Cond, class T = void> template <class Cond, class T = void>
struct enable_if : public enable_if_c<Cond::value, T> {}; struct enable_if : public enable_if_c<Cond::value, T> {};
template <bool, class T = void> template <bool, class T = void>
struct disable_if_c { struct disable_if_c {
typedef T type; typedef T type;
}; };
template <class T> template <class T>
struct disable_if_c<true, T> {}; struct disable_if_c<true, T> {};
template <class Cond, class T = void> template <class Cond, class T = void>
struct disable_if : public disable_if_c<Cond::value, T> {}; struct disable_if : public disable_if_c<Cond::value, T> {};
} }
#endif // TRAITS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #endif // TRAITS_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,93 +1,92 @@
#include "yaml-cpp/binary.h" #include "yaml-cpp/binary.h"
namespace YAML namespace YAML {
{ static const char encoding[] =
static const char encoding[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
std::string EncodeBase64(const unsigned char *data, std::size_t size) std::string EncodeBase64(const unsigned char *data, std::size_t size) {
{ const char PAD = '=';
const char PAD = '=';
std::string ret; std::string ret;
ret.resize(4 * size / 3 + 3); ret.resize(4 * size / 3 + 3);
char *out = &ret[0]; char *out = &ret[0];
std::size_t chunks = size / 3; std::size_t chunks = size / 3;
std::size_t remainder = size % 3; std::size_t remainder = size % 3;
for(std::size_t i=0;i<chunks;i++, data += 3) { for (std::size_t i = 0; i < chunks; i++, data += 3) {
*out++ = encoding[data[0] >> 2]; *out++ = encoding[data[0] >> 2];
*out++ = encoding[((data[0] & 0x3) << 4) | (data[1] >> 4)]; *out++ = encoding[((data[0] & 0x3) << 4) | (data[1] >> 4)];
*out++ = encoding[((data[1] & 0xf) << 2) | (data[2] >> 6)]; *out++ = encoding[((data[1] & 0xf) << 2) | (data[2] >> 6)];
*out++ = encoding[data[2] & 0x3f]; *out++ = encoding[data[2] & 0x3f];
} }
switch(remainder) { switch (remainder) {
case 0: case 0:
break; break;
case 1: case 1:
*out++ = encoding[data[0] >> 2]; *out++ = encoding[data[0] >> 2];
*out++ = encoding[((data[0] & 0x3) << 4)]; *out++ = encoding[((data[0] & 0x3) << 4)];
*out++ = PAD; *out++ = PAD;
*out++ = PAD; *out++ = PAD;
break; break;
case 2: case 2:
*out++ = encoding[data[0] >> 2]; *out++ = encoding[data[0] >> 2];
*out++ = encoding[((data[0] & 0x3) << 4) | (data[1] >> 4)]; *out++ = encoding[((data[0] & 0x3) << 4) | (data[1] >> 4)];
*out++ = encoding[((data[1] & 0xf) << 2)]; *out++ = encoding[((data[1] & 0xf) << 2)];
*out++ = PAD; *out++ = PAD;
break; break;
} }
ret.resize(out - &ret[0]); ret.resize(out - &ret[0]);
return ret; return ret;
} }
static const unsigned char decoding[] = { static const unsigned char decoding[] = {
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255,255,255,255,255,255,255,255,255,255,255, 62,255,255,255, 63, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 62, 255,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61,255,255,255, 0,255,255, 255, 255, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255,
255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 255, 0, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,255,255,255,255,255, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 25, 255, 255, 255, 255, 255, 255, 26, 27, 28, 29, 30, 31, 32, 33,
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,255,255,255,255,255, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 49, 50, 51, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
}; 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, };
std::vector<unsigned char> DecodeBase64(const std::string& input)
{ std::vector<unsigned char> DecodeBase64(const std::string &input) {
typedef std::vector<unsigned char> ret_type; typedef std::vector<unsigned char> ret_type;
if(input.empty()) if (input.empty())
return ret_type(); return ret_type();
ret_type ret(3 * input.size() / 4 + 1); ret_type ret(3 * input.size() / 4 + 1);
unsigned char *out = &ret[0]; unsigned char *out = &ret[0];
unsigned value = 0; unsigned value = 0;
for(std::size_t i=0;i<input.size();i++) { for (std::size_t i = 0; i < input.size(); i++) {
unsigned char d = decoding[static_cast<unsigned>(input[i])]; unsigned char d = decoding[static_cast<unsigned>(input[i])];
if(d == 255) if (d == 255)
return ret_type(); return ret_type();
value = (value << 6) | d; value = (value << 6) | d;
if(i % 4 == 3) { if (i % 4 == 3) {
*out++ = value >> 16; *out++ = value >> 16;
if(i > 0 && input[i - 1] != '=') if (i > 0 && input[i - 1] != '=')
*out++ = value >> 8; *out++ = value >> 8;
if(input[i] != '=') if (input[i] != '=')
*out++ = value; *out++ = value;
} }
} }
ret.resize(out - &ret[0]); ret.resize(out - &ret[0]);
return ret; return ret;
} }
} }

View File

@@ -1,35 +1,46 @@
#ifndef COLLECTIONSTACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef COLLECTIONSTACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define COLLECTIONSTACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define COLLECTIONSTACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
#include <stack> #include <stack>
#include <cassert> #include <cassert>
namespace YAML namespace YAML {
{ struct CollectionType {
struct CollectionType { enum value {
enum value { None, BlockMap, BlockSeq, FlowMap, FlowSeq, CompactMap }; None,
}; BlockMap,
BlockSeq,
FlowMap,
FlowSeq,
CompactMap
};
};
class CollectionStack class CollectionStack {
{ public:
public: CollectionType::value GetCurCollectionType() const {
CollectionType::value GetCurCollectionType() const { if (collectionStack.empty())
if(collectionStack.empty()) return CollectionType::None;
return CollectionType::None; return collectionStack.top();
return collectionStack.top(); }
}
void PushCollectionType(CollectionType::value type) { collectionStack.push(type); } void PushCollectionType(CollectionType::value type) {
void PopCollectionType(CollectionType::value type) { assert(type == GetCurCollectionType()); collectionStack.pop(); } collectionStack.push(type);
}
void PopCollectionType(CollectionType::value type) {
assert(type == GetCurCollectionType());
collectionStack.pop();
}
private: private:
std::stack<CollectionType::value> collectionStack; std::stack<CollectionType::value> collectionStack;
}; };
} }
#endif // COLLECTIONSTACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #endif // COLLECTIONSTACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -2,15 +2,14 @@
#include "yaml-cpp/contrib/graphbuilder.h" #include "yaml-cpp/contrib/graphbuilder.h"
#include "graphbuilderadapter.h" #include "graphbuilderadapter.h"
namespace YAML namespace YAML {
{ void* BuildGraphOfNextDocument(Parser& parser,
void *BuildGraphOfNextDocument(Parser& parser, GraphBuilderInterface& graphBuilder) GraphBuilderInterface& graphBuilder) {
{ GraphBuilderAdapter eventHandler(graphBuilder);
GraphBuilderAdapter eventHandler(graphBuilder); if (parser.HandleNextDocument(eventHandler)) {
if (parser.HandleNextDocument(eventHandler)) { return eventHandler.RootNode();
return eventHandler.RootNode(); } else {
} else { return NULL;
return NULL;
}
} }
} }
}

View File

@@ -1,96 +1,89 @@
#include "graphbuilderadapter.h" #include "graphbuilderadapter.h"
namespace YAML namespace YAML {
{ int GraphBuilderAdapter::ContainerFrame::sequenceMarker;
int GraphBuilderAdapter::ContainerFrame::sequenceMarker;
void GraphBuilderAdapter::OnNull(const Mark& mark, anchor_t anchor) void GraphBuilderAdapter::OnNull(const Mark &mark, anchor_t anchor) {
{ void *pParent = GetCurrentParent();
void *pParent = GetCurrentParent(); void *pNode = m_builder.NewNull(mark, pParent);
void *pNode = m_builder.NewNull(mark, pParent); RegisterAnchor(anchor, pNode);
RegisterAnchor(anchor, pNode);
DispositionNode(pNode); DispositionNode(pNode);
}
void GraphBuilderAdapter::OnAlias(const Mark &mark, anchor_t anchor) {
void *pReffedNode = m_anchors.Get(anchor);
DispositionNode(m_builder.AnchorReference(mark, pReffedNode));
}
void GraphBuilderAdapter::OnScalar(const Mark &mark, const std::string &tag,
anchor_t anchor, const std::string &value) {
void *pParent = GetCurrentParent();
void *pNode = m_builder.NewScalar(mark, tag, pParent, value);
RegisterAnchor(anchor, pNode);
DispositionNode(pNode);
}
void GraphBuilderAdapter::OnSequenceStart(const Mark &mark,
const std::string &tag,
anchor_t anchor) {
void *pNode = m_builder.NewSequence(mark, tag, GetCurrentParent());
m_containers.push(ContainerFrame(pNode));
RegisterAnchor(anchor, pNode);
}
void GraphBuilderAdapter::OnSequenceEnd() {
void *pSequence = m_containers.top().pContainer;
m_containers.pop();
DispositionNode(pSequence);
}
void GraphBuilderAdapter::OnMapStart(const Mark &mark, const std::string &tag,
anchor_t anchor) {
void *pNode = m_builder.NewMap(mark, tag, GetCurrentParent());
m_containers.push(ContainerFrame(pNode, m_pKeyNode));
m_pKeyNode = NULL;
RegisterAnchor(anchor, pNode);
}
void GraphBuilderAdapter::OnMapEnd() {
void *pMap = m_containers.top().pContainer;
m_pKeyNode = m_containers.top().pPrevKeyNode;
m_containers.pop();
DispositionNode(pMap);
}
void *GraphBuilderAdapter::GetCurrentParent() const {
if (m_containers.empty()) {
return NULL;
} }
return m_containers.top().pContainer;
}
void GraphBuilderAdapter::OnAlias(const Mark& mark, anchor_t anchor) void GraphBuilderAdapter::RegisterAnchor(anchor_t anchor, void *pNode) {
{ if (anchor) {
void *pReffedNode = m_anchors.Get(anchor); m_anchors.Register(anchor, pNode);
DispositionNode(m_builder.AnchorReference(mark, pReffedNode));
}
void GraphBuilderAdapter::OnScalar(const Mark& mark, const std::string& tag, anchor_t anchor, const std::string& value)
{
void *pParent = GetCurrentParent();
void *pNode = m_builder.NewScalar(mark, tag, pParent, value);
RegisterAnchor(anchor, pNode);
DispositionNode(pNode);
}
void GraphBuilderAdapter::OnSequenceStart(const Mark& mark, const std::string& tag, anchor_t anchor)
{
void *pNode = m_builder.NewSequence(mark, tag, GetCurrentParent());
m_containers.push(ContainerFrame(pNode));
RegisterAnchor(anchor, pNode);
}
void GraphBuilderAdapter::OnSequenceEnd()
{
void *pSequence = m_containers.top().pContainer;
m_containers.pop();
DispositionNode(pSequence);
}
void GraphBuilderAdapter::OnMapStart(const Mark& mark, const std::string& tag, anchor_t anchor)
{
void *pNode = m_builder.NewMap(mark, tag, GetCurrentParent());
m_containers.push(ContainerFrame(pNode, m_pKeyNode));
m_pKeyNode = NULL;
RegisterAnchor(anchor, pNode);
}
void GraphBuilderAdapter::OnMapEnd()
{
void *pMap = m_containers.top().pContainer;
m_pKeyNode = m_containers.top().pPrevKeyNode;
m_containers.pop();
DispositionNode(pMap);
}
void *GraphBuilderAdapter::GetCurrentParent() const
{
if (m_containers.empty()) {
return NULL;
}
return m_containers.top().pContainer;
}
void GraphBuilderAdapter::RegisterAnchor(anchor_t anchor, void *pNode)
{
if (anchor) {
m_anchors.Register(anchor, pNode);
}
}
void GraphBuilderAdapter::DispositionNode(void *pNode)
{
if (m_containers.empty()) {
m_pRootNode = pNode;
return;
}
void *pContainer = m_containers.top().pContainer;
if (m_containers.top().isMap()) {
if (m_pKeyNode) {
m_builder.AssignInMap(pContainer, m_pKeyNode, pNode);
m_pKeyNode = NULL;
} else {
m_pKeyNode = pNode;
}
} else {
m_builder.AppendToSequence(pContainer, pNode);
}
} }
} }
void GraphBuilderAdapter::DispositionNode(void *pNode) {
if (m_containers.empty()) {
m_pRootNode = pNode;
return;
}
void *pContainer = m_containers.top().pContainer;
if (m_containers.top().isMap()) {
if (m_pKeyNode) {
m_builder.AssignInMap(pContainer, m_pKeyNode, pNode);
m_pKeyNode = NULL;
} else {
m_pKeyNode = pNode;
}
} else {
m_builder.AppendToSequence(pContainer, pNode);
}
}
}

View File

@@ -1,7 +1,9 @@
#ifndef GRAPHBUILDERADAPTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef GRAPHBUILDERADAPTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define GRAPHBUILDERADAPTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define GRAPHBUILDERADAPTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
@@ -12,62 +14,58 @@
#include "yaml-cpp/contrib/anchordict.h" #include "yaml-cpp/contrib/anchordict.h"
#include "yaml-cpp/contrib/graphbuilder.h" #include "yaml-cpp/contrib/graphbuilder.h"
namespace YAML namespace YAML {
{ class GraphBuilderAdapter : public EventHandler {
class GraphBuilderAdapter : public EventHandler public:
{ GraphBuilderAdapter(GraphBuilderInterface& builder)
public: : m_builder(builder), m_pRootNode(NULL), m_pKeyNode(NULL) {}
GraphBuilderAdapter(GraphBuilderInterface& builder)
: m_builder(builder), m_pRootNode(NULL), m_pKeyNode(NULL)
{
}
virtual void OnDocumentStart(const Mark& mark) {(void)mark;} virtual void OnDocumentStart(const Mark& mark) { (void)mark; }
virtual void OnDocumentEnd() {} virtual void OnDocumentEnd() {}
virtual void OnNull(const Mark& mark, anchor_t anchor); virtual void OnNull(const Mark& mark, anchor_t anchor);
virtual void OnAlias(const Mark& mark, anchor_t anchor); virtual void OnAlias(const Mark& mark, anchor_t anchor);
virtual void OnScalar(const Mark& mark, const std::string& tag, anchor_t anchor, const std::string& value); virtual void OnScalar(const Mark& mark, const std::string& tag,
anchor_t anchor, const std::string& value);
virtual void OnSequenceStart(const Mark& mark, const std::string& tag, anchor_t anchor); virtual void OnSequenceStart(const Mark& mark, const std::string& tag,
virtual void OnSequenceEnd(); anchor_t anchor);
virtual void OnSequenceEnd();
virtual void OnMapStart(const Mark& mark, const std::string& tag, anchor_t anchor); virtual void OnMapStart(const Mark& mark, const std::string& tag,
virtual void OnMapEnd(); anchor_t anchor);
virtual void OnMapEnd();
void *RootNode() const {return m_pRootNode;} void* RootNode() const { return m_pRootNode; }
private: private:
struct ContainerFrame struct ContainerFrame {
{ ContainerFrame(void* pSequence)
ContainerFrame(void *pSequence) : pContainer(pSequence), pPrevKeyNode(&sequenceMarker) {}
: pContainer(pSequence), pPrevKeyNode(&sequenceMarker) ContainerFrame(void* pMap, void* pPrevKeyNode)
{} : pContainer(pMap), pPrevKeyNode(pPrevKeyNode) {}
ContainerFrame(void *pMap, void* pPrevKeyNode)
: pContainer(pMap), pPrevKeyNode(pPrevKeyNode)
{}
void *pContainer; void* pContainer;
void *pPrevKeyNode; void* pPrevKeyNode;
bool isMap() const {return pPrevKeyNode != &sequenceMarker;} bool isMap() const { return pPrevKeyNode != &sequenceMarker; }
private: private:
static int sequenceMarker; static int sequenceMarker;
};
typedef std::stack<ContainerFrame> ContainerStack;
typedef AnchorDict<void*> AnchorMap;
GraphBuilderInterface& m_builder;
ContainerStack m_containers;
AnchorMap m_anchors;
void *m_pRootNode;
void *m_pKeyNode;
void *GetCurrentParent() const;
void RegisterAnchor(anchor_t anchor, void *pNode);
void DispositionNode(void *pNode);
}; };
typedef std::stack<ContainerFrame> ContainerStack;
typedef AnchorDict<void*> AnchorMap;
GraphBuilderInterface& m_builder;
ContainerStack m_containers;
AnchorMap m_anchors;
void* m_pRootNode;
void* m_pKeyNode;
void* GetCurrentParent() const;
void RegisterAnchor(anchor_t anchor, void* pNode);
void DispositionNode(void* pNode);
};
} }
#endif // GRAPHBUILDERADAPTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #endif // GRAPHBUILDERADAPTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,24 +1,22 @@
#include "directives.h" #include "directives.h"
namespace YAML namespace YAML {
{ Directives::Directives() {
Directives::Directives() // version
{ version.isDefault = true;
// version version.major = 1;
version.isDefault = true; version.minor = 2;
version.major = 1; }
version.minor = 2;
} const std::string Directives::TranslateTagHandle(const std::string& handle)
const {
const std::string Directives::TranslateTagHandle(const std::string& handle) const std::map<std::string, std::string>::const_iterator it = tags.find(handle);
{ if (it == tags.end()) {
std::map <std::string, std::string>::const_iterator it = tags.find(handle); if (handle == "!!")
if(it == tags.end()) { return "tag:yaml.org,2002:";
if(handle == "!!") return handle;
return "tag:yaml.org,2002:"; }
return handle;
} return it->second;
}
return it->second;
}
} }

View File

@@ -1,29 +1,29 @@
#ifndef DIRECTIVES_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef DIRECTIVES_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define DIRECTIVES_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define DIRECTIVES_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
#include <string> #include <string>
#include <map> #include <map>
namespace YAML namespace YAML {
{ struct Version {
struct Version { bool isDefault;
bool isDefault; int major, minor;
int major, minor; };
};
struct Directives { struct Directives {
Directives(); Directives();
const std::string TranslateTagHandle(const std::string& handle) const; const std::string TranslateTagHandle(const std::string& handle) const;
Version version; Version version;
std::map<std::string, std::string> tags; std::map<std::string, std::string> tags;
}; };
} }
#endif // DIRECTIVES_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #endif // DIRECTIVES_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -5,101 +5,88 @@
#include <sstream> #include <sstream>
namespace { namespace {
std::string ToString(YAML::anchor_t anchor) { std::string ToString(YAML::anchor_t anchor) {
std::stringstream stream; std::stringstream stream;
stream << anchor; stream << anchor;
return stream.str(); return stream.str();
} }
} }
namespace YAML namespace YAML {
{ EmitFromEvents::EmitFromEvents(Emitter& emitter) : m_emitter(emitter) {}
EmitFromEvents::EmitFromEvents(Emitter& emitter): m_emitter(emitter)
{
}
void EmitFromEvents::OnDocumentStart(const Mark&) void EmitFromEvents::OnDocumentStart(const Mark&) {}
{
}
void EmitFromEvents::OnDocumentEnd() void EmitFromEvents::OnDocumentEnd() {}
{
}
void EmitFromEvents::OnNull(const Mark&, anchor_t anchor) void EmitFromEvents::OnNull(const Mark&, anchor_t anchor) {
{ BeginNode();
BeginNode(); EmitProps("", anchor);
EmitProps("", anchor); m_emitter << Null;
m_emitter << Null; }
}
void EmitFromEvents::OnAlias(const Mark&, anchor_t anchor) {
void EmitFromEvents::OnAlias(const Mark&, anchor_t anchor) BeginNode();
{ m_emitter << Alias(ToString(anchor));
BeginNode(); }
m_emitter << Alias(ToString(anchor));
} void EmitFromEvents::OnScalar(const Mark&, const std::string& tag,
anchor_t anchor, const std::string& value) {
void EmitFromEvents::OnScalar(const Mark&, const std::string& tag, anchor_t anchor, const std::string& value) BeginNode();
{ EmitProps(tag, anchor);
BeginNode(); m_emitter << value;
EmitProps(tag, anchor); }
m_emitter << value;
} void EmitFromEvents::OnSequenceStart(const Mark&, const std::string& tag,
anchor_t anchor) {
void EmitFromEvents::OnSequenceStart(const Mark&, const std::string& tag, anchor_t anchor) BeginNode();
{ EmitProps(tag, anchor);
BeginNode(); m_emitter << BeginSeq;
EmitProps(tag, anchor); m_stateStack.push(State::WaitingForSequenceEntry);
m_emitter << BeginSeq; }
m_stateStack.push(State::WaitingForSequenceEntry);
} void EmitFromEvents::OnSequenceEnd() {
m_emitter << EndSeq;
void EmitFromEvents::OnSequenceEnd() assert(m_stateStack.top() == State::WaitingForSequenceEntry);
{ m_stateStack.pop();
m_emitter << EndSeq; }
assert(m_stateStack.top() == State::WaitingForSequenceEntry);
m_stateStack.pop(); void EmitFromEvents::OnMapStart(const Mark&, const std::string& tag,
} anchor_t anchor) {
BeginNode();
void EmitFromEvents::OnMapStart(const Mark&, const std::string& tag, anchor_t anchor) EmitProps(tag, anchor);
{ m_emitter << BeginMap;
BeginNode(); m_stateStack.push(State::WaitingForKey);
EmitProps(tag, anchor); }
m_emitter << BeginMap;
m_stateStack.push(State::WaitingForKey); void EmitFromEvents::OnMapEnd() {
} m_emitter << EndMap;
assert(m_stateStack.top() == State::WaitingForKey);
void EmitFromEvents::OnMapEnd() m_stateStack.pop();
{ }
m_emitter << EndMap;
assert(m_stateStack.top() == State::WaitingForKey); void EmitFromEvents::BeginNode() {
m_stateStack.pop(); if (m_stateStack.empty())
} return;
void EmitFromEvents::BeginNode() switch (m_stateStack.top()) {
{ case State::WaitingForKey:
if(m_stateStack.empty()) m_emitter << Key;
return; m_stateStack.top() = State::WaitingForValue;
break;
switch(m_stateStack.top()) { case State::WaitingForValue:
case State::WaitingForKey: m_emitter << Value;
m_emitter << Key; m_stateStack.top() = State::WaitingForKey;
m_stateStack.top() = State::WaitingForValue; break;
break; default:
case State::WaitingForValue: break;
m_emitter << Value; }
m_stateStack.top() = State::WaitingForKey; }
break;
default: void EmitFromEvents::EmitProps(const std::string& tag, anchor_t anchor) {
break; if (!tag.empty() && tag != "?")
} m_emitter << VerbatimTag(tag);
} if (anchor)
m_emitter << Anchor(ToString(anchor));
void EmitFromEvents::EmitProps(const std::string& tag, anchor_t anchor) }
{
if(!tag.empty() && tag != "?")
m_emitter << VerbatimTag(tag);
if(anchor)
m_emitter << Anchor(ToString(anchor));
}
} }

File diff suppressed because it is too large Load Diff

View File

@@ -2,383 +2,346 @@
#include "yaml-cpp/exceptions.h" #include "yaml-cpp/exceptions.h"
#include <limits> #include <limits>
namespace YAML namespace YAML {
{ EmitterState::EmitterState()
EmitterState::EmitterState(): m_isGood(true), m_curIndent(0), m_hasAnchor(false), m_hasTag(false), m_hasNonContent(false), m_docCount(0) : m_isGood(true),
{ m_curIndent(0),
// set default global manipulators m_hasAnchor(false),
m_charset.set(EmitNonAscii); m_hasTag(false),
m_strFmt.set(Auto); m_hasNonContent(false),
m_boolFmt.set(TrueFalseBool); m_docCount(0) {
m_boolLengthFmt.set(LongBool); // set default global manipulators
m_boolCaseFmt.set(LowerCase); m_charset.set(EmitNonAscii);
m_intFmt.set(Dec); m_strFmt.set(Auto);
m_indent.set(2); m_boolFmt.set(TrueFalseBool);
m_preCommentIndent.set(2); m_boolLengthFmt.set(LongBool);
m_postCommentIndent.set(1); m_boolCaseFmt.set(LowerCase);
m_seqFmt.set(Block); m_intFmt.set(Dec);
m_mapFmt.set(Block); m_indent.set(2);
m_mapKeyFmt.set(Auto); m_preCommentIndent.set(2);
m_floatPrecision.set(std::numeric_limits<float>::digits10 + 1); m_postCommentIndent.set(1);
m_doublePrecision.set(std::numeric_limits<double>::digits10 + 1); m_seqFmt.set(Block);
} m_mapFmt.set(Block);
m_mapKeyFmt.set(Auto);
EmitterState::~EmitterState() m_floatPrecision.set(std::numeric_limits<float>::digits10 + 1);
{ m_doublePrecision.set(std::numeric_limits<double>::digits10 + 1);
}
// 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, FmtScope::Local);
SetStringFormat(value, FmtScope::Local);
SetBoolFormat(value, FmtScope::Local);
SetBoolCaseFormat(value, FmtScope::Local);
SetBoolLengthFormat(value, FmtScope::Local);
SetIntFormat(value, FmtScope::Local);
SetFlowType(GroupType::Seq, value, FmtScope::Local);
SetFlowType(GroupType::Map, value, FmtScope::Local);
SetMapKeyFormat(value, FmtScope::Local);
}
void EmitterState::SetAnchor()
{
m_hasAnchor = true;
}
void EmitterState::SetTag()
{
m_hasTag = true;
}
void EmitterState::SetNonContent()
{
m_hasNonContent = true;
}
void EmitterState::SetLongKey()
{
assert(!m_groups.empty());
if(m_groups.empty())
return;
assert(m_groups.top().type == GroupType::Map);
m_groups.top().longKey = true;
}
void EmitterState::ForceFlow()
{
assert(!m_groups.empty());
if(m_groups.empty())
return;
m_groups.top().flowType = FlowType::Flow;
}
void EmitterState::StartedNode()
{
if(m_groups.empty()) {
m_docCount++;
} else {
m_groups.top().childCount++;
if(m_groups.top().childCount % 2 == 0)
m_groups.top().longKey = false;
}
m_hasAnchor = false;
m_hasTag = false;
m_hasNonContent = false;
}
EmitterNodeType::value EmitterState::NextGroupType(GroupType::value type) const
{
if(type == GroupType::Seq) {
if(GetFlowType(type) == Block)
return EmitterNodeType::BlockSeq;
else
return EmitterNodeType::FlowSeq;
} else {
if(GetFlowType(type) == Block)
return EmitterNodeType::BlockMap;
else
return EmitterNodeType::FlowMap;
}
// can't happen
assert(false);
return EmitterNodeType::None;
}
void EmitterState::StartedDoc()
{
m_hasAnchor = false;
m_hasTag = false;
m_hasNonContent = false;
}
void EmitterState::EndedDoc()
{
m_hasAnchor = false;
m_hasTag = false;
m_hasNonContent = false;
}
void EmitterState::StartedScalar()
{
StartedNode();
ClearModifiedSettings();
}
void EmitterState::StartedGroup(GroupType::value type)
{
StartedNode();
const int lastGroupIndent = (m_groups.empty() ? 0 : m_groups.top().indent);
m_curIndent += lastGroupIndent;
std::auto_ptr<Group> pGroup(new Group(type));
// transfer settings (which last until this group is done)
pGroup->modifiedSettings = m_modifiedSettings;
// set up group
if(GetFlowType(type) == Block)
pGroup->flowType = FlowType::Block;
else
pGroup->flowType = FlowType::Flow;
pGroup->indent = GetIndent();
m_groups.push(pGroup);
}
void EmitterState::EndedGroup(GroupType::value type)
{
if(m_groups.empty()) {
if(type == GroupType::Seq)
return SetError(ErrorMsg::UNEXPECTED_END_SEQ);
else
return SetError(ErrorMsg::UNEXPECTED_END_MAP);
}
// get rid of the current group
{
std::auto_ptr<Group> pFinishedGroup = m_groups.pop();
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();
ClearModifiedSettings();
}
EmitterNodeType::value EmitterState::CurGroupNodeType() const
{
if(m_groups.empty())
return EmitterNodeType::None;
return m_groups.top().NodeType();
}
GroupType::value EmitterState::CurGroupType() const
{
return m_groups.empty() ? GroupType::None : m_groups.top().type;
}
FlowType::value EmitterState::CurGroupFlowType() const
{
return m_groups.empty() ? FlowType::None : m_groups.top().flowType;
}
int EmitterState::CurGroupIndent() const
{
return m_groups.empty() ? 0 : m_groups.top().indent;
}
std::size_t EmitterState::CurGroupChildCount() const
{
return m_groups.empty() ? m_docCount : m_groups.top().childCount;
}
bool EmitterState::CurGroupLongKey() const
{
return m_groups.empty() ? false : m_groups.top().longKey;
}
int EmitterState::LastIndent() const
{
if(m_groups.size() <= 1)
return 0;
return m_curIndent - m_groups.top(-1).indent;
}
void EmitterState::ClearModifiedSettings()
{
m_modifiedSettings.clear();
}
bool EmitterState::SetOutputCharset(EMITTER_MANIP value, FmtScope::value scope)
{
switch(value) {
case EmitNonAscii:
case EscapeNonAscii:
_Set(m_charset, value, scope);
return true;
default:
return false;
}
}
bool EmitterState::SetStringFormat(EMITTER_MANIP value, FmtScope::value 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, FmtScope::value 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, FmtScope::value scope)
{
switch(value) {
case LongBool:
case ShortBool:
_Set(m_boolLengthFmt, value, scope);
return true;
default:
return false;
}
}
bool EmitterState::SetBoolCaseFormat(EMITTER_MANIP value, FmtScope::value 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, FmtScope::value scope)
{
switch(value) {
case Dec:
case Hex:
case Oct:
_Set(m_intFmt, value, scope);
return true;
default:
return false;
}
}
bool EmitterState::SetIndent(unsigned value, FmtScope::value scope)
{
if(value <= 1)
return false;
_Set(m_indent, value, scope);
return true;
}
bool EmitterState::SetPreCommentIndent(unsigned value, FmtScope::value scope)
{
if(value == 0)
return false;
_Set(m_preCommentIndent, value, scope);
return true;
}
bool EmitterState::SetPostCommentIndent(unsigned value, FmtScope::value scope)
{
if(value == 0)
return false;
_Set(m_postCommentIndent, value, scope);
return true;
}
bool EmitterState::SetFlowType(GroupType::value groupType, EMITTER_MANIP value, FmtScope::value scope)
{
switch(value) {
case Block:
case Flow:
_Set(groupType == GroupType::Seq ? m_seqFmt : m_mapFmt, value, scope);
return true;
default:
return false;
}
}
EMITTER_MANIP EmitterState::GetFlowType(GroupType::value groupType) const
{
// force flow style if we're currently in a flow
if(CurGroupFlowType() == FlowType::Flow)
return Flow;
// otherwise, go with what's asked of us
return (groupType == GroupType::Seq ? m_seqFmt.get() : m_mapFmt.get());
}
bool EmitterState::SetMapKeyFormat(EMITTER_MANIP value, FmtScope::value scope)
{
switch(value) {
case Auto:
case LongKey:
_Set(m_mapKeyFmt, value, scope);
return true;
default:
return false;
}
}
bool EmitterState::SetFloatPrecision(int value, FmtScope::value scope)
{
if(value < 0 || value > std::numeric_limits<float>::digits10 + 1)
return false;
_Set(m_floatPrecision, value, scope);
return true;
}
bool EmitterState::SetDoublePrecision(int value, FmtScope::value scope)
{
if(value < 0 || value > std::numeric_limits<double>::digits10 + 1)
return false;
_Set(m_doublePrecision, value, scope);
return true;
}
} }
EmitterState::~EmitterState() {}
// 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, FmtScope::Local);
SetStringFormat(value, FmtScope::Local);
SetBoolFormat(value, FmtScope::Local);
SetBoolCaseFormat(value, FmtScope::Local);
SetBoolLengthFormat(value, FmtScope::Local);
SetIntFormat(value, FmtScope::Local);
SetFlowType(GroupType::Seq, value, FmtScope::Local);
SetFlowType(GroupType::Map, value, FmtScope::Local);
SetMapKeyFormat(value, FmtScope::Local);
}
void EmitterState::SetAnchor() { m_hasAnchor = true; }
void EmitterState::SetTag() { m_hasTag = true; }
void EmitterState::SetNonContent() { m_hasNonContent = true; }
void EmitterState::SetLongKey() {
assert(!m_groups.empty());
if (m_groups.empty())
return;
assert(m_groups.top().type == GroupType::Map);
m_groups.top().longKey = true;
}
void EmitterState::ForceFlow() {
assert(!m_groups.empty());
if (m_groups.empty())
return;
m_groups.top().flowType = FlowType::Flow;
}
void EmitterState::StartedNode() {
if (m_groups.empty()) {
m_docCount++;
} else {
m_groups.top().childCount++;
if (m_groups.top().childCount % 2 == 0)
m_groups.top().longKey = false;
}
m_hasAnchor = false;
m_hasTag = false;
m_hasNonContent = false;
}
EmitterNodeType::value EmitterState::NextGroupType(GroupType::value type)
const {
if (type == GroupType::Seq) {
if (GetFlowType(type) == Block)
return EmitterNodeType::BlockSeq;
else
return EmitterNodeType::FlowSeq;
} else {
if (GetFlowType(type) == Block)
return EmitterNodeType::BlockMap;
else
return EmitterNodeType::FlowMap;
}
// can't happen
assert(false);
return EmitterNodeType::None;
}
void EmitterState::StartedDoc() {
m_hasAnchor = false;
m_hasTag = false;
m_hasNonContent = false;
}
void EmitterState::EndedDoc() {
m_hasAnchor = false;
m_hasTag = false;
m_hasNonContent = false;
}
void EmitterState::StartedScalar() {
StartedNode();
ClearModifiedSettings();
}
void EmitterState::StartedGroup(GroupType::value type) {
StartedNode();
const int lastGroupIndent = (m_groups.empty() ? 0 : m_groups.top().indent);
m_curIndent += lastGroupIndent;
std::auto_ptr<Group> pGroup(new Group(type));
// transfer settings (which last until this group is done)
pGroup->modifiedSettings = m_modifiedSettings;
// set up group
if (GetFlowType(type) == Block)
pGroup->flowType = FlowType::Block;
else
pGroup->flowType = FlowType::Flow;
pGroup->indent = GetIndent();
m_groups.push(pGroup);
}
void EmitterState::EndedGroup(GroupType::value type) {
if (m_groups.empty()) {
if (type == GroupType::Seq)
return SetError(ErrorMsg::UNEXPECTED_END_SEQ);
else
return SetError(ErrorMsg::UNEXPECTED_END_MAP);
}
// get rid of the current group
{
std::auto_ptr<Group> pFinishedGroup = m_groups.pop();
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();
ClearModifiedSettings();
}
EmitterNodeType::value EmitterState::CurGroupNodeType() const {
if (m_groups.empty())
return EmitterNodeType::None;
return m_groups.top().NodeType();
}
GroupType::value EmitterState::CurGroupType() const {
return m_groups.empty() ? GroupType::None : m_groups.top().type;
}
FlowType::value EmitterState::CurGroupFlowType() const {
return m_groups.empty() ? FlowType::None : m_groups.top().flowType;
}
int EmitterState::CurGroupIndent() const {
return m_groups.empty() ? 0 : m_groups.top().indent;
}
std::size_t EmitterState::CurGroupChildCount() const {
return m_groups.empty() ? m_docCount : m_groups.top().childCount;
}
bool EmitterState::CurGroupLongKey() const {
return m_groups.empty() ? false : m_groups.top().longKey;
}
int EmitterState::LastIndent() const {
if (m_groups.size() <= 1)
return 0;
return m_curIndent - m_groups.top(-1).indent;
}
void EmitterState::ClearModifiedSettings() { m_modifiedSettings.clear(); }
bool EmitterState::SetOutputCharset(EMITTER_MANIP value,
FmtScope::value scope) {
switch (value) {
case EmitNonAscii:
case EscapeNonAscii:
_Set(m_charset, value, scope);
return true;
default:
return false;
}
}
bool EmitterState::SetStringFormat(EMITTER_MANIP value, FmtScope::value 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, FmtScope::value 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,
FmtScope::value scope) {
switch (value) {
case LongBool:
case ShortBool:
_Set(m_boolLengthFmt, value, scope);
return true;
default:
return false;
}
}
bool EmitterState::SetBoolCaseFormat(EMITTER_MANIP value,
FmtScope::value 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, FmtScope::value scope) {
switch (value) {
case Dec:
case Hex:
case Oct:
_Set(m_intFmt, value, scope);
return true;
default:
return false;
}
}
bool EmitterState::SetIndent(unsigned value, FmtScope::value scope) {
if (value <= 1)
return false;
_Set(m_indent, value, scope);
return true;
}
bool EmitterState::SetPreCommentIndent(unsigned value, FmtScope::value scope) {
if (value == 0)
return false;
_Set(m_preCommentIndent, value, scope);
return true;
}
bool EmitterState::SetPostCommentIndent(unsigned value, FmtScope::value scope) {
if (value == 0)
return false;
_Set(m_postCommentIndent, value, scope);
return true;
}
bool EmitterState::SetFlowType(GroupType::value groupType, EMITTER_MANIP value,
FmtScope::value scope) {
switch (value) {
case Block:
case Flow:
_Set(groupType == GroupType::Seq ? m_seqFmt : m_mapFmt, value, scope);
return true;
default:
return false;
}
}
EMITTER_MANIP EmitterState::GetFlowType(GroupType::value groupType) const {
// force flow style if we're currently in a flow
if (CurGroupFlowType() == FlowType::Flow)
return Flow;
// otherwise, go with what's asked of us
return (groupType == GroupType::Seq ? m_seqFmt.get() : m_mapFmt.get());
}
bool EmitterState::SetMapKeyFormat(EMITTER_MANIP value, FmtScope::value scope) {
switch (value) {
case Auto:
case LongKey:
_Set(m_mapKeyFmt, value, scope);
return true;
default:
return false;
}
}
bool EmitterState::SetFloatPrecision(int value, FmtScope::value scope) {
if (value < 0 || value > std::numeric_limits<float>::digits10 + 1)
return false;
_Set(m_floatPrecision, value, scope);
return true;
}
bool EmitterState::SetDoublePrecision(int value, FmtScope::value scope) {
if (value < 0 || value > std::numeric_limits<double>::digits10 + 1)
return false;
_Set(m_doublePrecision, value, scope);
return true;
}
}

View File

@@ -1,11 +1,12 @@
#ifndef EMITTERSTATE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef EMITTERSTATE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define EMITTERSTATE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define EMITTERSTATE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
#include "ptr_stack.h" #include "ptr_stack.h"
#include "setting.h" #include "setting.h"
#include "yaml-cpp/emitterdef.h" #include "yaml-cpp/emitterdef.h"
@@ -16,175 +17,198 @@
#include <memory> #include <memory>
#include <stdexcept> #include <stdexcept>
namespace YAML namespace YAML {
{ struct FmtScope {
struct FmtScope { enum value { Local, Global }; }; enum value {
struct GroupType { enum value { None, Seq, Map }; }; Local,
struct FlowType { enum value { None, Flow, Block }; }; Global
};
};
struct GroupType {
enum value {
None,
Seq,
Map
};
};
struct FlowType {
enum value {
None,
Flow,
Block
};
};
class EmitterState class EmitterState {
{ public:
public: EmitterState();
EmitterState(); ~EmitterState();
~EmitterState();
// basic state checking // basic state checking
bool good() const { return m_isGood; } bool good() const { return m_isGood; }
const std::string GetLastError() const { return m_lastError; } const std::string GetLastError() const { return m_lastError; }
void SetError(const std::string& error) { m_isGood = false; m_lastError = error; } void SetError(const std::string& error) {
m_isGood = false;
m_lastError = error;
}
// node handling // node handling
void SetAnchor(); void SetAnchor();
void SetTag(); void SetTag();
void SetNonContent(); void SetNonContent();
void SetLongKey(); void SetLongKey();
void ForceFlow(); void ForceFlow();
void StartedDoc(); void StartedDoc();
void EndedDoc(); void EndedDoc();
void StartedScalar(); void StartedScalar();
void StartedGroup(GroupType::value type); void StartedGroup(GroupType::value type);
void EndedGroup(GroupType::value type); void EndedGroup(GroupType::value type);
EmitterNodeType::value NextGroupType(GroupType::value type) const; EmitterNodeType::value NextGroupType(GroupType::value type) const;
EmitterNodeType::value CurGroupNodeType() const; EmitterNodeType::value CurGroupNodeType() const;
GroupType::value CurGroupType() const; GroupType::value CurGroupType() const;
FlowType::value CurGroupFlowType() const; FlowType::value CurGroupFlowType() const;
int CurGroupIndent() const; int CurGroupIndent() const;
std::size_t CurGroupChildCount() const; std::size_t CurGroupChildCount() const;
bool CurGroupLongKey() const; bool CurGroupLongKey() const;
int LastIndent() const; int LastIndent() const;
int CurIndent() const { return m_curIndent; } int CurIndent() const { return m_curIndent; }
bool HasAnchor() const { return m_hasAnchor; } bool HasAnchor() const { return m_hasAnchor; }
bool HasTag() const { return m_hasTag; } bool HasTag() const { return m_hasTag; }
bool HasBegunNode() const { return m_hasAnchor || m_hasTag || m_hasNonContent; } bool HasBegunNode() const {
bool HasBegunContent() const { return m_hasAnchor || m_hasTag; } return m_hasAnchor || m_hasTag || m_hasNonContent;
}
bool HasBegunContent() const { return m_hasAnchor || m_hasTag; }
void ClearModifiedSettings(); void ClearModifiedSettings();
// formatters // formatters
void SetLocalValue(EMITTER_MANIP value); void SetLocalValue(EMITTER_MANIP value);
bool SetOutputCharset(EMITTER_MANIP value, FmtScope::value scope); bool SetOutputCharset(EMITTER_MANIP value, FmtScope::value scope);
EMITTER_MANIP GetOutputCharset() const { return m_charset.get(); } EMITTER_MANIP GetOutputCharset() const { return m_charset.get(); }
bool SetStringFormat(EMITTER_MANIP value, FmtScope::value scope); bool SetStringFormat(EMITTER_MANIP value, FmtScope::value scope);
EMITTER_MANIP GetStringFormat() const { return m_strFmt.get(); } EMITTER_MANIP GetStringFormat() const { return m_strFmt.get(); }
bool SetBoolFormat(EMITTER_MANIP value, FmtScope::value scope); bool SetBoolFormat(EMITTER_MANIP value, FmtScope::value scope);
EMITTER_MANIP GetBoolFormat() const { return m_boolFmt.get(); } EMITTER_MANIP GetBoolFormat() const { return m_boolFmt.get(); }
bool SetBoolLengthFormat(EMITTER_MANIP value, FmtScope::value scope); bool SetBoolLengthFormat(EMITTER_MANIP value, FmtScope::value scope);
EMITTER_MANIP GetBoolLengthFormat() const { return m_boolLengthFmt.get(); } EMITTER_MANIP GetBoolLengthFormat() const { return m_boolLengthFmt.get(); }
bool SetBoolCaseFormat(EMITTER_MANIP value, FmtScope::value scope); bool SetBoolCaseFormat(EMITTER_MANIP value, FmtScope::value scope);
EMITTER_MANIP GetBoolCaseFormat() const { return m_boolCaseFmt.get(); } EMITTER_MANIP GetBoolCaseFormat() const { return m_boolCaseFmt.get(); }
bool SetIntFormat(EMITTER_MANIP value, FmtScope::value scope); bool SetIntFormat(EMITTER_MANIP value, FmtScope::value scope);
EMITTER_MANIP GetIntFormat() const { return m_intFmt.get(); } EMITTER_MANIP GetIntFormat() const { return m_intFmt.get(); }
bool SetIndent(unsigned value, FmtScope::value scope); bool SetIndent(unsigned value, FmtScope::value scope);
int GetIndent() const { return m_indent.get(); } int GetIndent() const { return m_indent.get(); }
bool SetPreCommentIndent(unsigned value, FmtScope::value scope); bool SetPreCommentIndent(unsigned value, FmtScope::value scope);
int GetPreCommentIndent() const { return m_preCommentIndent.get(); } int GetPreCommentIndent() const { return m_preCommentIndent.get(); }
bool SetPostCommentIndent(unsigned value, FmtScope::value scope); bool SetPostCommentIndent(unsigned value, FmtScope::value scope);
int GetPostCommentIndent() const { return m_postCommentIndent.get(); } int GetPostCommentIndent() const { return m_postCommentIndent.get(); }
bool SetFlowType(GroupType::value groupType, EMITTER_MANIP value, FmtScope::value scope); bool SetFlowType(GroupType::value groupType, EMITTER_MANIP value,
EMITTER_MANIP GetFlowType(GroupType::value groupType) const; FmtScope::value scope);
EMITTER_MANIP GetFlowType(GroupType::value groupType) const;
bool SetMapKeyFormat(EMITTER_MANIP value, FmtScope::value scope); bool SetMapKeyFormat(EMITTER_MANIP value, FmtScope::value scope);
EMITTER_MANIP GetMapKeyFormat() const { return m_mapKeyFmt.get(); } EMITTER_MANIP GetMapKeyFormat() const { return m_mapKeyFmt.get(); }
bool SetFloatPrecision(int value, FmtScope::value scope); bool SetFloatPrecision(int value, FmtScope::value scope);
unsigned GetFloatPrecision() const { return m_floatPrecision.get(); } unsigned GetFloatPrecision() const { return m_floatPrecision.get(); }
bool SetDoublePrecision(int value, FmtScope::value scope); bool SetDoublePrecision(int value, FmtScope::value scope);
unsigned GetDoublePrecision() const { return m_doublePrecision.get(); } unsigned GetDoublePrecision() const { return m_doublePrecision.get(); }
private: private:
template <typename T> template <typename T>
void _Set(Setting<T>& fmt, T value, FmtScope::value scope); void _Set(Setting<T>& fmt, T value, FmtScope::value scope);
void StartedNode(); void StartedNode();
private: private:
// basic state ok? // basic state ok?
bool m_isGood; bool m_isGood;
std::string m_lastError; std::string m_lastError;
// other state // other state
Setting<EMITTER_MANIP> m_charset; Setting<EMITTER_MANIP> m_charset;
Setting<EMITTER_MANIP> m_strFmt; Setting<EMITTER_MANIP> m_strFmt;
Setting<EMITTER_MANIP> m_boolFmt; Setting<EMITTER_MANIP> m_boolFmt;
Setting<EMITTER_MANIP> m_boolLengthFmt; Setting<EMITTER_MANIP> m_boolLengthFmt;
Setting<EMITTER_MANIP> m_boolCaseFmt; Setting<EMITTER_MANIP> m_boolCaseFmt;
Setting<EMITTER_MANIP> m_intFmt; Setting<EMITTER_MANIP> m_intFmt;
Setting<unsigned> m_indent; Setting<unsigned> m_indent;
Setting<unsigned> m_preCommentIndent, m_postCommentIndent; Setting<unsigned> m_preCommentIndent, m_postCommentIndent;
Setting<EMITTER_MANIP> m_seqFmt; Setting<EMITTER_MANIP> m_seqFmt;
Setting<EMITTER_MANIP> m_mapFmt; Setting<EMITTER_MANIP> m_mapFmt;
Setting<EMITTER_MANIP> m_mapKeyFmt; Setting<EMITTER_MANIP> m_mapKeyFmt;
Setting<int> m_floatPrecision; Setting<int> m_floatPrecision;
Setting<int> m_doublePrecision; Setting<int> m_doublePrecision;
SettingChanges m_modifiedSettings; SettingChanges m_modifiedSettings;
SettingChanges m_globalModifiedSettings; SettingChanges m_globalModifiedSettings;
struct Group { struct Group {
explicit Group(GroupType::value type_): type(type_), indent(0), childCount(0), longKey(false) {} explicit Group(GroupType::value type_)
: type(type_), indent(0), childCount(0), longKey(false) {}
GroupType::value type; GroupType::value type;
FlowType::value flowType; FlowType::value flowType;
int indent; int indent;
std::size_t childCount; std::size_t childCount;
bool longKey; bool longKey;
SettingChanges modifiedSettings; SettingChanges modifiedSettings;
EmitterNodeType::value NodeType() const { EmitterNodeType::value NodeType() const {
if(type == GroupType::Seq) { if (type == GroupType::Seq) {
if(flowType == FlowType::Flow) if (flowType == FlowType::Flow)
return EmitterNodeType::FlowSeq; return EmitterNodeType::FlowSeq;
else else
return EmitterNodeType::BlockSeq; return EmitterNodeType::BlockSeq;
} else { } else {
if(flowType == FlowType::Flow) if (flowType == FlowType::Flow)
return EmitterNodeType::FlowMap; return EmitterNodeType::FlowMap;
else else
return EmitterNodeType::BlockMap; return EmitterNodeType::BlockMap;
} }
// can't get here // can't get here
assert(false); assert(false);
return EmitterNodeType::None; return EmitterNodeType::None;
} }
}; };
ptr_stack<Group> m_groups; ptr_stack<Group> m_groups;
unsigned m_curIndent; unsigned m_curIndent;
bool m_hasAnchor; bool m_hasAnchor;
bool m_hasTag; bool m_hasTag;
bool m_hasNonContent; bool m_hasNonContent;
std::size_t m_docCount; std::size_t m_docCount;
}; };
template <typename T> template <typename T>
void EmitterState::_Set(Setting<T>& fmt, T value, FmtScope::value scope) { void EmitterState::_Set(Setting<T>& fmt, T value, FmtScope::value scope) {
switch(scope) { switch (scope) {
case FmtScope::Local: case FmtScope::Local:
m_modifiedSettings.push(fmt.set(value)); m_modifiedSettings.push(fmt.set(value));
break; break;
case FmtScope::Global: case FmtScope::Global:
fmt.set(value); fmt.set(value);
m_globalModifiedSettings.push(fmt.set(value)); // this pushes an identity set, so when we restore, m_globalModifiedSettings.push(
// it restores to the value here, and not the previous one fmt.set(value)); // this pushes an identity set, so when we restore,
break; // it restores to the value here, and not the previous one
default: break;
assert(false); default:
} assert(false);
} }
}
} }
#endif // EMITTERSTATE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #endif // EMITTERSTATE_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -7,418 +7,436 @@
#include <sstream> #include <sstream>
#include <iomanip> #include <iomanip>
namespace YAML namespace YAML {
{ namespace Utils {
namespace Utils namespace {
{ enum {
namespace { REPLACEMENT_CHARACTER = 0xFFFD
enum {REPLACEMENT_CHARACTER = 0xFFFD}; };
bool IsAnchorChar(int ch) { // test for ns-anchor-char bool IsAnchorChar(int ch) { // test for ns-anchor-char
switch (ch) { switch (ch) {
case ',': case '[': case ']': case '{': case '}': // c-flow-indicator case ',':
case ' ': case '\t': // s-white case '[':
case 0xFEFF: // c-byte-order-mark case ']':
case 0xA: case 0xD: // b-char case '{':
return false; case '}': // c-flow-indicator
case 0x85: case ' ':
return true; 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) if (ch < 0x20)
return false; return false;
if (ch < 0x7E) if (ch < 0x7E)
return true; return true;
if (ch < 0xA0) if (ch < 0xA0)
return false; return false;
if (ch >= 0xD800 && ch <= 0xDFFF) if (ch >= 0xD800 && ch <= 0xDFFF)
return false; return false;
if ((ch & 0xFFFE) == 0xFFFE) if ((ch & 0xFFFE) == 0xFFFE)
return false; return false;
if ((ch >= 0xFDD0) && (ch <= 0xFDEF)) if ((ch >= 0xFDD0) && (ch <= 0xFDEF))
return false; return false;
if (ch > 0x10FFFF) if (ch > 0x10FFFF)
return false; return false;
return true; 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_wrapper& 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, FlowType::value flowType, bool allowOnlyAscii) {
if(str.empty())
return false;
// first check the start
const RegEx& start = (flowType == FlowType::Flow ? 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 = (flowType == FlowType::Flow ? 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 && (0x80 <= static_cast<unsigned char>(buffer[0])))
return false;
++buffer;
}
return true;
}
bool IsValidSingleQuotedScalar(const std::string& str, bool escapeNonAscii)
{
// TODO: check for non-printable characters?
for(std::size_t i=0;i<str.size();i++) {
if(escapeNonAscii && (0x80 <= static_cast<unsigned char>(str[i])))
return false;
if(str[i] == '\n')
return false;
}
return true;
}
bool IsValidLiteralScalar(const std::string& str, FlowType::value flowType, bool escapeNonAscii)
{
if(flowType == FlowType::Flow)
return false;
// TODO: check for non-printable characters?
for(std::size_t i=0;i<str.size();i++) {
if(escapeNonAscii && (0x80 <= static_cast<unsigned char>(str[i])))
return false;
}
return true;
}
void WriteDoubleQuoteEscapeSequence(ostream_wrapper& out, int codePoint) {
static const char hexDigits[] = "0123456789abcdef";
out << "\\";
int digits = 8;
if(codePoint < 0xFF) {
out << "x";
digits = 2;
} else if(codePoint < 0xFFFF) {
out << "u";
digits = 4;
} else {
out << "U";
digits = 8;
}
// Write digits into the escape sequence
for (; digits > 0; --digits)
out << hexDigits[(codePoint >> (4 * (digits - 1))) & 0xF];
}
bool WriteAliasName(ostream_wrapper& 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;
}
}
StringFormat::value ComputeStringFormat(const std::string& str, EMITTER_MANIP strFormat, FlowType::value flowType, bool escapeNonAscii)
{
switch(strFormat) {
case Auto:
if(IsValidPlainScalar(str, flowType, escapeNonAscii))
return StringFormat::Plain;
return StringFormat::DoubleQuoted;
case SingleQuoted:
if(IsValidSingleQuotedScalar(str, escapeNonAscii))
return StringFormat::SingleQuoted;
return StringFormat::DoubleQuoted;
case DoubleQuoted:
return StringFormat::DoubleQuoted;
case Literal:
if(IsValidLiteralScalar(str, flowType, escapeNonAscii))
return StringFormat::Literal;
return StringFormat::DoubleQuoted;
default:
break;
}
return StringFormat::DoubleQuoted;
}
bool WriteSingleQuotedString(ostream_wrapper& 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_wrapper& out, const std::string& str, bool escapeNonAscii)
{
out << "\"";
int codePoint;
for(std::string::const_iterator i = str.begin();
GetNextCodePointAndAdvance(codePoint, i, str.end());
)
{
switch(codePoint) {
case '\"': out << "\\\""; break;
case '\\': out << "\\\\"; break;
case '\n': out << "\\n"; break;
case '\t': out << "\\t"; break;
case '\r': out << "\\r"; break;
case '\b': out << "\\b"; break;
default:
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_wrapper& 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 WriteChar(ostream_wrapper& out, char ch)
{
if(('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z'))
out << ch;
else if((0x20 <= ch && ch <= 0x7e) || ch == ' ')
out << "\"" << ch << "\"";
else if(ch == '\t')
out << "\"\\t\"";
else if(ch == '\n')
out << "\"\\n\"";
else if(ch == '\b')
out << "\"\\b\"";
else {
out << "\"";
WriteDoubleQuoteEscapeSequence(out, ch);
out << "\"";
}
return true;
}
bool WriteComment(ostream_wrapper& out, const std::string& str, int postCommentIndent)
{
const unsigned curIndent = out.col();
out << "#" << Indentation(postCommentIndent);
out.set_comment();
int codePoint;
for(std::string::const_iterator i = str.begin();
GetNextCodePointAndAdvance(codePoint, i, str.end());
)
{
if(codePoint == '\n') {
out << "\n" << IndentTo(curIndent) << "#" << Indentation(postCommentIndent);
out.set_comment();
} else {
WriteCodePoint(out, codePoint);
}
}
return true;
}
bool WriteAlias(ostream_wrapper& out, const std::string& str)
{
out << "*";
return WriteAliasName(out, str);
}
bool WriteAnchor(ostream_wrapper& out, const std::string& str)
{
out << "&";
return WriteAliasName(out, str);
}
bool WriteTag(ostream_wrapper& out, const std::string& str, bool verbatim)
{
out << (verbatim ? "!<" : "!");
StringCharSource buffer(str.c_str(), str.size());
const RegEx& reValid = verbatim ? Exp::URI() : Exp::Tag();
while(buffer) {
int n = reValid.Match(buffer);
if(n <= 0)
return false;
while(--n >= 0) {
out << buffer[0];
++buffer;
}
}
if (verbatim)
out << ">";
return true;
}
bool WriteTagWithPrefix(ostream_wrapper& out, const std::string& prefix, const std::string& tag)
{
out << "!";
StringCharSource prefixBuffer(prefix.c_str(), prefix.size());
while(prefixBuffer) {
int n = Exp::URI().Match(prefixBuffer);
if(n <= 0)
return false;
while(--n >= 0) {
out << prefixBuffer[0];
++prefixBuffer;
}
}
out << "!";
StringCharSource tagBuffer(tag.c_str(), tag.size());
while(tagBuffer) {
int n = Exp::Tag().Match(tagBuffer);
if(n <= 0)
return false;
while(--n >= 0) {
out << tagBuffer[0];
++tagBuffer;
}
}
return true;
}
bool WriteBinary(ostream_wrapper& out, const Binary& binary)
{
WriteDoubleQuotedString(out, EncodeBase64(binary.data(), binary.size()), 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_wrapper& 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, FlowType::value flowType,
bool allowOnlyAscii) {
if (str.empty())
return false;
// first check the start
const RegEx& start = (flowType == FlowType::Flow ? 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 = (flowType == FlowType::Flow ? 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 && (0x80 <= static_cast<unsigned char>(buffer[0])))
return false;
++buffer;
}
return true;
}
bool IsValidSingleQuotedScalar(const std::string& str, bool escapeNonAscii) {
// TODO: check for non-printable characters?
for (std::size_t i = 0; i < str.size(); i++) {
if (escapeNonAscii && (0x80 <= static_cast<unsigned char>(str[i])))
return false;
if (str[i] == '\n')
return false;
}
return true;
}
bool IsValidLiteralScalar(const std::string& str, FlowType::value flowType,
bool escapeNonAscii) {
if (flowType == FlowType::Flow)
return false;
// TODO: check for non-printable characters?
for (std::size_t i = 0; i < str.size(); i++) {
if (escapeNonAscii && (0x80 <= static_cast<unsigned char>(str[i])))
return false;
}
return true;
}
void WriteDoubleQuoteEscapeSequence(ostream_wrapper& out, int codePoint) {
static const char hexDigits[] = "0123456789abcdef";
out << "\\";
int digits = 8;
if (codePoint < 0xFF) {
out << "x";
digits = 2;
} else if (codePoint < 0xFFFF) {
out << "u";
digits = 4;
} else {
out << "U";
digits = 8;
}
// Write digits into the escape sequence
for (; digits > 0; --digits)
out << hexDigits[(codePoint >> (4 * (digits - 1))) & 0xF];
}
bool WriteAliasName(ostream_wrapper& 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;
}
}
StringFormat::value ComputeStringFormat(const std::string& str,
EMITTER_MANIP strFormat,
FlowType::value flowType,
bool escapeNonAscii) {
switch (strFormat) {
case Auto:
if (IsValidPlainScalar(str, flowType, escapeNonAscii))
return StringFormat::Plain;
return StringFormat::DoubleQuoted;
case SingleQuoted:
if (IsValidSingleQuotedScalar(str, escapeNonAscii))
return StringFormat::SingleQuoted;
return StringFormat::DoubleQuoted;
case DoubleQuoted:
return StringFormat::DoubleQuoted;
case Literal:
if (IsValidLiteralScalar(str, flowType, escapeNonAscii))
return StringFormat::Literal;
return StringFormat::DoubleQuoted;
default:
break;
}
return StringFormat::DoubleQuoted;
}
bool WriteSingleQuotedString(ostream_wrapper& 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_wrapper& out, const std::string& str,
bool escapeNonAscii) {
out << "\"";
int codePoint;
for (std::string::const_iterator i = str.begin();
GetNextCodePointAndAdvance(codePoint, i, str.end());) {
switch (codePoint) {
case '\"':
out << "\\\"";
break;
case '\\':
out << "\\\\";
break;
case '\n':
out << "\\n";
break;
case '\t':
out << "\\t";
break;
case '\r':
out << "\\r";
break;
case '\b':
out << "\\b";
break;
default:
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_wrapper& 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 WriteChar(ostream_wrapper& out, char ch) {
if (('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z'))
out << ch;
else if ((0x20 <= ch && ch <= 0x7e) || ch == ' ')
out << "\"" << ch << "\"";
else if (ch == '\t')
out << "\"\\t\"";
else if (ch == '\n')
out << "\"\\n\"";
else if (ch == '\b')
out << "\"\\b\"";
else {
out << "\"";
WriteDoubleQuoteEscapeSequence(out, ch);
out << "\"";
}
return true;
}
bool WriteComment(ostream_wrapper& out, const std::string& str,
int postCommentIndent) {
const unsigned curIndent = out.col();
out << "#" << Indentation(postCommentIndent);
out.set_comment();
int codePoint;
for (std::string::const_iterator i = str.begin();
GetNextCodePointAndAdvance(codePoint, i, str.end());) {
if (codePoint == '\n') {
out << "\n" << IndentTo(curIndent) << "#"
<< Indentation(postCommentIndent);
out.set_comment();
} else {
WriteCodePoint(out, codePoint);
}
}
return true;
}
bool WriteAlias(ostream_wrapper& out, const std::string& str) {
out << "*";
return WriteAliasName(out, str);
}
bool WriteAnchor(ostream_wrapper& out, const std::string& str) {
out << "&";
return WriteAliasName(out, str);
}
bool WriteTag(ostream_wrapper& out, const std::string& str, bool verbatim) {
out << (verbatim ? "!<" : "!");
StringCharSource buffer(str.c_str(), str.size());
const RegEx& reValid = verbatim ? Exp::URI() : Exp::Tag();
while (buffer) {
int n = reValid.Match(buffer);
if (n <= 0)
return false;
while (--n >= 0) {
out << buffer[0];
++buffer;
}
}
if (verbatim)
out << ">";
return true;
}
bool WriteTagWithPrefix(ostream_wrapper& out, const std::string& prefix,
const std::string& tag) {
out << "!";
StringCharSource prefixBuffer(prefix.c_str(), prefix.size());
while (prefixBuffer) {
int n = Exp::URI().Match(prefixBuffer);
if (n <= 0)
return false;
while (--n >= 0) {
out << prefixBuffer[0];
++prefixBuffer;
}
}
out << "!";
StringCharSource tagBuffer(tag.c_str(), tag.size());
while (tagBuffer) {
int n = Exp::Tag().Match(tagBuffer);
if (n <= 0)
return false;
while (--n >= 0) {
out << tagBuffer[0];
++tagBuffer;
}
}
return true;
}
bool WriteBinary(ostream_wrapper& out, const Binary& binary) {
WriteDoubleQuotedString(out, EncodeBase64(binary.data(), binary.size()),
false);
return true;
}
}
}

View File

@@ -1,36 +1,49 @@
#ifndef EMITTERUTILS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef EMITTERUTILS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define EMITTERUTILS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define EMITTERUTILS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
#include "emitterstate.h" #include "emitterstate.h"
#include "yaml-cpp/ostream_wrapper.h" #include "yaml-cpp/ostream_wrapper.h"
#include <string> #include <string>
namespace YAML namespace YAML {
{ class Binary;
class Binary;
struct StringFormat { enum value { Plain, SingleQuoted, DoubleQuoted, Literal }; }; struct StringFormat {
enum value {
Plain,
SingleQuoted,
DoubleQuoted,
Literal
};
};
namespace Utils namespace Utils {
{ StringFormat::value ComputeStringFormat(const std::string& str,
StringFormat::value ComputeStringFormat(const std::string& str, EMITTER_MANIP strFormat, FlowType::value flowType, bool escapeNonAscii); EMITTER_MANIP strFormat,
FlowType::value flowType,
bool escapeNonAscii);
bool WriteSingleQuotedString(ostream_wrapper& out, const std::string& str); bool WriteSingleQuotedString(ostream_wrapper& out, const std::string& str);
bool WriteDoubleQuotedString(ostream_wrapper& out, const std::string& str, bool escapeNonAscii); bool WriteDoubleQuotedString(ostream_wrapper& out, const std::string& str,
bool WriteLiteralString(ostream_wrapper& out, const std::string& str, int indent); bool escapeNonAscii);
bool WriteChar(ostream_wrapper& out, char ch); bool WriteLiteralString(ostream_wrapper& out, const std::string& str,
bool WriteComment(ostream_wrapper& out, const std::string& str, int postCommentIndent); int indent);
bool WriteAlias(ostream_wrapper& out, const std::string& str); bool WriteChar(ostream_wrapper& out, char ch);
bool WriteAnchor(ostream_wrapper& out, const std::string& str); bool WriteComment(ostream_wrapper& out, const std::string& str,
bool WriteTag(ostream_wrapper& out, const std::string& str, bool verbatim); int postCommentIndent);
bool WriteTagWithPrefix(ostream_wrapper& out, const std::string& prefix, const std::string& tag); bool WriteAlias(ostream_wrapper& out, const std::string& str);
bool WriteBinary(ostream_wrapper& out, const Binary& binary); bool WriteAnchor(ostream_wrapper& out, const std::string& str);
} bool WriteTag(ostream_wrapper& out, const std::string& str, bool verbatim);
bool WriteTagWithPrefix(ostream_wrapper& out, const std::string& prefix,
const std::string& tag);
bool WriteBinary(ostream_wrapper& out, const Binary& binary);
}
} }
#endif // EMITTERUTILS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #endif // EMITTERUTILS_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -2,112 +2,129 @@
#include "yaml-cpp/exceptions.h" #include "yaml-cpp/exceptions.h"
#include <sstream> #include <sstream>
namespace YAML namespace YAML {
{ namespace Exp {
namespace Exp unsigned ParseHex(const std::string& str, const Mark& mark) {
{ unsigned value = 0;
unsigned ParseHex(const std::string& str, const Mark& mark) for (std::size_t i = 0; i < str.size(); i++) {
{ char ch = str[i];
unsigned value = 0; int digit = 0;
for(std::size_t i=0;i<str.size();i++) { if ('a' <= ch && ch <= 'f')
char ch = str[i]; digit = ch - 'a' + 10;
int digit = 0; else if ('A' <= ch && ch <= 'F')
if('a' <= ch && ch <= 'f') digit = ch - 'A' + 10;
digit = ch - 'a' + 10; else if ('0' <= ch && ch <= '9')
else if('A' <= ch && ch <= 'F') digit = ch - '0';
digit = ch - 'A' + 10; else
else if('0' <= ch && ch <= '9') throw ParserException(mark, ErrorMsg::INVALID_HEX);
digit = ch - '0';
else
throw ParserException(mark, ErrorMsg::INVALID_HEX);
value = (value << 4) + digit; value = (value << 4) + digit;
} }
return value; return value;
} }
std::string Str(unsigned ch) std::string Str(unsigned ch) { return std::string(1, static_cast<char>(ch)); }
{
return std::string(1, static_cast<char>(ch)); // Escape
} // . Translates the next 'codeLength' characters into a hex number and returns
// the result.
// Escape // . Throws if it's not actually hex.
// . Translates the next 'codeLength' characters into a hex number and returns the result. std::string Escape(Stream& in, int codeLength) {
// . Throws if it's not actually hex. // grab string
std::string Escape(Stream& in, int codeLength) std::string str;
{ for (int i = 0; i < codeLength; i++)
// grab string str += in.get();
std::string str;
for(int i=0;i<codeLength;i++) // get the value
str += in.get(); unsigned value = ParseHex(str, in.mark());
// get the value // legal unicode?
unsigned value = ParseHex(str, in.mark()); if ((value >= 0xD800 && value <= 0xDFFF) || value > 0x10FFFF) {
std::stringstream msg;
// legal unicode? msg << ErrorMsg::INVALID_UNICODE << value;
if((value >= 0xD800 && value <= 0xDFFF) || value > 0x10FFFF) { throw ParserException(in.mark(), msg.str());
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);
// now break it up into chars else if (value <= 0x7FF)
if(value <= 0x7F) return Str(0xC0 + (value >> 6)) + Str(0x80 + (value & 0x3F));
return Str(value); else if (value <= 0xFFFF)
else if(value <= 0x7FF) return Str(0xE0 + (value >> 12)) + Str(0x80 + ((value >> 6) & 0x3F)) +
return Str(0xC0 + (value >> 6)) + Str(0x80 + (value & 0x3F)); Str(0x80 + (value & 0x3F));
else if(value <= 0xFFFF) else
return Str(0xE0 + (value >> 12)) + Str(0x80 + ((value >> 6) & 0x3F)) + Str(0x80 + (value & 0x3F)); return Str(0xF0 + (value >> 18)) + Str(0x80 + ((value >> 12) & 0x3F)) +
else Str(0x80 + ((value >> 6) & 0x3F)) + Str(0x80 + (value & 0x3F));
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
// Escape // quote)
// . Escapes the sequence starting 'in' (it must begin with a '\' or single quote) // and returns the result.
// and returns the result. // . Throws if it's an unknown escape character.
// . Throws if it's an unknown escape character. std::string Escape(Stream& in) {
std::string Escape(Stream& in) // eat slash
{ char escape = in.get();
// eat slash
char escape = in.get(); // switch on escape character
char ch = in.get();
// switch on escape character
char ch = in.get(); // first do single quote, since it's easier
if (escape == '\'' && ch == '\'')
// first do single quote, since it's easier return "\'";
if(escape == '\'' && ch == '\'')
return "\'"; // now do the slash (we're not gonna check if it's a slash - you better pass
// one!)
// now do the slash (we're not gonna check if it's a slash - you better pass one!) switch (ch) {
switch(ch) { case '0':
case '0': return std::string(1, '\x00'); return std::string(1, '\x00');
case 'a': return "\x07"; case 'a':
case 'b': return "\x08"; return "\x07";
case 't': case 'b':
case '\t': return "\x09"; return "\x08";
case 'n': return "\x0A"; case 't':
case 'v': return "\x0B"; case '\t':
case 'f': return "\x0C"; return "\x09";
case 'r': return "\x0D"; case 'n':
case 'e': return "\x1B"; return "\x0A";
case ' ': return "\x20"; case 'v':
case '\"': return "\""; return "\x0B";
case '\'': return "\'"; case 'f':
case '\\': return "\\"; return "\x0C";
case '/': return "/"; case 'r':
case 'N': return "\x85"; return "\x0D";
case '_': return "\xA0"; case 'e':
case 'L': return "\xE2\x80\xA8"; // LS (#x2028) return "\x1B";
case 'P': return "\xE2\x80\xA9"; // PS (#x2029) case ' ':
case 'x': return Escape(in, 2); return "\x20";
case 'u': return Escape(in, 4); case '\"':
case 'U': return Escape(in, 8); return "\"";
} case '\'':
return "\'";
std::stringstream msg; case '\\':
throw ParserException(in.mark(), std::string(ErrorMsg::INVALID_ESCAPE) + ch); 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(), std::string(ErrorMsg::INVALID_ESCAPE) + ch);
}
}
} }

376
src/exp.h
View File

@@ -1,196 +1,208 @@
#ifndef EXP_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef EXP_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define EXP_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define EXP_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
#include "regex.h" #include "regex.h"
#include <string> #include <string>
#include <ios> #include <ios>
#include "stream.h" #include "stream.h"
namespace YAML namespace YAML {
{ ////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////// // Here we store a bunch of expressions for matching different parts of the
// Here we store a bunch of expressions for matching different parts of the file. // file.
namespace Exp namespace Exp {
{ // misc
// misc inline const RegEx& Space() {
inline const RegEx& Space() { static const RegEx e = RegEx(' ');
static const RegEx e = RegEx(' '); return e;
return e; }
} inline const RegEx& Tab() {
inline const RegEx& Tab() { static const RegEx e = RegEx('\t');
static const RegEx e = RegEx('\t'); return e;
return e; }
} inline const RegEx& Blank() {
inline const RegEx& Blank() { static const RegEx e = Space() || Tab();
static const RegEx e = Space() || Tab(); return e;
return e; }
} inline const RegEx& Break() {
inline const RegEx& Break() { static const RegEx e = RegEx('\n') || RegEx("\r\n");
static const RegEx e = RegEx('\n') || RegEx("\r\n"); return e;
return e; }
} inline const RegEx& BlankOrBreak() {
inline const RegEx& BlankOrBreak() { static const RegEx e = Blank() || Break();
static const RegEx e = Blank() || Break(); return e;
return e; }
} inline const RegEx& Digit() {
inline const RegEx& Digit() { static const RegEx e = RegEx('0', '9');
static const RegEx e = RegEx('0', '9'); return e;
return e; }
} inline const RegEx& Alpha() {
inline const RegEx& Alpha() { static const RegEx e = RegEx('a', 'z') || RegEx('A', 'Z');
static const RegEx e = RegEx('a', 'z') || RegEx('A', 'Z'); return e;
return e; }
} inline const RegEx& AlphaNumeric() {
inline const RegEx& AlphaNumeric() { static const RegEx e = Alpha() || Digit();
static const RegEx e = Alpha() || Digit(); return e;
return e; }
} inline const RegEx& Word() {
inline const RegEx& Word() { static const RegEx e = AlphaNumeric() || RegEx('-');
static const RegEx e = AlphaNumeric() || RegEx('-'); return e;
return e; }
} inline const RegEx& Hex() {
inline const RegEx& Hex() { static const RegEx e = Digit() || RegEx('A', 'F') || RegEx('a', 'f');
static const RegEx e = Digit() || RegEx('A', 'F') || RegEx('a', 'f'); return e;
return e; }
} // Valid Unicode code points that are not part of c-printable (YAML 1.2, sec.
// Valid Unicode code points that are not part of c-printable (YAML 1.2, sec. 5.1) // 5.1)
inline const RegEx& NotPrintable() { inline const RegEx& NotPrintable() {
static const RegEx e = RegEx(0) || static const RegEx e =
RegEx("\x01\x02\x03\x04\x05\x06\x07\x08\x0B\x0C\x7F", REGEX_OR) || RegEx(0) ||
RegEx(0x0E, 0x1F) || RegEx("\x01\x02\x03\x04\x05\x06\x07\x08\x0B\x0C\x7F", REGEX_OR) ||
(RegEx('\xC2') + (RegEx('\x80', '\x84') || RegEx('\x86', '\x9F'))); RegEx(0x0E, 0x1F) ||
return e; (RegEx('\xC2') + (RegEx('\x80', '\x84') || RegEx('\x86', '\x9F')));
} return e;
inline const RegEx& Utf8_ByteOrderMark() { }
static const RegEx e = RegEx("\xEF\xBB\xBF"); inline const RegEx& Utf8_ByteOrderMark() {
return e; 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('?') + BlankOrBreak();
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& Anchor() {
static const RegEx e = !(RegEx("[]{},", REGEX_OR) || BlankOrBreak());
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) + (BlankOrBreak() || RegEx())));
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(",]}", 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 // 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('?') + BlankOrBreak();
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& Anchor() {
static const RegEx e = !(RegEx("[]{},", REGEX_OR) || BlankOrBreak());
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) + (BlankOrBreak() || RegEx())));
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(",]}", 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

View File

@@ -1,38 +1,39 @@
#ifndef INDENTATION_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef INDENTATION_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define INDENTATION_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define INDENTATION_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
#include "yaml-cpp/ostream_wrapper.h" #include "yaml-cpp/ostream_wrapper.h"
#include <iostream> #include <iostream>
namespace YAML namespace YAML {
{ struct Indentation {
struct Indentation { Indentation(unsigned n_) : n(n_) {}
Indentation(unsigned n_): n(n_) {} unsigned n;
unsigned n; };
};
inline ostream_wrapper& operator << (ostream_wrapper& out, const Indentation& indent) { inline ostream_wrapper& operator<<(ostream_wrapper& out,
for(unsigned i=0;i<indent.n;i++) const Indentation& indent) {
out << ' '; for (unsigned i = 0; i < indent.n; i++)
return out; out << ' ';
} return out;
struct IndentTo {
IndentTo(unsigned n_): n(n_) {}
unsigned n;
};
inline ostream_wrapper& operator << (ostream_wrapper& out, const IndentTo& indent) {
while(out.col() < indent.n)
out << ' ';
return out;
}
} }
struct IndentTo {
IndentTo(unsigned n_) : n(n_) {}
unsigned n;
};
#endif // INDENTATION_H_62B23520_7C8E_11DE_8A39_0800200C9A66 inline ostream_wrapper& operator<<(ostream_wrapper& out,
const IndentTo& indent) {
while (out.col() < indent.n)
out << ' ';
return out;
}
}
#endif // INDENTATION_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,6 +1,5 @@
#include "yaml-cpp/null.h" #include "yaml-cpp/null.h"
namespace YAML namespace YAML {
{ _Null Null;
_Null Null;
} }

View File

@@ -9,133 +9,119 @@
#include <sstream> #include <sstream>
#include <cstdio> #include <cstdio>
namespace YAML namespace YAML {
{ Parser::Parser() {}
Parser::Parser()
{
}
Parser::Parser(std::istream& in) Parser::Parser(std::istream& in) { Load(in); }
{
Load(in);
}
Parser::~Parser() Parser::~Parser() {}
{
}
Parser::operator bool() const Parser::operator bool() const {
{ return m_pScanner.get() && !m_pScanner->empty();
return m_pScanner.get() && !m_pScanner->empty(); }
}
void Parser::Load(std::istream& in) {
void Parser::Load(std::istream& in) m_pScanner.reset(new Scanner(in));
{ m_pDirectives.reset(new Directives);
m_pScanner.reset(new Scanner(in)); }
m_pDirectives.reset(new Directives);
} // HandleNextDocument
// . Handles the next document
// HandleNextDocument // . Throws a ParserException on error.
// . Handles the next document // . Returns false if there are no more documents
// . Throws a ParserException on error. bool Parser::HandleNextDocument(EventHandler& eventHandler) {
// . Returns false if there are no more documents if (!m_pScanner.get())
bool Parser::HandleNextDocument(EventHandler& eventHandler) return false;
{
if(!m_pScanner.get()) ParseDirectives();
return false; if (m_pScanner->empty())
return false;
ParseDirectives();
if(m_pScanner->empty()) SingleDocParser sdp(*m_pScanner, *m_pDirectives);
return false; sdp.HandleDocument(eventHandler);
return true;
SingleDocParser sdp(*m_pScanner, *m_pDirectives); }
sdp.HandleDocument(eventHandler);
return true; // ParseDirectives
} // . Reads any directives that are next in the queue.
void Parser::ParseDirectives() {
// ParseDirectives bool readDirective = false;
// . Reads any directives that are next in the queue.
void Parser::ParseDirectives() while (1) {
{ if (m_pScanner->empty())
bool readDirective = false; break;
while(1) { Token& token = m_pScanner->peek();
if(m_pScanner->empty()) if (token.type != Token::DIRECTIVE)
break; break;
Token& token = m_pScanner->peek(); // we keep the directives from the last document if none are specified;
if(token.type != Token::DIRECTIVE) // but if any directives are specific, then we reset them
break; if (!readDirective)
m_pDirectives.reset(new Directives);
// we keep the directives from the last document if none are specified;
// but if any directives are specific, then we reset them readDirective = true;
if(!readDirective) HandleDirective(token);
m_pDirectives.reset(new Directives); m_pScanner->pop();
}
readDirective = true; }
HandleDirective(token);
m_pScanner->pop(); void Parser::HandleDirective(const Token& token) {
} if (token.value == "YAML")
} HandleYamlDirective(token);
else if (token.value == "TAG")
void Parser::HandleDirective(const Token& token) HandleTagDirective(token);
{ }
if(token.value == "YAML")
HandleYamlDirective(token); // HandleYamlDirective
else if(token.value == "TAG") // . Should be of the form 'major.minor' (like a version number)
HandleTagDirective(token); void Parser::HandleYamlDirective(const Token& token) {
} if (token.params.size() != 1)
throw ParserException(token.mark, ErrorMsg::YAML_DIRECTIVE_ARGS);
// HandleYamlDirective
// . Should be of the form 'major.minor' (like a version number) if (!m_pDirectives->version.isDefault)
void Parser::HandleYamlDirective(const Token& token) throw ParserException(token.mark, ErrorMsg::REPEATED_YAML_DIRECTIVE);
{
if(token.params.size() != 1) std::stringstream str(token.params[0]);
throw ParserException(token.mark, ErrorMsg::YAML_DIRECTIVE_ARGS); str >> m_pDirectives->version.major;
str.get();
if(!m_pDirectives->version.isDefault) str >> m_pDirectives->version.minor;
throw ParserException(token.mark, ErrorMsg::REPEATED_YAML_DIRECTIVE); if (!str || str.peek() != EOF)
throw ParserException(
std::stringstream str(token.params[0]); token.mark, std::string(ErrorMsg::YAML_VERSION) + token.params[0]);
str >> m_pDirectives->version.major;
str.get(); if (m_pDirectives->version.major > 1)
str >> m_pDirectives->version.minor; throw ParserException(token.mark, ErrorMsg::YAML_MAJOR_VERSION);
if(!str || str.peek() != EOF)
throw ParserException(token.mark, std::string(ErrorMsg::YAML_VERSION) + token.params[0]); m_pDirectives->version.isDefault = false;
// TODO: warning on major == 1, minor > 2?
if(m_pDirectives->version.major > 1) }
throw ParserException(token.mark, ErrorMsg::YAML_MAJOR_VERSION);
// HandleTagDirective
m_pDirectives->version.isDefault = false; // . Should be of the form 'handle prefix', where 'handle' is converted to
// TODO: warning on major == 1, minor > 2? // 'prefix' in the file.
} void Parser::HandleTagDirective(const Token& token) {
if (token.params.size() != 2)
// HandleTagDirective throw ParserException(token.mark, ErrorMsg::TAG_DIRECTIVE_ARGS);
// . Should be of the form 'handle prefix', where 'handle' is converted to 'prefix' in the file.
void Parser::HandleTagDirective(const Token& token) const std::string& handle = token.params[0];
{ const std::string& prefix = token.params[1];
if(token.params.size() != 2) if (m_pDirectives->tags.find(handle) != m_pDirectives->tags.end())
throw ParserException(token.mark, ErrorMsg::TAG_DIRECTIVE_ARGS); throw ParserException(token.mark, ErrorMsg::REPEATED_TAG_DIRECTIVE);
const std::string& handle = token.params[0]; m_pDirectives->tags[handle] = prefix;
const std::string& prefix = token.params[1]; }
if(m_pDirectives->tags.find(handle) != m_pDirectives->tags.end())
throw ParserException(token.mark, ErrorMsg::REPEATED_TAG_DIRECTIVE); void Parser::PrintTokens(std::ostream& out) {
if (!m_pScanner.get())
m_pDirectives->tags[handle] = prefix; return;
}
while (1) {
void Parser::PrintTokens(std::ostream& out) if (m_pScanner->empty())
{ break;
if(!m_pScanner.get())
return; out << m_pScanner->peek() << "\n";
m_pScanner->pop();
while(1) { }
if(m_pScanner->empty()) }
break;
out << m_pScanner->peek() << "\n";
m_pScanner->pop();
}
}
} }

View File

@@ -1,7 +1,9 @@
#ifndef PTR_STACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef PTR_STACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define PTR_STACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define PTR_STACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
@@ -12,38 +14,39 @@
#include <vector> #include <vector>
template <typename T> template <typename T>
class ptr_stack: private YAML::noncopyable class ptr_stack : private YAML::noncopyable {
{ public:
public: ptr_stack() {}
ptr_stack() {} ~ptr_stack() { clear(); }
~ptr_stack() { clear(); }
void clear() { void clear() {
for(unsigned i=0;i<m_data.size();i++) for (unsigned i = 0; i < m_data.size(); i++)
delete m_data[i]; delete m_data[i];
m_data.clear(); m_data.clear();
} }
std::size_t size() const { return m_data.size(); } std::size_t size() const { return m_data.size(); }
bool empty() const { return m_data.empty(); } bool empty() const { return m_data.empty(); }
void push(std::auto_ptr<T> t) { void push(std::auto_ptr<T> t) {
m_data.push_back(NULL); m_data.push_back(NULL);
m_data.back() = t.release(); m_data.back() = t.release();
} }
std::auto_ptr<T> pop() { std::auto_ptr<T> pop() {
std::auto_ptr<T> t(m_data.back()); std::auto_ptr<T> t(m_data.back());
m_data.pop_back(); m_data.pop_back();
return t; return t;
} }
T& top() { return *m_data.back(); } T& top() { return *m_data.back(); }
const T& top() const { return *m_data.back(); } const T& top() const { return *m_data.back(); }
T& top(std::ptrdiff_t diff) { return **(m_data.end() - 1 + diff); } T& top(std::ptrdiff_t diff) { return **(m_data.end() - 1 + diff); }
const T& top(std::ptrdiff_t diff) const { return **(m_data.end() - 1 + diff); } const T& top(std::ptrdiff_t diff) const {
return **(m_data.end() - 1 + diff);
}
private: private:
std::vector<T*> m_data; std::vector<T*> m_data;
}; };
#endif // PTR_STACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #endif // PTR_STACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,7 +1,9 @@
#ifndef PTR_VECTOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef PTR_VECTOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define PTR_VECTOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define PTR_VECTOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
@@ -13,35 +15,34 @@
namespace YAML { namespace YAML {
template <typename T> template <typename T>
class ptr_vector: private YAML::noncopyable class ptr_vector : private YAML::noncopyable {
{ public:
public: ptr_vector() {}
ptr_vector() {} ~ptr_vector() { clear(); }
~ptr_vector() { clear(); }
void clear() { void clear() {
for(unsigned i=0;i<m_data.size();i++) for (unsigned i = 0; i < m_data.size(); i++)
delete m_data[i]; delete m_data[i];
m_data.clear(); m_data.clear();
} }
std::size_t size() const { return m_data.size(); } std::size_t size() const { return m_data.size(); }
bool empty() const { return m_data.empty(); } bool empty() const { return m_data.empty(); }
void push_back(std::auto_ptr<T> t) { void push_back(std::auto_ptr<T> t) {
m_data.push_back(NULL); m_data.push_back(NULL);
m_data.back() = t.release(); m_data.back() = t.release();
} }
T& operator[](std::size_t i) { return *m_data[i]; } T& operator[](std::size_t i) { return *m_data[i]; }
const T& operator[](std::size_t i) const { return *m_data[i]; } const T& operator[](std::size_t i) const { return *m_data[i]; }
T& back() { return *m_data.back(); } T& back() { return *m_data.back(); }
const T& back() const { return *m_data.back(); } const T& back() const { return *m_data.back(); }
private: private:
std::vector<T*> m_data; std::vector<T*> m_data;
}; };
} }
#endif // PTR_VECTOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #endif // PTR_VECTOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,60 +1,45 @@
#include "regex.h" #include "regex.h"
namespace YAML namespace YAML {
{ // constructors
// constructors RegEx::RegEx() : m_op(REGEX_EMPTY) {}
RegEx::RegEx(): m_op(REGEX_EMPTY)
{
}
RegEx::RegEx(REGEX_OP op): m_op(op) RegEx::RegEx(REGEX_OP op) : m_op(op) {}
{
}
RegEx::RegEx(char ch): m_op(REGEX_MATCH), m_a(ch) 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(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) RegEx::RegEx(const std::string& str, REGEX_OP op) : m_op(op) {
{ for (std::size_t i = 0; i < str.size(); i++)
for(std::size_t i=0;i<str.size();i++) m_params.push_back(RegEx(str[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;
}
} }
// 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;
}
}

View File

@@ -1,67 +1,85 @@
#ifndef REGEX_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef REGEX_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define REGEX_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define REGEX_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
#include <vector> #include <vector>
#include <string> #include <string>
namespace YAML namespace YAML {
{ class Stream;
class Stream;
enum REGEX_OP { REGEX_EMPTY, REGEX_MATCH, REGEX_RANGE, REGEX_OR, REGEX_AND, REGEX_NOT, REGEX_SEQ }; enum REGEX_OP {
REGEX_EMPTY,
REGEX_MATCH,
REGEX_RANGE,
REGEX_OR,
REGEX_AND,
REGEX_NOT,
REGEX_SEQ
};
// simplified regular expressions // simplified regular expressions
// . Only straightforward matches (no repeated characters) // . Only straightforward matches (no repeated characters)
// . Only matches from start of string // . Only matches from start of string
class RegEx class RegEx {
{ public:
public: RegEx();
RegEx(); RegEx(char ch);
RegEx(char ch); RegEx(char a, char z);
RegEx(char a, char z); RegEx(const std::string& str, REGEX_OP op = REGEX_SEQ);
RegEx(const std::string& str, REGEX_OP op = REGEX_SEQ); ~RegEx() {}
~RegEx() {}
friend RegEx operator ! (const RegEx& ex); 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); 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(char ch) const;
bool Matches(const std::string& str) const; bool Matches(const std::string& str) const;
bool Matches(const Stream& in) const; bool Matches(const Stream& in) const;
template <typename Source> bool Matches(const Source& source) const; template <typename Source>
bool Matches(const Source& source) const;
int Match(const std::string& str) const; int Match(const std::string& str) const;
int Match(const Stream& in) const; int Match(const Stream& in) const;
template <typename Source> int Match(const Source& source) const; template <typename Source>
int Match(const Source& source) const;
private: private:
RegEx(REGEX_OP op); RegEx(REGEX_OP op);
template <typename Source> bool IsValidSource(const Source& source) const; template <typename Source>
template <typename Source> int MatchUnchecked(const Source& source) const; 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>
template <typename Source> int MatchOpMatch(const Source& source) const; int MatchOpEmpty(const Source& source) const;
template <typename Source> int MatchOpRange(const Source& source) const; template <typename Source>
template <typename Source> int MatchOpOr(const Source& source) const; int MatchOpMatch(const Source& source) const;
template <typename Source> int MatchOpAnd(const Source& source) const; template <typename Source>
template <typename Source> int MatchOpNot(const Source& source) const; int MatchOpRange(const Source& source) const;
template <typename Source> int MatchOpSeq(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: private:
REGEX_OP m_op; REGEX_OP m_op;
char m_a, m_z; char m_a, m_z;
std::vector <RegEx> m_params; std::vector<RegEx> m_params;
}; };
} }
#include "regeximpl.h" #include "regeximpl.h"
#endif // REGEX_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #endif // REGEX_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,186 +1,186 @@
#ifndef REGEXIMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef REGEXIMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define REGEXIMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define REGEXIMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
#include "stream.h" #include "stream.h"
#include "stringsource.h" #include "stringsource.h"
#include "streamcharsource.h" #include "streamcharsource.h"
namespace YAML namespace YAML {
{ // query matches
// query matches inline bool RegEx::Matches(char ch) const {
inline bool RegEx::Matches(char ch) const { std::string str;
std::string str; str += ch;
str += ch; return Matches(str);
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
{
switch(m_op) {
case REGEX_MATCH:
case REGEX_RANGE:
return source;
default:
return true;
}
}
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 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 {
switch (m_op) {
case REGEX_MATCH:
case REGEX_RANGE:
return source;
default:
return true;
}
}
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

View File

@@ -5,41 +5,38 @@
#include <cassert> #include <cassert>
#include <memory> #include <memory>
namespace YAML namespace YAML {
{ Scanner::Scanner(std::istream& in)
Scanner::Scanner(std::istream& in) : INPUT(in),
: INPUT(in), m_startedStream(false), m_endedStream(false), m_simpleKeyAllowed(false), m_canBeJSONFlow(false) m_startedStream(false),
{ m_endedStream(false),
} m_simpleKeyAllowed(false),
m_canBeJSONFlow(false) {}
Scanner::~Scanner() Scanner::~Scanner() {}
{
}
// empty // empty
// . Returns true if there are no more tokens to be read // . Returns true if there are no more tokens to be read
bool Scanner::empty() bool Scanner::empty() {
{ EnsureTokensInQueue();
EnsureTokensInQueue(); return m_tokens.empty();
return m_tokens.empty(); }
}
// pop // pop
// . Simply removes the next token on the queue. // . Simply removes the next token on the queue.
void Scanner::pop() void Scanner::pop() {
{ EnsureTokensInQueue();
EnsureTokensInQueue(); if (!m_tokens.empty())
if(!m_tokens.empty()) m_tokens.pop();
m_tokens.pop(); }
}
// peek // peek
// . Returns (but does not remove) the next token on the queue. // . Returns (but does not remove) the next token on the queue.
Token& Scanner::peek() Token& Scanner::peek() {
{ EnsureTokensInQueue();
EnsureTokensInQueue(); assert(!m_tokens.empty()); // should we be asserting here? I mean, we really
assert(!m_tokens.empty()); // should we be asserting here? I mean, we really just be checking // just be checking
// if it's empty before peeking. // if it's empty before peeking.
#if 0 #if 0
static Token *pLast = 0; static Token *pLast = 0;
@@ -48,347 +45,340 @@ namespace YAML
pLast = &m_tokens.front(); pLast = &m_tokens.front();
#endif #endif
return m_tokens.front(); return m_tokens.front();
}
// mark
// . Returns the current mark in the stream
Mark Scanner::mark() const
{
return INPUT.mark();
}
// 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;
std::auto_ptr<IndentMarker> pIndent(new IndentMarker(-1, IndentMarker::NONE));
m_indentRefs.push_back(pIndent);
m_indents.push(&m_indentRefs.back());
}
// 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);
throw std::runtime_error("yaml-cpp: internal error, invalid indent type");
}
// 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);
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;
}
// 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_mark();
if(!m_tokens.empty()) {
const Token& token = m_tokens.front();
mark = token.mark;
}
throw ParserException(mark, msg);
}
} }
// mark
// . Returns the current mark in the stream
Mark Scanner::mark() const { return INPUT.mark(); }
// 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;
std::auto_ptr<IndentMarker> pIndent(new IndentMarker(-1, IndentMarker::NONE));
m_indentRefs.push_back(pIndent);
m_indents.push(&m_indentRefs.back());
}
// 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);
throw std::runtime_error("yaml-cpp: internal error, invalid indent type");
}
// 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);
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;
}
// 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_mark();
if (!m_tokens.empty()) {
const Token& token = m_tokens.front();
mark = token.mark;
}
throw ParserException(mark, msg);
}
}

View File

@@ -1,11 +1,12 @@
#ifndef SCANNER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef SCANNER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define SCANNER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define SCANNER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
#include <ios> #include <ios>
#include <string> #include <string>
#include <queue> #include <queue>
@@ -16,118 +17,127 @@
#include "stream.h" #include "stream.h"
#include "token.h" #include "token.h"
namespace YAML namespace YAML {
{ class Node;
class Node; class RegEx;
class RegEx;
class Scanner class Scanner {
{ public:
public: Scanner(std::istream &in);
Scanner(std::istream& in); ~Scanner();
~Scanner();
// token queue management (hopefully this looks kinda stl-ish) // token queue management (hopefully this looks kinda stl-ish)
bool empty(); bool empty();
void pop(); void pop();
Token& peek(); Token &peek();
Mark mark() const; Mark mark() const;
private: private:
struct IndentMarker { struct IndentMarker {
enum INDENT_TYPE { MAP, SEQ, NONE }; enum INDENT_TYPE {
enum STATUS { VALID, INVALID, UNKNOWN }; MAP,
IndentMarker(int column_, INDENT_TYPE type_): column(column_), type(type_), status(VALID), pStartToken(0) {} SEQ,
NONE
};
enum STATUS {
VALID,
INVALID,
UNKNOWN
};
IndentMarker(int column_, INDENT_TYPE type_)
: column(column_), type(type_), status(VALID), pStartToken(0) {}
int column; int column;
INDENT_TYPE type; INDENT_TYPE type;
STATUS status; STATUS status;
Token *pStartToken; Token *pStartToken;
}; };
enum FLOW_MARKER { FLOW_MAP, FLOW_SEQ }; enum FLOW_MARKER {
FLOW_MAP,
FLOW_SEQ
};
private: private:
// scanning // scanning
void EnsureTokensInQueue(); void EnsureTokensInQueue();
void ScanNextToken(); void ScanNextToken();
void ScanToNextToken(); void ScanToNextToken();
void StartStream(); void StartStream();
void EndStream(); void EndStream();
Token *PushToken(Token::TYPE type); Token *PushToken(Token::TYPE type);
bool InFlowContext() const { return !m_flows.empty(); } bool InFlowContext() const { return !m_flows.empty(); }
bool InBlockContext() const { return m_flows.empty(); } bool InBlockContext() const { return m_flows.empty(); }
int GetFlowLevel() const { return m_flows.size(); } int GetFlowLevel() const { return m_flows.size(); }
Token::TYPE GetStartTokenFor(IndentMarker::INDENT_TYPE type) const; Token::TYPE GetStartTokenFor(IndentMarker::INDENT_TYPE type) const;
IndentMarker *PushIndentTo(int column, IndentMarker::INDENT_TYPE type); IndentMarker *PushIndentTo(int column, IndentMarker::INDENT_TYPE type);
void PopIndentToHere(); void PopIndentToHere();
void PopAllIndents(); void PopAllIndents();
void PopIndent(); void PopIndent();
int GetTopIndent() const; int GetTopIndent() const;
// checking input // checking input
bool CanInsertPotentialSimpleKey() const; bool CanInsertPotentialSimpleKey() const;
bool ExistsActiveSimpleKey() const; bool ExistsActiveSimpleKey() const;
void InsertPotentialSimpleKey(); void InsertPotentialSimpleKey();
void InvalidateSimpleKey(); void InvalidateSimpleKey();
bool VerifySimpleKey(); bool VerifySimpleKey();
void PopAllSimpleKeys(); void PopAllSimpleKeys();
void ThrowParserException(const std::string& msg) const; void ThrowParserException(const std::string &msg) const;
bool IsWhitespaceToBeEaten(char ch); bool IsWhitespaceToBeEaten(char ch);
const RegEx& GetValueRegex() const; const RegEx &GetValueRegex() const;
struct SimpleKey { struct SimpleKey {
SimpleKey(const Mark& mark_, int flowLevel_); SimpleKey(const Mark &mark_, int flowLevel_);
void Validate(); void Validate();
void Invalidate(); void Invalidate();
Mark mark; Mark mark;
int flowLevel; int flowLevel;
IndentMarker *pIndent; IndentMarker *pIndent;
Token *pMapStart, *pKey; Token *pMapStart, *pKey;
}; };
// and the tokens // and the tokens
void ScanDirective(); void ScanDirective();
void ScanDocStart(); void ScanDocStart();
void ScanDocEnd(); void ScanDocEnd();
void ScanBlockSeqStart(); void ScanBlockSeqStart();
void ScanBlockMapSTart(); void ScanBlockMapSTart();
void ScanBlockEnd(); void ScanBlockEnd();
void ScanBlockEntry(); void ScanBlockEntry();
void ScanFlowStart(); void ScanFlowStart();
void ScanFlowEnd(); void ScanFlowEnd();
void ScanFlowEntry(); void ScanFlowEntry();
void ScanKey(); void ScanKey();
void ScanValue(); void ScanValue();
void ScanAnchorOrAlias(); void ScanAnchorOrAlias();
void ScanTag(); void ScanTag();
void ScanPlainScalar(); void ScanPlainScalar();
void ScanQuotedScalar(); void ScanQuotedScalar();
void ScanBlockScalar(); void ScanBlockScalar();
private: private:
// the stream // the stream
Stream INPUT; Stream INPUT;
// the output (tokens) // the output (tokens)
std::queue<Token> m_tokens; std::queue<Token> m_tokens;
// state info // state info
bool m_startedStream, m_endedStream; bool m_startedStream, m_endedStream;
bool m_simpleKeyAllowed; bool m_simpleKeyAllowed;
bool m_canBeJSONFlow; bool m_canBeJSONFlow;
std::stack<SimpleKey> m_simpleKeys; std::stack<SimpleKey> m_simpleKeys;
std::stack<IndentMarker *> m_indents; std::stack<IndentMarker *> m_indents;
ptr_vector<IndentMarker> m_indentRefs; // for "garbage collection" ptr_vector<IndentMarker> m_indentRefs; // for "garbage collection"
std::stack<FLOW_MARKER> m_flows; std::stack<FLOW_MARKER> m_flows;
}; };
} }
#endif // SCANNER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #endif // SCANNER_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -4,211 +4,215 @@
#include "yaml-cpp/exceptions.h" #include "yaml-cpp/exceptions.h"
#include "token.h" #include "token.h"
namespace YAML namespace YAML {
{ // ScanScalar
// ScanScalar // . This is where the scalar magic happens.
// . This is where the scalar magic happens. //
// // . We do the scanning in three phases:
// . We do the scanning in three phases: // 1. Scan until newline
// 1. Scan until newline // 2. Eat newline
// 2. Eat newline // 3. Scan leading blanks.
// 3. Scan leading blanks. //
// // . Depending on the parameters given, we store or stop
// . Depending on the parameters given, we store or stop // and different places in the above flow.
// and different places in the above flow. std::string ScanScalar(Stream& INPUT, ScanScalarParams& params) {
std::string ScanScalar(Stream& INPUT, ScanScalarParams& params) bool foundNonEmptyLine = false;
{ bool pastOpeningBreak = (params.fold == FOLD_FLOW);
bool foundNonEmptyLine = false; bool emptyLine = false, moreIndented = false;
bool pastOpeningBreak = (params.fold == FOLD_FLOW); int foldedNewlineCount = 0;
bool emptyLine = false, moreIndented = false; bool foldedNewlineStartedMoreIndented = false;
int foldedNewlineCount = 0; std::size_t lastEscapedChar = std::string::npos;
bool foldedNewlineStartedMoreIndented = false; std::string scalar;
std::size_t lastEscapedChar = std::string::npos; params.leadingSpaces = false;
std::string scalar;
params.leadingSpaces = false;
while(INPUT) { while (INPUT) {
// ******************************** // ********************************
// Phase #1: scan until line ending // Phase #1: scan until line ending
std::size_t lastNonWhitespaceChar = scalar.size(); std::size_t lastNonWhitespaceChar = scalar.size();
bool escapedNewline = false; bool escapedNewline = false;
while(!params.end.Matches(INPUT) && !Exp::Break().Matches(INPUT)) { while (!params.end.Matches(INPUT) && !Exp::Break().Matches(INPUT)) {
if(!INPUT) if (!INPUT)
break; break;
// document indicator? // document indicator?
if(INPUT.column() == 0 && Exp::DocIndicator().Matches(INPUT)) { if (INPUT.column() == 0 && Exp::DocIndicator().Matches(INPUT)) {
if(params.onDocIndicator == BREAK) if (params.onDocIndicator == BREAK)
break; break;
else if(params.onDocIndicator == THROW) else if (params.onDocIndicator == THROW)
throw ParserException(INPUT.mark(), ErrorMsg::DOC_IN_SCALAR); throw ParserException(INPUT.mark(), ErrorMsg::DOC_IN_SCALAR);
} }
foundNonEmptyLine = true; foundNonEmptyLine = true;
pastOpeningBreak = true; pastOpeningBreak = true;
// escaped newline? (only if we're escaping on slash) // escaped newline? (only if we're escaping on slash)
if(params.escape == '\\' && Exp::EscBreak().Matches(INPUT)) { if (params.escape == '\\' && Exp::EscBreak().Matches(INPUT)) {
// eat escape character and get out (but preserve trailing whitespace!) // eat escape character and get out (but preserve trailing whitespace!)
INPUT.get(); INPUT.get();
lastNonWhitespaceChar = scalar.size(); lastNonWhitespaceChar = scalar.size();
lastEscapedChar = scalar.size(); lastEscapedChar = scalar.size();
escapedNewline = true; escapedNewline = true;
break; break;
} }
// escape this? // escape this?
if(INPUT.peek() == params.escape) { if (INPUT.peek() == params.escape) {
scalar += Exp::Escape(INPUT); scalar += Exp::Escape(INPUT);
lastNonWhitespaceChar = scalar.size(); lastNonWhitespaceChar = scalar.size();
lastEscapedChar = scalar.size(); lastEscapedChar = scalar.size();
continue; continue;
} }
// otherwise, just add the damn character // otherwise, just add the damn character
char ch = INPUT.get(); char ch = INPUT.get();
scalar += ch; scalar += ch;
if(ch != ' ' && ch != '\t') if (ch != ' ' && ch != '\t')
lastNonWhitespaceChar = scalar.size(); lastNonWhitespaceChar = scalar.size();
} }
// eof? if we're looking to eat something, then we throw // eof? if we're looking to eat something, then we throw
if(!INPUT) { if (!INPUT) {
if(params.eatEnd) if (params.eatEnd)
throw ParserException(INPUT.mark(), ErrorMsg::EOF_IN_SCALAR); throw ParserException(INPUT.mark(), ErrorMsg::EOF_IN_SCALAR);
break; break;
} }
// doc indicator? // doc indicator?
if(params.onDocIndicator == BREAK && INPUT.column() == 0 && Exp::DocIndicator().Matches(INPUT)) if (params.onDocIndicator == BREAK && INPUT.column() == 0 &&
break; Exp::DocIndicator().Matches(INPUT))
break;
// are we done via character match? // are we done via character match?
int n = params.end.Match(INPUT); int n = params.end.Match(INPUT);
if(n >= 0) { if (n >= 0) {
if(params.eatEnd) if (params.eatEnd)
INPUT.eat(n); INPUT.eat(n);
break; break;
} }
// do we remove trailing whitespace? // do we remove trailing whitespace?
if(params.fold == FOLD_FLOW) if (params.fold == FOLD_FLOW)
scalar.erase(lastNonWhitespaceChar); scalar.erase(lastNonWhitespaceChar);
// ******************************** // ********************************
// Phase #2: eat line ending // Phase #2: eat line ending
n = Exp::Break().Match(INPUT); n = Exp::Break().Match(INPUT);
INPUT.eat(n); INPUT.eat(n);
// ******************************** // ********************************
// Phase #3: scan initial spaces // Phase #3: scan initial spaces
// first the required indentation // first the required indentation
while(INPUT.peek() == ' ' && (INPUT.column() < params.indent || (params.detectIndent && !foundNonEmptyLine))) while (INPUT.peek() == ' ' && (INPUT.column() < params.indent ||
INPUT.eat(1); (params.detectIndent && !foundNonEmptyLine)))
INPUT.eat(1);
// update indent if we're auto-detecting // update indent if we're auto-detecting
if(params.detectIndent && !foundNonEmptyLine) if (params.detectIndent && !foundNonEmptyLine)
params.indent = std::max(params.indent, INPUT.column()); params.indent = std::max(params.indent, INPUT.column());
// and then the rest of the whitespace // and then the rest of the whitespace
while(Exp::Blank().Matches(INPUT)) { while (Exp::Blank().Matches(INPUT)) {
// we check for tabs that masquerade as indentation // we check for tabs that masquerade as indentation
if(INPUT.peek() == '\t'&& INPUT.column() < params.indent && params.onTabInIndentation == THROW) if (INPUT.peek() == '\t' && INPUT.column() < params.indent &&
throw ParserException(INPUT.mark(), ErrorMsg::TAB_IN_INDENTATION); params.onTabInIndentation == THROW)
throw ParserException(INPUT.mark(), ErrorMsg::TAB_IN_INDENTATION);
if(!params.eatLeadingWhitespace) if (!params.eatLeadingWhitespace)
break; break;
INPUT.eat(1); INPUT.eat(1);
} }
// was this an empty line? // was this an empty line?
bool nextEmptyLine = Exp::Break().Matches(INPUT); bool nextEmptyLine = Exp::Break().Matches(INPUT);
bool nextMoreIndented = Exp::Blank().Matches(INPUT); bool nextMoreIndented = Exp::Blank().Matches(INPUT);
if(params.fold == FOLD_BLOCK && foldedNewlineCount == 0 && nextEmptyLine) if (params.fold == FOLD_BLOCK && foldedNewlineCount == 0 && nextEmptyLine)
foldedNewlineStartedMoreIndented = moreIndented; foldedNewlineStartedMoreIndented = moreIndented;
// for block scalars, we always start with a newline, so we should ignore it (not fold or keep) // for block scalars, we always start with a newline, so we should ignore it
if(pastOpeningBreak) { // (not fold or keep)
switch(params.fold) { if (pastOpeningBreak) {
case DONT_FOLD: switch (params.fold) {
scalar += "\n"; case DONT_FOLD:
break; scalar += "\n";
case FOLD_BLOCK: break;
if(!emptyLine && !nextEmptyLine && !moreIndented && !nextMoreIndented && INPUT.column() >= params.indent) case FOLD_BLOCK:
scalar += " "; if (!emptyLine && !nextEmptyLine && !moreIndented &&
else if(nextEmptyLine) !nextMoreIndented && INPUT.column() >= params.indent)
foldedNewlineCount++; scalar += " ";
else else if (nextEmptyLine)
scalar += "\n"; foldedNewlineCount++;
else
scalar += "\n";
if(!nextEmptyLine && foldedNewlineCount > 0) { if (!nextEmptyLine && foldedNewlineCount > 0) {
scalar += std::string(foldedNewlineCount - 1, '\n'); scalar += std::string(foldedNewlineCount - 1, '\n');
if(foldedNewlineStartedMoreIndented || nextMoreIndented | !foundNonEmptyLine) if (foldedNewlineStartedMoreIndented ||
scalar += "\n"; nextMoreIndented | !foundNonEmptyLine)
foldedNewlineCount = 0; scalar += "\n";
} foldedNewlineCount = 0;
break; }
case FOLD_FLOW: break;
if(nextEmptyLine) case FOLD_FLOW:
scalar += "\n"; if (nextEmptyLine)
else if(!emptyLine && !nextEmptyLine && !escapedNewline) scalar += "\n";
scalar += " "; else if (!emptyLine && !nextEmptyLine && !escapedNewline)
break; scalar += " ";
} break;
} }
}
emptyLine = nextEmptyLine; emptyLine = nextEmptyLine;
moreIndented = nextMoreIndented; moreIndented = nextMoreIndented;
pastOpeningBreak = true; pastOpeningBreak = true;
// are we done via indentation? // are we done via indentation?
if(!emptyLine && INPUT.column() < params.indent) { if (!emptyLine && INPUT.column() < params.indent) {
params.leadingSpaces = true; params.leadingSpaces = true;
break; break;
} }
} }
// post-processing // post-processing
if(params.trimTrailingSpaces) { if (params.trimTrailingSpaces) {
std::size_t pos = scalar.find_last_not_of(' '); std::size_t pos = scalar.find_last_not_of(' ');
if(lastEscapedChar != std::string::npos) { if (lastEscapedChar != std::string::npos) {
if(pos < lastEscapedChar || pos == std::string::npos) if (pos < lastEscapedChar || pos == std::string::npos)
pos = lastEscapedChar; pos = lastEscapedChar;
} }
if(pos < scalar.size()) if (pos < scalar.size())
scalar.erase(pos + 1); scalar.erase(pos + 1);
} }
switch(params.chomp) { switch (params.chomp) {
case CLIP: { case CLIP: {
std::size_t pos = scalar.find_last_not_of('\n'); std::size_t pos = scalar.find_last_not_of('\n');
if(lastEscapedChar != std::string::npos) { if (lastEscapedChar != std::string::npos) {
if(pos < lastEscapedChar || pos == std::string::npos) if (pos < lastEscapedChar || pos == std::string::npos)
pos = lastEscapedChar; pos = lastEscapedChar;
} }
if(pos == std::string::npos) if (pos == std::string::npos)
scalar.erase(); scalar.erase();
else if(pos + 1 < scalar.size()) else if (pos + 1 < scalar.size())
scalar.erase(pos + 2); scalar.erase(pos + 2);
} break; } break;
case STRIP: { case STRIP: {
std::size_t pos = scalar.find_last_not_of('\n'); std::size_t pos = scalar.find_last_not_of('\n');
if(lastEscapedChar != std::string::npos) { if (lastEscapedChar != std::string::npos) {
if(pos < lastEscapedChar || pos == std::string::npos) if (pos < lastEscapedChar || pos == std::string::npos)
pos = lastEscapedChar; pos = lastEscapedChar;
} }
if(pos == std::string::npos) if (pos == std::string::npos)
scalar.erase(); scalar.erase();
else if(pos < scalar.size()) else if (pos < scalar.size())
scalar.erase(pos + 1); scalar.erase(pos + 1);
} break; } break;
default: default:
break; break;
} }
return scalar; return scalar;
} }
} }

View File

@@ -1,45 +1,72 @@
#ifndef SCANSCALAR_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef SCANSCALAR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define SCANSCALAR_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define SCANSCALAR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
#include <string> #include <string>
#include "regex.h" #include "regex.h"
#include "stream.h" #include "stream.h"
namespace YAML namespace YAML {
{ enum CHOMP {
enum CHOMP { STRIP = -1, CLIP, KEEP }; STRIP = -1,
enum ACTION { NONE, BREAK, THROW }; CLIP,
enum FOLD { DONT_FOLD, FOLD_BLOCK, FOLD_FLOW }; KEEP
};
enum ACTION {
NONE,
BREAK,
THROW
};
enum FOLD {
DONT_FOLD,
FOLD_BLOCK,
FOLD_FLOW
};
struct ScanScalarParams { struct ScanScalarParams {
ScanScalarParams(): eatEnd(false), indent(0), detectIndent(false), eatLeadingWhitespace(0), escape(0), fold(DONT_FOLD), ScanScalarParams()
trimTrailingSpaces(0), chomp(CLIP), onDocIndicator(NONE), onTabInIndentation(NONE), leadingSpaces(false) {} : eatEnd(false),
indent(0),
detectIndent(false),
eatLeadingWhitespace(0),
escape(0),
fold(DONT_FOLD),
trimTrailingSpaces(0),
chomp(CLIP),
onDocIndicator(NONE),
onTabInIndentation(NONE),
leadingSpaces(false) {}
// input: // input:
RegEx end; // what condition ends this scalar? RegEx end; // what condition ends this scalar?
bool eatEnd; // should we eat that condition when we see it? bool eatEnd; // should we eat that condition when we see it?
int indent; // what level of indentation should be eaten and ignored? int indent; // what level of indentation should be eaten and ignored?
bool detectIndent; // should we try to autodetect the indent? bool detectIndent; // should we try to autodetect the indent?
bool eatLeadingWhitespace; // should we continue eating this delicious indentation after 'indent' spaces? bool eatLeadingWhitespace; // should we continue eating this delicious
char escape; // what character do we escape on (i.e., slash or single quote) (0 for none) // indentation after 'indent' spaces?
FOLD fold; // how do we fold line ends? char escape; // what character do we escape on (i.e., slash or single quote)
bool trimTrailingSpaces; // do we remove all trailing spaces (at the very end) // (0 for none)
CHOMP chomp; // do we strip, clip, or keep trailing newlines (at the very end) FOLD fold; // how do we fold line ends?
// Note: strip means kill all, clip means keep at most one, keep means keep all bool trimTrailingSpaces; // do we remove all trailing spaces (at the very
ACTION onDocIndicator; // what do we do if we see a document indicator? // end)
ACTION onTabInIndentation; // what do we do if we see a tab where we should be seeing indentation spaces 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: // output:
bool leadingSpaces; bool leadingSpaces;
}; };
std::string ScanScalar(Stream& INPUT, ScanScalarParams& info); std::string ScanScalar(Stream& INPUT, ScanScalarParams& info);
} }
#endif // SCANSCALAR_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #endif // SCANSCALAR_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -3,82 +3,77 @@
#include "exp.h" #include "exp.h"
#include "yaml-cpp/exceptions.h" #include "yaml-cpp/exceptions.h"
namespace YAML namespace YAML {
{ const std::string ScanVerbatimTag(Stream& INPUT) {
const std::string ScanVerbatimTag(Stream& INPUT) std::string tag;
{
std::string tag;
// eat the start character // eat the start character
INPUT.get(); INPUT.get();
while(INPUT) { while (INPUT) {
if(INPUT.peek() == Keys::VerbatimTagEnd) { if (INPUT.peek() == Keys::VerbatimTagEnd) {
// eat the end character // eat the end character
INPUT.get(); INPUT.get();
return tag; return tag;
} }
int n = Exp::URI().Match(INPUT); int n = Exp::URI().Match(INPUT);
if(n <= 0) if (n <= 0)
break; break;
tag += INPUT.get(n); tag += INPUT.get(n);
} }
throw ParserException(INPUT.mark(), ErrorMsg::END_OF_VERBATIM_TAG); 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;
}
} }
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;
}
}

View File

@@ -1,20 +1,19 @@
#ifndef SCANTAG_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef SCANTAG_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define SCANTAG_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define SCANTAG_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
#include <string> #include <string>
#include "stream.h" #include "stream.h"
namespace YAML namespace YAML {
{ const std::string ScanVerbatimTag(Stream& INPUT);
const std::string ScanVerbatimTag(Stream& INPUT); const std::string ScanTagHandle(Stream& INPUT, bool& canBeHandle);
const std::string ScanTagHandle(Stream& INPUT, bool& canBeHandle); const std::string ScanTagSuffix(Stream& INPUT);
const std::string ScanTagSuffix(Stream& INPUT);
} }
#endif // SCANTAG_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #endif // SCANTAG_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -7,433 +7,426 @@
#include "tag.h" #include "tag.h"
#include <sstream> #include <sstream>
namespace YAML namespace YAML {
{ ///////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////// // Specialization for scanning specific tokens
// Specialization for scanning specific tokens
// Directive
// Directive // . Note: no semantic checking is done here (that's for the parser to do)
// . Note: no semantic checking is done here (that's for the parser to do) void Scanner::ScanDirective() {
void Scanner::ScanDirective() std::string name;
{ std::vector<std::string> params;
std::string name;
std::vector <std::string> params; // pop indents and simple keys
PopAllIndents();
// pop indents and simple keys PopAllSimpleKeys();
PopAllIndents();
PopAllSimpleKeys(); m_simpleKeyAllowed = false;
m_canBeJSONFlow = false;
m_simpleKeyAllowed = false;
m_canBeJSONFlow = false; // store pos and eat indicator
Token token(Token::DIRECTIVE, INPUT.mark());
// store pos and eat indicator INPUT.eat(1);
Token token(Token::DIRECTIVE, INPUT.mark());
INPUT.eat(1); // read name
while (INPUT && !Exp::BlankOrBreak().Matches(INPUT))
// read name token.value += INPUT.get();
while(INPUT && !Exp::BlankOrBreak().Matches(INPUT))
token.value += INPUT.get(); // read parameters
while (1) {
// read parameters // first get rid of whitespace
while(1) { while (Exp::Blank().Matches(INPUT))
// first get rid of whitespace INPUT.eat(1);
while(Exp::Blank().Matches(INPUT))
INPUT.eat(1); // break on newline or comment
if (!INPUT || Exp::Break().Matches(INPUT) || Exp::Comment().Matches(INPUT))
// break on newline or comment break;
if(!INPUT || Exp::Break().Matches(INPUT) || Exp::Comment().Matches(INPUT))
break; // now read parameter
std::string param;
// now read parameter while (INPUT && !Exp::BlankOrBreak().Matches(INPUT))
std::string param; param += INPUT.get();
while(INPUT && !Exp::BlankOrBreak().Matches(INPUT))
param += INPUT.get(); token.params.push_back(param);
}
token.params.push_back(param);
} m_tokens.push(token);
}
m_tokens.push(token);
} // DocStart
void Scanner::ScanDocStart() {
// DocStart PopAllIndents();
void Scanner::ScanDocStart() PopAllSimpleKeys();
{ m_simpleKeyAllowed = false;
PopAllIndents(); m_canBeJSONFlow = false;
PopAllSimpleKeys();
m_simpleKeyAllowed = false; // eat
m_canBeJSONFlow = false; Mark mark = INPUT.mark();
INPUT.eat(3);
// eat m_tokens.push(Token(Token::DOC_START, mark));
Mark mark = INPUT.mark(); }
INPUT.eat(3);
m_tokens.push(Token(Token::DOC_START, mark)); // DocEnd
} void Scanner::ScanDocEnd() {
PopAllIndents();
// DocEnd PopAllSimpleKeys();
void Scanner::ScanDocEnd() m_simpleKeyAllowed = false;
{ m_canBeJSONFlow = false;
PopAllIndents();
PopAllSimpleKeys(); // eat
m_simpleKeyAllowed = false; Mark mark = INPUT.mark();
m_canBeJSONFlow = false; INPUT.eat(3);
m_tokens.push(Token(Token::DOC_END, mark));
// eat }
Mark mark = INPUT.mark();
INPUT.eat(3); // FlowStart
m_tokens.push(Token(Token::DOC_END, mark)); void Scanner::ScanFlowStart() {
} // flows can be simple keys
InsertPotentialSimpleKey();
// FlowStart m_simpleKeyAllowed = true;
void Scanner::ScanFlowStart() m_canBeJSONFlow = false;
{
// flows can be simple keys // eat
InsertPotentialSimpleKey(); Mark mark = INPUT.mark();
m_simpleKeyAllowed = true; char ch = INPUT.get();
m_canBeJSONFlow = false; FLOW_MARKER flowType = (ch == Keys::FlowSeqStart ? FLOW_SEQ : FLOW_MAP);
m_flows.push(flowType);
// eat Token::TYPE type =
Mark mark = INPUT.mark(); (flowType == FLOW_SEQ ? Token::FLOW_SEQ_START : Token::FLOW_MAP_START);
char ch = INPUT.get(); m_tokens.push(Token(type, mark));
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); // FlowEnd
m_tokens.push(Token(type, mark)); void Scanner::ScanFlowEnd() {
} if (InBlockContext())
throw ParserException(INPUT.mark(), ErrorMsg::FLOW_END);
// FlowEnd
void Scanner::ScanFlowEnd() // we might have a solo entry in the flow context
{ if (InFlowContext()) {
if(InBlockContext()) if (m_flows.top() == FLOW_MAP && VerifySimpleKey())
throw ParserException(INPUT.mark(), ErrorMsg::FLOW_END); m_tokens.push(Token(Token::VALUE, INPUT.mark()));
else if (m_flows.top() == FLOW_SEQ)
// we might have a solo entry in the flow context InvalidateSimpleKey();
if(InFlowContext()) { }
if(m_flows.top() == FLOW_MAP && VerifySimpleKey())
m_tokens.push(Token(Token::VALUE, INPUT.mark())); m_simpleKeyAllowed = false;
else if(m_flows.top() == FLOW_SEQ) m_canBeJSONFlow = true;
InvalidateSimpleKey();
} // eat
Mark mark = INPUT.mark();
m_simpleKeyAllowed = false; char ch = INPUT.get();
m_canBeJSONFlow = true;
// check that it matches the start
// eat FLOW_MARKER flowType = (ch == Keys::FlowSeqEnd ? FLOW_SEQ : FLOW_MAP);
Mark mark = INPUT.mark(); if (m_flows.top() != flowType)
char ch = INPUT.get(); throw ParserException(mark, ErrorMsg::FLOW_END);
m_flows.pop();
// check that it matches the start
FLOW_MARKER flowType = (ch == Keys::FlowSeqEnd ? FLOW_SEQ : FLOW_MAP); Token::TYPE type = (flowType ? Token::FLOW_SEQ_END : Token::FLOW_MAP_END);
if(m_flows.top() != flowType) m_tokens.push(Token(type, mark));
throw ParserException(mark, ErrorMsg::FLOW_END); }
m_flows.pop();
// FlowEntry
Token::TYPE type = (flowType ? Token::FLOW_SEQ_END : Token::FLOW_MAP_END); void Scanner::ScanFlowEntry() {
m_tokens.push(Token(type, mark)); // we might have a solo entry in the flow context
} if (InFlowContext()) {
if (m_flows.top() == FLOW_MAP && VerifySimpleKey())
// FlowEntry m_tokens.push(Token(Token::VALUE, INPUT.mark()));
void Scanner::ScanFlowEntry() else if (m_flows.top() == FLOW_SEQ)
{ InvalidateSimpleKey();
// we might have a solo entry in the flow context }
if(InFlowContext()) {
if(m_flows.top() == FLOW_MAP && VerifySimpleKey()) m_simpleKeyAllowed = true;
m_tokens.push(Token(Token::VALUE, INPUT.mark())); m_canBeJSONFlow = false;
else if(m_flows.top() == FLOW_SEQ)
InvalidateSimpleKey(); // eat
} Mark mark = INPUT.mark();
INPUT.eat(1);
m_simpleKeyAllowed = true; m_tokens.push(Token(Token::FLOW_ENTRY, mark));
m_canBeJSONFlow = false; }
// eat // BlockEntry
Mark mark = INPUT.mark(); void Scanner::ScanBlockEntry() {
INPUT.eat(1); // we better be in the block context!
m_tokens.push(Token(Token::FLOW_ENTRY, mark)); if (InFlowContext())
} throw ParserException(INPUT.mark(), ErrorMsg::BLOCK_ENTRY);
// BlockEntry // can we put it here?
void Scanner::ScanBlockEntry() if (!m_simpleKeyAllowed)
{ throw ParserException(INPUT.mark(), ErrorMsg::BLOCK_ENTRY);
// we better be in the block context!
if(InFlowContext()) PushIndentTo(INPUT.column(), IndentMarker::SEQ);
throw ParserException(INPUT.mark(), ErrorMsg::BLOCK_ENTRY); m_simpleKeyAllowed = true;
m_canBeJSONFlow = false;
// can we put it here?
if(!m_simpleKeyAllowed) // eat
throw ParserException(INPUT.mark(), ErrorMsg::BLOCK_ENTRY); Mark mark = INPUT.mark();
INPUT.eat(1);
PushIndentTo(INPUT.column(), IndentMarker::SEQ); m_tokens.push(Token(Token::BLOCK_ENTRY, mark));
m_simpleKeyAllowed = true; }
m_canBeJSONFlow = false;
// Key
// eat void Scanner::ScanKey() {
Mark mark = INPUT.mark(); // handle keys diffently in the block context (and manage indents)
INPUT.eat(1); if (InBlockContext()) {
m_tokens.push(Token(Token::BLOCK_ENTRY, mark)); if (!m_simpleKeyAllowed)
} throw ParserException(INPUT.mark(), ErrorMsg::MAP_KEY);
// Key PushIndentTo(INPUT.column(), IndentMarker::MAP);
void Scanner::ScanKey() }
{
// handle keys diffently in the block context (and manage indents) // can only put a simple key here if we're in block context
if(InBlockContext()) { m_simpleKeyAllowed = InBlockContext();
if(!m_simpleKeyAllowed)
throw ParserException(INPUT.mark(), ErrorMsg::MAP_KEY); // eat
Mark mark = INPUT.mark();
PushIndentTo(INPUT.column(), IndentMarker::MAP); INPUT.eat(1);
} m_tokens.push(Token(Token::KEY, mark));
}
// can only put a simple key here if we're in block context
m_simpleKeyAllowed = InBlockContext(); // Value
void Scanner::ScanValue() {
// eat // and check that simple key
Mark mark = INPUT.mark(); bool isSimpleKey = VerifySimpleKey();
INPUT.eat(1); m_canBeJSONFlow = false;
m_tokens.push(Token(Token::KEY, mark));
} if (isSimpleKey) {
// can't follow a simple key with another simple key (dunno why, though - it
// Value // seems fine)
void Scanner::ScanValue() m_simpleKeyAllowed = false;
{ } else {
// and check that simple key // handle values diffently in the block context (and manage indents)
bool isSimpleKey = VerifySimpleKey(); if (InBlockContext()) {
m_canBeJSONFlow = false; if (!m_simpleKeyAllowed)
throw ParserException(INPUT.mark(), ErrorMsg::MAP_VALUE);
if(isSimpleKey) {
// can't follow a simple key with another simple key (dunno why, though - it seems fine) PushIndentTo(INPUT.column(), IndentMarker::MAP);
m_simpleKeyAllowed = false; }
} else {
// handle values diffently in the block context (and manage indents) // can only put a simple key here if we're in block context
if(InBlockContext()) { m_simpleKeyAllowed = InBlockContext();
if(!m_simpleKeyAllowed) }
throw ParserException(INPUT.mark(), ErrorMsg::MAP_VALUE);
// eat
PushIndentTo(INPUT.column(), IndentMarker::MAP); Mark mark = INPUT.mark();
} INPUT.eat(1);
m_tokens.push(Token(Token::VALUE, mark));
// can only put a simple key here if we're in block context }
m_simpleKeyAllowed = InBlockContext();
} // AnchorOrAlias
void Scanner::ScanAnchorOrAlias() {
// eat bool alias;
Mark mark = INPUT.mark(); std::string name;
INPUT.eat(1);
m_tokens.push(Token(Token::VALUE, mark)); // insert a potential simple key
} InsertPotentialSimpleKey();
m_simpleKeyAllowed = false;
// AnchorOrAlias m_canBeJSONFlow = false;
void Scanner::ScanAnchorOrAlias()
{ // eat the indicator
bool alias; Mark mark = INPUT.mark();
std::string name; char indicator = INPUT.get();
alias = (indicator == Keys::Alias);
// insert a potential simple key
InsertPotentialSimpleKey(); // now eat the content
m_simpleKeyAllowed = false; while (INPUT && Exp::Anchor().Matches(INPUT))
m_canBeJSONFlow = false; name += INPUT.get();
// eat the indicator // we need to have read SOMETHING!
Mark mark = INPUT.mark(); if (name.empty())
char indicator = INPUT.get(); throw ParserException(INPUT.mark(), alias ? ErrorMsg::ALIAS_NOT_FOUND
alias = (indicator == Keys::Alias); : ErrorMsg::ANCHOR_NOT_FOUND);
// now eat the content // and needs to end correctly
while(INPUT && Exp::Anchor().Matches(INPUT)) if (INPUT && !Exp::AnchorEnd().Matches(INPUT))
name += INPUT.get(); throw ParserException(INPUT.mark(), alias ? ErrorMsg::CHAR_IN_ALIAS
: ErrorMsg::CHAR_IN_ANCHOR);
// we need to have read SOMETHING!
if(name.empty()) // and we're done
throw ParserException(INPUT.mark(), alias ? ErrorMsg::ALIAS_NOT_FOUND : ErrorMsg::ANCHOR_NOT_FOUND); Token token(alias ? Token::ALIAS : Token::ANCHOR, mark);
token.value = name;
// and needs to end correctly m_tokens.push(token);
if(INPUT && !Exp::AnchorEnd().Matches(INPUT)) }
throw ParserException(INPUT.mark(), alias ? ErrorMsg::CHAR_IN_ALIAS : ErrorMsg::CHAR_IN_ANCHOR);
// Tag
// and we're done void Scanner::ScanTag() {
Token token(alias ? Token::ALIAS : Token::ANCHOR, mark); // insert a potential simple key
token.value = name; InsertPotentialSimpleKey();
m_tokens.push(token); m_simpleKeyAllowed = false;
} m_canBeJSONFlow = false;
// Tag Token token(Token::TAG, INPUT.mark());
void Scanner::ScanTag()
{ // eat the indicator
// insert a potential simple key INPUT.get();
InsertPotentialSimpleKey();
m_simpleKeyAllowed = false; if (INPUT && INPUT.peek() == Keys::VerbatimTagStart) {
m_canBeJSONFlow = false; std::string tag = ScanVerbatimTag(INPUT);
Token token(Token::TAG, INPUT.mark()); token.value = tag;
token.data = Tag::VERBATIM;
// eat the indicator } else {
INPUT.get(); bool canBeHandle;
token.value = ScanTagHandle(INPUT, canBeHandle);
if(INPUT && INPUT.peek() == Keys::VerbatimTagStart){ if (!canBeHandle && token.value.empty())
std::string tag = ScanVerbatimTag(INPUT); token.data = Tag::NON_SPECIFIC;
else if (token.value.empty())
token.value = tag; token.data = Tag::SECONDARY_HANDLE;
token.data = Tag::VERBATIM; else
} else { token.data = Tag::PRIMARY_HANDLE;
bool canBeHandle;
token.value = ScanTagHandle(INPUT, canBeHandle); // is there a suffix?
if(!canBeHandle && token.value.empty()) if (canBeHandle && INPUT.peek() == Keys::Tag) {
token.data = Tag::NON_SPECIFIC; // eat the indicator
else if(token.value.empty()) INPUT.get();
token.data = Tag::SECONDARY_HANDLE; token.params.push_back(ScanTagSuffix(INPUT));
else token.data = Tag::NAMED_HANDLE;
token.data = Tag::PRIMARY_HANDLE; }
}
// is there a suffix?
if(canBeHandle && INPUT.peek() == Keys::Tag) { m_tokens.push(token);
// eat the indicator }
INPUT.get();
token.params.push_back(ScanTagSuffix(INPUT)); // PlainScalar
token.data = Tag::NAMED_HANDLE; void Scanner::ScanPlainScalar() {
} std::string scalar;
}
// set up the scanning parameters
m_tokens.push(token); ScanScalarParams params;
} params.end = (InFlowContext() ? Exp::EndScalarInFlow() : Exp::EndScalar()) ||
(Exp::BlankOrBreak() + Exp::Comment());
// PlainScalar params.eatEnd = false;
void Scanner::ScanPlainScalar() params.indent = (InFlowContext() ? 0 : GetTopIndent() + 1);
{ params.fold = FOLD_FLOW;
std::string scalar; params.eatLeadingWhitespace = true;
params.trimTrailingSpaces = true;
// set up the scanning parameters params.chomp = STRIP;
ScanScalarParams params; params.onDocIndicator = BREAK;
params.end = (InFlowContext() ? Exp::EndScalarInFlow() : Exp::EndScalar()) || (Exp::BlankOrBreak() + Exp::Comment()); params.onTabInIndentation = THROW;
params.eatEnd = false;
params.indent = (InFlowContext() ? 0 : GetTopIndent() + 1); // insert a potential simple key
params.fold = FOLD_FLOW; InsertPotentialSimpleKey();
params.eatLeadingWhitespace = true;
params.trimTrailingSpaces = true; Mark mark = INPUT.mark();
params.chomp = STRIP; scalar = ScanScalar(INPUT, params);
params.onDocIndicator = BREAK;
params.onTabInIndentation = THROW; // can have a simple key only if we ended the scalar by starting a new line
m_simpleKeyAllowed = params.leadingSpaces;
// insert a potential simple key m_canBeJSONFlow = false;
InsertPotentialSimpleKey();
// finally, check and see if we ended on an illegal character
Mark mark = INPUT.mark(); // if(Exp::IllegalCharInScalar.Matches(INPUT))
scalar = ScanScalar(INPUT, params); // throw ParserException(INPUT.mark(), ErrorMsg::CHAR_IN_SCALAR);
// can have a simple key only if we ended the scalar by starting a new line Token token(Token::PLAIN_SCALAR, mark);
m_simpleKeyAllowed = params.leadingSpaces; token.value = scalar;
m_canBeJSONFlow = false; m_tokens.push(token);
}
// finally, check and see if we ended on an illegal character
//if(Exp::IllegalCharInScalar.Matches(INPUT)) // QuotedScalar
// throw ParserException(INPUT.mark(), ErrorMsg::CHAR_IN_SCALAR); void Scanner::ScanQuotedScalar() {
std::string scalar;
Token token(Token::PLAIN_SCALAR, mark);
token.value = scalar; // peek at single or double quote (don't eat because we need to preserve (for
m_tokens.push(token); // the time being) the input position)
} char quote = INPUT.peek();
bool single = (quote == '\'');
// QuotedScalar
void Scanner::ScanQuotedScalar() // setup the scanning parameters
{ ScanScalarParams params;
std::string scalar; params.end = (single ? RegEx(quote) && !Exp::EscSingleQuote() : RegEx(quote));
params.eatEnd = true;
// peek at single or double quote (don't eat because we need to preserve (for the time being) the input position) params.escape = (single ? '\'' : '\\');
char quote = INPUT.peek(); params.indent = 0;
bool single = (quote == '\''); params.fold = FOLD_FLOW;
params.eatLeadingWhitespace = true;
// setup the scanning parameters params.trimTrailingSpaces = false;
ScanScalarParams params; params.chomp = CLIP;
params.end = (single ? RegEx(quote) && !Exp::EscSingleQuote() : RegEx(quote)); params.onDocIndicator = THROW;
params.eatEnd = true;
params.escape = (single ? '\'' : '\\'); // insert a potential simple key
params.indent = 0; InsertPotentialSimpleKey();
params.fold = FOLD_FLOW;
params.eatLeadingWhitespace = true; Mark mark = INPUT.mark();
params.trimTrailingSpaces = false;
params.chomp = CLIP; // now eat that opening quote
params.onDocIndicator = THROW; INPUT.get();
// insert a potential simple key // and scan
InsertPotentialSimpleKey(); scalar = ScanScalar(INPUT, params);
m_simpleKeyAllowed = false;
Mark mark = INPUT.mark(); m_canBeJSONFlow = true;
// now eat that opening quote Token token(Token::NON_PLAIN_SCALAR, mark);
INPUT.get(); token.value = scalar;
m_tokens.push(token);
// and scan }
scalar = ScanScalar(INPUT, params);
m_simpleKeyAllowed = false; // BlockScalarToken
m_canBeJSONFlow = true; // . These need a little extra processing beforehand.
// . We need to scan the line where the indicator is (this doesn't count as part
Token token(Token::NON_PLAIN_SCALAR, mark); // of the scalar),
token.value = scalar; // and then we need to figure out what level of indentation we'll be using.
m_tokens.push(token); void Scanner::ScanBlockScalar() {
} std::string scalar;
// BlockScalarToken ScanScalarParams params;
// . These need a little extra processing beforehand. params.indent = 1;
// . We need to scan the line where the indicator is (this doesn't count as part of the scalar), params.detectIndent = true;
// and then we need to figure out what level of indentation we'll be using.
void Scanner::ScanBlockScalar() // eat block indicator ('|' or '>')
{ Mark mark = INPUT.mark();
std::string scalar; char indicator = INPUT.get();
params.fold = (indicator == Keys::FoldedScalar ? FOLD_BLOCK : DONT_FOLD);
ScanScalarParams params;
params.indent = 1; // eat chomping/indentation indicators
params.detectIndent = true; params.chomp = CLIP;
int n = Exp::Chomp().Match(INPUT);
// eat block indicator ('|' or '>') for (int i = 0; i < n; i++) {
Mark mark = INPUT.mark(); char ch = INPUT.get();
char indicator = INPUT.get(); if (ch == '+')
params.fold = (indicator == Keys::FoldedScalar ? FOLD_BLOCK : DONT_FOLD); params.chomp = KEEP;
else if (ch == '-')
// eat chomping/indentation indicators params.chomp = STRIP;
params.chomp = CLIP; else if (Exp::Digit().Matches(ch)) {
int n = Exp::Chomp().Match(INPUT); if (ch == '0')
for(int i=0;i<n;i++) { throw ParserException(INPUT.mark(), ErrorMsg::ZERO_INDENT_IN_BLOCK);
char ch = INPUT.get();
if(ch == '+') params.indent = ch - '0';
params.chomp = KEEP; params.detectIndent = false;
else if(ch == '-') }
params.chomp = STRIP; }
else if(Exp::Digit().Matches(ch)) {
if(ch == '0') // now eat whitespace
throw ParserException(INPUT.mark(), ErrorMsg::ZERO_INDENT_IN_BLOCK); while (Exp::Blank().Matches(INPUT))
INPUT.eat(1);
params.indent = ch - '0';
params.detectIndent = false; // and comments to the end of the line
} if (Exp::Comment().Matches(INPUT))
} while (INPUT && !Exp::Break().Matches(INPUT))
INPUT.eat(1);
// now eat whitespace
while(Exp::Blank().Matches(INPUT)) // if it's not a line break, then we ran into a bad character inline
INPUT.eat(1); if (INPUT && !Exp::Break().Matches(INPUT))
throw ParserException(INPUT.mark(), ErrorMsg::CHAR_IN_BLOCK);
// and comments to the end of the line
if(Exp::Comment().Matches(INPUT)) // set the initial indentation
while(INPUT && !Exp::Break().Matches(INPUT)) if (GetTopIndent() >= 0)
INPUT.eat(1); params.indent += GetTopIndent();
// if it's not a line break, then we ran into a bad character inline params.eatLeadingWhitespace = false;
if(INPUT && !Exp::Break().Matches(INPUT)) params.trimTrailingSpaces = false;
throw ParserException(INPUT.mark(), ErrorMsg::CHAR_IN_BLOCK); params.onTabInIndentation = THROW;
// set the initial indentation scalar = ScanScalar(INPUT, params);
if(GetTopIndent() >= 0)
params.indent += GetTopIndent(); // simple keys always ok after block scalars (since we're gonna start a new
// line anyways)
params.eatLeadingWhitespace = false; m_simpleKeyAllowed = true;
params.trimTrailingSpaces = false; m_canBeJSONFlow = false;
params.onTabInIndentation = THROW;
Token token(Token::NON_PLAIN_SCALAR, mark);
scalar = ScanScalar(INPUT, params); token.value = scalar;
m_tokens.push(token);
// 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::NON_PLAIN_SCALAR, mark);
token.value = scalar;
m_tokens.push(token);
}
} }

View File

@@ -1,105 +1,99 @@
#ifndef SETTING_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef SETTING_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define SETTING_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define SETTING_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
#include <memory> #include <memory>
#include <vector> #include <vector>
#include "yaml-cpp/noncopyable.h" #include "yaml-cpp/noncopyable.h"
namespace YAML namespace YAML {
{ class SettingChangeBase;
class SettingChangeBase;
template <typename T> template <typename T>
class Setting class Setting {
{ public:
public: Setting() : m_value() {}
Setting(): m_value() {}
const T get() const { return m_value; } const T get() const { return m_value; }
std::auto_ptr <SettingChangeBase> set(const T& value); std::auto_ptr<SettingChangeBase> set(const T& value);
void restore(const Setting<T>& oldSetting) { void restore(const Setting<T>& oldSetting) { m_value = oldSetting.get(); }
m_value = oldSetting.get();
}
private: private:
T m_value; T m_value;
}; };
class SettingChangeBase class SettingChangeBase {
{ public:
public: virtual ~SettingChangeBase() {}
virtual ~SettingChangeBase() {} virtual void pop() = 0;
virtual void pop() = 0; };
};
template <typename T> template <typename T>
class SettingChange: public SettingChangeBase class SettingChange : public SettingChangeBase {
{ public:
public: SettingChange(Setting<T>* pSetting) : m_pCurSetting(pSetting) {
SettingChange(Setting<T> *pSetting): m_pCurSetting(pSetting) { // copy old setting to save its state
// copy old setting to save its state m_oldSetting = *pSetting;
m_oldSetting = *pSetting; }
}
virtual void pop() { virtual void pop() { m_pCurSetting->restore(m_oldSetting); }
m_pCurSetting->restore(m_oldSetting);
}
private: private:
Setting<T> *m_pCurSetting; Setting<T>* m_pCurSetting;
Setting<T> m_oldSetting; Setting<T> m_oldSetting;
}; };
template <typename T> template <typename T>
inline std::auto_ptr <SettingChangeBase> Setting<T>::set(const T& value) { inline std::auto_ptr<SettingChangeBase> Setting<T>::set(const T& value) {
std::auto_ptr <SettingChangeBase> pChange(new SettingChange<T> (this)); std::auto_ptr<SettingChangeBase> pChange(new SettingChange<T>(this));
m_value = value; m_value = value;
return pChange; 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 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

View File

@@ -3,137 +3,126 @@
#include "yaml-cpp/exceptions.h" #include "yaml-cpp/exceptions.h"
#include "exp.h" #include "exp.h"
namespace YAML namespace YAML {
{ Scanner::SimpleKey::SimpleKey(const Mark& mark_, int flowLevel_)
Scanner::SimpleKey::SimpleKey(const Mark& mark_, int flowLevel_) : mark(mark_), flowLevel(flowLevel_), pIndent(0), pMapStart(0), pKey(0) {}
: mark(mark_), flowLevel(flowLevel_), pIndent(0), pMapStart(0), pKey(0)
{
}
void Scanner::SimpleKey::Validate() void Scanner::SimpleKey::Validate() {
{ // Note: pIndent will *not* be garbage here;
// Note: pIndent will *not* be garbage here; // we "garbage collect" them so we can
// we "garbage collect" them so we can // always refer to them
// always refer to them if (pIndent)
if(pIndent) pIndent->status = IndentMarker::VALID;
pIndent->status = IndentMarker::VALID; if (pMapStart)
if(pMapStart) pMapStart->status = Token::VALID;
pMapStart->status = Token::VALID; if (pKey)
if(pKey) pKey->status = Token::VALID;
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();
}
} }
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();
}
}

View File

@@ -10,385 +10,394 @@
#include <cstdio> #include <cstdio>
#include <algorithm> #include <algorithm>
namespace YAML namespace YAML {
{ SingleDocParser::SingleDocParser(Scanner& scanner, const Directives& directives)
SingleDocParser::SingleDocParser(Scanner& scanner, const Directives& directives): m_scanner(scanner), m_directives(directives), m_pCollectionStack(new CollectionStack), m_curAnchor(0) : m_scanner(scanner),
{ m_directives(directives),
} m_pCollectionStack(new CollectionStack),
m_curAnchor(0) {}
SingleDocParser::~SingleDocParser() SingleDocParser::~SingleDocParser() {}
{
}
// HandleDocument // HandleDocument
// . Handles the next document // . Handles the next document
// . Throws a ParserException on error. // . Throws a ParserException on error.
void SingleDocParser::HandleDocument(EventHandler& eventHandler) void SingleDocParser::HandleDocument(EventHandler& eventHandler) {
{ assert(!m_scanner.empty()); // guaranteed that there are tokens
assert(!m_scanner.empty()); // guaranteed that there are tokens assert(!m_curAnchor);
assert(!m_curAnchor);
eventHandler.OnDocumentStart(m_scanner.peek().mark); eventHandler.OnDocumentStart(m_scanner.peek().mark);
// eat doc start // eat doc start
if(m_scanner.peek().type == Token::DOC_START) if (m_scanner.peek().type == Token::DOC_START)
m_scanner.pop(); m_scanner.pop();
// recurse! // recurse!
HandleNode(eventHandler); HandleNode(eventHandler);
eventHandler.OnDocumentEnd(); eventHandler.OnDocumentEnd();
// and finally eat any doc ends we see // and finally eat any doc ends we see
while(!m_scanner.empty() && m_scanner.peek().type == Token::DOC_END) while (!m_scanner.empty() && m_scanner.peek().type == Token::DOC_END)
m_scanner.pop(); m_scanner.pop();
} }
void SingleDocParser::HandleNode(EventHandler& eventHandler) void SingleDocParser::HandleNode(EventHandler& eventHandler) {
{ // an empty node *is* a possibility
// an empty node *is* a possibility if (m_scanner.empty()) {
if(m_scanner.empty()) { eventHandler.OnNull(m_scanner.mark(), NullAnchor);
eventHandler.OnNull(m_scanner.mark(), NullAnchor); return;
return; }
}
// save location
// save location Mark mark = m_scanner.peek().mark;
Mark mark = m_scanner.peek().mark;
// special case: a value node by itself must be a map, with no header
// special case: a value node by itself must be a map, with no header if (m_scanner.peek().type == Token::VALUE) {
if(m_scanner.peek().type == Token::VALUE) { eventHandler.OnMapStart(mark, "?", NullAnchor);
eventHandler.OnMapStart(mark, "?", NullAnchor); HandleMap(eventHandler);
HandleMap(eventHandler); eventHandler.OnMapEnd();
eventHandler.OnMapEnd(); return;
return; }
}
// special case: an alias node
// special case: an alias node if (m_scanner.peek().type == Token::ALIAS) {
if(m_scanner.peek().type == Token::ALIAS) { eventHandler.OnAlias(mark, LookupAnchor(mark, m_scanner.peek().value));
eventHandler.OnAlias(mark, LookupAnchor(mark, m_scanner.peek().value)); m_scanner.pop();
m_scanner.pop(); return;
return; }
}
std::string tag;
std::string tag; anchor_t anchor;
anchor_t anchor; ParseProperties(tag, anchor);
ParseProperties(tag, anchor);
const Token& token = m_scanner.peek();
const Token& token = m_scanner.peek();
if (token.type == Token::PLAIN_SCALAR && token.value == "null") {
if(token.type == Token::PLAIN_SCALAR && token.value == "null") { eventHandler.OnNull(mark, anchor);
eventHandler.OnNull(mark, anchor); m_scanner.pop();
m_scanner.pop(); return;
return; }
}
// add non-specific tags
// add non-specific tags if (tag.empty())
if(tag.empty()) tag = (token.type == Token::NON_PLAIN_SCALAR ? "!" : "?");
tag = (token.type == Token::NON_PLAIN_SCALAR ? "!" : "?");
// now split based on what kind of node we should be
// now split based on what kind of node we should be switch (token.type) {
switch(token.type) { case Token::PLAIN_SCALAR:
case Token::PLAIN_SCALAR: case Token::NON_PLAIN_SCALAR:
case Token::NON_PLAIN_SCALAR: eventHandler.OnScalar(mark, tag, anchor, token.value);
eventHandler.OnScalar(mark, tag, anchor, token.value); m_scanner.pop();
m_scanner.pop(); return;
return; case Token::FLOW_SEQ_START:
case Token::FLOW_SEQ_START: case Token::BLOCK_SEQ_START:
case Token::BLOCK_SEQ_START: eventHandler.OnSequenceStart(mark, tag, anchor);
eventHandler.OnSequenceStart(mark, tag, anchor); HandleSequence(eventHandler);
HandleSequence(eventHandler); eventHandler.OnSequenceEnd();
eventHandler.OnSequenceEnd(); return;
return; case Token::FLOW_MAP_START:
case Token::FLOW_MAP_START: case Token::BLOCK_MAP_START:
case Token::BLOCK_MAP_START: eventHandler.OnMapStart(mark, tag, anchor);
eventHandler.OnMapStart(mark, tag, anchor); HandleMap(eventHandler);
HandleMap(eventHandler); eventHandler.OnMapEnd();
eventHandler.OnMapEnd(); return;
return; case Token::KEY:
case Token::KEY: // compact maps can only go in a flow sequence
// compact maps can only go in a flow sequence if (m_pCollectionStack->GetCurCollectionType() ==
if(m_pCollectionStack->GetCurCollectionType() == CollectionType::FlowSeq) { CollectionType::FlowSeq) {
eventHandler.OnMapStart(mark, tag, anchor); eventHandler.OnMapStart(mark, tag, anchor);
HandleMap(eventHandler); HandleMap(eventHandler);
eventHandler.OnMapEnd(); eventHandler.OnMapEnd();
return; return;
} }
break; break;
default: default:
break; break;
} }
if(tag == "?") if (tag == "?")
eventHandler.OnNull(mark, anchor); eventHandler.OnNull(mark, anchor);
else else
eventHandler.OnScalar(mark, tag, anchor, ""); eventHandler.OnScalar(mark, tag, anchor, "");
} }
void SingleDocParser::HandleSequence(EventHandler& eventHandler) void SingleDocParser::HandleSequence(EventHandler& eventHandler) {
{ // split based on start token
// split based on start token switch (m_scanner.peek().type) {
switch(m_scanner.peek().type) { case Token::BLOCK_SEQ_START:
case Token::BLOCK_SEQ_START: HandleBlockSequence(eventHandler); break; HandleBlockSequence(eventHandler);
case Token::FLOW_SEQ_START: HandleFlowSequence(eventHandler); break; break;
default: break; case Token::FLOW_SEQ_START:
} HandleFlowSequence(eventHandler);
} break;
default:
void SingleDocParser::HandleBlockSequence(EventHandler& eventHandler) break;
{ }
// eat start token }
m_scanner.pop();
m_pCollectionStack->PushCollectionType(CollectionType::BlockSeq); void SingleDocParser::HandleBlockSequence(EventHandler& eventHandler) {
// eat start token
while(1) { m_scanner.pop();
if(m_scanner.empty()) m_pCollectionStack->PushCollectionType(CollectionType::BlockSeq);
throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_SEQ);
while (1) {
Token token = m_scanner.peek(); if (m_scanner.empty())
if(token.type != Token::BLOCK_ENTRY && token.type != Token::BLOCK_SEQ_END) throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_SEQ);
throw ParserException(token.mark, ErrorMsg::END_OF_SEQ);
Token token = m_scanner.peek();
m_scanner.pop(); if (token.type != Token::BLOCK_ENTRY && token.type != Token::BLOCK_SEQ_END)
if(token.type == Token::BLOCK_SEQ_END) throw ParserException(token.mark, ErrorMsg::END_OF_SEQ);
break;
m_scanner.pop();
// check for null if (token.type == Token::BLOCK_SEQ_END)
if(!m_scanner.empty()) { break;
const Token& token = m_scanner.peek();
if(token.type == Token::BLOCK_ENTRY || token.type == Token::BLOCK_SEQ_END) { // check for null
eventHandler.OnNull(token.mark, NullAnchor); if (!m_scanner.empty()) {
continue; const Token& token = m_scanner.peek();
} if (token.type == Token::BLOCK_ENTRY ||
} token.type == Token::BLOCK_SEQ_END) {
eventHandler.OnNull(token.mark, NullAnchor);
HandleNode(eventHandler); continue;
} }
}
m_pCollectionStack->PopCollectionType(CollectionType::BlockSeq);
} HandleNode(eventHandler);
}
void SingleDocParser::HandleFlowSequence(EventHandler& eventHandler)
{ m_pCollectionStack->PopCollectionType(CollectionType::BlockSeq);
// eat start token }
m_scanner.pop();
m_pCollectionStack->PushCollectionType(CollectionType::FlowSeq); void SingleDocParser::HandleFlowSequence(EventHandler& eventHandler) {
// eat start token
while(1) { m_scanner.pop();
if(m_scanner.empty()) m_pCollectionStack->PushCollectionType(CollectionType::FlowSeq);
throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_SEQ_FLOW);
while (1) {
// first check for end if (m_scanner.empty())
if(m_scanner.peek().type == Token::FLOW_SEQ_END) { throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_SEQ_FLOW);
m_scanner.pop();
break; // first check for end
} if (m_scanner.peek().type == Token::FLOW_SEQ_END) {
m_scanner.pop();
// then read the node break;
HandleNode(eventHandler); }
if(m_scanner.empty()) // then read the node
throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_SEQ_FLOW); HandleNode(eventHandler);
// now eat the separator (or could be a sequence end, which we ignore - but if it's neither, then it's a bad node) if (m_scanner.empty())
Token& token = m_scanner.peek(); throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_SEQ_FLOW);
if(token.type == Token::FLOW_ENTRY)
m_scanner.pop(); // now eat the separator (or could be a sequence end, which we ignore - but
else if(token.type != Token::FLOW_SEQ_END) // if it's neither, then it's a bad node)
throw ParserException(token.mark, ErrorMsg::END_OF_SEQ_FLOW); Token& token = m_scanner.peek();
} if (token.type == Token::FLOW_ENTRY)
m_scanner.pop();
m_pCollectionStack->PopCollectionType(CollectionType::FlowSeq); else if (token.type != Token::FLOW_SEQ_END)
} throw ParserException(token.mark, ErrorMsg::END_OF_SEQ_FLOW);
}
void SingleDocParser::HandleMap(EventHandler& eventHandler)
{ m_pCollectionStack->PopCollectionType(CollectionType::FlowSeq);
// split based on start token }
switch(m_scanner.peek().type) {
case Token::BLOCK_MAP_START: HandleBlockMap(eventHandler); break; void SingleDocParser::HandleMap(EventHandler& eventHandler) {
case Token::FLOW_MAP_START: HandleFlowMap(eventHandler); break; // split based on start token
case Token::KEY: HandleCompactMap(eventHandler); break; switch (m_scanner.peek().type) {
case Token::VALUE: HandleCompactMapWithNoKey(eventHandler); break; case Token::BLOCK_MAP_START:
default: break; HandleBlockMap(eventHandler);
} break;
} case Token::FLOW_MAP_START:
HandleFlowMap(eventHandler);
void SingleDocParser::HandleBlockMap(EventHandler& eventHandler) break;
{ case Token::KEY:
// eat start token HandleCompactMap(eventHandler);
m_scanner.pop(); break;
m_pCollectionStack->PushCollectionType(CollectionType::BlockMap); case Token::VALUE:
HandleCompactMapWithNoKey(eventHandler);
while(1) { break;
if(m_scanner.empty()) default:
throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_MAP); break;
}
Token token = m_scanner.peek(); }
if(token.type != Token::KEY && token.type != Token::VALUE && token.type != Token::BLOCK_MAP_END)
throw ParserException(token.mark, ErrorMsg::END_OF_MAP); void SingleDocParser::HandleBlockMap(EventHandler& eventHandler) {
// eat start token
if(token.type == Token::BLOCK_MAP_END) { m_scanner.pop();
m_scanner.pop(); m_pCollectionStack->PushCollectionType(CollectionType::BlockMap);
break;
} while (1) {
if (m_scanner.empty())
// grab key (if non-null) throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_MAP);
if(token.type == Token::KEY) {
m_scanner.pop(); Token token = m_scanner.peek();
HandleNode(eventHandler); if (token.type != Token::KEY && token.type != Token::VALUE &&
} else { token.type != Token::BLOCK_MAP_END)
eventHandler.OnNull(token.mark, NullAnchor); throw ParserException(token.mark, ErrorMsg::END_OF_MAP);
}
if (token.type == Token::BLOCK_MAP_END) {
// now grab value (optional) m_scanner.pop();
if(!m_scanner.empty() && m_scanner.peek().type == Token::VALUE) { break;
m_scanner.pop(); }
HandleNode(eventHandler);
} else { // grab key (if non-null)
eventHandler.OnNull(token.mark, NullAnchor); if (token.type == Token::KEY) {
} m_scanner.pop();
} HandleNode(eventHandler);
} else {
m_pCollectionStack->PopCollectionType(CollectionType::BlockMap); eventHandler.OnNull(token.mark, NullAnchor);
} }
void SingleDocParser::HandleFlowMap(EventHandler& eventHandler) // now grab value (optional)
{ if (!m_scanner.empty() && m_scanner.peek().type == Token::VALUE) {
// eat start token m_scanner.pop();
m_scanner.pop(); HandleNode(eventHandler);
m_pCollectionStack->PushCollectionType(CollectionType::FlowMap); } else {
eventHandler.OnNull(token.mark, NullAnchor);
while(1) { }
if(m_scanner.empty()) }
throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_MAP_FLOW);
m_pCollectionStack->PopCollectionType(CollectionType::BlockMap);
Token& token = m_scanner.peek(); }
const Mark mark = token.mark;
// first check for end void SingleDocParser::HandleFlowMap(EventHandler& eventHandler) {
if(token.type == Token::FLOW_MAP_END) { // eat start token
m_scanner.pop(); m_scanner.pop();
break; m_pCollectionStack->PushCollectionType(CollectionType::FlowMap);
}
while (1) {
// grab key (if non-null) if (m_scanner.empty())
if(token.type == Token::KEY) { throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_MAP_FLOW);
m_scanner.pop();
HandleNode(eventHandler); Token& token = m_scanner.peek();
} else { const Mark mark = token.mark;
eventHandler.OnNull(mark, NullAnchor); // first check for end
} if (token.type == Token::FLOW_MAP_END) {
m_scanner.pop();
// now grab value (optional) break;
if(!m_scanner.empty() && m_scanner.peek().type == Token::VALUE) { }
m_scanner.pop();
HandleNode(eventHandler); // grab key (if non-null)
} else { if (token.type == Token::KEY) {
eventHandler.OnNull(mark, NullAnchor); m_scanner.pop();
} HandleNode(eventHandler);
} else {
if(m_scanner.empty()) eventHandler.OnNull(mark, NullAnchor);
throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_MAP_FLOW); }
// now eat the separator (or could be a map end, which we ignore - but if it's neither, then it's a bad node) // now grab value (optional)
Token& nextToken = m_scanner.peek(); if (!m_scanner.empty() && m_scanner.peek().type == Token::VALUE) {
if(nextToken.type == Token::FLOW_ENTRY) m_scanner.pop();
m_scanner.pop(); HandleNode(eventHandler);
else if(nextToken.type != Token::FLOW_MAP_END) } else {
throw ParserException(nextToken.mark, ErrorMsg::END_OF_MAP_FLOW); eventHandler.OnNull(mark, NullAnchor);
} }
m_pCollectionStack->PopCollectionType(CollectionType::FlowMap); if (m_scanner.empty())
} throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_MAP_FLOW);
// . Single "key: value" pair in a flow sequence // now eat the separator (or could be a map end, which we ignore - but if
void SingleDocParser::HandleCompactMap(EventHandler& eventHandler) // it's neither, then it's a bad node)
{ Token& nextToken = m_scanner.peek();
m_pCollectionStack->PushCollectionType(CollectionType::CompactMap); if (nextToken.type == Token::FLOW_ENTRY)
m_scanner.pop();
// grab key else if (nextToken.type != Token::FLOW_MAP_END)
Mark mark = m_scanner.peek().mark; throw ParserException(nextToken.mark, ErrorMsg::END_OF_MAP_FLOW);
m_scanner.pop(); }
HandleNode(eventHandler);
m_pCollectionStack->PopCollectionType(CollectionType::FlowMap);
// now grab value (optional) }
if(!m_scanner.empty() && m_scanner.peek().type == Token::VALUE) {
m_scanner.pop(); // . Single "key: value" pair in a flow sequence
HandleNode(eventHandler); void SingleDocParser::HandleCompactMap(EventHandler& eventHandler) {
} else { m_pCollectionStack->PushCollectionType(CollectionType::CompactMap);
eventHandler.OnNull(mark, NullAnchor);
} // grab key
Mark mark = m_scanner.peek().mark;
m_pCollectionStack->PopCollectionType(CollectionType::CompactMap); m_scanner.pop();
} HandleNode(eventHandler);
// . Single ": value" pair in a flow sequence // now grab value (optional)
void SingleDocParser::HandleCompactMapWithNoKey(EventHandler& eventHandler) if (!m_scanner.empty() && m_scanner.peek().type == Token::VALUE) {
{ m_scanner.pop();
m_pCollectionStack->PushCollectionType(CollectionType::CompactMap); HandleNode(eventHandler);
} else {
// null key eventHandler.OnNull(mark, NullAnchor);
eventHandler.OnNull(m_scanner.peek().mark, NullAnchor); }
// grab value m_pCollectionStack->PopCollectionType(CollectionType::CompactMap);
m_scanner.pop(); }
HandleNode(eventHandler);
// . Single ": value" pair in a flow sequence
m_pCollectionStack->PopCollectionType(CollectionType::CompactMap); void SingleDocParser::HandleCompactMapWithNoKey(EventHandler& eventHandler) {
} m_pCollectionStack->PushCollectionType(CollectionType::CompactMap);
// ParseProperties // null key
// . Grabs any tag or anchor tokens and deals with them. eventHandler.OnNull(m_scanner.peek().mark, NullAnchor);
void SingleDocParser::ParseProperties(std::string& tag, anchor_t& anchor)
{ // grab value
tag.clear(); m_scanner.pop();
anchor = NullAnchor; HandleNode(eventHandler);
while(1) { m_pCollectionStack->PopCollectionType(CollectionType::CompactMap);
if(m_scanner.empty()) }
return;
// ParseProperties
switch(m_scanner.peek().type) { // . Grabs any tag or anchor tokens and deals with them.
case Token::TAG: ParseTag(tag); break; void SingleDocParser::ParseProperties(std::string& tag, anchor_t& anchor) {
case Token::ANCHOR: ParseAnchor(anchor); break; tag.clear();
default: return; anchor = NullAnchor;
}
} while (1) {
} if (m_scanner.empty())
return;
void SingleDocParser::ParseTag(std::string& tag)
{ switch (m_scanner.peek().type) {
Token& token = m_scanner.peek(); case Token::TAG:
if(!tag.empty()) ParseTag(tag);
throw ParserException(token.mark, ErrorMsg::MULTIPLE_TAGS); break;
case Token::ANCHOR:
Tag tagInfo(token); ParseAnchor(anchor);
tag = tagInfo.Translate(m_directives); break;
m_scanner.pop(); default:
} return;
}
void SingleDocParser::ParseAnchor(anchor_t& anchor) }
{ }
Token& token = m_scanner.peek();
if(anchor) void SingleDocParser::ParseTag(std::string& tag) {
throw ParserException(token.mark, ErrorMsg::MULTIPLE_ANCHORS); Token& token = m_scanner.peek();
if (!tag.empty())
anchor = RegisterAnchor(token.value); throw ParserException(token.mark, ErrorMsg::MULTIPLE_TAGS);
m_scanner.pop();
} Tag tagInfo(token);
tag = tagInfo.Translate(m_directives);
anchor_t SingleDocParser::RegisterAnchor(const std::string& name) m_scanner.pop();
{ }
if(name.empty())
return NullAnchor; void SingleDocParser::ParseAnchor(anchor_t& anchor) {
Token& token = m_scanner.peek();
return m_anchors[name] = ++m_curAnchor; if (anchor)
} throw ParserException(token.mark, ErrorMsg::MULTIPLE_ANCHORS);
anchor_t SingleDocParser::LookupAnchor(const Mark& mark, const std::string& name) const anchor = RegisterAnchor(token.value);
{ m_scanner.pop();
Anchors::const_iterator it = m_anchors.find(name); }
if(it == m_anchors.end())
throw ParserException(mark, ErrorMsg::UNKNOWN_ANCHOR); anchor_t SingleDocParser::RegisterAnchor(const std::string& name) {
if (name.empty())
return it->second; return NullAnchor;
}
return m_anchors[name] = ++m_curAnchor;
}
anchor_t SingleDocParser::LookupAnchor(const Mark& mark,
const std::string& name) const {
Anchors::const_iterator it = m_anchors.find(name);
if (it == m_anchors.end())
throw ParserException(mark, ErrorMsg::UNKNOWN_ANCHOR);
return it->second;
}
} }

View File

@@ -1,65 +1,64 @@
#ifndef SINGLEDOCPARSER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef SINGLEDOCPARSER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define SINGLEDOCPARSER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define SINGLEDOCPARSER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
#include "yaml-cpp/anchor.h" #include "yaml-cpp/anchor.h"
#include "yaml-cpp/noncopyable.h" #include "yaml-cpp/noncopyable.h"
#include <string> #include <string>
#include <map> #include <map>
#include <memory> #include <memory>
namespace YAML namespace YAML {
{ struct Directives;
struct Directives; struct Mark;
struct Mark; struct Token;
struct Token; class CollectionStack;
class CollectionStack; class EventHandler;
class EventHandler; class Node;
class Node; class Scanner;
class Scanner;
class SingleDocParser: private noncopyable class SingleDocParser : private noncopyable {
{ public:
public: SingleDocParser(Scanner& scanner, const Directives& directives);
SingleDocParser(Scanner& scanner, const Directives& directives); ~SingleDocParser();
~SingleDocParser();
void HandleDocument(EventHandler& eventHandler); void HandleDocument(EventHandler& eventHandler);
private: private:
void HandleNode(EventHandler& eventHandler); void HandleNode(EventHandler& eventHandler);
void HandleSequence(EventHandler& eventHandler); void HandleSequence(EventHandler& eventHandler);
void HandleBlockSequence(EventHandler& eventHandler); void HandleBlockSequence(EventHandler& eventHandler);
void HandleFlowSequence(EventHandler& eventHandler); void HandleFlowSequence(EventHandler& eventHandler);
void HandleMap(EventHandler& eventHandler); void HandleMap(EventHandler& eventHandler);
void HandleBlockMap(EventHandler& eventHandler); void HandleBlockMap(EventHandler& eventHandler);
void HandleFlowMap(EventHandler& eventHandler); void HandleFlowMap(EventHandler& eventHandler);
void HandleCompactMap(EventHandler& eventHandler); void HandleCompactMap(EventHandler& eventHandler);
void HandleCompactMapWithNoKey(EventHandler& eventHandler); void HandleCompactMapWithNoKey(EventHandler& eventHandler);
void ParseProperties(std::string& tag, anchor_t& anchor); void ParseProperties(std::string& tag, anchor_t& anchor);
void ParseTag(std::string& tag); void ParseTag(std::string& tag);
void ParseAnchor(anchor_t& anchor); void ParseAnchor(anchor_t& anchor);
anchor_t RegisterAnchor(const std::string& name); anchor_t RegisterAnchor(const std::string& name);
anchor_t LookupAnchor(const Mark& mark, const std::string& name) const; anchor_t LookupAnchor(const Mark& mark, const std::string& name) const;
private: private:
Scanner& m_scanner; Scanner& m_scanner;
const Directives& m_directives; const Directives& m_directives;
std::auto_ptr<CollectionStack> m_pCollectionStack; std::auto_ptr<CollectionStack> m_pCollectionStack;
typedef std::map<std::string, anchor_t> Anchors; typedef std::map<std::string, anchor_t> Anchors;
Anchors m_anchors; Anchors m_anchors;
anchor_t m_curAnchor; anchor_t m_curAnchor;
}; };
} }
#endif // SINGLEDOCPARSER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #endif // SINGLEDOCPARSER_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -6,442 +6,439 @@
#define YAML_PREFETCH_SIZE 2048 #define YAML_PREFETCH_SIZE 2048
#endif #endif
#define S_ARRAY_SIZE( A ) (sizeof(A)/sizeof(*(A))) #define S_ARRAY_SIZE(A) (sizeof(A) / sizeof(*(A)))
#define S_ARRAY_END( A ) ((A) + S_ARRAY_SIZE(A)) #define S_ARRAY_END(A) ((A) + S_ARRAY_SIZE(A))
#define CP_REPLACEMENT_CHARACTER (0xFFFD) #define CP_REPLACEMENT_CHARACTER (0xFFFD)
namespace YAML namespace YAML {
{ enum UtfIntroState {
enum UtfIntroState { uis_start,
uis_start, uis_utfbe_b1,
uis_utfbe_b1, uis_utf32be_b2,
uis_utf32be_b2, uis_utf32be_bom3,
uis_utf32be_bom3, uis_utf32be,
uis_utf32be, uis_utf16be,
uis_utf16be, uis_utf16be_bom1,
uis_utf16be_bom1, uis_utfle_bom1,
uis_utfle_bom1, uis_utf16le_bom2,
uis_utf16le_bom2, uis_utf32le_bom3,
uis_utf32le_bom3, uis_utf16le,
uis_utf16le, uis_utf32le,
uis_utf32le, uis_utf8_imp,
uis_utf8_imp, uis_utf16le_imp,
uis_utf16le_imp, uis_utf32le_imp3,
uis_utf32le_imp3, uis_utf8_bom1,
uis_utf8_bom1, uis_utf8_bom2,
uis_utf8_bom2, uis_utf8,
uis_utf8, uis_error
uis_error };
};
enum UtfIntroCharType { enum UtfIntroCharType {
uict00, uict00,
uictBB, uictBB,
uictBF, uictBF,
uictEF, uictEF,
uictFE, uictFE,
uictFF, uictFF,
uictAscii, uictAscii,
uictOther, uictOther,
uictMax uictMax
}; };
static bool s_introFinalState[] = { static bool s_introFinalState[] = {false, // uis_start
false, //uis_start false, // uis_utfbe_b1
false, //uis_utfbe_b1 false, // uis_utf32be_b2
false, //uis_utf32be_b2 false, // uis_utf32be_bom3
false, //uis_utf32be_bom3 true, // uis_utf32be
true, //uis_utf32be true, // uis_utf16be
true, //uis_utf16be false, // uis_utf16be_bom1
false, //uis_utf16be_bom1 false, // uis_utfle_bom1
false, //uis_utfle_bom1 false, // uis_utf16le_bom2
false, //uis_utf16le_bom2 false, // uis_utf32le_bom3
false, //uis_utf32le_bom3 true, // uis_utf16le
true, //uis_utf16le true, // uis_utf32le
true, //uis_utf32le false, // uis_utf8_imp
false, //uis_utf8_imp false, // uis_utf16le_imp
false, //uis_utf16le_imp false, // uis_utf32le_imp3
false, //uis_utf32le_imp3 false, // uis_utf8_bom1
false, //uis_utf8_bom1 false, // uis_utf8_bom2
false, //uis_utf8_bom2 true, // uis_utf8
true, //uis_utf8 true, // uis_error
true, //uis_error };
};
static UtfIntroState s_introTransitions[][uictMax] = { static UtfIntroState s_introTransitions[][uictMax] = {
// uict00, uictBB, uictBF, uictEF, uictFE, uictFF, uictAscii, uictOther // uict00, uictBB, uictBF, uictEF,
{uis_utfbe_b1, uis_utf8, uis_utf8, uis_utf8_bom1, uis_utf16be_bom1, uis_utfle_bom1, uis_utf8_imp, uis_utf8}, // uictFE, uictFF, uictAscii, uictOther
{uis_utf32be_b2, uis_utf8, uis_utf8, uis_utf8, uis_utf8, uis_utf8, uis_utf16be, uis_utf8}, {uis_utfbe_b1, uis_utf8, uis_utf8, uis_utf8_bom1,
{uis_utf32be, uis_utf8, uis_utf8, uis_utf8, uis_utf32be_bom3, uis_utf8, uis_utf8, uis_utf8}, uis_utf16be_bom1, uis_utfle_bom1, uis_utf8_imp, uis_utf8},
{uis_utf8, uis_utf8, uis_utf8, uis_utf8, uis_utf8, uis_utf32be, uis_utf8, uis_utf8}, {uis_utf32be_b2, uis_utf8, uis_utf8, uis_utf8,
{uis_utf32be, uis_utf32be, uis_utf32be, uis_utf32be, uis_utf32be, uis_utf32be, uis_utf32be, uis_utf32be}, uis_utf8, uis_utf8, uis_utf16be, uis_utf8},
{uis_utf16be, uis_utf16be, uis_utf16be, uis_utf16be, uis_utf16be, uis_utf16be, uis_utf16be, uis_utf16be}, {uis_utf32be, uis_utf8, uis_utf8, uis_utf8,
{uis_utf8, uis_utf8, uis_utf8, uis_utf8, uis_utf8, uis_utf16be, uis_utf8, uis_utf8}, uis_utf32be_bom3, uis_utf8, uis_utf8, uis_utf8},
{uis_utf8, uis_utf8, uis_utf8, uis_utf8, uis_utf16le_bom2, uis_utf8, uis_utf8, uis_utf8}, {uis_utf8, uis_utf8, uis_utf8, uis_utf8,
{uis_utf32le_bom3, uis_utf16le, uis_utf16le, uis_utf16le, uis_utf16le, uis_utf16le, uis_utf16le, uis_utf16le}, uis_utf8, uis_utf32be, uis_utf8, uis_utf8},
{uis_utf32le, uis_utf16le, uis_utf16le, uis_utf16le, uis_utf16le, uis_utf16le, uis_utf16le, uis_utf16le}, {uis_utf32be, uis_utf32be, uis_utf32be, uis_utf32be,
{uis_utf16le, uis_utf16le, uis_utf16le, uis_utf16le, uis_utf16le, uis_utf16le, uis_utf16le, uis_utf16le}, uis_utf32be, uis_utf32be, uis_utf32be, uis_utf32be},
{uis_utf32le, uis_utf32le, uis_utf32le, uis_utf32le, uis_utf32le, uis_utf32le, uis_utf32le, uis_utf32le}, {uis_utf16be, uis_utf16be, uis_utf16be, uis_utf16be,
{uis_utf16le_imp, uis_utf8, uis_utf8, uis_utf8, uis_utf8, uis_utf8, uis_utf8, uis_utf8}, uis_utf16be, uis_utf16be, uis_utf16be, uis_utf16be},
{uis_utf32le_imp3, uis_utf16le, uis_utf16le, uis_utf16le, uis_utf16le, uis_utf16le, uis_utf16le, uis_utf16le}, {uis_utf8, uis_utf8, uis_utf8, uis_utf8,
{uis_utf32le, uis_utf16le, uis_utf16le, uis_utf16le, uis_utf16le, uis_utf16le, uis_utf16le, uis_utf16le}, uis_utf8, uis_utf16be, uis_utf8, uis_utf8},
{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_utf16le_bom2, uis_utf8, uis_utf8, uis_utf8},
{uis_utf8, uis_utf8, uis_utf8, uis_utf8, uis_utf8, 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] = { static char s_introUngetCount[][uictMax] = {
// uict00, uictBB, uictBF, uictEF, uictFE, uictFF, uictAscii, uictOther // uict00, uictBB, uictBF, uictEF, uictFE, uictFF, uictAscii, uictOther
{0, 1, 1, 0, 0, 0, 0, 1}, {0, 1, 1, 0, 0, 0, 0, 1},
{0, 2, 2, 2, 2, 2, 2, 2}, {0, 2, 2, 2, 2, 2, 2, 2},
{3, 3, 3, 3, 0, 3, 3, 3}, {3, 3, 3, 3, 0, 3, 3, 3},
{4, 4, 4, 4, 4, 0, 4, 4}, {4, 4, 4, 4, 4, 0, 4, 4},
{1, 1, 1, 1, 1, 1, 1, 1}, {1, 1, 1, 1, 1, 1, 1, 1},
{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, 2, 0, 2, 2},
{2, 2, 2, 2, 0, 2, 2, 2}, {2, 2, 2, 2, 0, 2, 2, 2},
{0, 1, 1, 1, 1, 1, 1, 1}, {0, 1, 1, 1, 1, 1, 1, 1},
{0, 2, 2, 2, 2, 2, 2, 2}, {0, 2, 2, 2, 2, 2, 2, 2},
{1, 1, 1, 1, 1, 1, 1, 1}, {1, 1, 1, 1, 1, 1, 1, 1},
{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, 2, 2, 2, 2, 2, 2, 2},
{0, 3, 3, 3, 3, 3, 3, 3}, {0, 3, 3, 3, 3, 3, 3, 3},
{4, 4, 4, 4, 4, 4, 4, 4}, {4, 4, 4, 4, 4, 4, 4, 4},
{2, 0, 2, 2, 2, 2, 2, 2}, {2, 0, 2, 2, 2, 2, 2, 2},
{3, 3, 0, 3, 3, 3, 3, 3}, {3, 3, 0, 3, 3, 3, 3, 3},
{1, 1, 1, 1, 1, 1, 1, 1}, {1, 1, 1, 1, 1, 1, 1, 1}, };
};
inline UtfIntroCharType IntroCharTypeOf(std::istream::int_type ch) inline UtfIntroCharType IntroCharTypeOf(std::istream::int_type ch) {
{ if (std::istream::traits_type::eof() == ch) {
if (std::istream::traits_type::eof() == ch) { return uictOther;
return uictOther; }
}
switch (ch) { switch (ch) {
case 0: return uict00; case 0:
case 0xBB: return uictBB; return uict00;
case 0xBF: return uictBF; case 0xBB:
case 0xEF: return uictEF; return uictBB;
case 0xFE: return uictFE; case 0xBF:
case 0xFF: return uictFF; return uictBF;
} case 0xEF:
return uictEF;
case 0xFE:
return uictFE;
case 0xFF:
return uictFF;
}
if ((ch > 0) && (ch < 0xFF)) { if ((ch > 0) && (ch < 0xFF)) {
return uictAscii; return uictAscii;
} }
return uictOther; return uictOther;
} }
inline char Utf8Adjust(unsigned long ch, unsigned char lead_bits, unsigned char rshift) 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 header = ((1 << lead_bits) - 1) << (8 - lead_bits);
const unsigned char mask = (0xFF >> (lead_bits + 1)); const unsigned char mask = (0xFF >> (lead_bits + 1));
return static_cast<char>(static_cast<unsigned char>( return static_cast<char>(
header | ((ch >> rshift) & mask) static_cast<unsigned char>(header | ((ch >> rshift) & mask)));
)); }
}
inline void QueueUnicodeCodepoint(std::deque<char>& q, unsigned long ch) {
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
// We are not allowed to queue the Stream::eof() codepoint, so if (static_cast<unsigned long>(Stream::eof()) == ch) {
// replace it with CP_REPLACEMENT_CHARACTER ch = 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) {
if (ch < 0x80) q.push_back(Utf8Adjust(ch, 2, 6));
{ q.push_back(Utf8Adjust(ch, 1, 0));
q.push_back(Utf8Adjust(ch, 0, 0)); } else if (ch < 0x10000) {
} q.push_back(Utf8Adjust(ch, 3, 12));
else if (ch < 0x800) q.push_back(Utf8Adjust(ch, 1, 6));
{ q.push_back(Utf8Adjust(ch, 1, 0));
q.push_back(Utf8Adjust(ch, 2, 6)); } else {
q.push_back(Utf8Adjust(ch, 1, 0)); q.push_back(Utf8Adjust(ch, 4, 18));
} q.push_back(Utf8Adjust(ch, 1, 12));
else if (ch < 0x10000) q.push_back(Utf8Adjust(ch, 1, 6));
{ q.push_back(Utf8Adjust(ch, 1, 0));
q.push_back(Utf8Adjust(ch, 3, 12)); }
q.push_back(Utf8Adjust(ch, 1, 6)); }
q.push_back(Utf8Adjust(ch, 1, 0));
} Stream::Stream(std::istream& input)
else : m_input(input),
{ m_pPrefetched(new unsigned char[YAML_PREFETCH_SIZE]),
q.push_back(Utf8Adjust(ch, 4, 18)); m_nPrefetchedAvailable(0),
q.push_back(Utf8Adjust(ch, 1, 12)); m_nPrefetchedUsed(0) {
q.push_back(Utf8Adjust(ch, 1, 6)); typedef std::istream::traits_type char_traits;
q.push_back(Utf8Adjust(ch, 1, 0));
} if (!input)
} return;
Stream::Stream(std::istream& input) // Determine (or guess) the character-set by reading the BOM, if any. See
: m_input(input), // the YAML specification for the determination algorithm.
m_pPrefetched(new unsigned char[YAML_PREFETCH_SIZE]), char_traits::int_type intro[4];
m_nPrefetchedAvailable(0), m_nPrefetchedUsed(0) int nIntroUsed = 0;
{ UtfIntroState state = uis_start;
typedef std::istream::traits_type char_traits; for (; !s_introFinalState[state];) {
std::istream::int_type ch = input.get();
if(!input) intro[nIntroUsed++] = ch;
return; UtfIntroCharType charType = IntroCharTypeOf(ch);
UtfIntroState newState = s_introTransitions[state][charType];
// Determine (or guess) the character-set by reading the BOM, if any. See int nUngets = s_introUngetCount[state][charType];
// the YAML specification for the determination algorithm. if (nUngets > 0) {
char_traits::int_type intro[4]; input.clear();
int nIntroUsed = 0; for (; nUngets > 0; --nUngets) {
UtfIntroState state = uis_start; if (char_traits::eof() != intro[--nIntroUsed])
for(; !s_introFinalState[state]; ) { input.putback(char_traits::to_char_type(intro[nIntroUsed]));
std::istream::int_type ch = input.get(); }
intro[nIntroUsed++] = ch; }
UtfIntroCharType charType = IntroCharTypeOf(ch); state = newState;
UtfIntroState newState = s_introTransitions[state][charType]; }
int nUngets = s_introUngetCount[state][charType];
if(nUngets > 0) { switch (state) {
input.clear(); case uis_utf8:
for(; nUngets > 0; --nUngets) { m_charSet = utf8;
if(char_traits::eof() != intro[--nIntroUsed]) break;
input.putback(char_traits::to_char_type(intro[nIntroUsed])); case uis_utf16le:
} m_charSet = utf16le;
} break;
state = newState; case uis_utf16be:
} m_charSet = utf16be;
break;
switch (state) { case uis_utf32le:
case uis_utf8: m_charSet = utf8; break; m_charSet = utf32le;
case uis_utf16le: m_charSet = utf16le; break; break;
case uis_utf16be: m_charSet = utf16be; break; case uis_utf32be:
case uis_utf32le: m_charSet = utf32le; break; m_charSet = utf32be;
case uis_utf32be: m_charSet = utf32be; break; break;
default: m_charSet = utf8; break; default:
} m_charSet = utf8;
break;
ReadAheadTo(0); }
}
ReadAheadTo(0);
Stream::~Stream() }
{
delete[] m_pPrefetched; Stream::~Stream() { delete[] m_pPrefetched; }
}
char Stream::peek() const {
char Stream::peek() const if (m_readahead.empty()) {
{ return Stream::eof();
if (m_readahead.empty()) }
{
return Stream::eof(); return m_readahead[0];
} }
return m_readahead[0]; Stream::operator bool() const {
} return m_input.good() ||
(!m_readahead.empty() && m_readahead[0] != Stream::eof());
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() {
// get char ch = peek();
// . Extracts a character from the stream and updates our position AdvanceCurrent();
char Stream::get() m_mark.column++;
{
char ch = peek(); if (ch == '\n') {
AdvanceCurrent(); m_mark.column = 0;
m_mark.column++; m_mark.line++;
}
if(ch == '\n') {
m_mark.column = 0; return ch;
m_mark.line++; }
}
// get
return ch; // . Extracts 'n' characters from the stream and updates our position
} std::string Stream::get(int n) {
std::string ret;
// get ret.reserve(n);
// . Extracts 'n' characters from the stream and updates our position for (int i = 0; i < n; i++)
std::string Stream::get(int n) ret += get();
{ return ret;
std::string ret; }
ret.reserve(n);
for(int i=0;i<n;i++) // eat
ret += get(); // . Eats 'n' characters and updates our position.
return ret; void Stream::eat(int n) {
} for (int i = 0; i < n; i++)
get();
// eat }
// . Eats 'n' characters and updates our position.
void Stream::eat(int n) void Stream::AdvanceCurrent() {
{ if (!m_readahead.empty()) {
for(int i=0;i<n;i++) m_readahead.pop_front();
get(); m_mark.pos++;
} }
void Stream::AdvanceCurrent() ReadAheadTo(0);
{ }
if (!m_readahead.empty())
{ bool Stream::_ReadAheadTo(size_t i) const {
m_readahead.pop_front(); while (m_input.good() && (m_readahead.size() <= i)) {
m_mark.pos++; switch (m_charSet) {
} case utf8:
StreamInUtf8();
ReadAheadTo(0); break;
} case utf16le:
StreamInUtf16();
bool Stream::_ReadAheadTo(size_t i) const break;
{ case utf16be:
while (m_input.good() && (m_readahead.size() <= i)) StreamInUtf16();
{ break;
switch (m_charSet) case utf32le:
{ StreamInUtf32();
case utf8: StreamInUtf8(); break; break;
case utf16le: StreamInUtf16(); break; case utf32be:
case utf16be: StreamInUtf16(); break; StreamInUtf32();
case utf32le: StreamInUtf32(); break; break;
case utf32be: StreamInUtf32(); break; }
} }
}
// signal end of stream
// signal end of stream if (!m_input.good())
if(!m_input.good()) m_readahead.push_back(Stream::eof());
m_readahead.push_back(Stream::eof());
return m_readahead.size() > i;
return m_readahead.size() > i; }
}
void Stream::StreamInUtf8() const {
void Stream::StreamInUtf8() const unsigned char b = GetNextByte();
{ if (m_input.good()) {
unsigned char b = GetNextByte(); m_readahead.push_back(b);
if (m_input.good()) }
{ }
m_readahead.push_back(b);
} void Stream::StreamInUtf16() const {
} unsigned long ch = 0;
unsigned char bytes[2];
void Stream::StreamInUtf16() const int nBigEnd = (m_charSet == utf16be) ? 0 : 1;
{
unsigned long ch = 0; bytes[0] = GetNextByte();
unsigned char bytes[2]; bytes[1] = GetNextByte();
int nBigEnd = (m_charSet == utf16be) ? 0 : 1; if (!m_input.good()) {
return;
bytes[0] = GetNextByte(); }
bytes[1] = GetNextByte(); ch = (static_cast<unsigned long>(bytes[nBigEnd]) << 8) |
if (!m_input.good()) static_cast<unsigned long>(bytes[1 ^ nBigEnd]);
{
return; if (ch >= 0xDC00 && ch < 0xE000) {
} // Trailing (low) surrogate...ugh, wrong order
ch = (static_cast<unsigned long>(bytes[nBigEnd]) << 8) | QueueUnicodeCodepoint(m_readahead, CP_REPLACEMENT_CHARACTER);
static_cast<unsigned long>(bytes[1 ^ nBigEnd]); return;
} else if (ch >= 0xD800 && ch < 0xDC00) {
if (ch >= 0xDC00 && ch < 0xE000) // ch is a leading (high) surrogate
{
// Trailing (low) surrogate...ugh, wrong order // Four byte UTF-8 code point
QueueUnicodeCodepoint(m_readahead, CP_REPLACEMENT_CHARACTER);
return; // Read the trailing (low) surrogate
} for (;;) {
else if (ch >= 0xD800 && ch < 0xDC00) bytes[0] = GetNextByte();
{ bytes[1] = GetNextByte();
// ch is a leading (high) surrogate if (!m_input.good()) {
QueueUnicodeCodepoint(m_readahead, CP_REPLACEMENT_CHARACTER);
// Four byte UTF-8 code point return;
}
// Read the trailing (low) surrogate unsigned long chLow = (static_cast<unsigned long>(bytes[nBigEnd]) << 8) |
for (;;) static_cast<unsigned long>(bytes[1 ^ nBigEnd]);
{ if (chLow < 0xDC00 || ch >= 0xE000) {
bytes[0] = GetNextByte(); // Trouble...not a low surrogate. Dump a REPLACEMENT CHARACTER into the
bytes[1] = GetNextByte(); // stream.
if (!m_input.good()) QueueUnicodeCodepoint(m_readahead, CP_REPLACEMENT_CHARACTER);
{
QueueUnicodeCodepoint(m_readahead, CP_REPLACEMENT_CHARACTER); // Deal with the next UTF-16 unit
return; if (chLow < 0xD800 || ch >= 0xE000) {
} // Easiest case: queue the codepoint and return
unsigned long chLow = (static_cast<unsigned long>(bytes[nBigEnd]) << 8) | QueueUnicodeCodepoint(m_readahead, ch);
static_cast<unsigned long>(bytes[1 ^ nBigEnd]); return;
if (chLow < 0xDC00 || ch >= 0xE000) } else {
{ // Start the loop over with the new high surrogate
// Trouble...not a low surrogate. Dump a REPLACEMENT CHARACTER into the stream. ch = chLow;
QueueUnicodeCodepoint(m_readahead, CP_REPLACEMENT_CHARACTER); continue;
}
// Deal with the next UTF-16 unit }
if (chLow < 0xD800 || ch >= 0xE000)
{ // Select the payload bits from the high surrogate
// Easiest case: queue the codepoint and return ch &= 0x3FF;
QueueUnicodeCodepoint(m_readahead, ch); ch <<= 10;
return;
} // Include bits from low surrogate
else ch |= (chLow & 0x3FF);
{
// Start the loop over with the new high surrogate // Add the surrogacy offset
ch = chLow; ch += 0x10000;
continue; }
} }
}
QueueUnicodeCodepoint(m_readahead, ch);
// Select the payload bits from the high surrogate }
ch &= 0x3FF;
ch <<= 10; inline char* ReadBuffer(unsigned char* pBuffer) {
return reinterpret_cast<char*>(pBuffer);
// Include bits from low surrogate }
ch |= (chLow & 0x3FF);
unsigned char Stream::GetNextByte() const {
// Add the surrogacy offset if (m_nPrefetchedUsed >= m_nPrefetchedAvailable) {
ch += 0x10000; std::streambuf* pBuf = m_input.rdbuf();
} m_nPrefetchedAvailable = static_cast<std::size_t>(
} pBuf->sgetn(ReadBuffer(m_pPrefetched), YAML_PREFETCH_SIZE));
m_nPrefetchedUsed = 0;
QueueUnicodeCodepoint(m_readahead, ch); if (!m_nPrefetchedAvailable) {
} m_input.setstate(std::ios_base::eofbit);
}
inline char* ReadBuffer(unsigned char* pBuffer)
{ if (0 == m_nPrefetchedAvailable) {
return reinterpret_cast<char*>(pBuffer); return 0;
} }
}
unsigned char Stream::GetNextByte() const
{ return m_pPrefetched[m_nPrefetchedUsed++];
if (m_nPrefetchedUsed >= m_nPrefetchedAvailable) }
{
std::streambuf *pBuf = m_input.rdbuf(); void Stream::StreamInUtf32() const {
m_nPrefetchedAvailable = static_cast<std::size_t>(pBuf->sgetn(ReadBuffer(m_pPrefetched), YAML_PREFETCH_SIZE)); static int indexes[2][4] = {{3, 2, 1, 0}, {0, 1, 2, 3}};
m_nPrefetchedUsed = 0;
if (!m_nPrefetchedAvailable) unsigned long ch = 0;
{ unsigned char bytes[4];
m_input.setstate(std::ios_base::eofbit); int* pIndexes = (m_charSet == utf32be) ? indexes[1] : indexes[0];
}
bytes[0] = GetNextByte();
if (0 == m_nPrefetchedAvailable) bytes[1] = GetNextByte();
{ bytes[2] = GetNextByte();
return 0; bytes[3] = GetNextByte();
} if (!m_input.good()) {
} return;
}
return m_pPrefetched[m_nPrefetchedUsed++];
} for (int i = 0; i < 4; ++i) {
ch <<= 8;
void Stream::StreamInUtf32() const ch |= bytes[pIndexes[i]];
{ }
static int indexes[2][4] = {
{3, 2, 1, 0}, QueueUnicodeCodepoint(m_readahead, ch);
{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);
}
} }

View File

@@ -1,11 +1,12 @@
#ifndef STREAM_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef STREAM_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define STREAM_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define STREAM_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
#include "yaml-cpp/noncopyable.h" #include "yaml-cpp/noncopyable.h"
#include "yaml-cpp/mark.h" #include "yaml-cpp/mark.h"
#include <cstddef> #include <cstddef>
@@ -15,65 +16,67 @@
#include <set> #include <set>
#include <string> #include <string>
namespace YAML namespace YAML {
{ class Stream : private noncopyable {
class Stream: private noncopyable public:
{ friend class StreamCharSource;
public:
friend class StreamCharSource;
Stream(std::istream& input); Stream(std::istream& input);
~Stream(); ~Stream();
operator bool() const; operator bool() const;
bool operator !() const { return !static_cast <bool>(*this); } bool operator!() const { return !static_cast<bool>(*this); }
char peek() const; char peek() const;
char get(); char get();
std::string get(int n); std::string get(int n);
void eat(int n = 1); void eat(int n = 1);
static char eof() { return 0x04; } static char eof() { return 0x04; }
const Mark mark() const { return m_mark; } const Mark mark() const { return m_mark; }
int pos() const { return m_mark.pos; } int pos() const { return m_mark.pos; }
int line() const { return m_mark.line; } int line() const { return m_mark.line; }
int column() const { return m_mark.column; } int column() const { return m_mark.column; }
void ResetColumn() { m_mark.column = 0; } void ResetColumn() { m_mark.column = 0; }
private: private:
enum CharacterSet {utf8, utf16le, utf16be, utf32le, utf32be}; enum CharacterSet {
utf8,
utf16le,
utf16be,
utf32le,
utf32be
};
std::istream& m_input; std::istream& m_input;
Mark m_mark; Mark m_mark;
CharacterSet m_charSet; CharacterSet m_charSet;
mutable std::deque<char> m_readahead; mutable std::deque<char> m_readahead;
unsigned char* const m_pPrefetched; unsigned char* const m_pPrefetched;
mutable size_t m_nPrefetchedAvailable; mutable size_t m_nPrefetchedAvailable;
mutable size_t m_nPrefetchedUsed; mutable size_t m_nPrefetchedUsed;
void AdvanceCurrent(); void AdvanceCurrent();
char CharAt(size_t i) const; char CharAt(size_t i) const;
bool ReadAheadTo(size_t i) const; bool ReadAheadTo(size_t i) const;
bool _ReadAheadTo(size_t i) const; bool _ReadAheadTo(size_t i) const;
void StreamInUtf8() const; void StreamInUtf8() const;
void StreamInUtf16() const; void StreamInUtf16() const;
void StreamInUtf32() const; void StreamInUtf32() const;
unsigned char GetNextByte() const; unsigned char GetNextByte() const;
}; };
// CharAt // CharAt
// . Unchecked access // . Unchecked access
inline char Stream::CharAt(size_t i) const { inline char Stream::CharAt(size_t i) const { return m_readahead[i]; }
return m_readahead[i];
}
inline bool Stream::ReadAheadTo(size_t i) const { inline bool Stream::ReadAheadTo(size_t i) const {
if(m_readahead.size() > i) if (m_readahead.size() > i)
return true; return true;
return _ReadAheadTo(i); return _ReadAheadTo(i);
} }
} }
#endif // STREAM_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #endif // STREAM_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,48 +1,48 @@
#ifndef STREAMCHARSOURCE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef STREAMCHARSOURCE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define STREAMCHARSOURCE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define STREAMCHARSOURCE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
#include "yaml-cpp/noncopyable.h" #include "yaml-cpp/noncopyable.h"
#include <cstddef> #include <cstddef>
namespace YAML namespace YAML {
{ class StreamCharSource {
class StreamCharSource public:
{ StreamCharSource(const Stream& stream) : m_offset(0), m_stream(stream) {}
public: StreamCharSource(const StreamCharSource& source)
StreamCharSource(const Stream& stream): m_offset(0), m_stream(stream) {} : m_offset(source.m_offset), m_stream(source.m_stream) {}
StreamCharSource(const StreamCharSource& source): m_offset(source.m_offset), m_stream(source.m_stream) {} ~StreamCharSource() {}
~StreamCharSource() {}
operator bool() const; operator bool() const;
char operator [] (std::size_t i) const { return m_stream.CharAt(m_offset + i); } char operator[](std::size_t i) const { return m_stream.CharAt(m_offset + i); }
bool operator !() const { return !static_cast<bool>(*this); } bool operator!() const { return !static_cast<bool>(*this); }
const StreamCharSource operator + (int i) const; const StreamCharSource operator+(int i) const;
private: private:
std::size_t m_offset; std::size_t m_offset;
const Stream& m_stream; const Stream& m_stream;
StreamCharSource& operator = (const StreamCharSource&); // non-assignable StreamCharSource& operator=(const StreamCharSource&); // non-assignable
}; };
inline StreamCharSource::operator bool() const { inline StreamCharSource::operator bool() const {
return m_stream.ReadAheadTo(m_offset); 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 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

View File

@@ -1,47 +1,48 @@
#ifndef STRINGSOURCE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef STRINGSOURCE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define STRINGSOURCE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define STRINGSOURCE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
#include <cstddef> #include <cstddef>
namespace YAML namespace YAML {
{ class StringCharSource {
class StringCharSource public:
{ StringCharSource(const char* str, std::size_t size)
public: : m_str(str), m_size(size), m_offset(0) {}
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; } operator bool() const { return m_offset < m_size; }
char operator [] (std::size_t i) const { return m_str[m_offset + i]; } char operator[](std::size_t i) const { return m_str[m_offset + i]; }
bool operator !() const { return !static_cast<bool>(*this); } bool operator!() const { return !static_cast<bool>(*this); }
const StringCharSource operator + (int i) const { const StringCharSource operator+(int i) const {
StringCharSource source(*this); StringCharSource source(*this);
if(static_cast<int> (source.m_offset) + i >= 0) if (static_cast<int>(source.m_offset) + i >= 0)
source.m_offset += i; source.m_offset += i;
else else
source.m_offset = 0; source.m_offset = 0;
return source; return source;
} }
StringCharSource& operator ++ () { StringCharSource& operator++() {
++m_offset; ++m_offset;
return *this; return *this;
} }
StringCharSource& operator += (std::size_t offset) { StringCharSource& operator+=(std::size_t offset) {
m_offset += offset; m_offset += offset;
return *this; return *this;
} }
private:
const char *m_str; private:
std::size_t m_size; const char* m_str;
std::size_t m_offset; std::size_t m_size;
}; std::size_t m_offset;
};
} }
#endif // STRINGSOURCE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #endif // STRINGSOURCE_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -4,49 +4,45 @@
#include <cassert> #include <cassert>
#include <stdexcept> #include <stdexcept>
namespace YAML namespace YAML {
{ Tag::Tag(const Token& token) : type(static_cast<TYPE>(token.data)) {
Tag::Tag(const Token& token): type(static_cast<TYPE>(token.data)) switch (type) {
{ case VERBATIM:
switch(type) { value = token.value;
case VERBATIM: break;
value = token.value; case PRIMARY_HANDLE:
break; value = token.value;
case PRIMARY_HANDLE: break;
value = token.value; case SECONDARY_HANDLE:
break; value = token.value;
case SECONDARY_HANDLE: break;
value = token.value; case NAMED_HANDLE:
break; handle = token.value;
case NAMED_HANDLE: value = token.params[0];
handle = token.value; break;
value = token.params[0]; case NON_SPECIFIC:
break; break;
case NON_SPECIFIC: default:
break; assert(false);
default: }
assert(false);
}
}
const std::string Tag::Translate(const Directives& directives)
{
switch(type) {
case VERBATIM:
return value;
case PRIMARY_HANDLE:
return directives.TranslateTagHandle("!") + value;
case SECONDARY_HANDLE:
return directives.TranslateTagHandle("!!") + value;
case NAMED_HANDLE:
return directives.TranslateTagHandle("!" + handle + "!") + value;
case NON_SPECIFIC:
// TODO:
return "!";
default:
assert(false);
}
throw std::runtime_error("yaml-cpp: internal error, bad tag type");
}
} }
const std::string Tag::Translate(const Directives& directives) {
switch (type) {
case VERBATIM:
return value;
case PRIMARY_HANDLE:
return directives.TranslateTagHandle("!") + value;
case SECONDARY_HANDLE:
return directives.TranslateTagHandle("!!") + value;
case NAMED_HANDLE:
return directives.TranslateTagHandle("!" + handle + "!") + value;
case NON_SPECIFIC:
// TODO:
return "!";
default:
assert(false);
}
throw std::runtime_error("yaml-cpp: internal error, bad tag type");
}
}

View File

@@ -1,28 +1,33 @@
#ifndef TAG_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef TAG_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define TAG_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define TAG_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
#include <string> #include <string>
namespace YAML namespace YAML {
{ struct Token;
struct Token; struct Directives;
struct Directives;
struct Tag { struct Tag {
enum TYPE { enum TYPE {
VERBATIM, PRIMARY_HANDLE, SECONDARY_HANDLE, NAMED_HANDLE, NON_SPECIFIC VERBATIM,
}; PRIMARY_HANDLE,
SECONDARY_HANDLE,
NAMED_HANDLE,
NON_SPECIFIC
};
Tag(const Token& token); Tag(const Token& token);
const std::string Translate(const Directives& directives); const std::string Translate(const Directives& directives);
TYPE type; TYPE type;
std::string handle, value; std::string handle, value;
}; };
} }
#endif // TAG_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #endif // TAG_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,85 +1,74 @@
#ifndef TOKEN_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef TOKEN_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define TOKEN_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define TOKEN_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
#include "yaml-cpp/mark.h" #include "yaml-cpp/mark.h"
#include <iostream> #include <iostream>
#include <string> #include <string>
#include <vector> #include <vector>
namespace YAML namespace YAML {
{ const std::string TokenNames[] = {
const std::string TokenNames[] = { "DIRECTIVE", "DOC_START", "DOC_END", "BLOCK_SEQ_START",
"DIRECTIVE", "BLOCK_MAP_START", "BLOCK_SEQ_END", "BLOCK_MAP_END", "BLOCK_ENTRY",
"DOC_START", "FLOW_SEQ_START", "FLOW_MAP_START", "FLOW_SEQ_END", "FLOW_MAP_END",
"DOC_END", "FLOW_MAP_COMPACT", "FLOW_ENTRY", "KEY", "VALUE",
"BLOCK_SEQ_START", "ANCHOR", "ALIAS", "TAG", "SCALAR"};
"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 { struct Token {
// enums // enums
enum STATUS { VALID, INVALID, UNVERIFIED }; enum STATUS {
enum TYPE { VALID,
DIRECTIVE, INVALID,
DOC_START, UNVERIFIED
DOC_END, };
BLOCK_SEQ_START, enum TYPE {
BLOCK_MAP_START, DIRECTIVE,
BLOCK_SEQ_END, DOC_START,
BLOCK_MAP_END, DOC_END,
BLOCK_ENTRY, BLOCK_SEQ_START,
FLOW_SEQ_START, BLOCK_MAP_START,
FLOW_MAP_START, BLOCK_SEQ_END,
FLOW_SEQ_END, BLOCK_MAP_END,
FLOW_MAP_END, BLOCK_ENTRY,
FLOW_MAP_COMPACT, FLOW_SEQ_START,
FLOW_ENTRY, FLOW_MAP_START,
KEY, FLOW_SEQ_END,
VALUE, FLOW_MAP_END,
ANCHOR, FLOW_MAP_COMPACT,
ALIAS, FLOW_ENTRY,
TAG, KEY,
PLAIN_SCALAR, VALUE,
NON_PLAIN_SCALAR ANCHOR,
}; ALIAS,
TAG,
PLAIN_SCALAR,
NON_PLAIN_SCALAR
};
// data // data
Token(TYPE type_, const Mark& mark_): status(VALID), type(type_), mark(mark_), data(0) {} Token(TYPE type_, const Mark& mark_)
: status(VALID), type(type_), mark(mark_), data(0) {}
friend std::ostream& operator << (std::ostream& out, const Token& token) { friend std::ostream& operator<<(std::ostream& out, const Token& token) {
out << TokenNames[token.type] << std::string(": ") << token.value; out << TokenNames[token.type] << std::string(": ") << token.value;
for(std::size_t i=0;i<token.params.size();i++) for (std::size_t i = 0; i < token.params.size(); i++)
out << std::string(" ") << token.params[i]; out << std::string(" ") << token.params[i];
return out; return out;
} }
STATUS status; STATUS status;
TYPE type; TYPE type;
Mark mark; Mark mark;
std::string value; std::string value;
std::vector <std::string> params; std::vector<std::string> params;
int data; int data;
}; };
} }
#endif // TOKEN_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #endif // TOKEN_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -3,75 +3,74 @@
#include "yaml-cpp/yaml.h" #include "yaml-cpp/yaml.h"
#include <iostream> #include <iostream>
namespace Test namespace Test {
{ namespace Parser {
namespace Parser { TEST NoEndOfMapFlow() {
TEST NoEndOfMapFlow() try {
{ HANDLE("---{header: {id: 1");
try { }
HANDLE("---{header: {id: 1"); catch (const YAML::ParserException& e) {
} catch(const YAML::ParserException& e) { YAML_ASSERT(e.msg == std::string(YAML::ErrorMsg::END_OF_MAP_FLOW));
YAML_ASSERT(e.msg == std::string(YAML::ErrorMsg::END_OF_MAP_FLOW)); return true;
return true; }
} return " no exception caught";
return " no exception caught"; }
}
TEST PlainScalarStartingWithQuestionMark() {
TEST PlainScalarStartingWithQuestionMark() HANDLE("foo: ?bar");
{ EXPECT_DOC_START();
HANDLE("foo: ?bar"); EXPECT_MAP_START("?", 0);
EXPECT_DOC_START(); EXPECT_SCALAR("?", 0, "foo");
EXPECT_MAP_START("?", 0); EXPECT_SCALAR("?", 0, "?bar");
EXPECT_SCALAR("?", 0, "foo"); EXPECT_MAP_END();
EXPECT_SCALAR("?", 0, "?bar"); EXPECT_DOC_END();
EXPECT_MAP_END(); DONE();
EXPECT_DOC_END(); }
DONE();
} TEST NullStringScalar() {
HANDLE("foo: null");
TEST NullStringScalar() EXPECT_DOC_START();
{ EXPECT_MAP_START("?", 0);
HANDLE("foo: null"); EXPECT_SCALAR("?", 0, "foo");
EXPECT_DOC_START(); EXPECT_NULL(0);
EXPECT_MAP_START("?", 0); EXPECT_MAP_END();
EXPECT_SCALAR("?", 0, "foo"); EXPECT_DOC_END();
EXPECT_NULL(0); DONE();
EXPECT_MAP_END(); }
EXPECT_DOC_END(); }
DONE();
} namespace {
} void RunParserTest(TEST (*test)(), const std::string& name, int& passed,
int& total) {
namespace { TEST ret;
void RunParserTest(TEST (*test)(), const std::string& name, int& passed, int& total) { try {
TEST ret; ret = test();
try { }
ret = test(); catch (const YAML::Exception& e) {
} catch(const YAML::Exception& e) { ret.ok = false;
ret.ok = false; ret.error = std::string(" Exception caught: ") + e.what();
ret.error = std::string(" Exception caught: ") + e.what(); }
}
if (!ret.ok) {
if(!ret.ok) { std::cout << "Parser test failed: " << name << "\n";
std::cout << "Parser test failed: " << name << "\n"; std::cout << ret.error << "\n";
std::cout << ret.error << "\n"; }
}
if (ret.ok)
if(ret.ok) passed++;
passed++; total++;
total++; }
} }
}
bool RunParserTests() {
bool RunParserTests() int passed = 0;
{ int total = 0;
int passed = 0; RunParserTest(&Parser::NoEndOfMapFlow, "No end of map flow", passed, total);
int total = 0; RunParserTest(&Parser::PlainScalarStartingWithQuestionMark,
RunParserTest(&Parser::NoEndOfMapFlow, "No end of map flow", passed, total); "Plain scalar starting with question mark", passed, total);
RunParserTest(&Parser::PlainScalarStartingWithQuestionMark, "Plain scalar starting with question mark", passed, total); RunParserTest(&Parser::NullStringScalar, "Null string scalar", passed, total);
RunParserTest(&Parser::NullStringScalar, "Null string scalar", passed, total);
std::cout << "Parser tests: " << passed << "/" << total << " passed\n";
std::cout << "Parser tests: " << passed << "/" << total << " passed\n"; return passed == total;
return passed == total; }
}
} }

File diff suppressed because it is too large Load Diff

View File

@@ -1,13 +1,14 @@
#ifndef EMITTERTESTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef EMITTERTESTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define EMITTERTESTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define EMITTERTESTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
namespace Test { namespace Test {
bool RunEmitterTests(); bool RunEmitterTests();
} }
#endif // EMITTERTESTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #endif // EMITTERTESTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66

File diff suppressed because it is too large Load Diff

View File

@@ -7,184 +7,191 @@
#include <cassert> #include <cassert>
namespace Test { namespace Test {
inline std::string Quote(const std::string& text) { inline std::string Quote(const std::string& text) {
YAML::Emitter out; YAML::Emitter out;
out << YAML::DoubleQuoted << text; out << YAML::DoubleQuoted << text;
return out.c_str(); return out.c_str();
} }
struct Event { struct Event {
enum Type { DocStart, DocEnd, Null, Alias, Scalar, SeqStart, SeqEnd, MapStart, MapEnd }; enum Type {
DocStart,
typedef YAML::Mark Mark; DocEnd,
typedef YAML::anchor_t anchor_t; Null,
Alias,
Event(Type type_, const std::string& tag_, anchor_t anchor_, const std::string& scalar_): type(type_), tag(tag_), anchor(anchor_), scalar(scalar_) {} Scalar,
SeqStart,
Type type; SeqEnd,
std::string tag; MapStart,
anchor_t anchor; MapEnd
std::string scalar; };
std::ostream& write(std::ostream& out) const { typedef YAML::Mark Mark;
switch(type) { typedef YAML::anchor_t anchor_t;
case DocStart:
return out << "DocStart"; Event(Type type_, const std::string& tag_, anchor_t anchor_,
case DocEnd: const std::string& scalar_)
return out << "DocEnd"; : type(type_), tag(tag_), anchor(anchor_), scalar(scalar_) {}
case Null:
return out << "Null(" << anchor << ")"; Type type;
case Alias: std::string tag;
return out << "Alias(" << anchor << ")"; anchor_t anchor;
case Scalar: std::string scalar;
return out << "Scalar(" << Quote(tag) << ", " << anchor << ", " << Quote(scalar) << ")";
case SeqStart: std::ostream& write(std::ostream& out) const {
return out << "SeqStart(" << Quote(tag) << ", " << anchor << ")"; switch (type) {
case SeqEnd: case DocStart:
return out << "SeqEnd"; return out << "DocStart";
case MapStart: case DocEnd:
return out << "MapStart(" << Quote(tag) << ", " << anchor << ")"; return out << "DocEnd";
case MapEnd: case Null:
return out << "MapEnd"; return out << "Null(" << anchor << ")";
} case Alias:
assert(false); return out << "Alias(" << anchor << ")";
return out; case Scalar:
} return out << "Scalar(" << Quote(tag) << ", " << anchor << ", "
}; << Quote(scalar) << ")";
case SeqStart:
inline std::ostream& operator << (std::ostream& out, const Event& event) { return out << "SeqStart(" << Quote(tag) << ", " << anchor << ")";
return event.write(out); case SeqEnd:
} return out << "SeqEnd";
case MapStart:
inline bool operator == (const Event& a, const Event& b) { return out << "MapStart(" << Quote(tag) << ", " << anchor << ")";
return a.type == b.type && a.tag == b.tag && a.anchor == b.anchor && a.scalar == b.scalar; case MapEnd:
} return out << "MapEnd";
}
inline bool operator != (const Event& a, const Event& b) { assert(false);
return !(a == b); return out;
} }
};
class MockEventHandler: public YAML::EventHandler
{ inline std::ostream& operator<<(std::ostream& out, const Event& event) {
public: return event.write(out);
typedef YAML::Mark Mark; }
typedef YAML::anchor_t anchor_t;
inline bool operator==(const Event& a, const Event& b) {
MockEventHandler() {} return a.type == b.type && a.tag == b.tag && a.anchor == b.anchor &&
a.scalar == b.scalar;
virtual void OnDocumentStart(const Mark&) { }
m_actualEvents.push_back(Event(Event::DocStart, "", 0, ""));
} inline bool operator!=(const Event& a, const Event& b) { return !(a == b); }
virtual void OnDocumentEnd() { class MockEventHandler : public YAML::EventHandler {
m_actualEvents.push_back(Event(Event::DocEnd, "", 0, "")); public:
} typedef YAML::Mark Mark;
typedef YAML::anchor_t anchor_t;
virtual void OnNull(const Mark&, anchor_t anchor) {
m_actualEvents.push_back(Event(Event::Null, "", anchor, "")); MockEventHandler() {}
}
virtual void OnDocumentStart(const Mark&) {
virtual void OnAlias(const Mark&, anchor_t anchor) { m_actualEvents.push_back(Event(Event::DocStart, "", 0, ""));
m_actualEvents.push_back(Event(Event::Alias, "", anchor, "")); }
}
virtual void OnDocumentEnd() {
virtual void OnScalar(const Mark&, const std::string& tag, anchor_t anchor, const std::string& value) { m_actualEvents.push_back(Event(Event::DocEnd, "", 0, ""));
m_actualEvents.push_back(Event(Event::Scalar, tag, anchor, value)); }
}
virtual void OnNull(const Mark&, anchor_t anchor) {
virtual void OnSequenceStart(const Mark&, const std::string& tag, anchor_t anchor) { m_actualEvents.push_back(Event(Event::Null, "", anchor, ""));
m_actualEvents.push_back(Event(Event::SeqStart, tag, anchor, "")); }
}
virtual void OnAlias(const Mark&, anchor_t anchor) {
virtual void OnSequenceEnd() { m_actualEvents.push_back(Event(Event::Alias, "", anchor, ""));
m_actualEvents.push_back(Event(Event::SeqEnd, "", 0, "")); }
}
virtual void OnScalar(const Mark&, const std::string& tag, anchor_t anchor,
virtual void OnMapStart(const Mark&, const std::string& tag, anchor_t anchor) { const std::string& value) {
m_actualEvents.push_back(Event(Event::MapStart, tag, anchor, "")); m_actualEvents.push_back(Event(Event::Scalar, tag, anchor, value));
} }
virtual void OnMapEnd() { virtual void OnSequenceStart(const Mark&, const std::string& tag,
m_actualEvents.push_back(Event(Event::MapEnd, "", 0, "")); anchor_t anchor) {
} m_actualEvents.push_back(Event(Event::SeqStart, tag, anchor, ""));
}
void Expect(const Event& event) { m_expectedEvents.push_back(event); }
virtual void OnSequenceEnd() {
Test::TEST Check() const { m_actualEvents.push_back(Event(Event::SeqEnd, "", 0, ""));
std::size_t N = std::max(m_expectedEvents.size(), m_actualEvents.size()); }
for(std::size_t i=0;i<N;i++) {
if(i >= m_expectedEvents.size()) { virtual void OnMapStart(const Mark&, const std::string& tag,
std::stringstream out; anchor_t anchor) {
for(std::size_t j=0;j<i;j++) { m_actualEvents.push_back(Event(Event::MapStart, tag, anchor, ""));
out << " " << m_expectedEvents[j] << "\n"; }
}
out << " EXPECTED: (no event expected)\n"; virtual void OnMapEnd() {
out << " ACTUAL : " << m_actualEvents[i] << "\n"; m_actualEvents.push_back(Event(Event::MapEnd, "", 0, ""));
return out.str().c_str(); }
}
void Expect(const Event& event) { m_expectedEvents.push_back(event); }
if(i >= m_actualEvents.size()) {
std::stringstream out; Test::TEST Check() const {
for(std::size_t j=0;j<i;j++) { std::size_t N = std::max(m_expectedEvents.size(), m_actualEvents.size());
out << " " << m_expectedEvents[j] << "\n"; for (std::size_t i = 0; i < N; i++) {
} if (i >= m_expectedEvents.size()) {
out << " EXPECTED: " << m_expectedEvents[i] << "\n"; std::stringstream out;
out << " ACTUAL : (no event recorded)\n"; for (std::size_t j = 0; j < i; j++) {
return out.str().c_str(); out << " " << m_expectedEvents[j] << "\n";
} }
out << " EXPECTED: (no event expected)\n";
if(m_expectedEvents[i] != m_actualEvents[i]) { out << " ACTUAL : " << m_actualEvents[i] << "\n";
std::stringstream out; return out.str().c_str();
for(std::size_t j=0;j<i;j++) { }
out << " " << m_expectedEvents[j] << "\n";
} if (i >= m_actualEvents.size()) {
out << " EXPECTED: " << m_expectedEvents[i] << "\n"; std::stringstream out;
out << " ACTUAL : " << m_actualEvents[i] << "\n"; for (std::size_t j = 0; j < i; j++) {
return out.str().c_str(); out << " " << m_expectedEvents[j] << "\n";
} }
} out << " EXPECTED: " << m_expectedEvents[i] << "\n";
out << " ACTUAL : (no event recorded)\n";
return true; return out.str().c_str();
} }
std::vector<Event> m_expectedEvents; if (m_expectedEvents[i] != m_actualEvents[i]) {
std::vector<Event> m_actualEvents; std::stringstream out;
}; for (std::size_t j = 0; j < i; j++) {
out << " " << m_expectedEvents[j] << "\n";
#define HANDLE(ex)\ }
MockEventHandler handler;\ out << " EXPECTED: " << m_expectedEvents[i] << "\n";
std::stringstream stream(ex);\ out << " ACTUAL : " << m_actualEvents[i] << "\n";
YAML::Parser parser(stream);\ return out.str().c_str();
while(parser.HandleNextDocument(handler)) {} }
}
#define EXPECT_DOC_START()\
handler.Expect(Event(Event::DocStart, "", 0, "")) return true;
}
#define EXPECT_DOC_END()\
handler.Expect(Event(Event::DocEnd, "", 0, "")) std::vector<Event> m_expectedEvents;
std::vector<Event> m_actualEvents;
#define EXPECT_NULL(anchor)\ };
handler.Expect(Event(Event::Null, "", anchor, ""))
#define HANDLE(ex) \
#define EXPECT_ALIAS(anchor)\ MockEventHandler handler; \
handler.Expect(Event(Event::Alias, "", anchor, "")) std::stringstream stream(ex); \
YAML::Parser parser(stream); \
#define EXPECT_SCALAR(tag, anchor, value)\ while (parser.HandleNextDocument(handler)) { \
handler.Expect(Event(Event::Scalar, tag, anchor, value)) }
#define EXPECT_SEQ_START(tag, anchor)\ #define EXPECT_DOC_START() handler.Expect(Event(Event::DocStart, "", 0, ""))
handler.Expect(Event(Event::SeqStart, tag, anchor, ""))
#define EXPECT_DOC_END() handler.Expect(Event(Event::DocEnd, "", 0, ""))
#define EXPECT_SEQ_END()\
handler.Expect(Event(Event::SeqEnd, "", 0, "")) #define EXPECT_NULL(anchor) handler.Expect(Event(Event::Null, "", anchor, ""))
#define EXPECT_MAP_START(tag, anchor)\ #define EXPECT_ALIAS(anchor) handler.Expect(Event(Event::Alias, "", anchor, ""))
handler.Expect(Event(Event::MapStart, tag, anchor, ""))
#define EXPECT_SCALAR(tag, anchor, value) \
#define EXPECT_MAP_END()\ handler.Expect(Event(Event::Scalar, tag, anchor, value))
handler.Expect(Event(Event::MapEnd, "", 0, ""))
#define EXPECT_SEQ_START(tag, anchor) \
#define DONE()\ handler.Expect(Event(Event::SeqStart, tag, anchor, ""))
return handler.Check()
#define EXPECT_SEQ_END() handler.Expect(Event(Event::SeqEnd, "", 0, ""))
#define EXPECT_MAP_START(tag, anchor) \
handler.Expect(Event(Event::MapStart, tag, anchor, ""))
#define EXPECT_MAP_END() handler.Expect(Event(Event::MapEnd, "", 0, ""))
#define DONE() return handler.Check()
} }

View File

@@ -1,7 +1,6 @@
#include "tests.h" #include "tests.h"
int main() int main() {
{ Test::RunAll();
Test::RunAll(); return 0;
return 0;
} }

View File

@@ -1,13 +1,14 @@
#ifndef PARSERTESTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef PARSERTESTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define PARSERTESTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define PARSERTESTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
namespace Test { namespace Test {
bool RunParserTests(); bool RunParserTests();
} }
#endif // PARSERTESTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #endif // PARSERTESTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66

File diff suppressed because it is too large Load Diff

View File

@@ -2,148 +2,223 @@
#include "yaml-cpp/yaml.h" #include "yaml-cpp/yaml.h"
#include <iostream> #include <iostream>
namespace Test namespace Test {
{ namespace {
namespace { void RunSpecTest(TEST (*test)(), const std::string& index,
void RunSpecTest(TEST (*test)(), const std::string& index, const std::string& name, int& passed, int& total) { const std::string& name, int& passed, int& total) {
TEST ret; TEST ret;
try { try {
ret = test(); ret = test();
} catch(const YAML::Exception& e) { }
ret.ok = false; catch (const YAML::Exception& e) {
ret.error = std::string(" Exception caught: ") + e.what(); ret.ok = false;
} ret.error = std::string(" Exception caught: ") + e.what();
}
if(!ret.ok) { if (!ret.ok) {
std::cout << "Spec test " << index << " failed: " << name << "\n"; std::cout << "Spec test " << index << " failed: " << name << "\n";
std::cout << ret.error << "\n"; std::cout << ret.error << "\n";
} }
if(ret.ok) if (ret.ok)
passed++; passed++;
total++; total++;
} }
} }
bool RunSpecTests() bool RunSpecTests() {
{ int passed = 0;
int passed = 0; int total = 0;
int total = 0; RunSpecTest(&Spec::SeqScalars, "2.1", "Sequence of Scalars", passed, total);
RunSpecTest(&Spec::SeqScalars, "2.1", "Sequence of Scalars", passed, total); RunSpecTest(&Spec::MappingScalarsToScalars, "2.2",
RunSpecTest(&Spec::MappingScalarsToScalars, "2.2", "Mapping Scalars to Scalars", passed, total); "Mapping Scalars to Scalars", passed, total);
RunSpecTest(&Spec::MappingScalarsToSequences, "2.3", "Mapping Scalars to Sequences", passed, total); RunSpecTest(&Spec::MappingScalarsToSequences, "2.3",
RunSpecTest(&Spec::SequenceOfMappings, "2.4", "Sequence of Mappings", passed, total); "Mapping Scalars to Sequences", passed, total);
RunSpecTest(&Spec::SequenceOfSequences, "2.5", "Sequence of Sequences", passed, total); RunSpecTest(&Spec::SequenceOfMappings, "2.4", "Sequence of Mappings", passed,
RunSpecTest(&Spec::MappingOfMappings, "2.6", "Mapping of Mappings", passed, total); total);
RunSpecTest(&Spec::TwoDocumentsInAStream, "2.7", "Two Documents in a Stream", passed, total); RunSpecTest(&Spec::SequenceOfSequences, "2.5", "Sequence of Sequences",
RunSpecTest(&Spec::PlayByPlayFeed, "2.8", "Play by Play Feed from a Game", passed, total); passed, total);
RunSpecTest(&Spec::SingleDocumentWithTwoComments, "2.9", "Single Document with Two Comments", passed, total); RunSpecTest(&Spec::MappingOfMappings, "2.6", "Mapping of Mappings", passed,
RunSpecTest(&Spec::SimpleAnchor, "2.10", "Node for \"Sammy Sosa\" appears twice in this document", passed, total); total);
RunSpecTest(&Spec::MappingBetweenSequences, "2.11", "Mapping between Sequences", passed, total); RunSpecTest(&Spec::TwoDocumentsInAStream, "2.7", "Two Documents in a Stream",
RunSpecTest(&Spec::CompactNestedMapping, "2.12", "Compact Nested Mapping", passed, total); passed, total);
RunSpecTest(&Spec::InLiteralsNewlinesArePreserved, "2.13", "In literals, newlines are preserved", passed, total); RunSpecTest(&Spec::PlayByPlayFeed, "2.8", "Play by Play Feed from a Game",
RunSpecTest(&Spec::InFoldedScalarsNewlinesBecomeSpaces, "2.14", "In folded scalars, newlines become spaces", passed, total); passed, total);
RunSpecTest(&Spec::FoldedNewlinesArePreservedForMoreIndentedAndBlankLines, "2.15", "Folded newlines are preserved for \"more indented\" and blank lines", passed, total); RunSpecTest(&Spec::SingleDocumentWithTwoComments, "2.9",
RunSpecTest(&Spec::IndentationDeterminesScope, "2.16", "Indentation determines scope", passed, total); "Single Document with Two Comments", passed, total);
RunSpecTest(&Spec::QuotedScalars, "2.17", "Quoted scalars", passed, total); RunSpecTest(&Spec::SimpleAnchor, "2.10",
RunSpecTest(&Spec::MultiLineFlowScalars, "2.18", "Multi-line flow scalars", passed, total); "Node for \"Sammy Sosa\" appears twice in this document", passed,
total);
RunSpecTest(&Spec::VariousExplicitTags, "2.23", "Various Explicit Tags", passed, total); RunSpecTest(&Spec::MappingBetweenSequences, "2.11",
RunSpecTest(&Spec::GlobalTags, "2.24", "Global Tags", passed, total); "Mapping between Sequences", passed, total);
RunSpecTest(&Spec::UnorderedSets, "2.25", "Unordered Sets", passed, total); RunSpecTest(&Spec::CompactNestedMapping, "2.12", "Compact Nested Mapping",
RunSpecTest(&Spec::OrderedMappings, "2.26", "Ordered Mappings", passed, total); passed, total);
RunSpecTest(&Spec::Invoice, "2.27", "Invoice", passed, total); RunSpecTest(&Spec::InLiteralsNewlinesArePreserved, "2.13",
RunSpecTest(&Spec::LogFile, "2.28", "Log File", passed, total); "In literals, newlines are preserved", passed, total);
RunSpecTest(&Spec::InFoldedScalarsNewlinesBecomeSpaces, "2.14",
RunSpecTest(&Spec::BlockStructureIndicators, "5.3", "Block Structure Indicators", passed, total); "In folded scalars, newlines become spaces", passed, total);
RunSpecTest(&Spec::FlowStructureIndicators, "5.4", "Flow Structure Indicators", passed, total); RunSpecTest(
RunSpecTest(&Spec::NodePropertyIndicators, "5.6", "Node Property Indicators", passed, total); &Spec::FoldedNewlinesArePreservedForMoreIndentedAndBlankLines, "2.15",
RunSpecTest(&Spec::BlockScalarIndicators, "5.7", "Block Scalar Indicators", passed, total); "Folded newlines are preserved for \"more indented\" and blank lines",
RunSpecTest(&Spec::QuotedScalarIndicators, "5.8", "Quoted Scalar Indicators", passed, total); passed, total);
RunSpecTest(&Spec::LineBreakCharacters, "5.11", "Line Break Characters", passed, total); RunSpecTest(&Spec::IndentationDeterminesScope, "2.16",
RunSpecTest(&Spec::TabsAndSpaces, "5.12", "Tabs and Spaces", passed, total); "Indentation determines scope", passed, total);
RunSpecTest(&Spec::EscapedCharacters, "5.13", "Escaped Characters", passed, total); RunSpecTest(&Spec::QuotedScalars, "2.17", "Quoted scalars", passed, total);
RunSpecTest(&Spec::InvalidEscapedCharacters, "5.14", "Invalid Escaped Characters", passed, total); RunSpecTest(&Spec::MultiLineFlowScalars, "2.18", "Multi-line flow scalars",
passed, total);
RunSpecTest(&Spec::IndentationSpaces, "6.1", "Indentation Spaces", passed, total);
RunSpecTest(&Spec::IndentationIndicators, "6.2", "Indentation Indicators", passed, total); RunSpecTest(&Spec::VariousExplicitTags, "2.23", "Various Explicit Tags",
RunSpecTest(&Spec::SeparationSpaces, "6.3", "Separation Spaces", passed, total); passed, total);
RunSpecTest(&Spec::LinePrefixes, "6.4", "Line Prefixes", passed, total); RunSpecTest(&Spec::GlobalTags, "2.24", "Global Tags", passed, total);
RunSpecTest(&Spec::EmptyLines, "6.5", "Empty Lines", passed, total); RunSpecTest(&Spec::UnorderedSets, "2.25", "Unordered Sets", passed, total);
RunSpecTest(&Spec::LineFolding, "6.6", "Line Folding", passed, total); RunSpecTest(&Spec::OrderedMappings, "2.26", "Ordered Mappings", passed,
RunSpecTest(&Spec::BlockFolding, "6.7", "Block Folding", passed, total); total);
RunSpecTest(&Spec::FlowFolding, "6.8", "Flow Folding", passed, total); RunSpecTest(&Spec::Invoice, "2.27", "Invoice", passed, total);
RunSpecTest(&Spec::SeparatedComment, "6.9", "Separated Comment", passed, total); RunSpecTest(&Spec::LogFile, "2.28", "Log File", passed, total);
RunSpecTest(&Spec::CommentLines, "6.10", "Comment Lines", passed, total);
RunSpecTest(&Spec::MultiLineComments, "6.11", "Multi-Line Comments", passed, total); RunSpecTest(&Spec::BlockStructureIndicators, "5.3",
RunSpecTest(&Spec::SeparationSpacesII, "6.12", "Separation Spaces", passed, total); "Block Structure Indicators", passed, total);
RunSpecTest(&Spec::ReservedDirectives, "6.13", "Reserved Directives", passed, total); RunSpecTest(&Spec::FlowStructureIndicators, "5.4",
RunSpecTest(&Spec::YAMLDirective, "6.14", "YAML Directive", passed, total); "Flow Structure Indicators", passed, total);
RunSpecTest(&Spec::InvalidRepeatedYAMLDirective, "6.15", "Invalid Repeated YAML Directive", passed, total); RunSpecTest(&Spec::NodePropertyIndicators, "5.6", "Node Property Indicators",
RunSpecTest(&Spec::TagDirective, "6.16", "Tag Directive", passed, total); passed, total);
RunSpecTest(&Spec::InvalidRepeatedTagDirective, "6.17", "Invalid Repeated Tag Directive", passed, total); RunSpecTest(&Spec::BlockScalarIndicators, "5.7", "Block Scalar Indicators",
RunSpecTest(&Spec::PrimaryTagHandle, "6.18", "Primary Tag Handle", passed, total); passed, total);
RunSpecTest(&Spec::SecondaryTagHandle, "6.19", "SecondaryTagHandle", passed, total); RunSpecTest(&Spec::QuotedScalarIndicators, "5.8", "Quoted Scalar Indicators",
RunSpecTest(&Spec::TagHandles, "6.20", "TagHandles", passed, total); passed, total);
RunSpecTest(&Spec::LocalTagPrefix, "6.21", "LocalTagPrefix", passed, total); RunSpecTest(&Spec::LineBreakCharacters, "5.11", "Line Break Characters",
RunSpecTest(&Spec::GlobalTagPrefix, "6.22", "GlobalTagPrefix", passed, total); passed, total);
RunSpecTest(&Spec::NodeProperties, "6.23", "NodeProperties", passed, total); RunSpecTest(&Spec::TabsAndSpaces, "5.12", "Tabs and Spaces", passed, total);
RunSpecTest(&Spec::VerbatimTags, "6.24", "Verbatim Tags", passed, total); RunSpecTest(&Spec::EscapedCharacters, "5.13", "Escaped Characters", passed,
RunSpecTest(&Spec::InvalidVerbatimTags, "6.25", "Invalid Verbatim Tags", passed, total); total);
RunSpecTest(&Spec::TagShorthands, "6.26", "Tag Shorthands", passed, total); RunSpecTest(&Spec::InvalidEscapedCharacters, "5.14",
RunSpecTest(&Spec::InvalidTagShorthands, "6.27", "Invalid Tag Shorthands", passed, total); "Invalid Escaped Characters", passed, total);
RunSpecTest(&Spec::NonSpecificTags, "6.28", "Non Specific Tags", passed, total);
RunSpecTest(&Spec::NodeAnchors, "6.29", "Node Anchors", passed, total); RunSpecTest(&Spec::IndentationSpaces, "6.1", "Indentation Spaces", passed,
total);
RunSpecTest(&Spec::AliasNodes, "7.1", "Alias Nodes", passed, total); RunSpecTest(&Spec::IndentationIndicators, "6.2", "Indentation Indicators",
RunSpecTest(&Spec::EmptyNodes, "7.2", "Empty Nodes", passed, total); passed, total);
RunSpecTest(&Spec::CompletelyEmptyNodes, "7.3", "Completely Empty Nodes", passed, total); RunSpecTest(&Spec::SeparationSpaces, "6.3", "Separation Spaces", passed,
RunSpecTest(&Spec::DoubleQuotedImplicitKeys, "7.4", "Double Quoted Implicit Keys", passed, total); total);
RunSpecTest(&Spec::DoubleQuotedLineBreaks, "7.5", "Double Quoted Line Breaks", passed, total); RunSpecTest(&Spec::LinePrefixes, "6.4", "Line Prefixes", passed, total);
RunSpecTest(&Spec::DoubleQuotedLines, "7.6", "Double Quoted Lines", passed, total); RunSpecTest(&Spec::EmptyLines, "6.5", "Empty Lines", passed, total);
RunSpecTest(&Spec::SingleQuotedCharacters, "7.7", "Single Quoted Characters", passed, total); RunSpecTest(&Spec::LineFolding, "6.6", "Line Folding", passed, total);
RunSpecTest(&Spec::SingleQuotedImplicitKeys, "7.8", "Single Quoted Implicit Keys", passed, total); RunSpecTest(&Spec::BlockFolding, "6.7", "Block Folding", passed, total);
RunSpecTest(&Spec::SingleQuotedLines, "7.9", "Single Quoted Lines", passed, total); RunSpecTest(&Spec::FlowFolding, "6.8", "Flow Folding", passed, total);
RunSpecTest(&Spec::PlainCharacters, "7.10", "Plain Characters", passed, total); RunSpecTest(&Spec::SeparatedComment, "6.9", "Separated Comment", passed,
RunSpecTest(&Spec::PlainImplicitKeys, "7.11", "Plain Implicit Keys", passed, total); total);
RunSpecTest(&Spec::PlainLines, "7.12", "Plain Lines", passed, total); RunSpecTest(&Spec::CommentLines, "6.10", "Comment Lines", passed, total);
RunSpecTest(&Spec::FlowSequence, "7.13", "Flow Sequence", passed, total); RunSpecTest(&Spec::MultiLineComments, "6.11", "Multi-Line Comments", passed,
RunSpecTest(&Spec::FlowSequenceEntries, "7.14", "Flow Sequence Entries", passed, total); total);
RunSpecTest(&Spec::FlowMappings, "7.15", "Flow Mappings", passed, total); RunSpecTest(&Spec::SeparationSpacesII, "6.12", "Separation Spaces", passed,
RunSpecTest(&Spec::FlowMappingEntries, "7.16", "Flow Mapping Entries", passed, total); total);
RunSpecTest(&Spec::FlowMappingSeparateValues, "7.17", "Flow Mapping Separate Values", passed, total); RunSpecTest(&Spec::ReservedDirectives, "6.13", "Reserved Directives", passed,
RunSpecTest(&Spec::FlowMappingAdjacentValues, "7.18", "Flow Mapping Adjacent Values", passed, total); total);
RunSpecTest(&Spec::SinglePairFlowMappings, "7.19", "Single Pair Flow Mappings", passed, total); RunSpecTest(&Spec::YAMLDirective, "6.14", "YAML Directive", passed, total);
RunSpecTest(&Spec::SinglePairExplicitEntry, "7.20", "Single Pair Explicit Entry", passed, total); RunSpecTest(&Spec::InvalidRepeatedYAMLDirective, "6.15",
RunSpecTest(&Spec::SinglePairImplicitEntries, "7.21", "Single Pair Implicit Entries", passed, total); "Invalid Repeated YAML Directive", passed, total);
RunSpecTest(&Spec::InvalidImplicitKeys, "7.22", "Invalid Implicit Keys", passed, total); RunSpecTest(&Spec::TagDirective, "6.16", "Tag Directive", passed, total);
RunSpecTest(&Spec::FlowContent, "7.23", "Flow Content", passed, total); RunSpecTest(&Spec::InvalidRepeatedTagDirective, "6.17",
RunSpecTest(&Spec::FlowNodes, "7.24", "FlowNodes", passed, total); "Invalid Repeated Tag Directive", passed, total);
RunSpecTest(&Spec::PrimaryTagHandle, "6.18", "Primary Tag Handle", passed,
RunSpecTest(&Spec::BlockScalarHeader, "8.1", "Block Scalar Header", passed, total); total);
RunSpecTest(&Spec::BlockIndentationHeader, "8.2", "Block Indentation Header", passed, total); RunSpecTest(&Spec::SecondaryTagHandle, "6.19", "SecondaryTagHandle", passed,
RunSpecTest(&Spec::InvalidBlockScalarIndentationIndicators, "8.3", "Invalid Block Scalar Indentation Indicators", passed, total); total);
RunSpecTest(&Spec::ChompingFinalLineBreak, "8.4", "Chomping Final Line Break", passed, total); RunSpecTest(&Spec::TagHandles, "6.20", "TagHandles", passed, total);
RunSpecTest(&Spec::ChompingTrailingLines, "8.5", "Chomping Trailing Lines", passed, total); RunSpecTest(&Spec::LocalTagPrefix, "6.21", "LocalTagPrefix", passed, total);
RunSpecTest(&Spec::EmptyScalarChomping, "8.6", "Empty Scalar Chomping", passed, total); RunSpecTest(&Spec::GlobalTagPrefix, "6.22", "GlobalTagPrefix", passed, total);
RunSpecTest(&Spec::LiteralScalar, "8.7", "Literal Scalar", passed, total); RunSpecTest(&Spec::NodeProperties, "6.23", "NodeProperties", passed, total);
RunSpecTest(&Spec::LiteralContent, "8.8", "Literal Content", passed, total); RunSpecTest(&Spec::VerbatimTags, "6.24", "Verbatim Tags", passed, total);
RunSpecTest(&Spec::FoldedScalar, "8.9", "Folded Scalar", passed, total); RunSpecTest(&Spec::InvalidVerbatimTags, "6.25", "Invalid Verbatim Tags",
RunSpecTest(&Spec::FoldedLines, "8.10", "Folded Lines", passed, total); passed, total);
RunSpecTest(&Spec::MoreIndentedLines, "8.11", "More Indented Lines", passed, total); RunSpecTest(&Spec::TagShorthands, "6.26", "Tag Shorthands", passed, total);
RunSpecTest(&Spec::EmptySeparationLines, "8.12", "Empty Separation Lines", passed, total); RunSpecTest(&Spec::InvalidTagShorthands, "6.27", "Invalid Tag Shorthands",
RunSpecTest(&Spec::FinalEmptyLines, "8.13", "Final Empty Lines", passed, total); passed, total);
RunSpecTest(&Spec::BlockSequence, "8.14", "Block Sequence", passed, total); RunSpecTest(&Spec::NonSpecificTags, "6.28", "Non Specific Tags", passed,
RunSpecTest(&Spec::BlockSequenceEntryTypes, "8.15", "Block Sequence Entry Types", passed, total); total);
RunSpecTest(&Spec::BlockMappings, "8.16", "Block Mappings", passed, total); RunSpecTest(&Spec::NodeAnchors, "6.29", "Node Anchors", passed, total);
RunSpecTest(&Spec::ExplicitBlockMappingEntries, "8.17", "Explicit Block Mapping Entries", passed, total);
RunSpecTest(&Spec::ImplicitBlockMappingEntries, "8.18", "Implicit Block Mapping Entries", passed, total); RunSpecTest(&Spec::AliasNodes, "7.1", "Alias Nodes", passed, total);
RunSpecTest(&Spec::CompactBlockMappings, "8.19", "Compact Block Mappings", passed, total); RunSpecTest(&Spec::EmptyNodes, "7.2", "Empty Nodes", passed, total);
RunSpecTest(&Spec::BlockNodeTypes, "8.20", "Block Node Types", passed, total); RunSpecTest(&Spec::CompletelyEmptyNodes, "7.3", "Completely Empty Nodes",
RunSpecTest(&Spec::BlockScalarNodes, "8.21", "Block Scalar Nodes", passed, total); passed, total);
RunSpecTest(&Spec::BlockCollectionNodes, "8.22", "Block Collection Nodes", passed, total); RunSpecTest(&Spec::DoubleQuotedImplicitKeys, "7.4",
"Double Quoted Implicit Keys", passed, total);
std::cout << "Spec tests: " << passed << "/" << total << " passed\n"; RunSpecTest(&Spec::DoubleQuotedLineBreaks, "7.5", "Double Quoted Line Breaks",
return passed == total; passed, total);
} RunSpecTest(&Spec::DoubleQuotedLines, "7.6", "Double Quoted Lines", passed,
total);
RunSpecTest(&Spec::SingleQuotedCharacters, "7.7", "Single Quoted Characters",
passed, total);
RunSpecTest(&Spec::SingleQuotedImplicitKeys, "7.8",
"Single Quoted Implicit Keys", passed, total);
RunSpecTest(&Spec::SingleQuotedLines, "7.9", "Single Quoted Lines", passed,
total);
RunSpecTest(&Spec::PlainCharacters, "7.10", "Plain Characters", passed,
total);
RunSpecTest(&Spec::PlainImplicitKeys, "7.11", "Plain Implicit Keys", passed,
total);
RunSpecTest(&Spec::PlainLines, "7.12", "Plain Lines", passed, total);
RunSpecTest(&Spec::FlowSequence, "7.13", "Flow Sequence", passed, total);
RunSpecTest(&Spec::FlowSequenceEntries, "7.14", "Flow Sequence Entries",
passed, total);
RunSpecTest(&Spec::FlowMappings, "7.15", "Flow Mappings", passed, total);
RunSpecTest(&Spec::FlowMappingEntries, "7.16", "Flow Mapping Entries", passed,
total);
RunSpecTest(&Spec::FlowMappingSeparateValues, "7.17",
"Flow Mapping Separate Values", passed, total);
RunSpecTest(&Spec::FlowMappingAdjacentValues, "7.18",
"Flow Mapping Adjacent Values", passed, total);
RunSpecTest(&Spec::SinglePairFlowMappings, "7.19",
"Single Pair Flow Mappings", passed, total);
RunSpecTest(&Spec::SinglePairExplicitEntry, "7.20",
"Single Pair Explicit Entry", passed, total);
RunSpecTest(&Spec::SinglePairImplicitEntries, "7.21",
"Single Pair Implicit Entries", passed, total);
RunSpecTest(&Spec::InvalidImplicitKeys, "7.22", "Invalid Implicit Keys",
passed, total);
RunSpecTest(&Spec::FlowContent, "7.23", "Flow Content", passed, total);
RunSpecTest(&Spec::FlowNodes, "7.24", "FlowNodes", passed, total);
RunSpecTest(&Spec::BlockScalarHeader, "8.1", "Block Scalar Header", passed,
total);
RunSpecTest(&Spec::BlockIndentationHeader, "8.2", "Block Indentation Header",
passed, total);
RunSpecTest(&Spec::InvalidBlockScalarIndentationIndicators, "8.3",
"Invalid Block Scalar Indentation Indicators", passed, total);
RunSpecTest(&Spec::ChompingFinalLineBreak, "8.4", "Chomping Final Line Break",
passed, total);
RunSpecTest(&Spec::ChompingTrailingLines, "8.5", "Chomping Trailing Lines",
passed, total);
RunSpecTest(&Spec::EmptyScalarChomping, "8.6", "Empty Scalar Chomping",
passed, total);
RunSpecTest(&Spec::LiteralScalar, "8.7", "Literal Scalar", passed, total);
RunSpecTest(&Spec::LiteralContent, "8.8", "Literal Content", passed, total);
RunSpecTest(&Spec::FoldedScalar, "8.9", "Folded Scalar", passed, total);
RunSpecTest(&Spec::FoldedLines, "8.10", "Folded Lines", passed, total);
RunSpecTest(&Spec::MoreIndentedLines, "8.11", "More Indented Lines", passed,
total);
RunSpecTest(&Spec::EmptySeparationLines, "8.12", "Empty Separation Lines",
passed, total);
RunSpecTest(&Spec::FinalEmptyLines, "8.13", "Final Empty Lines", passed,
total);
RunSpecTest(&Spec::BlockSequence, "8.14", "Block Sequence", passed, total);
RunSpecTest(&Spec::BlockSequenceEntryTypes, "8.15",
"Block Sequence Entry Types", passed, total);
RunSpecTest(&Spec::BlockMappings, "8.16", "Block Mappings", passed, total);
RunSpecTest(&Spec::ExplicitBlockMappingEntries, "8.17",
"Explicit Block Mapping Entries", passed, total);
RunSpecTest(&Spec::ImplicitBlockMappingEntries, "8.18",
"Implicit Block Mapping Entries", passed, total);
RunSpecTest(&Spec::CompactBlockMappings, "8.19", "Compact Block Mappings",
passed, total);
RunSpecTest(&Spec::BlockNodeTypes, "8.20", "Block Node Types", passed, total);
RunSpecTest(&Spec::BlockScalarNodes, "8.21", "Block Scalar Nodes", passed,
total);
RunSpecTest(&Spec::BlockCollectionNodes, "8.22", "Block Collection Nodes",
passed, total);
std::cout << "Spec tests: " << passed << "/" << total << " passed\n";
return passed == total;
}
} }

View File

@@ -1,351 +1,352 @@
#ifndef SPECTESTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef SPECTESTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define SPECTESTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define SPECTESTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
#include "teststruct.h" #include "teststruct.h"
namespace Test { namespace Test {
namespace Spec { namespace Spec {
// 2.1 // 2.1
TEST SeqScalars(); TEST SeqScalars();
// 2.2 // 2.2
TEST MappingScalarsToScalars(); TEST MappingScalarsToScalars();
// 2.3 // 2.3
TEST MappingScalarsToSequences(); TEST MappingScalarsToSequences();
// 2.4 // 2.4
TEST SequenceOfMappings(); TEST SequenceOfMappings();
// 2.5 // 2.5
TEST SequenceOfSequences(); TEST SequenceOfSequences();
// 2.6 // 2.6
TEST MappingOfMappings(); TEST MappingOfMappings();
// 2.7 // 2.7
TEST TwoDocumentsInAStream(); TEST TwoDocumentsInAStream();
// 2.8 // 2.8
TEST PlayByPlayFeed(); TEST PlayByPlayFeed();
// 2.9 // 2.9
TEST SingleDocumentWithTwoComments(); TEST SingleDocumentWithTwoComments();
// 2.10 // 2.10
TEST SimpleAnchor(); TEST SimpleAnchor();
// 2.11 // 2.11
TEST MappingBetweenSequences(); TEST MappingBetweenSequences();
// 2.12 // 2.12
TEST CompactNestedMapping(); TEST CompactNestedMapping();
// 2.13 // 2.13
TEST InLiteralsNewlinesArePreserved(); TEST InLiteralsNewlinesArePreserved();
// 2.14 // 2.14
TEST InFoldedScalarsNewlinesBecomeSpaces(); TEST InFoldedScalarsNewlinesBecomeSpaces();
// 2.15 // 2.15
TEST FoldedNewlinesArePreservedForMoreIndentedAndBlankLines(); TEST FoldedNewlinesArePreservedForMoreIndentedAndBlankLines();
// 2.16 // 2.16
TEST IndentationDeterminesScope(); TEST IndentationDeterminesScope();
// 2.17 // 2.17
TEST QuotedScalars(); TEST QuotedScalars();
// 2.18 // 2.18
TEST MultiLineFlowScalars(); TEST MultiLineFlowScalars();
// TODO: 2.19 - 2.22 schema tags // TODO: 2.19 - 2.22 schema tags
// 2.23 // 2.23
TEST VariousExplicitTags(); TEST VariousExplicitTags();
// 2.24 // 2.24
TEST GlobalTags(); TEST GlobalTags();
// 2.25 // 2.25
TEST UnorderedSets(); TEST UnorderedSets();
// 2.26 // 2.26
TEST OrderedMappings(); TEST OrderedMappings();
// 2.27 // 2.27
TEST Invoice(); TEST Invoice();
// 2.28 // 2.28
TEST LogFile(); TEST LogFile();
// TODO: 5.1 - 5.2 BOM // TODO: 5.1 - 5.2 BOM
// 5.3 // 5.3
TEST BlockStructureIndicators(); TEST BlockStructureIndicators();
// 5.4 // 5.4
TEST FlowStructureIndicators(); TEST FlowStructureIndicators();
// 5.5 // 5.5
TEST CommentIndicator(); TEST CommentIndicator();
// 5.6 // 5.6
TEST NodePropertyIndicators(); TEST NodePropertyIndicators();
// 5.7 // 5.7
TEST BlockScalarIndicators(); TEST BlockScalarIndicators();
// 5.8 // 5.8
TEST QuotedScalarIndicators(); TEST QuotedScalarIndicators();
// TODO: 5.9 directive // TODO: 5.9 directive
// TODO: 5.10 reserved indicator // TODO: 5.10 reserved indicator
// 5.11 // 5.11
TEST LineBreakCharacters(); TEST LineBreakCharacters();
// 5.12 // 5.12
TEST TabsAndSpaces(); TEST TabsAndSpaces();
// 5.13 // 5.13
TEST EscapedCharacters(); TEST EscapedCharacters();
// 5.14 // 5.14
TEST InvalidEscapedCharacters(); TEST InvalidEscapedCharacters();
// 6.1 // 6.1
TEST IndentationSpaces(); TEST IndentationSpaces();
// 6.2 // 6.2
TEST IndentationIndicators(); TEST IndentationIndicators();
// 6.3 // 6.3
TEST SeparationSpaces(); TEST SeparationSpaces();
// 6.4 // 6.4
TEST LinePrefixes(); TEST LinePrefixes();
// 6.5 // 6.5
TEST EmptyLines(); TEST EmptyLines();
// 6.6 // 6.6
TEST LineFolding(); TEST LineFolding();
// 6.7 // 6.7
TEST BlockFolding(); TEST BlockFolding();
// 6.8 // 6.8
TEST FlowFolding(); TEST FlowFolding();
// 6.9 // 6.9
TEST SeparatedComment(); TEST SeparatedComment();
// 6.10 // 6.10
TEST CommentLines(); TEST CommentLines();
// 6.11 // 6.11
TEST MultiLineComments(); TEST MultiLineComments();
// 6.12 // 6.12
TEST SeparationSpacesII(); TEST SeparationSpacesII();
// 6.13 // 6.13
TEST ReservedDirectives(); TEST ReservedDirectives();
// 6.14 // 6.14
TEST YAMLDirective(); TEST YAMLDirective();
// 6.15 // 6.15
TEST InvalidRepeatedYAMLDirective(); TEST InvalidRepeatedYAMLDirective();
// 6.16 // 6.16
TEST TagDirective(); TEST TagDirective();
// 6.17 // 6.17
TEST InvalidRepeatedTagDirective(); TEST InvalidRepeatedTagDirective();
// 6.18 // 6.18
TEST PrimaryTagHandle(); TEST PrimaryTagHandle();
// 6.19 // 6.19
TEST SecondaryTagHandle(); TEST SecondaryTagHandle();
// 6.20 // 6.20
TEST TagHandles(); TEST TagHandles();
// 6.21 // 6.21
TEST LocalTagPrefix(); TEST LocalTagPrefix();
// 6.22 // 6.22
TEST GlobalTagPrefix(); TEST GlobalTagPrefix();
// 6.23 // 6.23
TEST NodeProperties(); TEST NodeProperties();
// 6.24 // 6.24
TEST VerbatimTags(); TEST VerbatimTags();
// 6.25 // 6.25
TEST InvalidVerbatimTags(); TEST InvalidVerbatimTags();
// 6.26 // 6.26
TEST TagShorthands(); TEST TagShorthands();
// 6.27 // 6.27
TEST InvalidTagShorthands(); TEST InvalidTagShorthands();
// 6.28 // 6.28
TEST NonSpecificTags(); TEST NonSpecificTags();
// 6.29 // 6.29
TEST NodeAnchors(); TEST NodeAnchors();
// 7.1 // 7.1
TEST AliasNodes(); TEST AliasNodes();
// 7.2 // 7.2
TEST EmptyNodes(); TEST EmptyNodes();
// 7.3 // 7.3
TEST CompletelyEmptyNodes(); TEST CompletelyEmptyNodes();
// 7.4 // 7.4
TEST DoubleQuotedImplicitKeys(); TEST DoubleQuotedImplicitKeys();
// 7.5 // 7.5
TEST DoubleQuotedLineBreaks(); TEST DoubleQuotedLineBreaks();
// 7.6 // 7.6
TEST DoubleQuotedLines(); TEST DoubleQuotedLines();
// 7.7 // 7.7
TEST SingleQuotedCharacters(); TEST SingleQuotedCharacters();
// 7.8 // 7.8
TEST SingleQuotedImplicitKeys(); TEST SingleQuotedImplicitKeys();
// 7.9 // 7.9
TEST SingleQuotedLines(); TEST SingleQuotedLines();
// 7.10 // 7.10
TEST PlainCharacters(); TEST PlainCharacters();
// 7.11 // 7.11
TEST PlainImplicitKeys(); TEST PlainImplicitKeys();
// 7.12 // 7.12
TEST PlainLines(); TEST PlainLines();
// 7.13 // 7.13
TEST FlowSequence(); TEST FlowSequence();
// 7.14 // 7.14
TEST FlowSequenceEntries(); TEST FlowSequenceEntries();
// 7.15 // 7.15
TEST FlowMappings(); TEST FlowMappings();
// 7.16 // 7.16
TEST FlowMappingEntries(); TEST FlowMappingEntries();
// 7.17 // 7.17
TEST FlowMappingSeparateValues(); TEST FlowMappingSeparateValues();
// 7.18 // 7.18
TEST FlowMappingAdjacentValues(); TEST FlowMappingAdjacentValues();
// 7.19 // 7.19
TEST SinglePairFlowMappings(); TEST SinglePairFlowMappings();
// 7.20 // 7.20
TEST SinglePairExplicitEntry(); TEST SinglePairExplicitEntry();
// 7.21 // 7.21
TEST SinglePairImplicitEntries(); TEST SinglePairImplicitEntries();
// 7.22 // 7.22
TEST InvalidImplicitKeys(); TEST InvalidImplicitKeys();
// 7.23 // 7.23
TEST FlowContent(); TEST FlowContent();
// 7.24 // 7.24
TEST FlowNodes(); TEST FlowNodes();
// 8.1 // 8.1
TEST BlockScalarHeader(); TEST BlockScalarHeader();
// 8.2 // 8.2
TEST BlockIndentationHeader(); TEST BlockIndentationHeader();
// 8.3 // 8.3
TEST InvalidBlockScalarIndentationIndicators(); TEST InvalidBlockScalarIndentationIndicators();
// 8.4 // 8.4
TEST ChompingFinalLineBreak(); TEST ChompingFinalLineBreak();
// 8.5 // 8.5
TEST ChompingTrailingLines(); TEST ChompingTrailingLines();
// 8.6 // 8.6
TEST EmptyScalarChomping(); TEST EmptyScalarChomping();
// 8.7 // 8.7
TEST LiteralScalar(); TEST LiteralScalar();
// 8.8 // 8.8
TEST LiteralContent(); TEST LiteralContent();
// 8.9 // 8.9
TEST FoldedScalar(); TEST FoldedScalar();
// 8.10 // 8.10
TEST FoldedLines(); TEST FoldedLines();
// 8.11 // 8.11
TEST MoreIndentedLines(); TEST MoreIndentedLines();
// 8.12 // 8.12
TEST EmptySeparationLines(); TEST EmptySeparationLines();
// 8.13 // 8.13
TEST FinalEmptyLines(); TEST FinalEmptyLines();
// 8.14 // 8.14
TEST BlockSequence(); TEST BlockSequence();
// 8.15 // 8.15
TEST BlockSequenceEntryTypes(); TEST BlockSequenceEntryTypes();
// 8.16 // 8.16
TEST BlockMappings(); TEST BlockMappings();
// 8.17 // 8.17
TEST ExplicitBlockMappingEntries(); TEST ExplicitBlockMappingEntries();
// 8.18 // 8.18
TEST ImplicitBlockMappingEntries(); TEST ImplicitBlockMappingEntries();
// 8.19 // 8.19
TEST CompactBlockMappings(); TEST CompactBlockMappings();
// 8.20 // 8.20
TEST BlockNodeTypes(); TEST BlockNodeTypes();
// 8.21 // 8.21
TEST BlockScalarNodes(); TEST BlockScalarNodes();
// 8.22 // 8.22
TEST BlockCollectionNodes(); TEST BlockCollectionNodes();
}
bool RunSpecTests();
} }
#endif // SPECTESTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 bool RunSpecTests();
}
#endif // SPECTESTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,53 +1,56 @@
#ifndef TESTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef TESTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define TESTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define TESTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
#include <string> #include <string>
namespace Test { namespace Test {
void RunAll(); void RunAll();
namespace Parser { namespace Parser {
// scalar tests // scalar tests
void SimpleScalar(std::string& inputScalar, std::string& desiredOutput); void SimpleScalar(std::string& inputScalar, std::string& desiredOutput);
void MultiLineScalar(std::string& inputScalar, std::string& desiredOutput); void MultiLineScalar(std::string& inputScalar, std::string& desiredOutput);
void LiteralScalar(std::string& inputScalar, std::string& desiredOutput); void LiteralScalar(std::string& inputScalar, std::string& desiredOutput);
void FoldedScalar(std::string& inputScalar, std::string& desiredOutput); void FoldedScalar(std::string& inputScalar, std::string& desiredOutput);
void ChompedFoldedScalar(std::string& inputScalar, std::string& desiredOutput); void ChompedFoldedScalar(std::string& inputScalar, std::string& desiredOutput);
void ChompedLiteralScalar(std::string& inputScalar, std::string& desiredOutput); void ChompedLiteralScalar(std::string& inputScalar, std::string& desiredOutput);
void FoldedScalarWithIndent(std::string& inputScalar, std::string& desiredOutput); void FoldedScalarWithIndent(std::string& inputScalar,
void ColonScalar(std::string& inputScalar, std::string& desiredOutput); std::string& desiredOutput);
void QuotedScalar(std::string& inputScalar, std::string& desiredOutput); void ColonScalar(std::string& inputScalar, std::string& desiredOutput);
void CommaScalar(std::string& inputScalar, std::string& desiredOutput); void QuotedScalar(std::string& inputScalar, std::string& desiredOutput);
void DashScalar(std::string& inputScalar, std::string& desiredOutput); void CommaScalar(std::string& inputScalar, std::string& desiredOutput);
void URLScalar(std::string& inputScalar, std::string& desiredOutput); void DashScalar(std::string& inputScalar, std::string& desiredOutput);
void URLScalar(std::string& inputScalar, std::string& desiredOutput);
// misc tests // misc tests
bool SimpleSeq(); bool SimpleSeq();
bool SimpleMap(); bool SimpleMap();
bool FlowSeq(); bool FlowSeq();
bool FlowMap(); bool FlowMap();
bool FlowMapWithOmittedKey(); bool FlowMapWithOmittedKey();
bool FlowMapWithOmittedValue(); bool FlowMapWithOmittedValue();
bool FlowMapWithSoloEntry(); bool FlowMapWithSoloEntry();
bool FlowMapEndingWithSoloEntry(); bool FlowMapEndingWithSoloEntry();
bool QuotedSimpleKeys(); bool QuotedSimpleKeys();
bool CompressedMapAndSeq(); bool CompressedMapAndSeq();
bool NullBlockSeqEntry(); bool NullBlockSeqEntry();
bool NullBlockMapKey(); bool NullBlockMapKey();
bool NullBlockMapValue(); bool NullBlockMapValue();
bool SimpleAlias(); bool SimpleAlias();
bool AliasWithNull(); bool AliasWithNull();
bool AnchorInSimpleKey(); bool AnchorInSimpleKey();
bool AliasAsSimpleKey(); bool AliasAsSimpleKey();
bool ExplicitDoc(); bool ExplicitDoc();
bool MultipleDocs(); bool MultipleDocs();
bool ExplicitEndDoc(); bool ExplicitEndDoc();
bool MultipleDocsWithSomeExplicitIndicators(); bool MultipleDocsWithSomeExplicitIndicators();
} }
} }
#endif // TESTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #endif // TESTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -2,17 +2,19 @@
#include <string> #include <string>
#define YAML_ASSERT(cond) do { if(!(cond)) return " Assert failed: " #cond; } while(false) #define YAML_ASSERT(cond) \
do { \
if (!(cond)) \
return " Assert failed: " #cond; \
} while (false)
namespace Test namespace Test {
{ struct TEST {
struct TEST { TEST() : ok(false) {}
TEST(): ok(false) {} TEST(bool ok_) : ok(ok_) {}
TEST(bool ok_): ok(ok_) {} TEST(const char *error_) : ok(false), error(error_) {}
TEST(const char *error_): ok(false), error(error_) {}
bool ok;
std::string error;
};
bool ok;
std::string error;
};
} }

View File

@@ -3,127 +3,135 @@
#include "yaml-cpp/yaml.h" #include "yaml-cpp/yaml.h"
#include <iostream> #include <iostream>
int main() int main() {
{ {
{ // test.yaml
// test.yaml // - foo
// - foo // - primes: [2, 3, 5, 7, 11]
// - primes: [2, 3, 5, 7, 11] // odds: [1, 3, 5, 7, 9, 11]
// odds: [1, 3, 5, 7, 9, 11] // - [x, y]
// - [x, y]
// move-like semantics // move-like semantics
YAML::Value root = YAML::Parse("test.yaml"); YAML::Value root = YAML::Parse("test.yaml");
std::cout << root[0].as<std::string>(); // "foo" std::cout << root[0].as<std::string>(); // "foo"
std::cout << str(root[0]); // "foo", shorthand? std::cout << str(root[0]); // "foo", shorthand?
std::cout << root[1]["primes"][3].as<int>(); // "7" std::cout << root[1]["primes"][3].as<int>(); // "7"
std::cout << root[1]["odds"][6].as<int>(); // throws? std::cout << root[1]["odds"][6].as<int>(); // throws?
root[2].push_back(5); root[2].push_back(5);
root[3] = "Hello, World"; root[3] = "Hello, World";
root[0].reset(); root[0].reset();
root[0]["key"] = "value"; root[0]["key"] = "value";
std::cout << root; std::cout << root;
// # not sure about formatting // # not sure about formatting
// - {key: value} // - {key: value}
// - primes: [2, 3, 5, 7, 11] // - primes: [2, 3, 5, 7, 11]
// odds: [1, 3, 5, 7, 9, 11] // odds: [1, 3, 5, 7, 9, 11]
// - [x, y, 5] // - [x, y, 5]
// - Hello, World // - Hello, World
} }
{ {
// for all copy-like commands, think of python's "name/value" semantics // for all copy-like commands, think of python's "name/value" semantics
YAML::Value root = "Hello"; // Hello YAML::Value root = "Hello"; // Hello
root = YAML::Sequence(); // [] root = YAML::Sequence(); // []
root[0] = 0; // [0] root[0] = 0; // [0]
root[2] = "two"; // [0, ~, two] # forces root[1] to be initialized to null root[2] = "two"; // [0, ~, two] # forces root[1] to be initialized to null
YAML::Value other = root; // both point to the same thing YAML::Value other = root; // both point to the same thing
other[0] = 5; // now root[0] is 0 also other[0] = 5; // now root[0] is 0 also
other.push_back(root); // &1 [5, ~, two, *1] other.push_back(root); // &1 [5, ~, two, *1]
other[3][0] = 0; // &1 [0, ~, two, *1] # since it's a true alias other[3][0] = 0; // &1 [0, ~, two, *1] # since it's a true alias
other.push_back(Copy(root)); // &1 [0, ~, two, *1, &2 [0, ~, two, *2]] other.push_back(Copy(root)); // &1 [0, ~, two, *1, &2 [0, ~, two, *2]]
other[4][0] = 5; // &1 [0, ~, two, *1, &2 [5, ~, two, *2]] # they're really different other[4][0] = 5; // &1 [0, ~, two, *1, &2 [5, ~, two, *2]] # they're
} // really different
}
{ {
YAML::Value node; // ~ YAML::Value node; // ~
node[0] = 1; // [1] # auto-construct a sequence node[0] = 1; // [1] # auto-construct a sequence
node["key"] = 5; // {0: 1, key: 5} # auto-turn it into a map node["key"] = 5; // {0: 1, key: 5} # auto-turn it into a map
node.push_back(10); // error, can't turn a map into a sequence node.push_back(10); // error, can't turn a map into a sequence
node.erase("key"); // {0: 1} # still a map, even if we remove the key that caused the problem node.erase("key"); // {0: 1} # still a map, even if we remove the key that
node = "Hello"; // Hello # assignment overwrites everything, so it's now just a plain scalar // caused the problem
} node = "Hello"; // Hello # assignment overwrites everything, so it's now
// just a plain scalar
}
{ {
YAML::Value map; // ~ YAML::Value map; // ~
map[3] = 1; // {3: 1} # auto-constructs a map, *not* a sequence map[3] = 1; // {3: 1} # auto-constructs a map, *not* a sequence
YAML::Value seq; // ~ YAML::Value seq; // ~
seq = YAML::Sequence(); // [] seq = YAML::Sequence(); // []
seq[3] = 1; // [~, ~, ~, 1] seq[3] = 1; // [~, ~, ~, 1]
} }
{ {
YAML::Value node; // ~ YAML::Value node; // ~
node[0] = node; // &1 [*1] # fun stuff node[0] = node; // &1 [*1] # fun stuff
} }
{ {
YAML::Value node; YAML::Value node;
YAML::Value subnode = node["key"]; // 'subnode' is not instantiated ('node' is still null) YAML::Value subnode =
subnode = "value"; // {key: value} # now it is node["key"]; // 'subnode' is not instantiated ('node' is still null)
YAML::Value subnode2 = node["key2"]; subnode = "value"; // {key: value} # now it is
node["key3"] = subnode2; // subnode2 is still not instantiated, but node["key3"] is "pseudo" aliased to it YAML::Value subnode2 = node["key2"];
subnode2 = "monkey"; // {key: value, key2: &1 monkey, key3: *1} # bam! it instantiates both node["key3"] = subnode2; // subnode2 is still not instantiated, but
} // node["key3"] is "pseudo" aliased to it
subnode2 = "monkey"; // {key: value, key2: &1 monkey, key3: *1} # bam! it
// instantiates both
}
{ {
YAML::Value seq = YAML::Sequence(); YAML::Value seq = YAML::Sequence();
seq[0] = "zero"; // [zero] seq[0] = "zero"; // [zero]
seq[1] = seq[0]; // [&1 zero, *1] seq[1] = seq[0]; // [&1 zero, *1]
seq[0] = seq[1]; // [&1 zero, *1] # no-op (they both alias the same thing, so setting them equal is nothing) seq[0] = seq[1]; // [&1 zero, *1] # no-op (they both alias the same thing,
Is(seq[0], seq[1]); // true // so setting them equal is nothing)
seq[1] = "one"; // [&1 one, *1] Is(seq[0], seq[1]); // true
UnAlias(seq[1]); // [one, one] seq[1] = "one"; // [&1 one, *1]
Is(seq[0], seq[1]); // false UnAlias(seq[1]); // [one, one]
} Is(seq[0], seq[1]); // false
}
{ {
YAML::Value root; YAML::Value root;
root.push_back("zero"); root.push_back("zero");
root.push_back("one"); root.push_back("one");
root.push_back("two"); root.push_back("two");
YAML::Value two = root[2]; YAML::Value two = root[2];
root = "scalar"; // 'two' is still "two", even though 'root' is "scalar" (the sequence effectively no longer exists) root = "scalar"; // 'two' is still "two", even though 'root' is "scalar"
// (the sequence effectively no longer exists)
// Note: in all likelihood, the memory for nodes "zero" and "one" is still allocated. How can it go away? Weak pointers? // Note: in all likelihood, the memory for nodes "zero" and "one" is still
} // allocated. How can it go away? Weak pointers?
}
{ {
YAML::Value root; // ~ YAML::Value root; // ~
root[0] = root; // &1 [*1] root[0] = root; // &1 [*1]
root[0] = 5; // [5] root[0] = 5; // [5]
} }
{ {
YAML::Value root; YAML::Value root;
YAML::Value key; YAML::Value key;
key["key"] = "value"; key["key"] = "value";
root[key] = key; // &1 {key: value}: *1 root[key] = key; // &1 {key: value}: *1
} }
{ {
YAML::Value root; YAML::Value root;
root[0] = "hi"; root[0] = "hi";
root[1][0] = "bye"; root[1][0] = "bye";
root[1][1] = root; // &1 [hi, [bye, *1]] # root root[1][1] = root; // &1 [hi, [bye, *1]] # root
YAML::Value sub = root[1]; // &1 [bye, [hi, *1]] # sub YAML::Value sub = root[1]; // &1 [bye, [hi, *1]] # sub
root = "gone"; // [bye, gone] # sub root = "gone"; // [bye, gone] # sub
} }
return 0; return 0;
} }

View File

@@ -2,29 +2,28 @@
#include "yaml-cpp/eventhandler.h" #include "yaml-cpp/eventhandler.h"
#include <iostream> #include <iostream>
class NullEventHandler: public YAML::EventHandler class NullEventHandler : public YAML::EventHandler {
{ public:
public: typedef YAML::Mark Mark;
typedef YAML::Mark Mark; typedef YAML::anchor_t anchor_t;
typedef YAML::anchor_t anchor_t;
NullEventHandler() {} NullEventHandler() {}
virtual void OnDocumentStart(const Mark&) {} virtual void OnDocumentStart(const Mark&) {}
virtual void OnDocumentEnd() {} virtual void OnDocumentEnd() {}
virtual void OnNull(const Mark&, anchor_t) {} virtual void OnNull(const Mark&, anchor_t) {}
virtual void OnAlias(const Mark&, anchor_t) {} virtual void OnAlias(const Mark&, anchor_t) {}
virtual void OnScalar(const Mark&, const std::string&, anchor_t, const std::string&) {} virtual void OnScalar(const Mark&, const std::string&, anchor_t,
virtual void OnSequenceStart(const Mark&, const std::string&, anchor_t) {} const std::string&) {}
virtual void OnSequenceEnd() {} virtual void OnSequenceStart(const Mark&, const std::string&, anchor_t) {}
virtual void OnMapStart(const Mark&, const std::string&, anchor_t) {} virtual void OnSequenceEnd() {}
virtual void OnMapEnd() {} virtual void OnMapStart(const Mark&, const std::string&, anchor_t) {}
virtual void OnMapEnd() {}
}; };
int main() int main() {
{ YAML::Parser parser(std::cin);
YAML::Parser parser(std::cin); NullEventHandler handler;
NullEventHandler handler; parser.HandleNextDocument(handler);
parser.HandleNextDocument(handler); return 0;
return 0;
} }

View File

@@ -2,31 +2,30 @@
#include "yaml-cpp/eventhandler.h" #include "yaml-cpp/eventhandler.h"
#include <iostream> #include <iostream>
class NullEventHandler: public YAML::EventHandler class NullEventHandler : public YAML::EventHandler {
{ public:
public: typedef YAML::Mark Mark;
typedef YAML::Mark Mark; typedef YAML::anchor_t anchor_t;
typedef YAML::anchor_t anchor_t;
NullEventHandler() {} NullEventHandler() {}
virtual void OnDocumentStart(const Mark&) {} virtual void OnDocumentStart(const Mark&) {}
virtual void OnDocumentEnd() {} virtual void OnDocumentEnd() {}
virtual void OnNull(const Mark&, anchor_t) {} virtual void OnNull(const Mark&, anchor_t) {}
virtual void OnAlias(const Mark&, anchor_t) {} virtual void OnAlias(const Mark&, anchor_t) {}
virtual void OnScalar(const Mark&, const std::string&, anchor_t, const std::string&) {} virtual void OnScalar(const Mark&, const std::string&, anchor_t,
virtual void OnSequenceStart(const Mark&, const std::string&, anchor_t) {} const std::string&) {}
virtual void OnSequenceEnd() {} virtual void OnSequenceStart(const Mark&, const std::string&, anchor_t) {}
virtual void OnMapStart(const Mark&, const std::string&, anchor_t) {} virtual void OnSequenceEnd() {}
virtual void OnMapEnd() {} virtual void OnMapStart(const Mark&, const std::string&, anchor_t) {}
virtual void OnMapEnd() {}
}; };
int main() int main() {
{ std::stringstream stream("---{header: {id: 1");
std::stringstream stream("---{header: {id: 1"); YAML::Parser parser(stream);
YAML::Parser parser(stream); // parser.PrintTokens(std::cout);
// parser.PrintTokens(std::cout); NullEventHandler handler;
NullEventHandler handler; parser.HandleNextDocument(handler);
parser.HandleNextDocument(handler); return 0;
return 0;
} }