scide: implement selectionLength for openDocument
[supercollider.git] / external_libraries / yaml-cpp-0.3.0 / src / emitter.cpp
blob91f48da7a524120093901e5a05f0219ccd36a2bd
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 bool Emitter::SetFloatPrecision(unsigned n)
99 return m_pState->SetFloatPrecision(n, GLOBAL);
102 bool Emitter::SetDoublePrecision(unsigned n)
104 return m_pState->SetDoublePrecision(n, GLOBAL);
107 // SetLocalValue
108 // . Either start/end a group, or set a modifier locally
109 Emitter& Emitter::SetLocalValue(EMITTER_MANIP value)
111 if(!good())
112 return *this;
114 switch(value) {
115 case BeginDoc:
116 EmitBeginDoc();
117 break;
118 case EndDoc:
119 EmitEndDoc();
120 break;
121 case BeginSeq:
122 EmitBeginSeq();
123 break;
124 case EndSeq:
125 EmitEndSeq();
126 break;
127 case BeginMap:
128 EmitBeginMap();
129 break;
130 case EndMap:
131 EmitEndMap();
132 break;
133 case Key:
134 EmitKey();
135 break;
136 case Value:
137 EmitValue();
138 break;
139 case TagByKind:
140 EmitKindTag();
141 break;
142 case Newline:
143 EmitNewline();
144 break;
145 default:
146 m_pState->SetLocalValue(value);
147 break;
149 return *this;
152 Emitter& Emitter::SetLocalIndent(const _Indent& indent)
154 m_pState->SetIndent(indent.value, LOCAL);
155 return *this;
158 Emitter& Emitter::SetLocalPrecision(const _Precision& precision)
160 if(precision.floatPrecision >= 0)
161 m_pState->SetFloatPrecision(precision.floatPrecision, LOCAL);
162 if(precision.doublePrecision >= 0)
163 m_pState->SetDoublePrecision(precision.doublePrecision, LOCAL);
164 return *this;
167 // GotoNextPreAtomicState
168 // . Runs the state machine, emitting if necessary, and returns 'true' if done (i.e., ready to emit an atom)
169 bool Emitter::GotoNextPreAtomicState()
171 if(!good())
172 return true;
174 unsigned curIndent = m_pState->GetCurIndent();
176 EMITTER_STATE curState = m_pState->GetCurState();
177 switch(curState) {
178 // document-level
179 case ES_WAITING_FOR_DOC:
180 m_pState->SwitchState(ES_WRITING_DOC);
181 return true;
182 case ES_WRITING_DOC:
183 return true;
184 case ES_DONE_WITH_DOC:
185 EmitBeginDoc();
186 return false;
188 // block sequence
189 case ES_WAITING_FOR_BLOCK_SEQ_ENTRY:
190 m_stream << IndentTo(curIndent) << "-";
191 m_pState->RequireSoftSeparation();
192 m_pState->SwitchState(ES_WRITING_BLOCK_SEQ_ENTRY);
193 return true;
194 case ES_WRITING_BLOCK_SEQ_ENTRY:
195 return true;
196 case ES_DONE_WITH_BLOCK_SEQ_ENTRY:
197 m_stream << '\n';
198 m_pState->SwitchState(ES_WAITING_FOR_BLOCK_SEQ_ENTRY);
199 return false;
201 // flow sequence
202 case ES_WAITING_FOR_FLOW_SEQ_ENTRY:
203 m_pState->SwitchState(ES_WRITING_FLOW_SEQ_ENTRY);
204 return true;
205 case ES_WRITING_FLOW_SEQ_ENTRY:
206 return true;
207 case ES_DONE_WITH_FLOW_SEQ_ENTRY:
208 EmitSeparationIfNecessary();
209 m_stream << ',';
210 m_pState->RequireSoftSeparation();
211 m_pState->SwitchState(ES_WAITING_FOR_FLOW_SEQ_ENTRY);
212 return false;
214 // block map
215 case ES_WAITING_FOR_BLOCK_MAP_ENTRY:
216 m_pState->SetError(ErrorMsg::EXPECTED_KEY_TOKEN);
217 return true;
218 case ES_WAITING_FOR_BLOCK_MAP_KEY:
219 if(m_pState->CurrentlyInLongKey()) {
220 m_stream << IndentTo(curIndent) << '?';
221 m_pState->RequireSoftSeparation();
223 m_pState->SwitchState(ES_WRITING_BLOCK_MAP_KEY);
224 return true;
225 case ES_WRITING_BLOCK_MAP_KEY:
226 return true;
227 case ES_DONE_WITH_BLOCK_MAP_KEY:
228 m_pState->SetError(ErrorMsg::EXPECTED_VALUE_TOKEN);
229 return true;
230 case ES_WAITING_FOR_BLOCK_MAP_VALUE:
231 m_pState->SwitchState(ES_WRITING_BLOCK_MAP_VALUE);
232 return true;
233 case ES_WRITING_BLOCK_MAP_VALUE:
234 return true;
235 case ES_DONE_WITH_BLOCK_MAP_VALUE:
236 m_pState->SetError(ErrorMsg::EXPECTED_KEY_TOKEN);
237 return true;
239 // flow map
240 case ES_WAITING_FOR_FLOW_MAP_ENTRY:
241 m_pState->SetError(ErrorMsg::EXPECTED_KEY_TOKEN);
242 return true;
243 case ES_WAITING_FOR_FLOW_MAP_KEY:
244 EmitSeparationIfNecessary();
245 m_pState->SwitchState(ES_WRITING_FLOW_MAP_KEY);
246 if(m_pState->CurrentlyInLongKey()) {
247 m_stream << '?';
248 m_pState->RequireSoftSeparation();
250 return true;
251 case ES_WRITING_FLOW_MAP_KEY:
252 return true;
253 case ES_DONE_WITH_FLOW_MAP_KEY:
254 m_pState->SetError(ErrorMsg::EXPECTED_VALUE_TOKEN);
255 return true;
256 case ES_WAITING_FOR_FLOW_MAP_VALUE:
257 EmitSeparationIfNecessary();
258 m_stream << ':';
259 m_pState->RequireSoftSeparation();
260 m_pState->SwitchState(ES_WRITING_FLOW_MAP_VALUE);
261 return true;
262 case ES_WRITING_FLOW_MAP_VALUE:
263 return true;
264 case ES_DONE_WITH_FLOW_MAP_VALUE:
265 m_pState->SetError(ErrorMsg::EXPECTED_KEY_TOKEN);
266 return true;
267 default:
268 assert(false);
271 assert(false);
272 return true;
275 // PreAtomicWrite
276 // . Depending on the emitter state, write to the stream to get it
277 // in position to do an atomic write (e.g., scalar, sequence, or map)
278 void Emitter::PreAtomicWrite()
280 if(!good())
281 return;
283 while(!GotoNextPreAtomicState())
287 // PostAtomicWrite
288 // . Clean up
289 void Emitter::PostAtomicWrite()
291 if(!good())
292 return;
294 EMITTER_STATE curState = m_pState->GetCurState();
295 switch(curState) {
296 // document-level
297 case ES_WRITING_DOC:
298 m_pState->SwitchState(ES_DONE_WITH_DOC);
299 break;
301 // block seq
302 case ES_WRITING_BLOCK_SEQ_ENTRY:
303 m_pState->SwitchState(ES_DONE_WITH_BLOCK_SEQ_ENTRY);
304 break;
306 // flow seq
307 case ES_WRITING_FLOW_SEQ_ENTRY:
308 m_pState->SwitchState(ES_DONE_WITH_FLOW_SEQ_ENTRY);
309 break;
311 // block map
312 case ES_WRITING_BLOCK_MAP_KEY:
313 if(!m_pState->CurrentlyInLongKey()) {
314 m_stream << ':';
315 m_pState->RequireSoftSeparation();
317 m_pState->SwitchState(ES_DONE_WITH_BLOCK_MAP_KEY);
318 break;
319 case ES_WRITING_BLOCK_MAP_VALUE:
320 m_pState->SwitchState(ES_DONE_WITH_BLOCK_MAP_VALUE);
321 break;
323 // flow map
324 case ES_WRITING_FLOW_MAP_KEY:
325 m_pState->SwitchState(ES_DONE_WITH_FLOW_MAP_KEY);
326 break;
327 case ES_WRITING_FLOW_MAP_VALUE:
328 m_pState->SwitchState(ES_DONE_WITH_FLOW_MAP_VALUE);
329 break;
330 default:
331 assert(false);
334 m_pState->ClearModifiedSettings();
337 // EmitSeparationIfNecessary
338 void Emitter::EmitSeparationIfNecessary()
340 if(!good())
341 return;
343 if(m_pState->RequiresSoftSeparation())
344 m_stream << ' ';
345 else if(m_pState->RequiresHardSeparation())
346 m_stream << '\n';
347 m_pState->UnsetSeparation();
350 // EmitBeginDoc
351 void Emitter::EmitBeginDoc()
353 if(!good())
354 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 begin 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 // EmitEndDoc
371 void Emitter::EmitEndDoc()
373 if(!good())
374 return;
377 EMITTER_STATE curState = m_pState->GetCurState();
378 if(curState != ES_WAITING_FOR_DOC && curState != ES_WRITING_DOC && curState != ES_DONE_WITH_DOC) {
379 m_pState->SetError("Unexpected end document");
380 return;
383 if(curState == ES_WRITING_DOC || curState == ES_DONE_WITH_DOC)
384 m_stream << '\n';
385 m_stream << "...\n";
387 m_pState->UnsetSeparation();
388 m_pState->SwitchState(ES_WAITING_FOR_DOC);
391 // EmitBeginSeq
392 void Emitter::EmitBeginSeq()
394 if(!good())
395 return;
397 // must have a long key if we're emitting a sequence
398 m_pState->StartLongKey();
400 PreAtomicWrite();
402 EMITTER_STATE curState = m_pState->GetCurState();
403 EMITTER_MANIP flowType = m_pState->GetFlowType(GT_SEQ);
404 if(flowType == Block) {
405 if(curState == ES_WRITING_BLOCK_SEQ_ENTRY ||
406 curState == ES_WRITING_BLOCK_MAP_KEY || curState == ES_WRITING_BLOCK_MAP_VALUE ||
407 curState == ES_WRITING_DOC
409 if(m_pState->RequiresHardSeparation() || curState != ES_WRITING_DOC) {
410 m_stream << "\n";
411 m_pState->UnsetSeparation();
414 m_pState->PushState(ES_WAITING_FOR_BLOCK_SEQ_ENTRY);
415 } else if(flowType == Flow) {
416 EmitSeparationIfNecessary();
417 m_stream << "[";
418 m_pState->PushState(ES_WAITING_FOR_FLOW_SEQ_ENTRY);
419 } else
420 assert(false);
422 m_pState->BeginGroup(GT_SEQ);
425 // EmitEndSeq
426 void Emitter::EmitEndSeq()
428 if(!good())
429 return;
431 if(m_pState->GetCurGroupType() != GT_SEQ)
432 return m_pState->SetError(ErrorMsg::UNEXPECTED_END_SEQ);
434 EMITTER_STATE curState = m_pState->GetCurState();
435 FLOW_TYPE flowType = m_pState->GetCurGroupFlowType();
436 if(flowType == FT_BLOCK) {
437 // Note: block sequences are *not* allowed to be empty, but we convert it
438 // to a flow sequence if it is
439 assert(curState == ES_DONE_WITH_BLOCK_SEQ_ENTRY || curState == ES_WAITING_FOR_BLOCK_SEQ_ENTRY);
440 if(curState == ES_WAITING_FOR_BLOCK_SEQ_ENTRY) {
441 // Note: only one of these will actually output anything for a given situation
442 EmitSeparationIfNecessary();
443 unsigned curIndent = m_pState->GetCurIndent();
444 m_stream << IndentTo(curIndent);
446 m_stream << "[]";
448 } else if(flowType == FT_FLOW) {
449 // Note: flow sequences are allowed to be empty
450 assert(curState == ES_DONE_WITH_FLOW_SEQ_ENTRY || curState == ES_WAITING_FOR_FLOW_SEQ_ENTRY);
451 m_stream << "]";
452 } else
453 assert(false);
455 m_pState->PopState();
456 m_pState->EndGroup(GT_SEQ);
458 PostAtomicWrite();
461 // EmitBeginMap
462 void Emitter::EmitBeginMap()
464 if(!good())
465 return;
467 // must have a long key if we're emitting a map
468 m_pState->StartLongKey();
470 PreAtomicWrite();
472 EMITTER_STATE curState = m_pState->GetCurState();
473 EMITTER_MANIP flowType = m_pState->GetFlowType(GT_MAP);
474 if(flowType == Block) {
475 if(curState == ES_WRITING_BLOCK_SEQ_ENTRY ||
476 curState == ES_WRITING_BLOCK_MAP_KEY || curState == ES_WRITING_BLOCK_MAP_VALUE ||
477 curState == ES_WRITING_DOC
479 if(m_pState->RequiresHardSeparation() || (curState != ES_WRITING_DOC && curState != ES_WRITING_BLOCK_SEQ_ENTRY)) {
480 m_stream << "\n";
481 m_pState->UnsetSeparation();
484 m_pState->PushState(ES_WAITING_FOR_BLOCK_MAP_ENTRY);
485 } else if(flowType == Flow) {
486 EmitSeparationIfNecessary();
487 m_stream << "{";
488 m_pState->PushState(ES_WAITING_FOR_FLOW_MAP_ENTRY);
489 } else
490 assert(false);
492 m_pState->BeginGroup(GT_MAP);
495 // EmitEndMap
496 void Emitter::EmitEndMap()
498 if(!good())
499 return;
501 if(m_pState->GetCurGroupType() != GT_MAP)
502 return m_pState->SetError(ErrorMsg::UNEXPECTED_END_MAP);
504 EMITTER_STATE curState = m_pState->GetCurState();
505 FLOW_TYPE flowType = m_pState->GetCurGroupFlowType();
506 if(flowType == FT_BLOCK) {
507 // Note: block sequences are *not* allowed to be empty, but we convert it
508 // to a flow sequence if it is
509 assert(curState == ES_DONE_WITH_BLOCK_MAP_VALUE || curState == ES_WAITING_FOR_BLOCK_MAP_ENTRY);
510 if(curState == ES_WAITING_FOR_BLOCK_MAP_ENTRY) {
511 // Note: only one of these will actually output anything for a given situation
512 EmitSeparationIfNecessary();
513 unsigned curIndent = m_pState->GetCurIndent();
514 m_stream << IndentTo(curIndent);
515 m_stream << "{}";
517 } else if(flowType == FT_FLOW) {
518 // Note: flow maps are allowed to be empty
519 assert(curState == ES_DONE_WITH_FLOW_MAP_VALUE || curState == ES_WAITING_FOR_FLOW_MAP_ENTRY);
520 EmitSeparationIfNecessary();
521 m_stream << "}";
522 } else
523 assert(false);
525 m_pState->PopState();
526 m_pState->EndGroup(GT_MAP);
528 PostAtomicWrite();
531 // EmitKey
532 void Emitter::EmitKey()
534 if(!good())
535 return;
537 EMITTER_STATE curState = m_pState->GetCurState();
538 FLOW_TYPE flowType = m_pState->GetCurGroupFlowType();
539 if(curState != ES_WAITING_FOR_BLOCK_MAP_ENTRY && curState != ES_DONE_WITH_BLOCK_MAP_VALUE
540 && curState != ES_WAITING_FOR_FLOW_MAP_ENTRY && curState != ES_DONE_WITH_FLOW_MAP_VALUE)
541 return m_pState->SetError(ErrorMsg::UNEXPECTED_KEY_TOKEN);
543 if(flowType == FT_BLOCK) {
544 if(curState == ES_DONE_WITH_BLOCK_MAP_VALUE)
545 m_stream << '\n';
546 unsigned curIndent = m_pState->GetCurIndent();
547 m_stream << IndentTo(curIndent);
548 m_pState->UnsetSeparation();
549 m_pState->SwitchState(ES_WAITING_FOR_BLOCK_MAP_KEY);
550 } else if(flowType == FT_FLOW) {
551 EmitSeparationIfNecessary();
552 if(curState == ES_DONE_WITH_FLOW_MAP_VALUE) {
553 m_stream << ',';
554 m_pState->RequireSoftSeparation();
556 m_pState->SwitchState(ES_WAITING_FOR_FLOW_MAP_KEY);
557 } else
558 assert(false);
560 if(m_pState->GetMapKeyFormat() == LongKey)
561 m_pState->StartLongKey();
562 else if(m_pState->GetMapKeyFormat() == Auto)
563 m_pState->StartSimpleKey();
564 else
565 assert(false);
568 // EmitValue
569 void Emitter::EmitValue()
571 if(!good())
572 return;
574 EMITTER_STATE curState = m_pState->GetCurState();
575 FLOW_TYPE flowType = m_pState->GetCurGroupFlowType();
576 if(curState != ES_DONE_WITH_BLOCK_MAP_KEY && curState != ES_DONE_WITH_FLOW_MAP_KEY)
577 return m_pState->SetError(ErrorMsg::UNEXPECTED_VALUE_TOKEN);
579 if(flowType == FT_BLOCK) {
580 if(m_pState->CurrentlyInLongKey()) {
581 m_stream << '\n';
582 m_stream << IndentTo(m_pState->GetCurIndent());
583 m_stream << ':';
584 m_pState->RequireSoftSeparation();
586 m_pState->SwitchState(ES_WAITING_FOR_BLOCK_MAP_VALUE);
587 } else if(flowType == FT_FLOW) {
588 m_pState->SwitchState(ES_WAITING_FOR_FLOW_MAP_VALUE);
589 } else
590 assert(false);
593 // EmitNewline
594 void Emitter::EmitNewline()
596 if(!good())
597 return;
599 if(CanEmitNewline()) {
600 m_stream << '\n';
601 m_pState->UnsetSeparation();
605 bool Emitter::CanEmitNewline() const
607 FLOW_TYPE flowType = m_pState->GetCurGroupFlowType();
608 if(flowType == FT_BLOCK && m_pState->CurrentlyInLongKey())
609 return true;
611 EMITTER_STATE curState = m_pState->GetCurState();
612 return curState != ES_DONE_WITH_BLOCK_MAP_KEY && curState != ES_WAITING_FOR_BLOCK_MAP_VALUE && curState != ES_WRITING_BLOCK_MAP_VALUE;
615 // *******************************************************************************************
616 // overloads of Write
618 Emitter& Emitter::Write(const std::string& str)
620 if(!good())
621 return *this;
623 // literal scalars must use long keys
624 if(m_pState->GetStringFormat() == Literal && m_pState->GetCurGroupFlowType() != FT_FLOW)
625 m_pState->StartLongKey();
627 PreAtomicWrite();
628 EmitSeparationIfNecessary();
630 bool escapeNonAscii = m_pState->GetOutputCharset() == EscapeNonAscii;
631 EMITTER_MANIP strFmt = m_pState->GetStringFormat();
632 FLOW_TYPE flowType = m_pState->GetCurGroupFlowType();
633 unsigned curIndent = m_pState->GetCurIndent();
635 switch(strFmt) {
636 case Auto:
637 Utils::WriteString(m_stream, str, flowType == FT_FLOW, escapeNonAscii);
638 break;
639 case SingleQuoted:
640 if(!Utils::WriteSingleQuotedString(m_stream, str)) {
641 m_pState->SetError(ErrorMsg::SINGLE_QUOTED_CHAR);
642 return *this;
644 break;
645 case DoubleQuoted:
646 Utils::WriteDoubleQuotedString(m_stream, str, escapeNonAscii);
647 break;
648 case Literal:
649 if(flowType == FT_FLOW)
650 Utils::WriteString(m_stream, str, flowType == FT_FLOW, escapeNonAscii);
651 else
652 Utils::WriteLiteralString(m_stream, str, curIndent + m_pState->GetIndent());
653 break;
654 default:
655 assert(false);
658 PostAtomicWrite();
659 return *this;
662 void Emitter::PreWriteIntegralType(std::stringstream& str)
664 PreAtomicWrite();
665 EmitSeparationIfNecessary();
667 EMITTER_MANIP intFmt = m_pState->GetIntFormat();
668 switch(intFmt) {
669 case Dec:
670 str << std::dec;
671 break;
672 case Hex:
673 str << "0x";
674 str << std::hex;
675 break;
676 case Oct:
677 str << "0";
678 str << std::oct;
679 break;
680 default:
681 assert(false);
685 void Emitter::PreWriteStreamable(std::stringstream&)
687 PreAtomicWrite();
688 EmitSeparationIfNecessary();
691 unsigned Emitter::GetFloatPrecision() const
693 return m_pState->GetFloatPrecision();
696 unsigned Emitter::GetDoublePrecision() const
698 return m_pState->GetDoublePrecision();
701 void Emitter::PostWriteIntegralType(const std::stringstream& str)
703 m_stream << str.str();
704 PostAtomicWrite();
707 void Emitter::PostWriteStreamable(const std::stringstream& str)
709 m_stream << str.str();
710 PostAtomicWrite();
713 const char *Emitter::ComputeFullBoolName(bool b) const
715 const EMITTER_MANIP mainFmt = (m_pState->GetBoolLengthFormat() == ShortBool ? YesNoBool : m_pState->GetBoolFormat());
716 const EMITTER_MANIP caseFmt = m_pState->GetBoolCaseFormat();
717 switch(mainFmt) {
718 case YesNoBool:
719 switch(caseFmt) {
720 case UpperCase: return b ? "YES" : "NO";
721 case CamelCase: return b ? "Yes" : "No";
722 case LowerCase: return b ? "yes" : "no";
723 default: break;
725 break;
726 case OnOffBool:
727 switch(caseFmt) {
728 case UpperCase: return b ? "ON" : "OFF";
729 case CamelCase: return b ? "On" : "Off";
730 case LowerCase: return b ? "on" : "off";
731 default: break;
733 break;
734 case TrueFalseBool:
735 switch(caseFmt) {
736 case UpperCase: return b ? "TRUE" : "FALSE";
737 case CamelCase: return b ? "True" : "False";
738 case LowerCase: return b ? "true" : "false";
739 default: break;
741 break;
742 default:
743 break;
745 return b ? "y" : "n"; // should never get here, but it can't hurt to give these answers
748 Emitter& Emitter::Write(bool b)
750 if(!good())
751 return *this;
753 PreAtomicWrite();
754 EmitSeparationIfNecessary();
756 const char *name = ComputeFullBoolName(b);
757 if(m_pState->GetBoolLengthFormat() == ShortBool)
758 m_stream << name[0];
759 else
760 m_stream << name;
762 PostAtomicWrite();
763 return *this;
766 Emitter& Emitter::Write(char ch)
768 if(!good())
769 return *this;
771 PreAtomicWrite();
772 EmitSeparationIfNecessary();
774 Utils::WriteChar(m_stream, ch);
776 PostAtomicWrite();
777 return *this;
780 Emitter& Emitter::Write(const _Alias& alias)
782 if(!good())
783 return *this;
785 PreAtomicWrite();
786 EmitSeparationIfNecessary();
787 if(!Utils::WriteAlias(m_stream, alias.content)) {
788 m_pState->SetError(ErrorMsg::INVALID_ALIAS);
789 return *this;
791 PostAtomicWrite();
792 return *this;
795 Emitter& Emitter::Write(const _Anchor& anchor)
797 if(!good())
798 return *this;
800 PreAtomicWrite();
801 EmitSeparationIfNecessary();
802 if(!Utils::WriteAnchor(m_stream, anchor.content)) {
803 m_pState->SetError(ErrorMsg::INVALID_ANCHOR);
804 return *this;
806 m_pState->RequireHardSeparation();
807 // Note: no PostAtomicWrite() because we need another value for this node
808 return *this;
811 Emitter& Emitter::Write(const _Tag& tag)
813 if(!good())
814 return *this;
816 PreAtomicWrite();
817 EmitSeparationIfNecessary();
819 bool success = false;
820 if(tag.type == _Tag::Type::Verbatim)
821 success = Utils::WriteTag(m_stream, tag.content, true);
822 else if(tag.type == _Tag::Type::PrimaryHandle)
823 success = Utils::WriteTag(m_stream, tag.content, false);
824 else
825 success = Utils::WriteTagWithPrefix(m_stream, tag.prefix, tag.content);
827 if(!success) {
828 m_pState->SetError(ErrorMsg::INVALID_TAG);
829 return *this;
832 m_pState->RequireHardSeparation();
833 // Note: no PostAtomicWrite() because we need another value for this node
834 return *this;
837 void Emitter::EmitKindTag()
839 Write(LocalTag(""));
842 Emitter& Emitter::Write(const _Comment& comment)
844 if(!good())
845 return *this;
847 if(m_stream.col() > 0)
848 m_stream << Indentation(m_pState->GetPreCommentIndent());
849 Utils::WriteComment(m_stream, comment.content, m_pState->GetPostCommentIndent());
850 m_pState->RequireHardSeparation();
851 m_pState->ForceHardSeparation();
853 return *this;
856 Emitter& Emitter::Write(const _Null& /*null*/)
858 if(!good())
859 return *this;
861 PreAtomicWrite();
862 EmitSeparationIfNecessary();
863 m_stream << "~";
864 PostAtomicWrite();
865 return *this;
868 Emitter& Emitter::Write(const Binary& binary)
870 Write(SecondaryTag("binary"));
872 if(!good())
873 return *this;
875 PreAtomicWrite();
876 EmitSeparationIfNecessary();
877 Utils::WriteBinary(m_stream, binary);
878 PostAtomicWrite();
879 return *this;