YAMLTraits.cpp revision 36b56886974eae4f9c5ebc96befd3e7bfe5de338
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(NULL) {
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 (MapHNode::NameToNode::iterator i = MN->Mapping.begin(),
162       End = MN->Mapping.end(); i != End; ++i) {
163    if (!MN->isValidKey(i->first())) {
164      setError(i->second, Twine("unknown key '") + i->first() + "'");
165      break;
166    }
167  }
168}
169
170unsigned Input::beginSequence() {
171  if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) {
172    return SQ->Entries.size();
173  }
174  return 0;
175}
176
177void Input::endSequence() {
178}
179
180bool Input::preflightElement(unsigned Index, void *&SaveInfo) {
181  if (EC)
182    return false;
183  if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) {
184    SaveInfo = CurrentNode;
185    CurrentNode = SQ->Entries[Index];
186    return true;
187  }
188  return false;
189}
190
191void Input::postflightElement(void *SaveInfo) {
192  CurrentNode = reinterpret_cast<HNode *>(SaveInfo);
193}
194
195unsigned Input::beginFlowSequence() {
196  if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) {
197    return SQ->Entries.size();
198  }
199  return 0;
200}
201
202bool Input::preflightFlowElement(unsigned index, void *&SaveInfo) {
203  if (EC)
204    return false;
205  if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) {
206    SaveInfo = CurrentNode;
207    CurrentNode = SQ->Entries[index];
208    return true;
209  }
210  return false;
211}
212
213void Input::postflightFlowElement(void *SaveInfo) {
214  CurrentNode = reinterpret_cast<HNode *>(SaveInfo);
215}
216
217void Input::endFlowSequence() {
218}
219
220void Input::beginEnumScalar() {
221  ScalarMatchFound = false;
222}
223
224bool Input::matchEnumScalar(const char *Str, bool) {
225  if (ScalarMatchFound)
226    return false;
227  if (ScalarHNode *SN = dyn_cast<ScalarHNode>(CurrentNode)) {
228    if (SN->value().equals(Str)) {
229      ScalarMatchFound = true;
230      return true;
231    }
232  }
233  return false;
234}
235
236void Input::endEnumScalar() {
237  if (!ScalarMatchFound) {
238    setError(CurrentNode, "unknown enumerated scalar");
239  }
240}
241
242bool Input::beginBitSetScalar(bool &DoClear) {
243  BitValuesUsed.clear();
244  if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) {
245    BitValuesUsed.insert(BitValuesUsed.begin(), SQ->Entries.size(), false);
246  } else {
247    setError(CurrentNode, "expected sequence of bit values");
248  }
249  DoClear = true;
250  return true;
251}
252
253bool Input::bitSetMatch(const char *Str, bool) {
254  if (EC)
255    return false;
256  if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) {
257    unsigned Index = 0;
258    for (std::vector<HNode *>::iterator i = SQ->Entries.begin(),
259         End = SQ->Entries.end(); i != End; ++i) {
260      if (ScalarHNode *SN = dyn_cast<ScalarHNode>(*i)) {
261        if (SN->value().equals(Str)) {
262          BitValuesUsed[Index] = true;
263          return true;
264        }
265      } else {
266        setError(CurrentNode, "unexpected scalar in sequence of bit values");
267      }
268      ++Index;
269    }
270  } else {
271    setError(CurrentNode, "expected sequence of bit values");
272  }
273  return false;
274}
275
276void Input::endBitSetScalar() {
277  if (EC)
278    return;
279  if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) {
280    assert(BitValuesUsed.size() == SQ->Entries.size());
281    for (unsigned i = 0; i < SQ->Entries.size(); ++i) {
282      if (!BitValuesUsed[i]) {
283        setError(SQ->Entries[i], "unknown bit value");
284        return;
285      }
286    }
287  }
288}
289
290void Input::scalarString(StringRef &S) {
291  if (ScalarHNode *SN = dyn_cast<ScalarHNode>(CurrentNode)) {
292    S = SN->value();
293  } else {
294    setError(CurrentNode, "unexpected scalar");
295  }
296}
297
298void Input::setError(HNode *hnode, const Twine &message) {
299  assert(hnode && "HNode must not be NULL");
300  this->setError(hnode->_node, message);
301}
302
303void Input::setError(Node *node, const Twine &message) {
304  Strm->printError(node, message);
305  EC = make_error_code(errc::invalid_argument);
306}
307
308Input::HNode *Input::createHNodes(Node *N) {
309  SmallString<128> StringStorage;
310  if (ScalarNode *SN = dyn_cast<ScalarNode>(N)) {
311    StringRef KeyStr = SN->getValue(StringStorage);
312    if (!StringStorage.empty()) {
313      // Copy string to permanent storage
314      unsigned Len = StringStorage.size();
315      char *Buf = StringAllocator.Allocate<char>(Len);
316      memcpy(Buf, &StringStorage[0], Len);
317      KeyStr = StringRef(Buf, Len);
318    }
319    return new ScalarHNode(N, KeyStr);
320  } else if (SequenceNode *SQ = dyn_cast<SequenceNode>(N)) {
321    SequenceHNode *SQHNode = new SequenceHNode(N);
322    for (SequenceNode::iterator i = SQ->begin(), End = SQ->end(); i != End;
323         ++i) {
324      HNode *Entry = this->createHNodes(i);
325      if (EC)
326        break;
327      SQHNode->Entries.push_back(Entry);
328    }
329    return SQHNode;
330  } else if (MappingNode *Map = dyn_cast<MappingNode>(N)) {
331    MapHNode *mapHNode = new MapHNode(N);
332    for (MappingNode::iterator i = Map->begin(), End = Map->end(); i != End;
333         ++i) {
334      ScalarNode *KeyScalar = dyn_cast<ScalarNode>(i->getKey());
335      StringStorage.clear();
336      StringRef KeyStr = KeyScalar->getValue(StringStorage);
337      if (!StringStorage.empty()) {
338        // Copy string to permanent storage
339        unsigned Len = StringStorage.size();
340        char *Buf = StringAllocator.Allocate<char>(Len);
341        memcpy(Buf, &StringStorage[0], Len);
342        KeyStr = StringRef(Buf, Len);
343      }
344      HNode *ValueHNode = this->createHNodes(i->getValue());
345      if (EC)
346        break;
347      mapHNode->Mapping[KeyStr] = ValueHNode;
348    }
349    return mapHNode;
350  } else if (isa<NullNode>(N)) {
351    return new EmptyHNode(N);
352  } else {
353    setError(N, "unknown node kind");
354    return NULL;
355  }
356}
357
358bool Input::MapHNode::isValidKey(StringRef Key) {
359  for (SmallVectorImpl<const char *>::iterator i = ValidKeys.begin(),
360       End = ValidKeys.end(); i != End; ++i) {
361    if (Key.equals(*i))
362      return true;
363  }
364  return false;
365}
366
367void Input::setError(const Twine &Message) {
368  this->setError(CurrentNode, Message);
369}
370
371bool Input::canElideEmptySequence() {
372  return false;
373}
374
375Input::MapHNode::~MapHNode() {
376  for (MapHNode::NameToNode::iterator i = Mapping.begin(), End = Mapping.end();
377                                                                i != End; ++i) {
378    delete i->second;
379  }
380}
381
382Input::SequenceHNode::~SequenceHNode() {
383  for (std::vector<HNode*>::iterator i = Entries.begin(), End = Entries.end();
384                                                                i != End; ++i) {
385    delete *i;
386  }
387}
388
389
390
391//===----------------------------------------------------------------------===//
392//  Output
393//===----------------------------------------------------------------------===//
394
395Output::Output(raw_ostream &yout, void *context)
396    : IO(context),
397      Out(yout),
398      Column(0),
399      ColumnAtFlowStart(0),
400      NeedBitValueComma(false),
401      NeedFlowSequenceComma(false),
402      EnumerationMatchFound(false),
403      NeedsNewLine(false) {
404}
405
406Output::~Output() {
407}
408
409bool Output::outputting() {
410  return true;
411}
412
413void Output::beginMapping() {
414  StateStack.push_back(inMapFirstKey);
415  NeedsNewLine = true;
416}
417
418bool Output::mapTag(StringRef Tag, bool Use) {
419  if (Use) {
420    this->output(" ");
421    this->output(Tag);
422  }
423  return Use;
424}
425
426void Output::endMapping() {
427  StateStack.pop_back();
428}
429
430bool Output::preflightKey(const char *Key, bool Required, bool SameAsDefault,
431                          bool &UseDefault, void *&) {
432  UseDefault = false;
433  if (Required || !SameAsDefault) {
434    this->newLineCheck();
435    this->paddedKey(Key);
436    return true;
437  }
438  return false;
439}
440
441void Output::postflightKey(void *) {
442  if (StateStack.back() == inMapFirstKey) {
443    StateStack.pop_back();
444    StateStack.push_back(inMapOtherKey);
445  }
446}
447
448void Output::beginDocuments() {
449  this->outputUpToEndOfLine("---");
450}
451
452bool Output::preflightDocument(unsigned index) {
453  if (index > 0)
454    this->outputUpToEndOfLine("\n---");
455  return true;
456}
457
458void Output::postflightDocument() {
459}
460
461void Output::endDocuments() {
462  output("\n...\n");
463}
464
465unsigned Output::beginSequence() {
466  StateStack.push_back(inSeq);
467  NeedsNewLine = true;
468  return 0;
469}
470
471void Output::endSequence() {
472  StateStack.pop_back();
473}
474
475bool Output::preflightElement(unsigned, void *&) {
476  return true;
477}
478
479void Output::postflightElement(void *) {
480}
481
482unsigned Output::beginFlowSequence() {
483  StateStack.push_back(inFlowSeq);
484  this->newLineCheck();
485  ColumnAtFlowStart = Column;
486  output("[ ");
487  NeedFlowSequenceComma = false;
488  return 0;
489}
490
491void Output::endFlowSequence() {
492  StateStack.pop_back();
493  this->outputUpToEndOfLine(" ]");
494}
495
496bool Output::preflightFlowElement(unsigned, void *&) {
497  if (NeedFlowSequenceComma)
498    output(", ");
499  if (Column > 70) {
500    output("\n");
501    for (int i = 0; i < ColumnAtFlowStart; ++i)
502      output(" ");
503    Column = ColumnAtFlowStart;
504    output("  ");
505  }
506  return true;
507}
508
509void Output::postflightFlowElement(void *) {
510  NeedFlowSequenceComma = true;
511}
512
513void Output::beginEnumScalar() {
514  EnumerationMatchFound = false;
515}
516
517bool Output::matchEnumScalar(const char *Str, bool Match) {
518  if (Match && !EnumerationMatchFound) {
519    this->newLineCheck();
520    this->outputUpToEndOfLine(Str);
521    EnumerationMatchFound = true;
522  }
523  return false;
524}
525
526void Output::endEnumScalar() {
527  if (!EnumerationMatchFound)
528    llvm_unreachable("bad runtime enum value");
529}
530
531bool Output::beginBitSetScalar(bool &DoClear) {
532  this->newLineCheck();
533  output("[ ");
534  NeedBitValueComma = false;
535  DoClear = false;
536  return true;
537}
538
539bool Output::bitSetMatch(const char *Str, bool Matches) {
540  if (Matches) {
541    if (NeedBitValueComma)
542      output(", ");
543    this->output(Str);
544    NeedBitValueComma = true;
545  }
546  return false;
547}
548
549void Output::endBitSetScalar() {
550  this->outputUpToEndOfLine(" ]");
551}
552
553void Output::scalarString(StringRef &S) {
554  const char ScalarSafeChars[] = "abcdefghijklmnopqrstuvwxyz"
555      "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-/^., \t";
556
557  this->newLineCheck();
558  if (S.empty()) {
559    // Print '' for the empty string because leaving the field empty is not
560    // allowed.
561    this->outputUpToEndOfLine("''");
562    return;
563  }
564  if (S.find_first_not_of(ScalarSafeChars) == StringRef::npos &&
565      !isspace(S.front()) && !isspace(S.back())) {
566    // If the string consists only of safe characters, print it out without
567    // quotes.
568    this->outputUpToEndOfLine(S);
569    return;
570  }
571  unsigned i = 0;
572  unsigned j = 0;
573  unsigned End = S.size();
574  output("'"); // Starting single quote.
575  const char *Base = S.data();
576  while (j < End) {
577    // Escape a single quote by doubling it.
578    if (S[j] == '\'') {
579      output(StringRef(&Base[i], j - i + 1));
580      output("'");
581      i = j + 1;
582    }
583    ++j;
584  }
585  output(StringRef(&Base[i], j - i));
586  this->outputUpToEndOfLine("'"); // Ending single quote.
587}
588
589void Output::setError(const Twine &message) {
590}
591
592bool Output::canElideEmptySequence() {
593  // Normally, with an optional key/value where the value is an empty sequence,
594  // the whole key/value can be not written.  But, that produces wrong yaml
595  // if the key/value is the only thing in the map and the map is used in
596  // a sequence.  This detects if the this sequence is the first key/value
597  // in map that itself is embedded in a sequnce.
598  if (StateStack.size() < 2)
599    return true;
600  if (StateStack.back() != inMapFirstKey)
601    return true;
602  return (StateStack[StateStack.size()-2] != inSeq);
603}
604
605void Output::output(StringRef s) {
606  Column += s.size();
607  Out << s;
608}
609
610void Output::outputUpToEndOfLine(StringRef s) {
611  this->output(s);
612  if (StateStack.empty() || StateStack.back() != inFlowSeq)
613    NeedsNewLine = true;
614}
615
616void Output::outputNewLine() {
617  Out << "\n";
618  Column = 0;
619}
620
621// if seq at top, indent as if map, then add "- "
622// if seq in middle, use "- " if firstKey, else use "  "
623//
624
625void Output::newLineCheck() {
626  if (!NeedsNewLine)
627    return;
628  NeedsNewLine = false;
629
630  this->outputNewLine();
631
632  assert(StateStack.size() > 0);
633  unsigned Indent = StateStack.size() - 1;
634  bool OutputDash = false;
635
636  if (StateStack.back() == inSeq) {
637    OutputDash = true;
638  } else if ((StateStack.size() > 1) && (StateStack.back() == inMapFirstKey) &&
639             (StateStack[StateStack.size() - 2] == inSeq)) {
640    --Indent;
641    OutputDash = true;
642  }
643
644  for (unsigned i = 0; i < Indent; ++i) {
645    output("  ");
646  }
647  if (OutputDash) {
648    output("- ");
649  }
650
651}
652
653void Output::paddedKey(StringRef key) {
654  output(key);
655  output(":");
656  const char *spaces = "                ";
657  if (key.size() < strlen(spaces))
658    output(&spaces[key.size()]);
659  else
660    output(" ");
661}
662
663//===----------------------------------------------------------------------===//
664//  traits for built-in types
665//===----------------------------------------------------------------------===//
666
667void ScalarTraits<bool>::output(const bool &Val, void *, raw_ostream &Out) {
668  Out << (Val ? "true" : "false");
669}
670
671StringRef ScalarTraits<bool>::input(StringRef Scalar, void *, bool &Val) {
672  if (Scalar.equals("true")) {
673    Val = true;
674    return StringRef();
675  } else if (Scalar.equals("false")) {
676    Val = false;
677    return StringRef();
678  }
679  return "invalid boolean";
680}
681
682void ScalarTraits<StringRef>::output(const StringRef &Val, void *,
683                                     raw_ostream &Out) {
684  Out << Val;
685}
686
687StringRef ScalarTraits<StringRef>::input(StringRef Scalar, void *,
688                                         StringRef &Val) {
689  Val = Scalar;
690  return StringRef();
691}
692
693void ScalarTraits<std::string>::output(const std::string &Val, void *,
694                                     raw_ostream &Out) {
695  Out << Val;
696}
697
698StringRef ScalarTraits<std::string>::input(StringRef Scalar, void *,
699                                         std::string &Val) {
700  Val = Scalar.str();
701  return StringRef();
702}
703
704void ScalarTraits<uint8_t>::output(const uint8_t &Val, void *,
705                                   raw_ostream &Out) {
706  // use temp uin32_t because ostream thinks uint8_t is a character
707  uint32_t Num = Val;
708  Out << Num;
709}
710
711StringRef ScalarTraits<uint8_t>::input(StringRef Scalar, void *, uint8_t &Val) {
712  unsigned long long n;
713  if (getAsUnsignedInteger(Scalar, 0, n))
714    return "invalid number";
715  if (n > 0xFF)
716    return "out of range number";
717  Val = n;
718  return StringRef();
719}
720
721void ScalarTraits<uint16_t>::output(const uint16_t &Val, void *,
722                                    raw_ostream &Out) {
723  Out << Val;
724}
725
726StringRef ScalarTraits<uint16_t>::input(StringRef Scalar, void *,
727                                        uint16_t &Val) {
728  unsigned long long n;
729  if (getAsUnsignedInteger(Scalar, 0, n))
730    return "invalid number";
731  if (n > 0xFFFF)
732    return "out of range number";
733  Val = n;
734  return StringRef();
735}
736
737void ScalarTraits<uint32_t>::output(const uint32_t &Val, void *,
738                                    raw_ostream &Out) {
739  Out << Val;
740}
741
742StringRef ScalarTraits<uint32_t>::input(StringRef Scalar, void *,
743                                        uint32_t &Val) {
744  unsigned long long n;
745  if (getAsUnsignedInteger(Scalar, 0, n))
746    return "invalid number";
747  if (n > 0xFFFFFFFFUL)
748    return "out of range number";
749  Val = n;
750  return StringRef();
751}
752
753void ScalarTraits<uint64_t>::output(const uint64_t &Val, void *,
754                                    raw_ostream &Out) {
755  Out << Val;
756}
757
758StringRef ScalarTraits<uint64_t>::input(StringRef Scalar, void *,
759                                        uint64_t &Val) {
760  unsigned long long N;
761  if (getAsUnsignedInteger(Scalar, 0, N))
762    return "invalid number";
763  Val = N;
764  return StringRef();
765}
766
767void ScalarTraits<int8_t>::output(const int8_t &Val, void *, raw_ostream &Out) {
768  // use temp in32_t because ostream thinks int8_t is a character
769  int32_t Num = Val;
770  Out << Num;
771}
772
773StringRef ScalarTraits<int8_t>::input(StringRef Scalar, void *, int8_t &Val) {
774  long long N;
775  if (getAsSignedInteger(Scalar, 0, N))
776    return "invalid number";
777  if ((N > 127) || (N < -128))
778    return "out of range number";
779  Val = N;
780  return StringRef();
781}
782
783void ScalarTraits<int16_t>::output(const int16_t &Val, void *,
784                                   raw_ostream &Out) {
785  Out << Val;
786}
787
788StringRef ScalarTraits<int16_t>::input(StringRef Scalar, void *, int16_t &Val) {
789  long long N;
790  if (getAsSignedInteger(Scalar, 0, N))
791    return "invalid number";
792  if ((N > INT16_MAX) || (N < INT16_MIN))
793    return "out of range number";
794  Val = N;
795  return StringRef();
796}
797
798void ScalarTraits<int32_t>::output(const int32_t &Val, void *,
799                                   raw_ostream &Out) {
800  Out << Val;
801}
802
803StringRef ScalarTraits<int32_t>::input(StringRef Scalar, void *, int32_t &Val) {
804  long long N;
805  if (getAsSignedInteger(Scalar, 0, N))
806    return "invalid number";
807  if ((N > INT32_MAX) || (N < INT32_MIN))
808    return "out of range number";
809  Val = N;
810  return StringRef();
811}
812
813void ScalarTraits<int64_t>::output(const int64_t &Val, void *,
814                                   raw_ostream &Out) {
815  Out << Val;
816}
817
818StringRef ScalarTraits<int64_t>::input(StringRef Scalar, void *, int64_t &Val) {
819  long long N;
820  if (getAsSignedInteger(Scalar, 0, N))
821    return "invalid number";
822  Val = N;
823  return StringRef();
824}
825
826void ScalarTraits<double>::output(const double &Val, void *, raw_ostream &Out) {
827  Out << format("%g", Val);
828}
829
830StringRef ScalarTraits<double>::input(StringRef Scalar, void *, double &Val) {
831  SmallString<32> buff(Scalar.begin(), Scalar.end());
832  char *end;
833  Val = strtod(buff.c_str(), &end);
834  if (*end != '\0')
835    return "invalid floating point number";
836  return StringRef();
837}
838
839void ScalarTraits<float>::output(const float &Val, void *, raw_ostream &Out) {
840  Out << format("%g", Val);
841}
842
843StringRef ScalarTraits<float>::input(StringRef Scalar, void *, float &Val) {
844  SmallString<32> buff(Scalar.begin(), Scalar.end());
845  char *end;
846  Val = strtod(buff.c_str(), &end);
847  if (*end != '\0')
848    return "invalid floating point number";
849  return StringRef();
850}
851
852void ScalarTraits<Hex8>::output(const Hex8 &Val, void *, raw_ostream &Out) {
853  uint8_t Num = Val;
854  Out << format("0x%02X", Num);
855}
856
857StringRef ScalarTraits<Hex8>::input(StringRef Scalar, void *, Hex8 &Val) {
858  unsigned long long n;
859  if (getAsUnsignedInteger(Scalar, 0, n))
860    return "invalid hex8 number";
861  if (n > 0xFF)
862    return "out of range hex8 number";
863  Val = n;
864  return StringRef();
865}
866
867void ScalarTraits<Hex16>::output(const Hex16 &Val, void *, raw_ostream &Out) {
868  uint16_t Num = Val;
869  Out << format("0x%04X", Num);
870}
871
872StringRef ScalarTraits<Hex16>::input(StringRef Scalar, void *, Hex16 &Val) {
873  unsigned long long n;
874  if (getAsUnsignedInteger(Scalar, 0, n))
875    return "invalid hex16 number";
876  if (n > 0xFFFF)
877    return "out of range hex16 number";
878  Val = n;
879  return StringRef();
880}
881
882void ScalarTraits<Hex32>::output(const Hex32 &Val, void *, raw_ostream &Out) {
883  uint32_t Num = Val;
884  Out << format("0x%08X", Num);
885}
886
887StringRef ScalarTraits<Hex32>::input(StringRef Scalar, void *, Hex32 &Val) {
888  unsigned long long n;
889  if (getAsUnsignedInteger(Scalar, 0, n))
890    return "invalid hex32 number";
891  if (n > 0xFFFFFFFFUL)
892    return "out of range hex32 number";
893  Val = n;
894  return StringRef();
895}
896
897void ScalarTraits<Hex64>::output(const Hex64 &Val, void *, raw_ostream &Out) {
898  uint64_t Num = Val;
899  Out << format("0x%016llX", Num);
900}
901
902StringRef ScalarTraits<Hex64>::input(StringRef Scalar, void *, Hex64 &Val) {
903  unsigned long long Num;
904  if (getAsUnsignedInteger(Scalar, 0, Num))
905    return "invalid hex64 number";
906  Val = Num;
907  return StringRef();
908}
909