Commit 9b4db068 authored by Jesse Beder's avatar Jesse Beder
Browse files

Run clang-format

parent e40ed4f9
#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 {
public:
CollectionType::value GetCurCollectionType() const {
if (collectionStack.empty())
return CollectionType::None;
return collectionStack.top();
}
void PushCollectionType(CollectionType::value type) {
collectionStack.push(type);
}
void PopCollectionType(CollectionType::value type) {
assert(type == GetCurCollectionType());
collectionStack.pop();
}
class CollectionStack private:
{ std::stack<CollectionType::value> collectionStack;
public: };
CollectionType::value GetCurCollectionType() const {
if(collectionStack.empty())
return CollectionType::None;
return collectionStack.top();
}
void PushCollectionType(CollectionType::value type) { collectionStack.push(type); }
void PopCollectionType(CollectionType::value type) { assert(type == GetCurCollectionType()); collectionStack.pop(); }
private:
std::stack<CollectionType::value> collectionStack;
};
} }
#endif // COLLECTIONSTACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #endif // COLLECTIONSTACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66
...@@ -2,15 +2,14 @@ ...@@ -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;
}
} }
} }
}
#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 *pNode = m_builder.NewNull(mark, pParent);
void *pParent = GetCurrentParent(); RegisterAnchor(anchor, pNode);
void *pNode = m_builder.NewNull(mark, pParent);
RegisterAnchor(anchor, pNode); DispositionNode(pNode);
}
DispositionNode(pNode);
} void GraphBuilderAdapter::OnAlias(const Mark &mark, anchor_t anchor) {
void *pReffedNode = m_anchors.Get(anchor);
void GraphBuilderAdapter::OnAlias(const Mark& mark, anchor_t anchor) DispositionNode(m_builder.AnchorReference(mark, pReffedNode));
{ }
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 GraphBuilderAdapter::OnScalar(const Mark& mark, const std::string& tag, anchor_t anchor, const std::string& value) void *pNode = m_builder.NewScalar(mark, tag, pParent, value);
{ RegisterAnchor(anchor, pNode);
void *pParent = GetCurrentParent();
void *pNode = m_builder.NewScalar(mark, tag, pParent, value); DispositionNode(pNode);
RegisterAnchor(anchor, pNode); }
DispositionNode(pNode); void GraphBuilderAdapter::OnSequenceStart(const Mark &mark,
} const std::string &tag,
anchor_t anchor) {
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));
void *pNode = m_builder.NewSequence(mark, tag, GetCurrentParent()); RegisterAnchor(anchor, pNode);
m_containers.push(ContainerFrame(pNode)); }
RegisterAnchor(anchor, pNode);
} void GraphBuilderAdapter::OnSequenceEnd() {
void *pSequence = m_containers.top().pContainer;
void GraphBuilderAdapter::OnSequenceEnd() m_containers.pop();
{
void *pSequence = m_containers.top().pContainer; DispositionNode(pSequence);
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());
void GraphBuilderAdapter::OnMapStart(const Mark& mark, const std::string& tag, anchor_t anchor) m_containers.push(ContainerFrame(pNode, m_pKeyNode));
{ m_pKeyNode = NULL;
void *pNode = m_builder.NewMap(mark, tag, GetCurrentParent()); RegisterAnchor(anchor, pNode);
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;
void GraphBuilderAdapter::OnMapEnd() m_containers.pop();
{ DispositionNode(pMap);
void *pMap = m_containers.top().pContainer; }
m_pKeyNode = m_containers.top().pPrevKeyNode;
m_containers.pop(); void *GraphBuilderAdapter::GetCurrentParent() const {
DispositionNode(pMap); if (m_containers.empty()) {
return NULL;
} }
return m_containers.top().pContainer;
void *GraphBuilderAdapter::GetCurrentParent() const }
{
if (m_containers.empty()) { void GraphBuilderAdapter::RegisterAnchor(anchor_t anchor, void *pNode) {
return NULL; if (anchor) {
} m_anchors.Register(anchor, pNode);
return m_containers.top().pContainer;
} }
}
void GraphBuilderAdapter::RegisterAnchor(anchor_t anchor, void *pNode)
{ void GraphBuilderAdapter::DispositionNode(void *pNode) {
if (anchor) { if (m_containers.empty()) {
m_anchors.Register(anchor, pNode); m_pRootNode = pNode;
} return;
} }
void GraphBuilderAdapter::DispositionNode(void *pNode) void *pContainer = m_containers.top().pContainer;
{ if (m_containers.top().isMap()) {
if (m_containers.empty()) { if (m_pKeyNode) {
m_pRootNode = pNode; m_builder.AssignInMap(pContainer, m_pKeyNode, pNode);
return; m_pKeyNode = NULL;
}
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 { } else {
m_builder.AppendToSequence(pContainer, pNode); m_pKeyNode = pNode;
} }
} else {
m_builder.AppendToSequence(pContainer, pNode);
} }
} }
}
#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 @@ ...@@ -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 OnDocumentEnd() {}
}
virtual void OnNull(const Mark& mark, anchor_t anchor);
virtual void OnDocumentStart(const Mark& mark) {(void)mark;} virtual void OnAlias(const Mark& mark, anchor_t anchor);
virtual void OnDocumentEnd() {} virtual void OnScalar(const Mark& mark, const std::string& tag,
anchor_t anchor, const std::string& value);
virtual void OnNull(const Mark& mark, anchor_t anchor);
virtual void OnAlias(const Mark& mark, anchor_t anchor); virtual void OnSequenceStart(const Mark& mark, const std::string& tag,
virtual void OnScalar(const Mark& mark, const std::string& tag, anchor_t anchor, const std::string& value); anchor_t anchor);
virtual void OnSequenceEnd();
virtual void OnSequenceStart(const Mark& mark, const std::string& tag, 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, anchor_t anchor); virtual void OnMapEnd();
virtual void OnMapEnd();
void* RootNode() const { return m_pRootNode; }
void *RootNode() const {return m_pRootNode;}
private:
private: struct ContainerFrame {
struct ContainerFrame ContainerFrame(void* pSequence)
{ : pContainer(pSequence), pPrevKeyNode(&sequenceMarker) {}
ContainerFrame(void *pSequence) ContainerFrame(void* pMap, void* pPrevKeyNode)
: pContainer(pSequence), pPrevKeyNode(&sequenceMarker) : pContainer(pMap), pPrevKeyNode(pPrevKeyNode) {}
{}
ContainerFrame(void *pMap, void* pPrevKeyNode) void* pContainer;
: pContainer(pMap), pPrevKeyNode(pPrevKeyNode) void* pPrevKeyNode;
{}
bool isMap() const { return pPrevKeyNode != &sequenceMarker; }
void *pContainer;
void *pPrevKeyNode; private:
static int sequenceMarker;
bool isMap() const {return pPrevKeyNode != &sequenceMarker;}
private:
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
#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;
}
} }
#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
...@@ -5,101 +5,88 @@ ...@@ -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 {
EmitFromEvents::EmitFromEvents(Emitter& emitter) : m_emitter(emitter) {}
void EmitFromEvents::OnDocumentStart(const Mark&) {}
void EmitFromEvents::OnDocumentEnd() {}
void EmitFromEvents::OnNull(const Mark&, anchor_t anchor) {
BeginNode();
EmitProps("", anchor);
m_emitter << Null;
}
void EmitFromEvents::OnAlias(const Mark&, anchor_t anchor) {
BeginNode();
m_emitter << Alias(ToString(anchor));
}
void EmitFromEvents::OnScalar(const Mark&, const std::string& tag,
anchor_t anchor, const std::string& value) {
BeginNode();
EmitProps(tag, anchor);
m_emitter << value;
} }
namespace YAML void EmitFromEvents::OnSequenceStart(const Mark&, const std::string& tag,
{ anchor_t anchor) {
EmitFromEvents::EmitFromEvents(Emitter& emitter): m_emitter(emitter) BeginNode();
{ EmitProps(tag, anchor);
} m_emitter << BeginSeq;
m_stateStack.push(State::WaitingForSequenceEntry);
void EmitFromEvents::OnDocumentStart(const Mark&) }
{
} void EmitFromEvents::OnSequenceEnd() {
m_emitter << EndSeq;
void EmitFromEvents::OnDocumentEnd() assert(m_stateStack.top() == State::WaitingForSequenceEntry);
{ m_stateStack.pop();
} }
void EmitFromEvents::OnNull(const Mark&, anchor_t anchor) void EmitFromEvents::OnMapStart(const Mark&, const std::string& tag,
{ anchor_t anchor) {
BeginNode(); BeginNode();
EmitProps("", anchor); EmitProps(tag, anchor);
m_emitter << Null; m_emitter << BeginMap;
} m_stateStack.push(State::WaitingForKey);
}
void EmitFromEvents::OnAlias(const Mark&, anchor_t anchor)
{
BeginNode();
m_emitter << Alias(ToString(anchor));
}
void EmitFromEvents::OnScalar(const Mark&, const std::string& tag, anchor_t anchor, const std::string& value)
{
BeginNode();
EmitProps(tag, anchor);
m_emitter << value;
}
void EmitFromEvents::OnSequenceStart(const Mark&, const std::string& tag, anchor_t anchor)
{
BeginNode();
EmitProps(tag, anchor);
m_emitter << BeginSeq;
m_stateStack.push(State::WaitingForSequenceEntry);
}
void EmitFromEvents::OnSequenceEnd()
{
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();
EmitProps(tag, anchor);
m_emitter << BeginMap;
m_stateStack.push(State::WaitingForKey);
}
void EmitFromEvents::OnMapEnd() void EmitFromEvents::OnMapEnd() {
{ m_emitter << EndMap;
m_emitter << EndMap; assert(m_stateStack.top() == State::WaitingForKey);
assert(m_stateStack.top() == State::WaitingForKey); m_stateStack.pop();
m_stateStack.pop(); }
}
void EmitFromEvents::BeginNode() {
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));
}
} }
...@@ -5,947 +5,902 @@ ...@@ -5,947 +5,902 @@
#include "yaml-cpp/exceptions.h" #include "yaml-cpp/exceptions.h"
#include <sstream> #include <sstream>
namespace YAML namespace YAML {
{ Emitter::Emitter() : m_pState(new EmitterState) {}
Emitter::Emitter(): m_pState(new EmitterState)
{
}
Emitter::Emitter(std::ostream& stream): m_pState(new EmitterState), m_stream(stream)
{
}
Emitter::~Emitter()
{
}
const char *Emitter::c_str() const
{
return m_stream.str();
}
std::size_t Emitter::size() const
{
return m_stream.pos();
}
// state checking
bool Emitter::good() const
{
return m_pState->good();
}
const std::string Emitter::GetLastError() const
{
return m_pState->GetLastError();
}
// global setters
bool Emitter::SetOutputCharset(EMITTER_MANIP value)
{
return m_pState->SetOutputCharset(value, FmtScope::Global);
}
bool Emitter::SetStringFormat(EMITTER_MANIP value)
{
return m_pState->SetStringFormat(value, FmtScope::Global);
}
bool Emitter::SetBoolFormat(EMITTER_MANIP value)
{
bool ok = false;
if(m_pState->SetBoolFormat(value, FmtScope::Global))
ok = true;
if(m_pState->SetBoolCaseFormat(value, FmtScope::Global))
ok = true;
if(m_pState->SetBoolLengthFormat(value, FmtScope::Global))
ok = true;
return ok;
}
bool Emitter::SetIntBase(EMITTER_MANIP value)
{
return m_pState->SetIntFormat(value, FmtScope::Global);
}
bool Emitter::SetSeqFormat(EMITTER_MANIP value)
{
return m_pState->SetFlowType(GroupType::Seq, value, FmtScope::Global);
}
bool Emitter::SetMapFormat(EMITTER_MANIP value)
{
bool ok = false;
if(m_pState->SetFlowType(GroupType::Map, value, FmtScope::Global))
ok = true;
if(m_pState->SetMapKeyFormat(value, FmtScope::Global))
ok = true;
return ok;
}
bool Emitter::SetIndent(unsigned n)
{
return m_pState->SetIndent(n, FmtScope::Global);
}
bool Emitter::SetPreCommentIndent(unsigned n)
{
return m_pState->SetPreCommentIndent(n, FmtScope::Global);
}
bool Emitter::SetPostCommentIndent(unsigned n)
{
return m_pState->SetPostCommentIndent(n, FmtScope::Global);
}
bool Emitter::SetFloatPrecision(unsigned n)
{
return m_pState->SetFloatPrecision(n, FmtScope::Global);
}
bool Emitter::SetDoublePrecision(unsigned n) Emitter::Emitter(std::ostream& stream)
{ : m_pState(new EmitterState), m_stream(stream) {}
return m_pState->SetDoublePrecision(n, FmtScope::Global);
}
// SetLocalValue Emitter::~Emitter() {}
// . Either start/end a group, or set a modifier locally
Emitter& Emitter::SetLocalValue(EMITTER_MANIP value)
{
if(!good())
return *this;
switch(value) {
case BeginDoc:
EmitBeginDoc();
break;
case EndDoc:
EmitEndDoc();
break;
case BeginSeq:
EmitBeginSeq();
break;
case EndSeq:
EmitEndSeq();
break;
case BeginMap:
EmitBeginMap();
break;
case EndMap:
EmitEndMap();
break;
case Key:
case Value:
// deprecated (these can be deduced by the parity of nodes in a map)
break;
case TagByKind:
EmitKindTag();
break;
case Newline:
EmitNewline();
break;
default:
m_pState->SetLocalValue(value);
break;
}
return *this;
}
Emitter& Emitter::SetLocalIndent(const _Indent& indent)
{
m_pState->SetIndent(indent.value, FmtScope::Local);
return *this;
}
Emitter& Emitter::SetLocalPrecision(const _Precision& precision)
{
if(precision.floatPrecision >= 0)
m_pState->SetFloatPrecision(precision.floatPrecision, FmtScope::Local);
if(precision.doublePrecision >= 0)
m_pState->SetDoublePrecision(precision.doublePrecision, FmtScope::Local);
return *this;
}
// EmitBeginDoc const char* Emitter::c_str() const { return m_stream.str(); }
void Emitter::EmitBeginDoc()
{ std::size_t Emitter::size() const { return m_stream.pos(); }
if(!good())
return; // state checking
bool Emitter::good() const { return m_pState->good(); }
if(m_pState->CurGroupType() != GroupType::None) {
m_pState->SetError("Unexpected begin document"); const std::string Emitter::GetLastError() const {
return; return m_pState->GetLastError();
} }
if(m_pState->HasAnchor() || m_pState->HasTag()) { // global setters
m_pState->SetError("Unexpected begin document"); bool Emitter::SetOutputCharset(EMITTER_MANIP value) {
return; return m_pState->SetOutputCharset(value, FmtScope::Global);
} }
if(m_stream.col() > 0) bool Emitter::SetStringFormat(EMITTER_MANIP value) {
m_stream << "\n"; return m_pState->SetStringFormat(value, FmtScope::Global);
m_stream << "---\n"; }
m_pState->StartedDoc(); bool Emitter::SetBoolFormat(EMITTER_MANIP value) {
} bool ok = false;
if (m_pState->SetBoolFormat(value, FmtScope::Global))
// EmitEndDoc ok = true;
void Emitter::EmitEndDoc() if (m_pState->SetBoolCaseFormat(value, FmtScope::Global))
{ ok = true;
if(!good()) if (m_pState->SetBoolLengthFormat(value, FmtScope::Global))
return; ok = true;
return ok;
if(m_pState->CurGroupType() != GroupType::None) { }
m_pState->SetError("Unexpected begin document");
return; bool Emitter::SetIntBase(EMITTER_MANIP value) {
} return m_pState->SetIntFormat(value, FmtScope::Global);
}
if(m_pState->HasAnchor() || m_pState->HasTag()) {
m_pState->SetError("Unexpected begin document"); bool Emitter::SetSeqFormat(EMITTER_MANIP value) {
return; return m_pState->SetFlowType(GroupType::Seq, value, FmtScope::Global);
} }
if(m_stream.col() > 0) bool Emitter::SetMapFormat(EMITTER_MANIP value) {
m_stream << "\n"; bool ok = false;
m_stream << "...\n"; if (m_pState->SetFlowType(GroupType::Map, value, FmtScope::Global))
} ok = true;
if (m_pState->SetMapKeyFormat(value, FmtScope::Global))
// EmitBeginSeq ok = true;
void Emitter::EmitBeginSeq() return ok;
{ }
if(!good())
return; bool Emitter::SetIndent(unsigned n) {
return m_pState->SetIndent(n, FmtScope::Global);
PrepareNode(m_pState->NextGroupType(GroupType::Seq)); }
m_pState->StartedGroup(GroupType::Seq); bool Emitter::SetPreCommentIndent(unsigned n) {
} return m_pState->SetPreCommentIndent(n, FmtScope::Global);
}
// EmitEndSeq
void Emitter::EmitEndSeq() bool Emitter::SetPostCommentIndent(unsigned n) {
{ return m_pState->SetPostCommentIndent(n, FmtScope::Global);
if(!good()) }
return;
bool Emitter::SetFloatPrecision(unsigned n) {
if(m_pState->CurGroupChildCount() == 0) return m_pState->SetFloatPrecision(n, FmtScope::Global);
m_pState->ForceFlow(); }
if(m_pState->CurGroupFlowType() == FlowType::Flow) { bool Emitter::SetDoublePrecision(unsigned n) {
if(m_stream.comment()) return m_pState->SetDoublePrecision(n, FmtScope::Global);
m_stream << "\n"; }
m_stream << IndentTo(m_pState->CurIndent());
if(m_pState->CurGroupChildCount() == 0) // SetLocalValue
m_stream << "["; // . Either start/end a group, or set a modifier locally
m_stream << "]"; Emitter& Emitter::SetLocalValue(EMITTER_MANIP value) {
} if (!good())
return *this;
m_pState->EndedGroup(GroupType::Seq);
} switch (value) {
case BeginDoc:
// EmitBeginMap EmitBeginDoc();
void Emitter::EmitBeginMap() break;
{ case EndDoc:
if(!good()) EmitEndDoc();
return; break;
case BeginSeq:
PrepareNode(m_pState->NextGroupType(GroupType::Map)); EmitBeginSeq();
break;
m_pState->StartedGroup(GroupType::Map); case EndSeq:
} EmitEndSeq();
break;
// EmitEndMap case BeginMap:
void Emitter::EmitEndMap() EmitBeginMap();
{ break;
if(!good()) case EndMap:
return; EmitEndMap();
break;
if(m_pState->CurGroupChildCount() == 0) case Key:
m_pState->ForceFlow(); case Value:
// deprecated (these can be deduced by the parity of nodes in a map)
if(m_pState->CurGroupFlowType() == FlowType::Flow) { break;
if(m_stream.comment()) case TagByKind:
m_stream << "\n"; EmitKindTag();
m_stream << IndentTo(m_pState->CurIndent()); break;
if(m_pState->CurGroupChildCount() == 0) case Newline:
m_stream << "{"; EmitNewline();
m_stream << "}"; break;
} default:
m_pState->SetLocalValue(value);
m_pState->EndedGroup(GroupType::Map); break;
} }
return *this;
}
Emitter& Emitter::SetLocalIndent(const _Indent& indent) {
m_pState->SetIndent(indent.value, FmtScope::Local);
return *this;
}
Emitter& Emitter::SetLocalPrecision(const _Precision& precision) {
if (precision.floatPrecision >= 0)
m_pState->SetFloatPrecision(precision.floatPrecision, FmtScope::Local);
if (precision.doublePrecision >= 0)
m_pState->SetDoublePrecision(precision.doublePrecision, FmtScope::Local);
return *this;
}
// EmitBeginDoc
void Emitter::EmitBeginDoc() {
if (!good())
return;
if (m_pState->CurGroupType() != GroupType::None) {
m_pState->SetError("Unexpected begin document");
return;
}
if (m_pState->HasAnchor() || m_pState->HasTag()) {
m_pState->SetError("Unexpected begin document");
return;
}
if (m_stream.col() > 0)
m_stream << "\n";
m_stream << "---\n";
m_pState->StartedDoc();
}
// EmitEndDoc
void Emitter::EmitEndDoc() {
if (!good())
return;
if (m_pState->CurGroupType() != GroupType::None) {
m_pState->SetError("Unexpected begin document");
return;
}
if (m_pState->HasAnchor() || m_pState->HasTag()) {
m_pState->SetError("Unexpected begin document");
return;
}
// EmitNewline if (m_stream.col() > 0)
void Emitter::EmitNewline() m_stream << "\n";
{ m_stream << "...\n";
if(!good()) }
return;
// EmitBeginSeq
PrepareNode(EmitterNodeType::None); void Emitter::EmitBeginSeq() {
if (!good())
return;
PrepareNode(m_pState->NextGroupType(GroupType::Seq));
m_pState->StartedGroup(GroupType::Seq);
}
// EmitEndSeq
void Emitter::EmitEndSeq() {
if (!good())
return;
if (m_pState->CurGroupChildCount() == 0)
m_pState->ForceFlow();
if (m_pState->CurGroupFlowType() == FlowType::Flow) {
if (m_stream.comment())
m_stream << "\n";
m_stream << IndentTo(m_pState->CurIndent());
if (m_pState->CurGroupChildCount() == 0)
m_stream << "[";
m_stream << "]";
}
m_pState->EndedGroup(GroupType::Seq);
}
// EmitBeginMap
void Emitter::EmitBeginMap() {
if (!good())
return;
PrepareNode(m_pState->NextGroupType(GroupType::Map));
m_pState->StartedGroup(GroupType::Map);
}
// EmitEndMap
void Emitter::EmitEndMap() {
if (!good())
return;
if (m_pState->CurGroupChildCount() == 0)
m_pState->ForceFlow();
if (m_pState->CurGroupFlowType() == FlowType::Flow) {
if (m_stream.comment())
m_stream << "\n";
m_stream << IndentTo(m_pState->CurIndent());
if (m_pState->CurGroupChildCount() == 0)
m_stream << "{";
m_stream << "}";
}
m_pState->EndedGroup(GroupType::Map);
}
// EmitNewline
void Emitter::EmitNewline() {
if (!good())
return;
PrepareNode(EmitterNodeType::None);
m_stream << "\n";
m_pState->SetNonContent();
}
bool Emitter::CanEmitNewline() const { return true; }
// Put the stream in a state so we can simply write the next node
// E.g., if we're in a sequence, write the "- "
void Emitter::PrepareNode(EmitterNodeType::value child) {
switch (m_pState->CurGroupNodeType()) {
case EmitterNodeType::None:
PrepareTopNode(child);
break;
case EmitterNodeType::FlowSeq:
FlowSeqPrepareNode(child);
break;
case EmitterNodeType::BlockSeq:
BlockSeqPrepareNode(child);
break;
case EmitterNodeType::FlowMap:
FlowMapPrepareNode(child);
break;
case EmitterNodeType::BlockMap:
BlockMapPrepareNode(child);
break;
case EmitterNodeType::Property:
case EmitterNodeType::Scalar:
assert(false);
break;
}
}
void Emitter::PrepareTopNode(EmitterNodeType::value child) {
if (child == EmitterNodeType::None)
return;
if (m_pState->CurGroupChildCount() > 0 && m_stream.col() > 0) {
if (child != EmitterNodeType::None)
EmitBeginDoc();
}
switch (child) {
case EmitterNodeType::None:
break;
case EmitterNodeType::Property:
case EmitterNodeType::Scalar:
case EmitterNodeType::FlowSeq:
case EmitterNodeType::FlowMap:
// TODO: if we were writing null, and
// we wanted it blank, we wouldn't want a space
SpaceOrIndentTo(m_pState->HasBegunContent(), 0);
break;
case EmitterNodeType::BlockSeq:
case EmitterNodeType::BlockMap:
if (m_pState->HasBegunNode())
m_stream << "\n"; m_stream << "\n";
m_pState->SetNonContent(); break;
} }
}
bool Emitter::CanEmitNewline() const
{
return true;
}
// Put the stream in a state so we can simply write the next node
// E.g., if we're in a sequence, write the "- "
void Emitter::PrepareNode(EmitterNodeType::value child)
{
switch(m_pState->CurGroupNodeType()) {
case EmitterNodeType::None:
PrepareTopNode(child);
break;
case EmitterNodeType::FlowSeq:
FlowSeqPrepareNode(child);
break;
case EmitterNodeType::BlockSeq:
BlockSeqPrepareNode(child);
break;
case EmitterNodeType::FlowMap:
FlowMapPrepareNode(child);
break;
case EmitterNodeType::BlockMap:
BlockMapPrepareNode(child);
break;
case EmitterNodeType::Property:
case EmitterNodeType::Scalar:
assert(false);
break;
}
}
void Emitter::PrepareTopNode(EmitterNodeType::value child)
{
if(child == EmitterNodeType::None)
return;
if(m_pState->CurGroupChildCount() > 0 && m_stream.col() > 0) {
if(child != EmitterNodeType::None)
EmitBeginDoc();
}
switch(child) {
case EmitterNodeType::None:
break;
case EmitterNodeType::Property:
case EmitterNodeType::Scalar:
case EmitterNodeType::FlowSeq:
case EmitterNodeType::FlowMap:
// TODO: if we were writing null, and
// we wanted it blank, we wouldn't want a space
SpaceOrIndentTo(m_pState->HasBegunContent(), 0);
break;
case EmitterNodeType::BlockSeq:
case EmitterNodeType::BlockMap:
if(m_pState->HasBegunNode())
m_stream << "\n";
break;
}
}
void Emitter::FlowSeqPrepareNode(EmitterNodeType::value child)
{
const unsigned lastIndent = m_pState->LastIndent();
if(!m_pState->HasBegunNode()) {
if(m_stream.comment())
m_stream << "\n";
m_stream << IndentTo(lastIndent);
if(m_pState->CurGroupChildCount() == 0)
m_stream << "[";
else
m_stream << ",";
}
switch(child) {
case EmitterNodeType::None:
break;
case EmitterNodeType::Property:
case EmitterNodeType::Scalar:
case EmitterNodeType::FlowSeq:
case EmitterNodeType::FlowMap:
SpaceOrIndentTo(m_pState->HasBegunContent() || m_pState->CurGroupChildCount() > 0, lastIndent);
break;
case EmitterNodeType::BlockSeq:
case EmitterNodeType::BlockMap:
assert(false);
break;
}
}
void Emitter::BlockSeqPrepareNode(EmitterNodeType::value child) void Emitter::FlowSeqPrepareNode(EmitterNodeType::value child) {
{ const unsigned lastIndent = m_pState->LastIndent();
const unsigned curIndent = m_pState->CurIndent();
const unsigned nextIndent = curIndent + m_pState->CurGroupIndent(); if (!m_pState->HasBegunNode()) {
if (m_stream.comment())
if(child == EmitterNodeType::None) m_stream << "\n";
return; m_stream << IndentTo(lastIndent);
if (m_pState->CurGroupChildCount() == 0)
if(!m_pState->HasBegunContent()) { m_stream << "[";
if(m_pState->CurGroupChildCount() > 0 || m_stream.comment()) { else
m_stream << "\n"; m_stream << ",";
} }
m_stream << IndentTo(curIndent);
m_stream << "-"; switch (child) {
} case EmitterNodeType::None:
break;
switch(child) { case EmitterNodeType::Property:
case EmitterNodeType::None: case EmitterNodeType::Scalar:
break; case EmitterNodeType::FlowSeq:
case EmitterNodeType::Property: case EmitterNodeType::FlowMap:
case EmitterNodeType::Scalar: SpaceOrIndentTo(
case EmitterNodeType::FlowSeq: m_pState->HasBegunContent() || m_pState->CurGroupChildCount() > 0,
case EmitterNodeType::FlowMap: lastIndent);
SpaceOrIndentTo(m_pState->HasBegunContent(), nextIndent); break;
break; case EmitterNodeType::BlockSeq:
case EmitterNodeType::BlockSeq: case EmitterNodeType::BlockMap:
m_stream << "\n"; assert(false);
break; break;
case EmitterNodeType::BlockMap: }
if(m_pState->HasBegunContent() || m_stream.comment()) }
m_stream << "\n";
break;
}
}
void Emitter::FlowMapPrepareNode(EmitterNodeType::value child)
{
if(m_pState->CurGroupChildCount() % 2 == 0) {
if(m_pState->GetMapKeyFormat() == LongKey)
m_pState->SetLongKey();
if(m_pState->CurGroupLongKey())
FlowMapPrepareLongKey(child);
else
FlowMapPrepareSimpleKey(child);
} else {
if(m_pState->CurGroupLongKey())
FlowMapPrepareLongKeyValue(child);
else
FlowMapPrepareSimpleKeyValue(child);
}
}
void Emitter::FlowMapPrepareLongKey(EmitterNodeType::value child) void Emitter::BlockSeqPrepareNode(EmitterNodeType::value child) {
{ const unsigned curIndent = m_pState->CurIndent();
const unsigned lastIndent = m_pState->LastIndent(); const unsigned nextIndent = curIndent + m_pState->CurGroupIndent();
if(!m_pState->HasBegunNode()) {
if(m_stream.comment())
m_stream << "\n";
m_stream << IndentTo(lastIndent);
if(m_pState->CurGroupChildCount() == 0)
m_stream << "{ ?";
else
m_stream << ", ?";
}
switch(child) {
case EmitterNodeType::None:
break;
case EmitterNodeType::Property:
case EmitterNodeType::Scalar:
case EmitterNodeType::FlowSeq:
case EmitterNodeType::FlowMap:
SpaceOrIndentTo(m_pState->HasBegunContent() || m_pState->CurGroupChildCount() > 0, lastIndent);
break;
case EmitterNodeType::BlockSeq:
case EmitterNodeType::BlockMap:
assert(false);
break;
}
}
void Emitter::FlowMapPrepareLongKeyValue(EmitterNodeType::value child)
{
const unsigned lastIndent = m_pState->LastIndent();
if(!m_pState->HasBegunNode()) {
if(m_stream.comment())
m_stream << "\n";
m_stream << IndentTo(lastIndent);
m_stream << ":";
}
switch(child) {
case EmitterNodeType::None:
break;
case EmitterNodeType::Property:
case EmitterNodeType::Scalar:
case EmitterNodeType::FlowSeq:
case EmitterNodeType::FlowMap:
SpaceOrIndentTo(m_pState->HasBegunContent() || m_pState->CurGroupChildCount() > 0, lastIndent);
break;
case EmitterNodeType::BlockSeq:
case EmitterNodeType::BlockMap:
assert(false);
break;
}
}
void Emitter::FlowMapPrepareSimpleKey(EmitterNodeType::value child)
{
const unsigned lastIndent = m_pState->LastIndent();
if(!m_pState->HasBegunNode()) {
if(m_stream.comment())
m_stream << "\n";
m_stream << IndentTo(lastIndent);
if(m_pState->CurGroupChildCount() == 0)
m_stream << "{";
else
m_stream << ",";
}
switch(child) {
case EmitterNodeType::None:
break;
case EmitterNodeType::Property:
case EmitterNodeType::Scalar:
case EmitterNodeType::FlowSeq:
case EmitterNodeType::FlowMap:
SpaceOrIndentTo(m_pState->HasBegunContent() || m_pState->CurGroupChildCount() > 0, lastIndent);
break;
case EmitterNodeType::BlockSeq:
case EmitterNodeType::BlockMap:
assert(false);
break;
}
}
void Emitter::FlowMapPrepareSimpleKeyValue(EmitterNodeType::value child)
{
const unsigned lastIndent = m_pState->LastIndent();
if(!m_pState->HasBegunNode()) {
if(m_stream.comment())
m_stream << "\n";
m_stream << IndentTo(lastIndent);
m_stream << ":";
}
switch(child) {
case EmitterNodeType::None:
break;
case EmitterNodeType::Property:
case EmitterNodeType::Scalar:
case EmitterNodeType::FlowSeq:
case EmitterNodeType::FlowMap:
SpaceOrIndentTo(m_pState->HasBegunContent() || m_pState->CurGroupChildCount() > 0, lastIndent);
break;
case EmitterNodeType::BlockSeq:
case EmitterNodeType::BlockMap:
assert(false);
break;
}
}
void Emitter::BlockMapPrepareNode(EmitterNodeType::value child) if (child == EmitterNodeType::None)
{ return;
if(m_pState->CurGroupChildCount() % 2 == 0) {
if(m_pState->GetMapKeyFormat() == LongKey)
m_pState->SetLongKey();
if(child == EmitterNodeType::BlockSeq || child == EmitterNodeType::BlockMap)
m_pState->SetLongKey();
if(m_pState->CurGroupLongKey())
BlockMapPrepareLongKey(child);
else
BlockMapPrepareSimpleKey(child);
} else {
if(m_pState->CurGroupLongKey())
BlockMapPrepareLongKeyValue(child);
else
BlockMapPrepareSimpleKeyValue(child);
}
}
void Emitter::BlockMapPrepareLongKey(EmitterNodeType::value child)
{
const unsigned curIndent = m_pState->CurIndent();
const std::size_t childCount = m_pState->CurGroupChildCount();
if(child == EmitterNodeType::None)
return;
if(!m_pState->HasBegunContent()) {
if(childCount > 0) {
m_stream << "\n";
}
if(m_stream.comment()) {
m_stream << "\n";
}
m_stream << IndentTo(curIndent);
m_stream << "?";
}
switch(child) {
case EmitterNodeType::None:
break;
case EmitterNodeType::Property:
case EmitterNodeType::Scalar:
case EmitterNodeType::FlowSeq:
case EmitterNodeType::FlowMap:
SpaceOrIndentTo(true, curIndent + 1);
break;
case EmitterNodeType::BlockSeq:
case EmitterNodeType::BlockMap:
break;
}
}
void Emitter::BlockMapPrepareLongKeyValue(EmitterNodeType::value child) if (!m_pState->HasBegunContent()) {
{ if (m_pState->CurGroupChildCount() > 0 || m_stream.comment()) {
const unsigned curIndent = m_pState->CurIndent(); m_stream << "\n";
if(child == EmitterNodeType::None)
return;
if(!m_pState->HasBegunContent()) {
m_stream << "\n";
m_stream << IndentTo(curIndent);
m_stream << ":";
}
switch(child) {
case EmitterNodeType::None:
break;
case EmitterNodeType::Property:
case EmitterNodeType::Scalar:
case EmitterNodeType::FlowSeq:
case EmitterNodeType::FlowMap:
case EmitterNodeType::BlockSeq:
case EmitterNodeType::BlockMap:
SpaceOrIndentTo(true, curIndent + 1);
break;
}
} }
m_stream << IndentTo(curIndent);
m_stream << "-";
}
switch (child) {
case EmitterNodeType::None:
break;
case EmitterNodeType::Property:
case EmitterNodeType::Scalar:
case EmitterNodeType::FlowSeq:
case EmitterNodeType::FlowMap:
SpaceOrIndentTo(m_pState->HasBegunContent(), nextIndent);
break;
case EmitterNodeType::BlockSeq:
m_stream << "\n";
break;
case EmitterNodeType::BlockMap:
if (m_pState->HasBegunContent() || m_stream.comment())
m_stream << "\n";
break;
}
}
void Emitter::BlockMapPrepareSimpleKey(EmitterNodeType::value child) void Emitter::FlowMapPrepareNode(EmitterNodeType::value child) {
{ if (m_pState->CurGroupChildCount() % 2 == 0) {
const unsigned curIndent = m_pState->CurIndent(); if (m_pState->GetMapKeyFormat() == LongKey)
const std::size_t childCount = m_pState->CurGroupChildCount(); m_pState->SetLongKey();
if(child == EmitterNodeType::None) if (m_pState->CurGroupLongKey())
return; FlowMapPrepareLongKey(child);
else
if(!m_pState->HasBegunNode()) { FlowMapPrepareSimpleKey(child);
if(childCount > 0) { } else {
m_stream << "\n"; if (m_pState->CurGroupLongKey())
} FlowMapPrepareLongKeyValue(child);
} else
FlowMapPrepareSimpleKeyValue(child);
switch(child) { }
case EmitterNodeType::None: }
break;
case EmitterNodeType::Property: void Emitter::FlowMapPrepareLongKey(EmitterNodeType::value child) {
case EmitterNodeType::Scalar: const unsigned lastIndent = m_pState->LastIndent();
case EmitterNodeType::FlowSeq:
case EmitterNodeType::FlowMap: if (!m_pState->HasBegunNode()) {
SpaceOrIndentTo(m_pState->HasBegunContent(), curIndent); if (m_stream.comment())
break; m_stream << "\n";
case EmitterNodeType::BlockSeq: m_stream << IndentTo(lastIndent);
case EmitterNodeType::BlockMap: if (m_pState->CurGroupChildCount() == 0)
break; m_stream << "{ ?";
} else
} m_stream << ", ?";
}
void Emitter::BlockMapPrepareSimpleKeyValue(EmitterNodeType::value child)
{ switch (child) {
const unsigned curIndent = m_pState->CurIndent(); case EmitterNodeType::None:
const unsigned nextIndent = curIndent + m_pState->CurGroupIndent(); break;
case EmitterNodeType::Property:
if(!m_pState->HasBegunNode()) { case EmitterNodeType::Scalar:
m_stream << ":"; case EmitterNodeType::FlowSeq:
} case EmitterNodeType::FlowMap:
SpaceOrIndentTo(
switch(child) { m_pState->HasBegunContent() || m_pState->CurGroupChildCount() > 0,
case EmitterNodeType::None: lastIndent);
break; break;
case EmitterNodeType::Property: case EmitterNodeType::BlockSeq:
case EmitterNodeType::Scalar: case EmitterNodeType::BlockMap:
case EmitterNodeType::FlowSeq: assert(false);
case EmitterNodeType::FlowMap: break;
SpaceOrIndentTo(true, nextIndent); }
break; }
case EmitterNodeType::BlockSeq:
case EmitterNodeType::BlockMap: void Emitter::FlowMapPrepareLongKeyValue(EmitterNodeType::value child) {
m_stream << "\n"; const unsigned lastIndent = m_pState->LastIndent();
break;
} if (!m_pState->HasBegunNode()) {
if (m_stream.comment())
m_stream << "\n";
m_stream << IndentTo(lastIndent);
m_stream << ":";
}
switch (child) {
case EmitterNodeType::None:
break;
case EmitterNodeType::Property:
case EmitterNodeType::Scalar:
case EmitterNodeType::FlowSeq:
case EmitterNodeType::FlowMap:
SpaceOrIndentTo(
m_pState->HasBegunContent() || m_pState->CurGroupChildCount() > 0,
lastIndent);
break;
case EmitterNodeType::BlockSeq:
case EmitterNodeType::BlockMap:
assert(false);
break;
}
}
void Emitter::FlowMapPrepareSimpleKey(EmitterNodeType::value child) {
const unsigned lastIndent = m_pState->LastIndent();
if (!m_pState->HasBegunNode()) {
if (m_stream.comment())
m_stream << "\n";
m_stream << IndentTo(lastIndent);
if (m_pState->CurGroupChildCount() == 0)
m_stream << "{";
else
m_stream << ",";
}
switch (child) {
case EmitterNodeType::None:
break;
case EmitterNodeType::Property:
case EmitterNodeType::Scalar:
case EmitterNodeType::FlowSeq:
case EmitterNodeType::FlowMap:
SpaceOrIndentTo(
m_pState->HasBegunContent() || m_pState->CurGroupChildCount() > 0,
lastIndent);
break;
case EmitterNodeType::BlockSeq:
case EmitterNodeType::BlockMap:
assert(false);
break;
}
}
void Emitter::FlowMapPrepareSimpleKeyValue(EmitterNodeType::value child) {
const unsigned lastIndent = m_pState->LastIndent();
if (!m_pState->HasBegunNode()) {
if (m_stream.comment())
m_stream << "\n";
m_stream << IndentTo(lastIndent);
m_stream << ":";
}
switch (child) {
case EmitterNodeType::None:
break;
case EmitterNodeType::Property:
case EmitterNodeType::Scalar:
case EmitterNodeType::FlowSeq:
case EmitterNodeType::FlowMap:
SpaceOrIndentTo(
m_pState->HasBegunContent() || m_pState->CurGroupChildCount() > 0,
lastIndent);
break;
case EmitterNodeType::BlockSeq:
case EmitterNodeType::BlockMap:
assert(false);
break;
}
}
void Emitter::BlockMapPrepareNode(EmitterNodeType::value child) {
if (m_pState->CurGroupChildCount() % 2 == 0) {
if (m_pState->GetMapKeyFormat() == LongKey)
m_pState->SetLongKey();
if (child == EmitterNodeType::BlockSeq ||
child == EmitterNodeType::BlockMap)
m_pState->SetLongKey();
if (m_pState->CurGroupLongKey())
BlockMapPrepareLongKey(child);
else
BlockMapPrepareSimpleKey(child);
} else {
if (m_pState->CurGroupLongKey())
BlockMapPrepareLongKeyValue(child);
else
BlockMapPrepareSimpleKeyValue(child);
}
}
void Emitter::BlockMapPrepareLongKey(EmitterNodeType::value child) {
const unsigned curIndent = m_pState->CurIndent();
const std::size_t childCount = m_pState->CurGroupChildCount();
if (child == EmitterNodeType::None)
return;
if (!m_pState->HasBegunContent()) {
if (childCount > 0) {
m_stream << "\n";
} }
if (m_stream.comment()) {
// SpaceOrIndentTo m_stream << "\n";
// . Prepares for some more content by proper spacing
void Emitter::SpaceOrIndentTo(bool requireSpace, unsigned indent)
{
if(m_stream.comment())
m_stream << "\n";
if(m_stream.col() > 0 && requireSpace)
m_stream << " ";
m_stream << IndentTo(indent);
} }
m_stream << IndentTo(curIndent);
m_stream << "?";
}
switch (child) {
case EmitterNodeType::None:
break;
case EmitterNodeType::Property:
case EmitterNodeType::Scalar:
case EmitterNodeType::FlowSeq:
case EmitterNodeType::FlowMap:
SpaceOrIndentTo(true, curIndent + 1);
break;
case EmitterNodeType::BlockSeq:
case EmitterNodeType::BlockMap:
break;
}
}
void Emitter::PrepareIntegralStream(std::stringstream& stream) const void Emitter::BlockMapPrepareLongKeyValue(EmitterNodeType::value child) {
{ const unsigned curIndent = m_pState->CurIndent();
switch(m_pState->GetIntFormat()) { if (child == EmitterNodeType::None)
case Dec: return;
stream << std::dec;
break; if (!m_pState->HasBegunContent()) {
case Hex: m_stream << "\n";
stream << "0x"; m_stream << IndentTo(curIndent);
stream << std::hex; m_stream << ":";
break; }
case Oct:
stream << "0"; switch (child) {
stream << std::oct; case EmitterNodeType::None:
break; break;
default: case EmitterNodeType::Property:
assert(false); case EmitterNodeType::Scalar:
} case EmitterNodeType::FlowSeq:
} case EmitterNodeType::FlowMap:
case EmitterNodeType::BlockSeq:
case EmitterNodeType::BlockMap:
SpaceOrIndentTo(true, curIndent + 1);
break;
}
}
void Emitter::StartedScalar() void Emitter::BlockMapPrepareSimpleKey(EmitterNodeType::value child) {
{ const unsigned curIndent = m_pState->CurIndent();
m_pState->StartedScalar(); const std::size_t childCount = m_pState->CurGroupChildCount();
}
// ******************************************************************************************* if (child == EmitterNodeType::None)
// overloads of Write return;
Emitter& Emitter::Write(const std::string& str) if (!m_pState->HasBegunNode()) {
{ if (childCount > 0) {
if(!good()) m_stream << "\n";
return *this;
const bool escapeNonAscii = m_pState->GetOutputCharset() == EscapeNonAscii;
const StringFormat::value strFormat = Utils::ComputeStringFormat(str, m_pState->GetStringFormat(), m_pState->CurGroupFlowType(), escapeNonAscii);
if(strFormat == StringFormat::Literal)
m_pState->SetMapKeyFormat(YAML::LongKey, FmtScope::Local);
PrepareNode(EmitterNodeType::Scalar);
switch(strFormat) {
case StringFormat::Plain:
m_stream << str;
break;
case StringFormat::SingleQuoted:
Utils::WriteSingleQuotedString(m_stream, str);
break;
case StringFormat::DoubleQuoted:
Utils::WriteDoubleQuotedString(m_stream, str, escapeNonAscii);
break;
case StringFormat::Literal:
Utils::WriteLiteralString(m_stream, str, m_pState->CurIndent() + m_pState->GetIndent());
break;
}
StartedScalar();
return *this;
}
unsigned Emitter::GetFloatPrecision() const
{
return m_pState->GetFloatPrecision();
}
unsigned Emitter::GetDoublePrecision() const
{
return m_pState->GetDoublePrecision();
} }
}
switch (child) {
case EmitterNodeType::None:
break;
case EmitterNodeType::Property:
case EmitterNodeType::Scalar:
case EmitterNodeType::FlowSeq:
case EmitterNodeType::FlowMap:
SpaceOrIndentTo(m_pState->HasBegunContent(), curIndent);
break;
case EmitterNodeType::BlockSeq:
case EmitterNodeType::BlockMap:
break;
}
}
void Emitter::BlockMapPrepareSimpleKeyValue(EmitterNodeType::value child) {
const unsigned curIndent = m_pState->CurIndent();
const unsigned nextIndent = curIndent + m_pState->CurGroupIndent();
if (!m_pState->HasBegunNode()) {
m_stream << ":";
}
switch (child) {
case EmitterNodeType::None:
break;
case EmitterNodeType::Property:
case EmitterNodeType::Scalar:
case EmitterNodeType::FlowSeq:
case EmitterNodeType::FlowMap:
SpaceOrIndentTo(true, nextIndent);
break;
case EmitterNodeType::BlockSeq:
case EmitterNodeType::BlockMap:
m_stream << "\n";
break;
}
}
// SpaceOrIndentTo
// . Prepares for some more content by proper spacing
void Emitter::SpaceOrIndentTo(bool requireSpace, unsigned indent) {
if (m_stream.comment())
m_stream << "\n";
if (m_stream.col() > 0 && requireSpace)
m_stream << " ";
m_stream << IndentTo(indent);
}
void Emitter::PrepareIntegralStream(std::stringstream& stream) const {
switch (m_pState->GetIntFormat()) {
case Dec:
stream << std::dec;
break;
case Hex:
stream << "0x";
stream << std::hex;
break;
case Oct:
stream << "0";
stream << std::oct;
break;
default:
assert(false);
}
}
void Emitter::StartedScalar() { m_pState->StartedScalar(); }
// *******************************************************************************************
// overloads of Write
Emitter& Emitter::Write(const std::string& str) {
if (!good())
return *this;
const bool escapeNonAscii = m_pState->GetOutputCharset() == EscapeNonAscii;
const StringFormat::value strFormat =
Utils::ComputeStringFormat(str, m_pState->GetStringFormat(),
m_pState->CurGroupFlowType(), escapeNonAscii);
if (strFormat == StringFormat::Literal)
m_pState->SetMapKeyFormat(YAML::LongKey, FmtScope::Local);
PrepareNode(EmitterNodeType::Scalar);
switch (strFormat) {
case StringFormat::Plain:
m_stream << str;
break;
case StringFormat::SingleQuoted:
Utils::WriteSingleQuotedString(m_stream, str);
break;
case StringFormat::DoubleQuoted:
Utils::WriteDoubleQuotedString(m_stream, str, escapeNonAscii);
break;
case StringFormat::Literal:
Utils::WriteLiteralString(m_stream, str,
m_pState->CurIndent() + m_pState->GetIndent());
break;
}
StartedScalar();
return *this;
}
unsigned Emitter::GetFloatPrecision() const {
return m_pState->GetFloatPrecision();
}
unsigned Emitter::GetDoublePrecision() const {
return m_pState->GetDoublePrecision();
}
const char* Emitter::ComputeFullBoolName(bool b) const {
const EMITTER_MANIP mainFmt = (m_pState->GetBoolLengthFormat() == ShortBool
? YesNoBool
: m_pState->GetBoolFormat());
const EMITTER_MANIP caseFmt = m_pState->GetBoolCaseFormat();
switch (mainFmt) {
case YesNoBool:
switch (caseFmt) {
case UpperCase:
return b ? "YES" : "NO";
case CamelCase:
return b ? "Yes" : "No";
case LowerCase:
return b ? "yes" : "no";
default:
break;
}
break;
case OnOffBool:
switch (caseFmt) {
case UpperCase:
return b ? "ON" : "OFF";
case CamelCase:
return b ? "On" : "Off";
case LowerCase:
return b ? "on" : "off";
default:
break;
}
break;
case TrueFalseBool:
switch (caseFmt) {
case UpperCase:
return b ? "TRUE" : "FALSE";
case CamelCase:
return b ? "True" : "False";
case LowerCase:
return b ? "true" : "false";
default:
break;
}
break;
default:
break;
}
return b ? "y" : "n"; // should never get here, but it can't hurt to give
// these answers
}
Emitter& Emitter::Write(bool b) {
if (!good())
return *this;
PrepareNode(EmitterNodeType::Scalar);
const char* name = ComputeFullBoolName(b);
if (m_pState->GetBoolLengthFormat() == ShortBool)
m_stream << name[0];
else
m_stream << name;
StartedScalar();
const char *Emitter::ComputeFullBoolName(bool b) const return *this;
{
const EMITTER_MANIP mainFmt = (m_pState->GetBoolLengthFormat() == ShortBool ? YesNoBool : m_pState->GetBoolFormat());
const EMITTER_MANIP caseFmt = m_pState->GetBoolCaseFormat();
switch(mainFmt) {
case YesNoBool:
switch(caseFmt) {
case UpperCase: return b ? "YES" : "NO";
case CamelCase: return b ? "Yes" : "No";
case LowerCase: return b ? "yes" : "no";
default: break;
}
break;
case OnOffBool:
switch(caseFmt) {
case UpperCase: return b ? "ON" : "OFF";
case CamelCase: return b ? "On" : "Off";
case LowerCase: return b ? "on" : "off";
default: break;
}
break;
case TrueFalseBool:
switch(caseFmt) {
case UpperCase: return b ? "TRUE" : "FALSE";
case CamelCase: return b ? "True" : "False";
case LowerCase: return b ? "true" : "false";
default: break;
}
break;
default:
break;
}
return b ? "y" : "n"; // should never get here, but it can't hurt to give these answers
}
Emitter& Emitter::Write(bool b)
{
if(!good())
return *this;
PrepareNode(EmitterNodeType::Scalar);
const char *name = ComputeFullBoolName(b);
if(m_pState->GetBoolLengthFormat() == ShortBool)
m_stream << name[0];
else
m_stream << name;
StartedScalar();
return *this;
}
Emitter& Emitter::Write(char ch)
{
if(!good())
return *this;
PrepareNode(EmitterNodeType::Scalar);
Utils::WriteChar(m_stream, ch);
StartedScalar();
return *this;
}
Emitter& Emitter::Write(const _Alias& alias)
{
if(!good())
return *this;
if(m_pState->HasAnchor() || m_pState->HasTag()) {
m_pState->SetError(ErrorMsg::INVALID_ALIAS);
return *this;
}
PrepareNode(EmitterNodeType::Scalar);
if(!Utils::WriteAlias(m_stream, alias.content)) {
m_pState->SetError(ErrorMsg::INVALID_ALIAS);
return *this;
}
StartedScalar();
return *this;
}
Emitter& Emitter::Write(const _Anchor& anchor)
{
if(!good())
return *this;
if(m_pState->HasAnchor()) {
m_pState->SetError(ErrorMsg::INVALID_ANCHOR);
return *this;
}
PrepareNode(EmitterNodeType::Property);
if(!Utils::WriteAnchor(m_stream, anchor.content)) {
m_pState->SetError(ErrorMsg::INVALID_ANCHOR);
return *this;
}
m_pState->SetAnchor();
return *this;
}
Emitter& Emitter::Write(const _Tag& tag)
{
if(!good())
return *this;
if(m_pState->HasTag()) {
m_pState->SetError(ErrorMsg::INVALID_TAG);
return *this;
}
PrepareNode(EmitterNodeType::Property);
bool success = false;
if(tag.type == _Tag::Type::Verbatim)
success = Utils::WriteTag(m_stream, tag.content, true);
else if(tag.type == _Tag::Type::PrimaryHandle)
success = Utils::WriteTag(m_stream, tag.content, false);
else
success = Utils::WriteTagWithPrefix(m_stream, tag.prefix, tag.content);
if(!success) {
m_pState->SetError(ErrorMsg::INVALID_TAG);
return *this;
}
m_pState->SetTag();
return *this;
}
void Emitter::EmitKindTag()
{
Write(LocalTag(""));
}
Emitter& Emitter::Write(const _Comment& comment)
{
if(!good())
return *this;
PrepareNode(EmitterNodeType::None);
if(m_stream.col() > 0)
m_stream << Indentation(m_pState->GetPreCommentIndent());
Utils::WriteComment(m_stream, comment.content, m_pState->GetPostCommentIndent());
m_pState->SetNonContent();
return *this;
}
Emitter& Emitter::Write(const _Null& /*null*/)
{
if(!good())
return *this;
PrepareNode(EmitterNodeType::Scalar);
m_stream << "~";
StartedScalar();
return *this;
}
Emitter& Emitter::Write(const Binary& binary)
{
Write(SecondaryTag("binary"));
if(!good())
return *this;
PrepareNode(EmitterNodeType::Scalar);
Utils::WriteBinary(m_stream, binary);
StartedScalar();
return *this;
}
} }
Emitter& Emitter::Write(char ch) {
if (!good())
return *this;
PrepareNode(EmitterNodeType::Scalar);
Utils::WriteChar(m_stream, ch);
StartedScalar();
return *this;
}
Emitter& Emitter::Write(const _Alias& alias) {
if (!good())
return *this;
if (m_pState->HasAnchor() || m_pState->HasTag()) {
m_pState->SetError(ErrorMsg::INVALID_ALIAS);
return *this;
}
PrepareNode(EmitterNodeType::Scalar);
if (!Utils::WriteAlias(m_stream, alias.content)) {
m_pState->SetError(ErrorMsg::INVALID_ALIAS);
return *this;
}
StartedScalar();
return *this;
}
Emitter& Emitter::Write(const _Anchor& anchor) {
if (!good())
return *this;
if (m_pState->HasAnchor()) {
m_pState->SetError(ErrorMsg::INVALID_ANCHOR);
return *this;
}
PrepareNode(EmitterNodeType::Property);
if (!Utils::WriteAnchor(m_stream, anchor.content)) {
m_pState->SetError(ErrorMsg::INVALID_ANCHOR);
return *this;
}
m_pState->SetAnchor();
return *this;
}
Emitter& Emitter::Write(const _Tag& tag) {
if (!good())
return *this;
if (m_pState->HasTag()) {
m_pState->SetError(ErrorMsg::INVALID_TAG);
return *this;
}
PrepareNode(EmitterNodeType::Property);
bool success = false;
if (tag.type == _Tag::Type::Verbatim)
success = Utils::WriteTag(m_stream, tag.content, true);
else if (tag.type == _Tag::Type::PrimaryHandle)
success = Utils::WriteTag(m_stream, tag.content, false);
else
success = Utils::WriteTagWithPrefix(m_stream, tag.prefix, tag.content);
if (!success) {
m_pState->SetError(ErrorMsg::INVALID_TAG);
return *this;
}
m_pState->SetTag();
return *this;
}
void Emitter::EmitKindTag() { Write(LocalTag("")); }
Emitter& Emitter::Write(const _Comment& comment) {
if (!good())
return *this;
PrepareNode(EmitterNodeType::None);
if (m_stream.col() > 0)
m_stream << Indentation(m_pState->GetPreCommentIndent());
Utils::WriteComment(m_stream, comment.content,
m_pState->GetPostCommentIndent());
m_pState->SetNonContent();
return *this;
}
Emitter& Emitter::Write(const _Null& /*null*/) {
if (!good())
return *this;
PrepareNode(EmitterNodeType::Scalar);
m_stream << "~";
StartedScalar();
return *this;
}
Emitter& Emitter::Write(const Binary& binary) {
Write(SecondaryTag("binary"));
if (!good())
return *this;
PrepareNode(EmitterNodeType::Scalar);
Utils::WriteBinary(m_stream, binary);
StartedScalar();
return *this;
}
}
...@@ -2,383 +2,346 @@ ...@@ -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;
}
}
#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 @@ ...@@ -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
};
class EmitterState };
{ struct GroupType {
public: enum value {
EmitterState(); None,
~EmitterState(); Seq,
Map
// basic state checking };
bool good() const { return m_isGood; } };
const std::string GetLastError() const { return m_lastError; } struct FlowType {
void SetError(const std::string& error) { m_isGood = false; m_lastError = error; } enum value {
None,
// node handling Flow,
void SetAnchor(); Block
void SetTag(); };
void SetNonContent(); };
void SetLongKey();
void ForceFlow(); class EmitterState {
void StartedDoc(); public:
void EndedDoc(); EmitterState();
void StartedScalar(); ~EmitterState();
void StartedGroup(GroupType::value type);
void EndedGroup(GroupType::value type); // basic state checking
bool good() const { return m_isGood; }
EmitterNodeType::value NextGroupType(GroupType::value type) const; const std::string GetLastError() const { return m_lastError; }
EmitterNodeType::value CurGroupNodeType() const; void SetError(const std::string& error) {
m_isGood = false;
GroupType::value CurGroupType() const; m_lastError = error;
FlowType::value CurGroupFlowType() const; }
int CurGroupIndent() const;
std::size_t CurGroupChildCount() const; // node handling
bool CurGroupLongKey() const; void SetAnchor();
void SetTag();
int LastIndent() const; void SetNonContent();
int CurIndent() const { return m_curIndent; } void SetLongKey();
bool HasAnchor() const { return m_hasAnchor; } void ForceFlow();
bool HasTag() const { return m_hasTag; } void StartedDoc();
bool HasBegunNode() const { return m_hasAnchor || m_hasTag || m_hasNonContent; } void EndedDoc();
bool HasBegunContent() const { return m_hasAnchor || m_hasTag; } void StartedScalar();
void StartedGroup(GroupType::value type);
void ClearModifiedSettings(); void EndedGroup(GroupType::value type);
// formatters EmitterNodeType::value NextGroupType(GroupType::value type) const;
void SetLocalValue(EMITTER_MANIP value); EmitterNodeType::value CurGroupNodeType() const;
bool SetOutputCharset(EMITTER_MANIP value, FmtScope::value scope); GroupType::value CurGroupType() const;
EMITTER_MANIP GetOutputCharset() const { return m_charset.get(); } FlowType::value CurGroupFlowType() const;
int CurGroupIndent() const;
bool SetStringFormat(EMITTER_MANIP value, FmtScope::value scope); std::size_t CurGroupChildCount() const;
EMITTER_MANIP GetStringFormat() const { return m_strFmt.get(); } bool CurGroupLongKey() const;
bool SetBoolFormat(EMITTER_MANIP value, FmtScope::value scope); int LastIndent() const;
EMITTER_MANIP GetBoolFormat() const { return m_boolFmt.get(); } int CurIndent() const { return m_curIndent; }
bool HasAnchor() const { return m_hasAnchor; }
bool SetBoolLengthFormat(EMITTER_MANIP value, FmtScope::value scope); bool HasTag() const { return m_hasTag; }
EMITTER_MANIP GetBoolLengthFormat() const { return m_boolLengthFmt.get(); } bool HasBegunNode() const {
return m_hasAnchor || m_hasTag || m_hasNonContent;
bool SetBoolCaseFormat(EMITTER_MANIP value, FmtScope::value scope); }
EMITTER_MANIP GetBoolCaseFormat() const { return m_boolCaseFmt.get(); } bool HasBegunContent() const { return m_hasAnchor || m_hasTag; }
bool SetIntFormat(EMITTER_MANIP value, FmtScope::value scope); void ClearModifiedSettings();
EMITTER_MANIP GetIntFormat() const { return m_intFmt.get(); }
// formatters
bool SetIndent(unsigned value, FmtScope::value scope); void SetLocalValue(EMITTER_MANIP value);
int GetIndent() const { return m_indent.get(); }
bool SetOutputCharset(EMITTER_MANIP value, FmtScope::value scope);
bool SetPreCommentIndent(unsigned value, FmtScope::value scope); EMITTER_MANIP GetOutputCharset() const { return m_charset.get(); }
int GetPreCommentIndent() const { return m_preCommentIndent.get(); }
bool SetPostCommentIndent(unsigned value, FmtScope::value scope); bool SetStringFormat(EMITTER_MANIP value, FmtScope::value scope);
int GetPostCommentIndent() const { return m_postCommentIndent.get(); } EMITTER_MANIP GetStringFormat() const { return m_strFmt.get(); }
bool SetFlowType(GroupType::value groupType, EMITTER_MANIP value, FmtScope::value scope); bool SetBoolFormat(EMITTER_MANIP value, FmtScope::value scope);
EMITTER_MANIP GetFlowType(GroupType::value groupType) const; EMITTER_MANIP GetBoolFormat() const { return m_boolFmt.get(); }
bool SetMapKeyFormat(EMITTER_MANIP value, FmtScope::value scope); bool SetBoolLengthFormat(EMITTER_MANIP value, FmtScope::value scope);
EMITTER_MANIP GetMapKeyFormat() const { return m_mapKeyFmt.get(); } EMITTER_MANIP GetBoolLengthFormat() const { return m_boolLengthFmt.get(); }
bool SetFloatPrecision(int value, FmtScope::value scope); bool SetBoolCaseFormat(EMITTER_MANIP value, FmtScope::value scope);
unsigned GetFloatPrecision() const { return m_floatPrecision.get(); } EMITTER_MANIP GetBoolCaseFormat() const { return m_boolCaseFmt.get(); }
bool SetDoublePrecision(int value, FmtScope::value scope);
unsigned GetDoublePrecision() const { return m_doublePrecision.get(); } bool SetIntFormat(EMITTER_MANIP value, FmtScope::value scope);
EMITTER_MANIP GetIntFormat() const { return m_intFmt.get(); }
private:
template <typename T> bool SetIndent(unsigned value, FmtScope::value scope);
void _Set(Setting<T>& fmt, T value, FmtScope::value scope); int GetIndent() const { return m_indent.get(); }
void StartedNode(); bool SetPreCommentIndent(unsigned value, FmtScope::value scope);
int GetPreCommentIndent() const { return m_preCommentIndent.get(); }
private: bool SetPostCommentIndent(unsigned value, FmtScope::value scope);
// basic state ok? int GetPostCommentIndent() const { return m_postCommentIndent.get(); }
bool m_isGood;
std::string m_lastError; bool SetFlowType(GroupType::value groupType, EMITTER_MANIP value,
FmtScope::value scope);
// other state EMITTER_MANIP GetFlowType(GroupType::value groupType) const;
Setting<EMITTER_MANIP> m_charset;
Setting<EMITTER_MANIP> m_strFmt; bool SetMapKeyFormat(EMITTER_MANIP value, FmtScope::value scope);
Setting<EMITTER_MANIP> m_boolFmt; EMITTER_MANIP GetMapKeyFormat() const { return m_mapKeyFmt.get(); }
Setting<EMITTER_MANIP> m_boolLengthFmt;
Setting<EMITTER_MANIP> m_boolCaseFmt; bool SetFloatPrecision(int value, FmtScope::value scope);
Setting<EMITTER_MANIP> m_intFmt; unsigned GetFloatPrecision() const { return m_floatPrecision.get(); }
Setting<unsigned> m_indent; bool SetDoublePrecision(int value, FmtScope::value scope);
Setting<unsigned> m_preCommentIndent, m_postCommentIndent; unsigned GetDoublePrecision() const { return m_doublePrecision.get(); }
Setting<EMITTER_MANIP> m_seqFmt;
Setting<EMITTER_MANIP> m_mapFmt; private:
Setting<EMITTER_MANIP> m_mapKeyFmt; template <typename T>
Setting<int> m_floatPrecision; void _Set(Setting<T>& fmt, T value, FmtScope::value scope);
Setting<int> m_doublePrecision;
void StartedNode();
SettingChanges m_modifiedSettings;
SettingChanges m_globalModifiedSettings; private:
// basic state ok?
struct Group { bool m_isGood;
explicit Group(GroupType::value type_): type(type_), indent(0), childCount(0), longKey(false) {} std::string m_lastError;
GroupType::value type; // other state
FlowType::value flowType; Setting<EMITTER_MANIP> m_charset;
int indent; Setting<EMITTER_MANIP> m_strFmt;
std::size_t childCount; Setting<EMITTER_MANIP> m_boolFmt;
bool longKey; Setting<EMITTER_MANIP> m_boolLengthFmt;
Setting<EMITTER_MANIP> m_boolCaseFmt;
SettingChanges modifiedSettings; Setting<EMITTER_MANIP> m_intFmt;
Setting<unsigned> m_indent;
EmitterNodeType::value NodeType() const { Setting<unsigned> m_preCommentIndent, m_postCommentIndent;
if(type == GroupType::Seq) { Setting<EMITTER_MANIP> m_seqFmt;
if(flowType == FlowType::Flow) Setting<EMITTER_MANIP> m_mapFmt;
return EmitterNodeType::FlowSeq; Setting<EMITTER_MANIP> m_mapKeyFmt;
else Setting<int> m_floatPrecision;
return EmitterNodeType::BlockSeq; Setting<int> m_doublePrecision;
} else {
if(flowType == FlowType::Flow) SettingChanges m_modifiedSettings;
return EmitterNodeType::FlowMap; SettingChanges m_globalModifiedSettings;
else
return EmitterNodeType::BlockMap; struct Group {
} explicit Group(GroupType::value type_)
: type(type_), indent(0), childCount(0), longKey(false) {}
// can't get here
assert(false); GroupType::value type;
return EmitterNodeType::None; FlowType::value flowType;
} int indent;
}; std::size_t childCount;
bool longKey;
ptr_stack<Group> m_groups;
unsigned m_curIndent; SettingChanges modifiedSettings;
bool m_hasAnchor;
bool m_hasTag; EmitterNodeType::value NodeType() const {
bool m_hasNonContent; if (type == GroupType::Seq) {
std::size_t m_docCount; if (flowType == FlowType::Flow)
}; return EmitterNodeType::FlowSeq;
else
template <typename T> return EmitterNodeType::BlockSeq;
void EmitterState::_Set(Setting<T>& fmt, T value, FmtScope::value scope) { } else {
switch(scope) { if (flowType == FlowType::Flow)
case FmtScope::Local: return EmitterNodeType::FlowMap;
m_modifiedSettings.push(fmt.set(value)); else
break; return EmitterNodeType::BlockMap;
case FmtScope::Global: }
fmt.set(value);
m_globalModifiedSettings.push(fmt.set(value)); // this pushes an identity set, so when we restore, // can't get here
// it restores to the value here, and not the previous one assert(false);
break; return EmitterNodeType::None;
default: }
assert(false); };
}
} ptr_stack<Group> m_groups;
unsigned m_curIndent;
bool m_hasAnchor;
bool m_hasTag;
bool m_hasNonContent;
std::size_t m_docCount;
};
template <typename T>
void EmitterState::_Set(Setting<T>& fmt, T value, FmtScope::value scope) {
switch (scope) {
case FmtScope::Local:
m_modifiedSettings.push(fmt.set(value));
break;
case FmtScope::Global:
fmt.set(value);
m_globalModifiedSettings.push(
fmt.set(value)); // this pushes an identity set, so when we restore,
// it restores to the value here, and not the previous one
break;
default:
assert(false);
}
}
} }
#endif // EMITTERSTATE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #endif // EMITTERSTATE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
...@@ -7,418 +7,436 @@ ...@@ -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:
if (ch < 0x20) case 0xD: // b-char
return false; return false;
case 0x85:
if (ch < 0x7E) return true;
return true; }
if (ch < 0xA0) if (ch < 0x20)
return false; return false;
if (ch >= 0xD800 && ch <= 0xDFFF)
return false; if (ch < 0x7E)
if ((ch & 0xFFFE) == 0xFFFE) return true;
return false;
if ((ch >= 0xFDD0) && (ch <= 0xFDEF)) if (ch < 0xA0)
return false; return false;
if (ch > 0x10FFFF) if (ch >= 0xD800 && ch <= 0xDFFF)
return false; return false;
if ((ch & 0xFFFE) == 0xFFFE)
return true; return false;
} if ((ch >= 0xFDD0) && (ch <= 0xFDEF))
return false;
int Utf8BytesIndicated(char ch) { if (ch > 0x10FFFF)
int byteVal = static_cast<unsigned char>(ch); return false;
switch (byteVal >> 4) {
case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: return true;
return 1; }
case 12: case 13:
return 2; int Utf8BytesIndicated(char ch) {
case 14: int byteVal = static_cast<unsigned char>(ch);
return 3; switch (byteVal >> 4) {
case 15: case 0:
return 4; case 1:
default: case 2:
return -1; case 3:
} case 4:
} case 5:
case 6:
bool IsTrailingByte(char ch) { case 7:
return (ch & 0xC0) == 0x80; return 1;
} case 12:
case 13:
bool GetNextCodePointAndAdvance(int& codePoint, std::string::const_iterator& first, std::string::const_iterator last) { return 2;
if (first == last) case 14:
return false; return 3;
case 15:
int nBytes = Utf8BytesIndicated(*first); return 4;
if (nBytes < 1) { default:
// Bad lead byte return -1;
++first; }
codePoint = REPLACEMENT_CHARACTER; }
return true;
} bool IsTrailingByte(char ch) { return (ch & 0xC0) == 0x80; }
if (nBytes == 1) { bool GetNextCodePointAndAdvance(int& codePoint,
codePoint = *first++; std::string::const_iterator& first,
return true; std::string::const_iterator last) {
} if (first == last)
return false;
// Gather bits from trailing bytes
codePoint = static_cast<unsigned char>(*first) & ~(0xFF << (7 - nBytes)); int nBytes = Utf8BytesIndicated(*first);
++first; if (nBytes < 1) {
--nBytes; // Bad lead byte
for (; nBytes > 0; ++first, --nBytes) { ++first;
if ((first == last) || !IsTrailingByte(*first)) { codePoint = REPLACEMENT_CHARACTER;
codePoint = REPLACEMENT_CHARACTER; return true;
break; }
}
codePoint <<= 6; if (nBytes == 1) {
codePoint |= *first & 0x3F; codePoint = *first++;
} return true;
}
// Check for illegal code points
if (codePoint > 0x10FFFF) // Gather bits from trailing bytes
codePoint = REPLACEMENT_CHARACTER; codePoint = static_cast<unsigned char>(*first) & ~(0xFF << (7 - nBytes));
else if (codePoint >= 0xD800 && codePoint <= 0xDFFF) ++first;
codePoint = REPLACEMENT_CHARACTER; --nBytes;
else if ((codePoint & 0xFFFE) == 0xFFFE) for (; nBytes > 0; ++first, --nBytes) {
codePoint = REPLACEMENT_CHARACTER; if ((first == last) || !IsTrailingByte(*first)) {
else if (codePoint >= 0xFDD0 && codePoint <= 0xFDEF) codePoint = REPLACEMENT_CHARACTER;
codePoint = REPLACEMENT_CHARACTER; break;
return true; }
} codePoint <<= 6;
codePoint |= *first & 0x3F;
void WriteCodePoint(ostream_wrapper& out, int codePoint) { }
if (codePoint < 0 || codePoint > 0x10FFFF) {
codePoint = REPLACEMENT_CHARACTER; // Check for illegal code points
} if (codePoint > 0x10FFFF)
if (codePoint < 0x7F) { codePoint = REPLACEMENT_CHARACTER;
out << static_cast<char>(codePoint); else if (codePoint >= 0xD800 && codePoint <= 0xDFFF)
} else if (codePoint < 0x7FF) { codePoint = REPLACEMENT_CHARACTER;
out << static_cast<char>(0xC0 | (codePoint >> 6)) else if ((codePoint & 0xFFFE) == 0xFFFE)
<< static_cast<char>(0x80 | (codePoint & 0x3F)); codePoint = REPLACEMENT_CHARACTER;
} else if (codePoint < 0xFFFF) { else if (codePoint >= 0xFDD0 && codePoint <= 0xFDEF)
out << static_cast<char>(0xE0 | (codePoint >> 12)) codePoint = REPLACEMENT_CHARACTER;
<< static_cast<char>(0x80 | ((codePoint >> 6) & 0x3F)) return true;
<< static_cast<char>(0x80 | (codePoint & 0x3F)); }
} else {
out << static_cast<char>(0xF0 | (codePoint >> 18)) void WriteCodePoint(ostream_wrapper& out, int codePoint) {
<< static_cast<char>(0x80 | ((codePoint >> 12) & 0x3F)) if (codePoint < 0 || codePoint > 0x10FFFF) {
<< static_cast<char>(0x80 | ((codePoint >> 6) & 0x3F)) codePoint = REPLACEMENT_CHARACTER;
<< static_cast<char>(0x80 | (codePoint & 0x3F)); }
} if (codePoint < 0x7F) {
} out << static_cast<char>(codePoint);
} else if (codePoint < 0x7FF) {
bool IsValidPlainScalar(const std::string& str, FlowType::value flowType, bool allowOnlyAscii) { out << static_cast<char>(0xC0 | (codePoint >> 6))
if(str.empty()) << static_cast<char>(0x80 | (codePoint & 0x3F));
return false; } else if (codePoint < 0xFFFF) {
out << static_cast<char>(0xE0 | (codePoint >> 12))
// first check the start << static_cast<char>(0x80 | ((codePoint >> 6) & 0x3F))
const RegEx& start = (flowType == FlowType::Flow ? Exp::PlainScalarInFlow() : Exp::PlainScalar()); << static_cast<char>(0x80 | (codePoint & 0x3F));
if(!start.Matches(str)) } else {
return false; out << static_cast<char>(0xF0 | (codePoint >> 18))
<< static_cast<char>(0x80 | ((codePoint >> 12) & 0x3F))
// and check the end for plain whitespace (which can't be faithfully kept in a plain scalar) << static_cast<char>(0x80 | ((codePoint >> 6) & 0x3F))
if(!str.empty() && *str.rbegin() == ' ') << static_cast<char>(0x80 | (codePoint & 0x3F));
return false; }
}
// then check until something is disallowed
const RegEx& disallowed = (flowType == FlowType::Flow ? Exp::EndScalarInFlow() : Exp::EndScalar()) bool IsValidPlainScalar(const std::string& str, FlowType::value flowType,
|| (Exp::BlankOrBreak() + Exp::Comment()) bool allowOnlyAscii) {
|| Exp::NotPrintable() if (str.empty())
|| Exp::Utf8_ByteOrderMark() return false;
|| Exp::Break()
|| Exp::Tab(); // first check the start
StringCharSource buffer(str.c_str(), str.size()); const RegEx& start = (flowType == FlowType::Flow ? Exp::PlainScalarInFlow()
while(buffer) { : Exp::PlainScalar());
if(disallowed.Matches(buffer)) if (!start.Matches(str))
return false; return false;
if(allowOnlyAscii && (0x80 <= static_cast<unsigned char>(buffer[0])))
return false; // and check the end for plain whitespace (which can't be faithfully kept in a
++buffer; // plain scalar)
} if (!str.empty() && *str.rbegin() == ' ')
return false;
return true;
} // then check until something is disallowed
const RegEx& disallowed = (flowType == FlowType::Flow ? Exp::EndScalarInFlow()
bool IsValidSingleQuotedScalar(const std::string& str, bool escapeNonAscii) : Exp::EndScalar()) ||
{ (Exp::BlankOrBreak() + Exp::Comment()) ||
// TODO: check for non-printable characters? Exp::NotPrintable() || Exp::Utf8_ByteOrderMark() ||
for(std::size_t i=0;i<str.size();i++) { Exp::Break() || Exp::Tab();
if(escapeNonAscii && (0x80 <= static_cast<unsigned char>(str[i]))) StringCharSource buffer(str.c_str(), str.size());
return false; while (buffer) {
if(str[i] == '\n') if (disallowed.Matches(buffer))
return false; return false;
} if (allowOnlyAscii && (0x80 <= static_cast<unsigned char>(buffer[0])))
return true; return false;
} ++buffer;
}
bool IsValidLiteralScalar(const std::string& str, FlowType::value flowType, bool escapeNonAscii)
{ return true;
if(flowType == FlowType::Flow) }
return false;
bool IsValidSingleQuotedScalar(const std::string& str, bool escapeNonAscii) {
// TODO: check for non-printable characters? // TODO: check for non-printable characters?
for(std::size_t i=0;i<str.size();i++) { for (std::size_t i = 0; i < str.size(); i++) {
if(escapeNonAscii && (0x80 <= static_cast<unsigned char>(str[i]))) if (escapeNonAscii && (0x80 <= static_cast<unsigned char>(str[i])))
return false; return false;
} if (str[i] == '\n')
return true; return false;
} }
return true;
void WriteDoubleQuoteEscapeSequence(ostream_wrapper& out, int codePoint) { }
static const char hexDigits[] = "0123456789abcdef";
bool IsValidLiteralScalar(const std::string& str, FlowType::value flowType,
out << "\\"; bool escapeNonAscii) {
int digits = 8; if (flowType == FlowType::Flow)
if(codePoint < 0xFF) { return false;
out << "x";
digits = 2; // TODO: check for non-printable characters?
} else if(codePoint < 0xFFFF) { for (std::size_t i = 0; i < str.size(); i++) {
out << "u"; if (escapeNonAscii && (0x80 <= static_cast<unsigned char>(str[i])))
digits = 4; return false;
} else { }
out << "U"; return true;
digits = 8; }
}
void WriteDoubleQuoteEscapeSequence(ostream_wrapper& out, int codePoint) {
// Write digits into the escape sequence static const char hexDigits[] = "0123456789abcdef";
for (; digits > 0; --digits)
out << hexDigits[(codePoint >> (4 * (digits - 1))) & 0xF]; out << "\\";
} int digits = 8;
if (codePoint < 0xFF) {
bool WriteAliasName(ostream_wrapper& out, const std::string& str) { out << "x";
int codePoint; digits = 2;
for(std::string::const_iterator i = str.begin(); } else if (codePoint < 0xFFFF) {
GetNextCodePointAndAdvance(codePoint, i, str.end()); out << "u";
) digits = 4;
{ } else {
if (!IsAnchorChar(codePoint)) out << "U";
return false; digits = 8;
}
WriteCodePoint(out, codePoint);
} // Write digits into the escape sequence
return true; for (; digits > 0; --digits)
} out << hexDigits[(codePoint >> (4 * (digits - 1))) & 0xF];
} }
StringFormat::value ComputeStringFormat(const std::string& str, EMITTER_MANIP strFormat, FlowType::value flowType, bool escapeNonAscii) bool WriteAliasName(ostream_wrapper& out, const std::string& str) {
{ int codePoint;
switch(strFormat) { for (std::string::const_iterator i = str.begin();
case Auto: GetNextCodePointAndAdvance(codePoint, i, str.end());) {
if(IsValidPlainScalar(str, flowType, escapeNonAscii)) if (!IsAnchorChar(codePoint))
return StringFormat::Plain; return false;
return StringFormat::DoubleQuoted;
case SingleQuoted: WriteCodePoint(out, codePoint);
if(IsValidSingleQuotedScalar(str, escapeNonAscii)) }
return StringFormat::SingleQuoted; return true;
return StringFormat::DoubleQuoted; }
case DoubleQuoted: }
return StringFormat::DoubleQuoted;
case Literal: StringFormat::value ComputeStringFormat(const std::string& str,
if(IsValidLiteralScalar(str, flowType, escapeNonAscii)) EMITTER_MANIP strFormat,
return StringFormat::Literal; FlowType::value flowType,
return StringFormat::DoubleQuoted; bool escapeNonAscii) {
default: switch (strFormat) {
break; case Auto:
} if (IsValidPlainScalar(str, flowType, escapeNonAscii))
return StringFormat::Plain;
return StringFormat::DoubleQuoted; return StringFormat::DoubleQuoted;
} case SingleQuoted:
if (IsValidSingleQuotedScalar(str, escapeNonAscii))
bool WriteSingleQuotedString(ostream_wrapper& out, const std::string& str) return StringFormat::SingleQuoted;
{ return StringFormat::DoubleQuoted;
out << "'"; case DoubleQuoted:
int codePoint; return StringFormat::DoubleQuoted;
for(std::string::const_iterator i = str.begin(); case Literal:
GetNextCodePointAndAdvance(codePoint, i, str.end()); if (IsValidLiteralScalar(str, flowType, escapeNonAscii))
) return StringFormat::Literal;
{ return StringFormat::DoubleQuoted;
if (codePoint == '\n') default:
return false; // We can't handle a new line and the attendant indentation yet break;
}
if (codePoint == '\'')
out << "''"; return StringFormat::DoubleQuoted;
else }
WriteCodePoint(out, codePoint);
} bool WriteSingleQuotedString(ostream_wrapper& out, const std::string& str) {
out << "'"; out << "'";
return true; int codePoint;
} for (std::string::const_iterator i = str.begin();
GetNextCodePointAndAdvance(codePoint, i, str.end());) {
bool WriteDoubleQuotedString(ostream_wrapper& out, const std::string& str, bool escapeNonAscii) if (codePoint == '\n')
{ return false; // We can't handle a new line and the attendant indentation
out << "\""; // yet
int codePoint;
for(std::string::const_iterator i = str.begin(); if (codePoint == '\'')
GetNextCodePointAndAdvance(codePoint, i, str.end()); out << "''";
) else
{ WriteCodePoint(out, codePoint);
switch(codePoint) { }
case '\"': out << "\\\""; break; out << "'";
case '\\': out << "\\\\"; break; return true;
case '\n': out << "\\n"; break; }
case '\t': out << "\\t"; break;
case '\r': out << "\\r"; break; bool WriteDoubleQuotedString(ostream_wrapper& out, const std::string& str,
case '\b': out << "\\b"; break; bool escapeNonAscii) {
default: out << "\"";
if(codePoint < 0x20 || (codePoint >= 0x80 && codePoint <= 0xA0)) // Control characters and non-breaking space int codePoint;
WriteDoubleQuoteEscapeSequence(out, codePoint); for (std::string::const_iterator i = str.begin();
else if (codePoint == 0xFEFF) // Byte order marks (ZWNS) should be escaped (YAML 1.2, sec. 5.2) GetNextCodePointAndAdvance(codePoint, i, str.end());) {
WriteDoubleQuoteEscapeSequence(out, codePoint); switch (codePoint) {
else if (escapeNonAscii && codePoint > 0x7E) case '\"':
WriteDoubleQuoteEscapeSequence(out, codePoint); out << "\\\"";
else break;
WriteCodePoint(out, codePoint); case '\\':
} out << "\\\\";
} break;
out << "\""; case '\n':
return true; out << "\\n";
} break;
case '\t':
bool WriteLiteralString(ostream_wrapper& out, const std::string& str, int indent) out << "\\t";
{ break;
out << "|\n"; case '\r':
out << IndentTo(indent); out << "\\r";
int codePoint; break;
for(std::string::const_iterator i = str.begin(); case '\b':
GetNextCodePointAndAdvance(codePoint, i, str.end()); out << "\\b";
) break;
{ default:
if (codePoint == '\n') if (codePoint < 0x20 ||
out << "\n" << IndentTo(indent); (codePoint >= 0x80 &&
else codePoint <= 0xA0)) // Control characters and non-breaking space
WriteCodePoint(out, codePoint); WriteDoubleQuoteEscapeSequence(out, codePoint);
} else if (codePoint == 0xFEFF) // Byte order marks (ZWNS) should be
return true; // escaped (YAML 1.2, sec. 5.2)
} WriteDoubleQuoteEscapeSequence(out, codePoint);
else if (escapeNonAscii && codePoint > 0x7E)
bool WriteChar(ostream_wrapper& out, char ch) WriteDoubleQuoteEscapeSequence(out, codePoint);
{ else
if(('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z')) WriteCodePoint(out, codePoint);
out << ch; }
else if((0x20 <= ch && ch <= 0x7e) || ch == ' ') }
out << "\"" << ch << "\""; out << "\"";
else if(ch == '\t') return true;
out << "\"\\t\""; }
else if(ch == '\n')
out << "\"\\n\""; bool WriteLiteralString(ostream_wrapper& out, const std::string& str,
else if(ch == '\b') int indent) {
out << "\"\\b\""; out << "|\n";
else { out << IndentTo(indent);
out << "\""; int codePoint;
WriteDoubleQuoteEscapeSequence(out, ch); for (std::string::const_iterator i = str.begin();
out << "\""; GetNextCodePointAndAdvance(codePoint, i, str.end());) {
} if (codePoint == '\n')
return true; out << "\n" << IndentTo(indent);
} else
WriteCodePoint(out, codePoint);
bool WriteComment(ostream_wrapper& out, const std::string& str, int postCommentIndent) }
{ return true;
const unsigned curIndent = out.col(); }
out << "#" << Indentation(postCommentIndent);
out.set_comment(); bool WriteChar(ostream_wrapper& out, char ch) {
int codePoint; if (('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z'))
for(std::string::const_iterator i = str.begin(); out << ch;
GetNextCodePointAndAdvance(codePoint, i, str.end()); else if ((0x20 <= ch && ch <= 0x7e) || ch == ' ')
) out << "\"" << ch << "\"";
{ else if (ch == '\t')
if(codePoint == '\n') { out << "\"\\t\"";
out << "\n" << IndentTo(curIndent) << "#" << Indentation(postCommentIndent); else if (ch == '\n')
out.set_comment(); out << "\"\\n\"";
} else { else if (ch == '\b')
WriteCodePoint(out, codePoint); out << "\"\\b\"";
} else {
} out << "\"";
return true; WriteDoubleQuoteEscapeSequence(out, ch);
} out << "\"";
}
bool WriteAlias(ostream_wrapper& out, const std::string& str) return true;
{ }
out << "*";
return WriteAliasName(out, str); bool WriteComment(ostream_wrapper& out, const std::string& str,
} int postCommentIndent) {
const unsigned curIndent = out.col();
bool WriteAnchor(ostream_wrapper& out, const std::string& str) out << "#" << Indentation(postCommentIndent);
{ out.set_comment();
out << "&"; int codePoint;
return WriteAliasName(out, str); for (std::string::const_iterator i = str.begin();
} GetNextCodePointAndAdvance(codePoint, i, str.end());) {
if (codePoint == '\n') {
bool WriteTag(ostream_wrapper& out, const std::string& str, bool verbatim) out << "\n" << IndentTo(curIndent) << "#"
{ << Indentation(postCommentIndent);
out << (verbatim ? "!<" : "!"); out.set_comment();
StringCharSource buffer(str.c_str(), str.size()); } else {
const RegEx& reValid = verbatim ? Exp::URI() : Exp::Tag(); WriteCodePoint(out, codePoint);
while(buffer) { }
int n = reValid.Match(buffer); }
if(n <= 0) return true;
return false; }
while(--n >= 0) { bool WriteAlias(ostream_wrapper& out, const std::string& str) {
out << buffer[0]; out << "*";
++buffer; return WriteAliasName(out, str);
} }
}
if (verbatim) bool WriteAnchor(ostream_wrapper& out, const std::string& str) {
out << ">"; out << "&";
return true; return WriteAliasName(out, str);
} }
bool WriteTagWithPrefix(ostream_wrapper& out, const std::string& prefix, const std::string& tag) bool WriteTag(ostream_wrapper& out, const std::string& str, bool verbatim) {
{ out << (verbatim ? "!<" : "!");
out << "!"; StringCharSource buffer(str.c_str(), str.size());
StringCharSource prefixBuffer(prefix.c_str(), prefix.size()); const RegEx& reValid = verbatim ? Exp::URI() : Exp::Tag();
while(prefixBuffer) { while (buffer) {
int n = Exp::URI().Match(prefixBuffer); int n = reValid.Match(buffer);
if(n <= 0) if (n <= 0)
return false; return false;
while(--n >= 0) { while (--n >= 0) {
out << prefixBuffer[0]; out << buffer[0];
++prefixBuffer; ++buffer;
} }
} }
if (verbatim)
out << "!"; out << ">";
StringCharSource tagBuffer(tag.c_str(), tag.size()); return true;
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;
}
}
} }
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;
}
}
}
#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 {
struct StringFormat { enum value { Plain, SingleQuoted, DoubleQuoted, Literal }; }; 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 WriteSingleQuotedString(ostream_wrapper& out, const std::string& str); bool escapeNonAscii);
bool WriteDoubleQuotedString(ostream_wrapper& out, const std::string& str, bool escapeNonAscii);
bool WriteLiteralString(ostream_wrapper& out, const std::string& str, int indent); bool WriteSingleQuotedString(ostream_wrapper& out, const std::string& str);
bool WriteChar(ostream_wrapper& out, char ch); bool WriteDoubleQuotedString(ostream_wrapper& out, const std::string& str,
bool WriteComment(ostream_wrapper& out, const std::string& str, int postCommentIndent); bool escapeNonAscii);
bool WriteAlias(ostream_wrapper& out, const std::string& str); bool WriteLiteralString(ostream_wrapper& out, const std::string& str,
bool WriteAnchor(ostream_wrapper& out, const std::string& str); int indent);
bool WriteTag(ostream_wrapper& out, const std::string& str, bool verbatim); bool WriteChar(ostream_wrapper& out, char ch);
bool WriteTagWithPrefix(ostream_wrapper& out, const std::string& prefix, const std::string& tag); bool WriteComment(ostream_wrapper& out, const std::string& str,
bool WriteBinary(ostream_wrapper& out, const Binary& binary); int postCommentIndent);
} bool WriteAlias(ostream_wrapper& out, const std::string& str);
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
...@@ -2,112 +2,129 @@ ...@@ -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 // Escape
// . Translates the next 'codeLength' characters into a hex number and returns the result. // . Translates the next 'codeLength' characters into a hex number and returns
// . Throws if it's not actually hex. // the result.
std::string Escape(Stream& in, int codeLength) // . Throws if it's not actually hex.
{ std::string Escape(Stream& in, int codeLength) {
// grab string // grab string
std::string str; std::string str;
for(int i=0;i<codeLength;i++) for (int i = 0; i < codeLength; i++)
str += in.get(); str += in.get();
// get the value // get the value
unsigned value = ParseHex(str, in.mark()); unsigned value = ParseHex(str, in.mark());
// legal unicode? // legal unicode?
if((value >= 0xD800 && value <= 0xDFFF) || value > 0x10FFFF) { if ((value >= 0xD800 && value <= 0xDFFF) || value > 0x10FFFF) {
std::stringstream msg; std::stringstream msg;
msg << ErrorMsg::INVALID_UNICODE << value; msg << ErrorMsg::INVALID_UNICODE << value;
throw ParserException(in.mark(), msg.str()); throw ParserException(in.mark(), msg.str());
} }
// now break it up into chars // now break it up into chars
if(value <= 0x7F) if (value <= 0x7F)
return Str(value); return Str(value);
else if(value <= 0x7FF) else if (value <= 0x7FF)
return Str(0xC0 + (value >> 6)) + Str(0x80 + (value & 0x3F)); return Str(0xC0 + (value >> 6)) + Str(0x80 + (value & 0x3F));
else if(value <= 0xFFFF) else if (value <= 0xFFFF)
return Str(0xE0 + (value >> 12)) + Str(0x80 + ((value >> 6) & 0x3F)) + Str(0x80 + (value & 0x3F)); return Str(0xE0 + (value >> 12)) + Str(0x80 + ((value >> 6) & 0x3F)) +
else 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 // Escape
// . Escapes the sequence starting 'in' (it must begin with a '\' or single quote) // . Escapes the sequence starting 'in' (it must begin with a '\' or single
// and returns the result. // quote)
// . Throws if it's an unknown escape character. // and returns the result.
std::string Escape(Stream& in) // . Throws if it's an unknown escape character.
{ std::string Escape(Stream& in) {
// eat slash // eat slash
char escape = in.get(); char escape = in.get();
// switch on escape character // switch on escape character
char ch = in.get(); char ch = in.get();
// first do single quote, since it's easier // first do single quote, since it's easier
if(escape == '\'' && ch == '\'') if (escape == '\'' && ch == '\'')
return "\'"; 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
switch(ch) { // one!)
case '0': return std::string(1, '\x00'); switch (ch) {
case 'a': return "\x07"; case '0':
case 'b': return "\x08"; return std::string(1, '\x00');
case 't': case 'a':
case '\t': return "\x09"; return "\x07";
case 'n': return "\x0A"; case 'b':
case 'v': return "\x0B"; return "\x08";
case 'f': return "\x0C"; case 't':
case 'r': return "\x0D"; case '\t':
case 'e': return "\x1B"; return "\x09";
case ' ': return "\x20"; case 'n':
case '\"': return "\""; return "\x0A";
case '\'': return "\'"; case 'v':
case '\\': return "\\"; return "\x0B";
case '/': return "/"; case 'f':
case 'N': return "\x85"; return "\x0C";
case '_': return "\xA0"; case 'r':
case 'L': return "\xE2\x80\xA8"; // LS (#x2028) return "\x0D";
case 'P': return "\xE2\x80\xA9"; // PS (#x2029) case 'e':
case 'x': return Escape(in, 2); return "\x1B";
case 'u': return Escape(in, 4); case ' ':
case 'U': return Escape(in, 8); return "\x20";
} case '\"':
return "\"";
case '\'':
return "\'";
case '\\':
return "\\";
case '/':
return "/";
case 'N':
return "\x85";
case '_':
return "\xA0";
case 'L':
return "\xE2\x80\xA8"; // LS (#x2028)
case 'P':
return "\xE2\x80\xA9"; // PS (#x2029)
case 'x':
return Escape(in, 2);
case 'u':
return Escape(in, 4);
case 'U':
return Escape(in, 8);
}
std::stringstream msg; std::stringstream msg;
throw ParserException(in.mark(), std::string(ErrorMsg::INVALID_ESCAPE) + ch); throw ParserException(in.mark(), std::string(ErrorMsg::INVALID_ESCAPE) + ch);
} }
} }
} }
#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 // actual tags
inline const RegEx& DocStart() { inline const RegEx& DocStart() {
static const RegEx e = RegEx("---") + (BlankOrBreak() || RegEx()); static const RegEx e = RegEx("---") + (BlankOrBreak() || RegEx());
return e; return e;
} }
inline const RegEx& DocEnd() { inline const RegEx& DocEnd() {
static const RegEx e = RegEx("...") + (BlankOrBreak() || RegEx()); static const RegEx e = RegEx("...") + (BlankOrBreak() || RegEx());
return e; return e;
} }
inline const RegEx& DocIndicator() { inline const RegEx& DocIndicator() {
static const RegEx e = DocStart() || DocEnd(); static const RegEx e = DocStart() || DocEnd();
return e; return e;
} }
inline const RegEx& BlockEntry() { inline const RegEx& BlockEntry() {
static const RegEx e = RegEx('-') + (BlankOrBreak() || RegEx()); static const RegEx e = RegEx('-') + (BlankOrBreak() || RegEx());
return e; return e;
} }
inline const RegEx& Key() { inline const RegEx& Key() {
static const RegEx e = RegEx('?') + BlankOrBreak(); static const RegEx e = RegEx('?') + BlankOrBreak();
return e; return e;
} }
inline const RegEx& KeyInFlow() { inline const RegEx& KeyInFlow() {
static const RegEx e = RegEx('?') + BlankOrBreak(); static const RegEx e = RegEx('?') + BlankOrBreak();
return e; return e;
} }
inline const RegEx& Value() { inline const RegEx& Value() {
static const RegEx e = RegEx(':') + (BlankOrBreak() || RegEx()); static const RegEx e = RegEx(':') + (BlankOrBreak() || RegEx());
return e; return e;
} }
inline const RegEx& ValueInFlow() { inline const RegEx& ValueInFlow() {
static const RegEx e = RegEx(':') + (BlankOrBreak() || RegEx(",}", REGEX_OR)); static const RegEx e = RegEx(':') + (BlankOrBreak() || RegEx(",}", REGEX_OR));
return e; return e;
} }
inline const RegEx& ValueInJSONFlow() { inline const RegEx& ValueInJSONFlow() {
static const RegEx e = RegEx(':'); static const RegEx e = RegEx(':');
return e; return e;
} }
inline const RegEx Comment() { inline const RegEx Comment() {
static const RegEx e = RegEx('#'); static const RegEx e = RegEx('#');
return e; return e;
} }
inline const RegEx& Anchor() { inline const RegEx& Anchor() {
static const RegEx e = !(RegEx("[]{},", REGEX_OR) || BlankOrBreak()); static const RegEx e = !(RegEx("[]{},", REGEX_OR) || BlankOrBreak());
return e; return e;
} }
inline const RegEx& AnchorEnd() { inline const RegEx& AnchorEnd() {
static const RegEx e = RegEx("?:,]}%@`", REGEX_OR) || BlankOrBreak(); static const RegEx e = RegEx("?:,]}%@`", REGEX_OR) || BlankOrBreak();
return e; return e;
} }
inline const RegEx& URI() { inline const RegEx& URI() {
static const RegEx e = Word() || RegEx("#;/?:@&=+$,_.!~*'()[]", REGEX_OR) || (RegEx('%') + Hex() + Hex()); static const RegEx e = Word() || RegEx("#;/?:@&=+$,_.!~*'()[]", REGEX_OR) ||
return e; (RegEx('%') + Hex() + Hex());
} return e;
inline const RegEx& Tag() { }
static const RegEx e = Word() || RegEx("#;/?:@&=+$_.~*'", REGEX_OR) || (RegEx('%') + Hex() + Hex()); inline const RegEx& Tag() {
return e; static const RegEx e = Word() || RegEx("#;/?:@&=+$_.~*'", REGEX_OR) ||
} (RegEx('%') + Hex() + Hex());
return e;
}
// Plain scalar rules: // Plain scalar rules:
// . Cannot start with a blank. // . Cannot start with a blank.
// . Can never start with any of , [ ] { } # & * ! | > \' \" % @ ` // . Can never start with any of , [ ] { } # & * ! | > \' \" % @ `
// . In the block context - ? : must be not be followed with a space. // . 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. // . In the flow context ? is illegal and : and - must not be followed with a
inline const RegEx& PlainScalar() { // space.
static const RegEx e = !(BlankOrBreak() || RegEx(",[]{}#&*!|>\'\"%@`", REGEX_OR) || (RegEx("-?:", REGEX_OR) + (BlankOrBreak() || RegEx()))); inline const RegEx& PlainScalar() {
return e; static const RegEx e =
} !(BlankOrBreak() || RegEx(",[]{}#&*!|>\'\"%@`", REGEX_OR) ||
inline const RegEx& PlainScalarInFlow() { (RegEx("-?:", REGEX_OR) + (BlankOrBreak() || RegEx())));
static const RegEx e = !(BlankOrBreak() || RegEx("?,[]{}#&*!|>\'\"%@`", REGEX_OR) || (RegEx("-:", REGEX_OR) + Blank())); return e;
return e; }
} inline const RegEx& PlainScalarInFlow() {
inline const RegEx& EndScalar() { static const RegEx e =
static const RegEx e = RegEx(':') + (BlankOrBreak() || RegEx()); !(BlankOrBreak() || RegEx("?,[]{}#&*!|>\'\"%@`", REGEX_OR) ||
return e; (RegEx("-:", REGEX_OR) + Blank()));
} return e;
inline const RegEx& EndScalarInFlow() { }
static const RegEx e = (RegEx(':') + (BlankOrBreak() || RegEx() || RegEx(",]}", REGEX_OR))) || RegEx(",?[]{}", REGEX_OR); inline const RegEx& EndScalar() {
return e; 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() { inline const RegEx& EscSingleQuote() {
static const RegEx e = RegEx("\'\'"); static const RegEx e = RegEx("\'\'");
return e; return e;
} }
inline const RegEx& EscBreak() { inline const RegEx& EscBreak() {
static const RegEx e = RegEx('\\') + Break(); static const RegEx e = RegEx('\\') + Break();
return e; return e;
} }
inline const RegEx& ChompIndicator() { inline const RegEx& ChompIndicator() {
static const RegEx e = RegEx("+-", REGEX_OR); static const RegEx e = RegEx("+-", REGEX_OR);
return e; return e;
} }
inline const RegEx& Chomp() { inline const RegEx& Chomp() {
static const RegEx e = (ChompIndicator() + Digit()) || (Digit() + ChompIndicator()) || ChompIndicator() || Digit(); static const RegEx e = (ChompIndicator() + Digit()) ||
return e; (Digit() + ChompIndicator()) || ChompIndicator() ||
} Digit();
return e;
}
// and some functions // and some functions
std::string Escape(Stream& in); std::string Escape(Stream& in);
} }
namespace Keys namespace Keys {
{ const char Directive = '%';
const char Directive = '%'; const char FlowSeqStart = '[';
const char FlowSeqStart = '['; const char FlowSeqEnd = ']';
const char FlowSeqEnd = ']'; const char FlowMapStart = '{';
const char FlowMapStart = '{'; const char FlowMapEnd = '}';
const char FlowMapEnd = '}'; const char FlowEntry = ',';
const char FlowEntry = ','; const char Alias = '*';
const char Alias = '*'; const char Anchor = '&';
const char Anchor = '&'; const char Tag = '!';
const char Tag = '!'; const char LiteralScalar = '|';
const char LiteralScalar = '|'; const char FoldedScalar = '>';
const char FoldedScalar = '>'; const char VerbatimTagStart = '<';
const char VerbatimTagStart = '<'; const char VerbatimTagEnd = '>';
const char VerbatimTagEnd = '>'; }
}
} }
#endif // EXP_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #endif // EXP_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#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) {
for(unsigned i=0;i<indent.n;i++)
out << ' ';
return out;
}
struct IndentTo { inline ostream_wrapper& operator<<(ostream_wrapper& out,
IndentTo(unsigned n_): n(n_) {} const Indentation& indent) {
unsigned n; for (unsigned i = 0; i < indent.n; i++)
}; out << ' ';
return out;
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;
};
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 #endif // INDENTATION_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#include "yaml-cpp/null.h" #include "yaml-cpp/null.h"
namespace YAML namespace YAML {
{ _Null Null;
_Null Null;
} }
...@@ -2,55 +2,47 @@ ...@@ -2,55 +2,47 @@
#include <cstring> #include <cstring>
#include <iostream> #include <iostream>
namespace YAML namespace YAML {
{ ostream_wrapper::ostream_wrapper()
ostream_wrapper::ostream_wrapper(): m_pStream(0), m_pos(0), m_row(0), m_col(0), m_comment(false) : m_pStream(0), m_pos(0), m_row(0), m_col(0), m_comment(false) {}
{
} ostream_wrapper::ostream_wrapper(std::ostream& stream)
: m_pStream(&stream), m_pos(0), m_row(0), m_col(0), m_comment(false) {}
ostream_wrapper::ostream_wrapper(std::ostream& stream): m_pStream(&stream), m_pos(0), m_row(0), m_col(0), m_comment(false)
{ ostream_wrapper::~ostream_wrapper() {}
}
void ostream_wrapper::write(const std::string& str) {
ostream_wrapper::~ostream_wrapper() if (m_pStream) {
{ m_pStream->write(str.c_str(), str.size());
} } else {
m_buffer.resize(std::max(m_buffer.size(), m_pos + str.size() + 1));
void ostream_wrapper::write(const std::string& str) std::copy(str.begin(), str.end(), &m_buffer[m_pos]);
{ }
if(m_pStream) {
m_pStream->write(str.c_str(), str.size()); for (std::size_t i = 0; i < str.size(); i++)
} else { update_pos(str[i]);
m_buffer.resize(std::max(m_buffer.size(), m_pos + str.size() + 1)); }
std::copy(str.begin(), str.end(), &m_buffer[m_pos]);
} void ostream_wrapper::write(const char* str, std::size_t size) {
if (m_pStream) {
for(std::size_t i=0;i<str.size();i++) m_pStream->write(str, size);
update_pos(str[i]); } else {
} m_buffer.resize(std::max(m_buffer.size(), m_pos + size + 1));
std::copy(str, str + size, &m_buffer[m_pos]);
void ostream_wrapper::write(const char *str, std::size_t size) }
{
if(m_pStream) { for (std::size_t i = 0; i < size; i++)
m_pStream->write(str, size); update_pos(str[i]);
} else { }
m_buffer.resize(std::max(m_buffer.size(), m_pos + size + 1));
std::copy(str, str + size, &m_buffer[m_pos]); void ostream_wrapper::update_pos(char ch) {
} m_pos++;
m_col++;
for(std::size_t i=0;i<size;i++)
update_pos(str[i]); if (ch == '\n') {
} m_row++;
m_col = 0;
void ostream_wrapper::update_pos(char ch) m_comment = false;
{ }
m_pos++; }
m_col++;
if(ch == '\n') {
m_row++;
m_col = 0;
m_comment = false;
}
}
} }
...@@ -9,133 +9,119 @@ ...@@ -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) { Load(in); }
}
Parser::~Parser() {}
Parser::Parser(std::istream& in)
{ Parser::operator bool() const {
Load(in); return m_pScanner.get() && !m_pScanner->empty();
} }
Parser::~Parser() void Parser::Load(std::istream& in) {
{ m_pScanner.reset(new Scanner(in));
} m_pDirectives.reset(new Directives);
}
Parser::operator bool() const
{ // HandleNextDocument
return m_pScanner.get() && !m_pScanner->empty(); // . Handles the next document
} // . Throws a ParserException on error.
// . Returns false if there are no more documents
void Parser::Load(std::istream& in) bool Parser::HandleNextDocument(EventHandler& eventHandler) {
{ if (!m_pScanner.get())
m_pScanner.reset(new Scanner(in)); return false;
m_pDirectives.reset(new Directives);
} ParseDirectives();
if (m_pScanner->empty())
// HandleNextDocument return false;
// . Handles the next document
// . Throws a ParserException on error. SingleDocParser sdp(*m_pScanner, *m_pDirectives);
// . Returns false if there are no more documents sdp.HandleDocument(eventHandler);
bool Parser::HandleNextDocument(EventHandler& eventHandler) return true;
{ }
if(!m_pScanner.get())
return false; // ParseDirectives
// . Reads any directives that are next in the queue.
ParseDirectives(); void Parser::ParseDirectives() {
if(m_pScanner->empty()) bool readDirective = false;
return false;
while (1) {
SingleDocParser sdp(*m_pScanner, *m_pDirectives); if (m_pScanner->empty())
sdp.HandleDocument(eventHandler); break;
return true;
} Token& token = m_pScanner->peek();
if (token.type != Token::DIRECTIVE)
// ParseDirectives break;
// . Reads any directives that are next in the queue.
void Parser::ParseDirectives() // we keep the directives from the last document if none are specified;
{ // but if any directives are specific, then we reset them
bool readDirective = false; if (!readDirective)
m_pDirectives.reset(new Directives);
while(1) {
if(m_pScanner->empty()) readDirective = true;
break; HandleDirective(token);
m_pScanner->pop();
Token& token = m_pScanner->peek(); }
if(token.type != Token::DIRECTIVE) }
break;
void Parser::HandleDirective(const Token& token) {
// we keep the directives from the last document if none are specified; if (token.value == "YAML")
// but if any directives are specific, then we reset them HandleYamlDirective(token);
if(!readDirective) else if (token.value == "TAG")
m_pDirectives.reset(new Directives); HandleTagDirective(token);
}
readDirective = true;
HandleDirective(token); // HandleYamlDirective
m_pScanner->pop(); // . Should be of the form 'major.minor' (like a version number)
} void Parser::HandleYamlDirective(const Token& token) {
} if (token.params.size() != 1)
throw ParserException(token.mark, ErrorMsg::YAML_DIRECTIVE_ARGS);
void Parser::HandleDirective(const Token& token)
{ if (!m_pDirectives->version.isDefault)
if(token.value == "YAML") throw ParserException(token.mark, ErrorMsg::REPEATED_YAML_DIRECTIVE);
HandleYamlDirective(token);
else if(token.value == "TAG") std::stringstream str(token.params[0]);
HandleTagDirective(token); str >> m_pDirectives->version.major;
} str.get();
str >> m_pDirectives->version.minor;
// HandleYamlDirective if (!str || str.peek() != EOF)
// . Should be of the form 'major.minor' (like a version number) throw ParserException(
void Parser::HandleYamlDirective(const Token& token) token.mark, std::string(ErrorMsg::YAML_VERSION) + token.params[0]);
{
if(token.params.size() != 1) if (m_pDirectives->version.major > 1)
throw ParserException(token.mark, ErrorMsg::YAML_DIRECTIVE_ARGS); throw ParserException(token.mark, ErrorMsg::YAML_MAJOR_VERSION);
if(!m_pDirectives->version.isDefault) m_pDirectives->version.isDefault = false;
throw ParserException(token.mark, ErrorMsg::REPEATED_YAML_DIRECTIVE); // TODO: warning on major == 1, minor > 2?
}
std::stringstream str(token.params[0]);
str >> m_pDirectives->version.major; // HandleTagDirective
str.get(); // . Should be of the form 'handle prefix', where 'handle' is converted to
str >> m_pDirectives->version.minor; // 'prefix' in the file.
if(!str || str.peek() != EOF) void Parser::HandleTagDirective(const Token& token) {
throw ParserException(token.mark, std::string(ErrorMsg::YAML_VERSION) + token.params[0]); if (token.params.size() != 2)
throw ParserException(token.mark, ErrorMsg::TAG_DIRECTIVE_ARGS);
if(m_pDirectives->version.major > 1)
throw ParserException(token.mark, ErrorMsg::YAML_MAJOR_VERSION); const std::string& handle = token.params[0];
const std::string& prefix = token.params[1];
m_pDirectives->version.isDefault = false; if (m_pDirectives->tags.find(handle) != m_pDirectives->tags.end())
// TODO: warning on major == 1, minor > 2? throw ParserException(token.mark, ErrorMsg::REPEATED_TAG_DIRECTIVE);
}
m_pDirectives->tags[handle] = prefix;
// HandleTagDirective }
// . Should be of the form 'handle prefix', where 'handle' is converted to 'prefix' in the file.
void Parser::HandleTagDirective(const Token& token) void Parser::PrintTokens(std::ostream& out) {
{ if (!m_pScanner.get())
if(token.params.size() != 2) return;
throw ParserException(token.mark, ErrorMsg::TAG_DIRECTIVE_ARGS);
while (1) {
const std::string& handle = token.params[0]; if (m_pScanner->empty())
const std::string& prefix = token.params[1]; break;
if(m_pDirectives->tags.find(handle) != m_pDirectives->tags.end())
throw ParserException(token.mark, ErrorMsg::REPEATED_TAG_DIRECTIVE); out << m_pScanner->peek() << "\n";
m_pScanner->pop();
m_pDirectives->tags[handle] = prefix; }
} }
void Parser::PrintTokens(std::ostream& out)
{
if(!m_pScanner.get())
return;
while(1) {
if(m_pScanner->empty())
break;
out << m_pScanner->peek() << "\n";
m_pScanner->pop();
}
}
} }
#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 @@ ...@@ -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 {
const T& top(std::ptrdiff_t diff) const { return **(m_data.end() - 1 + diff); } return **(m_data.end() - 1 + diff);
}
private:
std::vector<T*> m_data; private:
std::vector<T*> m_data;
}; };
#endif // PTR_STACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #endif // PTR_STACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#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
...@@ -12,36 +14,35 @@ ...@@ -12,36 +14,35 @@
#include <vector> #include <vector>
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
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment