3 #include "emitterstate.h"
4 #include "yaml-cpp/exceptions.h" // IWYU pragma: keep
7 EmitterState::EmitterState()
12 m_hasNonContent(false),
14 // set default global manipulators
15 m_charset.set(EmitNonAscii);
17 m_boolFmt.set(TrueFalseBool);
18 m_nullFmt.set(NullAsTilde);
19 m_boolLengthFmt.set(LongBool);
20 m_boolCaseFmt.set(LowerCase);
23 m_preCommentIndent.set(2);
24 m_postCommentIndent.set(1);
27 m_mapKeyFmt.set(Auto);
28 m_floatPrecision.set(std::numeric_limits<float>::digits10 + 1);
29 m_doublePrecision.set(std::numeric_limits<double>::digits10 + 1);
32 EmitterState::~EmitterState() {}
35 // . We blindly tries to set all possible formatters to this value
36 // . Only the ones that make sense will be accepted
37 void EmitterState::SetLocalValue(EMITTER_MANIP value) {
38 SetOutputCharset(value, FmtScope::Local);
39 SetStringFormat(value, FmtScope::Local);
40 SetBoolFormat(value, FmtScope::Local);
41 SetBoolCaseFormat(value, FmtScope::Local);
42 SetBoolLengthFormat(value, FmtScope::Local);
43 SetNullFormat(value, FmtScope::Local);
44 SetIntFormat(value, FmtScope::Local);
45 SetFlowType(GroupType::Seq, value, FmtScope::Local);
46 SetFlowType(GroupType::Map, value, FmtScope::Local);
47 SetMapKeyFormat(value, FmtScope::Local);
50 void EmitterState::SetAnchor() { m_hasAnchor = true; }
52 void EmitterState::SetTag() { m_hasTag = true; }
54 void EmitterState::SetNonContent() { m_hasNonContent = true; }
56 void EmitterState::SetLongKey() {
57 assert(!m_groups.empty());
58 if (m_groups.empty()) {
62 assert(m_groups.back()->type == GroupType::Map);
63 m_groups.back()->longKey = true;
66 void EmitterState::ForceFlow() {
67 assert(!m_groups.empty());
68 if (m_groups.empty()) {
72 m_groups.back()->flowType = FlowType::Flow;
75 void EmitterState::StartedNode() {
76 if (m_groups.empty()) {
79 m_groups.back()->childCount++;
80 if (m_groups.back()->childCount % 2 == 0) {
81 m_groups.back()->longKey = false;
87 m_hasNonContent = false;
90 EmitterNodeType::value EmitterState::NextGroupType(
91 GroupType::value type) const {
92 if (type == GroupType::Seq) {
93 if (GetFlowType(type) == Block)
94 return EmitterNodeType::BlockSeq;
96 return EmitterNodeType::FlowSeq;
98 if (GetFlowType(type) == Block)
99 return EmitterNodeType::BlockMap;
101 return EmitterNodeType::FlowMap;
106 return EmitterNodeType::NoType;
109 void EmitterState::StartedDoc() {
112 m_hasNonContent = false;
115 void EmitterState::EndedDoc() {
118 m_hasNonContent = false;
121 void EmitterState::StartedScalar() {
123 ClearModifiedSettings();
126 void EmitterState::StartedGroup(GroupType::value type) {
129 const std::size_t lastGroupIndent =
130 (m_groups.empty() ? 0 : m_groups.back()->indent);
131 m_curIndent += lastGroupIndent;
133 // TODO: Create move constructors for settings types to simplify transfer
134 std::unique_ptr<Group> pGroup(new Group(type));
136 // transfer settings (which last until this group is done)
138 // NB: if pGroup->modifiedSettings == m_modifiedSettings,
139 // m_modifiedSettings is not changed!
140 pGroup->modifiedSettings = std::move(m_modifiedSettings);
143 if (GetFlowType(type) == Block) {
144 pGroup->flowType = FlowType::Block;
146 pGroup->flowType = FlowType::Flow;
148 pGroup->indent = GetIndent();
150 m_groups.push_back(std::move(pGroup));
153 void EmitterState::EndedGroup(GroupType::value type) {
154 if (m_groups.empty()) {
155 if (type == GroupType::Seq) {
156 return SetError(ErrorMsg::UNEXPECTED_END_SEQ);
158 return SetError(ErrorMsg::UNEXPECTED_END_MAP);
162 // get rid of the current group
164 std::unique_ptr<Group> pFinishedGroup = std::move(m_groups.back());
166 if (pFinishedGroup->type != type) {
167 return SetError(ErrorMsg::UNMATCHED_GROUP_TAG);
171 // reset old settings
172 std::size_t lastIndent = (m_groups.empty() ? 0 : m_groups.back()->indent);
173 assert(m_curIndent >= lastIndent);
174 m_curIndent -= lastIndent;
176 // some global settings that we changed may have been overridden
177 // by a local setting we just popped, so we need to restore them
178 m_globalModifiedSettings.restore();
180 ClearModifiedSettings();
183 EmitterNodeType::value EmitterState::CurGroupNodeType() const {
184 if (m_groups.empty()) {
185 return EmitterNodeType::NoType;
188 return m_groups.back()->NodeType();
191 GroupType::value EmitterState::CurGroupType() const {
192 return m_groups.empty() ? GroupType::NoType : m_groups.back()->type;
195 FlowType::value EmitterState::CurGroupFlowType() const {
196 return m_groups.empty() ? FlowType::NoType : m_groups.back()->flowType;
199 std::size_t EmitterState::CurGroupIndent() const {
200 return m_groups.empty() ? 0 : m_groups.back()->indent;
203 std::size_t EmitterState::CurGroupChildCount() const {
204 return m_groups.empty() ? m_docCount : m_groups.back()->childCount;
207 bool EmitterState::CurGroupLongKey() const {
208 return m_groups.empty() ? false : m_groups.back()->longKey;
211 std::size_t EmitterState::LastIndent() const {
212 if (m_groups.size() <= 1) {
216 return m_curIndent - m_groups[m_groups.size() - 2]->indent;
219 void EmitterState::ClearModifiedSettings() { m_modifiedSettings.clear(); }
221 bool EmitterState::SetOutputCharset(EMITTER_MANIP value,
222 FmtScope::value scope) {
227 _Set(m_charset, value, scope);
234 bool EmitterState::SetStringFormat(EMITTER_MANIP value, FmtScope::value scope) {
240 _Set(m_strFmt, value, scope);
247 bool EmitterState::SetBoolFormat(EMITTER_MANIP value, FmtScope::value scope) {
252 _Set(m_boolFmt, value, scope);
259 bool EmitterState::SetBoolLengthFormat(EMITTER_MANIP value,
260 FmtScope::value scope) {
264 _Set(m_boolLengthFmt, value, scope);
271 bool EmitterState::SetBoolCaseFormat(EMITTER_MANIP value,
272 FmtScope::value scope) {
277 _Set(m_boolCaseFmt, value, scope);
284 bool EmitterState::SetNullFormat(EMITTER_MANIP value, FmtScope::value scope) {
288 _Set(m_nullFmt, value, scope);
295 bool EmitterState::SetIntFormat(EMITTER_MANIP value, FmtScope::value scope) {
300 _Set(m_intFmt, value, scope);
307 bool EmitterState::SetIndent(std::size_t value, FmtScope::value scope) {
311 _Set(m_indent, value, scope);
315 bool EmitterState::SetPreCommentIndent(std::size_t value,
316 FmtScope::value scope) {
320 _Set(m_preCommentIndent, value, scope);
324 bool EmitterState::SetPostCommentIndent(std::size_t value,
325 FmtScope::value scope) {
329 _Set(m_postCommentIndent, value, scope);
333 bool EmitterState::SetFlowType(GroupType::value groupType, EMITTER_MANIP value,
334 FmtScope::value scope) {
338 _Set(groupType == GroupType::Seq ? m_seqFmt : m_mapFmt, value, scope);
345 EMITTER_MANIP EmitterState::GetFlowType(GroupType::value groupType) const {
346 // force flow style if we're currently in a flow
347 if (CurGroupFlowType() == FlowType::Flow)
350 // otherwise, go with what's asked of us
351 return (groupType == GroupType::Seq ? m_seqFmt.get() : m_mapFmt.get());
354 bool EmitterState::SetMapKeyFormat(EMITTER_MANIP value, FmtScope::value scope) {
358 _Set(m_mapKeyFmt, value, scope);
365 bool EmitterState::SetFloatPrecision(std::size_t value, FmtScope::value scope) {
366 if (value > std::numeric_limits<float>::digits10 + 1)
368 _Set(m_floatPrecision, value, scope);
372 bool EmitterState::SetDoublePrecision(std::size_t value,
373 FmtScope::value scope) {
374 if (value > std::numeric_limits<double>::digits10 + 1)
376 _Set(m_doublePrecision, value, scope);