YAMLTraits.cpp revision dce4a407a24b04eebc6a376f8e62b41aaa7b071f
1//===- lib/Support/YAMLTraits.cpp -----------------------------------------===//
2//
3//                             The LLVM Linker
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "llvm/Support/YAMLTraits.h"
11#include "llvm/ADT/Twine.h"
12#include "llvm/Support/Casting.h"
13#include "llvm/Support/ErrorHandling.h"
14#include "llvm/Support/Format.h"
15#include "llvm/Support/YAMLParser.h"
16#include "llvm/Support/raw_ostream.h"
17#include <cctype>
18#include <cstring>
19using namespace llvm;
20using namespace yaml;
21
22//===----------------------------------------------------------------------===//
23//  IO
24//===----------------------------------------------------------------------===//
25
26IO::IO(void *Context) : Ctxt(Context) {
27}
28
29IO::~IO() {
30}
31
32void *IO::getContext() {
33  return Ctxt;
34}
35
36void IO::setContext(void *Context) {
37  Ctxt = Context;
38}
39
40//===----------------------------------------------------------------------===//
41//  Input
42//===----------------------------------------------------------------------===//
43
44Input::Input(StringRef InputContent,
45             void *Ctxt,
46             SourceMgr::DiagHandlerTy DiagHandler,
47             void *DiagHandlerCtxt)
48  : IO(Ctxt),
49    Strm(new Stream(InputContent, SrcMgr)),
50    CurrentNode(nullptr) {
51  if (DiagHandler)
52    SrcMgr.setDiagHandler(DiagHandler, DiagHandlerCtxt);
53  DocIterator = Strm->begin();
54}
55
56Input::~Input() {
57}
58
59error_code Input::error() {
60  return EC;
61}
62
63// Pin the vtables to this file.
64void Input::HNode::anchor() {}
65void Input::EmptyHNode::anchor() {}
66void Input::ScalarHNode::anchor() {}
67
68bool Input::outputting() {
69  return false;
70}
71
72bool Input::setCurrentDocument() {
73  if (DocIterator != Strm->end()) {
74    Node *N = DocIterator->getRoot();
75    if (!N) {
76      assert(Strm->failed() && "Root is NULL iff parsing failed");
77      EC = make_error_code(errc::invalid_argument);
78      return false;
79    }
80
81    if (isa<NullNode>(N)) {
82      // Empty files are allowed and ignored
83      ++DocIterator;
84      return setCurrentDocument();
85    }
86    TopNode.reset(this->createHNodes(N));
87    CurrentNode = TopNode.get();
88    return true;
89  }
90  return false;
91}
92
93void Input::nextDocument() {
94  ++DocIterator;
95}
96
97bool Input::mapTag(StringRef Tag, bool Default) {
98  std::string foundTag = CurrentNode->_node->getVerbatimTag();
99  if (foundTag.empty()) {
100    // If no tag found and 'Tag' is the default, say it was found.
101    return Default;
102  }
103  // Return true iff found tag matches supplied tag.
104  return Tag.equals(foundTag);
105}
106
107void Input::beginMapping() {
108  if (EC)
109    return;
110  // CurrentNode can be null if the document is empty.
111  MapHNode *MN = dyn_cast_or_null<MapHNode>(CurrentNode);
112  if (MN) {
113    MN->ValidKeys.clear();
114  }
115}
116
117bool Input::preflightKey(const char *Key, bool Required, bool, bool &UseDefault,
118                         void *&SaveInfo) {
119  UseDefault = false;
120  if (EC)
121    return false;
122
123  // CurrentNode is null for empty documents, which is an error in case required
124  // nodes are present.
125  if (!CurrentNode) {
126    if (Required)
127      EC = make_error_code(errc::invalid_argument);
128    return false;
129  }
130
131  MapHNode *MN = dyn_cast<MapHNode>(CurrentNode);
132  if (!MN) {
133    setError(CurrentNode, "not a mapping");
134    return false;
135  }
136  MN->ValidKeys.push_back(Key);
137  HNode *Value = MN->Mapping[Key];
138  if (!Value) {
139    if (Required)
140      setError(CurrentNode, Twine("missing required key '") + Key + "'");
141    else
142      UseDefault = true;
143    return false;
144  }
145  SaveInfo = CurrentNode;
146  CurrentNode = Value;
147  return true;
148}
149
150void Input::postflightKey(void *saveInfo) {
151  CurrentNode = reinterpret_cast<HNode *>(saveInfo);
152}
153
154void Input::endMapping() {
155  if (EC)
156    return;
157  // CurrentNode can be null if the document is empty.
158  MapHNode *MN = dyn_cast_or_null<MapHNode>(CurrentNode);
159  if (!MN)
160    return;
161  for (const auto &NN : MN->Mapping) {
162    if (!MN->isValidKey(NN.first())) {
163      setError(NN.second, Twine("unknown key '") + NN.first() + "'");
164      break;
165    }
166  }
167}
168
169unsigned Input::beginSequence() {
170  if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) {
171    return SQ->Entries.size();
172  }
173  return 0;
174}
175
176void Input::endSequence() {
177}
178
179bool Input::preflightElement(unsigned Index, void *&SaveInfo) {
180  if (EC)
181    return false;
182  if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) {
183    SaveInfo = CurrentNode;
184    CurrentNode = SQ->Entries[Index];
185    return true;
186  }
187  return false;
188}
189
190void Input::postflightElement(void *SaveInfo) {
191  CurrentNode = reinterpret_cast<HNode *>(SaveInfo);
192}
193
194unsigned Input::beginFlowSequence() {
195  if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) {
196    return SQ->Entries.size();
197  }
198  return 0;
199}
200
201bool Input::preflightFlowElement(unsigned index, void *&SaveInfo) {
202  if (EC)
203    return false;
204  if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) {
205    SaveInfo = CurrentNode;
206    CurrentNode = SQ->Entries[index];
207    return true;
208  }
209  return false;
210}
211
212void Input::postflightFlowElement(void *SaveInfo) {
213  CurrentNode = reinterpret_cast<HNode *>(SaveInfo);
214}
215
216void Input::endFlowSequence() {
217}
218
219void Input::beginEnumScalar() {
220  ScalarMatchFound = false;
221}
222
223bool Input::matchEnumScalar(const char *Str, bool) {
224  if (ScalarMatchFound)
225    return false;
226  if (ScalarHNode *SN = dyn_cast<ScalarHNode>(CurrentNode)) {
227    if (SN->value().equals(Str)) {
228      ScalarMatchFound = true;
229      return true;
230    }
231  }
232  return false;
233}
234
235void Input::endEnumScalar() {
236  if (!ScalarMatchFound) {
237    setError(CurrentNode, "unknown enumerated scalar");
238  }
239}
240
241bool Input::beginBitSetScalar(bool &DoClear) {
242  BitValuesUsed.clear();
243  if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) {
244    BitValuesUsed.insert(BitValuesUsed.begin(), SQ->Entries.size(), false);
245  } else {
246    setError(CurrentNode, "expected sequence of bit values");
247  }
248  DoClear = true;
249  return true;
250}
251
252bool Input::bitSetMatch(const char *Str, bool) {
253  if (EC)
254    return false;
255  if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) {
256    unsigned Index = 0;
257    for (HNode *N : SQ->Entries) {
258      if (ScalarHNode *SN = dyn_cast<ScalarHNode>(N)) {
259        if (SN->value().equals(Str)) {
260          BitValuesUsed[Index] = true;
261          return true;
262        }
263      } else {
264        setError(CurrentNode, "unexpected scalar in sequence of bit values");
265      }
266      ++Index;
267    }
268  } else {
269    setError(CurrentNode, "expected sequence of bit values");
270  }
271  return false;
272}
273
274void Input::endBitSetScalar() {
275  if (EC)
276    return;
277  if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) {
278    assert(BitValuesUsed.size() == SQ->Entries.size());
279    for (unsigned i = 0; i < SQ->Entries.size(); ++i) {
280      if (!BitValuesUsed[i]) {
281        setError(SQ->Entries[i], "unknown bit value");
282        return;
283      }
284    }
285  }
286}
287
288void Input::scalarString(StringRef &S, bool) {
289  if (ScalarHNode *SN = dyn_cast<ScalarHNode>(CurrentNode)) {
290    S = SN->value();
291  } else {
292    setError(CurrentNode, "unexpected scalar");
293  }
294}
295
296void Input::setError(HNode *hnode, const Twine &message) {
297  assert(hnode && "HNode must not be NULL");
298  this->setError(hnode->_node, message);
299}
300
301void Input::setError(Node *node, const Twine &message) {
302  Strm->printError(node, message);
303  EC = make_error_code(errc::invalid_argument);
304}
305
306Input::HNode *Input::createHNodes(Node *N) {
307  SmallString<128> StringStorage;
308  if (ScalarNode *SN = dyn_cast<ScalarNode>(N)) {
309    StringRef KeyStr = SN->getValue(StringStorage);
310    if (!StringStorage.empty()) {
311      // Copy string to permanent storage
312      unsigned Len = StringStorage.size();
313      char *Buf = StringAllocator.Allocate<char>(Len);
314      memcpy(Buf, &StringStorage[0], Len);
315      KeyStr = StringRef(Buf, Len);
316    }
317    return new ScalarHNode(N, KeyStr);
318  } else if (SequenceNode *SQ = dyn_cast<SequenceNode>(N)) {
319    SequenceHNode *SQHNode = new SequenceHNode(N);
320    for (Node &SN : *SQ) {
321      HNode *Entry = this->createHNodes(&SN);
322      if (EC)
323        break;
324      SQHNode->Entries.push_back(Entry);
325    }
326    return SQHNode;
327  } else if (MappingNode *Map = dyn_cast<MappingNode>(N)) {
328    MapHNode *mapHNode = new MapHNode(N);
329    for (KeyValueNode &KVN : *Map) {
330      ScalarNode *KeyScalar = dyn_cast<ScalarNode>(KVN.getKey());
331      StringStorage.clear();
332      StringRef KeyStr = KeyScalar->getValue(StringStorage);
333      if (!StringStorage.empty()) {
334        // Copy string to permanent storage
335        unsigned Len = StringStorage.size();
336        char *Buf = StringAllocator.Allocate<char>(Len);
337        memcpy(Buf, &StringStorage[0], Len);
338        KeyStr = StringRef(Buf, Len);
339      }
340      HNode *ValueHNode = this->createHNodes(KVN.getValue());
341      if (EC)
342        break;
343      mapHNode->Mapping[KeyStr] = ValueHNode;
344    }
345    return mapHNode;
346  } else if (isa<NullNode>(N)) {
347    return new EmptyHNode(N);
348  } else {
349    setError(N, "unknown node kind");
350    return nullptr;
351  }
352}
353
354bool Input::MapHNode::isValidKey(StringRef Key) {
355  for (const char *K : ValidKeys) {
356    if (Key.equals(K))
357      return true;
358  }
359  return false;
360}
361
362void Input::setError(const Twine &Message) {
363  this->setError(CurrentNode, Message);
364}
365
366bool Input::canElideEmptySequence() {
367  return false;
368}
369
370Input::MapHNode::~MapHNode() {
371  for (auto &N : Mapping)
372    delete N.second;
373}
374
375Input::SequenceHNode::~SequenceHNode() {
376  for (HNode *N : Entries)
377    delete N;
378}
379
380
381
382//===----------------------------------------------------------------------===//
383//  Output
384//===----------------------------------------------------------------------===//
385
386Output::Output(raw_ostream &yout, void *context)
387    : IO(context),
388      Out(yout),
389      Column(0),
390      ColumnAtFlowStart(0),
391      NeedBitValueComma(false),
392      NeedFlowSequenceComma(false),
393      EnumerationMatchFound(false),
394      NeedsNewLine(false) {
395}
396
397Output::~Output() {
398}
399
400bool Output::outputting() {
401  return true;
402}
403
404void Output::beginMapping() {
405  StateStack.push_back(inMapFirstKey);
406  NeedsNewLine = true;
407}
408
409bool Output::mapTag(StringRef Tag, bool Use) {
410  if (Use) {
411    this->output(" ");
412    this->output(Tag);
413  }
414  return Use;
415}
416
417void Output::endMapping() {
418  StateStack.pop_back();
419}
420
421bool Output::preflightKey(const char *Key, bool Required, bool SameAsDefault,
422                          bool &UseDefault, void *&) {
423  UseDefault = false;
424  if (Required || !SameAsDefault) {
425    this->newLineCheck();
426    this->paddedKey(Key);
427    return true;
428  }
429  return false;
430}
431
432void Output::postflightKey(void *) {
433  if (StateStack.back() == inMapFirstKey) {
434    StateStack.pop_back();
435    StateStack.push_back(inMapOtherKey);
436  }
437}
438
439void Output::beginDocuments() {
440  this->outputUpToEndOfLine("---");
441}
442
443bool Output::preflightDocument(unsigned index) {
444  if (index > 0)
445    this->outputUpToEndOfLine("\n---");
446  return true;
447}
448
449void Output::postflightDocument() {
450}
451
452void Output::endDocuments() {
453  output("\n...\n");
454}
455
456unsigned Output::beginSequence() {
457  StateStack.push_back(inSeq);
458  NeedsNewLine = true;
459  return 0;
460}
461
462void Output::endSequence() {
463  StateStack.pop_back();
464}
465
466bool Output::preflightElement(unsigned, void *&) {
467  return true;
468}
469
470void Output::postflightElement(void *) {
471}
472
473unsigned Output::beginFlowSequence() {
474  StateStack.push_back(inFlowSeq);
475  this->newLineCheck();
476  ColumnAtFlowStart = Column;
477  output("[ ");
478  NeedFlowSequenceComma = false;
479  return 0;
480}
481
482void Output::endFlowSequence() {
483  StateStack.pop_back();
484  this->outputUpToEndOfLine(" ]");
485}
486
487bool Output::preflightFlowElement(unsigned, void *&) {
488  if (NeedFlowSequenceComma)
489    output(", ");
490  if (Column > 70) {
491    output("\n");
492    for (int i = 0; i < ColumnAtFlowStart; ++i)
493      output(" ");
494    Column = ColumnAtFlowStart;
495    output("  ");
496  }
497  return true;
498}
499
500void Output::postflightFlowElement(void *) {
501  NeedFlowSequenceComma = true;
502}
503
504void Output::beginEnumScalar() {
505  EnumerationMatchFound = false;
506}
507
508bool Output::matchEnumScalar(const char *Str, bool Match) {
509  if (Match && !EnumerationMatchFound) {
510    this->newLineCheck();
511    this->outputUpToEndOfLine(Str);
512    EnumerationMatchFound = true;
513  }
514  return false;
515}
516
517void Output::endEnumScalar() {
518  if (!EnumerationMatchFound)
519    llvm_unreachable("bad runtime enum value");
520}
521
522bool Output::beginBitSetScalar(bool &DoClear) {
523  this->newLineCheck();
524  output("[ ");
525  NeedBitValueComma = false;
526  DoClear = false;
527  return true;
528}
529
530bool Output::bitSetMatch(const char *Str, bool Matches) {
531  if (Matches) {
532    if (NeedBitValueComma)
533      output(", ");
534    this->output(Str);
535    NeedBitValueComma = true;
536  }
537  return false;
538}
539
540void Output::endBitSetScalar() {
541  this->outputUpToEndOfLine(" ]");
542}
543
544void Output::scalarString(StringRef &S, bool MustQuote) {
545  this->newLineCheck();
546  if (S.empty()) {
547    // Print '' for the empty string because leaving the field empty is not
548    // allowed.
549    this->outputUpToEndOfLine("''");
550    return;
551  }
552  if (!MustQuote) {
553    // Only quote if we must.
554    this->outputUpToEndOfLine(S);
555    return;
556  }
557  unsigned i = 0;
558  unsigned j = 0;
559  unsigned End = S.size();
560  output("'"); // Starting single quote.
561  const char *Base = S.data();
562  while (j < End) {
563    // Escape a single quote by doubling it.
564    if (S[j] == '\'') {
565      output(StringRef(&Base[i], j - i + 1));
566      output("'");
567      i = j + 1;
568    }
569    ++j;
570  }
571  output(StringRef(&Base[i], j - i));
572  this->outputUpToEndOfLine("'"); // Ending single quote.
573}
574
575void Output::setError(const Twine &message) {
576}
577
578bool Output::canElideEmptySequence() {
579  // Normally, with an optional key/value where the value is an empty sequence,
580  // the whole key/value can be not written.  But, that produces wrong yaml
581  // if the key/value is the only thing in the map and the map is used in
582  // a sequence.  This detects if the this sequence is the first key/value
583  // in map that itself is embedded in a sequnce.
584  if (StateStack.size() < 2)
585    return true;
586  if (StateStack.back() != inMapFirstKey)
587    return true;
588  return (StateStack[StateStack.size()-2] != inSeq);
589}
590
591void Output::output(StringRef s) {
592  Column += s.size();
593  Out << s;
594}
595
596void Output::outputUpToEndOfLine(StringRef s) {
597  this->output(s);
598  if (StateStack.empty() || StateStack.back() != inFlowSeq)
599    NeedsNewLine = true;
600}
601
602void Output::outputNewLine() {
603  Out << "\n";
604  Column = 0;
605}
606
607// if seq at top, indent as if map, then add "- "
608// if seq in middle, use "- " if firstKey, else use "  "
609//
610
611void Output::newLineCheck() {
612  if (!NeedsNewLine)
613    return;
614  NeedsNewLine = false;
615
616  this->outputNewLine();
617
618  assert(StateStack.size() > 0);
619  unsigned Indent = StateStack.size() - 1;
620  bool OutputDash = false;
621
622  if (StateStack.back() == inSeq) {
623    OutputDash = true;
624  } else if ((StateStack.size() > 1) && (StateStack.back() == inMapFirstKey) &&
625             (StateStack[StateStack.size() - 2] == inSeq)) {
626    --Indent;
627    OutputDash = true;
628  }
629
630  for (unsigned i = 0; i < Indent; ++i) {
631    output("  ");
632  }
633  if (OutputDash) {
634    output("- ");
635  }
636
637}
638
639void Output::paddedKey(StringRef key) {
640  output(key);
641  output(":");
642  const char *spaces = "                ";
643  if (key.size() < strlen(spaces))
644    output(&spaces[key.size()]);
645  else
646    output(" ");
647}
648
649//===----------------------------------------------------------------------===//
650//  traits for built-in types
651//===----------------------------------------------------------------------===//
652
653void ScalarTraits<bool>::output(const bool &Val, void *, raw_ostream &Out) {
654  Out << (Val ? "true" : "false");
655}
656
657StringRef ScalarTraits<bool>::input(StringRef Scalar, void *, bool &Val) {
658  if (Scalar.equals("true")) {
659    Val = true;
660    return StringRef();
661  } else if (Scalar.equals("false")) {
662    Val = false;
663    return StringRef();
664  }
665  return "invalid boolean";
666}
667
668void ScalarTraits<StringRef>::output(const StringRef &Val, void *,
669                                     raw_ostream &Out) {
670  Out << Val;
671}
672
673StringRef ScalarTraits<StringRef>::input(StringRef Scalar, void *,
674                                         StringRef &Val) {
675  Val = Scalar;
676  return StringRef();
677}
678
679void ScalarTraits<std::string>::output(const std::string &Val, void *,
680                                     raw_ostream &Out) {
681  Out << Val;
682}
683
684StringRef ScalarTraits<std::string>::input(StringRef Scalar, void *,
685                                         std::string &Val) {
686  Val = Scalar.str();
687  return StringRef();
688}
689
690void ScalarTraits<uint8_t>::output(const uint8_t &Val, void *,
691                                   raw_ostream &Out) {
692  // use temp uin32_t because ostream thinks uint8_t is a character
693  uint32_t Num = Val;
694  Out << Num;
695}
696
697StringRef ScalarTraits<uint8_t>::input(StringRef Scalar, void *, uint8_t &Val) {
698  unsigned long long n;
699  if (getAsUnsignedInteger(Scalar, 0, n))
700    return "invalid number";
701  if (n > 0xFF)
702    return "out of range number";
703  Val = n;
704  return StringRef();
705}
706
707void ScalarTraits<uint16_t>::output(const uint16_t &Val, void *,
708                                    raw_ostream &Out) {
709  Out << Val;
710}
711
712StringRef ScalarTraits<uint16_t>::input(StringRef Scalar, void *,
713                                        uint16_t &Val) {
714  unsigned long long n;
715  if (getAsUnsignedInteger(Scalar, 0, n))
716    return "invalid number";
717  if (n > 0xFFFF)
718    return "out of range number";
719  Val = n;
720  return StringRef();
721}
722
723void ScalarTraits<uint32_t>::output(const uint32_t &Val, void *,
724                                    raw_ostream &Out) {
725  Out << Val;
726}
727
728StringRef ScalarTraits<uint32_t>::input(StringRef Scalar, void *,
729                                        uint32_t &Val) {
730  unsigned long long n;
731  if (getAsUnsignedInteger(Scalar, 0, n))
732    return "invalid number";
733  if (n > 0xFFFFFFFFUL)
734    return "out of range number";
735  Val = n;
736  return StringRef();
737}
738
739void ScalarTraits<uint64_t>::output(const uint64_t &Val, void *,
740                                    raw_ostream &Out) {
741  Out << Val;
742}
743
744StringRef ScalarTraits<uint64_t>::input(StringRef Scalar, void *,
745                                        uint64_t &Val) {
746  unsigned long long N;
747  if (getAsUnsignedInteger(Scalar, 0, N))
748    return "invalid number";
749  Val = N;
750  return StringRef();
751}
752
753void ScalarTraits<int8_t>::output(const int8_t &Val, void *, raw_ostream &Out) {
754  // use temp in32_t because ostream thinks int8_t is a character
755  int32_t Num = Val;
756  Out << Num;
757}
758
759StringRef ScalarTraits<int8_t>::input(StringRef Scalar, void *, int8_t &Val) {
760  long long N;
761  if (getAsSignedInteger(Scalar, 0, N))
762    return "invalid number";
763  if ((N > 127) || (N < -128))
764    return "out of range number";
765  Val = N;
766  return StringRef();
767}
768
769void ScalarTraits<int16_t>::output(const int16_t &Val, void *,
770                                   raw_ostream &Out) {
771  Out << Val;
772}
773
774StringRef ScalarTraits<int16_t>::input(StringRef Scalar, void *, int16_t &Val) {
775  long long N;
776  if (getAsSignedInteger(Scalar, 0, N))
777    return "invalid number";
778  if ((N > INT16_MAX) || (N < INT16_MIN))
779    return "out of range number";
780  Val = N;
781  return StringRef();
782}
783
784void ScalarTraits<int32_t>::output(const int32_t &Val, void *,
785                                   raw_ostream &Out) {
786  Out << Val;
787}
788
789StringRef ScalarTraits<int32_t>::input(StringRef Scalar, void *, int32_t &Val) {
790  long long N;
791  if (getAsSignedInteger(Scalar, 0, N))
792    return "invalid number";
793  if ((N > INT32_MAX) || (N < INT32_MIN))
794    return "out of range number";
795  Val = N;
796  return StringRef();
797}
798
799void ScalarTraits<int64_t>::output(const int64_t &Val, void *,
800                                   raw_ostream &Out) {
801  Out << Val;
802}
803
804StringRef ScalarTraits<int64_t>::input(StringRef Scalar, void *, int64_t &Val) {
805  long long N;
806  if (getAsSignedInteger(Scalar, 0, N))
807    return "invalid number";
808  Val = N;
809  return StringRef();
810}
811
812void ScalarTraits<double>::output(const double &Val, void *, raw_ostream &Out) {
813  Out << format("%g", Val);
814}
815
816StringRef ScalarTraits<double>::input(StringRef Scalar, void *, double &Val) {
817  SmallString<32> buff(Scalar.begin(), Scalar.end());
818  char *end;
819  Val = strtod(buff.c_str(), &end);
820  if (*end != '\0')
821    return "invalid floating point number";
822  return StringRef();
823}
824
825void ScalarTraits<float>::output(const float &Val, void *, raw_ostream &Out) {
826  Out << format("%g", Val);
827}
828
829StringRef ScalarTraits<float>::input(StringRef Scalar, void *, float &Val) {
830  SmallString<32> buff(Scalar.begin(), Scalar.end());
831  char *end;
832  Val = strtod(buff.c_str(), &end);
833  if (*end != '\0')
834    return "invalid floating point number";
835  return StringRef();
836}
837
838void ScalarTraits<Hex8>::output(const Hex8 &Val, void *, raw_ostream &Out) {
839  uint8_t Num = Val;
840  Out << format("0x%02X", Num);
841}
842
843StringRef ScalarTraits<Hex8>::input(StringRef Scalar, void *, Hex8 &Val) {
844  unsigned long long n;
845  if (getAsUnsignedInteger(Scalar, 0, n))
846    return "invalid hex8 number";
847  if (n > 0xFF)
848    return "out of range hex8 number";
849  Val = n;
850  return StringRef();
851}
852
853void ScalarTraits<Hex16>::output(const Hex16 &Val, void *, raw_ostream &Out) {
854  uint16_t Num = Val;
855  Out << format("0x%04X", Num);
856}
857
858StringRef ScalarTraits<Hex16>::input(StringRef Scalar, void *, Hex16 &Val) {
859  unsigned long long n;
860  if (getAsUnsignedInteger(Scalar, 0, n))
861    return "invalid hex16 number";
862  if (n > 0xFFFF)
863    return "out of range hex16 number";
864  Val = n;
865  return StringRef();
866}
867
868void ScalarTraits<Hex32>::output(const Hex32 &Val, void *, raw_ostream &Out) {
869  uint32_t Num = Val;
870  Out << format("0x%08X", Num);
871}
872
873StringRef ScalarTraits<Hex32>::input(StringRef Scalar, void *, Hex32 &Val) {
874  unsigned long long n;
875  if (getAsUnsignedInteger(Scalar, 0, n))
876    return "invalid hex32 number";
877  if (n > 0xFFFFFFFFUL)
878    return "out of range hex32 number";
879  Val = n;
880  return StringRef();
881}
882
883void ScalarTraits<Hex64>::output(const Hex64 &Val, void *, raw_ostream &Out) {
884  uint64_t Num = Val;
885  Out << format("0x%016llX", Num);
886}
887
888StringRef ScalarTraits<Hex64>::input(StringRef Scalar, void *, Hex64 &Val) {
889  unsigned long long Num;
890  if (getAsUnsignedInteger(Scalar, 0, Num))
891    return "invalid hex64 number";
892  Val = Num;
893  return StringRef();
894}
895