LLVM 21.0.0git
YAMLTraits.cpp
Go to the documentation of this file.
1//===- lib/Support/YAMLTraits.cpp -----------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
10#include "llvm/ADT/STLExtras.h"
13#include "llvm/ADT/StringRef.h"
14#include "llvm/ADT/Twine.h"
16#include "llvm/Support/Errc.h"
18#include "llvm/Support/Format.h"
24#include <cassert>
25#include <cstdint>
26#include <cstring>
27#include <string>
28#include <vector>
29
30using namespace llvm;
31using namespace yaml;
32
33//===----------------------------------------------------------------------===//
34// IO
35//===----------------------------------------------------------------------===//
36
37IO::IO(void *Context) : Ctxt(Context) {}
38
39IO::~IO() = default;
40
41void *IO::getContext() const {
42 return Ctxt;
43}
44
45void IO::setContext(void *Context) {
46 Ctxt = Context;
47}
48
49void IO::setAllowUnknownKeys(bool Allow) {
50 llvm_unreachable("Only supported for Input");
51}
52
53//===----------------------------------------------------------------------===//
54// Input
55//===----------------------------------------------------------------------===//
56
57Input::Input(StringRef InputContent, void *Ctxt,
58 SourceMgr::DiagHandlerTy DiagHandler, void *DiagHandlerCtxt)
59 : IO(Ctxt), Strm(new Stream(InputContent, SrcMgr, false, &EC)) {
60 if (DiagHandler)
61 SrcMgr.setDiagHandler(DiagHandler, DiagHandlerCtxt);
62 DocIterator = Strm->begin();
63}
64
65Input::Input(MemoryBufferRef Input, void *Ctxt,
66 SourceMgr::DiagHandlerTy DiagHandler, void *DiagHandlerCtxt)
67 : IO(Ctxt), Strm(new Stream(Input, SrcMgr, false, &EC)) {
68 if (DiagHandler)
69 SrcMgr.setDiagHandler(DiagHandler, DiagHandlerCtxt);
70 DocIterator = Strm->begin();
71}
72
73Input::~Input() = default;
74
75std::error_code Input::error() { return EC; }
76
77bool Input::outputting() const {
78 return false;
79}
80
81bool Input::setCurrentDocument() {
82 if (DocIterator != Strm->end()) {
83 Node *N = DocIterator->getRoot();
84 if (!N) {
85 EC = make_error_code(errc::invalid_argument);
86 return false;
87 }
88
89 if (isa<NullNode>(N)) {
90 // Empty files are allowed and ignored
91 ++DocIterator;
92 return setCurrentDocument();
93 }
94 releaseHNodeBuffers();
95 TopNode = createHNodes(N);
96 CurrentNode = TopNode;
97 return true;
98 }
99 return false;
100}
101
102bool Input::nextDocument() {
103 return ++DocIterator != Strm->end();
104}
105
106const Node *Input::getCurrentNode() const {
107 return CurrentNode ? CurrentNode->_node : nullptr;
108}
109
110bool Input::mapTag(StringRef Tag, bool Default) {
111 // CurrentNode can be null if setCurrentDocument() was unable to
112 // parse the document because it was invalid or empty.
113 if (!CurrentNode)
114 return false;
115
116 std::string foundTag = CurrentNode->_node->getVerbatimTag();
117 if (foundTag.empty()) {
118 // If no tag found and 'Tag' is the default, say it was found.
119 return Default;
120 }
121 // Return true iff found tag matches supplied tag.
122 return Tag == foundTag;
123}
124
125void Input::beginMapping() {
126 if (EC)
127 return;
128 // CurrentNode can be null if the document is empty.
129 MapHNode *MN = dyn_cast_or_null<MapHNode>(CurrentNode);
130 if (MN) {
131 MN->ValidKeys.clear();
132 }
133}
134
135std::vector<StringRef> Input::keys() {
136 MapHNode *MN = dyn_cast<MapHNode>(CurrentNode);
137 std::vector<StringRef> Ret;
138 if (!MN) {
139 setError(CurrentNode, "not a mapping");
140 return Ret;
141 }
142 for (auto &P : MN->Mapping)
143 Ret.push_back(P.first());
144 return Ret;
145}
146
147bool Input::preflightKey(const char *Key, bool Required, bool, bool &UseDefault,
148 void *&SaveInfo) {
149 UseDefault = false;
150 if (EC)
151 return false;
152
153 // CurrentNode is null for empty documents, which is an error in case required
154 // nodes are present.
155 if (!CurrentNode) {
156 if (Required)
157 EC = make_error_code(errc::invalid_argument);
158 else
159 UseDefault = true;
160 return false;
161 }
162
163 MapHNode *MN = dyn_cast<MapHNode>(CurrentNode);
164 if (!MN) {
165 if (Required || !isa<EmptyHNode>(CurrentNode))
166 setError(CurrentNode, "not a mapping");
167 else
168 UseDefault = true;
169 return false;
170 }
171 MN->ValidKeys.push_back(Key);
172 HNode *Value = MN->Mapping[Key].first;
173 if (!Value) {
174 if (Required)
175 setError(CurrentNode, Twine("missing required key '") + Key + "'");
176 else
177 UseDefault = true;
178 return false;
179 }
180 SaveInfo = CurrentNode;
181 CurrentNode = Value;
182 return true;
183}
184
185void Input::postflightKey(void *saveInfo) {
186 CurrentNode = reinterpret_cast<HNode *>(saveInfo);
187}
188
189void Input::endMapping() {
190 if (EC)
191 return;
192 // CurrentNode can be null if the document is empty.
193 MapHNode *MN = dyn_cast_or_null<MapHNode>(CurrentNode);
194 if (!MN)
195 return;
196 for (const auto &NN : MN->Mapping) {
197 if (!is_contained(MN->ValidKeys, NN.first())) {
198 const SMRange &ReportLoc = NN.second.second;
199 if (!AllowUnknownKeys) {
200 setError(ReportLoc, Twine("unknown key '") + NN.first() + "'");
201 break;
202 } else
203 reportWarning(ReportLoc, Twine("unknown key '") + NN.first() + "'");
204 }
205 }
206}
207
208void Input::beginFlowMapping() { beginMapping(); }
209
210void Input::endFlowMapping() { endMapping(); }
211
212unsigned Input::beginSequence() {
213 if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode))
214 return SQ->Entries.size();
215 if (isa<EmptyHNode>(CurrentNode))
216 return 0;
217 // Treat case where there's a scalar "null" value as an empty sequence.
218 if (ScalarHNode *SN = dyn_cast<ScalarHNode>(CurrentNode)) {
219 if (isNull(SN->value()))
220 return 0;
221 }
222 // Any other type of HNode is an error.
223 setError(CurrentNode, "not a sequence");
224 return 0;
225}
226
227void Input::endSequence() {
228}
229
230bool Input::preflightElement(unsigned Index, void *&SaveInfo) {
231 if (EC)
232 return false;
233 if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) {
234 SaveInfo = CurrentNode;
235 CurrentNode = SQ->Entries[Index];
236 return true;
237 }
238 return false;
239}
240
241void Input::postflightElement(void *SaveInfo) {
242 CurrentNode = reinterpret_cast<HNode *>(SaveInfo);
243}
244
245unsigned Input::beginFlowSequence() { return beginSequence(); }
246
247bool Input::preflightFlowElement(unsigned index, void *&SaveInfo) {
248 if (EC)
249 return false;
250 if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) {
251 SaveInfo = CurrentNode;
252 CurrentNode = SQ->Entries[index];
253 return true;
254 }
255 return false;
256}
257
258void Input::postflightFlowElement(void *SaveInfo) {
259 CurrentNode = reinterpret_cast<HNode *>(SaveInfo);
260}
261
262void Input::endFlowSequence() {
263}
264
265void Input::beginEnumScalar() {
266 ScalarMatchFound = false;
267}
268
269bool Input::matchEnumScalar(const char *Str, bool) {
270 if (ScalarMatchFound)
271 return false;
272 if (ScalarHNode *SN = dyn_cast<ScalarHNode>(CurrentNode)) {
273 if (SN->value() == Str) {
274 ScalarMatchFound = true;
275 return true;
276 }
277 }
278 return false;
279}
280
281bool Input::matchEnumFallback() {
282 if (ScalarMatchFound)
283 return false;
284 ScalarMatchFound = true;
285 return true;
286}
287
288void Input::endEnumScalar() {
289 if (!ScalarMatchFound) {
290 setError(CurrentNode, "unknown enumerated scalar");
291 }
292}
293
294bool Input::beginBitSetScalar(bool &DoClear) {
295 BitValuesUsed.clear();
296 if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) {
297 BitValuesUsed.resize(SQ->Entries.size());
298 } else {
299 setError(CurrentNode, "expected sequence of bit values");
300 }
301 DoClear = true;
302 return true;
303}
304
305bool Input::bitSetMatch(const char *Str, bool) {
306 if (EC)
307 return false;
308 if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) {
309 unsigned Index = 0;
310 for (auto &N : SQ->Entries) {
311 if (ScalarHNode *SN = dyn_cast<ScalarHNode>(N)) {
312 if (SN->value() == Str) {
313 BitValuesUsed[Index] = true;
314 return true;
315 }
316 } else {
317 setError(CurrentNode, "unexpected scalar in sequence of bit values");
318 }
319 ++Index;
320 }
321 } else {
322 setError(CurrentNode, "expected sequence of bit values");
323 }
324 return false;
325}
326
327void Input::endBitSetScalar() {
328 if (EC)
329 return;
330 if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) {
331 assert(BitValuesUsed.size() == SQ->Entries.size());
332 for (unsigned i = 0; i < SQ->Entries.size(); ++i) {
333 if (!BitValuesUsed[i]) {
334 setError(SQ->Entries[i], "unknown bit value");
335 return;
336 }
337 }
338 }
339}
340
341void Input::scalarString(StringRef &S, QuotingType) {
342 if (ScalarHNode *SN = dyn_cast<ScalarHNode>(CurrentNode)) {
343 S = SN->value();
344 } else {
345 setError(CurrentNode, "unexpected scalar");
346 }
347}
348
349void Input::blockScalarString(StringRef &S) { scalarString(S, QuotingType::None); }
350
351void Input::scalarTag(std::string &Tag) {
352 Tag = CurrentNode->_node->getVerbatimTag();
353}
354
355void Input::setError(HNode *hnode, const Twine &message) {
356 assert(hnode && "HNode must not be NULL");
357 setError(hnode->_node, message);
358}
359
360NodeKind Input::getNodeKind() {
361 if (isa<ScalarHNode>(CurrentNode))
362 return NodeKind::Scalar;
363 else if (isa<MapHNode>(CurrentNode))
364 return NodeKind::Map;
365 else if (isa<SequenceHNode>(CurrentNode))
366 return NodeKind::Sequence;
367 llvm_unreachable("Unsupported node kind");
368}
369
370void Input::setError(Node *node, const Twine &message) {
371 Strm->printError(node, message);
372 EC = make_error_code(errc::invalid_argument);
373}
374
375void Input::setError(const SMRange &range, const Twine &message) {
376 Strm->printError(range, message);
377 EC = make_error_code(errc::invalid_argument);
378}
379
380void Input::reportWarning(HNode *hnode, const Twine &message) {
381 assert(hnode && "HNode must not be NULL");
382 Strm->printError(hnode->_node, message, SourceMgr::DK_Warning);
383}
384
385void Input::reportWarning(Node *node, const Twine &message) {
386 Strm->printError(node, message, SourceMgr::DK_Warning);
387}
388
389void Input::reportWarning(const SMRange &range, const Twine &message) {
390 Strm->printError(range, message, SourceMgr::DK_Warning);
391}
392
393void Input::releaseHNodeBuffers() {
394 EmptyHNodeAllocator.DestroyAll();
395 ScalarHNodeAllocator.DestroyAll();
396 SequenceHNodeAllocator.DestroyAll();
397 MapHNodeAllocator.DestroyAll();
398}
399
400Input::HNode *Input::createHNodes(Node *N) {
401 SmallString<128> StringStorage;
402 switch (N->getType()) {
403 case Node::NK_Scalar: {
404 ScalarNode *SN = dyn_cast<ScalarNode>(N);
405 StringRef KeyStr = SN->getValue(StringStorage);
406 if (!StringStorage.empty()) {
407 // Copy string to permanent storage
408 KeyStr = StringStorage.str().copy(StringAllocator);
409 }
410 return new (ScalarHNodeAllocator.Allocate()) ScalarHNode(N, KeyStr);
411 }
412 case Node::NK_BlockScalar: {
413 BlockScalarNode *BSN = dyn_cast<BlockScalarNode>(N);
414 StringRef ValueCopy = BSN->getValue().copy(StringAllocator);
415 return new (ScalarHNodeAllocator.Allocate()) ScalarHNode(N, ValueCopy);
416 }
417 case Node::NK_Sequence: {
418 SequenceNode *SQ = dyn_cast<SequenceNode>(N);
419 auto SQHNode = new (SequenceHNodeAllocator.Allocate()) SequenceHNode(N);
420 for (Node &SN : *SQ) {
421 auto Entry = createHNodes(&SN);
422 if (EC)
423 break;
424 SQHNode->Entries.push_back(Entry);
425 }
426 return SQHNode;
427 }
428 case Node::NK_Mapping: {
429 MappingNode *Map = dyn_cast<MappingNode>(N);
430 auto mapHNode = new (MapHNodeAllocator.Allocate()) MapHNode(N);
431 for (KeyValueNode &KVN : *Map) {
432 Node *KeyNode = KVN.getKey();
433 ScalarNode *Key = dyn_cast_or_null<ScalarNode>(KeyNode);
434 Node *Value = KVN.getValue();
435 if (!Key || !Value) {
436 if (!Key)
437 setError(KeyNode, "Map key must be a scalar");
438 if (!Value)
439 setError(KeyNode, "Map value must not be empty");
440 break;
441 }
442 StringStorage.clear();
443 StringRef KeyStr = Key->getValue(StringStorage);
444 if (!StringStorage.empty()) {
445 // Copy string to permanent storage
446 KeyStr = StringStorage.str().copy(StringAllocator);
447 }
448 if (mapHNode->Mapping.count(KeyStr))
449 // From YAML spec: "The content of a mapping node is an unordered set of
450 // key/value node pairs, with the restriction that each of the keys is
451 // unique."
452 setError(KeyNode, Twine("duplicated mapping key '") + KeyStr + "'");
453 auto ValueHNode = createHNodes(Value);
454 if (EC)
455 break;
456 mapHNode->Mapping[KeyStr] =
457 std::make_pair(std::move(ValueHNode), KeyNode->getSourceRange());
458 }
459 return std::move(mapHNode);
460 }
461 case Node::NK_Null:
462 return new (EmptyHNodeAllocator.Allocate()) EmptyHNode(N);
463 default:
464 setError(N, "unknown node kind");
465 return nullptr;
466 }
467}
468
469void Input::setError(const Twine &Message) {
470 setError(CurrentNode, Message);
471}
472
473void Input::setAllowUnknownKeys(bool Allow) { AllowUnknownKeys = Allow; }
474
475bool Input::canElideEmptySequence() {
476 return false;
477}
478
479//===----------------------------------------------------------------------===//
480// Output
481//===----------------------------------------------------------------------===//
482
483Output::Output(raw_ostream &yout, void *context, int WrapColumn)
484 : IO(context), Out(yout), WrapColumn(WrapColumn) {}
485
486Output::~Output() = default;
487
488bool Output::outputting() const {
489 return true;
490}
491
492void Output::beginMapping() {
493 StateStack.push_back(inMapFirstKey);
494 PaddingBeforeContainer = Padding;
495 Padding = "\n";
496}
497
498bool Output::mapTag(StringRef Tag, bool Use) {
499 if (Use) {
500 // If this tag is being written inside a sequence we should write the start
501 // of the sequence before writing the tag, otherwise the tag won't be
502 // attached to the element in the sequence, but rather the sequence itself.
503 bool SequenceElement = false;
504 if (StateStack.size() > 1) {
505 auto &E = StateStack[StateStack.size() - 2];
506 SequenceElement = inSeqAnyElement(E) || inFlowSeqAnyElement(E);
507 }
508 if (SequenceElement && StateStack.back() == inMapFirstKey) {
509 newLineCheck();
510 } else {
511 output(" ");
512 }
513 output(Tag);
514 if (SequenceElement) {
515 // If we're writing the tag during the first element of a map, the tag
516 // takes the place of the first element in the sequence.
517 if (StateStack.back() == inMapFirstKey) {
518 StateStack.pop_back();
519 StateStack.push_back(inMapOtherKey);
520 }
521 // Tags inside maps in sequences should act as keys in the map from a
522 // formatting perspective, so we always want a newline in a sequence.
523 Padding = "\n";
524 }
525 }
526 return Use;
527}
528
529void Output::endMapping() {
530 // If we did not map anything, we should explicitly emit an empty map
531 if (StateStack.back() == inMapFirstKey) {
532 Padding = PaddingBeforeContainer;
533 newLineCheck();
534 output("{}");
535 Padding = "\n";
536 }
537 StateStack.pop_back();
538}
539
540std::vector<StringRef> Output::keys() {
541 report_fatal_error("invalid call");
542}
543
544bool Output::preflightKey(const char *Key, bool Required, bool SameAsDefault,
545 bool &UseDefault, void *&SaveInfo) {
546 UseDefault = false;
547 SaveInfo = nullptr;
548 if (Required || !SameAsDefault || WriteDefaultValues) {
549 auto State = StateStack.back();
550 if (State == inFlowMapFirstKey || State == inFlowMapOtherKey) {
551 flowKey(Key);
552 } else {
553 newLineCheck();
554 paddedKey(Key);
555 }
556 return true;
557 }
558 return false;
559}
560
561void Output::postflightKey(void *) {
562 if (StateStack.back() == inMapFirstKey) {
563 StateStack.pop_back();
564 StateStack.push_back(inMapOtherKey);
565 } else if (StateStack.back() == inFlowMapFirstKey) {
566 StateStack.pop_back();
567 StateStack.push_back(inFlowMapOtherKey);
568 }
569}
570
571void Output::beginFlowMapping() {
572 StateStack.push_back(inFlowMapFirstKey);
573 newLineCheck();
574 ColumnAtMapFlowStart = Column;
575 output("{ ");
576}
577
578void Output::endFlowMapping() {
579 StateStack.pop_back();
580 outputUpToEndOfLine(" }");
581}
582
583void Output::beginDocuments() {
584 outputUpToEndOfLine("---");
585}
586
587bool Output::preflightDocument(unsigned index) {
588 if (index > 0)
589 outputUpToEndOfLine("\n---");
590 return true;
591}
592
593void Output::postflightDocument() {
594}
595
596void Output::endDocuments() {
597 output("\n...\n");
598}
599
600unsigned Output::beginSequence() {
601 StateStack.push_back(inSeqFirstElement);
602 PaddingBeforeContainer = Padding;
603 Padding = "\n";
604 return 0;
605}
606
607void Output::endSequence() {
608 // If we did not emit anything, we should explicitly emit an empty sequence
609 if (StateStack.back() == inSeqFirstElement) {
610 Padding = PaddingBeforeContainer;
611 newLineCheck(/*EmptySequence=*/true);
612 output("[]");
613 Padding = "\n";
614 }
615 StateStack.pop_back();
616}
617
618bool Output::preflightElement(unsigned, void *&SaveInfo) {
619 SaveInfo = nullptr;
620 return true;
621}
622
623void Output::postflightElement(void *) {
624 if (StateStack.back() == inSeqFirstElement) {
625 StateStack.pop_back();
626 StateStack.push_back(inSeqOtherElement);
627 } else if (StateStack.back() == inFlowSeqFirstElement) {
628 StateStack.pop_back();
629 StateStack.push_back(inFlowSeqOtherElement);
630 }
631}
632
633unsigned Output::beginFlowSequence() {
634 StateStack.push_back(inFlowSeqFirstElement);
635 newLineCheck();
636 ColumnAtFlowStart = Column;
637 output("[ ");
638 NeedFlowSequenceComma = false;
639 return 0;
640}
641
642void Output::endFlowSequence() {
643 StateStack.pop_back();
644 outputUpToEndOfLine(" ]");
645}
646
647bool Output::preflightFlowElement(unsigned, void *&SaveInfo) {
648 if (NeedFlowSequenceComma)
649 output(", ");
650 if (WrapColumn && Column > WrapColumn) {
651 output("\n");
652 for (int i = 0; i < ColumnAtFlowStart; ++i)
653 output(" ");
654 Column = ColumnAtFlowStart;
655 output(" ");
656 }
657 SaveInfo = nullptr;
658 return true;
659}
660
661void Output::postflightFlowElement(void *) {
662 NeedFlowSequenceComma = true;
663}
664
665void Output::beginEnumScalar() {
666 EnumerationMatchFound = false;
667}
668
669bool Output::matchEnumScalar(const char *Str, bool Match) {
670 if (Match && !EnumerationMatchFound) {
671 newLineCheck();
672 outputUpToEndOfLine(Str);
673 EnumerationMatchFound = true;
674 }
675 return false;
676}
677
678bool Output::matchEnumFallback() {
679 if (EnumerationMatchFound)
680 return false;
681 EnumerationMatchFound = true;
682 return true;
683}
684
685void Output::endEnumScalar() {
686 if (!EnumerationMatchFound)
687 llvm_unreachable("bad runtime enum value");
688}
689
690bool Output::beginBitSetScalar(bool &DoClear) {
691 newLineCheck();
692 output("[ ");
693 NeedBitValueComma = false;
694 DoClear = false;
695 return true;
696}
697
698bool Output::bitSetMatch(const char *Str, bool Matches) {
699 if (Matches) {
700 if (NeedBitValueComma)
701 output(", ");
702 output(Str);
703 NeedBitValueComma = true;
704 }
705 return false;
706}
707
708void Output::endBitSetScalar() {
709 outputUpToEndOfLine(" ]");
710}
711
712void Output::scalarString(StringRef &S, QuotingType MustQuote) {
713 newLineCheck();
714 if (S.empty()) {
715 // Print '' for the empty string because leaving the field empty is not
716 // allowed.
717 outputUpToEndOfLine("''");
718 return;
719 }
720 output(S, MustQuote);
721 outputUpToEndOfLine("");
722}
723
724void Output::blockScalarString(StringRef &S) {
725 if (!StateStack.empty())
726 newLineCheck();
727 output(" |");
728 outputNewLine();
729
730 unsigned Indent = StateStack.empty() ? 1 : StateStack.size();
731
732 auto Buffer = MemoryBuffer::getMemBuffer(S, "", false);
733 for (line_iterator Lines(*Buffer, false); !Lines.is_at_end(); ++Lines) {
734 for (unsigned I = 0; I < Indent; ++I) {
735 output(" ");
736 }
737 output(*Lines);
738 outputNewLine();
739 }
740}
741
742void Output::scalarTag(std::string &Tag) {
743 if (Tag.empty())
744 return;
745 newLineCheck();
746 output(Tag);
747 output(" ");
748}
749
750void Output::setError(const Twine &message) {
751}
752
753std::error_code Output::error() { return {}; }
754
755bool Output::canElideEmptySequence() {
756 // Normally, with an optional key/value where the value is an empty sequence,
757 // the whole key/value can be not written. But, that produces wrong yaml
758 // if the key/value is the only thing in the map and the map is used in
759 // a sequence. This detects if the this sequence is the first key/value
760 // in map that itself is embedded in a sequence.
761 if (StateStack.size() < 2)
762 return true;
763 if (StateStack.back() != inMapFirstKey)
764 return true;
765 return !inSeqAnyElement(StateStack[StateStack.size() - 2]);
766}
767
768void Output::output(StringRef s) {
769 Column += s.size();
770 Out << s;
771}
772
773void Output::output(StringRef S, QuotingType MustQuote) {
774 if (MustQuote == QuotingType::None) {
775 // Only quote if we must.
776 output(S);
777 return;
778 }
779
780 StringLiteral Quote = MustQuote == QuotingType::Single ? StringLiteral("'")
781 : StringLiteral("\"");
782 output(Quote); // Starting quote.
783
784 // When using double-quoted strings (and only in that case), non-printable
785 // characters may be present, and will be escaped using a variety of
786 // unicode-scalar and special short-form escapes. This is handled in
787 // yaml::escape.
788 if (MustQuote == QuotingType::Double) {
789 output(yaml::escape(S, /* EscapePrintable= */ false));
790 output(Quote);
791 return;
792 }
793
794 unsigned i = 0;
795 unsigned j = 0;
796 unsigned End = S.size();
797 const char *Base = S.data();
798
799 // When using single-quoted strings, any single quote ' must be doubled to be
800 // escaped.
801 while (j < End) {
802 if (S[j] == '\'') { // Escape quotes.
803 output(StringRef(&Base[i], j - i)); // "flush".
804 output(StringLiteral("''")); // Print it as ''
805 i = j + 1;
806 }
807 ++j;
808 }
809 output(StringRef(&Base[i], j - i));
810 output(Quote); // Ending quote.
811}
812
813void Output::outputUpToEndOfLine(StringRef s) {
814 output(s);
815 if (StateStack.empty() || (!inFlowSeqAnyElement(StateStack.back()) &&
816 !inFlowMapAnyKey(StateStack.back())))
817 Padding = "\n";
818}
819
820void Output::outputNewLine() {
821 Out << "\n";
822 Column = 0;
823}
824
825// if seq at top, indent as if map, then add "- "
826// if seq in middle, use "- " if firstKey, else use " "
827//
828
829void Output::newLineCheck(bool EmptySequence) {
830 if (Padding != "\n") {
831 output(Padding);
832 Padding = {};
833 return;
834 }
835 outputNewLine();
836 Padding = {};
837
838 if (StateStack.size() == 0 || EmptySequence)
839 return;
840
841 unsigned Indent = StateStack.size() - 1;
842 bool PossiblyNestedSeq = false;
843 auto I = StateStack.rbegin(), E = StateStack.rend();
844
845 if (inSeqAnyElement(*I)) {
846 PossiblyNestedSeq = true; // Not possibly but always.
847 ++Indent;
848 } else if (*I == inMapFirstKey || *I == inFlowMapFirstKey ||
849 inFlowSeqAnyElement(*I)) {
850 PossiblyNestedSeq = true;
851 ++I; // Skip back().
852 }
853
854 unsigned OutputDashCount = 0;
855 if (PossiblyNestedSeq) {
856 // Count up consecutive inSeqFirstElement from the end, unless
857 // inSeqFirstElement is the top of nested sequence.
858 while (I != E) {
859 // Don't count the top of nested sequence.
860 if (!inSeqAnyElement(*I))
861 break;
862
863 ++OutputDashCount;
864
865 // Stop counting if consecutive inSeqFirstElement ends.
866 if (*I++ != inSeqFirstElement)
867 break;
868 }
869 }
870
871 for (unsigned I = OutputDashCount; I < Indent; ++I)
872 output(" ");
873
874 for (unsigned I = 0; I < OutputDashCount; ++I)
875 output("- ");
876}
877
878void Output::paddedKey(StringRef key) {
879 output(key, needsQuotes(key, false));
880 output(":");
881 const char *spaces = " ";
882 if (key.size() < strlen(spaces))
883 Padding = &spaces[key.size()];
884 else
885 Padding = " ";
886}
887
888void Output::flowKey(StringRef Key) {
889 if (StateStack.back() == inFlowMapOtherKey)
890 output(", ");
891 if (WrapColumn && Column > WrapColumn) {
892 output("\n");
893 for (int I = 0; I < ColumnAtMapFlowStart; ++I)
894 output(" ");
895 Column = ColumnAtMapFlowStart;
896 output(" ");
897 }
898 output(Key, needsQuotes(Key, false));
899 output(": ");
900}
901
902NodeKind Output::getNodeKind() { report_fatal_error("invalid call"); }
903
904bool Output::inSeqAnyElement(InState State) {
905 return State == inSeqFirstElement || State == inSeqOtherElement;
906}
907
908bool Output::inFlowSeqAnyElement(InState State) {
909 return State == inFlowSeqFirstElement || State == inFlowSeqOtherElement;
910}
911
912bool Output::inMapAnyKey(InState State) {
913 return State == inMapFirstKey || State == inMapOtherKey;
914}
915
916bool Output::inFlowMapAnyKey(InState State) {
917 return State == inFlowMapFirstKey || State == inFlowMapOtherKey;
918}
919
920//===----------------------------------------------------------------------===//
921// traits for built-in types
922//===----------------------------------------------------------------------===//
923
924void ScalarTraits<bool>::output(const bool &Val, void *, raw_ostream &Out) {
925 Out << (Val ? "true" : "false");
926}
927
928StringRef ScalarTraits<bool>::input(StringRef Scalar, void *, bool &Val) {
929 if (std::optional<bool> Parsed = parseBool(Scalar)) {
930 Val = *Parsed;
931 return StringRef();
932 }
933 return "invalid boolean";
934}
935
936void ScalarTraits<StringRef>::output(const StringRef &Val, void *,
937 raw_ostream &Out) {
938 Out << Val;
939}
940
941StringRef ScalarTraits<StringRef>::input(StringRef Scalar, void *,
942 StringRef &Val) {
943 Val = Scalar;
944 return StringRef();
945}
946
947void ScalarTraits<std::string>::output(const std::string &Val, void *,
948 raw_ostream &Out) {
949 Out << Val;
950}
951
952StringRef ScalarTraits<std::string>::input(StringRef Scalar, void *,
953 std::string &Val) {
954 Val = Scalar.str();
955 return StringRef();
956}
957
958void ScalarTraits<uint8_t>::output(const uint8_t &Val, void *,
959 raw_ostream &Out) {
960 // use temp uin32_t because ostream thinks uint8_t is a character
961 uint32_t Num = Val;
962 Out << Num;
963}
964
965StringRef ScalarTraits<uint8_t>::input(StringRef Scalar, void *, uint8_t &Val) {
966 unsigned long long n;
967 if (getAsUnsignedInteger(Scalar, 0, n))
968 return "invalid number";
969 if (n > 0xFF)
970 return "out of range number";
971 Val = n;
972 return StringRef();
973}
974
975void ScalarTraits<uint16_t>::output(const uint16_t &Val, void *,
976 raw_ostream &Out) {
977 Out << Val;
978}
979
980StringRef ScalarTraits<uint16_t>::input(StringRef Scalar, void *,
981 uint16_t &Val) {
982 unsigned long long n;
983 if (getAsUnsignedInteger(Scalar, 0, n))
984 return "invalid number";
985 if (n > 0xFFFF)
986 return "out of range number";
987 Val = n;
988 return StringRef();
989}
990
991void ScalarTraits<uint32_t>::output(const uint32_t &Val, void *,
992 raw_ostream &Out) {
993 Out << Val;
994}
995
996StringRef ScalarTraits<uint32_t>::input(StringRef Scalar, void *,
997 uint32_t &Val) {
998 unsigned long long n;
999 if (getAsUnsignedInteger(Scalar, 0, n))
1000 return "invalid number";
1001 if (n > 0xFFFFFFFFUL)
1002 return "out of range number";
1003 Val = n;
1004 return StringRef();
1005}
1006
1007void ScalarTraits<uint64_t>::output(const uint64_t &Val, void *,
1008 raw_ostream &Out) {
1009 Out << Val;
1010}
1011
1012StringRef ScalarTraits<uint64_t>::input(StringRef Scalar, void *,
1013 uint64_t &Val) {
1014 unsigned long long N;
1015 if (getAsUnsignedInteger(Scalar, 0, N))
1016 return "invalid number";
1017 Val = N;
1018 return StringRef();
1019}
1020
1021void ScalarTraits<int8_t>::output(const int8_t &Val, void *, raw_ostream &Out) {
1022 // use temp in32_t because ostream thinks int8_t is a character
1023 int32_t Num = Val;
1024 Out << Num;
1025}
1026
1027StringRef ScalarTraits<int8_t>::input(StringRef Scalar, void *, int8_t &Val) {
1028 long long N;
1029 if (getAsSignedInteger(Scalar, 0, N))
1030 return "invalid number";
1031 if ((N > 127) || (N < -128))
1032 return "out of range number";
1033 Val = N;
1034 return StringRef();
1035}
1036
1037void ScalarTraits<int16_t>::output(const int16_t &Val, void *,
1038 raw_ostream &Out) {
1039 Out << Val;
1040}
1041
1042StringRef ScalarTraits<int16_t>::input(StringRef Scalar, void *, int16_t &Val) {
1043 long long N;
1044 if (getAsSignedInteger(Scalar, 0, N))
1045 return "invalid number";
1046 if ((N > INT16_MAX) || (N < INT16_MIN))
1047 return "out of range number";
1048 Val = N;
1049 return StringRef();
1050}
1051
1052void ScalarTraits<int32_t>::output(const int32_t &Val, void *,
1053 raw_ostream &Out) {
1054 Out << Val;
1055}
1056
1057StringRef ScalarTraits<int32_t>::input(StringRef Scalar, void *, int32_t &Val) {
1058 long long N;
1059 if (getAsSignedInteger(Scalar, 0, N))
1060 return "invalid number";
1061 if ((N > INT32_MAX) || (N < INT32_MIN))
1062 return "out of range number";
1063 Val = N;
1064 return StringRef();
1065}
1066
1067void ScalarTraits<int64_t>::output(const int64_t &Val, void *,
1068 raw_ostream &Out) {
1069 Out << Val;
1070}
1071
1072StringRef ScalarTraits<int64_t>::input(StringRef Scalar, void *, int64_t &Val) {
1073 long long N;
1074 if (getAsSignedInteger(Scalar, 0, N))
1075 return "invalid number";
1076 Val = N;
1077 return StringRef();
1078}
1079
1080void ScalarTraits<double>::output(const double &Val, void *, raw_ostream &Out) {
1081 Out << format("%g", Val);
1082}
1083
1084StringRef ScalarTraits<double>::input(StringRef Scalar, void *, double &Val) {
1085 if (to_float(Scalar, Val))
1086 return StringRef();
1087 return "invalid floating point number";
1088}
1089
1090void ScalarTraits<float>::output(const float &Val, void *, raw_ostream &Out) {
1091 Out << format("%g", Val);
1092}
1093
1094StringRef ScalarTraits<float>::input(StringRef Scalar, void *, float &Val) {
1095 if (to_float(Scalar, Val))
1096 return StringRef();
1097 return "invalid floating point number";
1098}
1099
1100void ScalarTraits<Hex8>::output(const Hex8 &Val, void *, raw_ostream &Out) {
1101 Out << format("0x%" PRIX8, (uint8_t)Val);
1102}
1103
1104StringRef ScalarTraits<Hex8>::input(StringRef Scalar, void *, Hex8 &Val) {
1105 unsigned long long n;
1106 if (getAsUnsignedInteger(Scalar, 0, n))
1107 return "invalid hex8 number";
1108 if (n > 0xFF)
1109 return "out of range hex8 number";
1110 Val = n;
1111 return StringRef();
1112}
1113
1114void ScalarTraits<Hex16>::output(const Hex16 &Val, void *, raw_ostream &Out) {
1115 Out << format("0x%" PRIX16, (uint16_t)Val);
1116}
1117
1118StringRef ScalarTraits<Hex16>::input(StringRef Scalar, void *, Hex16 &Val) {
1119 unsigned long long n;
1120 if (getAsUnsignedInteger(Scalar, 0, n))
1121 return "invalid hex16 number";
1122 if (n > 0xFFFF)
1123 return "out of range hex16 number";
1124 Val = n;
1125 return StringRef();
1126}
1127
1128void ScalarTraits<Hex32>::output(const Hex32 &Val, void *, raw_ostream &Out) {
1129 Out << format("0x%" PRIX32, (uint32_t)Val);
1130}
1131
1132StringRef ScalarTraits<Hex32>::input(StringRef Scalar, void *, Hex32 &Val) {
1133 unsigned long long n;
1134 if (getAsUnsignedInteger(Scalar, 0, n))
1135 return "invalid hex32 number";
1136 if (n > 0xFFFFFFFFUL)
1137 return "out of range hex32 number";
1138 Val = n;
1139 return StringRef();
1140}
1141
1142void ScalarTraits<Hex64>::output(const Hex64 &Val, void *, raw_ostream &Out) {
1143 Out << format("0x%" PRIX64, (uint64_t)Val);
1144}
1145
1146StringRef ScalarTraits<Hex64>::input(StringRef Scalar, void *, Hex64 &Val) {
1147 unsigned long long Num;
1148 if (getAsUnsignedInteger(Scalar, 0, Num))
1149 return "invalid hex64 number";
1150 Val = Num;
1151 return StringRef();
1152}
1153
1154void ScalarTraits<VersionTuple>::output(const VersionTuple &Val, void *,
1155 llvm::raw_ostream &Out) {
1156 Out << Val.getAsString();
1157}
1158
1159StringRef ScalarTraits<VersionTuple>::input(StringRef Scalar, void *,
1160 VersionTuple &Val) {
1161 if (Val.tryParse(Scalar))
1162 return "invalid version format";
1163 return StringRef();
1164}
@ Default
Definition: DwarfDebug.cpp:87
bool End
Definition: ELF_riscv.cpp:480
Infer address spaces
#define I(x, y, z)
Definition: MD5.cpp:58
#define P(N)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file contains some templates that are useful if you are working with the STL at all.
This file defines the SmallString class.
This file contains some functions that are useful when dealing with strings.
static void DiagHandler(const SMDiagnostic &Diag, void *Context)
Definition: TextStub.cpp:1060
Defines the llvm::VersionTuple class, which represents a version in the form major[....
static std::unique_ptr< MemoryBuffer > getMemBuffer(StringRef InputData, StringRef BufferName="", bool RequiresNullTerminator=true)
Open the specified memory range as a MemoryBuffer.
Represents a range in source code.
Definition: SMLoc.h:48
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition: SmallString.h:26
StringRef str() const
Explicit conversion to StringRef.
Definition: SmallString.h:254
bool empty() const
Definition: SmallVector.h:81
void(*)(const SMDiagnostic &, void *Context) DiagHandlerTy
Clients that want to handle their own diagnostics in a custom way can register a function pointer+con...
Definition: SourceMgr.h:43
void setDiagHandler(DiagHandlerTy DH, void *Ctx=nullptr)
Specify a diagnostic handler to be invoked every time PrintMessage is called.
Definition: SourceMgr.h:112
A wrapper around a string literal that serves as a proxy for constructing global tables of StringRefs...
Definition: StringRef.h:853
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:51
constexpr bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:147
constexpr size_t size() const
size - Get the string size.
Definition: StringRef.h:150
constexpr const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
Definition: StringRef.h:144
StringRef copy(Allocator &A) const
Definition: StringRef.h:166
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:81
A Use represents the edge between a Value definition and its users.
Definition: Use.h:43
LLVM Value Representation.
Definition: Value.h:74
Represents a version number in the form major[.minor[.subminor[.build]]].
Definition: VersionTuple.h:29
bool tryParse(StringRef string)
Try to parse the given string as a version number.
std::string getAsString() const
Retrieve a string representation of the version number.
A forward iterator which reads text lines from a buffer.
Definition: LineIterator.h:33
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
A block scalar node is an opaque datum that can be presented as a series of zero or more Unicode scal...
Definition: YAMLParser.h:260
StringRef getValue() const
Gets the value of this node as a StringRef.
Definition: YAMLParser.h:273
A key and value pair.
Definition: YAMLParser.h:290
Represents a YAML map created from either a block map for a flow map.
Definition: YAMLParser.h:419
A scalar node is an opaque datum that can be presented as a series of zero or more Unicode scalar val...
Definition: YAMLParser.h:212
StringRef getValue(SmallVectorImpl< char > &Storage) const
Gets the value of this node as a StringRef.
Represents a YAML sequence created from either a block sequence for a flow sequence.
Definition: YAMLParser.h:467
This class represents a YAML stream potentially containing multiple documents.
Definition: YAMLParser.h:86
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Key
PAL metadata keys.
@ Entry
Definition: COFF.h:844
std::optional< bool > parseBool(StringRef S)
Parse S as a bool according to https://yaml.org/type/bool.html.
Definition: YAMLParser.cpp:770
std::string escape(StringRef Input, bool EscapePrintable=true)
Escape Input for a double quoted scalar; if EscapePrintable is true, all UTF8 sequences will be escap...
Definition: YAMLParser.cpp:704
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
bool getAsSignedInteger(StringRef Str, unsigned Radix, long long &Result)
Definition: StringRef.cpp:498
std::error_code make_error_code(BitcodeError E)
SourceMgr SrcMgr
Definition: Error.cpp:24
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:167
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition: Format.h:125
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition: STLExtras.h:1903
bool getAsUnsignedInteger(StringRef Str, unsigned Radix, unsigned long long &Result)
Helper functions for StringRef::getAsInteger.
Definition: StringRef.cpp:488
#define N
Determine the kind of a node from its type.