mirror of
https://github.com/jbeder/yaml-cpp.git
synced 2025-09-09 20:51:16 +00:00
Structured emitter node handling better
This commit is contained in:
@@ -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;
|
||||
|
13
include/yaml-cpp/emitterdef.h
Normal file
13
include/yaml-cpp/emitterdef.h
Normal 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
|
@@ -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();
|
||||
case EmitterNodeType::FlowSeq:
|
||||
FlowSeqPrepareNode(child);
|
||||
break;
|
||||
case FlowType::Block:
|
||||
BlockSeqPrepareNode();
|
||||
case EmitterNodeType::BlockSeq:
|
||||
BlockSeqPrepareNode(child);
|
||||
break;
|
||||
case FlowType::None:
|
||||
case EmitterNodeType::FlowMap:
|
||||
FlowMapPrepareNode(child);
|
||||
break;
|
||||
case EmitterNodeType::BlockMap:
|
||||
BlockMapPrepareNode(child);
|
||||
break;
|
||||
case EmitterNodeType::Scalar:
|
||||
assert(false);
|
||||
}
|
||||
break;
|
||||
case GroupType::Map:
|
||||
switch(m_pState->CurGroupFlowType()) {
|
||||
case FlowType::Flow:
|
||||
FlowMapPrepareNode();
|
||||
break;
|
||||
case FlowType::Block:
|
||||
BlockMapPrepareNode();
|
||||
break;
|
||||
case FlowType::None:
|
||||
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);
|
||||
|
@@ -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);
|
||||
@@ -98,20 +120,22 @@ namespace YAML
|
||||
m_globalModifiedSettings.restore();
|
||||
}
|
||||
|
||||
GroupType::value EmitterState::CurGroupType() const
|
||||
EmitterNodeType::value EmitterState::CurGroupNodeType() const
|
||||
{
|
||||
if(m_groups.empty())
|
||||
return GroupType::None;
|
||||
return EmitterNodeType::None;
|
||||
|
||||
return m_groups.top().type;
|
||||
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
|
||||
{
|
||||
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
|
||||
|
@@ -8,6 +8,7 @@
|
||||
|
||||
#include "ptr_stack.h"
|
||||
#include "setting.h"
|
||||
#include "yaml-cpp/emitterdef.h"
|
||||
#include "yaml-cpp/emittermanip.h"
|
||||
#include <cassert>
|
||||
#include <vector>
|
||||
@@ -37,10 +38,14 @@ namespace YAML
|
||||
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<Group> m_groups;
|
||||
|
@@ -39,6 +39,9 @@ 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<T*> m_data;
|
||||
};
|
||||
|
Reference in New Issue
Block a user