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