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() {
47 void IO::setContext(void *Context
) {
51 //===----------------------------------------------------------------------===//
53 //===----------------------------------------------------------------------===//
55 Input::Input(StringRef InputContent
, void *Ctxt
,
56 SourceMgr::DiagHandlerTy DiagHandler
, void *DiagHandlerCtxt
)
57 : IO(Ctxt
), Strm(new Stream(InputContent
, SrcMgr
, false, &EC
)) {
59 SrcMgr
.setDiagHandler(DiagHandler
, DiagHandlerCtxt
);
60 DocIterator
= Strm
->begin();
63 Input::Input(MemoryBufferRef Input
, void *Ctxt
,
64 SourceMgr::DiagHandlerTy DiagHandler
, void *DiagHandlerCtxt
)
65 : IO(Ctxt
), Strm(new Stream(Input
, SrcMgr
, false, &EC
)) {
67 SrcMgr
.setDiagHandler(DiagHandler
, DiagHandlerCtxt
);
68 DocIterator
= Strm
->begin();
71 Input::~Input() = default;
73 std::error_code
Input::error() { return EC
; }
75 // Pin the vtables to this file.
76 void Input::HNode::anchor() {}
77 void Input::EmptyHNode::anchor() {}
78 void Input::ScalarHNode::anchor() {}
79 void Input::MapHNode::anchor() {}
80 void Input::SequenceHNode::anchor() {}
82 bool Input::outputting() {
86 bool Input::setCurrentDocument() {
87 if (DocIterator
!= Strm
->end()) {
88 Node
*N
= DocIterator
->getRoot();
90 assert(Strm
->failed() && "Root is NULL iff parsing failed");
91 EC
= make_error_code(errc::invalid_argument
);
95 if (isa
<NullNode
>(N
)) {
96 // Empty files are allowed and ignored
98 return setCurrentDocument();
100 TopNode
= createHNodes(N
);
101 CurrentNode
= TopNode
.get();
107 bool Input::nextDocument() {
108 return ++DocIterator
!= Strm
->end();
111 const Node
*Input::getCurrentNode() const {
112 return CurrentNode
? CurrentNode
->_node
: nullptr;
115 bool Input::mapTag(StringRef Tag
, bool Default
) {
116 // CurrentNode can be null if setCurrentDocument() was unable to
117 // parse the document because it was invalid or empty.
121 std::string foundTag
= CurrentNode
->_node
->getVerbatimTag();
122 if (foundTag
.empty()) {
123 // If no tag found and 'Tag' is the default, say it was found.
126 // Return true iff found tag matches supplied tag.
127 return Tag
.equals(foundTag
);
130 void Input::beginMapping() {
133 // CurrentNode can be null if the document is empty.
134 MapHNode
*MN
= dyn_cast_or_null
<MapHNode
>(CurrentNode
);
136 MN
->ValidKeys
.clear();
140 std::vector
<StringRef
> Input::keys() {
141 MapHNode
*MN
= dyn_cast
<MapHNode
>(CurrentNode
);
142 std::vector
<StringRef
> Ret
;
144 setError(CurrentNode
, "not a mapping");
147 for (auto &P
: MN
->Mapping
)
148 Ret
.push_back(P
.first());
152 bool Input::preflightKey(const char *Key
, bool Required
, bool, bool &UseDefault
,
158 // CurrentNode is null for empty documents, which is an error in case required
159 // nodes are present.
162 EC
= make_error_code(errc::invalid_argument
);
166 MapHNode
*MN
= dyn_cast
<MapHNode
>(CurrentNode
);
168 if (Required
|| !isa
<EmptyHNode
>(CurrentNode
))
169 setError(CurrentNode
, "not a mapping");
172 MN
->ValidKeys
.push_back(Key
);
173 HNode
*Value
= MN
->Mapping
[Key
].get();
176 setError(CurrentNode
, Twine("missing required key '") + Key
+ "'");
181 SaveInfo
= CurrentNode
;
186 void Input::postflightKey(void *saveInfo
) {
187 CurrentNode
= reinterpret_cast<HNode
*>(saveInfo
);
190 void Input::endMapping() {
193 // CurrentNode can be null if the document is empty.
194 MapHNode
*MN
= dyn_cast_or_null
<MapHNode
>(CurrentNode
);
197 for (const auto &NN
: MN
->Mapping
) {
198 if (!is_contained(MN
->ValidKeys
, NN
.first())) {
199 setError(NN
.second
.get(), Twine("unknown key '") + NN
.first() + "'");
205 void Input::beginFlowMapping() { beginMapping(); }
207 void Input::endFlowMapping() { endMapping(); }
209 unsigned Input::beginSequence() {
210 if (SequenceHNode
*SQ
= dyn_cast
<SequenceHNode
>(CurrentNode
))
211 return SQ
->Entries
.size();
212 if (isa
<EmptyHNode
>(CurrentNode
))
214 // Treat case where there's a scalar "null" value as an empty sequence.
215 if (ScalarHNode
*SN
= dyn_cast
<ScalarHNode
>(CurrentNode
)) {
216 if (isNull(SN
->value()))
219 // Any other type of HNode is an error.
220 setError(CurrentNode
, "not a sequence");
224 void Input::endSequence() {
227 bool Input::preflightElement(unsigned Index
, void *&SaveInfo
) {
230 if (SequenceHNode
*SQ
= dyn_cast
<SequenceHNode
>(CurrentNode
)) {
231 SaveInfo
= CurrentNode
;
232 CurrentNode
= SQ
->Entries
[Index
].get();
238 void Input::postflightElement(void *SaveInfo
) {
239 CurrentNode
= reinterpret_cast<HNode
*>(SaveInfo
);
242 unsigned Input::beginFlowSequence() { return beginSequence(); }
244 bool Input::preflightFlowElement(unsigned index
, void *&SaveInfo
) {
247 if (SequenceHNode
*SQ
= dyn_cast
<SequenceHNode
>(CurrentNode
)) {
248 SaveInfo
= CurrentNode
;
249 CurrentNode
= SQ
->Entries
[index
].get();
255 void Input::postflightFlowElement(void *SaveInfo
) {
256 CurrentNode
= reinterpret_cast<HNode
*>(SaveInfo
);
259 void Input::endFlowSequence() {
262 void Input::beginEnumScalar() {
263 ScalarMatchFound
= false;
266 bool Input::matchEnumScalar(const char *Str
, bool) {
267 if (ScalarMatchFound
)
269 if (ScalarHNode
*SN
= dyn_cast
<ScalarHNode
>(CurrentNode
)) {
270 if (SN
->value().equals(Str
)) {
271 ScalarMatchFound
= true;
278 bool Input::matchEnumFallback() {
279 if (ScalarMatchFound
)
281 ScalarMatchFound
= true;
285 void Input::endEnumScalar() {
286 if (!ScalarMatchFound
) {
287 setError(CurrentNode
, "unknown enumerated scalar");
291 bool Input::beginBitSetScalar(bool &DoClear
) {
292 BitValuesUsed
.clear();
293 if (SequenceHNode
*SQ
= dyn_cast
<SequenceHNode
>(CurrentNode
)) {
294 BitValuesUsed
.insert(BitValuesUsed
.begin(), SQ
->Entries
.size(), false);
296 setError(CurrentNode
, "expected sequence of bit values");
302 bool Input::bitSetMatch(const char *Str
, bool) {
305 if (SequenceHNode
*SQ
= dyn_cast
<SequenceHNode
>(CurrentNode
)) {
307 for (auto &N
: SQ
->Entries
) {
308 if (ScalarHNode
*SN
= dyn_cast
<ScalarHNode
>(N
.get())) {
309 if (SN
->value().equals(Str
)) {
310 BitValuesUsed
[Index
] = true;
314 setError(CurrentNode
, "unexpected scalar in sequence of bit values");
319 setError(CurrentNode
, "expected sequence of bit values");
324 void Input::endBitSetScalar() {
327 if (SequenceHNode
*SQ
= dyn_cast
<SequenceHNode
>(CurrentNode
)) {
328 assert(BitValuesUsed
.size() == SQ
->Entries
.size());
329 for (unsigned i
= 0; i
< SQ
->Entries
.size(); ++i
) {
330 if (!BitValuesUsed
[i
]) {
331 setError(SQ
->Entries
[i
].get(), "unknown bit value");
338 void Input::scalarString(StringRef
&S
, QuotingType
) {
339 if (ScalarHNode
*SN
= dyn_cast
<ScalarHNode
>(CurrentNode
)) {
342 setError(CurrentNode
, "unexpected scalar");
346 void Input::blockScalarString(StringRef
&S
) { scalarString(S
, QuotingType::None
); }
348 void Input::scalarTag(std::string
&Tag
) {
349 Tag
= CurrentNode
->_node
->getVerbatimTag();
352 void Input::setError(HNode
*hnode
, const Twine
&message
) {
353 assert(hnode
&& "HNode must not be NULL");
354 setError(hnode
->_node
, message
);
357 NodeKind
Input::getNodeKind() {
358 if (isa
<ScalarHNode
>(CurrentNode
))
359 return NodeKind::Scalar
;
360 else if (isa
<MapHNode
>(CurrentNode
))
361 return NodeKind::Map
;
362 else if (isa
<SequenceHNode
>(CurrentNode
))
363 return NodeKind::Sequence
;
364 llvm_unreachable("Unsupported node kind");
367 void Input::setError(Node
*node
, const Twine
&message
) {
368 Strm
->printError(node
, message
);
369 EC
= make_error_code(errc::invalid_argument
);
372 std::unique_ptr
<Input::HNode
> Input::createHNodes(Node
*N
) {
373 SmallString
<128> StringStorage
;
374 if (ScalarNode
*SN
= dyn_cast
<ScalarNode
>(N
)) {
375 StringRef KeyStr
= SN
->getValue(StringStorage
);
376 if (!StringStorage
.empty()) {
377 // Copy string to permanent storage
378 KeyStr
= StringStorage
.str().copy(StringAllocator
);
380 return llvm::make_unique
<ScalarHNode
>(N
, KeyStr
);
381 } else if (BlockScalarNode
*BSN
= dyn_cast
<BlockScalarNode
>(N
)) {
382 StringRef ValueCopy
= BSN
->getValue().copy(StringAllocator
);
383 return llvm::make_unique
<ScalarHNode
>(N
, ValueCopy
);
384 } else if (SequenceNode
*SQ
= dyn_cast
<SequenceNode
>(N
)) {
385 auto SQHNode
= llvm::make_unique
<SequenceHNode
>(N
);
386 for (Node
&SN
: *SQ
) {
387 auto Entry
= createHNodes(&SN
);
390 SQHNode
->Entries
.push_back(std::move(Entry
));
392 return std::move(SQHNode
);
393 } else if (MappingNode
*Map
= dyn_cast
<MappingNode
>(N
)) {
394 auto mapHNode
= llvm::make_unique
<MapHNode
>(N
);
395 for (KeyValueNode
&KVN
: *Map
) {
396 Node
*KeyNode
= KVN
.getKey();
397 ScalarNode
*Key
= dyn_cast
<ScalarNode
>(KeyNode
);
398 Node
*Value
= KVN
.getValue();
399 if (!Key
|| !Value
) {
401 setError(KeyNode
, "Map key must be a scalar");
403 setError(KeyNode
, "Map value must not be empty");
406 StringStorage
.clear();
407 StringRef KeyStr
= Key
->getValue(StringStorage
);
408 if (!StringStorage
.empty()) {
409 // Copy string to permanent storage
410 KeyStr
= StringStorage
.str().copy(StringAllocator
);
412 auto ValueHNode
= createHNodes(Value
);
415 mapHNode
->Mapping
[KeyStr
] = std::move(ValueHNode
);
417 return std::move(mapHNode
);
418 } else if (isa
<NullNode
>(N
)) {
419 return llvm::make_unique
<EmptyHNode
>(N
);
421 setError(N
, "unknown node kind");
426 void Input::setError(const Twine
&Message
) {
427 setError(CurrentNode
, Message
);
430 bool Input::canElideEmptySequence() {
434 //===----------------------------------------------------------------------===//
436 //===----------------------------------------------------------------------===//
438 Output::Output(raw_ostream
&yout
, void *context
, int WrapColumn
)
439 : IO(context
), Out(yout
), WrapColumn(WrapColumn
) {}
441 Output::~Output() = default;
443 bool Output::outputting() {
447 void Output::beginMapping() {
448 StateStack
.push_back(inMapFirstKey
);
449 PaddingBeforeContainer
= Padding
;
453 bool Output::mapTag(StringRef Tag
, bool Use
) {
455 // If this tag is being written inside a sequence we should write the start
456 // of the sequence before writing the tag, otherwise the tag won't be
457 // attached to the element in the sequence, but rather the sequence itself.
458 bool SequenceElement
= false;
459 if (StateStack
.size() > 1) {
460 auto &E
= StateStack
[StateStack
.size() - 2];
461 SequenceElement
= inSeqAnyElement(E
) || inFlowSeqAnyElement(E
);
463 if (SequenceElement
&& StateStack
.back() == inMapFirstKey
) {
469 if (SequenceElement
) {
470 // If we're writing the tag during the first element of a map, the tag
471 // takes the place of the first element in the sequence.
472 if (StateStack
.back() == inMapFirstKey
) {
473 StateStack
.pop_back();
474 StateStack
.push_back(inMapOtherKey
);
476 // Tags inside maps in sequences should act as keys in the map from a
477 // formatting perspective, so we always want a newline in a sequence.
484 void Output::endMapping() {
485 // If we did not map anything, we should explicitly emit an empty map
486 if (StateStack
.back() == inMapFirstKey
) {
487 Padding
= PaddingBeforeContainer
;
492 StateStack
.pop_back();
495 std::vector
<StringRef
> Output::keys() {
496 report_fatal_error("invalid call");
499 bool Output::preflightKey(const char *Key
, bool Required
, bool SameAsDefault
,
500 bool &UseDefault
, void *&) {
502 if (Required
|| !SameAsDefault
|| WriteDefaultValues
) {
503 auto State
= StateStack
.back();
504 if (State
== inFlowMapFirstKey
|| State
== inFlowMapOtherKey
) {
515 void Output::postflightKey(void *) {
516 if (StateStack
.back() == inMapFirstKey
) {
517 StateStack
.pop_back();
518 StateStack
.push_back(inMapOtherKey
);
519 } else if (StateStack
.back() == inFlowMapFirstKey
) {
520 StateStack
.pop_back();
521 StateStack
.push_back(inFlowMapOtherKey
);
525 void Output::beginFlowMapping() {
526 StateStack
.push_back(inFlowMapFirstKey
);
528 ColumnAtMapFlowStart
= Column
;
532 void Output::endFlowMapping() {
533 StateStack
.pop_back();
534 outputUpToEndOfLine(" }");
537 void Output::beginDocuments() {
538 outputUpToEndOfLine("---");
541 bool Output::preflightDocument(unsigned index
) {
543 outputUpToEndOfLine("\n---");
547 void Output::postflightDocument() {
550 void Output::endDocuments() {
554 unsigned Output::beginSequence() {
555 StateStack
.push_back(inSeqFirstElement
);
556 PaddingBeforeContainer
= Padding
;
561 void Output::endSequence() {
562 // If we did not emit anything, we should explicitly emit an empty sequence
563 if (StateStack
.back() == inSeqFirstElement
) {
564 Padding
= PaddingBeforeContainer
;
569 StateStack
.pop_back();
572 bool Output::preflightElement(unsigned, void *&) {
576 void Output::postflightElement(void *) {
577 if (StateStack
.back() == inSeqFirstElement
) {
578 StateStack
.pop_back();
579 StateStack
.push_back(inSeqOtherElement
);
580 } else if (StateStack
.back() == inFlowSeqFirstElement
) {
581 StateStack
.pop_back();
582 StateStack
.push_back(inFlowSeqOtherElement
);
586 unsigned Output::beginFlowSequence() {
587 StateStack
.push_back(inFlowSeqFirstElement
);
589 ColumnAtFlowStart
= Column
;
591 NeedFlowSequenceComma
= false;
595 void Output::endFlowSequence() {
596 StateStack
.pop_back();
597 outputUpToEndOfLine(" ]");
600 bool Output::preflightFlowElement(unsigned, void *&) {
601 if (NeedFlowSequenceComma
)
603 if (WrapColumn
&& Column
> WrapColumn
) {
605 for (int i
= 0; i
< ColumnAtFlowStart
; ++i
)
607 Column
= ColumnAtFlowStart
;
613 void Output::postflightFlowElement(void *) {
614 NeedFlowSequenceComma
= true;
617 void Output::beginEnumScalar() {
618 EnumerationMatchFound
= false;
621 bool Output::matchEnumScalar(const char *Str
, bool Match
) {
622 if (Match
&& !EnumerationMatchFound
) {
624 outputUpToEndOfLine(Str
);
625 EnumerationMatchFound
= true;
630 bool Output::matchEnumFallback() {
631 if (EnumerationMatchFound
)
633 EnumerationMatchFound
= true;
637 void Output::endEnumScalar() {
638 if (!EnumerationMatchFound
)
639 llvm_unreachable("bad runtime enum value");
642 bool Output::beginBitSetScalar(bool &DoClear
) {
645 NeedBitValueComma
= false;
650 bool Output::bitSetMatch(const char *Str
, bool Matches
) {
652 if (NeedBitValueComma
)
655 NeedBitValueComma
= true;
660 void Output::endBitSetScalar() {
661 outputUpToEndOfLine(" ]");
664 void Output::scalarString(StringRef
&S
, QuotingType MustQuote
) {
667 // Print '' for the empty string because leaving the field empty is not
669 outputUpToEndOfLine("''");
672 if (MustQuote
== QuotingType::None
) {
673 // Only quote if we must.
674 outputUpToEndOfLine(S
);
678 const char *const Quote
= MustQuote
== QuotingType::Single
? "'" : "\"";
679 output(Quote
); // Starting quote.
681 // When using double-quoted strings (and only in that case), non-printable characters may be
682 // present, and will be escaped using a variety of unicode-scalar and special short-form
683 // escapes. This is handled in yaml::escape.
684 if (MustQuote
== QuotingType::Double
) {
685 output(yaml::escape(S
, /* EscapePrintable= */ false));
686 outputUpToEndOfLine(Quote
);
692 unsigned End
= S
.size();
693 const char *Base
= S
.data();
695 // When using single-quoted strings, any single quote ' must be doubled to be escaped.
697 if (S
[j
] == '\'') { // Escape quotes.
698 output(StringRef(&Base
[i
], j
- i
)); // "flush".
699 output(StringLiteral("''")); // Print it as ''
704 output(StringRef(&Base
[i
], j
- i
));
705 outputUpToEndOfLine(Quote
); // Ending quote.
708 void Output::blockScalarString(StringRef
&S
) {
709 if (!StateStack
.empty())
714 unsigned Indent
= StateStack
.empty() ? 1 : StateStack
.size();
716 auto Buffer
= MemoryBuffer::getMemBuffer(S
, "", false);
717 for (line_iterator
Lines(*Buffer
, false); !Lines
.is_at_end(); ++Lines
) {
718 for (unsigned I
= 0; I
< Indent
; ++I
) {
726 void Output::scalarTag(std::string
&Tag
) {
734 void Output::setError(const Twine
&message
) {
737 bool Output::canElideEmptySequence() {
738 // Normally, with an optional key/value where the value is an empty sequence,
739 // the whole key/value can be not written. But, that produces wrong yaml
740 // if the key/value is the only thing in the map and the map is used in
741 // a sequence. This detects if the this sequence is the first key/value
742 // in map that itself is embedded in a sequnce.
743 if (StateStack
.size() < 2)
745 if (StateStack
.back() != inMapFirstKey
)
747 return !inSeqAnyElement(StateStack
[StateStack
.size() - 2]);
750 void Output::output(StringRef s
) {
755 void Output::outputUpToEndOfLine(StringRef s
) {
757 if (StateStack
.empty() || (!inFlowSeqAnyElement(StateStack
.back()) &&
758 !inFlowMapAnyKey(StateStack
.back())))
762 void Output::outputNewLine() {
767 // if seq at top, indent as if map, then add "- "
768 // if seq in middle, use "- " if firstKey, else use " "
771 void Output::newLineCheck() {
772 if (Padding
!= "\n") {
780 if (StateStack
.size() == 0)
783 unsigned Indent
= StateStack
.size() - 1;
784 bool OutputDash
= false;
786 if (StateStack
.back() == inSeqFirstElement
||
787 StateStack
.back() == inSeqOtherElement
) {
789 } else if ((StateStack
.size() > 1) &&
790 ((StateStack
.back() == inMapFirstKey
) ||
791 inFlowSeqAnyElement(StateStack
.back()) ||
792 (StateStack
.back() == inFlowMapFirstKey
)) &&
793 inSeqAnyElement(StateStack
[StateStack
.size() - 2])) {
798 for (unsigned i
= 0; i
< Indent
; ++i
) {
807 void Output::paddedKey(StringRef key
) {
810 const char *spaces
= " ";
811 if (key
.size() < strlen(spaces
))
812 Padding
= &spaces
[key
.size()];
817 void Output::flowKey(StringRef Key
) {
818 if (StateStack
.back() == inFlowMapOtherKey
)
820 if (WrapColumn
&& Column
> WrapColumn
) {
822 for (int I
= 0; I
< ColumnAtMapFlowStart
; ++I
)
824 Column
= ColumnAtMapFlowStart
;
831 NodeKind
Output::getNodeKind() { report_fatal_error("invalid call"); }
833 bool Output::inSeqAnyElement(InState State
) {
834 return State
== inSeqFirstElement
|| State
== inSeqOtherElement
;
837 bool Output::inFlowSeqAnyElement(InState State
) {
838 return State
== inFlowSeqFirstElement
|| State
== inFlowSeqOtherElement
;
841 bool Output::inMapAnyKey(InState State
) {
842 return State
== inMapFirstKey
|| State
== inMapOtherKey
;
845 bool Output::inFlowMapAnyKey(InState State
) {
846 return State
== inFlowMapFirstKey
|| State
== inFlowMapOtherKey
;
849 //===----------------------------------------------------------------------===//
850 // traits for built-in types
851 //===----------------------------------------------------------------------===//
853 void ScalarTraits
<bool>::output(const bool &Val
, void *, raw_ostream
&Out
) {
854 Out
<< (Val
? "true" : "false");
857 StringRef ScalarTraits
<bool>::input(StringRef Scalar
, void *, bool &Val
) {
858 if (Scalar
.equals("true")) {
861 } else if (Scalar
.equals("false")) {
865 return "invalid boolean";
868 void ScalarTraits
<StringRef
>::output(const StringRef
&Val
, void *,
873 StringRef ScalarTraits
<StringRef
>::input(StringRef Scalar
, void *,
879 void ScalarTraits
<std::string
>::output(const std::string
&Val
, void *,
884 StringRef ScalarTraits
<std::string
>::input(StringRef Scalar
, void *,
890 void ScalarTraits
<uint8_t>::output(const uint8_t &Val
, void *,
892 // use temp uin32_t because ostream thinks uint8_t is a character
897 StringRef ScalarTraits
<uint8_t>::input(StringRef Scalar
, void *, uint8_t &Val
) {
898 unsigned long long n
;
899 if (getAsUnsignedInteger(Scalar
, 0, n
))
900 return "invalid number";
902 return "out of range number";
907 void ScalarTraits
<uint16_t>::output(const uint16_t &Val
, void *,
912 StringRef ScalarTraits
<uint16_t>::input(StringRef Scalar
, void *,
914 unsigned long long n
;
915 if (getAsUnsignedInteger(Scalar
, 0, n
))
916 return "invalid number";
918 return "out of range number";
923 void ScalarTraits
<uint32_t>::output(const uint32_t &Val
, void *,
928 StringRef ScalarTraits
<uint32_t>::input(StringRef Scalar
, void *,
930 unsigned long long n
;
931 if (getAsUnsignedInteger(Scalar
, 0, n
))
932 return "invalid number";
933 if (n
> 0xFFFFFFFFUL
)
934 return "out of range number";
939 void ScalarTraits
<uint64_t>::output(const uint64_t &Val
, void *,
944 StringRef ScalarTraits
<uint64_t>::input(StringRef Scalar
, void *,
946 unsigned long long N
;
947 if (getAsUnsignedInteger(Scalar
, 0, N
))
948 return "invalid number";
953 void ScalarTraits
<int8_t>::output(const int8_t &Val
, void *, raw_ostream
&Out
) {
954 // use temp in32_t because ostream thinks int8_t is a character
959 StringRef ScalarTraits
<int8_t>::input(StringRef Scalar
, void *, int8_t &Val
) {
961 if (getAsSignedInteger(Scalar
, 0, N
))
962 return "invalid number";
963 if ((N
> 127) || (N
< -128))
964 return "out of range number";
969 void ScalarTraits
<int16_t>::output(const int16_t &Val
, void *,
974 StringRef ScalarTraits
<int16_t>::input(StringRef Scalar
, void *, int16_t &Val
) {
976 if (getAsSignedInteger(Scalar
, 0, N
))
977 return "invalid number";
978 if ((N
> INT16_MAX
) || (N
< INT16_MIN
))
979 return "out of range number";
984 void ScalarTraits
<int32_t>::output(const int32_t &Val
, void *,
989 StringRef ScalarTraits
<int32_t>::input(StringRef Scalar
, void *, int32_t &Val
) {
991 if (getAsSignedInteger(Scalar
, 0, N
))
992 return "invalid number";
993 if ((N
> INT32_MAX
) || (N
< INT32_MIN
))
994 return "out of range number";
999 void ScalarTraits
<int64_t>::output(const int64_t &Val
, void *,
1004 StringRef ScalarTraits
<int64_t>::input(StringRef Scalar
, void *, int64_t &Val
) {
1006 if (getAsSignedInteger(Scalar
, 0, N
))
1007 return "invalid number";
1012 void ScalarTraits
<double>::output(const double &Val
, void *, raw_ostream
&Out
) {
1013 Out
<< format("%g", Val
);
1016 StringRef ScalarTraits
<double>::input(StringRef Scalar
, void *, double &Val
) {
1017 if (to_float(Scalar
, Val
))
1019 return "invalid floating point number";
1022 void ScalarTraits
<float>::output(const float &Val
, void *, raw_ostream
&Out
) {
1023 Out
<< format("%g", Val
);
1026 StringRef ScalarTraits
<float>::input(StringRef Scalar
, void *, float &Val
) {
1027 if (to_float(Scalar
, Val
))
1029 return "invalid floating point number";
1032 void ScalarTraits
<Hex8
>::output(const Hex8
&Val
, void *, raw_ostream
&Out
) {
1034 Out
<< format("0x%02X", Num
);
1037 StringRef ScalarTraits
<Hex8
>::input(StringRef Scalar
, void *, Hex8
&Val
) {
1038 unsigned long long n
;
1039 if (getAsUnsignedInteger(Scalar
, 0, n
))
1040 return "invalid hex8 number";
1042 return "out of range hex8 number";
1047 void ScalarTraits
<Hex16
>::output(const Hex16
&Val
, void *, raw_ostream
&Out
) {
1049 Out
<< format("0x%04X", Num
);
1052 StringRef ScalarTraits
<Hex16
>::input(StringRef Scalar
, void *, Hex16
&Val
) {
1053 unsigned long long n
;
1054 if (getAsUnsignedInteger(Scalar
, 0, n
))
1055 return "invalid hex16 number";
1057 return "out of range hex16 number";
1062 void ScalarTraits
<Hex32
>::output(const Hex32
&Val
, void *, raw_ostream
&Out
) {
1064 Out
<< format("0x%08X", Num
);
1067 StringRef ScalarTraits
<Hex32
>::input(StringRef Scalar
, void *, Hex32
&Val
) {
1068 unsigned long long n
;
1069 if (getAsUnsignedInteger(Scalar
, 0, n
))
1070 return "invalid hex32 number";
1071 if (n
> 0xFFFFFFFFUL
)
1072 return "out of range hex32 number";
1077 void ScalarTraits
<Hex64
>::output(const Hex64
&Val
, void *, raw_ostream
&Out
) {
1079 Out
<< format("0x%016llX", Num
);
1082 StringRef ScalarTraits
<Hex64
>::input(StringRef Scalar
, void *, Hex64
&Val
) {
1083 unsigned long long Num
;
1084 if (getAsUnsignedInteger(Scalar
, 0, Num
))
1085 return "invalid hex64 number";