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