"vscode:/vscode.git/clone" did not exist on "2fbfffcb95b1381b4d155e59241c12ea3e59c203"
emitter.cpp 14.8 KB
Newer Older
1
#include "yaml-cpp/emitter.h"
2
3
4
#include "emitterstate.h"
#include "emitterutils.h"
#include "indentation.h"
5
#include "yaml-cpp/exceptions.h"
6
7
8
9
10
11
12
13
14
15
16
17
#include <sstream>

namespace YAML
{	
	Emitter::Emitter(): m_pState(new EmitterState)
	{
	}
	
	Emitter::~Emitter()
	{
	}
	
18
	const char *Emitter::c_str() const
19
	{
20
		return m_stream.str();
21
22
	}
	
23
	unsigned Emitter::size() const
24
	{
25
		return m_stream.pos();
26
27
28
29
30
31
32
33
34
35
36
37
38
39
	}
	
	// state checking
	bool Emitter::good() const
	{
		return m_pState->good();
	}
	
	const std::string Emitter::GetLastError() const
	{
		return m_pState->GetLastError();
	}

	// global setters
40
41
	bool Emitter::SetOutputCharset(EMITTER_MANIP value)
	{
42
		return m_pState->SetOutputCharset(value, FmtScope::Global);
43
44
	}

45
46
	bool Emitter::SetStringFormat(EMITTER_MANIP value)
	{
47
		return m_pState->SetStringFormat(value, FmtScope::Global);
48
49
50
51
52
	}
	
	bool Emitter::SetBoolFormat(EMITTER_MANIP value)
	{
		bool ok = false;
53
		if(m_pState->SetBoolFormat(value, FmtScope::Global))
54
			ok = true;
55
		if(m_pState->SetBoolCaseFormat(value, FmtScope::Global))
56
			ok = true;
57
		if(m_pState->SetBoolLengthFormat(value, FmtScope::Global))
58
59
60
61
62
63
			ok = true;
		return ok;
	}
	
	bool Emitter::SetIntBase(EMITTER_MANIP value)
	{
64
		return m_pState->SetIntFormat(value, FmtScope::Global);
65
66
67
68
	}
	
	bool Emitter::SetSeqFormat(EMITTER_MANIP value)
	{
69
		return m_pState->SetFlowType(GroupType::Seq, value, FmtScope::Global);
70
71
72
73
74
	}
	
	bool Emitter::SetMapFormat(EMITTER_MANIP value)
	{
		bool ok = false;
75
		if(m_pState->SetFlowType(GroupType::Map, value, FmtScope::Global))
76
			ok = true;
77
		if(m_pState->SetMapKeyFormat(value, FmtScope::Global))
78
79
80
81
82
83
			ok = true;
		return ok;
	}
	
	bool Emitter::SetIndent(unsigned n)
	{
84
		return m_pState->SetIndent(n, FmtScope::Global);
85
86
87
88
	}
	
	bool Emitter::SetPreCommentIndent(unsigned n)
	{
89
		return m_pState->SetPreCommentIndent(n, FmtScope::Global);
90
91
92
93
	}
	
	bool Emitter::SetPostCommentIndent(unsigned n)
	{
94
		return m_pState->SetPostCommentIndent(n, FmtScope::Global);
95
	}
96
97
98
    
    bool Emitter::SetFloatPrecision(unsigned n)
    {
99
        return m_pState->SetFloatPrecision(n, FmtScope::Global);
100
101
102
103
    }

    bool Emitter::SetDoublePrecision(unsigned n)
    {
104
        return m_pState->SetDoublePrecision(n, FmtScope::Global);
105
    }
106
107
108
109
110
111
112
113
114

	// SetLocalValue
	// . Either start/end a group, or set a modifier locally
	Emitter& Emitter::SetLocalValue(EMITTER_MANIP value)
	{
		if(!good())
			return *this;
		
		switch(value) {
115
116
117
118
119
120
			case BeginDoc:
				EmitBeginDoc();
				break;
			case EndDoc:
				EmitEndDoc();
				break;
121
122
123
124
125
126
127
128
129
130
131
132
133
134
			case BeginSeq:
				EmitBeginSeq();
				break;
			case EndSeq:
				EmitEndSeq();
				break;
			case BeginMap:
				EmitBeginMap();
				break;
			case EndMap:
				EmitEndMap();
				break;
			case Key:
			case Value:
Jesse Beder's avatar
Jesse Beder committed
135
                // deprecated (these can be deduced by the parity of nodes in a map)
136
				break;
137
138
139
			case TagByKind:
				EmitKindTag();
				break;
140
141
142
			case Newline:
				EmitNewline();
				break;
143
144
145
146
147
148
149
150
151
			default:
				m_pState->SetLocalValue(value);
				break;
		}
		return *this;
	}
	
	Emitter& Emitter::SetLocalIndent(const _Indent& indent)
	{
152
		m_pState->SetIndent(indent.value, FmtScope::Local);
153
154
155
		return *this;
	}

156
157
158
    Emitter& Emitter::SetLocalPrecision(const _Precision& precision)
    {
        if(precision.floatPrecision >= 0)
159
            m_pState->SetFloatPrecision(precision.floatPrecision, FmtScope::Local);
160
        if(precision.doublePrecision >= 0)
161
            m_pState->SetDoublePrecision(precision.doublePrecision, FmtScope::Local);
162
163
164
        return *this;
    }

165
166
167
168
169
	// EmitBeginDoc
	void Emitter::EmitBeginDoc()
	{
		if(!good())
			return;
Jesse Beder's avatar
Jesse Beder committed
170
171
172
173
174
175
176
177
178
179
180
181
182
183
        
        if(m_pState->CurGroupType() != GroupType::None) {
			m_pState->SetError("Unexpected begin document");
			return;
        }
        
        if(m_pState->HasAnchor() || m_pState->HasTag()) {
			m_pState->SetError("Unexpected begin document");
			return;
        }
        
        if(m_stream.col() > 0)
            m_stream << "\n";
        m_stream << "---\n";
184
185
186
187
188
189
190
	}
	
	// EmitEndDoc
	void Emitter::EmitEndDoc()
	{
		if(!good())
			return;
Jesse Beder's avatar
Jesse Beder committed
191
192
193
194
195
196
197
198
199
200
201
202
203
204
        
        if(m_pState->CurGroupType() != GroupType::None) {
			m_pState->SetError("Unexpected begin document");
			return;
        }
        
        if(m_pState->HasAnchor() || m_pState->HasTag()) {
			m_pState->SetError("Unexpected begin document");
			return;
        }
        
        if(m_stream.col() > 0)
            m_stream << "\n";
        m_stream << "...\n";
205
206
	}

207
208
209
210
211
	// EmitBeginSeq
	void Emitter::EmitBeginSeq()
	{
		if(!good())
			return;
Jesse Beder's avatar
Jesse Beder committed
212
        
213
        PrepareNode(m_pState->NextGroupType(GroupType::Seq));
Jesse Beder's avatar
Jesse Beder committed
214
        
215
        m_pState->StartedGroup(GroupType::Seq);
216
217
218
219
220
221
222
	}
	
	// EmitEndSeq
	void Emitter::EmitEndSeq()
	{
		if(!good())
			return;
Jesse Beder's avatar
Jesse Beder committed
223
        
224
        m_pState->EndedGroup(GroupType::Seq);
225
226
227
228
229
230
231
	}
	
	// EmitBeginMap
	void Emitter::EmitBeginMap()
	{
		if(!good())
			return;
Jesse Beder's avatar
Jesse Beder committed
232

233
        PrepareNode(m_pState->NextGroupType(GroupType::Map));
Jesse Beder's avatar
Jesse Beder committed
234
        
235
        m_pState->StartedGroup(GroupType::Map);
236
237
238
239
240
241
242
	}
	
	// EmitEndMap
	void Emitter::EmitEndMap()
	{
		if(!good())
			return;
Jesse Beder's avatar
Jesse Beder committed
243

244
        m_pState->EndedGroup(GroupType::Map);
Jesse Beder's avatar
Jesse Beder committed
245
    }
246

247
248
249
250
251
	// EmitNewline
	void Emitter::EmitNewline()
	{
		if(!good())
			return;
Jesse Beder's avatar
Jesse Beder committed
252
        
Jesse Beder's avatar
Jesse Beder committed
253
        PrepareNode(EmitterNodeType::None);
Jesse Beder's avatar
Jesse Beder committed
254
255
        m_stream << "\n";
        m_pState->SetNonContent();
256
257
258
259
	}

	bool Emitter::CanEmitNewline() const
	{
Jesse Beder's avatar
Jesse Beder committed
260
        return true;
261
262
	}

Jesse Beder's avatar
Jesse Beder committed
263
264
    // Put the stream in a state so we can simply write the next node
    // E.g., if we're in a sequence, write the "- "
265
    void Emitter::PrepareNode(EmitterNodeType::value child)
Jesse Beder's avatar
Jesse Beder committed
266
    {
267
268
269
        switch(m_pState->CurGroupNodeType()) {
            case EmitterNodeType::None:
                PrepareTopNode(child);
Jesse Beder's avatar
Jesse Beder committed
270
                break;
271
272
            case EmitterNodeType::FlowSeq:
                FlowSeqPrepareNode(child);
Jesse Beder's avatar
Jesse Beder committed
273
                break;
274
275
276
277
278
279
280
281
282
283
284
            case EmitterNodeType::BlockSeq:
                BlockSeqPrepareNode(child);
                break;
            case EmitterNodeType::FlowMap:
                FlowMapPrepareNode(child);
                break;
            case EmitterNodeType::BlockMap:
                BlockMapPrepareNode(child);
                break;
            case EmitterNodeType::Scalar:
                assert(false);
Jesse Beder's avatar
Jesse Beder committed
285
286
287
288
                break;
        }
    }
    
289
    void Emitter::PrepareTopNode(EmitterNodeType::value child)
Jesse Beder's avatar
Jesse Beder committed
290
    {
Jesse Beder's avatar
Jesse Beder committed
291
        if(!m_pState->HasBegunNode() && m_stream.pos() > 0) {
292
293
294
            EmitBeginDoc();
        }
        
Jesse Beder's avatar
Jesse Beder committed
295
296
297
298
299
300
301
        switch(child) {
            case EmitterNodeType::None:
            case EmitterNodeType::Scalar:
            case EmitterNodeType::FlowSeq:
            case EmitterNodeType::FlowMap:
                // TODO: if we were writing null, and
                // we wanted it blank, we wouldn't want a space
Jesse Beder's avatar
Jesse Beder committed
302
                if(m_pState->HasBegunContent())
Jesse Beder's avatar
Jesse Beder committed
303
304
305
306
307
308
309
310
                    m_stream << " ";
                break;
            case EmitterNodeType::BlockSeq:
            case EmitterNodeType::BlockMap:
                if(m_pState->HasBegunNode())
                    m_stream << "\n";
                break;
        }
Jesse Beder's avatar
Jesse Beder committed
311
312
    }
    
313
    void Emitter::FlowSeqPrepareNode(EmitterNodeType::value child)
Jesse Beder's avatar
Jesse Beder committed
314
315
316
    {
    }

317
    void Emitter::BlockSeqPrepareNode(EmitterNodeType::value child)
Jesse Beder's avatar
Jesse Beder committed
318
    {
Jesse Beder's avatar
Jesse Beder committed
319
        const unsigned curIndent = m_pState->CurIndent();
320
321
        const unsigned nextIndent = curIndent + m_pState->CurGroupIndent();
        
Jesse Beder's avatar
Jesse Beder committed
322
        if(!m_pState->HasBegunNode()) {
323
324
325
326
327
            if(m_pState->CurGroupChildCount() > 0) {
                m_stream << "\n";
            }
            m_stream << IndentTo(curIndent);
            m_stream << "-";
Jesse Beder's avatar
Jesse Beder committed
328
        }
329
330
331
332
333
334
        
        switch(child) {
            case EmitterNodeType::None:
            case EmitterNodeType::Scalar:
            case EmitterNodeType::FlowSeq:
            case EmitterNodeType::FlowMap:
Jesse Beder's avatar
Jesse Beder committed
335
                if(m_pState->HasBegunContent())
336
                    m_stream << " ";
Jesse Beder's avatar
Jesse Beder committed
337
338
                else
                    m_stream << IndentTo(nextIndent);
339
340
341
342
343
                break;
            case EmitterNodeType::BlockSeq:
                m_stream << "\n";
                break;
            case EmitterNodeType::BlockMap:
Jesse Beder's avatar
Jesse Beder committed
344
                if(m_pState->HasBegunContent())
Jesse Beder's avatar
Jesse Beder committed
345
                    m_stream << "\n";
346
347
                break;
        }
Jesse Beder's avatar
Jesse Beder committed
348
349
    }
    
350
    void Emitter::FlowMapPrepareNode(EmitterNodeType::value child)
Jesse Beder's avatar
Jesse Beder committed
351
352
353
    {
    }

354
    void Emitter::BlockMapPrepareNode(EmitterNodeType::value child)
Jesse Beder's avatar
Jesse Beder committed
355
    {
356
357
358
359
        const unsigned curIndent = m_pState->CurIndent();
        const unsigned nextIndent = curIndent + m_pState->CurGroupIndent();
        const std::size_t childCount = m_pState->CurGroupChildCount();

Jesse Beder's avatar
Jesse Beder committed
360
        if(!m_pState->HasBegunNode()) {
361
362
363
364
365
            if(childCount % 2 == 0) {
                // key
                if(childCount > 0) {
                    m_stream << "\n";
                }
366
367
                if(false /* long key */) {
                }
368
369
            } else {
                // value
370
371
372
373
374
375
376
377
378
379
380
381
382
383
                if(false /* was long key */) {
                } else {
                    m_stream << ":";
                }
            }
        }
        
        if(childCount % 2 == 0) {
            // key
            switch(child) {
                case EmitterNodeType::None:
                case EmitterNodeType::Scalar:
                case EmitterNodeType::FlowSeq:
                case EmitterNodeType::FlowMap:
Jesse Beder's avatar
Jesse Beder committed
384
                    if(m_pState->HasBegunContent())
385
                        m_stream << " ";
Jesse Beder's avatar
Jesse Beder committed
386
387
                    else
                        m_stream << IndentTo(curIndent);
388
389
390
391
392
393
394
395
396
397
398
399
                    break;
                case EmitterNodeType::BlockSeq:
                case EmitterNodeType::BlockMap:
                    break;
            }
        } else {
            // value
            switch(child) {
                case EmitterNodeType::None:
                case EmitterNodeType::Scalar:
                case EmitterNodeType::FlowSeq:
                case EmitterNodeType::FlowMap:
Jesse Beder's avatar
Jesse Beder committed
400
                    m_stream << " ";
401
402
403
404
405
                    break;
                case EmitterNodeType::BlockSeq:
                case EmitterNodeType::BlockMap:
                    m_stream << "\n";
                    break;
406
407
            }
        }
Jesse Beder's avatar
Jesse Beder committed
408
409
    }

410
411
412
413
414
415
416
	// *******************************************************************************************
	// overloads of Write
	
	Emitter& Emitter::Write(const std::string& str)
	{
		if(!good())
			return *this;
Jesse Beder's avatar
Jesse Beder committed
417
        
418
        PrepareNode(EmitterNodeType::Scalar);
Jesse Beder's avatar
Jesse Beder committed
419
        
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
		const bool escapeNonAscii = m_pState->GetOutputCharset() == EscapeNonAscii;
        const StringFormat::value strFormat = Utils::ComputeStringFormat(str, m_pState->GetStringFormat(), m_pState->CurGroupFlowType(), escapeNonAscii);
        
        switch(strFormat) {
            case StringFormat::Plain:
                m_stream << str;
                break;
            case StringFormat::SingleQuoted:
                Utils::WriteSingleQuotedString(m_stream, str);
                break;
            case StringFormat::DoubleQuoted:
                Utils::WriteDoubleQuotedString(m_stream, str, escapeNonAscii);
                break;
            case StringFormat::Literal:
                Utils::WriteLiteralString(m_stream, str, m_pState->CurIndent() + m_pState->GetIndent());
                break;
        }

438
        m_pState->StartedScalar();
Jesse Beder's avatar
Jesse Beder committed
439
        
440
441
		return *this;
	}
442

443
444
445
446
447
448
449
450
451
452
    unsigned Emitter::GetFloatPrecision() const
    {
        return m_pState->GetFloatPrecision();
    }
    
    unsigned Emitter::GetDoublePrecision() const
    {
        return m_pState->GetDoublePrecision();
    }

453
454
455
456
457
458
459
	const char *Emitter::ComputeFullBoolName(bool b) const
	{
		const EMITTER_MANIP mainFmt = (m_pState->GetBoolLengthFormat() == ShortBool ? YesNoBool : m_pState->GetBoolFormat());
		const EMITTER_MANIP caseFmt = m_pState->GetBoolCaseFormat();
		switch(mainFmt) {
			case YesNoBool:
				switch(caseFmt) {
460
461
462
463
					case UpperCase: return b ? "YES" : "NO";
					case CamelCase: return b ? "Yes" : "No";
					case LowerCase: return b ? "yes" : "no";
					default: break;
464
				}
465
				break;
466
467
			case OnOffBool:
				switch(caseFmt) {
468
469
470
471
					case UpperCase: return b ? "ON" : "OFF";
					case CamelCase: return b ? "On" : "Off";
					case LowerCase: return b ? "on" : "off";
					default: break;
472
				}
473
474
				break;
			case TrueFalseBool:
475
				switch(caseFmt) {
476
477
478
479
					case UpperCase: return b ? "TRUE" : "FALSE";
					case CamelCase: return b ? "True" : "False";
					case LowerCase: return b ? "true" : "false";
					default: break;
480
				}
481
482
483
				break;
			default:
				break;
484
		}
485
		return b ? "y" : "n"; // should never get here, but it can't hurt to give these answers
486
	}
487

488
489
490
491
	Emitter& Emitter::Write(bool b)
	{
		if(!good())
			return *this;
492

493
        m_pState->StartedScalar();
Jesse Beder's avatar
Jesse Beder committed
494

495
496
497
		return *this;
	}

Jesse Beder's avatar
Jesse Beder committed
498
499
500
501
	Emitter& Emitter::Write(char ch)
	{
		if(!good())
			return *this;
502

503
        m_pState->StartedScalar();
Jesse Beder's avatar
Jesse Beder committed
504

Jesse Beder's avatar
Jesse Beder committed
505
506
507
		return *this;
	}

508
509
510
511
	Emitter& Emitter::Write(const _Alias& alias)
	{
		if(!good())
			return *this;
Jesse Beder's avatar
Jesse Beder committed
512
513
514
515
516
        
        if(m_pState->HasAnchor() || m_pState->HasTag()) {
            m_pState->SetError(ErrorMsg::INVALID_ALIAS);
            return *this;
        }
517

Jesse Beder's avatar
Jesse Beder committed
518
519
520
521
522
523
524
        PrepareNode(EmitterNodeType::Scalar);

		if(!Utils::WriteAlias(m_stream, alias.content)) {
			m_pState->SetError(ErrorMsg::INVALID_ALIAS);
			return *this;
		}
        
525
        m_pState->StartedScalar();
Jesse Beder's avatar
Jesse Beder committed
526

527
528
529
530
531
532
533
		return *this;
	}
	
	Emitter& Emitter::Write(const _Anchor& anchor)
	{
		if(!good())
			return *this;
Jesse Beder's avatar
Jesse Beder committed
534
535
536
537
538
        
        if(m_pState->HasAnchor()) {
            m_pState->SetError(ErrorMsg::INVALID_ANCHOR);
            return *this;
        }
539

Jesse Beder's avatar
Jesse Beder committed
540
541
542
543
544
545
546
547
        PrepareNode(EmitterNodeType::None);

		if(!Utils::WriteAnchor(m_stream, anchor.content)) {
			m_pState->SetError(ErrorMsg::INVALID_ANCHOR);
			return *this;
		}
        
        m_pState->SetAnchor();
Jesse Beder's avatar
Jesse Beder committed
548

549
550
551
		return *this;
	}
	
552
553
554
555
	Emitter& Emitter::Write(const _Tag& tag)
	{
		if(!good())
			return *this;
556
        
Jesse Beder's avatar
Jesse Beder committed
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
        if(m_pState->HasTag()) {
            m_pState->SetError(ErrorMsg::INVALID_TAG);
            return *this;
        }
        
        PrepareNode(EmitterNodeType::None);
        
		bool success = false;
		if(tag.type == _Tag::Type::Verbatim)
			success = Utils::WriteTag(m_stream, tag.content, true);
		else if(tag.type == _Tag::Type::PrimaryHandle)
			success = Utils::WriteTag(m_stream, tag.content, false);
		else
			success = Utils::WriteTagWithPrefix(m_stream, tag.prefix, tag.content);
		
		if(!success) {
			m_pState->SetError(ErrorMsg::INVALID_TAG);
			return *this;
		}

        m_pState->SetTag();

579
		return *this;
580
	}
581

582
583
	void Emitter::EmitKindTag()
	{
584
		Write(LocalTag(""));
585
586
	}

587
588
589
590
	Emitter& Emitter::Write(const _Comment& comment)
	{
		if(!good())
			return *this;
591

592
593
594
595
596
597
598
        PrepareNode(EmitterNodeType::None);
        
		if(m_stream.col() > 0)
			m_stream << Indentation(m_pState->GetPreCommentIndent());
		Utils::WriteComment(m_stream, comment.content, m_pState->GetPostCommentIndent());

        m_pState->SetNonContent();
Jesse Beder's avatar
Jesse Beder committed
599

600
601
		return *this;
	}
602
603
604
605
606

	Emitter& Emitter::Write(const _Null& /*null*/)
	{
		if(!good())
			return *this;
607

608
        m_pState->StartedScalar();
Jesse Beder's avatar
Jesse Beder committed
609

610
611
		return *this;
	}
612

613
	Emitter& Emitter::Write(const Binary& binary)
614
	{
615
616
		Write(SecondaryTag("binary"));

617
618
		if(!good())
			return *this;
619

620
        m_pState->StartedScalar();
Jesse Beder's avatar
Jesse Beder committed
621

622
623
		return *this;
	}
624
}
625