supernova: allocators - fix construct method
[supercollider.git] / external_libraries / yaml-cpp-0.2.6 / src / emitter.cpp
blobad21e2285aeeb172db852e5abe3cd2270257fbeb
1 #include "yaml-cpp/emitter.h"
2 #include "emitterstate.h"
3 #include "emitterutils.h"
4 #include "indentation.h"
5 #include "yaml-cpp/exceptions.h"
6 #include <sstream>
8 namespace YAML
9 {
10 Emitter::Emitter(): m_pState(new EmitterState)
14 Emitter::~Emitter()
18 const char *Emitter::c_str() const
20 return m_stream.str();
23 unsigned Emitter::size() const
25 return m_stream.pos();
28 // state checking
29 bool Emitter::good() const
31 return m_pState->good();
34 const std::string Emitter::GetLastError() const
36 return m_pState->GetLastError();
39 // global setters
40 bool Emitter::SetOutputCharset(EMITTER_MANIP value)
42 return m_pState->SetOutputCharset(value, GLOBAL);
45 bool Emitter::SetStringFormat(EMITTER_MANIP value)
47 return m_pState->SetStringFormat(value, GLOBAL);
50 bool Emitter::SetBoolFormat(EMITTER_MANIP value)
52 bool ok = false;
53 if(m_pState->SetBoolFormat(value, GLOBAL))
54 ok = true;
55 if(m_pState->SetBoolCaseFormat(value, GLOBAL))
56 ok = true;
57 if(m_pState->SetBoolLengthFormat(value, GLOBAL))
58 ok = true;
59 return ok;
62 bool Emitter::SetIntBase(EMITTER_MANIP value)
64 return m_pState->SetIntFormat(value, GLOBAL);
67 bool Emitter::SetSeqFormat(EMITTER_MANIP value)
69 return m_pState->SetFlowType(GT_SEQ, value, GLOBAL);
72 bool Emitter::SetMapFormat(EMITTER_MANIP value)
74 bool ok = false;
75 if(m_pState->SetFlowType(GT_MAP, value, GLOBAL))
76 ok = true;
77 if(m_pState->SetMapKeyFormat(value, GLOBAL))
78 ok = true;
79 return ok;
82 bool Emitter::SetIndent(unsigned n)
84 return m_pState->SetIndent(n, GLOBAL);
87 bool Emitter::SetPreCommentIndent(unsigned n)
89 return m_pState->SetPreCommentIndent(n, GLOBAL);
92 bool Emitter::SetPostCommentIndent(unsigned n)
94 return m_pState->SetPostCommentIndent(n, GLOBAL);
97 // SetLocalValue
98 // . Either start/end a group, or set a modifier locally
99 Emitter& Emitter::SetLocalValue(EMITTER_MANIP value)
101 if(!good())
102 return *this;
104 switch(value) {
105 case BeginDoc:
106 EmitBeginDoc();
107 break;
108 case EndDoc:
109 EmitEndDoc();
110 break;
111 case BeginSeq:
112 EmitBeginSeq();
113 break;
114 case EndSeq:
115 EmitEndSeq();
116 break;
117 case BeginMap:
118 EmitBeginMap();
119 break;
120 case EndMap:
121 EmitEndMap();
122 break;
123 case Key:
124 EmitKey();
125 break;
126 case Value:
127 EmitValue();
128 break;
129 case TagByKind:
130 EmitKindTag();
131 break;
132 case Newline:
133 EmitNewline();
134 break;
135 default:
136 m_pState->SetLocalValue(value);
137 break;
139 return *this;
142 Emitter& Emitter::SetLocalIndent(const _Indent& indent)
144 m_pState->SetIndent(indent.value, LOCAL);
145 return *this;
148 // GotoNextPreAtomicState
149 // . Runs the state machine, emitting if necessary, and returns 'true' if done (i.e., ready to emit an atom)
150 bool Emitter::GotoNextPreAtomicState()
152 if(!good())
153 return true;
155 unsigned curIndent = m_pState->GetCurIndent();
157 EMITTER_STATE curState = m_pState->GetCurState();
158 switch(curState) {
159 // document-level
160 case ES_WAITING_FOR_DOC:
161 m_pState->SwitchState(ES_WRITING_DOC);
162 return true;
163 case ES_WRITING_DOC:
164 return true;
165 case ES_DONE_WITH_DOC:
166 EmitBeginDoc();
167 return false;
169 // block sequence
170 case ES_WAITING_FOR_BLOCK_SEQ_ENTRY:
171 m_stream << IndentTo(curIndent) << "-";
172 m_pState->RequireSoftSeparation();
173 m_pState->SwitchState(ES_WRITING_BLOCK_SEQ_ENTRY);
174 return true;
175 case ES_WRITING_BLOCK_SEQ_ENTRY:
176 return true;
177 case ES_DONE_WITH_BLOCK_SEQ_ENTRY:
178 m_stream << '\n';
179 m_pState->SwitchState(ES_WAITING_FOR_BLOCK_SEQ_ENTRY);
180 return false;
182 // flow sequence
183 case ES_WAITING_FOR_FLOW_SEQ_ENTRY:
184 m_pState->SwitchState(ES_WRITING_FLOW_SEQ_ENTRY);
185 return true;
186 case ES_WRITING_FLOW_SEQ_ENTRY:
187 return true;
188 case ES_DONE_WITH_FLOW_SEQ_ENTRY:
189 m_stream << ',';
190 m_pState->RequireSoftSeparation();
191 m_pState->SwitchState(ES_WAITING_FOR_FLOW_SEQ_ENTRY);
192 return false;
194 // block map
195 case ES_WAITING_FOR_BLOCK_MAP_ENTRY:
196 m_pState->SetError(ErrorMsg::EXPECTED_KEY_TOKEN);
197 return true;
198 case ES_WAITING_FOR_BLOCK_MAP_KEY:
199 if(m_pState->CurrentlyInLongKey()) {
200 m_stream << IndentTo(curIndent) << '?';
201 m_pState->RequireSoftSeparation();
203 m_pState->SwitchState(ES_WRITING_BLOCK_MAP_KEY);
204 return true;
205 case ES_WRITING_BLOCK_MAP_KEY:
206 return true;
207 case ES_DONE_WITH_BLOCK_MAP_KEY:
208 m_pState->SetError(ErrorMsg::EXPECTED_VALUE_TOKEN);
209 return true;
210 case ES_WAITING_FOR_BLOCK_MAP_VALUE:
211 m_pState->SwitchState(ES_WRITING_BLOCK_MAP_VALUE);
212 return true;
213 case ES_WRITING_BLOCK_MAP_VALUE:
214 return true;
215 case ES_DONE_WITH_BLOCK_MAP_VALUE:
216 m_pState->SetError(ErrorMsg::EXPECTED_KEY_TOKEN);
217 return true;
219 // flow map
220 case ES_WAITING_FOR_FLOW_MAP_ENTRY:
221 m_pState->SetError(ErrorMsg::EXPECTED_KEY_TOKEN);
222 return true;
223 case ES_WAITING_FOR_FLOW_MAP_KEY:
224 m_pState->SwitchState(ES_WRITING_FLOW_MAP_KEY);
225 if(m_pState->CurrentlyInLongKey()) {
226 EmitSeparationIfNecessary();
227 m_stream << '?';
228 m_pState->RequireSoftSeparation();
230 return true;
231 case ES_WRITING_FLOW_MAP_KEY:
232 return true;
233 case ES_DONE_WITH_FLOW_MAP_KEY:
234 m_pState->SetError(ErrorMsg::EXPECTED_VALUE_TOKEN);
235 return true;
236 case ES_WAITING_FOR_FLOW_MAP_VALUE:
237 m_stream << ':';
238 m_pState->RequireSoftSeparation();
239 m_pState->SwitchState(ES_WRITING_FLOW_MAP_VALUE);
240 return true;
241 case ES_WRITING_FLOW_MAP_VALUE:
242 return true;
243 case ES_DONE_WITH_FLOW_MAP_VALUE:
244 m_pState->SetError(ErrorMsg::EXPECTED_KEY_TOKEN);
245 return true;
246 default:
247 assert(false);
250 assert(false);
251 return true;
254 // PreAtomicWrite
255 // . Depending on the emitter state, write to the stream to get it
256 // in position to do an atomic write (e.g., scalar, sequence, or map)
257 void Emitter::PreAtomicWrite()
259 if(!good())
260 return;
262 while(!GotoNextPreAtomicState())
266 // PostAtomicWrite
267 // . Clean up
268 void Emitter::PostAtomicWrite()
270 if(!good())
271 return;
273 EMITTER_STATE curState = m_pState->GetCurState();
274 switch(curState) {
275 // document-level
276 case ES_WRITING_DOC:
277 m_pState->SwitchState(ES_DONE_WITH_DOC);
278 break;
280 // block seq
281 case ES_WRITING_BLOCK_SEQ_ENTRY:
282 m_pState->SwitchState(ES_DONE_WITH_BLOCK_SEQ_ENTRY);
283 break;
285 // flow seq
286 case ES_WRITING_FLOW_SEQ_ENTRY:
287 m_pState->SwitchState(ES_DONE_WITH_FLOW_SEQ_ENTRY);
288 break;
290 // block map
291 case ES_WRITING_BLOCK_MAP_KEY:
292 if(!m_pState->CurrentlyInLongKey()) {
293 m_stream << ':';
294 m_pState->RequireSoftSeparation();
296 m_pState->SwitchState(ES_DONE_WITH_BLOCK_MAP_KEY);
297 break;
298 case ES_WRITING_BLOCK_MAP_VALUE:
299 m_pState->SwitchState(ES_DONE_WITH_BLOCK_MAP_VALUE);
300 break;
302 // flow map
303 case ES_WRITING_FLOW_MAP_KEY:
304 m_pState->SwitchState(ES_DONE_WITH_FLOW_MAP_KEY);
305 break;
306 case ES_WRITING_FLOW_MAP_VALUE:
307 m_pState->SwitchState(ES_DONE_WITH_FLOW_MAP_VALUE);
308 break;
309 default:
310 assert(false);
313 m_pState->ClearModifiedSettings();
316 // EmitSeparationIfNecessary
317 void Emitter::EmitSeparationIfNecessary()
319 if(!good())
320 return;
322 if(m_pState->RequiresSoftSeparation())
323 m_stream << ' ';
324 else if(m_pState->RequiresHardSeparation())
325 m_stream << '\n';
326 m_pState->UnsetSeparation();
329 // EmitBeginDoc
330 void Emitter::EmitBeginDoc()
332 if(!good())
333 return;
335 EMITTER_STATE curState = m_pState->GetCurState();
336 if(curState != ES_WAITING_FOR_DOC && curState != ES_WRITING_DOC && curState != ES_DONE_WITH_DOC) {
337 m_pState->SetError("Unexpected begin document");
338 return;
341 if(curState == ES_WRITING_DOC || curState == ES_DONE_WITH_DOC)
342 m_stream << '\n';
343 m_stream << "---\n";
345 m_pState->UnsetSeparation();
346 m_pState->SwitchState(ES_WAITING_FOR_DOC);
349 // EmitEndDoc
350 void Emitter::EmitEndDoc()
352 if(!good())
353 return;
356 EMITTER_STATE curState = m_pState->GetCurState();
357 if(curState != ES_WAITING_FOR_DOC && curState != ES_WRITING_DOC && curState != ES_DONE_WITH_DOC) {
358 m_pState->SetError("Unexpected end document");
359 return;
362 if(curState == ES_WRITING_DOC || curState == ES_DONE_WITH_DOC)
363 m_stream << '\n';
364 m_stream << "...\n";
366 m_pState->UnsetSeparation();
367 m_pState->SwitchState(ES_WAITING_FOR_DOC);
370 // EmitBeginSeq
371 void Emitter::EmitBeginSeq()
373 if(!good())
374 return;
376 // must have a long key if we're emitting a sequence
377 m_pState->StartLongKey();
379 PreAtomicWrite();
381 EMITTER_STATE curState = m_pState->GetCurState();
382 EMITTER_MANIP flowType = m_pState->GetFlowType(GT_SEQ);
383 if(flowType == Block) {
384 if(curState == ES_WRITING_BLOCK_SEQ_ENTRY ||
385 curState == ES_WRITING_BLOCK_MAP_KEY || curState == ES_WRITING_BLOCK_MAP_VALUE ||
386 curState == ES_WRITING_DOC
388 if(m_pState->RequiresHardSeparation() || curState != ES_WRITING_DOC) {
389 m_stream << "\n";
390 m_pState->UnsetSeparation();
393 m_pState->PushState(ES_WAITING_FOR_BLOCK_SEQ_ENTRY);
394 } else if(flowType == Flow) {
395 EmitSeparationIfNecessary();
396 m_stream << "[";
397 m_pState->PushState(ES_WAITING_FOR_FLOW_SEQ_ENTRY);
398 } else
399 assert(false);
401 m_pState->BeginGroup(GT_SEQ);
404 // EmitEndSeq
405 void Emitter::EmitEndSeq()
407 if(!good())
408 return;
410 if(m_pState->GetCurGroupType() != GT_SEQ)
411 return m_pState->SetError(ErrorMsg::UNEXPECTED_END_SEQ);
413 EMITTER_STATE curState = m_pState->GetCurState();
414 FLOW_TYPE flowType = m_pState->GetCurGroupFlowType();
415 if(flowType == FT_BLOCK) {
416 // Note: block sequences are *not* allowed to be empty, but we convert it
417 // to a flow sequence if it is
418 assert(curState == ES_DONE_WITH_BLOCK_SEQ_ENTRY || curState == ES_WAITING_FOR_BLOCK_SEQ_ENTRY);
419 if(curState == ES_WAITING_FOR_BLOCK_SEQ_ENTRY) {
420 // Note: only one of these will actually output anything for a given situation
421 EmitSeparationIfNecessary();
422 unsigned curIndent = m_pState->GetCurIndent();
423 m_stream << IndentTo(curIndent);
425 m_stream << "[]";
427 } else if(flowType == FT_FLOW) {
428 // Note: flow sequences are allowed to be empty
429 assert(curState == ES_DONE_WITH_FLOW_SEQ_ENTRY || curState == ES_WAITING_FOR_FLOW_SEQ_ENTRY);
430 m_stream << "]";
431 } else
432 assert(false);
434 m_pState->PopState();
435 m_pState->EndGroup(GT_SEQ);
437 PostAtomicWrite();
440 // EmitBeginMap
441 void Emitter::EmitBeginMap()
443 if(!good())
444 return;
446 // must have a long key if we're emitting a map
447 m_pState->StartLongKey();
449 PreAtomicWrite();
451 EMITTER_STATE curState = m_pState->GetCurState();
452 EMITTER_MANIP flowType = m_pState->GetFlowType(GT_MAP);
453 if(flowType == Block) {
454 if(curState == ES_WRITING_BLOCK_SEQ_ENTRY ||
455 curState == ES_WRITING_BLOCK_MAP_KEY || curState == ES_WRITING_BLOCK_MAP_VALUE ||
456 curState == ES_WRITING_DOC
458 if(m_pState->RequiresHardSeparation() || (curState != ES_WRITING_DOC && curState != ES_WRITING_BLOCK_SEQ_ENTRY)) {
459 m_stream << "\n";
460 m_pState->UnsetSeparation();
463 m_pState->PushState(ES_WAITING_FOR_BLOCK_MAP_ENTRY);
464 } else if(flowType == Flow) {
465 EmitSeparationIfNecessary();
466 m_stream << "{";
467 m_pState->PushState(ES_WAITING_FOR_FLOW_MAP_ENTRY);
468 } else
469 assert(false);
471 m_pState->BeginGroup(GT_MAP);
474 // EmitEndMap
475 void Emitter::EmitEndMap()
477 if(!good())
478 return;
480 if(m_pState->GetCurGroupType() != GT_MAP)
481 return m_pState->SetError(ErrorMsg::UNEXPECTED_END_MAP);
483 EMITTER_STATE curState = m_pState->GetCurState();
484 FLOW_TYPE flowType = m_pState->GetCurGroupFlowType();
485 if(flowType == FT_BLOCK) {
486 // Note: block sequences are *not* allowed to be empty, but we convert it
487 // to a flow sequence if it is
488 assert(curState == ES_DONE_WITH_BLOCK_MAP_VALUE || curState == ES_WAITING_FOR_BLOCK_MAP_ENTRY);
489 if(curState == ES_WAITING_FOR_BLOCK_MAP_ENTRY) {
490 // Note: only one of these will actually output anything for a given situation
491 EmitSeparationIfNecessary();
492 unsigned curIndent = m_pState->GetCurIndent();
493 m_stream << IndentTo(curIndent);
494 m_stream << "{}";
496 } else if(flowType == FT_FLOW) {
497 // Note: flow maps are allowed to be empty
498 assert(curState == ES_DONE_WITH_FLOW_MAP_VALUE || curState == ES_WAITING_FOR_FLOW_MAP_ENTRY);
499 m_stream << "}";
500 } else
501 assert(false);
503 m_pState->PopState();
504 m_pState->EndGroup(GT_MAP);
506 PostAtomicWrite();
509 // EmitKey
510 void Emitter::EmitKey()
512 if(!good())
513 return;
515 EMITTER_STATE curState = m_pState->GetCurState();
516 FLOW_TYPE flowType = m_pState->GetCurGroupFlowType();
517 if(curState != ES_WAITING_FOR_BLOCK_MAP_ENTRY && curState != ES_DONE_WITH_BLOCK_MAP_VALUE
518 && curState != ES_WAITING_FOR_FLOW_MAP_ENTRY && curState != ES_DONE_WITH_FLOW_MAP_VALUE)
519 return m_pState->SetError(ErrorMsg::UNEXPECTED_KEY_TOKEN);
521 if(flowType == FT_BLOCK) {
522 if(curState == ES_DONE_WITH_BLOCK_MAP_VALUE)
523 m_stream << '\n';
524 unsigned curIndent = m_pState->GetCurIndent();
525 m_stream << IndentTo(curIndent);
526 m_pState->UnsetSeparation();
527 m_pState->SwitchState(ES_WAITING_FOR_BLOCK_MAP_KEY);
528 } else if(flowType == FT_FLOW) {
529 if(curState == ES_DONE_WITH_FLOW_MAP_VALUE) {
530 m_stream << ',';
531 m_pState->RequireSoftSeparation();
533 m_pState->SwitchState(ES_WAITING_FOR_FLOW_MAP_KEY);
534 } else
535 assert(false);
537 if(m_pState->GetMapKeyFormat() == LongKey)
538 m_pState->StartLongKey();
539 else if(m_pState->GetMapKeyFormat() == Auto)
540 m_pState->StartSimpleKey();
541 else
542 assert(false);
545 // EmitValue
546 void Emitter::EmitValue()
548 if(!good())
549 return;
551 EMITTER_STATE curState = m_pState->GetCurState();
552 FLOW_TYPE flowType = m_pState->GetCurGroupFlowType();
553 if(curState != ES_DONE_WITH_BLOCK_MAP_KEY && curState != ES_DONE_WITH_FLOW_MAP_KEY)
554 return m_pState->SetError(ErrorMsg::UNEXPECTED_VALUE_TOKEN);
556 if(flowType == FT_BLOCK) {
557 if(m_pState->CurrentlyInLongKey()) {
558 m_stream << '\n';
559 m_stream << IndentTo(m_pState->GetCurIndent());
560 m_stream << ':';
561 m_pState->RequireSoftSeparation();
563 m_pState->SwitchState(ES_WAITING_FOR_BLOCK_MAP_VALUE);
564 } else if(flowType == FT_FLOW) {
565 m_pState->SwitchState(ES_WAITING_FOR_FLOW_MAP_VALUE);
566 } else
567 assert(false);
570 // EmitNewline
571 void Emitter::EmitNewline()
573 if(!good())
574 return;
576 if(CanEmitNewline()) {
577 m_stream << '\n';
578 m_pState->UnsetSeparation();
582 bool Emitter::CanEmitNewline() const
584 FLOW_TYPE flowType = m_pState->GetCurGroupFlowType();
585 if(flowType == FT_BLOCK && m_pState->CurrentlyInLongKey())
586 return true;
588 EMITTER_STATE curState = m_pState->GetCurState();
589 return curState != ES_DONE_WITH_BLOCK_MAP_KEY && curState != ES_WAITING_FOR_BLOCK_MAP_VALUE && curState != ES_WRITING_BLOCK_MAP_VALUE;
592 // *******************************************************************************************
593 // overloads of Write
595 Emitter& Emitter::Write(const std::string& str)
597 if(!good())
598 return *this;
600 // literal scalars must use long keys
601 if(m_pState->GetStringFormat() == Literal && m_pState->GetCurGroupFlowType() != FT_FLOW)
602 m_pState->StartLongKey();
604 PreAtomicWrite();
605 EmitSeparationIfNecessary();
607 bool escapeNonAscii = m_pState->GetOutputCharset() == EscapeNonAscii;
608 EMITTER_MANIP strFmt = m_pState->GetStringFormat();
609 FLOW_TYPE flowType = m_pState->GetCurGroupFlowType();
610 unsigned curIndent = m_pState->GetCurIndent();
612 switch(strFmt) {
613 case Auto:
614 Utils::WriteString(m_stream, str, flowType == FT_FLOW, escapeNonAscii);
615 break;
616 case SingleQuoted:
617 if(!Utils::WriteSingleQuotedString(m_stream, str)) {
618 m_pState->SetError(ErrorMsg::SINGLE_QUOTED_CHAR);
619 return *this;
621 break;
622 case DoubleQuoted:
623 Utils::WriteDoubleQuotedString(m_stream, str, escapeNonAscii);
624 break;
625 case Literal:
626 if(flowType == FT_FLOW)
627 Utils::WriteString(m_stream, str, flowType == FT_FLOW, escapeNonAscii);
628 else
629 Utils::WriteLiteralString(m_stream, str, curIndent + m_pState->GetIndent());
630 break;
631 default:
632 assert(false);
635 PostAtomicWrite();
636 return *this;
639 void Emitter::PreWriteIntegralType(std::stringstream& str)
641 PreAtomicWrite();
642 EmitSeparationIfNecessary();
644 EMITTER_MANIP intFmt = m_pState->GetIntFormat();
645 switch(intFmt) {
646 case Dec:
647 str << std::dec;
648 break;
649 case Hex:
650 str << std::hex;
651 break;
652 case Oct:
653 str << std::oct;
654 break;
655 default:
656 assert(false);
660 void Emitter::PreWriteStreamable(std::stringstream& str)
662 PreAtomicWrite();
663 EmitSeparationIfNecessary();
664 str.precision(15);
667 void Emitter::PostWriteIntegralType(const std::stringstream& str)
669 m_stream << str.str();
670 PostAtomicWrite();
673 void Emitter::PostWriteStreamable(const std::stringstream& str)
675 m_stream << str.str();
676 PostAtomicWrite();
679 const char *Emitter::ComputeFullBoolName(bool b) const
681 const EMITTER_MANIP mainFmt = (m_pState->GetBoolLengthFormat() == ShortBool ? YesNoBool : m_pState->GetBoolFormat());
682 const EMITTER_MANIP caseFmt = m_pState->GetBoolCaseFormat();
683 switch(mainFmt) {
684 case YesNoBool:
685 switch(caseFmt) {
686 case UpperCase: return b ? "YES" : "NO";
687 case CamelCase: return b ? "Yes" : "No";
688 case LowerCase: return b ? "yes" : "no";
689 default: break;
691 break;
692 case OnOffBool:
693 switch(caseFmt) {
694 case UpperCase: return b ? "ON" : "OFF";
695 case CamelCase: return b ? "On" : "Off";
696 case LowerCase: return b ? "on" : "off";
697 default: break;
699 break;
700 case TrueFalseBool:
701 switch(caseFmt) {
702 case UpperCase: return b ? "TRUE" : "FALSE";
703 case CamelCase: return b ? "True" : "False";
704 case LowerCase: return b ? "true" : "false";
705 default: break;
707 break;
708 default:
709 break;
711 return b ? "y" : "n"; // should never get here, but it can't hurt to give these answers
714 Emitter& Emitter::Write(bool b)
716 if(!good())
717 return *this;
719 PreAtomicWrite();
720 EmitSeparationIfNecessary();
722 const char *name = ComputeFullBoolName(b);
723 if(m_pState->GetBoolLengthFormat() == ShortBool)
724 m_stream << name[0];
725 else
726 m_stream << name;
728 PostAtomicWrite();
729 return *this;
732 Emitter& Emitter::Write(const _Alias& alias)
734 if(!good())
735 return *this;
737 PreAtomicWrite();
738 EmitSeparationIfNecessary();
739 if(!Utils::WriteAlias(m_stream, alias.content)) {
740 m_pState->SetError(ErrorMsg::INVALID_ALIAS);
741 return *this;
743 PostAtomicWrite();
744 return *this;
747 Emitter& Emitter::Write(const _Anchor& anchor)
749 if(!good())
750 return *this;
752 PreAtomicWrite();
753 EmitSeparationIfNecessary();
754 if(!Utils::WriteAnchor(m_stream, anchor.content)) {
755 m_pState->SetError(ErrorMsg::INVALID_ANCHOR);
756 return *this;
758 m_pState->RequireHardSeparation();
759 // Note: no PostAtomicWrite() because we need another value for this node
760 return *this;
763 Emitter& Emitter::Write(const _Tag& tag)
765 if(!good())
766 return *this;
768 PreAtomicWrite();
769 EmitSeparationIfNecessary();
771 bool success = false;
772 if(tag.type == _Tag::Type::Verbatim)
773 success = Utils::WriteTag(m_stream, tag.content, true);
774 else if(tag.type == _Tag::Type::PrimaryHandle)
775 success = Utils::WriteTag(m_stream, tag.content, false);
776 else
777 success = Utils::WriteTagWithPrefix(m_stream, tag.prefix, tag.content);
779 if(!success) {
780 m_pState->SetError(ErrorMsg::INVALID_TAG);
781 return *this;
784 m_pState->RequireHardSeparation();
785 // Note: no PostAtomicWrite() because we need another value for this node
786 return *this;
789 void Emitter::EmitKindTag()
791 Write(LocalTag(""));
794 Emitter& Emitter::Write(const _Comment& comment)
796 if(!good())
797 return *this;
799 m_stream << Indentation(m_pState->GetPreCommentIndent());
800 Utils::WriteComment(m_stream, comment.content, m_pState->GetPostCommentIndent());
801 return *this;
804 Emitter& Emitter::Write(const _Null& /*null*/)
806 if(!good())
807 return *this;
809 PreAtomicWrite();
810 EmitSeparationIfNecessary();
811 m_stream << "~";
812 PostAtomicWrite();
813 return *this;
816 Emitter& Emitter::Write(const _Binary& binary)
818 Write(SecondaryTag("binary"));
820 if(!good())
821 return *this;
823 PreAtomicWrite();
824 EmitSeparationIfNecessary();
825 Utils::WriteBinary(m_stream, binary.data, binary.size);
826 PostAtomicWrite();
827 return *this;