1 //===- lib/Support/YAMLTraits.cpp -----------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "llvm/Support/YAMLTraits.h"
10 #include "llvm/ADT/STLExtras.h"
11 #include "llvm/ADT/SmallString.h"
12 #include "llvm/ADT/StringExtras.h"
13 #include "llvm/ADT/StringRef.h"
14 #include "llvm/ADT/Twine.h"
15 #include "llvm/Support/Casting.h"
16 #include "llvm/Support/Errc.h"
17 #include "llvm/Support/ErrorHandling.h"
18 #include "llvm/Support/Format.h"
19 #include "llvm/Support/LineIterator.h"
20 #include "llvm/Support/MemoryBuffer.h"
21 #include "llvm/Support/VersionTuple.h"
22 #include "llvm/Support/YAMLParser.h"
23 #include "llvm/Support/raw_ostream.h"
33 //===----------------------------------------------------------------------===//
35 //===----------------------------------------------------------------------===//
37 IO::IO(void *Context
) : Ctxt(Context
) {}
41 void *IO::getContext() const {
45 void IO::setContext(void *Context
) {
49 void IO::setAllowUnknownKeys(bool Allow
) {
50 llvm_unreachable("Only supported for Input");
53 //===----------------------------------------------------------------------===//
55 //===----------------------------------------------------------------------===//
57 Input::Input(StringRef InputContent
, void *Ctxt
,
58 SourceMgr::DiagHandlerTy DiagHandler
, void *DiagHandlerCtxt
)
59 : IO(Ctxt
), Strm(new Stream(InputContent
, SrcMgr
, false, &EC
)) {
61 SrcMgr
.setDiagHandler(DiagHandler
, DiagHandlerCtxt
);
62 DocIterator
= Strm
->begin();
65 Input::Input(MemoryBufferRef Input
, void *Ctxt
,
66 SourceMgr::DiagHandlerTy DiagHandler
, void *DiagHandlerCtxt
)
67 : IO(Ctxt
), Strm(new Stream(Input
, SrcMgr
, false, &EC
)) {
69 SrcMgr
.setDiagHandler(DiagHandler
, DiagHandlerCtxt
);
70 DocIterator
= Strm
->begin();
73 Input::~Input() = default;
75 std::error_code
Input::error() { return EC
; }
77 bool Input::outputting() const {
81 bool Input::setCurrentDocument() {
82 if (DocIterator
!= Strm
->end()) {
83 Node
*N
= DocIterator
->getRoot();
85 EC
= make_error_code(errc::invalid_argument
);
89 if (isa
<NullNode
>(N
)) {
90 // Empty files are allowed and ignored
92 return setCurrentDocument();
94 releaseHNodeBuffers();
95 TopNode
= createHNodes(N
);
96 CurrentNode
= TopNode
;
102 bool Input::nextDocument() {
103 return ++DocIterator
!= Strm
->end();
106 const Node
*Input::getCurrentNode() const {
107 return CurrentNode
? CurrentNode
->_node
: nullptr;
110 bool Input::mapTag(StringRef Tag
, bool Default
) {
111 // CurrentNode can be null if setCurrentDocument() was unable to
112 // parse the document because it was invalid or empty.
116 std::string foundTag
= CurrentNode
->_node
->getVerbatimTag();
117 if (foundTag
.empty()) {
118 // If no tag found and 'Tag' is the default, say it was found.
121 // Return true iff found tag matches supplied tag.
122 return Tag
== foundTag
;
125 void Input::beginMapping() {
128 // CurrentNode can be null if the document is empty.
129 MapHNode
*MN
= dyn_cast_or_null
<MapHNode
>(CurrentNode
);
131 MN
->ValidKeys
.clear();
135 std::vector
<StringRef
> Input::keys() {
136 MapHNode
*MN
= dyn_cast
<MapHNode
>(CurrentNode
);
137 std::vector
<StringRef
> Ret
;
139 setError(CurrentNode
, "not a mapping");
142 for (auto &P
: MN
->Mapping
)
143 Ret
.push_back(P
.first());
147 bool Input::preflightKey(const char *Key
, bool Required
, bool, bool &UseDefault
,
153 // CurrentNode is null for empty documents, which is an error in case required
154 // nodes are present.
157 EC
= make_error_code(errc::invalid_argument
);
163 MapHNode
*MN
= dyn_cast
<MapHNode
>(CurrentNode
);
165 if (Required
|| !isa
<EmptyHNode
>(CurrentNode
))
166 setError(CurrentNode
, "not a mapping");
171 MN
->ValidKeys
.push_back(Key
);
172 HNode
*Value
= MN
->Mapping
[Key
].first
;
175 setError(CurrentNode
, Twine("missing required key '") + Key
+ "'");
180 SaveInfo
= CurrentNode
;
185 void Input::postflightKey(void *saveInfo
) {
186 CurrentNode
= reinterpret_cast<HNode
*>(saveInfo
);
189 void Input::endMapping() {
192 // CurrentNode can be null if the document is empty.
193 MapHNode
*MN
= dyn_cast_or_null
<MapHNode
>(CurrentNode
);
196 for (const auto &NN
: MN
->Mapping
) {
197 if (!is_contained(MN
->ValidKeys
, NN
.first())) {
198 const SMRange
&ReportLoc
= NN
.second
.second
;
199 if (!AllowUnknownKeys
) {
200 setError(ReportLoc
, Twine("unknown key '") + NN
.first() + "'");
203 reportWarning(ReportLoc
, Twine("unknown key '") + NN
.first() + "'");
208 void Input::beginFlowMapping() { beginMapping(); }
210 void Input::endFlowMapping() { endMapping(); }
212 unsigned Input::beginSequence() {
213 if (SequenceHNode
*SQ
= dyn_cast
<SequenceHNode
>(CurrentNode
))
214 return SQ
->Entries
.size();
215 if (isa
<EmptyHNode
>(CurrentNode
))
217 // Treat case where there's a scalar "null" value as an empty sequence.
218 if (ScalarHNode
*SN
= dyn_cast
<ScalarHNode
>(CurrentNode
)) {
219 if (isNull(SN
->value()))
222 // Any other type of HNode is an error.
223 setError(CurrentNode
, "not a sequence");
227 void Input::endSequence() {
230 bool Input::preflightElement(unsigned Index
, void *&SaveInfo
) {
233 if (SequenceHNode
*SQ
= dyn_cast
<SequenceHNode
>(CurrentNode
)) {
234 SaveInfo
= CurrentNode
;
235 CurrentNode
= SQ
->Entries
[Index
];
241 void Input::postflightElement(void *SaveInfo
) {
242 CurrentNode
= reinterpret_cast<HNode
*>(SaveInfo
);
245 unsigned Input::beginFlowSequence() { return beginSequence(); }
247 bool Input::preflightFlowElement(unsigned index
, void *&SaveInfo
) {
250 if (SequenceHNode
*SQ
= dyn_cast
<SequenceHNode
>(CurrentNode
)) {
251 SaveInfo
= CurrentNode
;
252 CurrentNode
= SQ
->Entries
[index
];
258 void Input::postflightFlowElement(void *SaveInfo
) {
259 CurrentNode
= reinterpret_cast<HNode
*>(SaveInfo
);
262 void Input::endFlowSequence() {
265 void Input::beginEnumScalar() {
266 ScalarMatchFound
= false;
269 bool Input::matchEnumScalar(const char *Str
, bool) {
270 if (ScalarMatchFound
)
272 if (ScalarHNode
*SN
= dyn_cast
<ScalarHNode
>(CurrentNode
)) {
273 if (SN
->value() == Str
) {
274 ScalarMatchFound
= true;
281 bool Input::matchEnumFallback() {
282 if (ScalarMatchFound
)
284 ScalarMatchFound
= true;
288 void Input::endEnumScalar() {
289 if (!ScalarMatchFound
) {
290 setError(CurrentNode
, "unknown enumerated scalar");
294 bool Input::beginBitSetScalar(bool &DoClear
) {
295 BitValuesUsed
.clear();
296 if (SequenceHNode
*SQ
= dyn_cast
<SequenceHNode
>(CurrentNode
)) {
297 BitValuesUsed
.resize(SQ
->Entries
.size());
299 setError(CurrentNode
, "expected sequence of bit values");
305 bool Input::bitSetMatch(const char *Str
, bool) {
308 if (SequenceHNode
*SQ
= dyn_cast
<SequenceHNode
>(CurrentNode
)) {
310 for (auto &N
: SQ
->Entries
) {
311 if (ScalarHNode
*SN
= dyn_cast
<ScalarHNode
>(N
)) {
312 if (SN
->value() == Str
) {
313 BitValuesUsed
[Index
] = true;
317 setError(CurrentNode
, "unexpected scalar in sequence of bit values");
322 setError(CurrentNode
, "expected sequence of bit values");
327 void Input::endBitSetScalar() {
330 if (SequenceHNode
*SQ
= dyn_cast
<SequenceHNode
>(CurrentNode
)) {
331 assert(BitValuesUsed
.size() == SQ
->Entries
.size());
332 for (unsigned i
= 0; i
< SQ
->Entries
.size(); ++i
) {
333 if (!BitValuesUsed
[i
]) {
334 setError(SQ
->Entries
[i
], "unknown bit value");
341 void Input::scalarString(StringRef
&S
, QuotingType
) {
342 if (ScalarHNode
*SN
= dyn_cast
<ScalarHNode
>(CurrentNode
)) {
345 setError(CurrentNode
, "unexpected scalar");
349 void Input::blockScalarString(StringRef
&S
) { scalarString(S
, QuotingType::None
); }
351 void Input::scalarTag(std::string
&Tag
) {
352 Tag
= CurrentNode
->_node
->getVerbatimTag();
355 void Input::setError(HNode
*hnode
, const Twine
&message
) {
356 assert(hnode
&& "HNode must not be NULL");
357 setError(hnode
->_node
, message
);
360 NodeKind
Input::getNodeKind() {
361 if (isa
<ScalarHNode
>(CurrentNode
))
362 return NodeKind::Scalar
;
363 else if (isa
<MapHNode
>(CurrentNode
))
364 return NodeKind::Map
;
365 else if (isa
<SequenceHNode
>(CurrentNode
))
366 return NodeKind::Sequence
;
367 llvm_unreachable("Unsupported node kind");
370 void Input::setError(Node
*node
, const Twine
&message
) {
371 Strm
->printError(node
, message
);
372 EC
= make_error_code(errc::invalid_argument
);
375 void Input::setError(const SMRange
&range
, const Twine
&message
) {
376 Strm
->printError(range
, message
);
377 EC
= make_error_code(errc::invalid_argument
);
380 void Input::reportWarning(HNode
*hnode
, const Twine
&message
) {
381 assert(hnode
&& "HNode must not be NULL");
382 Strm
->printError(hnode
->_node
, message
, SourceMgr::DK_Warning
);
385 void Input::reportWarning(Node
*node
, const Twine
&message
) {
386 Strm
->printError(node
, message
, SourceMgr::DK_Warning
);
389 void Input::reportWarning(const SMRange
&range
, const Twine
&message
) {
390 Strm
->printError(range
, message
, SourceMgr::DK_Warning
);
393 void Input::releaseHNodeBuffers() {
394 EmptyHNodeAllocator
.DestroyAll();
395 ScalarHNodeAllocator
.DestroyAll();
396 SequenceHNodeAllocator
.DestroyAll();
397 MapHNodeAllocator
.DestroyAll();
400 Input::HNode
*Input::createHNodes(Node
*N
) {
401 SmallString
<128> StringStorage
;
402 switch (N
->getType()) {
403 case Node::NK_Scalar
: {
404 ScalarNode
*SN
= dyn_cast
<ScalarNode
>(N
);
405 StringRef KeyStr
= SN
->getValue(StringStorage
);
406 if (!StringStorage
.empty()) {
407 // Copy string to permanent storage
408 KeyStr
= StringStorage
.str().copy(StringAllocator
);
410 return new (ScalarHNodeAllocator
.Allocate()) ScalarHNode(N
, KeyStr
);
412 case Node::NK_BlockScalar
: {
413 BlockScalarNode
*BSN
= dyn_cast
<BlockScalarNode
>(N
);
414 StringRef ValueCopy
= BSN
->getValue().copy(StringAllocator
);
415 return new (ScalarHNodeAllocator
.Allocate()) ScalarHNode(N
, ValueCopy
);
417 case Node::NK_Sequence
: {
418 SequenceNode
*SQ
= dyn_cast
<SequenceNode
>(N
);
419 auto SQHNode
= new (SequenceHNodeAllocator
.Allocate()) SequenceHNode(N
);
420 for (Node
&SN
: *SQ
) {
421 auto Entry
= createHNodes(&SN
);
424 SQHNode
->Entries
.push_back(Entry
);
428 case Node::NK_Mapping
: {
429 MappingNode
*Map
= dyn_cast
<MappingNode
>(N
);
430 auto mapHNode
= new (MapHNodeAllocator
.Allocate()) MapHNode(N
);
431 for (KeyValueNode
&KVN
: *Map
) {
432 Node
*KeyNode
= KVN
.getKey();
433 ScalarNode
*Key
= dyn_cast_or_null
<ScalarNode
>(KeyNode
);
434 Node
*Value
= KVN
.getValue();
435 if (!Key
|| !Value
) {
437 setError(KeyNode
, "Map key must be a scalar");
439 setError(KeyNode
, "Map value must not be empty");
442 StringStorage
.clear();
443 StringRef KeyStr
= Key
->getValue(StringStorage
);
444 if (!StringStorage
.empty()) {
445 // Copy string to permanent storage
446 KeyStr
= StringStorage
.str().copy(StringAllocator
);
448 if (mapHNode
->Mapping
.count(KeyStr
))
449 // From YAML spec: "The content of a mapping node is an unordered set of
450 // key/value node pairs, with the restriction that each of the keys is
452 setError(KeyNode
, Twine("duplicated mapping key '") + KeyStr
+ "'");
453 auto ValueHNode
= createHNodes(Value
);
456 mapHNode
->Mapping
[KeyStr
] =
457 std::make_pair(std::move(ValueHNode
), KeyNode
->getSourceRange());
459 return std::move(mapHNode
);
462 return new (EmptyHNodeAllocator
.Allocate()) EmptyHNode(N
);
464 setError(N
, "unknown node kind");
469 void Input::setError(const Twine
&Message
) {
470 setError(CurrentNode
, Message
);
473 void Input::setAllowUnknownKeys(bool Allow
) { AllowUnknownKeys
= Allow
; }
475 bool Input::canElideEmptySequence() {
479 //===----------------------------------------------------------------------===//
481 //===----------------------------------------------------------------------===//
483 Output::Output(raw_ostream
&yout
, void *context
, int WrapColumn
)
484 : IO(context
), Out(yout
), WrapColumn(WrapColumn
) {}
486 Output::~Output() = default;
488 bool Output::outputting() const {
492 void Output::beginMapping() {
493 StateStack
.push_back(inMapFirstKey
);
494 PaddingBeforeContainer
= Padding
;
498 bool Output::mapTag(StringRef Tag
, bool Use
) {
500 // If this tag is being written inside a sequence we should write the start
501 // of the sequence before writing the tag, otherwise the tag won't be
502 // attached to the element in the sequence, but rather the sequence itself.
503 bool SequenceElement
= false;
504 if (StateStack
.size() > 1) {
505 auto &E
= StateStack
[StateStack
.size() - 2];
506 SequenceElement
= inSeqAnyElement(E
) || inFlowSeqAnyElement(E
);
508 if (SequenceElement
&& StateStack
.back() == inMapFirstKey
) {
514 if (SequenceElement
) {
515 // If we're writing the tag during the first element of a map, the tag
516 // takes the place of the first element in the sequence.
517 if (StateStack
.back() == inMapFirstKey
) {
518 StateStack
.pop_back();
519 StateStack
.push_back(inMapOtherKey
);
521 // Tags inside maps in sequences should act as keys in the map from a
522 // formatting perspective, so we always want a newline in a sequence.
529 void Output::endMapping() {
530 // If we did not map anything, we should explicitly emit an empty map
531 if (StateStack
.back() == inMapFirstKey
) {
532 Padding
= PaddingBeforeContainer
;
537 StateStack
.pop_back();
540 std::vector
<StringRef
> Output::keys() {
541 report_fatal_error("invalid call");
544 bool Output::preflightKey(const char *Key
, bool Required
, bool SameAsDefault
,
545 bool &UseDefault
, void *&SaveInfo
) {
548 if (Required
|| !SameAsDefault
|| WriteDefaultValues
) {
549 auto State
= StateStack
.back();
550 if (State
== inFlowMapFirstKey
|| State
== inFlowMapOtherKey
) {
561 void Output::postflightKey(void *) {
562 if (StateStack
.back() == inMapFirstKey
) {
563 StateStack
.pop_back();
564 StateStack
.push_back(inMapOtherKey
);
565 } else if (StateStack
.back() == inFlowMapFirstKey
) {
566 StateStack
.pop_back();
567 StateStack
.push_back(inFlowMapOtherKey
);
571 void Output::beginFlowMapping() {
572 StateStack
.push_back(inFlowMapFirstKey
);
574 ColumnAtMapFlowStart
= Column
;
578 void Output::endFlowMapping() {
579 StateStack
.pop_back();
580 outputUpToEndOfLine(" }");
583 void Output::beginDocuments() {
584 outputUpToEndOfLine("---");
587 bool Output::preflightDocument(unsigned index
) {
589 outputUpToEndOfLine("\n---");
593 void Output::postflightDocument() {
596 void Output::endDocuments() {
600 unsigned Output::beginSequence() {
601 StateStack
.push_back(inSeqFirstElement
);
602 PaddingBeforeContainer
= Padding
;
607 void Output::endSequence() {
608 // If we did not emit anything, we should explicitly emit an empty sequence
609 if (StateStack
.back() == inSeqFirstElement
) {
610 Padding
= PaddingBeforeContainer
;
611 newLineCheck(/*EmptySequence=*/true);
615 StateStack
.pop_back();
618 bool Output::preflightElement(unsigned, void *&SaveInfo
) {
623 void Output::postflightElement(void *) {
624 if (StateStack
.back() == inSeqFirstElement
) {
625 StateStack
.pop_back();
626 StateStack
.push_back(inSeqOtherElement
);
627 } else if (StateStack
.back() == inFlowSeqFirstElement
) {
628 StateStack
.pop_back();
629 StateStack
.push_back(inFlowSeqOtherElement
);
633 unsigned Output::beginFlowSequence() {
634 StateStack
.push_back(inFlowSeqFirstElement
);
636 ColumnAtFlowStart
= Column
;
638 NeedFlowSequenceComma
= false;
642 void Output::endFlowSequence() {
643 StateStack
.pop_back();
644 outputUpToEndOfLine(" ]");
647 bool Output::preflightFlowElement(unsigned, void *&SaveInfo
) {
648 if (NeedFlowSequenceComma
)
650 if (WrapColumn
&& Column
> WrapColumn
) {
652 for (int i
= 0; i
< ColumnAtFlowStart
; ++i
)
654 Column
= ColumnAtFlowStart
;
661 void Output::postflightFlowElement(void *) {
662 NeedFlowSequenceComma
= true;
665 void Output::beginEnumScalar() {
666 EnumerationMatchFound
= false;
669 bool Output::matchEnumScalar(const char *Str
, bool Match
) {
670 if (Match
&& !EnumerationMatchFound
) {
672 outputUpToEndOfLine(Str
);
673 EnumerationMatchFound
= true;
678 bool Output::matchEnumFallback() {
679 if (EnumerationMatchFound
)
681 EnumerationMatchFound
= true;
685 void Output::endEnumScalar() {
686 if (!EnumerationMatchFound
)
687 llvm_unreachable("bad runtime enum value");
690 bool Output::beginBitSetScalar(bool &DoClear
) {
693 NeedBitValueComma
= false;
698 bool Output::bitSetMatch(const char *Str
, bool Matches
) {
700 if (NeedBitValueComma
)
703 NeedBitValueComma
= true;
708 void Output::endBitSetScalar() {
709 outputUpToEndOfLine(" ]");
712 void Output::scalarString(StringRef
&S
, QuotingType MustQuote
) {
715 // Print '' for the empty string because leaving the field empty is not
717 outputUpToEndOfLine("''");
720 output(S
, MustQuote
);
721 outputUpToEndOfLine("");
724 void Output::blockScalarString(StringRef
&S
) {
725 if (!StateStack
.empty())
730 unsigned Indent
= StateStack
.empty() ? 1 : StateStack
.size();
732 auto Buffer
= MemoryBuffer::getMemBuffer(S
, "", false);
733 for (line_iterator
Lines(*Buffer
, false); !Lines
.is_at_end(); ++Lines
) {
734 for (unsigned I
= 0; I
< Indent
; ++I
) {
742 void Output::scalarTag(std::string
&Tag
) {
750 void Output::setError(const Twine
&message
) {
753 bool Output::canElideEmptySequence() {
754 // Normally, with an optional key/value where the value is an empty sequence,
755 // the whole key/value can be not written. But, that produces wrong yaml
756 // if the key/value is the only thing in the map and the map is used in
757 // a sequence. This detects if the this sequence is the first key/value
758 // in map that itself is embedded in a sequence.
759 if (StateStack
.size() < 2)
761 if (StateStack
.back() != inMapFirstKey
)
763 return !inSeqAnyElement(StateStack
[StateStack
.size() - 2]);
766 void Output::output(StringRef s
) {
771 void Output::output(StringRef S
, QuotingType MustQuote
) {
772 if (MustQuote
== QuotingType::None
) {
773 // Only quote if we must.
778 StringLiteral Quote
= MustQuote
== QuotingType::Single
? StringLiteral("'")
779 : StringLiteral("\"");
780 output(Quote
); // Starting quote.
782 // When using double-quoted strings (and only in that case), non-printable
783 // characters may be present, and will be escaped using a variety of
784 // unicode-scalar and special short-form escapes. This is handled in
786 if (MustQuote
== QuotingType::Double
) {
787 output(yaml::escape(S
, /* EscapePrintable= */ false));
794 unsigned End
= S
.size();
795 const char *Base
= S
.data();
797 // When using single-quoted strings, any single quote ' must be doubled to be
800 if (S
[j
] == '\'') { // Escape quotes.
801 output(StringRef(&Base
[i
], j
- i
)); // "flush".
802 output(StringLiteral("''")); // Print it as ''
807 output(StringRef(&Base
[i
], j
- i
));
808 output(Quote
); // Ending quote.
811 void Output::outputUpToEndOfLine(StringRef s
) {
813 if (StateStack
.empty() || (!inFlowSeqAnyElement(StateStack
.back()) &&
814 !inFlowMapAnyKey(StateStack
.back())))
818 void Output::outputNewLine() {
823 // if seq at top, indent as if map, then add "- "
824 // if seq in middle, use "- " if firstKey, else use " "
827 void Output::newLineCheck(bool EmptySequence
) {
828 if (Padding
!= "\n") {
836 if (StateStack
.size() == 0 || EmptySequence
)
839 unsigned Indent
= StateStack
.size() - 1;
840 bool PossiblyNestedSeq
= false;
841 auto I
= StateStack
.rbegin(), E
= StateStack
.rend();
843 if (inSeqAnyElement(*I
)) {
844 PossiblyNestedSeq
= true; // Not possibly but always.
846 } else if (*I
== inMapFirstKey
|| *I
== inFlowMapFirstKey
||
847 inFlowSeqAnyElement(*I
)) {
848 PossiblyNestedSeq
= true;
852 unsigned OutputDashCount
= 0;
853 if (PossiblyNestedSeq
) {
854 // Count up consecutive inSeqFirstElement from the end, unless
855 // inSeqFirstElement is the top of nested sequence.
857 // Don't count the top of nested sequence.
858 if (!inSeqAnyElement(*I
))
863 // Stop counting if consecutive inSeqFirstElement ends.
864 if (*I
++ != inSeqFirstElement
)
869 for (unsigned I
= OutputDashCount
; I
< Indent
; ++I
)
872 for (unsigned I
= 0; I
< OutputDashCount
; ++I
)
876 void Output::paddedKey(StringRef key
) {
877 output(key
, needsQuotes(key
, false));
879 const char *spaces
= " ";
880 if (key
.size() < strlen(spaces
))
881 Padding
= &spaces
[key
.size()];
886 void Output::flowKey(StringRef Key
) {
887 if (StateStack
.back() == inFlowMapOtherKey
)
889 if (WrapColumn
&& Column
> WrapColumn
) {
891 for (int I
= 0; I
< ColumnAtMapFlowStart
; ++I
)
893 Column
= ColumnAtMapFlowStart
;
896 output(Key
, needsQuotes(Key
, false));
900 NodeKind
Output::getNodeKind() { report_fatal_error("invalid call"); }
902 bool Output::inSeqAnyElement(InState State
) {
903 return State
== inSeqFirstElement
|| State
== inSeqOtherElement
;
906 bool Output::inFlowSeqAnyElement(InState State
) {
907 return State
== inFlowSeqFirstElement
|| State
== inFlowSeqOtherElement
;
910 bool Output::inMapAnyKey(InState State
) {
911 return State
== inMapFirstKey
|| State
== inMapOtherKey
;
914 bool Output::inFlowMapAnyKey(InState State
) {
915 return State
== inFlowMapFirstKey
|| State
== inFlowMapOtherKey
;
918 //===----------------------------------------------------------------------===//
919 // traits for built-in types
920 //===----------------------------------------------------------------------===//
922 void ScalarTraits
<bool>::output(const bool &Val
, void *, raw_ostream
&Out
) {
923 Out
<< (Val
? "true" : "false");
926 StringRef ScalarTraits
<bool>::input(StringRef Scalar
, void *, bool &Val
) {
927 if (std::optional
<bool> Parsed
= parseBool(Scalar
)) {
931 return "invalid boolean";
934 void ScalarTraits
<StringRef
>::output(const StringRef
&Val
, void *,
939 StringRef ScalarTraits
<StringRef
>::input(StringRef Scalar
, void *,
945 void ScalarTraits
<std::string
>::output(const std::string
&Val
, void *,
950 StringRef ScalarTraits
<std::string
>::input(StringRef Scalar
, void *,
956 void ScalarTraits
<uint8_t>::output(const uint8_t &Val
, void *,
958 // use temp uin32_t because ostream thinks uint8_t is a character
963 StringRef ScalarTraits
<uint8_t>::input(StringRef Scalar
, void *, uint8_t &Val
) {
964 unsigned long long n
;
965 if (getAsUnsignedInteger(Scalar
, 0, n
))
966 return "invalid number";
968 return "out of range number";
973 void ScalarTraits
<uint16_t>::output(const uint16_t &Val
, void *,
978 StringRef ScalarTraits
<uint16_t>::input(StringRef Scalar
, void *,
980 unsigned long long n
;
981 if (getAsUnsignedInteger(Scalar
, 0, n
))
982 return "invalid number";
984 return "out of range number";
989 void ScalarTraits
<uint32_t>::output(const uint32_t &Val
, void *,
994 StringRef ScalarTraits
<uint32_t>::input(StringRef Scalar
, void *,
996 unsigned long long n
;
997 if (getAsUnsignedInteger(Scalar
, 0, n
))
998 return "invalid number";
999 if (n
> 0xFFFFFFFFUL
)
1000 return "out of range number";
1005 void ScalarTraits
<uint64_t>::output(const uint64_t &Val
, void *,
1010 StringRef ScalarTraits
<uint64_t>::input(StringRef Scalar
, void *,
1012 unsigned long long N
;
1013 if (getAsUnsignedInteger(Scalar
, 0, N
))
1014 return "invalid number";
1019 void ScalarTraits
<int8_t>::output(const int8_t &Val
, void *, raw_ostream
&Out
) {
1020 // use temp in32_t because ostream thinks int8_t is a character
1025 StringRef ScalarTraits
<int8_t>::input(StringRef Scalar
, void *, int8_t &Val
) {
1027 if (getAsSignedInteger(Scalar
, 0, N
))
1028 return "invalid number";
1029 if ((N
> 127) || (N
< -128))
1030 return "out of range number";
1035 void ScalarTraits
<int16_t>::output(const int16_t &Val
, void *,
1040 StringRef ScalarTraits
<int16_t>::input(StringRef Scalar
, void *, int16_t &Val
) {
1042 if (getAsSignedInteger(Scalar
, 0, N
))
1043 return "invalid number";
1044 if ((N
> INT16_MAX
) || (N
< INT16_MIN
))
1045 return "out of range number";
1050 void ScalarTraits
<int32_t>::output(const int32_t &Val
, void *,
1055 StringRef ScalarTraits
<int32_t>::input(StringRef Scalar
, void *, int32_t &Val
) {
1057 if (getAsSignedInteger(Scalar
, 0, N
))
1058 return "invalid number";
1059 if ((N
> INT32_MAX
) || (N
< INT32_MIN
))
1060 return "out of range number";
1065 void ScalarTraits
<int64_t>::output(const int64_t &Val
, void *,
1070 StringRef ScalarTraits
<int64_t>::input(StringRef Scalar
, void *, int64_t &Val
) {
1072 if (getAsSignedInteger(Scalar
, 0, N
))
1073 return "invalid number";
1078 void ScalarTraits
<double>::output(const double &Val
, void *, raw_ostream
&Out
) {
1079 Out
<< format("%g", Val
);
1082 StringRef ScalarTraits
<double>::input(StringRef Scalar
, void *, double &Val
) {
1083 if (to_float(Scalar
, Val
))
1085 return "invalid floating point number";
1088 void ScalarTraits
<float>::output(const float &Val
, void *, raw_ostream
&Out
) {
1089 Out
<< format("%g", Val
);
1092 StringRef ScalarTraits
<float>::input(StringRef Scalar
, void *, float &Val
) {
1093 if (to_float(Scalar
, Val
))
1095 return "invalid floating point number";
1098 void ScalarTraits
<Hex8
>::output(const Hex8
&Val
, void *, raw_ostream
&Out
) {
1099 Out
<< format("0x%" PRIX8
, (uint8_t)Val
);
1102 StringRef ScalarTraits
<Hex8
>::input(StringRef Scalar
, void *, Hex8
&Val
) {
1103 unsigned long long n
;
1104 if (getAsUnsignedInteger(Scalar
, 0, n
))
1105 return "invalid hex8 number";
1107 return "out of range hex8 number";
1112 void ScalarTraits
<Hex16
>::output(const Hex16
&Val
, void *, raw_ostream
&Out
) {
1113 Out
<< format("0x%" PRIX16
, (uint16_t)Val
);
1116 StringRef ScalarTraits
<Hex16
>::input(StringRef Scalar
, void *, Hex16
&Val
) {
1117 unsigned long long n
;
1118 if (getAsUnsignedInteger(Scalar
, 0, n
))
1119 return "invalid hex16 number";
1121 return "out of range hex16 number";
1126 void ScalarTraits
<Hex32
>::output(const Hex32
&Val
, void *, raw_ostream
&Out
) {
1127 Out
<< format("0x%" PRIX32
, (uint32_t)Val
);
1130 StringRef ScalarTraits
<Hex32
>::input(StringRef Scalar
, void *, Hex32
&Val
) {
1131 unsigned long long n
;
1132 if (getAsUnsignedInteger(Scalar
, 0, n
))
1133 return "invalid hex32 number";
1134 if (n
> 0xFFFFFFFFUL
)
1135 return "out of range hex32 number";
1140 void ScalarTraits
<Hex64
>::output(const Hex64
&Val
, void *, raw_ostream
&Out
) {
1141 Out
<< format("0x%" PRIX64
, (uint64_t)Val
);
1144 StringRef ScalarTraits
<Hex64
>::input(StringRef Scalar
, void *, Hex64
&Val
) {
1145 unsigned long long Num
;
1146 if (getAsUnsignedInteger(Scalar
, 0, Num
))
1147 return "invalid hex64 number";
1152 void ScalarTraits
<VersionTuple
>::output(const VersionTuple
&Val
, void *,
1153 llvm::raw_ostream
&Out
) {
1154 Out
<< Val
.getAsString();
1157 StringRef ScalarTraits
<VersionTuple
>::input(StringRef Scalar
, void *,
1158 VersionTuple
&Val
) {
1159 if (Val
.tryParse(Scalar
))
1160 return "invalid version format";