1249259Sdim//===- lib/Support/YAMLTraits.cpp -----------------------------------------===// 2249259Sdim// 3249259Sdim// The LLVM Linker 4249259Sdim// 5249259Sdim// This file is distributed under the University of Illinois Open Source 6249259Sdim// License. See LICENSE.TXT for details. 7249259Sdim// 8249259Sdim//===----------------------------------------------------------------------===// 9249259Sdim 10249259Sdim#include "llvm/Support/YAMLTraits.h" 11249259Sdim#include "llvm/ADT/Twine.h" 12249259Sdim#include "llvm/Support/Casting.h" 13249259Sdim#include "llvm/Support/ErrorHandling.h" 14249259Sdim#include "llvm/Support/Format.h" 15249259Sdim#include "llvm/Support/YAMLParser.h" 16249259Sdim#include "llvm/Support/raw_ostream.h" 17249259Sdim#include <cstring> 18263508Sdim#include <cctype> 19249259Sdimusing namespace llvm; 20249259Sdimusing namespace yaml; 21249259Sdim 22249259Sdim//===----------------------------------------------------------------------===// 23249259Sdim// IO 24249259Sdim//===----------------------------------------------------------------------===// 25249259Sdim 26249259SdimIO::IO(void *Context) : Ctxt(Context) { 27249259Sdim} 28249259Sdim 29249259SdimIO::~IO() { 30249259Sdim} 31249259Sdim 32249259Sdimvoid *IO::getContext() { 33249259Sdim return Ctxt; 34249259Sdim} 35249259Sdim 36249259Sdimvoid IO::setContext(void *Context) { 37249259Sdim Ctxt = Context; 38249259Sdim} 39249259Sdim 40249259Sdim//===----------------------------------------------------------------------===// 41249259Sdim// Input 42249259Sdim//===----------------------------------------------------------------------===// 43249259Sdim 44263508SdimInput::Input(StringRef InputContent, 45263508Sdim void *Ctxt, 46263508Sdim SourceMgr::DiagHandlerTy DiagHandler, 47263508Sdim void *DiagHandlerCtxt) 48263508Sdim : IO(Ctxt), 49249259Sdim Strm(new Stream(InputContent, SrcMgr)), 50249259Sdim CurrentNode(NULL) { 51263508Sdim if (DiagHandler) 52263508Sdim SrcMgr.setDiagHandler(DiagHandler, DiagHandlerCtxt); 53249259Sdim DocIterator = Strm->begin(); 54249259Sdim} 55249259Sdim 56249259SdimInput::~Input() { 57249259Sdim} 58249259Sdim 59249259Sdimerror_code Input::error() { 60249259Sdim return EC; 61249259Sdim} 62249259Sdim 63263508Sdim// Pin the vtables to this file. 64263508Sdimvoid Input::HNode::anchor() {} 65263508Sdimvoid Input::EmptyHNode::anchor() {} 66263508Sdimvoid Input::ScalarHNode::anchor() {} 67249259Sdim 68263508Sdimbool Input::outputting() const { 69249259Sdim return false; 70249259Sdim} 71249259Sdim 72249259Sdimbool Input::setCurrentDocument() { 73249259Sdim if (DocIterator != Strm->end()) { 74249259Sdim Node *N = DocIterator->getRoot(); 75263508Sdim if (!N) { 76263508Sdim assert(Strm->failed() && "Root is NULL iff parsing failed"); 77263508Sdim EC = make_error_code(errc::invalid_argument); 78263508Sdim return false; 79263508Sdim } 80263508Sdim 81249259Sdim if (isa<NullNode>(N)) { 82249259Sdim // Empty files are allowed and ignored 83249259Sdim ++DocIterator; 84249259Sdim return setCurrentDocument(); 85249259Sdim } 86249259Sdim TopNode.reset(this->createHNodes(N)); 87249259Sdim CurrentNode = TopNode.get(); 88249259Sdim return true; 89249259Sdim } 90249259Sdim return false; 91249259Sdim} 92249259Sdim 93249259Sdimvoid Input::nextDocument() { 94249259Sdim ++DocIterator; 95249259Sdim} 96249259Sdim 97263508Sdimbool Input::mapTag(StringRef Tag, bool Default) { 98263508Sdim std::string foundTag = CurrentNode->_node->getVerbatimTag(); 99263508Sdim if (foundTag.empty()) { 100263508Sdim // If no tag found and 'Tag' is the default, say it was found. 101263508Sdim return Default; 102263508Sdim } 103263508Sdim // Return true iff found tag matches supplied tag. 104263508Sdim return Tag.equals(foundTag); 105263508Sdim} 106263508Sdim 107249259Sdimvoid Input::beginMapping() { 108249259Sdim if (EC) 109249259Sdim return; 110263508Sdim // CurrentNode can be null if the document is empty. 111263508Sdim MapHNode *MN = dyn_cast_or_null<MapHNode>(CurrentNode); 112249259Sdim if (MN) { 113249259Sdim MN->ValidKeys.clear(); 114249259Sdim } 115249259Sdim} 116249259Sdim 117249259Sdimbool Input::preflightKey(const char *Key, bool Required, bool, bool &UseDefault, 118249259Sdim void *&SaveInfo) { 119249259Sdim UseDefault = false; 120249259Sdim if (EC) 121249259Sdim return false; 122263508Sdim 123263508Sdim // CurrentNode is null for empty documents, which is an error in case required 124263508Sdim // nodes are present. 125263508Sdim if (!CurrentNode) { 126263508Sdim if (Required) 127263508Sdim EC = make_error_code(errc::invalid_argument); 128263508Sdim return false; 129263508Sdim } 130263508Sdim 131249259Sdim MapHNode *MN = dyn_cast<MapHNode>(CurrentNode); 132249259Sdim if (!MN) { 133249259Sdim setError(CurrentNode, "not a mapping"); 134249259Sdim return false; 135249259Sdim } 136249259Sdim MN->ValidKeys.push_back(Key); 137249259Sdim HNode *Value = MN->Mapping[Key]; 138249259Sdim if (!Value) { 139249259Sdim if (Required) 140249259Sdim setError(CurrentNode, Twine("missing required key '") + Key + "'"); 141249259Sdim else 142249259Sdim UseDefault = true; 143249259Sdim return false; 144249259Sdim } 145249259Sdim SaveInfo = CurrentNode; 146249259Sdim CurrentNode = Value; 147249259Sdim return true; 148249259Sdim} 149249259Sdim 150249259Sdimvoid Input::postflightKey(void *saveInfo) { 151249259Sdim CurrentNode = reinterpret_cast<HNode *>(saveInfo); 152249259Sdim} 153249259Sdim 154249259Sdimvoid Input::endMapping() { 155249259Sdim if (EC) 156249259Sdim return; 157263508Sdim // CurrentNode can be null if the document is empty. 158263508Sdim MapHNode *MN = dyn_cast_or_null<MapHNode>(CurrentNode); 159249259Sdim if (!MN) 160249259Sdim return; 161249259Sdim for (MapHNode::NameToNode::iterator i = MN->Mapping.begin(), 162249259Sdim End = MN->Mapping.end(); i != End; ++i) { 163263508Sdim if (!MN->isValidKey(i->first())) { 164263508Sdim setError(i->second, Twine("unknown key '") + i->first() + "'"); 165249259Sdim break; 166249259Sdim } 167249259Sdim } 168249259Sdim} 169249259Sdim 170249259Sdimunsigned Input::beginSequence() { 171249259Sdim if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) { 172249259Sdim return SQ->Entries.size(); 173249259Sdim } 174249259Sdim return 0; 175249259Sdim} 176249259Sdim 177249259Sdimvoid Input::endSequence() { 178249259Sdim} 179249259Sdim 180249259Sdimbool Input::preflightElement(unsigned Index, void *&SaveInfo) { 181249259Sdim if (EC) 182249259Sdim return false; 183249259Sdim if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) { 184249259Sdim SaveInfo = CurrentNode; 185249259Sdim CurrentNode = SQ->Entries[Index]; 186249259Sdim return true; 187249259Sdim } 188249259Sdim return false; 189249259Sdim} 190249259Sdim 191249259Sdimvoid Input::postflightElement(void *SaveInfo) { 192249259Sdim CurrentNode = reinterpret_cast<HNode *>(SaveInfo); 193249259Sdim} 194249259Sdim 195249259Sdimunsigned Input::beginFlowSequence() { 196249259Sdim if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) { 197249259Sdim return SQ->Entries.size(); 198249259Sdim } 199249259Sdim return 0; 200249259Sdim} 201249259Sdim 202249259Sdimbool Input::preflightFlowElement(unsigned index, void *&SaveInfo) { 203249259Sdim if (EC) 204249259Sdim return false; 205249259Sdim if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) { 206249259Sdim SaveInfo = CurrentNode; 207249259Sdim CurrentNode = SQ->Entries[index]; 208249259Sdim return true; 209249259Sdim } 210249259Sdim return false; 211249259Sdim} 212249259Sdim 213249259Sdimvoid Input::postflightFlowElement(void *SaveInfo) { 214249259Sdim CurrentNode = reinterpret_cast<HNode *>(SaveInfo); 215249259Sdim} 216249259Sdim 217249259Sdimvoid Input::endFlowSequence() { 218249259Sdim} 219249259Sdim 220249259Sdimvoid Input::beginEnumScalar() { 221249259Sdim ScalarMatchFound = false; 222249259Sdim} 223249259Sdim 224249259Sdimbool Input::matchEnumScalar(const char *Str, bool) { 225249259Sdim if (ScalarMatchFound) 226249259Sdim return false; 227249259Sdim if (ScalarHNode *SN = dyn_cast<ScalarHNode>(CurrentNode)) { 228249259Sdim if (SN->value().equals(Str)) { 229249259Sdim ScalarMatchFound = true; 230249259Sdim return true; 231249259Sdim } 232249259Sdim } 233249259Sdim return false; 234249259Sdim} 235249259Sdim 236249259Sdimvoid Input::endEnumScalar() { 237249259Sdim if (!ScalarMatchFound) { 238249259Sdim setError(CurrentNode, "unknown enumerated scalar"); 239249259Sdim } 240249259Sdim} 241249259Sdim 242249259Sdimbool Input::beginBitSetScalar(bool &DoClear) { 243249259Sdim BitValuesUsed.clear(); 244249259Sdim if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) { 245249259Sdim BitValuesUsed.insert(BitValuesUsed.begin(), SQ->Entries.size(), false); 246249259Sdim } else { 247249259Sdim setError(CurrentNode, "expected sequence of bit values"); 248249259Sdim } 249249259Sdim DoClear = true; 250249259Sdim return true; 251249259Sdim} 252249259Sdim 253249259Sdimbool Input::bitSetMatch(const char *Str, bool) { 254249259Sdim if (EC) 255249259Sdim return false; 256249259Sdim if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) { 257249259Sdim unsigned Index = 0; 258249259Sdim for (std::vector<HNode *>::iterator i = SQ->Entries.begin(), 259249259Sdim End = SQ->Entries.end(); i != End; ++i) { 260249259Sdim if (ScalarHNode *SN = dyn_cast<ScalarHNode>(*i)) { 261249259Sdim if (SN->value().equals(Str)) { 262249259Sdim BitValuesUsed[Index] = true; 263249259Sdim return true; 264249259Sdim } 265249259Sdim } else { 266249259Sdim setError(CurrentNode, "unexpected scalar in sequence of bit values"); 267249259Sdim } 268249259Sdim ++Index; 269249259Sdim } 270249259Sdim } else { 271249259Sdim setError(CurrentNode, "expected sequence of bit values"); 272249259Sdim } 273249259Sdim return false; 274249259Sdim} 275249259Sdim 276249259Sdimvoid Input::endBitSetScalar() { 277249259Sdim if (EC) 278249259Sdim return; 279249259Sdim if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) { 280249259Sdim assert(BitValuesUsed.size() == SQ->Entries.size()); 281249259Sdim for (unsigned i = 0; i < SQ->Entries.size(); ++i) { 282249259Sdim if (!BitValuesUsed[i]) { 283249259Sdim setError(SQ->Entries[i], "unknown bit value"); 284249259Sdim return; 285249259Sdim } 286249259Sdim } 287249259Sdim } 288249259Sdim} 289249259Sdim 290249259Sdimvoid Input::scalarString(StringRef &S) { 291249259Sdim if (ScalarHNode *SN = dyn_cast<ScalarHNode>(CurrentNode)) { 292249259Sdim S = SN->value(); 293249259Sdim } else { 294249259Sdim setError(CurrentNode, "unexpected scalar"); 295249259Sdim } 296249259Sdim} 297249259Sdim 298249259Sdimvoid Input::setError(HNode *hnode, const Twine &message) { 299263508Sdim assert(hnode && "HNode must not be NULL"); 300249259Sdim this->setError(hnode->_node, message); 301249259Sdim} 302249259Sdim 303249259Sdimvoid Input::setError(Node *node, const Twine &message) { 304249259Sdim Strm->printError(node, message); 305249259Sdim EC = make_error_code(errc::invalid_argument); 306249259Sdim} 307249259Sdim 308249259SdimInput::HNode *Input::createHNodes(Node *N) { 309249259Sdim SmallString<128> StringStorage; 310249259Sdim if (ScalarNode *SN = dyn_cast<ScalarNode>(N)) { 311249259Sdim StringRef KeyStr = SN->getValue(StringStorage); 312249259Sdim if (!StringStorage.empty()) { 313249259Sdim // Copy string to permanent storage 314249259Sdim unsigned Len = StringStorage.size(); 315249259Sdim char *Buf = StringAllocator.Allocate<char>(Len); 316249259Sdim memcpy(Buf, &StringStorage[0], Len); 317249259Sdim KeyStr = StringRef(Buf, Len); 318249259Sdim } 319249259Sdim return new ScalarHNode(N, KeyStr); 320249259Sdim } else if (SequenceNode *SQ = dyn_cast<SequenceNode>(N)) { 321249259Sdim SequenceHNode *SQHNode = new SequenceHNode(N); 322249259Sdim for (SequenceNode::iterator i = SQ->begin(), End = SQ->end(); i != End; 323249259Sdim ++i) { 324249259Sdim HNode *Entry = this->createHNodes(i); 325249259Sdim if (EC) 326249259Sdim break; 327249259Sdim SQHNode->Entries.push_back(Entry); 328249259Sdim } 329249259Sdim return SQHNode; 330249259Sdim } else if (MappingNode *Map = dyn_cast<MappingNode>(N)) { 331249259Sdim MapHNode *mapHNode = new MapHNode(N); 332249259Sdim for (MappingNode::iterator i = Map->begin(), End = Map->end(); i != End; 333249259Sdim ++i) { 334249259Sdim ScalarNode *KeyScalar = dyn_cast<ScalarNode>(i->getKey()); 335249259Sdim StringStorage.clear(); 336249259Sdim StringRef KeyStr = KeyScalar->getValue(StringStorage); 337249259Sdim if (!StringStorage.empty()) { 338249259Sdim // Copy string to permanent storage 339249259Sdim unsigned Len = StringStorage.size(); 340249259Sdim char *Buf = StringAllocator.Allocate<char>(Len); 341249259Sdim memcpy(Buf, &StringStorage[0], Len); 342249259Sdim KeyStr = StringRef(Buf, Len); 343249259Sdim } 344249259Sdim HNode *ValueHNode = this->createHNodes(i->getValue()); 345249259Sdim if (EC) 346249259Sdim break; 347249259Sdim mapHNode->Mapping[KeyStr] = ValueHNode; 348249259Sdim } 349249259Sdim return mapHNode; 350249259Sdim } else if (isa<NullNode>(N)) { 351249259Sdim return new EmptyHNode(N); 352249259Sdim } else { 353249259Sdim setError(N, "unknown node kind"); 354249259Sdim return NULL; 355249259Sdim } 356249259Sdim} 357249259Sdim 358249259Sdimbool Input::MapHNode::isValidKey(StringRef Key) { 359263508Sdim for (SmallVectorImpl<const char *>::iterator i = ValidKeys.begin(), 360249259Sdim End = ValidKeys.end(); i != End; ++i) { 361249259Sdim if (Key.equals(*i)) 362249259Sdim return true; 363249259Sdim } 364249259Sdim return false; 365249259Sdim} 366249259Sdim 367249259Sdimvoid Input::setError(const Twine &Message) { 368249259Sdim this->setError(CurrentNode, Message); 369249259Sdim} 370249259Sdim 371263508Sdimbool Input::canElideEmptySequence() { 372263508Sdim return false; 373263508Sdim} 374263508Sdim 375249259SdimInput::MapHNode::~MapHNode() { 376249259Sdim for (MapHNode::NameToNode::iterator i = Mapping.begin(), End = Mapping.end(); 377249259Sdim i != End; ++i) { 378249259Sdim delete i->second; 379249259Sdim } 380249259Sdim} 381249259Sdim 382249259SdimInput::SequenceHNode::~SequenceHNode() { 383249259Sdim for (std::vector<HNode*>::iterator i = Entries.begin(), End = Entries.end(); 384249259Sdim i != End; ++i) { 385249259Sdim delete *i; 386249259Sdim } 387249259Sdim} 388249259Sdim 389249259Sdim 390249259Sdim 391249259Sdim//===----------------------------------------------------------------------===// 392249259Sdim// Output 393249259Sdim//===----------------------------------------------------------------------===// 394249259Sdim 395249259SdimOutput::Output(raw_ostream &yout, void *context) 396249259Sdim : IO(context), 397249259Sdim Out(yout), 398249259Sdim Column(0), 399249259Sdim ColumnAtFlowStart(0), 400249259Sdim NeedBitValueComma(false), 401249259Sdim NeedFlowSequenceComma(false), 402249259Sdim EnumerationMatchFound(false), 403249259Sdim NeedsNewLine(false) { 404249259Sdim} 405249259Sdim 406249259SdimOutput::~Output() { 407249259Sdim} 408249259Sdim 409263508Sdimbool Output::outputting() const { 410249259Sdim return true; 411249259Sdim} 412249259Sdim 413249259Sdimvoid Output::beginMapping() { 414249259Sdim StateStack.push_back(inMapFirstKey); 415249259Sdim NeedsNewLine = true; 416249259Sdim} 417249259Sdim 418263508Sdimbool Output::mapTag(StringRef Tag, bool Use) { 419263508Sdim if (Use) { 420263508Sdim this->output(" "); 421263508Sdim this->output(Tag); 422263508Sdim } 423263508Sdim return Use; 424263508Sdim} 425263508Sdim 426249259Sdimvoid Output::endMapping() { 427249259Sdim StateStack.pop_back(); 428249259Sdim} 429249259Sdim 430249259Sdimbool Output::preflightKey(const char *Key, bool Required, bool SameAsDefault, 431249259Sdim bool &UseDefault, void *&) { 432249259Sdim UseDefault = false; 433249259Sdim if (Required || !SameAsDefault) { 434249259Sdim this->newLineCheck(); 435249259Sdim this->paddedKey(Key); 436249259Sdim return true; 437249259Sdim } 438249259Sdim return false; 439249259Sdim} 440249259Sdim 441249259Sdimvoid Output::postflightKey(void *) { 442249259Sdim if (StateStack.back() == inMapFirstKey) { 443249259Sdim StateStack.pop_back(); 444249259Sdim StateStack.push_back(inMapOtherKey); 445249259Sdim } 446249259Sdim} 447249259Sdim 448249259Sdimvoid Output::beginDocuments() { 449249259Sdim this->outputUpToEndOfLine("---"); 450249259Sdim} 451249259Sdim 452249259Sdimbool Output::preflightDocument(unsigned index) { 453249259Sdim if (index > 0) 454249259Sdim this->outputUpToEndOfLine("\n---"); 455249259Sdim return true; 456249259Sdim} 457249259Sdim 458249259Sdimvoid Output::postflightDocument() { 459249259Sdim} 460249259Sdim 461249259Sdimvoid Output::endDocuments() { 462249259Sdim output("\n...\n"); 463249259Sdim} 464249259Sdim 465249259Sdimunsigned Output::beginSequence() { 466249259Sdim StateStack.push_back(inSeq); 467249259Sdim NeedsNewLine = true; 468249259Sdim return 0; 469249259Sdim} 470249259Sdim 471249259Sdimvoid Output::endSequence() { 472249259Sdim StateStack.pop_back(); 473249259Sdim} 474249259Sdim 475249259Sdimbool Output::preflightElement(unsigned, void *&) { 476249259Sdim return true; 477249259Sdim} 478249259Sdim 479249259Sdimvoid Output::postflightElement(void *) { 480249259Sdim} 481249259Sdim 482249259Sdimunsigned Output::beginFlowSequence() { 483249259Sdim StateStack.push_back(inFlowSeq); 484249259Sdim this->newLineCheck(); 485249259Sdim ColumnAtFlowStart = Column; 486249259Sdim output("[ "); 487249259Sdim NeedFlowSequenceComma = false; 488249259Sdim return 0; 489249259Sdim} 490249259Sdim 491249259Sdimvoid Output::endFlowSequence() { 492249259Sdim StateStack.pop_back(); 493249259Sdim this->outputUpToEndOfLine(" ]"); 494249259Sdim} 495249259Sdim 496249259Sdimbool Output::preflightFlowElement(unsigned, void *&) { 497249259Sdim if (NeedFlowSequenceComma) 498249259Sdim output(", "); 499249259Sdim if (Column > 70) { 500249259Sdim output("\n"); 501249259Sdim for (int i = 0; i < ColumnAtFlowStart; ++i) 502249259Sdim output(" "); 503249259Sdim Column = ColumnAtFlowStart; 504249259Sdim output(" "); 505249259Sdim } 506249259Sdim return true; 507249259Sdim} 508249259Sdim 509249259Sdimvoid Output::postflightFlowElement(void *) { 510249259Sdim NeedFlowSequenceComma = true; 511249259Sdim} 512249259Sdim 513249259Sdimvoid Output::beginEnumScalar() { 514249259Sdim EnumerationMatchFound = false; 515249259Sdim} 516249259Sdim 517249259Sdimbool Output::matchEnumScalar(const char *Str, bool Match) { 518249259Sdim if (Match && !EnumerationMatchFound) { 519249259Sdim this->newLineCheck(); 520249259Sdim this->outputUpToEndOfLine(Str); 521249259Sdim EnumerationMatchFound = true; 522249259Sdim } 523249259Sdim return false; 524249259Sdim} 525249259Sdim 526249259Sdimvoid Output::endEnumScalar() { 527249259Sdim if (!EnumerationMatchFound) 528249259Sdim llvm_unreachable("bad runtime enum value"); 529249259Sdim} 530249259Sdim 531249259Sdimbool Output::beginBitSetScalar(bool &DoClear) { 532249259Sdim this->newLineCheck(); 533249259Sdim output("[ "); 534249259Sdim NeedBitValueComma = false; 535249259Sdim DoClear = false; 536249259Sdim return true; 537249259Sdim} 538249259Sdim 539249259Sdimbool Output::bitSetMatch(const char *Str, bool Matches) { 540249259Sdim if (Matches) { 541249259Sdim if (NeedBitValueComma) 542249259Sdim output(", "); 543249259Sdim this->output(Str); 544249259Sdim NeedBitValueComma = true; 545249259Sdim } 546249259Sdim return false; 547249259Sdim} 548249259Sdim 549249259Sdimvoid Output::endBitSetScalar() { 550249259Sdim this->outputUpToEndOfLine(" ]"); 551249259Sdim} 552249259Sdim 553249259Sdimvoid Output::scalarString(StringRef &S) { 554263508Sdim const char ScalarSafeChars[] = "abcdefghijklmnopqrstuvwxyz" 555263508Sdim "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-/^., \t"; 556263508Sdim 557249259Sdim this->newLineCheck(); 558263508Sdim if (S.empty()) { 559263508Sdim // Print '' for the empty string because leaving the field empty is not 560263508Sdim // allowed. 561263508Sdim this->outputUpToEndOfLine("''"); 562263508Sdim return; 563263508Sdim } 564263508Sdim if (S.find_first_not_of(ScalarSafeChars) == StringRef::npos && 565263508Sdim !isspace(S.front()) && !isspace(S.back())) { 566263508Sdim // If the string consists only of safe characters, print it out without 567263508Sdim // quotes. 568249259Sdim this->outputUpToEndOfLine(S); 569249259Sdim return; 570249259Sdim } 571249259Sdim unsigned i = 0; 572249259Sdim unsigned j = 0; 573249259Sdim unsigned End = S.size(); 574249259Sdim output("'"); // Starting single quote. 575249259Sdim const char *Base = S.data(); 576249259Sdim while (j < End) { 577249259Sdim // Escape a single quote by doubling it. 578249259Sdim if (S[j] == '\'') { 579249259Sdim output(StringRef(&Base[i], j - i + 1)); 580249259Sdim output("'"); 581249259Sdim i = j + 1; 582249259Sdim } 583249259Sdim ++j; 584249259Sdim } 585249259Sdim output(StringRef(&Base[i], j - i)); 586249259Sdim this->outputUpToEndOfLine("'"); // Ending single quote. 587249259Sdim} 588249259Sdim 589249259Sdimvoid Output::setError(const Twine &message) { 590249259Sdim} 591249259Sdim 592263508Sdimbool Output::canElideEmptySequence() { 593263508Sdim // Normally, with an optional key/value where the value is an empty sequence, 594263508Sdim // the whole key/value can be not written. But, that produces wrong yaml 595263508Sdim // if the key/value is the only thing in the map and the map is used in 596263508Sdim // a sequence. This detects if the this sequence is the first key/value 597263508Sdim // in map that itself is embedded in a sequnce. 598263508Sdim if (StateStack.size() < 2) 599263508Sdim return true; 600263508Sdim if (StateStack.back() != inMapFirstKey) 601263508Sdim return true; 602263508Sdim return (StateStack[StateStack.size()-2] != inSeq); 603263508Sdim} 604263508Sdim 605249259Sdimvoid Output::output(StringRef s) { 606249259Sdim Column += s.size(); 607249259Sdim Out << s; 608249259Sdim} 609249259Sdim 610249259Sdimvoid Output::outputUpToEndOfLine(StringRef s) { 611249259Sdim this->output(s); 612249259Sdim if (StateStack.empty() || StateStack.back() != inFlowSeq) 613249259Sdim NeedsNewLine = true; 614249259Sdim} 615249259Sdim 616249259Sdimvoid Output::outputNewLine() { 617249259Sdim Out << "\n"; 618249259Sdim Column = 0; 619249259Sdim} 620249259Sdim 621249259Sdim// if seq at top, indent as if map, then add "- " 622249259Sdim// if seq in middle, use "- " if firstKey, else use " " 623249259Sdim// 624249259Sdim 625249259Sdimvoid Output::newLineCheck() { 626249259Sdim if (!NeedsNewLine) 627249259Sdim return; 628249259Sdim NeedsNewLine = false; 629249259Sdim 630249259Sdim this->outputNewLine(); 631249259Sdim 632249259Sdim assert(StateStack.size() > 0); 633249259Sdim unsigned Indent = StateStack.size() - 1; 634249259Sdim bool OutputDash = false; 635249259Sdim 636249259Sdim if (StateStack.back() == inSeq) { 637249259Sdim OutputDash = true; 638249259Sdim } else if ((StateStack.size() > 1) && (StateStack.back() == inMapFirstKey) && 639249259Sdim (StateStack[StateStack.size() - 2] == inSeq)) { 640249259Sdim --Indent; 641249259Sdim OutputDash = true; 642249259Sdim } 643249259Sdim 644249259Sdim for (unsigned i = 0; i < Indent; ++i) { 645249259Sdim output(" "); 646249259Sdim } 647249259Sdim if (OutputDash) { 648249259Sdim output("- "); 649249259Sdim } 650249259Sdim 651249259Sdim} 652249259Sdim 653249259Sdimvoid Output::paddedKey(StringRef key) { 654249259Sdim output(key); 655249259Sdim output(":"); 656249259Sdim const char *spaces = " "; 657249259Sdim if (key.size() < strlen(spaces)) 658249259Sdim output(&spaces[key.size()]); 659249259Sdim else 660249259Sdim output(" "); 661249259Sdim} 662249259Sdim 663249259Sdim//===----------------------------------------------------------------------===// 664249259Sdim// traits for built-in types 665249259Sdim//===----------------------------------------------------------------------===// 666249259Sdim 667249259Sdimvoid ScalarTraits<bool>::output(const bool &Val, void *, raw_ostream &Out) { 668249259Sdim Out << (Val ? "true" : "false"); 669249259Sdim} 670249259Sdim 671249259SdimStringRef ScalarTraits<bool>::input(StringRef Scalar, void *, bool &Val) { 672249259Sdim if (Scalar.equals("true")) { 673249259Sdim Val = true; 674249259Sdim return StringRef(); 675249259Sdim } else if (Scalar.equals("false")) { 676249259Sdim Val = false; 677249259Sdim return StringRef(); 678249259Sdim } 679249259Sdim return "invalid boolean"; 680249259Sdim} 681249259Sdim 682249259Sdimvoid ScalarTraits<StringRef>::output(const StringRef &Val, void *, 683249259Sdim raw_ostream &Out) { 684249259Sdim Out << Val; 685249259Sdim} 686249259Sdim 687249259SdimStringRef ScalarTraits<StringRef>::input(StringRef Scalar, void *, 688249259Sdim StringRef &Val) { 689249259Sdim Val = Scalar; 690249259Sdim return StringRef(); 691249259Sdim} 692249259Sdim 693249259Sdimvoid ScalarTraits<uint8_t>::output(const uint8_t &Val, void *, 694249259Sdim raw_ostream &Out) { 695249259Sdim // use temp uin32_t because ostream thinks uint8_t is a character 696249259Sdim uint32_t Num = Val; 697249259Sdim Out << Num; 698249259Sdim} 699249259Sdim 700249259SdimStringRef ScalarTraits<uint8_t>::input(StringRef Scalar, void *, uint8_t &Val) { 701249259Sdim unsigned long long n; 702249259Sdim if (getAsUnsignedInteger(Scalar, 0, n)) 703249259Sdim return "invalid number"; 704249259Sdim if (n > 0xFF) 705249259Sdim return "out of range number"; 706249259Sdim Val = n; 707249259Sdim return StringRef(); 708249259Sdim} 709249259Sdim 710249259Sdimvoid ScalarTraits<uint16_t>::output(const uint16_t &Val, void *, 711249259Sdim raw_ostream &Out) { 712249259Sdim Out << Val; 713249259Sdim} 714249259Sdim 715249259SdimStringRef ScalarTraits<uint16_t>::input(StringRef Scalar, void *, 716249259Sdim uint16_t &Val) { 717249259Sdim unsigned long long n; 718249259Sdim if (getAsUnsignedInteger(Scalar, 0, n)) 719249259Sdim return "invalid number"; 720249259Sdim if (n > 0xFFFF) 721249259Sdim return "out of range number"; 722249259Sdim Val = n; 723249259Sdim return StringRef(); 724249259Sdim} 725249259Sdim 726249259Sdimvoid ScalarTraits<uint32_t>::output(const uint32_t &Val, void *, 727249259Sdim raw_ostream &Out) { 728249259Sdim Out << Val; 729249259Sdim} 730249259Sdim 731249259SdimStringRef ScalarTraits<uint32_t>::input(StringRef Scalar, void *, 732249259Sdim uint32_t &Val) { 733249259Sdim unsigned long long n; 734249259Sdim if (getAsUnsignedInteger(Scalar, 0, n)) 735249259Sdim return "invalid number"; 736249259Sdim if (n > 0xFFFFFFFFUL) 737249259Sdim return "out of range number"; 738249259Sdim Val = n; 739249259Sdim return StringRef(); 740249259Sdim} 741249259Sdim 742249259Sdimvoid ScalarTraits<uint64_t>::output(const uint64_t &Val, void *, 743249259Sdim raw_ostream &Out) { 744249259Sdim Out << Val; 745249259Sdim} 746249259Sdim 747249259SdimStringRef ScalarTraits<uint64_t>::input(StringRef Scalar, void *, 748249259Sdim uint64_t &Val) { 749249259Sdim unsigned long long N; 750249259Sdim if (getAsUnsignedInteger(Scalar, 0, N)) 751249259Sdim return "invalid number"; 752249259Sdim Val = N; 753249259Sdim return StringRef(); 754249259Sdim} 755249259Sdim 756249259Sdimvoid ScalarTraits<int8_t>::output(const int8_t &Val, void *, raw_ostream &Out) { 757249259Sdim // use temp in32_t because ostream thinks int8_t is a character 758249259Sdim int32_t Num = Val; 759249259Sdim Out << Num; 760249259Sdim} 761249259Sdim 762249259SdimStringRef ScalarTraits<int8_t>::input(StringRef Scalar, void *, int8_t &Val) { 763249259Sdim long long N; 764249259Sdim if (getAsSignedInteger(Scalar, 0, N)) 765249259Sdim return "invalid number"; 766249259Sdim if ((N > 127) || (N < -128)) 767249259Sdim return "out of range number"; 768249259Sdim Val = N; 769249259Sdim return StringRef(); 770249259Sdim} 771249259Sdim 772249259Sdimvoid ScalarTraits<int16_t>::output(const int16_t &Val, void *, 773249259Sdim raw_ostream &Out) { 774249259Sdim Out << Val; 775249259Sdim} 776249259Sdim 777249259SdimStringRef ScalarTraits<int16_t>::input(StringRef Scalar, void *, int16_t &Val) { 778249259Sdim long long N; 779249259Sdim if (getAsSignedInteger(Scalar, 0, N)) 780249259Sdim return "invalid number"; 781249259Sdim if ((N > INT16_MAX) || (N < INT16_MIN)) 782249259Sdim return "out of range number"; 783249259Sdim Val = N; 784249259Sdim return StringRef(); 785249259Sdim} 786249259Sdim 787249259Sdimvoid ScalarTraits<int32_t>::output(const int32_t &Val, void *, 788249259Sdim raw_ostream &Out) { 789249259Sdim Out << Val; 790249259Sdim} 791249259Sdim 792249259SdimStringRef ScalarTraits<int32_t>::input(StringRef Scalar, void *, int32_t &Val) { 793249259Sdim long long N; 794249259Sdim if (getAsSignedInteger(Scalar, 0, N)) 795249259Sdim return "invalid number"; 796249259Sdim if ((N > INT32_MAX) || (N < INT32_MIN)) 797249259Sdim return "out of range number"; 798249259Sdim Val = N; 799249259Sdim return StringRef(); 800249259Sdim} 801249259Sdim 802249259Sdimvoid ScalarTraits<int64_t>::output(const int64_t &Val, void *, 803249259Sdim raw_ostream &Out) { 804249259Sdim Out << Val; 805249259Sdim} 806249259Sdim 807249259SdimStringRef ScalarTraits<int64_t>::input(StringRef Scalar, void *, int64_t &Val) { 808249259Sdim long long N; 809249259Sdim if (getAsSignedInteger(Scalar, 0, N)) 810249259Sdim return "invalid number"; 811249259Sdim Val = N; 812249259Sdim return StringRef(); 813249259Sdim} 814249259Sdim 815249259Sdimvoid ScalarTraits<double>::output(const double &Val, void *, raw_ostream &Out) { 816249259Sdim Out << format("%g", Val); 817249259Sdim} 818249259Sdim 819249259SdimStringRef ScalarTraits<double>::input(StringRef Scalar, void *, double &Val) { 820249259Sdim SmallString<32> buff(Scalar.begin(), Scalar.end()); 821249259Sdim char *end; 822249259Sdim Val = strtod(buff.c_str(), &end); 823249259Sdim if (*end != '\0') 824249259Sdim return "invalid floating point number"; 825249259Sdim return StringRef(); 826249259Sdim} 827249259Sdim 828249259Sdimvoid ScalarTraits<float>::output(const float &Val, void *, raw_ostream &Out) { 829249259Sdim Out << format("%g", Val); 830249259Sdim} 831249259Sdim 832249259SdimStringRef ScalarTraits<float>::input(StringRef Scalar, void *, float &Val) { 833249259Sdim SmallString<32> buff(Scalar.begin(), Scalar.end()); 834249259Sdim char *end; 835249259Sdim Val = strtod(buff.c_str(), &end); 836249259Sdim if (*end != '\0') 837249259Sdim return "invalid floating point number"; 838249259Sdim return StringRef(); 839249259Sdim} 840249259Sdim 841249259Sdimvoid ScalarTraits<Hex8>::output(const Hex8 &Val, void *, raw_ostream &Out) { 842249259Sdim uint8_t Num = Val; 843249259Sdim Out << format("0x%02X", Num); 844249259Sdim} 845249259Sdim 846249259SdimStringRef ScalarTraits<Hex8>::input(StringRef Scalar, void *, Hex8 &Val) { 847249259Sdim unsigned long long n; 848249259Sdim if (getAsUnsignedInteger(Scalar, 0, n)) 849249259Sdim return "invalid hex8 number"; 850249259Sdim if (n > 0xFF) 851249259Sdim return "out of range hex8 number"; 852249259Sdim Val = n; 853249259Sdim return StringRef(); 854249259Sdim} 855249259Sdim 856249259Sdimvoid ScalarTraits<Hex16>::output(const Hex16 &Val, void *, raw_ostream &Out) { 857249259Sdim uint16_t Num = Val; 858249259Sdim Out << format("0x%04X", Num); 859249259Sdim} 860249259Sdim 861249259SdimStringRef ScalarTraits<Hex16>::input(StringRef Scalar, void *, Hex16 &Val) { 862249259Sdim unsigned long long n; 863249259Sdim if (getAsUnsignedInteger(Scalar, 0, n)) 864249259Sdim return "invalid hex16 number"; 865249259Sdim if (n > 0xFFFF) 866249259Sdim return "out of range hex16 number"; 867249259Sdim Val = n; 868249259Sdim return StringRef(); 869249259Sdim} 870249259Sdim 871249259Sdimvoid ScalarTraits<Hex32>::output(const Hex32 &Val, void *, raw_ostream &Out) { 872249259Sdim uint32_t Num = Val; 873249259Sdim Out << format("0x%08X", Num); 874249259Sdim} 875249259Sdim 876249259SdimStringRef ScalarTraits<Hex32>::input(StringRef Scalar, void *, Hex32 &Val) { 877249259Sdim unsigned long long n; 878249259Sdim if (getAsUnsignedInteger(Scalar, 0, n)) 879249259Sdim return "invalid hex32 number"; 880249259Sdim if (n > 0xFFFFFFFFUL) 881249259Sdim return "out of range hex32 number"; 882249259Sdim Val = n; 883249259Sdim return StringRef(); 884249259Sdim} 885249259Sdim 886249259Sdimvoid ScalarTraits<Hex64>::output(const Hex64 &Val, void *, raw_ostream &Out) { 887249259Sdim uint64_t Num = Val; 888249259Sdim Out << format("0x%016llX", Num); 889249259Sdim} 890249259Sdim 891249259SdimStringRef ScalarTraits<Hex64>::input(StringRef Scalar, void *, Hex64 &Val) { 892249259Sdim unsigned long long Num; 893249259Sdim if (getAsUnsignedInteger(Scalar, 0, Num)) 894249259Sdim return "invalid hex64 number"; 895249259Sdim Val = Num; 896249259Sdim return StringRef(); 897249259Sdim} 898