1 //===- lib/Support/YAMLTraits.cpp -----------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "llvm/Support/YAMLTraits.h" 10 #include "llvm/ADT/STLExtras.h" 11 #include "llvm/ADT/SmallString.h" 12 #include "llvm/ADT/StringExtras.h" 13 #include "llvm/ADT/StringRef.h" 14 #include "llvm/ADT/Twine.h" 15 #include "llvm/Support/Casting.h" 16 #include "llvm/Support/Errc.h" 17 #include "llvm/Support/ErrorHandling.h" 18 #include "llvm/Support/Format.h" 19 #include "llvm/Support/LineIterator.h" 20 #include "llvm/Support/MemoryBuffer.h" 21 #include "llvm/Support/VersionTuple.h" 22 #include "llvm/Support/YAMLParser.h" 23 #include "llvm/Support/raw_ostream.h" 24 #include <cassert> 25 #include <cstdint> 26 #include <cstring> 27 #include <string> 28 #include <vector> 29 30 using namespace llvm; 31 using namespace yaml; 32 33 //===----------------------------------------------------------------------===// 34 // IO 35 //===----------------------------------------------------------------------===// 36 37 IO::IO(void *Context) : Ctxt(Context) {} 38 39 IO::~IO() = default; 40 41 void *IO::getContext() const { 42 return Ctxt; 43 } 44 45 void IO::setContext(void *Context) { 46 Ctxt = Context; 47 } 48 49 void IO::setAllowUnknownKeys(bool Allow) { 50 llvm_unreachable("Only supported for Input"); 51 } 52 53 //===----------------------------------------------------------------------===// 54 // Input 55 //===----------------------------------------------------------------------===// 56 57 Input::Input(StringRef InputContent, void *Ctxt, 58 SourceMgr::DiagHandlerTy DiagHandler, void *DiagHandlerCtxt) 59 : IO(Ctxt), Strm(new Stream(InputContent, SrcMgr, false, &EC)) { 60 if (DiagHandler) 61 SrcMgr.setDiagHandler(DiagHandler, DiagHandlerCtxt); 62 DocIterator = Strm->begin(); 63 } 64 65 Input::Input(MemoryBufferRef Input, void *Ctxt, 66 SourceMgr::DiagHandlerTy DiagHandler, void *DiagHandlerCtxt) 67 : IO(Ctxt), Strm(new Stream(Input, SrcMgr, false, &EC)) { 68 if (DiagHandler) 69 SrcMgr.setDiagHandler(DiagHandler, DiagHandlerCtxt); 70 DocIterator = Strm->begin(); 71 } 72 73 Input::~Input() = default; 74 75 std::error_code Input::error() { return EC; } 76 77 bool Input::outputting() const { 78 return false; 79 } 80 81 bool Input::setCurrentDocument() { 82 if (DocIterator != Strm->end()) { 83 Node *N = DocIterator->getRoot(); 84 if (!N) { 85 EC = make_error_code(errc::invalid_argument); 86 return false; 87 } 88 89 if (isa<NullNode>(N)) { 90 // Empty files are allowed and ignored 91 ++DocIterator; 92 return setCurrentDocument(); 93 } 94 releaseHNodeBuffers(); 95 TopNode = createHNodes(N); 96 CurrentNode = TopNode; 97 return true; 98 } 99 return false; 100 } 101 102 bool Input::nextDocument() { 103 return ++DocIterator != Strm->end(); 104 } 105 106 const Node *Input::getCurrentNode() const { 107 return CurrentNode ? CurrentNode->_node : nullptr; 108 } 109 110 bool Input::mapTag(StringRef Tag, bool Default) { 111 // CurrentNode can be null if setCurrentDocument() was unable to 112 // parse the document because it was invalid or empty. 113 if (!CurrentNode) 114 return false; 115 116 std::string foundTag = CurrentNode->_node->getVerbatimTag(); 117 if (foundTag.empty()) { 118 // If no tag found and 'Tag' is the default, say it was found. 119 return Default; 120 } 121 // Return true iff found tag matches supplied tag. 122 return Tag == foundTag; 123 } 124 125 void Input::beginMapping() { 126 if (EC) 127 return; 128 // CurrentNode can be null if the document is empty. 129 MapHNode *MN = dyn_cast_or_null<MapHNode>(CurrentNode); 130 if (MN) { 131 MN->ValidKeys.clear(); 132 } 133 } 134 135 std::vector<StringRef> Input::keys() { 136 MapHNode *MN = dyn_cast<MapHNode>(CurrentNode); 137 std::vector<StringRef> Ret; 138 if (!MN) { 139 setError(CurrentNode, "not a mapping"); 140 return Ret; 141 } 142 for (auto &P : MN->Mapping) 143 Ret.push_back(P.first()); 144 return Ret; 145 } 146 147 bool Input::preflightKey(const char *Key, bool Required, bool, bool &UseDefault, 148 void *&SaveInfo) { 149 UseDefault = false; 150 if (EC) 151 return false; 152 153 // CurrentNode is null for empty documents, which is an error in case required 154 // nodes are present. 155 if (!CurrentNode) { 156 if (Required) 157 EC = make_error_code(errc::invalid_argument); 158 else 159 UseDefault = true; 160 return false; 161 } 162 163 MapHNode *MN = dyn_cast<MapHNode>(CurrentNode); 164 if (!MN) { 165 if (Required || !isa<EmptyHNode>(CurrentNode)) 166 setError(CurrentNode, "not a mapping"); 167 else 168 UseDefault = true; 169 return false; 170 } 171 MN->ValidKeys.push_back(Key); 172 HNode *Value = MN->Mapping[Key].first; 173 if (!Value) { 174 if (Required) 175 setError(CurrentNode, Twine("missing required key '") + Key + "'"); 176 else 177 UseDefault = true; 178 return false; 179 } 180 SaveInfo = CurrentNode; 181 CurrentNode = Value; 182 return true; 183 } 184 185 void Input::postflightKey(void *saveInfo) { 186 CurrentNode = reinterpret_cast<HNode *>(saveInfo); 187 } 188 189 void Input::endMapping() { 190 if (EC) 191 return; 192 // CurrentNode can be null if the document is empty. 193 MapHNode *MN = dyn_cast_or_null<MapHNode>(CurrentNode); 194 if (!MN) 195 return; 196 for (const auto &NN : MN->Mapping) { 197 if (!is_contained(MN->ValidKeys, NN.first())) { 198 const SMRange &ReportLoc = NN.second.second; 199 if (!AllowUnknownKeys) { 200 setError(ReportLoc, Twine("unknown key '") + NN.first() + "'"); 201 break; 202 } else 203 reportWarning(ReportLoc, Twine("unknown key '") + NN.first() + "'"); 204 } 205 } 206 } 207 208 void Input::beginFlowMapping() { beginMapping(); } 209 210 void Input::endFlowMapping() { endMapping(); } 211 212 unsigned Input::beginSequence() { 213 if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) 214 return SQ->Entries.size(); 215 if (isa<EmptyHNode>(CurrentNode)) 216 return 0; 217 // Treat case where there's a scalar "null" value as an empty sequence. 218 if (ScalarHNode *SN = dyn_cast<ScalarHNode>(CurrentNode)) { 219 if (isNull(SN->value())) 220 return 0; 221 } 222 // Any other type of HNode is an error. 223 setError(CurrentNode, "not a sequence"); 224 return 0; 225 } 226 227 void Input::endSequence() { 228 } 229 230 bool Input::preflightElement(unsigned Index, void *&SaveInfo) { 231 if (EC) 232 return false; 233 if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) { 234 SaveInfo = CurrentNode; 235 CurrentNode = SQ->Entries[Index]; 236 return true; 237 } 238 return false; 239 } 240 241 void Input::postflightElement(void *SaveInfo) { 242 CurrentNode = reinterpret_cast<HNode *>(SaveInfo); 243 } 244 245 unsigned Input::beginFlowSequence() { return beginSequence(); } 246 247 bool Input::preflightFlowElement(unsigned index, void *&SaveInfo) { 248 if (EC) 249 return false; 250 if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) { 251 SaveInfo = CurrentNode; 252 CurrentNode = SQ->Entries[index]; 253 return true; 254 } 255 return false; 256 } 257 258 void Input::postflightFlowElement(void *SaveInfo) { 259 CurrentNode = reinterpret_cast<HNode *>(SaveInfo); 260 } 261 262 void Input::endFlowSequence() { 263 } 264 265 void Input::beginEnumScalar() { 266 ScalarMatchFound = false; 267 } 268 269 bool Input::matchEnumScalar(const char *Str, bool) { 270 if (ScalarMatchFound) 271 return false; 272 if (ScalarHNode *SN = dyn_cast<ScalarHNode>(CurrentNode)) { 273 if (SN->value() == Str) { 274 ScalarMatchFound = true; 275 return true; 276 } 277 } 278 return false; 279 } 280 281 bool Input::matchEnumFallback() { 282 if (ScalarMatchFound) 283 return false; 284 ScalarMatchFound = true; 285 return true; 286 } 287 288 void Input::endEnumScalar() { 289 if (!ScalarMatchFound) { 290 setError(CurrentNode, "unknown enumerated scalar"); 291 } 292 } 293 294 bool Input::beginBitSetScalar(bool &DoClear) { 295 BitValuesUsed.clear(); 296 if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) { 297 BitValuesUsed.resize(SQ->Entries.size()); 298 } else { 299 setError(CurrentNode, "expected sequence of bit values"); 300 } 301 DoClear = true; 302 return true; 303 } 304 305 bool Input::bitSetMatch(const char *Str, bool) { 306 if (EC) 307 return false; 308 if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) { 309 unsigned Index = 0; 310 for (auto &N : SQ->Entries) { 311 if (ScalarHNode *SN = dyn_cast<ScalarHNode>(N)) { 312 if (SN->value() == Str) { 313 BitValuesUsed[Index] = true; 314 return true; 315 } 316 } else { 317 setError(CurrentNode, "unexpected scalar in sequence of bit values"); 318 } 319 ++Index; 320 } 321 } else { 322 setError(CurrentNode, "expected sequence of bit values"); 323 } 324 return false; 325 } 326 327 void Input::endBitSetScalar() { 328 if (EC) 329 return; 330 if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) { 331 assert(BitValuesUsed.size() == SQ->Entries.size()); 332 for (unsigned i = 0; i < SQ->Entries.size(); ++i) { 333 if (!BitValuesUsed[i]) { 334 setError(SQ->Entries[i], "unknown bit value"); 335 return; 336 } 337 } 338 } 339 } 340 341 void Input::scalarString(StringRef &S, QuotingType) { 342 if (ScalarHNode *SN = dyn_cast<ScalarHNode>(CurrentNode)) { 343 S = SN->value(); 344 } else { 345 setError(CurrentNode, "unexpected scalar"); 346 } 347 } 348 349 void Input::blockScalarString(StringRef &S) { scalarString(S, QuotingType::None); } 350 351 void Input::scalarTag(std::string &Tag) { 352 Tag = CurrentNode->_node->getVerbatimTag(); 353 } 354 355 void Input::setError(HNode *hnode, const Twine &message) { 356 assert(hnode && "HNode must not be NULL"); 357 setError(hnode->_node, message); 358 } 359 360 NodeKind Input::getNodeKind() { 361 if (isa<ScalarHNode>(CurrentNode)) 362 return NodeKind::Scalar; 363 else if (isa<MapHNode>(CurrentNode)) 364 return NodeKind::Map; 365 else if (isa<SequenceHNode>(CurrentNode)) 366 return NodeKind::Sequence; 367 llvm_unreachable("Unsupported node kind"); 368 } 369 370 void Input::setError(Node *node, const Twine &message) { 371 Strm->printError(node, message); 372 EC = make_error_code(errc::invalid_argument); 373 } 374 375 void Input::setError(const SMRange &range, const Twine &message) { 376 Strm->printError(range, message); 377 EC = make_error_code(errc::invalid_argument); 378 } 379 380 void Input::reportWarning(HNode *hnode, const Twine &message) { 381 assert(hnode && "HNode must not be NULL"); 382 Strm->printError(hnode->_node, message, SourceMgr::DK_Warning); 383 } 384 385 void Input::reportWarning(Node *node, const Twine &message) { 386 Strm->printError(node, message, SourceMgr::DK_Warning); 387 } 388 389 void Input::reportWarning(const SMRange &range, const Twine &message) { 390 Strm->printError(range, message, SourceMgr::DK_Warning); 391 } 392 393 void Input::releaseHNodeBuffers() { 394 EmptyHNodeAllocator.DestroyAll(); 395 ScalarHNodeAllocator.DestroyAll(); 396 SequenceHNodeAllocator.DestroyAll(); 397 MapHNodeAllocator.DestroyAll(); 398 } 399 400 Input::HNode *Input::createHNodes(Node *N) { 401 SmallString<128> StringStorage; 402 switch (N->getType()) { 403 case Node::NK_Scalar: { 404 ScalarNode *SN = dyn_cast<ScalarNode>(N); 405 StringRef KeyStr = SN->getValue(StringStorage); 406 if (!StringStorage.empty()) { 407 // Copy string to permanent storage 408 KeyStr = StringStorage.str().copy(StringAllocator); 409 } 410 return new (ScalarHNodeAllocator.Allocate()) ScalarHNode(N, KeyStr); 411 } 412 case Node::NK_BlockScalar: { 413 BlockScalarNode *BSN = dyn_cast<BlockScalarNode>(N); 414 StringRef ValueCopy = BSN->getValue().copy(StringAllocator); 415 return new (ScalarHNodeAllocator.Allocate()) ScalarHNode(N, ValueCopy); 416 } 417 case Node::NK_Sequence: { 418 SequenceNode *SQ = dyn_cast<SequenceNode>(N); 419 auto SQHNode = new (SequenceHNodeAllocator.Allocate()) SequenceHNode(N); 420 for (Node &SN : *SQ) { 421 auto Entry = createHNodes(&SN); 422 if (EC) 423 break; 424 SQHNode->Entries.push_back(Entry); 425 } 426 return SQHNode; 427 } 428 case Node::NK_Mapping: { 429 MappingNode *Map = dyn_cast<MappingNode>(N); 430 auto mapHNode = new (MapHNodeAllocator.Allocate()) MapHNode(N); 431 for (KeyValueNode &KVN : *Map) { 432 Node *KeyNode = KVN.getKey(); 433 ScalarNode *Key = dyn_cast_or_null<ScalarNode>(KeyNode); 434 Node *Value = KVN.getValue(); 435 if (!Key || !Value) { 436 if (!Key) 437 setError(KeyNode, "Map key must be a scalar"); 438 if (!Value) 439 setError(KeyNode, "Map value must not be empty"); 440 break; 441 } 442 StringStorage.clear(); 443 StringRef KeyStr = Key->getValue(StringStorage); 444 if (!StringStorage.empty()) { 445 // Copy string to permanent storage 446 KeyStr = StringStorage.str().copy(StringAllocator); 447 } 448 if (mapHNode->Mapping.count(KeyStr)) 449 // From YAML spec: "The content of a mapping node is an unordered set of 450 // key/value node pairs, with the restriction that each of the keys is 451 // unique." 452 setError(KeyNode, Twine("duplicated mapping key '") + KeyStr + "'"); 453 auto ValueHNode = createHNodes(Value); 454 if (EC) 455 break; 456 mapHNode->Mapping[KeyStr] = 457 std::make_pair(std::move(ValueHNode), KeyNode->getSourceRange()); 458 } 459 return std::move(mapHNode); 460 } 461 case Node::NK_Null: 462 return new (EmptyHNodeAllocator.Allocate()) EmptyHNode(N); 463 default: 464 setError(N, "unknown node kind"); 465 return nullptr; 466 } 467 } 468 469 void Input::setError(const Twine &Message) { 470 setError(CurrentNode, Message); 471 } 472 473 void Input::setAllowUnknownKeys(bool Allow) { AllowUnknownKeys = Allow; } 474 475 bool Input::canElideEmptySequence() { 476 return false; 477 } 478 479 //===----------------------------------------------------------------------===// 480 // Output 481 //===----------------------------------------------------------------------===// 482 483 Output::Output(raw_ostream &yout, void *context, int WrapColumn) 484 : IO(context), Out(yout), WrapColumn(WrapColumn) {} 485 486 Output::~Output() = default; 487 488 bool Output::outputting() const { 489 return true; 490 } 491 492 void Output::beginMapping() { 493 StateStack.push_back(inMapFirstKey); 494 PaddingBeforeContainer = Padding; 495 Padding = "\n"; 496 } 497 498 bool Output::mapTag(StringRef Tag, bool Use) { 499 if (Use) { 500 // If this tag is being written inside a sequence we should write the start 501 // of the sequence before writing the tag, otherwise the tag won't be 502 // attached to the element in the sequence, but rather the sequence itself. 503 bool SequenceElement = false; 504 if (StateStack.size() > 1) { 505 auto &E = StateStack[StateStack.size() - 2]; 506 SequenceElement = inSeqAnyElement(E) || inFlowSeqAnyElement(E); 507 } 508 if (SequenceElement && StateStack.back() == inMapFirstKey) { 509 newLineCheck(); 510 } else { 511 output(" "); 512 } 513 output(Tag); 514 if (SequenceElement) { 515 // If we're writing the tag during the first element of a map, the tag 516 // takes the place of the first element in the sequence. 517 if (StateStack.back() == inMapFirstKey) { 518 StateStack.pop_back(); 519 StateStack.push_back(inMapOtherKey); 520 } 521 // Tags inside maps in sequences should act as keys in the map from a 522 // formatting perspective, so we always want a newline in a sequence. 523 Padding = "\n"; 524 } 525 } 526 return Use; 527 } 528 529 void Output::endMapping() { 530 // If we did not map anything, we should explicitly emit an empty map 531 if (StateStack.back() == inMapFirstKey) { 532 Padding = PaddingBeforeContainer; 533 newLineCheck(); 534 output("{}"); 535 Padding = "\n"; 536 } 537 StateStack.pop_back(); 538 } 539 540 std::vector<StringRef> Output::keys() { 541 report_fatal_error("invalid call"); 542 } 543 544 bool Output::preflightKey(const char *Key, bool Required, bool SameAsDefault, 545 bool &UseDefault, void *&SaveInfo) { 546 UseDefault = false; 547 SaveInfo = nullptr; 548 if (Required || !SameAsDefault || WriteDefaultValues) { 549 auto State = StateStack.back(); 550 if (State == inFlowMapFirstKey || State == inFlowMapOtherKey) { 551 flowKey(Key); 552 } else { 553 newLineCheck(); 554 paddedKey(Key); 555 } 556 return true; 557 } 558 return false; 559 } 560 561 void Output::postflightKey(void *) { 562 if (StateStack.back() == inMapFirstKey) { 563 StateStack.pop_back(); 564 StateStack.push_back(inMapOtherKey); 565 } else if (StateStack.back() == inFlowMapFirstKey) { 566 StateStack.pop_back(); 567 StateStack.push_back(inFlowMapOtherKey); 568 } 569 } 570 571 void Output::beginFlowMapping() { 572 StateStack.push_back(inFlowMapFirstKey); 573 newLineCheck(); 574 ColumnAtMapFlowStart = Column; 575 output("{ "); 576 } 577 578 void Output::endFlowMapping() { 579 StateStack.pop_back(); 580 outputUpToEndOfLine(" }"); 581 } 582 583 void Output::beginDocuments() { 584 outputUpToEndOfLine("---"); 585 } 586 587 bool Output::preflightDocument(unsigned index) { 588 if (index > 0) 589 outputUpToEndOfLine("\n---"); 590 return true; 591 } 592 593 void Output::postflightDocument() { 594 } 595 596 void Output::endDocuments() { 597 output("\n...\n"); 598 } 599 600 unsigned Output::beginSequence() { 601 StateStack.push_back(inSeqFirstElement); 602 PaddingBeforeContainer = Padding; 603 Padding = "\n"; 604 return 0; 605 } 606 607 void Output::endSequence() { 608 // If we did not emit anything, we should explicitly emit an empty sequence 609 if (StateStack.back() == inSeqFirstElement) { 610 Padding = PaddingBeforeContainer; 611 newLineCheck(/*EmptySequence=*/true); 612 output("[]"); 613 Padding = "\n"; 614 } 615 StateStack.pop_back(); 616 } 617 618 bool Output::preflightElement(unsigned, void *&SaveInfo) { 619 SaveInfo = nullptr; 620 return true; 621 } 622 623 void Output::postflightElement(void *) { 624 if (StateStack.back() == inSeqFirstElement) { 625 StateStack.pop_back(); 626 StateStack.push_back(inSeqOtherElement); 627 } else if (StateStack.back() == inFlowSeqFirstElement) { 628 StateStack.pop_back(); 629 StateStack.push_back(inFlowSeqOtherElement); 630 } 631 } 632 633 unsigned Output::beginFlowSequence() { 634 StateStack.push_back(inFlowSeqFirstElement); 635 newLineCheck(); 636 ColumnAtFlowStart = Column; 637 output("[ "); 638 NeedFlowSequenceComma = false; 639 return 0; 640 } 641 642 void Output::endFlowSequence() { 643 StateStack.pop_back(); 644 outputUpToEndOfLine(" ]"); 645 } 646 647 bool Output::preflightFlowElement(unsigned, void *&SaveInfo) { 648 if (NeedFlowSequenceComma) 649 output(", "); 650 if (WrapColumn && Column > WrapColumn) { 651 output("\n"); 652 for (int i = 0; i < ColumnAtFlowStart; ++i) 653 output(" "); 654 Column = ColumnAtFlowStart; 655 output(" "); 656 } 657 SaveInfo = nullptr; 658 return true; 659 } 660 661 void Output::postflightFlowElement(void *) { 662 NeedFlowSequenceComma = true; 663 } 664 665 void Output::beginEnumScalar() { 666 EnumerationMatchFound = false; 667 } 668 669 bool Output::matchEnumScalar(const char *Str, bool Match) { 670 if (Match && !EnumerationMatchFound) { 671 newLineCheck(); 672 outputUpToEndOfLine(Str); 673 EnumerationMatchFound = true; 674 } 675 return false; 676 } 677 678 bool Output::matchEnumFallback() { 679 if (EnumerationMatchFound) 680 return false; 681 EnumerationMatchFound = true; 682 return true; 683 } 684 685 void Output::endEnumScalar() { 686 if (!EnumerationMatchFound) 687 llvm_unreachable("bad runtime enum value"); 688 } 689 690 bool Output::beginBitSetScalar(bool &DoClear) { 691 newLineCheck(); 692 output("[ "); 693 NeedBitValueComma = false; 694 DoClear = false; 695 return true; 696 } 697 698 bool Output::bitSetMatch(const char *Str, bool Matches) { 699 if (Matches) { 700 if (NeedBitValueComma) 701 output(", "); 702 output(Str); 703 NeedBitValueComma = true; 704 } 705 return false; 706 } 707 708 void Output::endBitSetScalar() { 709 outputUpToEndOfLine(" ]"); 710 } 711 712 void Output::scalarString(StringRef &S, QuotingType MustQuote) { 713 newLineCheck(); 714 if (S.empty()) { 715 // Print '' for the empty string because leaving the field empty is not 716 // allowed. 717 outputUpToEndOfLine("''"); 718 return; 719 } 720 output(S, MustQuote); 721 outputUpToEndOfLine(""); 722 } 723 724 void Output::blockScalarString(StringRef &S) { 725 if (!StateStack.empty()) 726 newLineCheck(); 727 output(" |"); 728 outputNewLine(); 729 730 unsigned Indent = StateStack.empty() ? 1 : StateStack.size(); 731 732 auto Buffer = MemoryBuffer::getMemBuffer(S, "", false); 733 for (line_iterator Lines(*Buffer, false); !Lines.is_at_end(); ++Lines) { 734 for (unsigned I = 0; I < Indent; ++I) { 735 output(" "); 736 } 737 output(*Lines); 738 outputNewLine(); 739 } 740 } 741 742 void Output::scalarTag(std::string &Tag) { 743 if (Tag.empty()) 744 return; 745 newLineCheck(); 746 output(Tag); 747 output(" "); 748 } 749 750 void Output::setError(const Twine &message) { 751 } 752 753 std::error_code Output::error() { return {}; } 754 755 bool Output::canElideEmptySequence() { 756 // Normally, with an optional key/value where the value is an empty sequence, 757 // the whole key/value can be not written. But, that produces wrong yaml 758 // if the key/value is the only thing in the map and the map is used in 759 // a sequence. This detects if the this sequence is the first key/value 760 // in map that itself is embedded in a sequence. 761 if (StateStack.size() < 2) 762 return true; 763 if (StateStack.back() != inMapFirstKey) 764 return true; 765 return !inSeqAnyElement(StateStack[StateStack.size() - 2]); 766 } 767 768 void Output::output(StringRef s) { 769 Column += s.size(); 770 Out << s; 771 } 772 773 void Output::output(StringRef S, QuotingType MustQuote) { 774 if (MustQuote == QuotingType::None) { 775 // Only quote if we must. 776 output(S); 777 return; 778 } 779 780 StringLiteral Quote = MustQuote == QuotingType::Single ? StringLiteral("'") 781 : StringLiteral("\""); 782 output(Quote); // Starting quote. 783 784 // When using double-quoted strings (and only in that case), non-printable 785 // characters may be present, and will be escaped using a variety of 786 // unicode-scalar and special short-form escapes. This is handled in 787 // yaml::escape. 788 if (MustQuote == QuotingType::Double) { 789 output(yaml::escape(S, /* EscapePrintable= */ false)); 790 output(Quote); 791 return; 792 } 793 794 unsigned i = 0; 795 unsigned j = 0; 796 unsigned End = S.size(); 797 const char *Base = S.data(); 798 799 // When using single-quoted strings, any single quote ' must be doubled to be 800 // escaped. 801 while (j < End) { 802 if (S[j] == '\'') { // Escape quotes. 803 output(StringRef(&Base[i], j - i)); // "flush". 804 output(StringLiteral("''")); // Print it as '' 805 i = j + 1; 806 } 807 ++j; 808 } 809 output(StringRef(&Base[i], j - i)); 810 output(Quote); // Ending quote. 811 } 812 813 void Output::outputUpToEndOfLine(StringRef s) { 814 output(s); 815 if (StateStack.empty() || (!inFlowSeqAnyElement(StateStack.back()) && 816 !inFlowMapAnyKey(StateStack.back()))) 817 Padding = "\n"; 818 } 819 820 void Output::outputNewLine() { 821 Out << "\n"; 822 Column = 0; 823 } 824 825 // if seq at top, indent as if map, then add "- " 826 // if seq in middle, use "- " if firstKey, else use " " 827 // 828 829 void Output::newLineCheck(bool EmptySequence) { 830 if (Padding != "\n") { 831 output(Padding); 832 Padding = {}; 833 return; 834 } 835 outputNewLine(); 836 Padding = {}; 837 838 if (StateStack.size() == 0 || EmptySequence) 839 return; 840 841 unsigned Indent = StateStack.size() - 1; 842 bool PossiblyNestedSeq = false; 843 auto I = StateStack.rbegin(), E = StateStack.rend(); 844 845 if (inSeqAnyElement(*I)) { 846 PossiblyNestedSeq = true; // Not possibly but always. 847 ++Indent; 848 } else if (*I == inMapFirstKey || *I == inFlowMapFirstKey || 849 inFlowSeqAnyElement(*I)) { 850 PossiblyNestedSeq = true; 851 ++I; // Skip back(). 852 } 853 854 unsigned OutputDashCount = 0; 855 if (PossiblyNestedSeq) { 856 // Count up consecutive inSeqFirstElement from the end, unless 857 // inSeqFirstElement is the top of nested sequence. 858 while (I != E) { 859 // Don't count the top of nested sequence. 860 if (!inSeqAnyElement(*I)) 861 break; 862 863 ++OutputDashCount; 864 865 // Stop counting if consecutive inSeqFirstElement ends. 866 if (*I++ != inSeqFirstElement) 867 break; 868 } 869 } 870 871 for (unsigned I = OutputDashCount; I < Indent; ++I) 872 output(" "); 873 874 for (unsigned I = 0; I < OutputDashCount; ++I) 875 output("- "); 876 } 877 878 void Output::paddedKey(StringRef key) { 879 output(key, needsQuotes(key, false)); 880 output(":"); 881 const char *spaces = " "; 882 if (key.size() < strlen(spaces)) 883 Padding = &spaces[key.size()]; 884 else 885 Padding = " "; 886 } 887 888 void Output::flowKey(StringRef Key) { 889 if (StateStack.back() == inFlowMapOtherKey) 890 output(", "); 891 if (WrapColumn && Column > WrapColumn) { 892 output("\n"); 893 for (int I = 0; I < ColumnAtMapFlowStart; ++I) 894 output(" "); 895 Column = ColumnAtMapFlowStart; 896 output(" "); 897 } 898 output(Key, needsQuotes(Key, false)); 899 output(": "); 900 } 901 902 NodeKind Output::getNodeKind() { report_fatal_error("invalid call"); } 903 904 bool Output::inSeqAnyElement(InState State) { 905 return State == inSeqFirstElement || State == inSeqOtherElement; 906 } 907 908 bool Output::inFlowSeqAnyElement(InState State) { 909 return State == inFlowSeqFirstElement || State == inFlowSeqOtherElement; 910 } 911 912 bool Output::inMapAnyKey(InState State) { 913 return State == inMapFirstKey || State == inMapOtherKey; 914 } 915 916 bool Output::inFlowMapAnyKey(InState State) { 917 return State == inFlowMapFirstKey || State == inFlowMapOtherKey; 918 } 919 920 //===----------------------------------------------------------------------===// 921 // traits for built-in types 922 //===----------------------------------------------------------------------===// 923 924 void ScalarTraits<bool>::output(const bool &Val, void *, raw_ostream &Out) { 925 Out << (Val ? "true" : "false"); 926 } 927 928 StringRef ScalarTraits<bool>::input(StringRef Scalar, void *, bool &Val) { 929 if (std::optional<bool> Parsed = parseBool(Scalar)) { 930 Val = *Parsed; 931 return StringRef(); 932 } 933 return "invalid boolean"; 934 } 935 936 void ScalarTraits<StringRef>::output(const StringRef &Val, void *, 937 raw_ostream &Out) { 938 Out << Val; 939 } 940 941 StringRef ScalarTraits<StringRef>::input(StringRef Scalar, void *, 942 StringRef &Val) { 943 Val = Scalar; 944 return StringRef(); 945 } 946 947 void ScalarTraits<std::string>::output(const std::string &Val, void *, 948 raw_ostream &Out) { 949 Out << Val; 950 } 951 952 StringRef ScalarTraits<std::string>::input(StringRef Scalar, void *, 953 std::string &Val) { 954 Val = Scalar.str(); 955 return StringRef(); 956 } 957 958 void ScalarTraits<uint8_t>::output(const uint8_t &Val, void *, 959 raw_ostream &Out) { 960 // use temp uin32_t because ostream thinks uint8_t is a character 961 uint32_t Num = Val; 962 Out << Num; 963 } 964 965 StringRef ScalarTraits<uint8_t>::input(StringRef Scalar, void *, uint8_t &Val) { 966 unsigned long long n; 967 if (getAsUnsignedInteger(Scalar, 0, n)) 968 return "invalid number"; 969 if (n > 0xFF) 970 return "out of range number"; 971 Val = n; 972 return StringRef(); 973 } 974 975 void ScalarTraits<uint16_t>::output(const uint16_t &Val, void *, 976 raw_ostream &Out) { 977 Out << Val; 978 } 979 980 StringRef ScalarTraits<uint16_t>::input(StringRef Scalar, void *, 981 uint16_t &Val) { 982 unsigned long long n; 983 if (getAsUnsignedInteger(Scalar, 0, n)) 984 return "invalid number"; 985 if (n > 0xFFFF) 986 return "out of range number"; 987 Val = n; 988 return StringRef(); 989 } 990 991 void ScalarTraits<uint32_t>::output(const uint32_t &Val, void *, 992 raw_ostream &Out) { 993 Out << Val; 994 } 995 996 StringRef ScalarTraits<uint32_t>::input(StringRef Scalar, void *, 997 uint32_t &Val) { 998 unsigned long long n; 999 if (getAsUnsignedInteger(Scalar, 0, n)) 1000 return "invalid number"; 1001 if (n > 0xFFFFFFFFUL) 1002 return "out of range number"; 1003 Val = n; 1004 return StringRef(); 1005 } 1006 1007 void ScalarTraits<uint64_t>::output(const uint64_t &Val, void *, 1008 raw_ostream &Out) { 1009 Out << Val; 1010 } 1011 1012 StringRef ScalarTraits<uint64_t>::input(StringRef Scalar, void *, 1013 uint64_t &Val) { 1014 unsigned long long N; 1015 if (getAsUnsignedInteger(Scalar, 0, N)) 1016 return "invalid number"; 1017 Val = N; 1018 return StringRef(); 1019 } 1020 1021 void ScalarTraits<int8_t>::output(const int8_t &Val, void *, raw_ostream &Out) { 1022 // use temp in32_t because ostream thinks int8_t is a character 1023 int32_t Num = Val; 1024 Out << Num; 1025 } 1026 1027 StringRef ScalarTraits<int8_t>::input(StringRef Scalar, void *, int8_t &Val) { 1028 long long N; 1029 if (getAsSignedInteger(Scalar, 0, N)) 1030 return "invalid number"; 1031 if ((N > 127) || (N < -128)) 1032 return "out of range number"; 1033 Val = N; 1034 return StringRef(); 1035 } 1036 1037 void ScalarTraits<int16_t>::output(const int16_t &Val, void *, 1038 raw_ostream &Out) { 1039 Out << Val; 1040 } 1041 1042 StringRef ScalarTraits<int16_t>::input(StringRef Scalar, void *, int16_t &Val) { 1043 long long N; 1044 if (getAsSignedInteger(Scalar, 0, N)) 1045 return "invalid number"; 1046 if ((N > INT16_MAX) || (N < INT16_MIN)) 1047 return "out of range number"; 1048 Val = N; 1049 return StringRef(); 1050 } 1051 1052 void ScalarTraits<int32_t>::output(const int32_t &Val, void *, 1053 raw_ostream &Out) { 1054 Out << Val; 1055 } 1056 1057 StringRef ScalarTraits<int32_t>::input(StringRef Scalar, void *, int32_t &Val) { 1058 long long N; 1059 if (getAsSignedInteger(Scalar, 0, N)) 1060 return "invalid number"; 1061 if ((N > INT32_MAX) || (N < INT32_MIN)) 1062 return "out of range number"; 1063 Val = N; 1064 return StringRef(); 1065 } 1066 1067 void ScalarTraits<int64_t>::output(const int64_t &Val, void *, 1068 raw_ostream &Out) { 1069 Out << Val; 1070 } 1071 1072 StringRef ScalarTraits<int64_t>::input(StringRef Scalar, void *, int64_t &Val) { 1073 long long N; 1074 if (getAsSignedInteger(Scalar, 0, N)) 1075 return "invalid number"; 1076 Val = N; 1077 return StringRef(); 1078 } 1079 1080 void ScalarTraits<double>::output(const double &Val, void *, raw_ostream &Out) { 1081 Out << format("%g", Val); 1082 } 1083 1084 StringRef ScalarTraits<double>::input(StringRef Scalar, void *, double &Val) { 1085 if (to_float(Scalar, Val)) 1086 return StringRef(); 1087 return "invalid floating point number"; 1088 } 1089 1090 void ScalarTraits<float>::output(const float &Val, void *, raw_ostream &Out) { 1091 Out << format("%g", Val); 1092 } 1093 1094 StringRef ScalarTraits<float>::input(StringRef Scalar, void *, float &Val) { 1095 if (to_float(Scalar, Val)) 1096 return StringRef(); 1097 return "invalid floating point number"; 1098 } 1099 1100 void ScalarTraits<Hex8>::output(const Hex8 &Val, void *, raw_ostream &Out) { 1101 Out << format("0x%" PRIX8, (uint8_t)Val); 1102 } 1103 1104 StringRef ScalarTraits<Hex8>::input(StringRef Scalar, void *, Hex8 &Val) { 1105 unsigned long long n; 1106 if (getAsUnsignedInteger(Scalar, 0, n)) 1107 return "invalid hex8 number"; 1108 if (n > 0xFF) 1109 return "out of range hex8 number"; 1110 Val = n; 1111 return StringRef(); 1112 } 1113 1114 void ScalarTraits<Hex16>::output(const Hex16 &Val, void *, raw_ostream &Out) { 1115 Out << format("0x%" PRIX16, (uint16_t)Val); 1116 } 1117 1118 StringRef ScalarTraits<Hex16>::input(StringRef Scalar, void *, Hex16 &Val) { 1119 unsigned long long n; 1120 if (getAsUnsignedInteger(Scalar, 0, n)) 1121 return "invalid hex16 number"; 1122 if (n > 0xFFFF) 1123 return "out of range hex16 number"; 1124 Val = n; 1125 return StringRef(); 1126 } 1127 1128 void ScalarTraits<Hex32>::output(const Hex32 &Val, void *, raw_ostream &Out) { 1129 Out << format("0x%" PRIX32, (uint32_t)Val); 1130 } 1131 1132 StringRef ScalarTraits<Hex32>::input(StringRef Scalar, void *, Hex32 &Val) { 1133 unsigned long long n; 1134 if (getAsUnsignedInteger(Scalar, 0, n)) 1135 return "invalid hex32 number"; 1136 if (n > 0xFFFFFFFFUL) 1137 return "out of range hex32 number"; 1138 Val = n; 1139 return StringRef(); 1140 } 1141 1142 void ScalarTraits<Hex64>::output(const Hex64 &Val, void *, raw_ostream &Out) { 1143 Out << format("0x%" PRIX64, (uint64_t)Val); 1144 } 1145 1146 StringRef ScalarTraits<Hex64>::input(StringRef Scalar, void *, Hex64 &Val) { 1147 unsigned long long Num; 1148 if (getAsUnsignedInteger(Scalar, 0, Num)) 1149 return "invalid hex64 number"; 1150 Val = Num; 1151 return StringRef(); 1152 } 1153 1154 void ScalarTraits<VersionTuple>::output(const VersionTuple &Val, void *, 1155 llvm::raw_ostream &Out) { 1156 Out << Val.getAsString(); 1157 } 1158 1159 StringRef ScalarTraits<VersionTuple>::input(StringRef Scalar, void *, 1160 VersionTuple &Val) { 1161 if (Val.tryParse(Scalar)) 1162 return "invalid version format"; 1163 return StringRef(); 1164 } 1165