diff --git a/include/yaml-cpp/emitter.h b/include/yaml-cpp/emitter.h index 4e329cc..4251bab 100644 --- a/include/yaml-cpp/emitter.h +++ b/include/yaml-cpp/emitter.h @@ -8,6 +8,7 @@ #include "yaml-cpp/dll.h" #include "yaml-cpp/binary.h" +#include "yaml-cpp/emitterdef.h" #include "yaml-cpp/emittermanip.h" #include "yaml-cpp/ostream.h" #include "yaml-cpp/noncopyable.h" @@ -85,12 +86,12 @@ namespace YAML void EmitKindTag(); void EmitTag(bool verbatim, const _Tag& tag); - void PrepareNode(); - void PrepareTopNode(); - void FlowSeqPrepareNode(); - void BlockSeqPrepareNode(); - void FlowMapPrepareNode(); - void BlockMapPrepareNode(); + void PrepareNode(EmitterNodeType::value child); + void PrepareTopNode(EmitterNodeType::value child); + void FlowSeqPrepareNode(EmitterNodeType::value child); + void BlockSeqPrepareNode(EmitterNodeType::value child); + void FlowMapPrepareNode(EmitterNodeType::value child); + void BlockMapPrepareNode(EmitterNodeType::value child); const char *ComputeFullBoolName(bool b) const; bool CanEmitNewline() const; diff --git a/include/yaml-cpp/emitterdef.h b/include/yaml-cpp/emitterdef.h new file mode 100644 index 0000000..d8d5559 --- /dev/null +++ b/include/yaml-cpp/emitterdef.h @@ -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 diff --git a/src/emitter.cpp b/src/emitter.cpp index 52b5462..802f86a 100644 --- a/src/emitter.cpp +++ b/src/emitter.cpp @@ -210,7 +210,7 @@ namespace YAML if(!good()) return; - PrepareNode(); + PrepareNode(m_pState->NextGroupType(GroupType::Seq)); m_pState->BeginGroup(GroupType::Seq); } @@ -230,7 +230,7 @@ namespace YAML if(!good()) return; - PrepareNode(); + PrepareNode(m_pState->NextGroupType(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 // E.g., if we're in a sequence, write the "- " - void Emitter::PrepareNode() + void Emitter::PrepareNode(EmitterNodeType::value child) { - switch(m_pState->CurGroupType()) { - case GroupType::None: - PrepareTopNode(); + switch(m_pState->CurGroupNodeType()) { + case EmitterNodeType::None: + PrepareTopNode(child); break; - case GroupType::Seq: - switch(m_pState->CurGroupFlowType()) { - case FlowType::Flow: - FlowSeqPrepareNode(); - break; - case FlowType::Block: - BlockSeqPrepareNode(); - break; - case FlowType::None: - assert(false); - } + case EmitterNodeType::FlowSeq: + FlowSeqPrepareNode(child); break; - case GroupType::Map: - switch(m_pState->CurGroupFlowType()) { - case FlowType::Flow: - FlowMapPrepareNode(); - break; - case FlowType::Block: - BlockMapPrepareNode(); - break; - case FlowType::None: - assert(false); - } + case EmitterNodeType::BlockSeq: + BlockSeqPrepareNode(child); + break; + case EmitterNodeType::FlowMap: + FlowMapPrepareNode(child); + break; + case EmitterNodeType::BlockMap: + BlockMapPrepareNode(child); + break; + case EmitterNodeType::Scalar: + assert(false); break; } } - void Emitter::PrepareTopNode() + void Emitter::PrepareTopNode(EmitterNodeType::value child) { const bool hasAnchor = m_pState->HasAnchor(); const bool hasTag = m_pState->HasTag(); @@ -306,11 +297,11 @@ namespace YAML 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(); if(!m_pState->HasTag() && !m_pState->HasAnchor()) { @@ -319,16 +310,26 @@ namespace YAML } m_stream << IndentTo(curIndent); 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()) return *this; - PrepareNode(); + PrepareNode(EmitterNodeType::Scalar); const bool escapeNonAscii = m_pState->GetOutputCharset() == EscapeNonAscii; const StringFormat::value strFormat = Utils::ComputeStringFormat(str, m_pState->GetStringFormat(), m_pState->CurGroupFlowType(), escapeNonAscii); diff --git a/src/emitterstate.cpp b/src/emitterstate.cpp index e7e5a87..90e0196 100644 --- a/src/emitterstate.cpp +++ b/src/emitterstate.cpp @@ -52,6 +52,25 @@ namespace YAML 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() { BeginNode(); @@ -70,7 +89,10 @@ namespace YAML pGroup->modifiedSettings = m_modifiedSettings; // set up group - pGroup->flow = GetFlowType(type); + if(GetFlowType(type) == Block) + pGroup->flowType = FlowType::Block; + else + pGroup->flowType = FlowType::Flow; pGroup->indent = GetIndent(); m_groups.push(pGroup); @@ -97,21 +119,23 @@ namespace YAML // by a local setting we just popped, so we need to restore them 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 GroupType::None; - - return m_groups.top().type; + return m_groups.empty() ? GroupType::None : m_groups.top().type; } FlowType::value EmitterState::CurGroupFlowType() const { - if(m_groups.empty()) - return FlowType::None; - - return (m_groups.top().flow == Flow ? FlowType::Flow : FlowType::Block); + return m_groups.empty() ? FlowType::None : m_groups.top().flowType; } int EmitterState::CurGroupIndent() const diff --git a/src/emitterstate.h b/src/emitterstate.h index c53a4e1..e4c9297 100644 --- a/src/emitterstate.h +++ b/src/emitterstate.h @@ -8,6 +8,7 @@ #include "ptr_stack.h" #include "setting.h" +#include "yaml-cpp/emitterdef.h" #include "yaml-cpp/emittermanip.h" #include #include @@ -36,11 +37,15 @@ namespace YAML void BeginScalar(); void BeginGroup(GroupType::value type); void EndGroup(GroupType::value type); - + + EmitterNodeType::value NextGroupType(GroupType::value type) const; + EmitterNodeType::value CurGroupNodeType() const; + GroupType::value CurGroupType() const; FlowType::value CurGroupFlowType() const; int CurGroupIndent() const; std::size_t CurGroupChildCount() const; + int CurIndent() const { return m_curIndent; } bool HasAnchor() const { return m_hasAnchor; } bool HasTag() const { return m_hasTag; } @@ -120,11 +125,29 @@ namespace YAML explicit Group(GroupType::value type_): type(type_), indent(0), childCount(0) {} GroupType::value type; - EMITTER_MANIP flow; + FlowType::value flowType; int indent; std::size_t childCount; 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 m_groups; diff --git a/src/ptr_stack.h b/src/ptr_stack.h index bf454fb..eec0fb8 100644 --- a/src/ptr_stack.h +++ b/src/ptr_stack.h @@ -38,7 +38,10 @@ public: } T& top() { 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: std::vector m_data; };