LLVM 20.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
753bool Output::canElideEmptySequence() {
754 // Normally, with an optional key/value where the value is an empty sequence,
755 // the whole key/value can be not written. But, that produces wrong yaml
756 // if the key/value is the only thing in the map and the map is used in
757 // a sequence. This detects if the this sequence is the first key/value
758 // in map that itself is embedded in a sequence.
759 if (StateStack.size() < 2)
760 return true;
761 if (StateStack.back() != inMapFirstKey)
762 return true;
763 return !inSeqAnyElement(StateStack[StateStack.size() - 2]);
764}
765
766void Output::output(StringRef s) {
767 Column += s.size();
768 Out << s;
769}
770
771void Output::output(StringRef S, QuotingType MustQuote) {
772 if (MustQuote == QuotingType::None) {
773 // Only quote if we must.
774 output(S);
775 return;
776 }
777
778 StringLiteral Quote = MustQuote == QuotingType::Single ? StringLiteral("'")
779 : StringLiteral("\"");
780 output(Quote); // Starting quote.
781
782 // When using double-quoted strings (and only in that case), non-printable
783 // characters may be present, and will be escaped using a variety of
784 // unicode-scalar and special short-form escapes. This is handled in
785 // yaml::escape.
786 if (MustQuote == QuotingType::Double) {
787 output(yaml::escape(S, /* EscapePrintable= */ false));
788 output(Quote);
789 return;
790 }
791
792 unsigned i = 0;
793 unsigned j = 0;
794 unsigned End = S.size();
795 const char *Base = S.data();
796
797 // When using single-quoted strings, any single quote ' must be doubled to be
798 // escaped.
799 while (j < End) {
800 if (S[j] == '\'') { // Escape quotes.
801 output(StringRef(&Base[i], j - i)); // "flush".
802 output(StringLiteral("''")); // Print it as ''
803 i = j + 1;
804 }
805 ++j;
806 }
807 output(StringRef(&Base[i], j - i));
808 output(Quote); // Ending quote.
809}
810
811void Output::outputUpToEndOfLine(StringRef s) {
812 output(s);
813 if (StateStack.empty() || (!inFlowSeqAnyElement(StateStack.back()) &&
814 !inFlowMapAnyKey(StateStack.back())))
815 Padding = "\n";
816}
817
818void Output::outputNewLine() {
819 Out << "\n";
820 Column = 0;
821}
822
823// if seq at top, indent as if map, then add "- "
824// if seq in middle, use "- " if firstKey, else use " "
825//
826
827void Output::newLineCheck(bool EmptySequence) {
828 if (Padding != "\n") {
829 output(Padding);
830 Padding = {};
831 return;
832 }
833 outputNewLine();
834 Padding = {};
835
836 if (StateStack.size() == 0 || EmptySequence)
837 return;
838
839 unsigned Indent = StateStack.size() - 1;
840 bool PossiblyNestedSeq = false;
841 auto I = StateStack.rbegin(), E = StateStack.rend();
842
843 if (inSeqAnyElement(*I)) {
844 PossiblyNestedSeq = true; // Not possibly but always.
845 ++Indent;
846 } else if (*I == inMapFirstKey || *I == inFlowMapFirstKey ||
847 inFlowSeqAnyElement(*I)) {
848 PossiblyNestedSeq = true;
849 ++I; // Skip back().
850 }
851
852 unsigned OutputDashCount = 0;
853 if (PossiblyNestedSeq) {
854 // Count up consecutive inSeqFirstElement from the end, unless
855 // inSeqFirstElement is the top of nested sequence.
856 while (I != E) {
857 // Don't count the top of nested sequence.
858 if (!inSeqAnyElement(*I))
859 break;
860
861 ++OutputDashCount;
862
863 // Stop counting if consecutive inSeqFirstElement ends.
864 if (*I++ != inSeqFirstElement)
865 break;
866 }
867 }
868
869 for (unsigned I = OutputDashCount; I < Indent; ++I)
870 output(" ");
871
872 for (unsigned I = 0; I < OutputDashCount; ++I)
873 output("- ");
874}
875
876void Output::paddedKey(StringRef key) {
877 output(key, needsQuotes(key, false));
878 output(":");
879 const char *spaces = " ";
880 if (key.size() < strlen(spaces))
881 Padding = &spaces[key.size()];
882 else
883 Padding = " ";
884}
885
886void Output::flowKey(StringRef Key) {
887 if (StateStack.back() == inFlowMapOtherKey)
888 output(", ");
889 if (WrapColumn && Column > WrapColumn) {
890 output("\n");
891 for (int I = 0; I < ColumnAtMapFlowStart; ++I)
892 output(" ");
893 Column = ColumnAtMapFlowStart;
894 output(" ");
895 }
896 output(Key, needsQuotes(Key, false));
897 output(": ");
898}
899
900NodeKind Output::getNodeKind() { report_fatal_error("invalid call"); }
901
902bool Output::inSeqAnyElement(InState State) {
903 return State == inSeqFirstElement || State == inSeqOtherElement;
904}
905
906bool Output::inFlowSeqAnyElement(InState State) {
907 return State == inFlowSeqFirstElement || State == inFlowSeqOtherElement;
908}
909
910bool Output::inMapAnyKey(InState State) {
911 return State == inMapFirstKey || State == inMapOtherKey;
912}
913
914bool Output::inFlowMapAnyKey(InState State) {
915 return State == inFlowMapFirstKey || State == inFlowMapOtherKey;
916}
917
918//===----------------------------------------------------------------------===//
919// traits for built-in types
920//===----------------------------------------------------------------------===//
921
922void ScalarTraits<bool>::output(const bool &Val, void *, raw_ostream &Out) {
923 Out << (Val ? "true" : "false");
924}
925
926StringRef ScalarTraits<bool>::input(StringRef Scalar, void *, bool &Val) {
927 if (std::optional<bool> Parsed = parseBool(Scalar)) {
928 Val = *Parsed;
929 return StringRef();
930 }
931 return "invalid boolean";
932}
933
934void ScalarTraits<StringRef>::output(const StringRef &Val, void *,
935 raw_ostream &Out) {
936 Out << Val;
937}
938
939StringRef ScalarTraits<StringRef>::input(StringRef Scalar, void *,
940 StringRef &Val) {
941 Val = Scalar;
942 return StringRef();
943}
944
945void ScalarTraits<std::string>::output(const std::string &Val, void *,
946 raw_ostream &Out) {
947 Out << Val;
948}
949
950StringRef ScalarTraits<std::string>::input(StringRef Scalar, void *,
951 std::string &Val) {
952 Val = Scalar.str();
953 return StringRef();
954}
955
956void ScalarTraits<uint8_t>::output(const uint8_t &Val, void *,
957 raw_ostream &Out) {
958 // use temp uin32_t because ostream thinks uint8_t is a character
959 uint32_t Num = Val;
960 Out << Num;
961}
962
963StringRef ScalarTraits<uint8_t>::input(StringRef Scalar, void *, uint8_t &Val) {
964 unsigned long long n;
965 if (getAsUnsignedInteger(Scalar, 0, n))
966 return "invalid number";
967 if (n > 0xFF)
968 return "out of range number";
969 Val = n;
970 return StringRef();
971}
972
973void ScalarTraits<uint16_t>::output(const uint16_t &Val, void *,
974 raw_ostream &Out) {
975 Out << Val;
976}
977
978StringRef ScalarTraits<uint16_t>::input(StringRef Scalar, void *,
979 uint16_t &Val) {
980 unsigned long long n;
981 if (getAsUnsignedInteger(Scalar, 0, n))
982 return "invalid number";
983 if (n > 0xFFFF)
984 return "out of range number";
985 Val = n;
986 return StringRef();
987}
988
989void ScalarTraits<uint32_t>::output(const uint32_t &Val, void *,
990 raw_ostream &Out) {
991 Out << Val;
992}
993
994StringRef ScalarTraits<uint32_t>::input(StringRef Scalar, void *,
995 uint32_t &Val) {
996 unsigned long long n;
997 if (getAsUnsignedInteger(Scalar, 0, n))
998 return "invalid number";
999 if (n > 0xFFFFFFFFUL)
1000 return "out of range number";
1001 Val = n;
1002 return StringRef();
1003}
1004
1005void ScalarTraits<uint64_t>::output(const uint64_t &Val, void *,
1006 raw_ostream &Out) {
1007 Out << Val;
1008}
1009
1010StringRef ScalarTraits<uint64_t>::input(StringRef Scalar, void *,
1011 uint64_t &Val) {
1012 unsigned long long N;
1013 if (getAsUnsignedInteger(Scalar, 0, N))
1014 return "invalid number";
1015 Val = N;
1016 return StringRef();
1017}
1018
1019void ScalarTraits<int8_t>::output(const int8_t &Val, void *, raw_ostream &Out) {
1020 // use temp in32_t because ostream thinks int8_t is a character
1021 int32_t Num = Val;
1022 Out << Num;
1023}
1024
1025StringRef ScalarTraits<int8_t>::input(StringRef Scalar, void *, int8_t &Val) {
1026 long long N;
1027 if (getAsSignedInteger(Scalar, 0, N))
1028 return "invalid number";
1029 if ((N > 127) || (N < -128))
1030 return "out of range number";
1031 Val = N;
1032 return StringRef();
1033}
1034
1035void ScalarTraits<int16_t>::output(const int16_t &Val, void *,
1036 raw_ostream &Out) {
1037 Out << Val;
1038}
1039
1040StringRef ScalarTraits<int16_t>::input(StringRef Scalar, void *, int16_t &Val) {
1041 long long N;
1042 if (getAsSignedInteger(Scalar, 0, N))
1043 return "invalid number";
1044 if ((N > INT16_MAX) || (N < INT16_MIN))
1045 return "out of range number";
1046 Val = N;
1047 return StringRef();
1048}
1049
1050void ScalarTraits<int32_t>::output(const int32_t &Val, void *,
1051 raw_ostream &Out) {
1052 Out << Val;
1053}
1054
1055StringRef ScalarTraits<int32_t>::input(StringRef Scalar, void *, int32_t &Val) {
1056 long long N;
1057 if (getAsSignedInteger(Scalar, 0, N))
1058 return "invalid number";
1059 if ((N > INT32_MAX) || (N < INT32_MIN))
1060 return "out of range number";
1061 Val = N;
1062 return StringRef();
1063}
1064
1065void ScalarTraits<int64_t>::output(const int64_t &Val, void *,
1066 raw_ostream &Out) {
1067 Out << Val;
1068}
1069
1070StringRef ScalarTraits<int64_t>::input(StringRef Scalar, void *, int64_t &Val) {
1071 long long N;
1072 if (getAsSignedInteger(Scalar, 0, N))
1073 return "invalid number";
1074 Val = N;
1075 return StringRef();
1076}
1077
1078void ScalarTraits<double>::output(const double &Val, void *, raw_ostream &Out) {
1079 Out << format("%g", Val);
1080}
1081
1082StringRef ScalarTraits<double>::input(StringRef Scalar, void *, double &Val) {
1083 if (to_float(Scalar, Val))
1084 return StringRef();
1085 return "invalid floating point number";
1086}
1087
1088void ScalarTraits<float>::output(const float &Val, void *, raw_ostream &Out) {
1089 Out << format("%g", Val);
1090}
1091
1092StringRef ScalarTraits<float>::input(StringRef Scalar, void *, float &Val) {
1093 if (to_float(Scalar, Val))
1094 return StringRef();
1095 return "invalid floating point number";
1096}
1097
1098void ScalarTraits<Hex8>::output(const Hex8 &Val, void *, raw_ostream &Out) {
1099 Out << format("0x%" PRIX8, (uint8_t)Val);
1100}
1101
1102StringRef ScalarTraits<Hex8>::input(StringRef Scalar, void *, Hex8 &Val) {
1103 unsigned long long n;
1104 if (getAsUnsignedInteger(Scalar, 0, n))
1105 return "invalid hex8 number";
1106 if (n > 0xFF)
1107 return "out of range hex8 number";
1108 Val = n;
1109 return StringRef();
1110}
1111
1112void ScalarTraits<Hex16>::output(const Hex16 &Val, void *, raw_ostream &Out) {
1113 Out << format("0x%" PRIX16, (uint16_t)Val);
1114}
1115
1116StringRef ScalarTraits<Hex16>::input(StringRef Scalar, void *, Hex16 &Val) {
1117 unsigned long long n;
1118 if (getAsUnsignedInteger(Scalar, 0, n))
1119 return "invalid hex16 number";
1120 if (n > 0xFFFF)
1121 return "out of range hex16 number";
1122 Val = n;
1123 return StringRef();
1124}
1125
1126void ScalarTraits<Hex32>::output(const Hex32 &Val, void *, raw_ostream &Out) {
1127 Out << format("0x%" PRIX32, (uint32_t)Val);
1128}
1129
1130StringRef ScalarTraits<Hex32>::input(StringRef Scalar, void *, Hex32 &Val) {
1131 unsigned long long n;
1132 if (getAsUnsignedInteger(Scalar, 0, n))
1133 return "invalid hex32 number";
1134 if (n > 0xFFFFFFFFUL)
1135 return "out of range hex32 number";
1136 Val = n;
1137 return StringRef();
1138}
1139
1140void ScalarTraits<Hex64>::output(const Hex64 &Val, void *, raw_ostream &Out) {
1141 Out << format("0x%" PRIX64, (uint64_t)Val);
1142}
1143
1144StringRef ScalarTraits<Hex64>::input(StringRef Scalar, void *, Hex64 &Val) {
1145 unsigned long long Num;
1146 if (getAsUnsignedInteger(Scalar, 0, Num))
1147 return "invalid hex64 number";
1148 Val = Num;
1149 return StringRef();
1150}
1151
1152void ScalarTraits<VersionTuple>::output(const VersionTuple &Val, void *,
1153 llvm::raw_ostream &Out) {
1154 Out << Val.getAsString();
1155}
1156
1157StringRef ScalarTraits<VersionTuple>::input(StringRef Scalar, void *,
1158 VersionTuple &Val) {
1159 if (Val.tryParse(Scalar))
1160 return "invalid version format";
1161 return StringRef();
1162}
@ 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.