Structured emitter node handling better

This commit is contained in:
Jesse Beder
2012-05-21 21:57:25 -05:00
parent 23fb2dc811
commit 35d827f187
6 changed files with 120 additions and 55 deletions

View File

@@ -8,6 +8,7 @@
#include "yaml-cpp/dll.h" #include "yaml-cpp/dll.h"
#include "yaml-cpp/binary.h" #include "yaml-cpp/binary.h"
#include "yaml-cpp/emitterdef.h"
#include "yaml-cpp/emittermanip.h" #include "yaml-cpp/emittermanip.h"
#include "yaml-cpp/ostream.h" #include "yaml-cpp/ostream.h"
#include "yaml-cpp/noncopyable.h" #include "yaml-cpp/noncopyable.h"
@@ -85,12 +86,12 @@ namespace YAML
void EmitKindTag(); void EmitKindTag();
void EmitTag(bool verbatim, const _Tag& tag); void EmitTag(bool verbatim, const _Tag& tag);
void PrepareNode(); void PrepareNode(EmitterNodeType::value child);
void PrepareTopNode(); void PrepareTopNode(EmitterNodeType::value child);
void FlowSeqPrepareNode(); void FlowSeqPrepareNode(EmitterNodeType::value child);
void BlockSeqPrepareNode(); void BlockSeqPrepareNode(EmitterNodeType::value child);
void FlowMapPrepareNode(); void FlowMapPrepareNode(EmitterNodeType::value child);
void BlockMapPrepareNode(); void BlockMapPrepareNode(EmitterNodeType::value child);
const char *ComputeFullBoolName(bool b) const; const char *ComputeFullBoolName(bool b) const;
bool CanEmitNewline() const; bool CanEmitNewline() const;

View File

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

View File

@@ -210,7 +210,7 @@ namespace YAML
if(!good()) if(!good())
return; return;
PrepareNode(); PrepareNode(m_pState->NextGroupType(GroupType::Seq));
m_pState->BeginGroup(GroupType::Seq); m_pState->BeginGroup(GroupType::Seq);
} }
@@ -230,7 +230,7 @@ namespace YAML
if(!good()) if(!good())
return; return;
PrepareNode(); PrepareNode(m_pState->NextGroupType(GroupType::Map));
m_pState->BeginGroup(GroupType::Map); m_pState->BeginGroup(GroupType::Map);
} }
@@ -258,40 +258,31 @@ namespace YAML
// Put the stream in a state so we can simply write the next node // Put the stream in a state so we can simply write the next node
// E.g., if we're in a sequence, write the "- " // E.g., if we're in a sequence, write the "- "
void Emitter::PrepareNode() void Emitter::PrepareNode(EmitterNodeType::value child)
{ {
switch(m_pState->CurGroupType()) { switch(m_pState->CurGroupNodeType()) {
case GroupType::None: case EmitterNodeType::None:
PrepareTopNode(); PrepareTopNode(child);
break; break;
case GroupType::Seq: case EmitterNodeType::FlowSeq:
switch(m_pState->CurGroupFlowType()) { FlowSeqPrepareNode(child);
case FlowType::Flow:
FlowSeqPrepareNode();
break;
case FlowType::Block:
BlockSeqPrepareNode();
break;
case FlowType::None:
assert(false);
}
break; break;
case GroupType::Map: case EmitterNodeType::BlockSeq:
switch(m_pState->CurGroupFlowType()) { BlockSeqPrepareNode(child);
case FlowType::Flow: break;
FlowMapPrepareNode(); case EmitterNodeType::FlowMap:
break; FlowMapPrepareNode(child);
case FlowType::Block: break;
BlockMapPrepareNode(); case EmitterNodeType::BlockMap:
break; BlockMapPrepareNode(child);
case FlowType::None: break;
assert(false); case EmitterNodeType::Scalar:
} assert(false);
break; break;
} }
} }
void Emitter::PrepareTopNode() void Emitter::PrepareTopNode(EmitterNodeType::value child)
{ {
const bool hasAnchor = m_pState->HasAnchor(); const bool hasAnchor = m_pState->HasAnchor();
const bool hasTag = m_pState->HasTag(); const bool hasTag = m_pState->HasTag();
@@ -306,11 +297,11 @@ namespace YAML
m_stream << " "; m_stream << " ";
} }
void Emitter::FlowSeqPrepareNode() void Emitter::FlowSeqPrepareNode(EmitterNodeType::value child)
{ {
} }
void Emitter::BlockSeqPrepareNode() void Emitter::BlockSeqPrepareNode(EmitterNodeType::value child)
{ {
const unsigned curIndent = m_pState->CurIndent(); const unsigned curIndent = m_pState->CurIndent();
if(!m_pState->HasTag() && !m_pState->HasAnchor()) { if(!m_pState->HasTag() && !m_pState->HasAnchor()) {
@@ -319,16 +310,26 @@ namespace YAML
} }
m_stream << IndentTo(curIndent); m_stream << IndentTo(curIndent);
m_stream << "-"; m_stream << "-";
m_stream << IndentTo(curIndent + m_pState->CurGroupIndent());
} }
} }
void Emitter::FlowMapPrepareNode() void Emitter::FlowMapPrepareNode(EmitterNodeType::value child)
{ {
} }
void Emitter::BlockMapPrepareNode() void Emitter::BlockMapPrepareNode(EmitterNodeType::value child)
{ {
if(!m_pState->HasTag() && !m_pState->HasAnchor()) {
const std::size_t childCount = m_pState->CurGroupChildCount();
if(childCount % 2 == 0) {
// key
if(childCount > 0) {
m_stream << "\n";
}
} else {
// value
}
}
} }
// ******************************************************************************************* // *******************************************************************************************
@@ -339,7 +340,7 @@ namespace YAML
if(!good()) if(!good())
return *this; return *this;
PrepareNode(); PrepareNode(EmitterNodeType::Scalar);
const bool escapeNonAscii = m_pState->GetOutputCharset() == EscapeNonAscii; const bool escapeNonAscii = m_pState->GetOutputCharset() == EscapeNonAscii;
const StringFormat::value strFormat = Utils::ComputeStringFormat(str, m_pState->GetStringFormat(), m_pState->CurGroupFlowType(), escapeNonAscii); const StringFormat::value strFormat = Utils::ComputeStringFormat(str, m_pState->GetStringFormat(), m_pState->CurGroupFlowType(), escapeNonAscii);

View File

@@ -52,6 +52,25 @@ namespace YAML
m_hasTag = false; m_hasTag = 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::BeginScalar() void EmitterState::BeginScalar()
{ {
BeginNode(); BeginNode();
@@ -70,7 +89,10 @@ namespace YAML
pGroup->modifiedSettings = m_modifiedSettings; pGroup->modifiedSettings = m_modifiedSettings;
// set up group // set up group
pGroup->flow = GetFlowType(type); if(GetFlowType(type) == Block)
pGroup->flowType = FlowType::Block;
else
pGroup->flowType = FlowType::Flow;
pGroup->indent = GetIndent(); pGroup->indent = GetIndent();
m_groups.push(pGroup); m_groups.push(pGroup);
@@ -97,21 +119,23 @@ namespace YAML
// by a local setting we just popped, so we need to restore them // by a local setting we just popped, so we need to restore them
m_globalModifiedSettings.restore(); m_globalModifiedSettings.restore();
} }
GroupType::value EmitterState::CurGroupType() const EmitterNodeType::value EmitterState::CurGroupNodeType() const
{
if(m_groups.empty())
return EmitterNodeType::None;
return m_groups.top().NodeType();
}
GroupType::value EmitterState::CurGroupType() const
{ {
if(m_groups.empty()) return m_groups.empty() ? GroupType::None : m_groups.top().type;
return GroupType::None;
return m_groups.top().type;
} }
FlowType::value EmitterState::CurGroupFlowType() const FlowType::value EmitterState::CurGroupFlowType() const
{ {
if(m_groups.empty()) return m_groups.empty() ? FlowType::None : m_groups.top().flowType;
return FlowType::None;
return (m_groups.top().flow == Flow ? FlowType::Flow : FlowType::Block);
} }
int EmitterState::CurGroupIndent() const int EmitterState::CurGroupIndent() const

View File

@@ -8,6 +8,7 @@
#include "ptr_stack.h" #include "ptr_stack.h"
#include "setting.h" #include "setting.h"
#include "yaml-cpp/emitterdef.h"
#include "yaml-cpp/emittermanip.h" #include "yaml-cpp/emittermanip.h"
#include <cassert> #include <cassert>
#include <vector> #include <vector>
@@ -36,11 +37,15 @@ namespace YAML
void BeginScalar(); void BeginScalar();
void BeginGroup(GroupType::value type); void BeginGroup(GroupType::value type);
void EndGroup(GroupType::value type); void EndGroup(GroupType::value type);
EmitterNodeType::value NextGroupType(GroupType::value type) const;
EmitterNodeType::value CurGroupNodeType() const;
GroupType::value CurGroupType() const; GroupType::value CurGroupType() const;
FlowType::value CurGroupFlowType() const; FlowType::value CurGroupFlowType() const;
int CurGroupIndent() const; int CurGroupIndent() const;
std::size_t CurGroupChildCount() const; std::size_t CurGroupChildCount() const;
int CurIndent() const { return m_curIndent; } int CurIndent() const { return m_curIndent; }
bool HasAnchor() const { return m_hasAnchor; } bool HasAnchor() const { return m_hasAnchor; }
bool HasTag() const { return m_hasTag; } bool HasTag() const { return m_hasTag; }
@@ -120,11 +125,29 @@ namespace YAML
explicit Group(GroupType::value type_): type(type_), indent(0), childCount(0) {} explicit Group(GroupType::value type_): type(type_), indent(0), childCount(0) {}
GroupType::value type; GroupType::value type;
EMITTER_MANIP flow; FlowType::value flowType;
int indent; int indent;
std::size_t childCount; std::size_t childCount;
SettingChanges modifiedSettings; SettingChanges modifiedSettings;
EmitterNodeType::value NodeType() const {
if(type == GroupType::Seq) {
if(flowType == FlowType::Flow)
return EmitterNodeType::FlowSeq;
else
return EmitterNodeType::BlockSeq;
} else {
if(flowType == FlowType::Flow)
return EmitterNodeType::FlowMap;
else
return EmitterNodeType::BlockMap;
}
// can't get here
assert(false);
return EmitterNodeType::None;
}
}; };
ptr_stack<Group> m_groups; ptr_stack<Group> m_groups;

View File

@@ -38,7 +38,10 @@ public:
} }
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); }
const T& top(std::ptrdiff_t diff) const { return **(m_data.end() - 1 + diff); }
private: private:
std::vector<T*> m_data; std::vector<T*> m_data;
}; };