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/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;
|
||||||
|
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())
|
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);
|
||||||
|
@@ -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
|
||||||
|
@@ -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;
|
||||||
|
@@ -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;
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user