YAMLTraits.cpp revision 327952
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 10288943Sdim#include "llvm/Support/YAMLTraits.h" 11321369Sdim#include "llvm/ADT/STLExtras.h" 12288943Sdim#include "llvm/ADT/SmallString.h" 13321369Sdim#include "llvm/ADT/StringExtras.h" 14321369Sdim#include "llvm/ADT/StringRef.h" 15249259Sdim#include "llvm/ADT/Twine.h" 16249259Sdim#include "llvm/Support/Casting.h" 17288943Sdim#include "llvm/Support/Errc.h" 18249259Sdim#include "llvm/Support/ErrorHandling.h" 19249259Sdim#include "llvm/Support/Format.h" 20288943Sdim#include "llvm/Support/LineIterator.h" 21321369Sdim#include "llvm/Support/MemoryBuffer.h" 22327952Sdim#include "llvm/Support/Unicode.h" 23249259Sdim#include "llvm/Support/YAMLParser.h" 24249259Sdim#include "llvm/Support/raw_ostream.h" 25321369Sdim#include <algorithm> 26321369Sdim#include <cassert> 27321369Sdim#include <cstdint> 28321369Sdim#include <cstdlib> 29249259Sdim#include <cstring> 30321369Sdim#include <string> 31321369Sdim#include <vector> 32321369Sdim 33249259Sdimusing namespace llvm; 34249259Sdimusing namespace yaml; 35249259Sdim 36249259Sdim//===----------------------------------------------------------------------===// 37249259Sdim// IO 38249259Sdim//===----------------------------------------------------------------------===// 39249259Sdim 40321369SdimIO::IO(void *Context) : Ctxt(Context) {} 41249259Sdim 42321369SdimIO::~IO() = default; 43249259Sdim 44249259Sdimvoid *IO::getContext() { 45249259Sdim return Ctxt; 46249259Sdim} 47249259Sdim 48249259Sdimvoid IO::setContext(void *Context) { 49249259Sdim Ctxt = Context; 50249259Sdim} 51249259Sdim 52249259Sdim//===----------------------------------------------------------------------===// 53249259Sdim// Input 54249259Sdim//===----------------------------------------------------------------------===// 55249259Sdim 56314564SdimInput::Input(StringRef InputContent, void *Ctxt, 57314564Sdim SourceMgr::DiagHandlerTy DiagHandler, void *DiagHandlerCtxt) 58321369Sdim : IO(Ctxt), Strm(new Stream(InputContent, SrcMgr, false, &EC)) { 59261991Sdim if (DiagHandler) 60261991Sdim SrcMgr.setDiagHandler(DiagHandler, DiagHandlerCtxt); 61249259Sdim DocIterator = Strm->begin(); 62249259Sdim} 63249259Sdim 64321369SdimInput::Input(MemoryBufferRef Input, void *Ctxt, 65321369Sdim SourceMgr::DiagHandlerTy DiagHandler, void *DiagHandlerCtxt) 66321369Sdim : IO(Ctxt), Strm(new Stream(Input, SrcMgr, false, &EC)) { 67321369Sdim if (DiagHandler) 68321369Sdim SrcMgr.setDiagHandler(DiagHandler, DiagHandlerCtxt); 69321369Sdim DocIterator = Strm->begin(); 70249259Sdim} 71249259Sdim 72321369SdimInput::~Input() = default; 73321369Sdim 74276479Sdimstd::error_code Input::error() { return EC; } 75249259Sdim 76261991Sdim// Pin the vtables to this file. 77261991Sdimvoid Input::HNode::anchor() {} 78261991Sdimvoid Input::EmptyHNode::anchor() {} 79261991Sdimvoid Input::ScalarHNode::anchor() {} 80280031Sdimvoid Input::MapHNode::anchor() {} 81280031Sdimvoid Input::SequenceHNode::anchor() {} 82249259Sdim 83276479Sdimbool Input::outputting() { 84249259Sdim return false; 85249259Sdim} 86249259Sdim 87249259Sdimbool Input::setCurrentDocument() { 88249259Sdim if (DocIterator != Strm->end()) { 89249259Sdim Node *N = DocIterator->getRoot(); 90261991Sdim if (!N) { 91261991Sdim assert(Strm->failed() && "Root is NULL iff parsing failed"); 92261991Sdim EC = make_error_code(errc::invalid_argument); 93261991Sdim return false; 94261991Sdim } 95261991Sdim 96249259Sdim if (isa<NullNode>(N)) { 97249259Sdim // Empty files are allowed and ignored 98249259Sdim ++DocIterator; 99249259Sdim return setCurrentDocument(); 100249259Sdim } 101280031Sdim TopNode = this->createHNodes(N); 102249259Sdim CurrentNode = TopNode.get(); 103249259Sdim return true; 104249259Sdim } 105249259Sdim return false; 106249259Sdim} 107249259Sdim 108276479Sdimbool Input::nextDocument() { 109276479Sdim return ++DocIterator != Strm->end(); 110249259Sdim} 111249259Sdim 112288943Sdimconst Node *Input::getCurrentNode() const { 113288943Sdim return CurrentNode ? CurrentNode->_node : nullptr; 114288943Sdim} 115288943Sdim 116261991Sdimbool Input::mapTag(StringRef Tag, bool Default) { 117261991Sdim std::string foundTag = CurrentNode->_node->getVerbatimTag(); 118261991Sdim if (foundTag.empty()) { 119261991Sdim // If no tag found and 'Tag' is the default, say it was found. 120261991Sdim return Default; 121261991Sdim } 122261991Sdim // Return true iff found tag matches supplied tag. 123261991Sdim return Tag.equals(foundTag); 124261991Sdim} 125261991Sdim 126249259Sdimvoid Input::beginMapping() { 127249259Sdim if (EC) 128249259Sdim return; 129261991Sdim // CurrentNode can be null if the document is empty. 130261991Sdim MapHNode *MN = dyn_cast_or_null<MapHNode>(CurrentNode); 131249259Sdim if (MN) { 132249259Sdim MN->ValidKeys.clear(); 133249259Sdim } 134249259Sdim} 135249259Sdim 136314564Sdimstd::vector<StringRef> Input::keys() { 137314564Sdim MapHNode *MN = dyn_cast<MapHNode>(CurrentNode); 138314564Sdim std::vector<StringRef> Ret; 139314564Sdim if (!MN) { 140314564Sdim setError(CurrentNode, "not a mapping"); 141314564Sdim return Ret; 142314564Sdim } 143314564Sdim for (auto &P : MN->Mapping) 144314564Sdim Ret.push_back(P.first()); 145314564Sdim return Ret; 146314564Sdim} 147314564Sdim 148249259Sdimbool Input::preflightKey(const char *Key, bool Required, bool, bool &UseDefault, 149249259Sdim void *&SaveInfo) { 150249259Sdim UseDefault = false; 151249259Sdim if (EC) 152249259Sdim return false; 153261991Sdim 154261991Sdim // CurrentNode is null for empty documents, which is an error in case required 155261991Sdim // nodes are present. 156261991Sdim if (!CurrentNode) { 157261991Sdim if (Required) 158261991Sdim EC = make_error_code(errc::invalid_argument); 159261991Sdim return false; 160261991Sdim } 161261991Sdim 162249259Sdim MapHNode *MN = dyn_cast<MapHNode>(CurrentNode); 163249259Sdim if (!MN) { 164327952Sdim if (Required || !isa<EmptyHNode>(CurrentNode)) 165327952Sdim setError(CurrentNode, "not a mapping"); 166249259Sdim return false; 167249259Sdim } 168249259Sdim MN->ValidKeys.push_back(Key); 169280031Sdim HNode *Value = MN->Mapping[Key].get(); 170249259Sdim if (!Value) { 171249259Sdim if (Required) 172249259Sdim setError(CurrentNode, Twine("missing required key '") + Key + "'"); 173249259Sdim else 174249259Sdim UseDefault = true; 175249259Sdim return false; 176249259Sdim } 177249259Sdim SaveInfo = CurrentNode; 178249259Sdim CurrentNode = Value; 179249259Sdim return true; 180249259Sdim} 181249259Sdim 182249259Sdimvoid Input::postflightKey(void *saveInfo) { 183249259Sdim CurrentNode = reinterpret_cast<HNode *>(saveInfo); 184249259Sdim} 185249259Sdim 186249259Sdimvoid Input::endMapping() { 187249259Sdim if (EC) 188249259Sdim return; 189261991Sdim // CurrentNode can be null if the document is empty. 190261991Sdim MapHNode *MN = dyn_cast_or_null<MapHNode>(CurrentNode); 191249259Sdim if (!MN) 192249259Sdim return; 193276479Sdim for (const auto &NN : MN->Mapping) { 194314564Sdim if (!is_contained(MN->ValidKeys, NN.first())) { 195280031Sdim setError(NN.second.get(), Twine("unknown key '") + NN.first() + "'"); 196249259Sdim break; 197249259Sdim } 198249259Sdim } 199249259Sdim} 200249259Sdim 201288943Sdimvoid Input::beginFlowMapping() { beginMapping(); } 202288943Sdim 203288943Sdimvoid Input::endFlowMapping() { endMapping(); } 204288943Sdim 205249259Sdimunsigned Input::beginSequence() { 206288943Sdim if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) 207249259Sdim return SQ->Entries.size(); 208288943Sdim if (isa<EmptyHNode>(CurrentNode)) 209288943Sdim return 0; 210288943Sdim // Treat case where there's a scalar "null" value as an empty sequence. 211288943Sdim if (ScalarHNode *SN = dyn_cast<ScalarHNode>(CurrentNode)) { 212288943Sdim if (isNull(SN->value())) 213288943Sdim return 0; 214249259Sdim } 215288943Sdim // Any other type of HNode is an error. 216288943Sdim setError(CurrentNode, "not a sequence"); 217249259Sdim return 0; 218249259Sdim} 219249259Sdim 220249259Sdimvoid Input::endSequence() { 221249259Sdim} 222249259Sdim 223249259Sdimbool Input::preflightElement(unsigned Index, void *&SaveInfo) { 224249259Sdim if (EC) 225249259Sdim return false; 226249259Sdim if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) { 227249259Sdim SaveInfo = CurrentNode; 228280031Sdim CurrentNode = SQ->Entries[Index].get(); 229249259Sdim return true; 230249259Sdim } 231249259Sdim return false; 232249259Sdim} 233249259Sdim 234249259Sdimvoid Input::postflightElement(void *SaveInfo) { 235249259Sdim CurrentNode = reinterpret_cast<HNode *>(SaveInfo); 236249259Sdim} 237249259Sdim 238288943Sdimunsigned Input::beginFlowSequence() { return beginSequence(); } 239249259Sdim 240249259Sdimbool Input::preflightFlowElement(unsigned index, void *&SaveInfo) { 241249259Sdim if (EC) 242249259Sdim return false; 243249259Sdim if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) { 244249259Sdim SaveInfo = CurrentNode; 245280031Sdim CurrentNode = SQ->Entries[index].get(); 246249259Sdim return true; 247249259Sdim } 248249259Sdim return false; 249249259Sdim} 250249259Sdim 251249259Sdimvoid Input::postflightFlowElement(void *SaveInfo) { 252249259Sdim CurrentNode = reinterpret_cast<HNode *>(SaveInfo); 253249259Sdim} 254249259Sdim 255249259Sdimvoid Input::endFlowSequence() { 256249259Sdim} 257249259Sdim 258249259Sdimvoid Input::beginEnumScalar() { 259249259Sdim ScalarMatchFound = false; 260249259Sdim} 261249259Sdim 262249259Sdimbool Input::matchEnumScalar(const char *Str, bool) { 263249259Sdim if (ScalarMatchFound) 264249259Sdim return false; 265249259Sdim if (ScalarHNode *SN = dyn_cast<ScalarHNode>(CurrentNode)) { 266249259Sdim if (SN->value().equals(Str)) { 267249259Sdim ScalarMatchFound = true; 268249259Sdim return true; 269249259Sdim } 270249259Sdim } 271249259Sdim return false; 272249259Sdim} 273249259Sdim 274288943Sdimbool Input::matchEnumFallback() { 275288943Sdim if (ScalarMatchFound) 276288943Sdim return false; 277288943Sdim ScalarMatchFound = true; 278288943Sdim return true; 279288943Sdim} 280288943Sdim 281249259Sdimvoid Input::endEnumScalar() { 282249259Sdim if (!ScalarMatchFound) { 283249259Sdim setError(CurrentNode, "unknown enumerated scalar"); 284249259Sdim } 285249259Sdim} 286249259Sdim 287249259Sdimbool Input::beginBitSetScalar(bool &DoClear) { 288249259Sdim BitValuesUsed.clear(); 289249259Sdim if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) { 290249259Sdim BitValuesUsed.insert(BitValuesUsed.begin(), SQ->Entries.size(), false); 291249259Sdim } else { 292249259Sdim setError(CurrentNode, "expected sequence of bit values"); 293249259Sdim } 294249259Sdim DoClear = true; 295249259Sdim return true; 296249259Sdim} 297249259Sdim 298249259Sdimbool Input::bitSetMatch(const char *Str, bool) { 299249259Sdim if (EC) 300249259Sdim return false; 301249259Sdim if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) { 302249259Sdim unsigned Index = 0; 303280031Sdim for (auto &N : SQ->Entries) { 304280031Sdim if (ScalarHNode *SN = dyn_cast<ScalarHNode>(N.get())) { 305249259Sdim if (SN->value().equals(Str)) { 306249259Sdim BitValuesUsed[Index] = true; 307249259Sdim return true; 308249259Sdim } 309249259Sdim } else { 310249259Sdim setError(CurrentNode, "unexpected scalar in sequence of bit values"); 311249259Sdim } 312249259Sdim ++Index; 313249259Sdim } 314249259Sdim } else { 315249259Sdim setError(CurrentNode, "expected sequence of bit values"); 316249259Sdim } 317249259Sdim return false; 318249259Sdim} 319249259Sdim 320249259Sdimvoid Input::endBitSetScalar() { 321249259Sdim if (EC) 322249259Sdim return; 323249259Sdim if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) { 324249259Sdim assert(BitValuesUsed.size() == SQ->Entries.size()); 325249259Sdim for (unsigned i = 0; i < SQ->Entries.size(); ++i) { 326249259Sdim if (!BitValuesUsed[i]) { 327280031Sdim setError(SQ->Entries[i].get(), "unknown bit value"); 328249259Sdim return; 329249259Sdim } 330249259Sdim } 331249259Sdim } 332249259Sdim} 333249259Sdim 334327952Sdimvoid Input::scalarString(StringRef &S, QuotingType) { 335249259Sdim if (ScalarHNode *SN = dyn_cast<ScalarHNode>(CurrentNode)) { 336249259Sdim S = SN->value(); 337249259Sdim } else { 338249259Sdim setError(CurrentNode, "unexpected scalar"); 339249259Sdim } 340249259Sdim} 341249259Sdim 342327952Sdimvoid Input::blockScalarString(StringRef &S) { scalarString(S, QuotingType::None); } 343288943Sdim 344249259Sdimvoid Input::setError(HNode *hnode, const Twine &message) { 345261991Sdim assert(hnode && "HNode must not be NULL"); 346249259Sdim this->setError(hnode->_node, message); 347249259Sdim} 348249259Sdim 349249259Sdimvoid Input::setError(Node *node, const Twine &message) { 350249259Sdim Strm->printError(node, message); 351249259Sdim EC = make_error_code(errc::invalid_argument); 352249259Sdim} 353249259Sdim 354280031Sdimstd::unique_ptr<Input::HNode> Input::createHNodes(Node *N) { 355249259Sdim SmallString<128> StringStorage; 356249259Sdim if (ScalarNode *SN = dyn_cast<ScalarNode>(N)) { 357249259Sdim StringRef KeyStr = SN->getValue(StringStorage); 358249259Sdim if (!StringStorage.empty()) { 359249259Sdim // Copy string to permanent storage 360296417Sdim KeyStr = StringStorage.str().copy(StringAllocator); 361249259Sdim } 362280031Sdim return llvm::make_unique<ScalarHNode>(N, KeyStr); 363288943Sdim } else if (BlockScalarNode *BSN = dyn_cast<BlockScalarNode>(N)) { 364296417Sdim StringRef ValueCopy = BSN->getValue().copy(StringAllocator); 365296417Sdim return llvm::make_unique<ScalarHNode>(N, ValueCopy); 366249259Sdim } else if (SequenceNode *SQ = dyn_cast<SequenceNode>(N)) { 367280031Sdim auto SQHNode = llvm::make_unique<SequenceHNode>(N); 368276479Sdim for (Node &SN : *SQ) { 369280031Sdim auto Entry = this->createHNodes(&SN); 370249259Sdim if (EC) 371249259Sdim break; 372280031Sdim SQHNode->Entries.push_back(std::move(Entry)); 373249259Sdim } 374280031Sdim return std::move(SQHNode); 375249259Sdim } else if (MappingNode *Map = dyn_cast<MappingNode>(N)) { 376280031Sdim auto mapHNode = llvm::make_unique<MapHNode>(N); 377276479Sdim for (KeyValueNode &KVN : *Map) { 378280031Sdim Node *KeyNode = KVN.getKey(); 379327952Sdim ScalarNode *Key = dyn_cast<ScalarNode>(KeyNode); 380327952Sdim Node *Value = KVN.getValue(); 381327952Sdim if (!Key || !Value) { 382327952Sdim if (!Key) 383327952Sdim setError(KeyNode, "Map key must be a scalar"); 384327952Sdim if (!Value) 385327952Sdim setError(KeyNode, "Map value must not be empty"); 386280031Sdim break; 387280031Sdim } 388249259Sdim StringStorage.clear(); 389327952Sdim StringRef KeyStr = Key->getValue(StringStorage); 390249259Sdim if (!StringStorage.empty()) { 391249259Sdim // Copy string to permanent storage 392296417Sdim KeyStr = StringStorage.str().copy(StringAllocator); 393249259Sdim } 394327952Sdim auto ValueHNode = this->createHNodes(Value); 395249259Sdim if (EC) 396249259Sdim break; 397280031Sdim mapHNode->Mapping[KeyStr] = std::move(ValueHNode); 398249259Sdim } 399280031Sdim return std::move(mapHNode); 400249259Sdim } else if (isa<NullNode>(N)) { 401280031Sdim return llvm::make_unique<EmptyHNode>(N); 402249259Sdim } else { 403249259Sdim setError(N, "unknown node kind"); 404276479Sdim return nullptr; 405249259Sdim } 406249259Sdim} 407249259Sdim 408249259Sdimvoid Input::setError(const Twine &Message) { 409249259Sdim this->setError(CurrentNode, Message); 410249259Sdim} 411249259Sdim 412261991Sdimbool Input::canElideEmptySequence() { 413261991Sdim return false; 414261991Sdim} 415261991Sdim 416249259Sdim//===----------------------------------------------------------------------===// 417249259Sdim// Output 418249259Sdim//===----------------------------------------------------------------------===// 419249259Sdim 420288943SdimOutput::Output(raw_ostream &yout, void *context, int WrapColumn) 421321369Sdim : IO(context), Out(yout), WrapColumn(WrapColumn) {} 422249259Sdim 423321369SdimOutput::~Output() = default; 424249259Sdim 425276479Sdimbool Output::outputting() { 426249259Sdim return true; 427249259Sdim} 428249259Sdim 429249259Sdimvoid Output::beginMapping() { 430249259Sdim StateStack.push_back(inMapFirstKey); 431249259Sdim NeedsNewLine = true; 432249259Sdim} 433249259Sdim 434261991Sdimbool Output::mapTag(StringRef Tag, bool Use) { 435261991Sdim if (Use) { 436309124Sdim // If this tag is being written inside a sequence we should write the start 437309124Sdim // of the sequence before writing the tag, otherwise the tag won't be 438309124Sdim // attached to the element in the sequence, but rather the sequence itself. 439309124Sdim bool SequenceElement = 440309124Sdim StateStack.size() > 1 && (StateStack[StateStack.size() - 2] == inSeq || 441309124Sdim StateStack[StateStack.size() - 2] == inFlowSeq); 442309124Sdim if (SequenceElement && StateStack.back() == inMapFirstKey) { 443309124Sdim this->newLineCheck(); 444309124Sdim } else { 445309124Sdim this->output(" "); 446309124Sdim } 447261991Sdim this->output(Tag); 448309124Sdim if (SequenceElement) { 449309124Sdim // If we're writing the tag during the first element of a map, the tag 450309124Sdim // takes the place of the first element in the sequence. 451309124Sdim if (StateStack.back() == inMapFirstKey) { 452309124Sdim StateStack.pop_back(); 453309124Sdim StateStack.push_back(inMapOtherKey); 454309124Sdim } 455309124Sdim // Tags inside maps in sequences should act as keys in the map from a 456309124Sdim // formatting perspective, so we always want a newline in a sequence. 457309124Sdim NeedsNewLine = true; 458309124Sdim } 459261991Sdim } 460261991Sdim return Use; 461261991Sdim} 462261991Sdim 463249259Sdimvoid Output::endMapping() { 464249259Sdim StateStack.pop_back(); 465249259Sdim} 466249259Sdim 467314564Sdimstd::vector<StringRef> Output::keys() { 468314564Sdim report_fatal_error("invalid call"); 469314564Sdim} 470314564Sdim 471249259Sdimbool Output::preflightKey(const char *Key, bool Required, bool SameAsDefault, 472249259Sdim bool &UseDefault, void *&) { 473249259Sdim UseDefault = false; 474321369Sdim if (Required || !SameAsDefault || WriteDefaultValues) { 475288943Sdim auto State = StateStack.back(); 476288943Sdim if (State == inFlowMapFirstKey || State == inFlowMapOtherKey) { 477288943Sdim flowKey(Key); 478288943Sdim } else { 479288943Sdim this->newLineCheck(); 480288943Sdim this->paddedKey(Key); 481288943Sdim } 482249259Sdim return true; 483249259Sdim } 484249259Sdim return false; 485249259Sdim} 486249259Sdim 487249259Sdimvoid Output::postflightKey(void *) { 488249259Sdim if (StateStack.back() == inMapFirstKey) { 489249259Sdim StateStack.pop_back(); 490249259Sdim StateStack.push_back(inMapOtherKey); 491288943Sdim } else if (StateStack.back() == inFlowMapFirstKey) { 492288943Sdim StateStack.pop_back(); 493288943Sdim StateStack.push_back(inFlowMapOtherKey); 494249259Sdim } 495249259Sdim} 496249259Sdim 497288943Sdimvoid Output::beginFlowMapping() { 498288943Sdim StateStack.push_back(inFlowMapFirstKey); 499288943Sdim this->newLineCheck(); 500288943Sdim ColumnAtMapFlowStart = Column; 501288943Sdim output("{ "); 502288943Sdim} 503288943Sdim 504288943Sdimvoid Output::endFlowMapping() { 505288943Sdim StateStack.pop_back(); 506288943Sdim this->outputUpToEndOfLine(" }"); 507288943Sdim} 508288943Sdim 509249259Sdimvoid Output::beginDocuments() { 510249259Sdim this->outputUpToEndOfLine("---"); 511249259Sdim} 512249259Sdim 513249259Sdimbool Output::preflightDocument(unsigned index) { 514249259Sdim if (index > 0) 515249259Sdim this->outputUpToEndOfLine("\n---"); 516249259Sdim return true; 517249259Sdim} 518249259Sdim 519249259Sdimvoid Output::postflightDocument() { 520249259Sdim} 521249259Sdim 522249259Sdimvoid Output::endDocuments() { 523249259Sdim output("\n...\n"); 524249259Sdim} 525249259Sdim 526249259Sdimunsigned Output::beginSequence() { 527249259Sdim StateStack.push_back(inSeq); 528249259Sdim NeedsNewLine = true; 529249259Sdim return 0; 530249259Sdim} 531249259Sdim 532249259Sdimvoid Output::endSequence() { 533249259Sdim StateStack.pop_back(); 534249259Sdim} 535249259Sdim 536249259Sdimbool Output::preflightElement(unsigned, void *&) { 537249259Sdim return true; 538249259Sdim} 539249259Sdim 540249259Sdimvoid Output::postflightElement(void *) { 541249259Sdim} 542249259Sdim 543249259Sdimunsigned Output::beginFlowSequence() { 544249259Sdim StateStack.push_back(inFlowSeq); 545249259Sdim this->newLineCheck(); 546249259Sdim ColumnAtFlowStart = Column; 547249259Sdim output("[ "); 548249259Sdim NeedFlowSequenceComma = false; 549249259Sdim return 0; 550249259Sdim} 551249259Sdim 552249259Sdimvoid Output::endFlowSequence() { 553249259Sdim StateStack.pop_back(); 554249259Sdim this->outputUpToEndOfLine(" ]"); 555249259Sdim} 556249259Sdim 557249259Sdimbool Output::preflightFlowElement(unsigned, void *&) { 558249259Sdim if (NeedFlowSequenceComma) 559249259Sdim output(", "); 560288943Sdim if (WrapColumn && Column > WrapColumn) { 561249259Sdim output("\n"); 562249259Sdim for (int i = 0; i < ColumnAtFlowStart; ++i) 563249259Sdim output(" "); 564249259Sdim Column = ColumnAtFlowStart; 565249259Sdim output(" "); 566249259Sdim } 567249259Sdim return true; 568249259Sdim} 569249259Sdim 570249259Sdimvoid Output::postflightFlowElement(void *) { 571249259Sdim NeedFlowSequenceComma = true; 572249259Sdim} 573249259Sdim 574249259Sdimvoid Output::beginEnumScalar() { 575249259Sdim EnumerationMatchFound = false; 576249259Sdim} 577249259Sdim 578249259Sdimbool Output::matchEnumScalar(const char *Str, bool Match) { 579249259Sdim if (Match && !EnumerationMatchFound) { 580249259Sdim this->newLineCheck(); 581249259Sdim this->outputUpToEndOfLine(Str); 582249259Sdim EnumerationMatchFound = true; 583249259Sdim } 584249259Sdim return false; 585249259Sdim} 586249259Sdim 587288943Sdimbool Output::matchEnumFallback() { 588288943Sdim if (EnumerationMatchFound) 589288943Sdim return false; 590288943Sdim EnumerationMatchFound = true; 591288943Sdim return true; 592288943Sdim} 593288943Sdim 594249259Sdimvoid Output::endEnumScalar() { 595249259Sdim if (!EnumerationMatchFound) 596249259Sdim llvm_unreachable("bad runtime enum value"); 597249259Sdim} 598249259Sdim 599249259Sdimbool Output::beginBitSetScalar(bool &DoClear) { 600249259Sdim this->newLineCheck(); 601249259Sdim output("[ "); 602249259Sdim NeedBitValueComma = false; 603249259Sdim DoClear = false; 604249259Sdim return true; 605249259Sdim} 606249259Sdim 607249259Sdimbool Output::bitSetMatch(const char *Str, bool Matches) { 608249259Sdim if (Matches) { 609249259Sdim if (NeedBitValueComma) 610249259Sdim output(", "); 611249259Sdim this->output(Str); 612249259Sdim NeedBitValueComma = true; 613249259Sdim } 614249259Sdim return false; 615249259Sdim} 616249259Sdim 617249259Sdimvoid Output::endBitSetScalar() { 618249259Sdim this->outputUpToEndOfLine(" ]"); 619249259Sdim} 620249259Sdim 621327952Sdimvoid Output::scalarString(StringRef &S, QuotingType MustQuote) { 622249259Sdim this->newLineCheck(); 623261991Sdim if (S.empty()) { 624261991Sdim // Print '' for the empty string because leaving the field empty is not 625261991Sdim // allowed. 626261991Sdim this->outputUpToEndOfLine("''"); 627261991Sdim return; 628261991Sdim } 629327952Sdim if (MustQuote == QuotingType::None) { 630276479Sdim // Only quote if we must. 631249259Sdim this->outputUpToEndOfLine(S); 632249259Sdim return; 633249259Sdim } 634327952Sdim 635249259Sdim unsigned i = 0; 636249259Sdim unsigned j = 0; 637249259Sdim unsigned End = S.size(); 638249259Sdim const char *Base = S.data(); 639327952Sdim 640327952Sdim const char *const Quote = MustQuote == QuotingType::Single ? "'" : "\""; 641327952Sdim const char QuoteChar = MustQuote == QuotingType::Single ? '\'' : '"'; 642327952Sdim 643327952Sdim output(Quote); // Starting quote. 644327952Sdim 645327952Sdim // When using single-quoted strings, any single quote ' must be doubled to be 646327952Sdim // escaped. 647327952Sdim // When using double-quoted strings, print \x + hex for non-printable ASCII 648327952Sdim // characters, and escape double quotes. 649249259Sdim while (j < End) { 650327952Sdim if (S[j] == QuoteChar) { // Escape quotes. 651327952Sdim output(StringRef(&Base[i], j - i)); // "flush". 652327952Sdim if (MustQuote == QuotingType::Double) { // Print it as \" 653327952Sdim output(StringLiteral("\\")); 654327952Sdim output(StringRef(Quote, 1)); 655327952Sdim } else { // Single 656327952Sdim output(StringLiteral("''")); // Print it as '' 657327952Sdim } 658249259Sdim i = j + 1; 659327952Sdim } else if (MustQuote == QuotingType::Double && 660327952Sdim !sys::unicode::isPrintable(S[j]) && (S[j] & 0x80) == 0) { 661327952Sdim // If we're double quoting non-printable characters, we prefer printing 662327952Sdim // them as "\x" + their hex representation. Note that special casing is 663327952Sdim // needed for UTF-8, where a byte may be part of a UTF-8 sequence and 664327952Sdim // appear as non-printable, in which case we want to print the correct 665327952Sdim // unicode character and not its hex representation. 666327952Sdim output(StringRef(&Base[i], j - i)); // "flush" 667327952Sdim output(StringLiteral("\\x")); 668327952Sdim 669327952Sdim // Output the byte 0x0F as \x0f. 670327952Sdim auto FormattedHex = format_hex_no_prefix(S[j], 2); 671327952Sdim Out << FormattedHex; 672327952Sdim Column += 4; // one for the '\', one for the 'x', and two for the hex 673327952Sdim 674327952Sdim i = j + 1; 675249259Sdim } 676249259Sdim ++j; 677249259Sdim } 678249259Sdim output(StringRef(&Base[i], j - i)); 679327952Sdim this->outputUpToEndOfLine(Quote); // Ending quote. 680249259Sdim} 681249259Sdim 682288943Sdimvoid Output::blockScalarString(StringRef &S) { 683288943Sdim if (!StateStack.empty()) 684288943Sdim newLineCheck(); 685288943Sdim output(" |"); 686288943Sdim outputNewLine(); 687288943Sdim 688288943Sdim unsigned Indent = StateStack.empty() ? 1 : StateStack.size(); 689288943Sdim 690288943Sdim auto Buffer = MemoryBuffer::getMemBuffer(S, "", false); 691288943Sdim for (line_iterator Lines(*Buffer, false); !Lines.is_at_end(); ++Lines) { 692288943Sdim for (unsigned I = 0; I < Indent; ++I) { 693288943Sdim output(" "); 694288943Sdim } 695288943Sdim output(*Lines); 696288943Sdim outputNewLine(); 697288943Sdim } 698288943Sdim} 699288943Sdim 700249259Sdimvoid Output::setError(const Twine &message) { 701249259Sdim} 702249259Sdim 703261991Sdimbool Output::canElideEmptySequence() { 704261991Sdim // Normally, with an optional key/value where the value is an empty sequence, 705261991Sdim // the whole key/value can be not written. But, that produces wrong yaml 706261991Sdim // if the key/value is the only thing in the map and the map is used in 707261991Sdim // a sequence. This detects if the this sequence is the first key/value 708261991Sdim // in map that itself is embedded in a sequnce. 709261991Sdim if (StateStack.size() < 2) 710261991Sdim return true; 711261991Sdim if (StateStack.back() != inMapFirstKey) 712261991Sdim return true; 713261991Sdim return (StateStack[StateStack.size()-2] != inSeq); 714261991Sdim} 715261991Sdim 716249259Sdimvoid Output::output(StringRef s) { 717249259Sdim Column += s.size(); 718249259Sdim Out << s; 719249259Sdim} 720249259Sdim 721249259Sdimvoid Output::outputUpToEndOfLine(StringRef s) { 722249259Sdim this->output(s); 723288943Sdim if (StateStack.empty() || (StateStack.back() != inFlowSeq && 724288943Sdim StateStack.back() != inFlowMapFirstKey && 725288943Sdim StateStack.back() != inFlowMapOtherKey)) 726249259Sdim NeedsNewLine = true; 727249259Sdim} 728249259Sdim 729249259Sdimvoid Output::outputNewLine() { 730249259Sdim Out << "\n"; 731249259Sdim Column = 0; 732249259Sdim} 733249259Sdim 734249259Sdim// if seq at top, indent as if map, then add "- " 735249259Sdim// if seq in middle, use "- " if firstKey, else use " " 736249259Sdim// 737249259Sdim 738249259Sdimvoid Output::newLineCheck() { 739249259Sdim if (!NeedsNewLine) 740249259Sdim return; 741249259Sdim NeedsNewLine = false; 742249259Sdim 743249259Sdim this->outputNewLine(); 744249259Sdim 745249259Sdim assert(StateStack.size() > 0); 746249259Sdim unsigned Indent = StateStack.size() - 1; 747249259Sdim bool OutputDash = false; 748249259Sdim 749249259Sdim if (StateStack.back() == inSeq) { 750249259Sdim OutputDash = true; 751288943Sdim } else if ((StateStack.size() > 1) && ((StateStack.back() == inMapFirstKey) || 752288943Sdim (StateStack.back() == inFlowSeq) || 753288943Sdim (StateStack.back() == inFlowMapFirstKey)) && 754249259Sdim (StateStack[StateStack.size() - 2] == inSeq)) { 755249259Sdim --Indent; 756249259Sdim OutputDash = true; 757249259Sdim } 758249259Sdim 759249259Sdim for (unsigned i = 0; i < Indent; ++i) { 760249259Sdim output(" "); 761249259Sdim } 762249259Sdim if (OutputDash) { 763249259Sdim output("- "); 764249259Sdim } 765249259Sdim 766249259Sdim} 767249259Sdim 768249259Sdimvoid Output::paddedKey(StringRef key) { 769249259Sdim output(key); 770249259Sdim output(":"); 771249259Sdim const char *spaces = " "; 772249259Sdim if (key.size() < strlen(spaces)) 773249259Sdim output(&spaces[key.size()]); 774249259Sdim else 775249259Sdim output(" "); 776249259Sdim} 777249259Sdim 778288943Sdimvoid Output::flowKey(StringRef Key) { 779288943Sdim if (StateStack.back() == inFlowMapOtherKey) 780288943Sdim output(", "); 781288943Sdim if (WrapColumn && Column > WrapColumn) { 782288943Sdim output("\n"); 783288943Sdim for (int I = 0; I < ColumnAtMapFlowStart; ++I) 784288943Sdim output(" "); 785288943Sdim Column = ColumnAtMapFlowStart; 786288943Sdim output(" "); 787288943Sdim } 788288943Sdim output(Key); 789288943Sdim output(": "); 790288943Sdim} 791288943Sdim 792249259Sdim//===----------------------------------------------------------------------===// 793249259Sdim// traits for built-in types 794249259Sdim//===----------------------------------------------------------------------===// 795249259Sdim 796249259Sdimvoid ScalarTraits<bool>::output(const bool &Val, void *, raw_ostream &Out) { 797249259Sdim Out << (Val ? "true" : "false"); 798249259Sdim} 799249259Sdim 800249259SdimStringRef ScalarTraits<bool>::input(StringRef Scalar, void *, bool &Val) { 801249259Sdim if (Scalar.equals("true")) { 802249259Sdim Val = true; 803249259Sdim return StringRef(); 804249259Sdim } else if (Scalar.equals("false")) { 805249259Sdim Val = false; 806249259Sdim return StringRef(); 807249259Sdim } 808249259Sdim return "invalid boolean"; 809249259Sdim} 810249259Sdim 811249259Sdimvoid ScalarTraits<StringRef>::output(const StringRef &Val, void *, 812249259Sdim raw_ostream &Out) { 813249259Sdim Out << Val; 814249259Sdim} 815249259Sdim 816249259SdimStringRef ScalarTraits<StringRef>::input(StringRef Scalar, void *, 817249259Sdim StringRef &Val) { 818249259Sdim Val = Scalar; 819249259Sdim return StringRef(); 820249259Sdim} 821288943Sdim 822276479Sdimvoid ScalarTraits<std::string>::output(const std::string &Val, void *, 823276479Sdim raw_ostream &Out) { 824276479Sdim Out << Val; 825276479Sdim} 826249259Sdim 827276479SdimStringRef ScalarTraits<std::string>::input(StringRef Scalar, void *, 828276479Sdim std::string &Val) { 829276479Sdim Val = Scalar.str(); 830276479Sdim return StringRef(); 831276479Sdim} 832276479Sdim 833249259Sdimvoid ScalarTraits<uint8_t>::output(const uint8_t &Val, void *, 834249259Sdim raw_ostream &Out) { 835249259Sdim // use temp uin32_t because ostream thinks uint8_t is a character 836249259Sdim uint32_t Num = Val; 837249259Sdim Out << Num; 838249259Sdim} 839249259Sdim 840249259SdimStringRef ScalarTraits<uint8_t>::input(StringRef Scalar, void *, uint8_t &Val) { 841249259Sdim unsigned long long n; 842249259Sdim if (getAsUnsignedInteger(Scalar, 0, n)) 843249259Sdim return "invalid number"; 844249259Sdim if (n > 0xFF) 845249259Sdim return "out of range number"; 846249259Sdim Val = n; 847249259Sdim return StringRef(); 848249259Sdim} 849249259Sdim 850249259Sdimvoid ScalarTraits<uint16_t>::output(const uint16_t &Val, void *, 851249259Sdim raw_ostream &Out) { 852249259Sdim Out << Val; 853249259Sdim} 854249259Sdim 855249259SdimStringRef ScalarTraits<uint16_t>::input(StringRef Scalar, void *, 856249259Sdim uint16_t &Val) { 857249259Sdim unsigned long long n; 858249259Sdim if (getAsUnsignedInteger(Scalar, 0, n)) 859249259Sdim return "invalid number"; 860249259Sdim if (n > 0xFFFF) 861249259Sdim return "out of range number"; 862249259Sdim Val = n; 863249259Sdim return StringRef(); 864249259Sdim} 865249259Sdim 866249259Sdimvoid ScalarTraits<uint32_t>::output(const uint32_t &Val, void *, 867249259Sdim raw_ostream &Out) { 868249259Sdim Out << Val; 869249259Sdim} 870249259Sdim 871249259SdimStringRef ScalarTraits<uint32_t>::input(StringRef Scalar, void *, 872249259Sdim uint32_t &Val) { 873249259Sdim unsigned long long n; 874249259Sdim if (getAsUnsignedInteger(Scalar, 0, n)) 875249259Sdim return "invalid number"; 876249259Sdim if (n > 0xFFFFFFFFUL) 877249259Sdim return "out of range number"; 878249259Sdim Val = n; 879249259Sdim return StringRef(); 880249259Sdim} 881249259Sdim 882249259Sdimvoid ScalarTraits<uint64_t>::output(const uint64_t &Val, void *, 883249259Sdim raw_ostream &Out) { 884249259Sdim Out << Val; 885249259Sdim} 886249259Sdim 887249259SdimStringRef ScalarTraits<uint64_t>::input(StringRef Scalar, void *, 888249259Sdim uint64_t &Val) { 889249259Sdim unsigned long long N; 890249259Sdim if (getAsUnsignedInteger(Scalar, 0, N)) 891249259Sdim return "invalid number"; 892249259Sdim Val = N; 893249259Sdim return StringRef(); 894249259Sdim} 895249259Sdim 896249259Sdimvoid ScalarTraits<int8_t>::output(const int8_t &Val, void *, raw_ostream &Out) { 897249259Sdim // use temp in32_t because ostream thinks int8_t is a character 898249259Sdim int32_t Num = Val; 899249259Sdim Out << Num; 900249259Sdim} 901249259Sdim 902249259SdimStringRef ScalarTraits<int8_t>::input(StringRef Scalar, void *, int8_t &Val) { 903249259Sdim long long N; 904249259Sdim if (getAsSignedInteger(Scalar, 0, N)) 905249259Sdim return "invalid number"; 906249259Sdim if ((N > 127) || (N < -128)) 907249259Sdim return "out of range number"; 908249259Sdim Val = N; 909249259Sdim return StringRef(); 910249259Sdim} 911249259Sdim 912249259Sdimvoid ScalarTraits<int16_t>::output(const int16_t &Val, void *, 913249259Sdim raw_ostream &Out) { 914249259Sdim Out << Val; 915249259Sdim} 916249259Sdim 917249259SdimStringRef ScalarTraits<int16_t>::input(StringRef Scalar, void *, int16_t &Val) { 918249259Sdim long long N; 919249259Sdim if (getAsSignedInteger(Scalar, 0, N)) 920249259Sdim return "invalid number"; 921249259Sdim if ((N > INT16_MAX) || (N < INT16_MIN)) 922249259Sdim return "out of range number"; 923249259Sdim Val = N; 924249259Sdim return StringRef(); 925249259Sdim} 926249259Sdim 927249259Sdimvoid ScalarTraits<int32_t>::output(const int32_t &Val, void *, 928249259Sdim raw_ostream &Out) { 929249259Sdim Out << Val; 930249259Sdim} 931249259Sdim 932249259SdimStringRef ScalarTraits<int32_t>::input(StringRef Scalar, void *, int32_t &Val) { 933249259Sdim long long N; 934249259Sdim if (getAsSignedInteger(Scalar, 0, N)) 935249259Sdim return "invalid number"; 936249259Sdim if ((N > INT32_MAX) || (N < INT32_MIN)) 937249259Sdim return "out of range number"; 938249259Sdim Val = N; 939249259Sdim return StringRef(); 940249259Sdim} 941249259Sdim 942249259Sdimvoid ScalarTraits<int64_t>::output(const int64_t &Val, void *, 943249259Sdim raw_ostream &Out) { 944249259Sdim Out << Val; 945249259Sdim} 946249259Sdim 947249259SdimStringRef ScalarTraits<int64_t>::input(StringRef Scalar, void *, int64_t &Val) { 948249259Sdim long long N; 949249259Sdim if (getAsSignedInteger(Scalar, 0, N)) 950249259Sdim return "invalid number"; 951249259Sdim Val = N; 952249259Sdim return StringRef(); 953249259Sdim} 954249259Sdim 955249259Sdimvoid ScalarTraits<double>::output(const double &Val, void *, raw_ostream &Out) { 956249259Sdim Out << format("%g", Val); 957249259Sdim} 958249259Sdim 959249259SdimStringRef ScalarTraits<double>::input(StringRef Scalar, void *, double &Val) { 960321369Sdim if (to_float(Scalar, Val)) 961321369Sdim return StringRef(); 962321369Sdim return "invalid floating point number"; 963249259Sdim} 964249259Sdim 965249259Sdimvoid ScalarTraits<float>::output(const float &Val, void *, raw_ostream &Out) { 966249259Sdim Out << format("%g", Val); 967249259Sdim} 968249259Sdim 969249259SdimStringRef ScalarTraits<float>::input(StringRef Scalar, void *, float &Val) { 970321369Sdim if (to_float(Scalar, Val)) 971321369Sdim return StringRef(); 972321369Sdim return "invalid floating point number"; 973249259Sdim} 974249259Sdim 975249259Sdimvoid ScalarTraits<Hex8>::output(const Hex8 &Val, void *, raw_ostream &Out) { 976249259Sdim uint8_t Num = Val; 977249259Sdim Out << format("0x%02X", Num); 978249259Sdim} 979249259Sdim 980249259SdimStringRef ScalarTraits<Hex8>::input(StringRef Scalar, void *, Hex8 &Val) { 981249259Sdim unsigned long long n; 982249259Sdim if (getAsUnsignedInteger(Scalar, 0, n)) 983249259Sdim return "invalid hex8 number"; 984249259Sdim if (n > 0xFF) 985249259Sdim return "out of range hex8 number"; 986249259Sdim Val = n; 987249259Sdim return StringRef(); 988249259Sdim} 989249259Sdim 990249259Sdimvoid ScalarTraits<Hex16>::output(const Hex16 &Val, void *, raw_ostream &Out) { 991249259Sdim uint16_t Num = Val; 992249259Sdim Out << format("0x%04X", Num); 993249259Sdim} 994249259Sdim 995249259SdimStringRef ScalarTraits<Hex16>::input(StringRef Scalar, void *, Hex16 &Val) { 996249259Sdim unsigned long long n; 997249259Sdim if (getAsUnsignedInteger(Scalar, 0, n)) 998249259Sdim return "invalid hex16 number"; 999249259Sdim if (n > 0xFFFF) 1000249259Sdim return "out of range hex16 number"; 1001249259Sdim Val = n; 1002249259Sdim return StringRef(); 1003249259Sdim} 1004249259Sdim 1005249259Sdimvoid ScalarTraits<Hex32>::output(const Hex32 &Val, void *, raw_ostream &Out) { 1006249259Sdim uint32_t Num = Val; 1007249259Sdim Out << format("0x%08X", Num); 1008249259Sdim} 1009249259Sdim 1010249259SdimStringRef ScalarTraits<Hex32>::input(StringRef Scalar, void *, Hex32 &Val) { 1011249259Sdim unsigned long long n; 1012249259Sdim if (getAsUnsignedInteger(Scalar, 0, n)) 1013249259Sdim return "invalid hex32 number"; 1014249259Sdim if (n > 0xFFFFFFFFUL) 1015249259Sdim return "out of range hex32 number"; 1016249259Sdim Val = n; 1017249259Sdim return StringRef(); 1018249259Sdim} 1019249259Sdim 1020249259Sdimvoid ScalarTraits<Hex64>::output(const Hex64 &Val, void *, raw_ostream &Out) { 1021249259Sdim uint64_t Num = Val; 1022249259Sdim Out << format("0x%016llX", Num); 1023249259Sdim} 1024249259Sdim 1025249259SdimStringRef ScalarTraits<Hex64>::input(StringRef Scalar, void *, Hex64 &Val) { 1026249259Sdim unsigned long long Num; 1027249259Sdim if (getAsUnsignedInteger(Scalar, 0, Num)) 1028249259Sdim return "invalid hex64 number"; 1029249259Sdim Val = Num; 1030249259Sdim return StringRef(); 1031249259Sdim} 1032