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