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