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/Unicode.h"
22 #include "llvm/Support/YAMLParser.h"
23 #include "llvm/Support/raw_ostream.h"
35 //===----------------------------------------------------------------------===//
37 //===----------------------------------------------------------------------===//
39 IO::IO(void *Context
) : Ctxt(Context
) {}
43 void *IO::getContext() const {
47 void IO::setContext(void *Context
) {
51 void IO::setAllowUnknownKeys(bool Allow
) {
52 llvm_unreachable("Only supported for Input");
55 //===----------------------------------------------------------------------===//
57 //===----------------------------------------------------------------------===//
59 Input::Input(StringRef InputContent
, void *Ctxt
,
60 SourceMgr::DiagHandlerTy DiagHandler
, void *DiagHandlerCtxt
)
61 : IO(Ctxt
), Strm(new Stream(InputContent
, SrcMgr
, false, &EC
)) {
63 SrcMgr
.setDiagHandler(DiagHandler
, DiagHandlerCtxt
);
64 DocIterator
= Strm
->begin();
67 Input::Input(MemoryBufferRef Input
, void *Ctxt
,
68 SourceMgr::DiagHandlerTy DiagHandler
, void *DiagHandlerCtxt
)
69 : IO(Ctxt
), Strm(new Stream(Input
, SrcMgr
, false, &EC
)) {
71 SrcMgr
.setDiagHandler(DiagHandler
, DiagHandlerCtxt
);
72 DocIterator
= Strm
->begin();
75 Input::~Input() = default;
77 std::error_code
Input::error() { return EC
; }
79 // Pin the vtables to this file.
80 void Input::HNode::anchor() {}
81 void Input::EmptyHNode::anchor() {}
82 void Input::ScalarHNode::anchor() {}
83 void Input::MapHNode::anchor() {}
84 void Input::SequenceHNode::anchor() {}
86 bool Input::outputting() const {
90 bool Input::setCurrentDocument() {
91 if (DocIterator
!= Strm
->end()) {
92 Node
*N
= DocIterator
->getRoot();
94 EC
= make_error_code(errc::invalid_argument
);
98 if (isa
<NullNode
>(N
)) {
99 // Empty files are allowed and ignored
101 return setCurrentDocument();
103 TopNode
= createHNodes(N
);
104 CurrentNode
= TopNode
.get();
110 bool Input::nextDocument() {
111 return ++DocIterator
!= Strm
->end();
114 const Node
*Input::getCurrentNode() const {
115 return CurrentNode
? CurrentNode
->_node
: nullptr;
118 bool Input::mapTag(StringRef Tag
, bool Default
) {
119 // CurrentNode can be null if setCurrentDocument() was unable to
120 // parse the document because it was invalid or empty.
124 std::string foundTag
= CurrentNode
->_node
->getVerbatimTag();
125 if (foundTag
.empty()) {
126 // If no tag found and 'Tag' is the default, say it was found.
129 // Return true iff found tag matches supplied tag.
130 return Tag
.equals(foundTag
);
133 void Input::beginMapping() {
136 // CurrentNode can be null if the document is empty.
137 MapHNode
*MN
= dyn_cast_or_null
<MapHNode
>(CurrentNode
);
139 MN
->ValidKeys
.clear();
143 std::vector
<StringRef
> Input::keys() {
144 MapHNode
*MN
= dyn_cast
<MapHNode
>(CurrentNode
);
145 std::vector
<StringRef
> Ret
;
147 setError(CurrentNode
, "not a mapping");
150 for (auto &P
: MN
->Mapping
)
151 Ret
.push_back(P
.first());
155 bool Input::preflightKey(const char *Key
, bool Required
, bool, bool &UseDefault
,
161 // CurrentNode is null for empty documents, which is an error in case required
162 // nodes are present.
165 EC
= make_error_code(errc::invalid_argument
);
169 MapHNode
*MN
= dyn_cast
<MapHNode
>(CurrentNode
);
171 if (Required
|| !isa
<EmptyHNode
>(CurrentNode
))
172 setError(CurrentNode
, "not a mapping");
177 MN
->ValidKeys
.push_back(Key
);
178 HNode
*Value
= MN
->Mapping
[Key
].first
.get();
181 setError(CurrentNode
, Twine("missing required key '") + Key
+ "'");
186 SaveInfo
= CurrentNode
;
191 void Input::postflightKey(void *saveInfo
) {
192 CurrentNode
= reinterpret_cast<HNode
*>(saveInfo
);
195 void Input::endMapping() {
198 // CurrentNode can be null if the document is empty.
199 MapHNode
*MN
= dyn_cast_or_null
<MapHNode
>(CurrentNode
);
202 for (const auto &NN
: MN
->Mapping
) {
203 if (!is_contained(MN
->ValidKeys
, NN
.first())) {
204 const SMRange
&ReportLoc
= NN
.second
.second
;
205 if (!AllowUnknownKeys
) {
206 setError(ReportLoc
, Twine("unknown key '") + NN
.first() + "'");
209 reportWarning(ReportLoc
, Twine("unknown key '") + NN
.first() + "'");
214 void Input::beginFlowMapping() { beginMapping(); }
216 void Input::endFlowMapping() { endMapping(); }
218 unsigned Input::beginSequence() {
219 if (SequenceHNode
*SQ
= dyn_cast
<SequenceHNode
>(CurrentNode
))
220 return SQ
->Entries
.size();
221 if (isa
<EmptyHNode
>(CurrentNode
))
223 // Treat case where there's a scalar "null" value as an empty sequence.
224 if (ScalarHNode
*SN
= dyn_cast
<ScalarHNode
>(CurrentNode
)) {
225 if (isNull(SN
->value()))
228 // Any other type of HNode is an error.
229 setError(CurrentNode
, "not a sequence");
233 void Input::endSequence() {
236 bool Input::preflightElement(unsigned Index
, void *&SaveInfo
) {
239 if (SequenceHNode
*SQ
= dyn_cast
<SequenceHNode
>(CurrentNode
)) {
240 SaveInfo
= CurrentNode
;
241 CurrentNode
= SQ
->Entries
[Index
].get();
247 void Input::postflightElement(void *SaveInfo
) {
248 CurrentNode
= reinterpret_cast<HNode
*>(SaveInfo
);
251 unsigned Input::beginFlowSequence() { return beginSequence(); }
253 bool Input::preflightFlowElement(unsigned index
, void *&SaveInfo
) {
256 if (SequenceHNode
*SQ
= dyn_cast
<SequenceHNode
>(CurrentNode
)) {
257 SaveInfo
= CurrentNode
;
258 CurrentNode
= SQ
->Entries
[index
].get();
264 void Input::postflightFlowElement(void *SaveInfo
) {
265 CurrentNode
= reinterpret_cast<HNode
*>(SaveInfo
);
268 void Input::endFlowSequence() {
271 void Input::beginEnumScalar() {
272 ScalarMatchFound
= false;
275 bool Input::matchEnumScalar(const char *Str
, bool) {
276 if (ScalarMatchFound
)
278 if (ScalarHNode
*SN
= dyn_cast
<ScalarHNode
>(CurrentNode
)) {
279 if (SN
->value().equals(Str
)) {
280 ScalarMatchFound
= true;
287 bool Input::matchEnumFallback() {
288 if (ScalarMatchFound
)
290 ScalarMatchFound
= true;
294 void Input::endEnumScalar() {
295 if (!ScalarMatchFound
) {
296 setError(CurrentNode
, "unknown enumerated scalar");
300 bool Input::beginBitSetScalar(bool &DoClear
) {
301 BitValuesUsed
.clear();
302 if (SequenceHNode
*SQ
= dyn_cast
<SequenceHNode
>(CurrentNode
)) {
303 BitValuesUsed
.insert(BitValuesUsed
.begin(), SQ
->Entries
.size(), false);
305 setError(CurrentNode
, "expected sequence of bit values");
311 bool Input::bitSetMatch(const char *Str
, bool) {
314 if (SequenceHNode
*SQ
= dyn_cast
<SequenceHNode
>(CurrentNode
)) {
316 for (auto &N
: SQ
->Entries
) {
317 if (ScalarHNode
*SN
= dyn_cast
<ScalarHNode
>(N
.get())) {
318 if (SN
->value().equals(Str
)) {
319 BitValuesUsed
[Index
] = true;
323 setError(CurrentNode
, "unexpected scalar in sequence of bit values");
328 setError(CurrentNode
, "expected sequence of bit values");
333 void Input::endBitSetScalar() {
336 if (SequenceHNode
*SQ
= dyn_cast
<SequenceHNode
>(CurrentNode
)) {
337 assert(BitValuesUsed
.size() == SQ
->Entries
.size());
338 for (unsigned i
= 0; i
< SQ
->Entries
.size(); ++i
) {
339 if (!BitValuesUsed
[i
]) {
340 setError(SQ
->Entries
[i
].get(), "unknown bit value");
347 void Input::scalarString(StringRef
&S
, QuotingType
) {
348 if (ScalarHNode
*SN
= dyn_cast
<ScalarHNode
>(CurrentNode
)) {
351 setError(CurrentNode
, "unexpected scalar");
355 void Input::blockScalarString(StringRef
&S
) { scalarString(S
, QuotingType::None
); }
357 void Input::scalarTag(std::string
&Tag
) {
358 Tag
= CurrentNode
->_node
->getVerbatimTag();
361 void Input::setError(HNode
*hnode
, const Twine
&message
) {
362 assert(hnode
&& "HNode must not be NULL");
363 setError(hnode
->_node
, message
);
366 NodeKind
Input::getNodeKind() {
367 if (isa
<ScalarHNode
>(CurrentNode
))
368 return NodeKind::Scalar
;
369 else if (isa
<MapHNode
>(CurrentNode
))
370 return NodeKind::Map
;
371 else if (isa
<SequenceHNode
>(CurrentNode
))
372 return NodeKind::Sequence
;
373 llvm_unreachable("Unsupported node kind");
376 void Input::setError(Node
*node
, const Twine
&message
) {
377 Strm
->printError(node
, message
);
378 EC
= make_error_code(errc::invalid_argument
);
381 void Input::setError(const SMRange
&range
, const Twine
&message
) {
382 Strm
->printError(range
, message
);
383 EC
= make_error_code(errc::invalid_argument
);
386 void Input::reportWarning(HNode
*hnode
, const Twine
&message
) {
387 assert(hnode
&& "HNode must not be NULL");
388 Strm
->printError(hnode
->_node
, message
, SourceMgr::DK_Warning
);
391 void Input::reportWarning(Node
*node
, const Twine
&message
) {
392 Strm
->printError(node
, message
, SourceMgr::DK_Warning
);
395 void Input::reportWarning(const SMRange
&range
, const Twine
&message
) {
396 Strm
->printError(range
, message
, SourceMgr::DK_Warning
);
399 std::unique_ptr
<Input::HNode
> Input::createHNodes(Node
*N
) {
400 SmallString
<128> StringStorage
;
401 if (ScalarNode
*SN
= dyn_cast
<ScalarNode
>(N
)) {
402 StringRef KeyStr
= SN
->getValue(StringStorage
);
403 if (!StringStorage
.empty()) {
404 // Copy string to permanent storage
405 KeyStr
= StringStorage
.str().copy(StringAllocator
);
407 return std::make_unique
<ScalarHNode
>(N
, KeyStr
);
408 } else if (BlockScalarNode
*BSN
= dyn_cast
<BlockScalarNode
>(N
)) {
409 StringRef ValueCopy
= BSN
->getValue().copy(StringAllocator
);
410 return std::make_unique
<ScalarHNode
>(N
, ValueCopy
);
411 } else if (SequenceNode
*SQ
= dyn_cast
<SequenceNode
>(N
)) {
412 auto SQHNode
= std::make_unique
<SequenceHNode
>(N
);
413 for (Node
&SN
: *SQ
) {
414 auto Entry
= createHNodes(&SN
);
417 SQHNode
->Entries
.push_back(std::move(Entry
));
419 return std::move(SQHNode
);
420 } else if (MappingNode
*Map
= dyn_cast
<MappingNode
>(N
)) {
421 auto mapHNode
= std::make_unique
<MapHNode
>(N
);
422 for (KeyValueNode
&KVN
: *Map
) {
423 Node
*KeyNode
= KVN
.getKey();
424 ScalarNode
*Key
= dyn_cast_or_null
<ScalarNode
>(KeyNode
);
425 Node
*Value
= KVN
.getValue();
426 if (!Key
|| !Value
) {
428 setError(KeyNode
, "Map key must be a scalar");
430 setError(KeyNode
, "Map value must not be empty");
433 StringStorage
.clear();
434 StringRef KeyStr
= Key
->getValue(StringStorage
);
435 if (!StringStorage
.empty()) {
436 // Copy string to permanent storage
437 KeyStr
= StringStorage
.str().copy(StringAllocator
);
439 auto ValueHNode
= createHNodes(Value
);
442 mapHNode
->Mapping
[KeyStr
] =
443 std::make_pair(std::move(ValueHNode
), KeyNode
->getSourceRange());
445 return std::move(mapHNode
);
446 } else if (isa
<NullNode
>(N
)) {
447 return std::make_unique
<EmptyHNode
>(N
);
449 setError(N
, "unknown node kind");
454 void Input::setError(const Twine
&Message
) {
455 setError(CurrentNode
, Message
);
458 void Input::setAllowUnknownKeys(bool Allow
) { AllowUnknownKeys
= Allow
; }
460 bool Input::canElideEmptySequence() {
464 //===----------------------------------------------------------------------===//
466 //===----------------------------------------------------------------------===//
468 Output::Output(raw_ostream
&yout
, void *context
, int WrapColumn
)
469 : IO(context
), Out(yout
), WrapColumn(WrapColumn
) {}
471 Output::~Output() = default;
473 bool Output::outputting() const {
477 void Output::beginMapping() {
478 StateStack
.push_back(inMapFirstKey
);
479 PaddingBeforeContainer
= Padding
;
483 bool Output::mapTag(StringRef Tag
, bool Use
) {
485 // If this tag is being written inside a sequence we should write the start
486 // of the sequence before writing the tag, otherwise the tag won't be
487 // attached to the element in the sequence, but rather the sequence itself.
488 bool SequenceElement
= false;
489 if (StateStack
.size() > 1) {
490 auto &E
= StateStack
[StateStack
.size() - 2];
491 SequenceElement
= inSeqAnyElement(E
) || inFlowSeqAnyElement(E
);
493 if (SequenceElement
&& StateStack
.back() == inMapFirstKey
) {
499 if (SequenceElement
) {
500 // If we're writing the tag during the first element of a map, the tag
501 // takes the place of the first element in the sequence.
502 if (StateStack
.back() == inMapFirstKey
) {
503 StateStack
.pop_back();
504 StateStack
.push_back(inMapOtherKey
);
506 // Tags inside maps in sequences should act as keys in the map from a
507 // formatting perspective, so we always want a newline in a sequence.
514 void Output::endMapping() {
515 // If we did not map anything, we should explicitly emit an empty map
516 if (StateStack
.back() == inMapFirstKey
) {
517 Padding
= PaddingBeforeContainer
;
522 StateStack
.pop_back();
525 std::vector
<StringRef
> Output::keys() {
526 report_fatal_error("invalid call");
529 bool Output::preflightKey(const char *Key
, bool Required
, bool SameAsDefault
,
530 bool &UseDefault
, void *&) {
532 if (Required
|| !SameAsDefault
|| WriteDefaultValues
) {
533 auto State
= StateStack
.back();
534 if (State
== inFlowMapFirstKey
|| State
== inFlowMapOtherKey
) {
545 void Output::postflightKey(void *) {
546 if (StateStack
.back() == inMapFirstKey
) {
547 StateStack
.pop_back();
548 StateStack
.push_back(inMapOtherKey
);
549 } else if (StateStack
.back() == inFlowMapFirstKey
) {
550 StateStack
.pop_back();
551 StateStack
.push_back(inFlowMapOtherKey
);
555 void Output::beginFlowMapping() {
556 StateStack
.push_back(inFlowMapFirstKey
);
558 ColumnAtMapFlowStart
= Column
;
562 void Output::endFlowMapping() {
563 StateStack
.pop_back();
564 outputUpToEndOfLine(" }");
567 void Output::beginDocuments() {
568 outputUpToEndOfLine("---");
571 bool Output::preflightDocument(unsigned index
) {
573 outputUpToEndOfLine("\n---");
577 void Output::postflightDocument() {
580 void Output::endDocuments() {
584 unsigned Output::beginSequence() {
585 StateStack
.push_back(inSeqFirstElement
);
586 PaddingBeforeContainer
= Padding
;
591 void Output::endSequence() {
592 // If we did not emit anything, we should explicitly emit an empty sequence
593 if (StateStack
.back() == inSeqFirstElement
) {
594 Padding
= PaddingBeforeContainer
;
595 newLineCheck(/*EmptySequence=*/true);
599 StateStack
.pop_back();
602 bool Output::preflightElement(unsigned, void *&) {
606 void Output::postflightElement(void *) {
607 if (StateStack
.back() == inSeqFirstElement
) {
608 StateStack
.pop_back();
609 StateStack
.push_back(inSeqOtherElement
);
610 } else if (StateStack
.back() == inFlowSeqFirstElement
) {
611 StateStack
.pop_back();
612 StateStack
.push_back(inFlowSeqOtherElement
);
616 unsigned Output::beginFlowSequence() {
617 StateStack
.push_back(inFlowSeqFirstElement
);
619 ColumnAtFlowStart
= Column
;
621 NeedFlowSequenceComma
= false;
625 void Output::endFlowSequence() {
626 StateStack
.pop_back();
627 outputUpToEndOfLine(" ]");
630 bool Output::preflightFlowElement(unsigned, void *&) {
631 if (NeedFlowSequenceComma
)
633 if (WrapColumn
&& Column
> WrapColumn
) {
635 for (int i
= 0; i
< ColumnAtFlowStart
; ++i
)
637 Column
= ColumnAtFlowStart
;
643 void Output::postflightFlowElement(void *) {
644 NeedFlowSequenceComma
= true;
647 void Output::beginEnumScalar() {
648 EnumerationMatchFound
= false;
651 bool Output::matchEnumScalar(const char *Str
, bool Match
) {
652 if (Match
&& !EnumerationMatchFound
) {
654 outputUpToEndOfLine(Str
);
655 EnumerationMatchFound
= true;
660 bool Output::matchEnumFallback() {
661 if (EnumerationMatchFound
)
663 EnumerationMatchFound
= true;
667 void Output::endEnumScalar() {
668 if (!EnumerationMatchFound
)
669 llvm_unreachable("bad runtime enum value");
672 bool Output::beginBitSetScalar(bool &DoClear
) {
675 NeedBitValueComma
= false;
680 bool Output::bitSetMatch(const char *Str
, bool Matches
) {
682 if (NeedBitValueComma
)
685 NeedBitValueComma
= true;
690 void Output::endBitSetScalar() {
691 outputUpToEndOfLine(" ]");
694 void Output::scalarString(StringRef
&S
, QuotingType MustQuote
) {
697 // Print '' for the empty string because leaving the field empty is not
699 outputUpToEndOfLine("''");
702 if (MustQuote
== QuotingType::None
) {
703 // Only quote if we must.
704 outputUpToEndOfLine(S
);
708 const char *const Quote
= MustQuote
== QuotingType::Single
? "'" : "\"";
709 output(Quote
); // Starting quote.
711 // When using double-quoted strings (and only in that case), non-printable characters may be
712 // present, and will be escaped using a variety of unicode-scalar and special short-form
713 // escapes. This is handled in yaml::escape.
714 if (MustQuote
== QuotingType::Double
) {
715 output(yaml::escape(S
, /* EscapePrintable= */ false));
716 outputUpToEndOfLine(Quote
);
722 unsigned End
= S
.size();
723 const char *Base
= S
.data();
725 // When using single-quoted strings, any single quote ' must be doubled to be escaped.
727 if (S
[j
] == '\'') { // Escape quotes.
728 output(StringRef(&Base
[i
], j
- i
)); // "flush".
729 output(StringLiteral("''")); // Print it as ''
734 output(StringRef(&Base
[i
], j
- i
));
735 outputUpToEndOfLine(Quote
); // Ending quote.
738 void Output::blockScalarString(StringRef
&S
) {
739 if (!StateStack
.empty())
744 unsigned Indent
= StateStack
.empty() ? 1 : StateStack
.size();
746 auto Buffer
= MemoryBuffer::getMemBuffer(S
, "", false);
747 for (line_iterator
Lines(*Buffer
, false); !Lines
.is_at_end(); ++Lines
) {
748 for (unsigned I
= 0; I
< Indent
; ++I
) {
756 void Output::scalarTag(std::string
&Tag
) {
764 void Output::setError(const Twine
&message
) {
767 bool Output::canElideEmptySequence() {
768 // Normally, with an optional key/value where the value is an empty sequence,
769 // the whole key/value can be not written. But, that produces wrong yaml
770 // if the key/value is the only thing in the map and the map is used in
771 // a sequence. This detects if the this sequence is the first key/value
772 // in map that itself is embedded in a sequence.
773 if (StateStack
.size() < 2)
775 if (StateStack
.back() != inMapFirstKey
)
777 return !inSeqAnyElement(StateStack
[StateStack
.size() - 2]);
780 void Output::output(StringRef s
) {
785 void Output::outputUpToEndOfLine(StringRef s
) {
787 if (StateStack
.empty() || (!inFlowSeqAnyElement(StateStack
.back()) &&
788 !inFlowMapAnyKey(StateStack
.back())))
792 void Output::outputNewLine() {
797 // if seq at top, indent as if map, then add "- "
798 // if seq in middle, use "- " if firstKey, else use " "
801 void Output::newLineCheck(bool EmptySequence
) {
802 if (Padding
!= "\n") {
810 if (StateStack
.size() == 0 || EmptySequence
)
813 unsigned Indent
= StateStack
.size() - 1;
814 bool OutputDash
= false;
816 if (StateStack
.back() == inSeqFirstElement
||
817 StateStack
.back() == inSeqOtherElement
) {
819 } else if ((StateStack
.size() > 1) &&
820 ((StateStack
.back() == inMapFirstKey
) ||
821 inFlowSeqAnyElement(StateStack
.back()) ||
822 (StateStack
.back() == inFlowMapFirstKey
)) &&
823 inSeqAnyElement(StateStack
[StateStack
.size() - 2])) {
828 for (unsigned i
= 0; i
< Indent
; ++i
) {
836 void Output::paddedKey(StringRef key
) {
839 const char *spaces
= " ";
840 if (key
.size() < strlen(spaces
))
841 Padding
= &spaces
[key
.size()];
846 void Output::flowKey(StringRef Key
) {
847 if (StateStack
.back() == inFlowMapOtherKey
)
849 if (WrapColumn
&& Column
> WrapColumn
) {
851 for (int I
= 0; I
< ColumnAtMapFlowStart
; ++I
)
853 Column
= ColumnAtMapFlowStart
;
860 NodeKind
Output::getNodeKind() { report_fatal_error("invalid call"); }
862 bool Output::inSeqAnyElement(InState State
) {
863 return State
== inSeqFirstElement
|| State
== inSeqOtherElement
;
866 bool Output::inFlowSeqAnyElement(InState State
) {
867 return State
== inFlowSeqFirstElement
|| State
== inFlowSeqOtherElement
;
870 bool Output::inMapAnyKey(InState State
) {
871 return State
== inMapFirstKey
|| State
== inMapOtherKey
;
874 bool Output::inFlowMapAnyKey(InState State
) {
875 return State
== inFlowMapFirstKey
|| State
== inFlowMapOtherKey
;
878 //===----------------------------------------------------------------------===//
879 // traits for built-in types
880 //===----------------------------------------------------------------------===//
882 void ScalarTraits
<bool>::output(const bool &Val
, void *, raw_ostream
&Out
) {
883 Out
<< (Val
? "true" : "false");
886 StringRef ScalarTraits
<bool>::input(StringRef Scalar
, void *, bool &Val
) {
887 if (llvm::Optional
<bool> Parsed
= parseBool(Scalar
)) {
891 return "invalid boolean";
894 void ScalarTraits
<StringRef
>::output(const StringRef
&Val
, void *,
899 StringRef ScalarTraits
<StringRef
>::input(StringRef Scalar
, void *,
905 void ScalarTraits
<std::string
>::output(const std::string
&Val
, void *,
910 StringRef ScalarTraits
<std::string
>::input(StringRef Scalar
, void *,
916 void ScalarTraits
<uint8_t>::output(const uint8_t &Val
, void *,
918 // use temp uin32_t because ostream thinks uint8_t is a character
923 StringRef ScalarTraits
<uint8_t>::input(StringRef Scalar
, void *, uint8_t &Val
) {
924 unsigned long long n
;
925 if (getAsUnsignedInteger(Scalar
, 0, n
))
926 return "invalid number";
928 return "out of range number";
933 void ScalarTraits
<uint16_t>::output(const uint16_t &Val
, void *,
938 StringRef ScalarTraits
<uint16_t>::input(StringRef Scalar
, void *,
940 unsigned long long n
;
941 if (getAsUnsignedInteger(Scalar
, 0, n
))
942 return "invalid number";
944 return "out of range number";
949 void ScalarTraits
<uint32_t>::output(const uint32_t &Val
, void *,
954 StringRef ScalarTraits
<uint32_t>::input(StringRef Scalar
, void *,
956 unsigned long long n
;
957 if (getAsUnsignedInteger(Scalar
, 0, n
))
958 return "invalid number";
959 if (n
> 0xFFFFFFFFUL
)
960 return "out of range number";
965 void ScalarTraits
<uint64_t>::output(const uint64_t &Val
, void *,
970 StringRef ScalarTraits
<uint64_t>::input(StringRef Scalar
, void *,
972 unsigned long long N
;
973 if (getAsUnsignedInteger(Scalar
, 0, N
))
974 return "invalid number";
979 void ScalarTraits
<int8_t>::output(const int8_t &Val
, void *, raw_ostream
&Out
) {
980 // use temp in32_t because ostream thinks int8_t is a character
985 StringRef ScalarTraits
<int8_t>::input(StringRef Scalar
, void *, int8_t &Val
) {
987 if (getAsSignedInteger(Scalar
, 0, N
))
988 return "invalid number";
989 if ((N
> 127) || (N
< -128))
990 return "out of range number";
995 void ScalarTraits
<int16_t>::output(const int16_t &Val
, void *,
1000 StringRef ScalarTraits
<int16_t>::input(StringRef Scalar
, void *, int16_t &Val
) {
1002 if (getAsSignedInteger(Scalar
, 0, N
))
1003 return "invalid number";
1004 if ((N
> INT16_MAX
) || (N
< INT16_MIN
))
1005 return "out of range number";
1010 void ScalarTraits
<int32_t>::output(const int32_t &Val
, void *,
1015 StringRef ScalarTraits
<int32_t>::input(StringRef Scalar
, void *, int32_t &Val
) {
1017 if (getAsSignedInteger(Scalar
, 0, N
))
1018 return "invalid number";
1019 if ((N
> INT32_MAX
) || (N
< INT32_MIN
))
1020 return "out of range number";
1025 void ScalarTraits
<int64_t>::output(const int64_t &Val
, void *,
1030 StringRef ScalarTraits
<int64_t>::input(StringRef Scalar
, void *, int64_t &Val
) {
1032 if (getAsSignedInteger(Scalar
, 0, N
))
1033 return "invalid number";
1038 void ScalarTraits
<double>::output(const double &Val
, void *, raw_ostream
&Out
) {
1039 Out
<< format("%g", Val
);
1042 StringRef ScalarTraits
<double>::input(StringRef Scalar
, void *, double &Val
) {
1043 if (to_float(Scalar
, Val
))
1045 return "invalid floating point number";
1048 void ScalarTraits
<float>::output(const float &Val
, void *, raw_ostream
&Out
) {
1049 Out
<< format("%g", Val
);
1052 StringRef ScalarTraits
<float>::input(StringRef Scalar
, void *, float &Val
) {
1053 if (to_float(Scalar
, Val
))
1055 return "invalid floating point number";
1058 void ScalarTraits
<Hex8
>::output(const Hex8
&Val
, void *, raw_ostream
&Out
) {
1059 Out
<< format("0x%" PRIX8
, (uint8_t)Val
);
1062 StringRef ScalarTraits
<Hex8
>::input(StringRef Scalar
, void *, Hex8
&Val
) {
1063 unsigned long long n
;
1064 if (getAsUnsignedInteger(Scalar
, 0, n
))
1065 return "invalid hex8 number";
1067 return "out of range hex8 number";
1072 void ScalarTraits
<Hex16
>::output(const Hex16
&Val
, void *, raw_ostream
&Out
) {
1073 Out
<< format("0x%" PRIX16
, (uint16_t)Val
);
1076 StringRef ScalarTraits
<Hex16
>::input(StringRef Scalar
, void *, Hex16
&Val
) {
1077 unsigned long long n
;
1078 if (getAsUnsignedInteger(Scalar
, 0, n
))
1079 return "invalid hex16 number";
1081 return "out of range hex16 number";
1086 void ScalarTraits
<Hex32
>::output(const Hex32
&Val
, void *, raw_ostream
&Out
) {
1087 Out
<< format("0x%" PRIX32
, (uint32_t)Val
);
1090 StringRef ScalarTraits
<Hex32
>::input(StringRef Scalar
, void *, Hex32
&Val
) {
1091 unsigned long long n
;
1092 if (getAsUnsignedInteger(Scalar
, 0, n
))
1093 return "invalid hex32 number";
1094 if (n
> 0xFFFFFFFFUL
)
1095 return "out of range hex32 number";
1100 void ScalarTraits
<Hex64
>::output(const Hex64
&Val
, void *, raw_ostream
&Out
) {
1101 Out
<< format("0x%" PRIX64
, (uint64_t)Val
);
1104 StringRef ScalarTraits
<Hex64
>::input(StringRef Scalar
, void *, Hex64
&Val
) {
1105 unsigned long long Num
;
1106 if (getAsUnsignedInteger(Scalar
, 0, Num
))
1107 return "invalid hex64 number";
1112 void ScalarTraits
<VersionTuple
>::output(const VersionTuple
&Val
, void *,
1113 llvm::raw_ostream
&Out
) {
1114 Out
<< Val
.getAsString();
1117 StringRef ScalarTraits
<VersionTuple
>::input(StringRef Scalar
, void *,
1118 VersionTuple
&Val
) {
1119 if (Val
.tryParse(Scalar
))
1120 return "invalid version format";