1 //===- lib/Support/YAMLTraits.cpp -----------------------------------------===//
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "llvm/Support/YAMLTraits.h"
11 #include "llvm/ADT/STLExtras.h"
12 #include "llvm/ADT/SmallString.h"
13 #include "llvm/ADT/StringExtras.h"
14 #include "llvm/ADT/StringRef.h"
15 #include "llvm/ADT/Twine.h"
16 #include "llvm/Support/Casting.h"
17 #include "llvm/Support/Errc.h"
18 #include "llvm/Support/ErrorHandling.h"
19 #include "llvm/Support/Format.h"
20 #include "llvm/Support/LineIterator.h"
21 #include "llvm/Support/MemoryBuffer.h"
22 #include "llvm/Support/Unicode.h"
23 #include "llvm/Support/YAMLParser.h"
24 #include "llvm/Support/raw_ostream.h"
36 //===----------------------------------------------------------------------===//
38 //===----------------------------------------------------------------------===//
40 IO::IO(void *Context
) : Ctxt(Context
) {}
44 void *IO::getContext() {
48 void IO::setContext(void *Context
) {
52 //===----------------------------------------------------------------------===//
54 //===----------------------------------------------------------------------===//
56 Input::Input(StringRef InputContent
, void *Ctxt
,
57 SourceMgr::DiagHandlerTy DiagHandler
, void *DiagHandlerCtxt
)
58 : IO(Ctxt
), Strm(new Stream(InputContent
, SrcMgr
, false, &EC
)) {
60 SrcMgr
.setDiagHandler(DiagHandler
, DiagHandlerCtxt
);
61 DocIterator
= Strm
->begin();
64 Input::Input(MemoryBufferRef Input
, void *Ctxt
,
65 SourceMgr::DiagHandlerTy DiagHandler
, void *DiagHandlerCtxt
)
66 : IO(Ctxt
), Strm(new Stream(Input
, SrcMgr
, false, &EC
)) {
68 SrcMgr
.setDiagHandler(DiagHandler
, DiagHandlerCtxt
);
69 DocIterator
= Strm
->begin();
72 Input::~Input() = default;
74 std::error_code
Input::error() { return EC
; }
76 // Pin the vtables to this file.
77 void Input::HNode::anchor() {}
78 void Input::EmptyHNode::anchor() {}
79 void Input::ScalarHNode::anchor() {}
80 void Input::MapHNode::anchor() {}
81 void Input::SequenceHNode::anchor() {}
83 bool Input::outputting() {
87 bool Input::setCurrentDocument() {
88 if (DocIterator
!= Strm
->end()) {
89 Node
*N
= DocIterator
->getRoot();
91 assert(Strm
->failed() && "Root is NULL iff parsing failed");
92 EC
= make_error_code(errc::invalid_argument
);
96 if (isa
<NullNode
>(N
)) {
97 // Empty files are allowed and ignored
99 return setCurrentDocument();
101 TopNode
= this->createHNodes(N
);
102 CurrentNode
= TopNode
.get();
108 bool Input::nextDocument() {
109 return ++DocIterator
!= Strm
->end();
112 const Node
*Input::getCurrentNode() const {
113 return CurrentNode
? CurrentNode
->_node
: nullptr;
116 bool Input::mapTag(StringRef Tag
, bool Default
) {
117 std::string foundTag
= CurrentNode
->_node
->getVerbatimTag();
118 if (foundTag
.empty()) {
119 // If no tag found and 'Tag' is the default, say it was found.
122 // Return true iff found tag matches supplied tag.
123 return Tag
.equals(foundTag
);
126 void Input::beginMapping() {
129 // CurrentNode can be null if the document is empty.
130 MapHNode
*MN
= dyn_cast_or_null
<MapHNode
>(CurrentNode
);
132 MN
->ValidKeys
.clear();
136 std::vector
<StringRef
> Input::keys() {
137 MapHNode
*MN
= dyn_cast
<MapHNode
>(CurrentNode
);
138 std::vector
<StringRef
> Ret
;
140 setError(CurrentNode
, "not a mapping");
143 for (auto &P
: MN
->Mapping
)
144 Ret
.push_back(P
.first());
148 bool Input::preflightKey(const char *Key
, bool Required
, bool, bool &UseDefault
,
154 // CurrentNode is null for empty documents, which is an error in case required
155 // nodes are present.
158 EC
= make_error_code(errc::invalid_argument
);
162 MapHNode
*MN
= dyn_cast
<MapHNode
>(CurrentNode
);
164 if (Required
|| !isa
<EmptyHNode
>(CurrentNode
))
165 setError(CurrentNode
, "not a mapping");
168 MN
->ValidKeys
.push_back(Key
);
169 HNode
*Value
= MN
->Mapping
[Key
].get();
172 setError(CurrentNode
, Twine("missing required key '") + Key
+ "'");
177 SaveInfo
= CurrentNode
;
182 void Input::postflightKey(void *saveInfo
) {
183 CurrentNode
= reinterpret_cast<HNode
*>(saveInfo
);
186 void Input::endMapping() {
189 // CurrentNode can be null if the document is empty.
190 MapHNode
*MN
= dyn_cast_or_null
<MapHNode
>(CurrentNode
);
193 for (const auto &NN
: MN
->Mapping
) {
194 if (!is_contained(MN
->ValidKeys
, NN
.first())) {
195 setError(NN
.second
.get(), Twine("unknown key '") + NN
.first() + "'");
201 void Input::beginFlowMapping() { beginMapping(); }
203 void Input::endFlowMapping() { endMapping(); }
205 unsigned Input::beginSequence() {
206 if (SequenceHNode
*SQ
= dyn_cast
<SequenceHNode
>(CurrentNode
))
207 return SQ
->Entries
.size();
208 if (isa
<EmptyHNode
>(CurrentNode
))
210 // Treat case where there's a scalar "null" value as an empty sequence.
211 if (ScalarHNode
*SN
= dyn_cast
<ScalarHNode
>(CurrentNode
)) {
212 if (isNull(SN
->value()))
215 // Any other type of HNode is an error.
216 setError(CurrentNode
, "not a sequence");
220 void Input::endSequence() {
223 bool Input::preflightElement(unsigned Index
, void *&SaveInfo
) {
226 if (SequenceHNode
*SQ
= dyn_cast
<SequenceHNode
>(CurrentNode
)) {
227 SaveInfo
= CurrentNode
;
228 CurrentNode
= SQ
->Entries
[Index
].get();
234 void Input::postflightElement(void *SaveInfo
) {
235 CurrentNode
= reinterpret_cast<HNode
*>(SaveInfo
);
238 unsigned Input::beginFlowSequence() { return beginSequence(); }
240 bool Input::preflightFlowElement(unsigned index
, void *&SaveInfo
) {
243 if (SequenceHNode
*SQ
= dyn_cast
<SequenceHNode
>(CurrentNode
)) {
244 SaveInfo
= CurrentNode
;
245 CurrentNode
= SQ
->Entries
[index
].get();
251 void Input::postflightFlowElement(void *SaveInfo
) {
252 CurrentNode
= reinterpret_cast<HNode
*>(SaveInfo
);
255 void Input::endFlowSequence() {
258 void Input::beginEnumScalar() {
259 ScalarMatchFound
= false;
262 bool Input::matchEnumScalar(const char *Str
, bool) {
263 if (ScalarMatchFound
)
265 if (ScalarHNode
*SN
= dyn_cast
<ScalarHNode
>(CurrentNode
)) {
266 if (SN
->value().equals(Str
)) {
267 ScalarMatchFound
= true;
274 bool Input::matchEnumFallback() {
275 if (ScalarMatchFound
)
277 ScalarMatchFound
= true;
281 void Input::endEnumScalar() {
282 if (!ScalarMatchFound
) {
283 setError(CurrentNode
, "unknown enumerated scalar");
287 bool Input::beginBitSetScalar(bool &DoClear
) {
288 BitValuesUsed
.clear();
289 if (SequenceHNode
*SQ
= dyn_cast
<SequenceHNode
>(CurrentNode
)) {
290 BitValuesUsed
.insert(BitValuesUsed
.begin(), SQ
->Entries
.size(), false);
292 setError(CurrentNode
, "expected sequence of bit values");
298 bool Input::bitSetMatch(const char *Str
, bool) {
301 if (SequenceHNode
*SQ
= dyn_cast
<SequenceHNode
>(CurrentNode
)) {
303 for (auto &N
: SQ
->Entries
) {
304 if (ScalarHNode
*SN
= dyn_cast
<ScalarHNode
>(N
.get())) {
305 if (SN
->value().equals(Str
)) {
306 BitValuesUsed
[Index
] = true;
310 setError(CurrentNode
, "unexpected scalar in sequence of bit values");
315 setError(CurrentNode
, "expected sequence of bit values");
320 void Input::endBitSetScalar() {
323 if (SequenceHNode
*SQ
= dyn_cast
<SequenceHNode
>(CurrentNode
)) {
324 assert(BitValuesUsed
.size() == SQ
->Entries
.size());
325 for (unsigned i
= 0; i
< SQ
->Entries
.size(); ++i
) {
326 if (!BitValuesUsed
[i
]) {
327 setError(SQ
->Entries
[i
].get(), "unknown bit value");
334 void Input::scalarString(StringRef
&S
, QuotingType
) {
335 if (ScalarHNode
*SN
= dyn_cast
<ScalarHNode
>(CurrentNode
)) {
338 setError(CurrentNode
, "unexpected scalar");
342 void Input::blockScalarString(StringRef
&S
) { scalarString(S
, QuotingType::None
); }
344 void Input::setError(HNode
*hnode
, const Twine
&message
) {
345 assert(hnode
&& "HNode must not be NULL");
346 this->setError(hnode
->_node
, message
);
349 void Input::setError(Node
*node
, const Twine
&message
) {
350 Strm
->printError(node
, message
);
351 EC
= make_error_code(errc::invalid_argument
);
354 std::unique_ptr
<Input::HNode
> Input::createHNodes(Node
*N
) {
355 SmallString
<128> StringStorage
;
356 if (ScalarNode
*SN
= dyn_cast
<ScalarNode
>(N
)) {
357 StringRef KeyStr
= SN
->getValue(StringStorage
);
358 if (!StringStorage
.empty()) {
359 // Copy string to permanent storage
360 KeyStr
= StringStorage
.str().copy(StringAllocator
);
362 return llvm::make_unique
<ScalarHNode
>(N
, KeyStr
);
363 } else if (BlockScalarNode
*BSN
= dyn_cast
<BlockScalarNode
>(N
)) {
364 StringRef ValueCopy
= BSN
->getValue().copy(StringAllocator
);
365 return llvm::make_unique
<ScalarHNode
>(N
, ValueCopy
);
366 } else if (SequenceNode
*SQ
= dyn_cast
<SequenceNode
>(N
)) {
367 auto SQHNode
= llvm::make_unique
<SequenceHNode
>(N
);
368 for (Node
&SN
: *SQ
) {
369 auto Entry
= this->createHNodes(&SN
);
372 SQHNode
->Entries
.push_back(std::move(Entry
));
374 return std::move(SQHNode
);
375 } else if (MappingNode
*Map
= dyn_cast
<MappingNode
>(N
)) {
376 auto mapHNode
= llvm::make_unique
<MapHNode
>(N
);
377 for (KeyValueNode
&KVN
: *Map
) {
378 Node
*KeyNode
= KVN
.getKey();
379 ScalarNode
*Key
= dyn_cast
<ScalarNode
>(KeyNode
);
380 Node
*Value
= KVN
.getValue();
381 if (!Key
|| !Value
) {
383 setError(KeyNode
, "Map key must be a scalar");
385 setError(KeyNode
, "Map value must not be empty");
388 StringStorage
.clear();
389 StringRef KeyStr
= Key
->getValue(StringStorage
);
390 if (!StringStorage
.empty()) {
391 // Copy string to permanent storage
392 KeyStr
= StringStorage
.str().copy(StringAllocator
);
394 auto ValueHNode
= this->createHNodes(Value
);
397 mapHNode
->Mapping
[KeyStr
] = std::move(ValueHNode
);
399 return std::move(mapHNode
);
400 } else if (isa
<NullNode
>(N
)) {
401 return llvm::make_unique
<EmptyHNode
>(N
);
403 setError(N
, "unknown node kind");
408 void Input::setError(const Twine
&Message
) {
409 this->setError(CurrentNode
, Message
);
412 bool Input::canElideEmptySequence() {
416 //===----------------------------------------------------------------------===//
418 //===----------------------------------------------------------------------===//
420 Output::Output(raw_ostream
&yout
, void *context
, int WrapColumn
)
421 : IO(context
), Out(yout
), WrapColumn(WrapColumn
) {}
423 Output::~Output() = default;
425 bool Output::outputting() {
429 void Output::beginMapping() {
430 StateStack
.push_back(inMapFirstKey
);
434 bool Output::mapTag(StringRef Tag
, bool Use
) {
436 // If this tag is being written inside a sequence we should write the start
437 // of the sequence before writing the tag, otherwise the tag won't be
438 // attached to the element in the sequence, but rather the sequence itself.
439 bool SequenceElement
=
440 StateStack
.size() > 1 && (StateStack
[StateStack
.size() - 2] == inSeq
||
441 StateStack
[StateStack
.size() - 2] == inFlowSeq
);
442 if (SequenceElement
&& StateStack
.back() == inMapFirstKey
) {
443 this->newLineCheck();
448 if (SequenceElement
) {
449 // If we're writing the tag during the first element of a map, the tag
450 // takes the place of the first element in the sequence.
451 if (StateStack
.back() == inMapFirstKey
) {
452 StateStack
.pop_back();
453 StateStack
.push_back(inMapOtherKey
);
455 // Tags inside maps in sequences should act as keys in the map from a
456 // formatting perspective, so we always want a newline in a sequence.
463 void Output::endMapping() {
464 StateStack
.pop_back();
467 std::vector
<StringRef
> Output::keys() {
468 report_fatal_error("invalid call");
471 bool Output::preflightKey(const char *Key
, bool Required
, bool SameAsDefault
,
472 bool &UseDefault
, void *&) {
474 if (Required
|| !SameAsDefault
|| WriteDefaultValues
) {
475 auto State
= StateStack
.back();
476 if (State
== inFlowMapFirstKey
|| State
== inFlowMapOtherKey
) {
479 this->newLineCheck();
480 this->paddedKey(Key
);
487 void Output::postflightKey(void *) {
488 if (StateStack
.back() == inMapFirstKey
) {
489 StateStack
.pop_back();
490 StateStack
.push_back(inMapOtherKey
);
491 } else if (StateStack
.back() == inFlowMapFirstKey
) {
492 StateStack
.pop_back();
493 StateStack
.push_back(inFlowMapOtherKey
);
497 void Output::beginFlowMapping() {
498 StateStack
.push_back(inFlowMapFirstKey
);
499 this->newLineCheck();
500 ColumnAtMapFlowStart
= Column
;
504 void Output::endFlowMapping() {
505 StateStack
.pop_back();
506 this->outputUpToEndOfLine(" }");
509 void Output::beginDocuments() {
510 this->outputUpToEndOfLine("---");
513 bool Output::preflightDocument(unsigned index
) {
515 this->outputUpToEndOfLine("\n---");
519 void Output::postflightDocument() {
522 void Output::endDocuments() {
526 unsigned Output::beginSequence() {
527 StateStack
.push_back(inSeq
);
532 void Output::endSequence() {
533 StateStack
.pop_back();
536 bool Output::preflightElement(unsigned, void *&) {
540 void Output::postflightElement(void *) {
543 unsigned Output::beginFlowSequence() {
544 StateStack
.push_back(inFlowSeq
);
545 this->newLineCheck();
546 ColumnAtFlowStart
= Column
;
548 NeedFlowSequenceComma
= false;
552 void Output::endFlowSequence() {
553 StateStack
.pop_back();
554 this->outputUpToEndOfLine(" ]");
557 bool Output::preflightFlowElement(unsigned, void *&) {
558 if (NeedFlowSequenceComma
)
560 if (WrapColumn
&& Column
> WrapColumn
) {
562 for (int i
= 0; i
< ColumnAtFlowStart
; ++i
)
564 Column
= ColumnAtFlowStart
;
570 void Output::postflightFlowElement(void *) {
571 NeedFlowSequenceComma
= true;
574 void Output::beginEnumScalar() {
575 EnumerationMatchFound
= false;
578 bool Output::matchEnumScalar(const char *Str
, bool Match
) {
579 if (Match
&& !EnumerationMatchFound
) {
580 this->newLineCheck();
581 this->outputUpToEndOfLine(Str
);
582 EnumerationMatchFound
= true;
587 bool Output::matchEnumFallback() {
588 if (EnumerationMatchFound
)
590 EnumerationMatchFound
= true;
594 void Output::endEnumScalar() {
595 if (!EnumerationMatchFound
)
596 llvm_unreachable("bad runtime enum value");
599 bool Output::beginBitSetScalar(bool &DoClear
) {
600 this->newLineCheck();
602 NeedBitValueComma
= false;
607 bool Output::bitSetMatch(const char *Str
, bool Matches
) {
609 if (NeedBitValueComma
)
612 NeedBitValueComma
= true;
617 void Output::endBitSetScalar() {
618 this->outputUpToEndOfLine(" ]");
621 void Output::scalarString(StringRef
&S
, QuotingType MustQuote
) {
622 this->newLineCheck();
624 // Print '' for the empty string because leaving the field empty is not
626 this->outputUpToEndOfLine("''");
629 if (MustQuote
== QuotingType::None
) {
630 // Only quote if we must.
631 this->outputUpToEndOfLine(S
);
637 unsigned End
= S
.size();
638 const char *Base
= S
.data();
640 const char *const Quote
= MustQuote
== QuotingType::Single
? "'" : "\"";
641 output(Quote
); // Starting quote.
643 // When using double-quoted strings (and only in that case), non-printable characters may be
644 // present, and will be escaped using a variety of unicode-scalar and special short-form
645 // escapes. This is handled in yaml::escape.
646 if (MustQuote
== QuotingType::Double
) {
647 output(yaml::escape(Base
, /* EscapePrintable= */ false));
648 this->outputUpToEndOfLine(Quote
);
652 // When using single-quoted strings, any single quote ' must be doubled to be escaped.
654 if (S
[j
] == '\'') { // Escape quotes.
655 output(StringRef(&Base
[i
], j
- i
)); // "flush".
656 output(StringLiteral("''")); // Print it as ''
661 output(StringRef(&Base
[i
], j
- i
));
662 this->outputUpToEndOfLine(Quote
); // Ending quote.
665 void Output::blockScalarString(StringRef
&S
) {
666 if (!StateStack
.empty())
671 unsigned Indent
= StateStack
.empty() ? 1 : StateStack
.size();
673 auto Buffer
= MemoryBuffer::getMemBuffer(S
, "", false);
674 for (line_iterator
Lines(*Buffer
, false); !Lines
.is_at_end(); ++Lines
) {
675 for (unsigned I
= 0; I
< Indent
; ++I
) {
683 void Output::setError(const Twine
&message
) {
686 bool Output::canElideEmptySequence() {
687 // Normally, with an optional key/value where the value is an empty sequence,
688 // the whole key/value can be not written. But, that produces wrong yaml
689 // if the key/value is the only thing in the map and the map is used in
690 // a sequence. This detects if the this sequence is the first key/value
691 // in map that itself is embedded in a sequnce.
692 if (StateStack
.size() < 2)
694 if (StateStack
.back() != inMapFirstKey
)
696 return (StateStack
[StateStack
.size()-2] != inSeq
);
699 void Output::output(StringRef s
) {
704 void Output::outputUpToEndOfLine(StringRef s
) {
706 if (StateStack
.empty() || (StateStack
.back() != inFlowSeq
&&
707 StateStack
.back() != inFlowMapFirstKey
&&
708 StateStack
.back() != inFlowMapOtherKey
))
712 void Output::outputNewLine() {
717 // if seq at top, indent as if map, then add "- "
718 // if seq in middle, use "- " if firstKey, else use " "
721 void Output::newLineCheck() {
724 NeedsNewLine
= false;
726 this->outputNewLine();
728 assert(StateStack
.size() > 0);
729 unsigned Indent
= StateStack
.size() - 1;
730 bool OutputDash
= false;
732 if (StateStack
.back() == inSeq
) {
734 } else if ((StateStack
.size() > 1) && ((StateStack
.back() == inMapFirstKey
) ||
735 (StateStack
.back() == inFlowSeq
) ||
736 (StateStack
.back() == inFlowMapFirstKey
)) &&
737 (StateStack
[StateStack
.size() - 2] == inSeq
)) {
742 for (unsigned i
= 0; i
< Indent
; ++i
) {
751 void Output::paddedKey(StringRef key
) {
754 const char *spaces
= " ";
755 if (key
.size() < strlen(spaces
))
756 output(&spaces
[key
.size()]);
761 void Output::flowKey(StringRef Key
) {
762 if (StateStack
.back() == inFlowMapOtherKey
)
764 if (WrapColumn
&& Column
> WrapColumn
) {
766 for (int I
= 0; I
< ColumnAtMapFlowStart
; ++I
)
768 Column
= ColumnAtMapFlowStart
;
775 //===----------------------------------------------------------------------===//
776 // traits for built-in types
777 //===----------------------------------------------------------------------===//
779 void ScalarTraits
<bool>::output(const bool &Val
, void *, raw_ostream
&Out
) {
780 Out
<< (Val
? "true" : "false");
783 StringRef ScalarTraits
<bool>::input(StringRef Scalar
, void *, bool &Val
) {
784 if (Scalar
.equals("true")) {
787 } else if (Scalar
.equals("false")) {
791 return "invalid boolean";
794 void ScalarTraits
<StringRef
>::output(const StringRef
&Val
, void *,
799 StringRef ScalarTraits
<StringRef
>::input(StringRef Scalar
, void *,
805 void ScalarTraits
<std::string
>::output(const std::string
&Val
, void *,
810 StringRef ScalarTraits
<std::string
>::input(StringRef Scalar
, void *,
816 void ScalarTraits
<uint8_t>::output(const uint8_t &Val
, void *,
818 // use temp uin32_t because ostream thinks uint8_t is a character
823 StringRef ScalarTraits
<uint8_t>::input(StringRef Scalar
, void *, uint8_t &Val
) {
824 unsigned long long n
;
825 if (getAsUnsignedInteger(Scalar
, 0, n
))
826 return "invalid number";
828 return "out of range number";
833 void ScalarTraits
<uint16_t>::output(const uint16_t &Val
, void *,
838 StringRef ScalarTraits
<uint16_t>::input(StringRef Scalar
, void *,
840 unsigned long long n
;
841 if (getAsUnsignedInteger(Scalar
, 0, n
))
842 return "invalid number";
844 return "out of range number";
849 void ScalarTraits
<uint32_t>::output(const uint32_t &Val
, void *,
854 StringRef ScalarTraits
<uint32_t>::input(StringRef Scalar
, void *,
856 unsigned long long n
;
857 if (getAsUnsignedInteger(Scalar
, 0, n
))
858 return "invalid number";
859 if (n
> 0xFFFFFFFFUL
)
860 return "out of range number";
865 void ScalarTraits
<uint64_t>::output(const uint64_t &Val
, void *,
870 StringRef ScalarTraits
<uint64_t>::input(StringRef Scalar
, void *,
872 unsigned long long N
;
873 if (getAsUnsignedInteger(Scalar
, 0, N
))
874 return "invalid number";
879 void ScalarTraits
<int8_t>::output(const int8_t &Val
, void *, raw_ostream
&Out
) {
880 // use temp in32_t because ostream thinks int8_t is a character
885 StringRef ScalarTraits
<int8_t>::input(StringRef Scalar
, void *, int8_t &Val
) {
887 if (getAsSignedInteger(Scalar
, 0, N
))
888 return "invalid number";
889 if ((N
> 127) || (N
< -128))
890 return "out of range number";
895 void ScalarTraits
<int16_t>::output(const int16_t &Val
, void *,
900 StringRef ScalarTraits
<int16_t>::input(StringRef Scalar
, void *, int16_t &Val
) {
902 if (getAsSignedInteger(Scalar
, 0, N
))
903 return "invalid number";
904 if ((N
> INT16_MAX
) || (N
< INT16_MIN
))
905 return "out of range number";
910 void ScalarTraits
<int32_t>::output(const int32_t &Val
, void *,
915 StringRef ScalarTraits
<int32_t>::input(StringRef Scalar
, void *, int32_t &Val
) {
917 if (getAsSignedInteger(Scalar
, 0, N
))
918 return "invalid number";
919 if ((N
> INT32_MAX
) || (N
< INT32_MIN
))
920 return "out of range number";
925 void ScalarTraits
<int64_t>::output(const int64_t &Val
, void *,
930 StringRef ScalarTraits
<int64_t>::input(StringRef Scalar
, void *, int64_t &Val
) {
932 if (getAsSignedInteger(Scalar
, 0, N
))
933 return "invalid number";
938 void ScalarTraits
<double>::output(const double &Val
, void *, raw_ostream
&Out
) {
939 Out
<< format("%g", Val
);
942 StringRef ScalarTraits
<double>::input(StringRef Scalar
, void *, double &Val
) {
943 if (to_float(Scalar
, Val
))
945 return "invalid floating point number";
948 void ScalarTraits
<float>::output(const float &Val
, void *, raw_ostream
&Out
) {
949 Out
<< format("%g", Val
);
952 StringRef ScalarTraits
<float>::input(StringRef Scalar
, void *, float &Val
) {
953 if (to_float(Scalar
, Val
))
955 return "invalid floating point number";
958 void ScalarTraits
<Hex8
>::output(const Hex8
&Val
, void *, raw_ostream
&Out
) {
960 Out
<< format("0x%02X", Num
);
963 StringRef ScalarTraits
<Hex8
>::input(StringRef Scalar
, void *, Hex8
&Val
) {
964 unsigned long long n
;
965 if (getAsUnsignedInteger(Scalar
, 0, n
))
966 return "invalid hex8 number";
968 return "out of range hex8 number";
973 void ScalarTraits
<Hex16
>::output(const Hex16
&Val
, void *, raw_ostream
&Out
) {
975 Out
<< format("0x%04X", Num
);
978 StringRef ScalarTraits
<Hex16
>::input(StringRef Scalar
, void *, Hex16
&Val
) {
979 unsigned long long n
;
980 if (getAsUnsignedInteger(Scalar
, 0, n
))
981 return "invalid hex16 number";
983 return "out of range hex16 number";
988 void ScalarTraits
<Hex32
>::output(const Hex32
&Val
, void *, raw_ostream
&Out
) {
990 Out
<< format("0x%08X", Num
);
993 StringRef ScalarTraits
<Hex32
>::input(StringRef Scalar
, void *, Hex32
&Val
) {
994 unsigned long long n
;
995 if (getAsUnsignedInteger(Scalar
, 0, n
))
996 return "invalid hex32 number";
997 if (n
> 0xFFFFFFFFUL
)
998 return "out of range hex32 number";
1003 void ScalarTraits
<Hex64
>::output(const Hex64
&Val
, void *, raw_ostream
&Out
) {
1005 Out
<< format("0x%016llX", Num
);
1008 StringRef ScalarTraits
<Hex64
>::input(StringRef Scalar
, void *, Hex64
&Val
) {
1009 unsigned long long Num
;
1010 if (getAsUnsignedInteger(Scalar
, 0, Num
))
1011 return "invalid hex64 number";