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