YAMLTraits.cpp revision 344779
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 } 101344779Sdim TopNode = 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 344344779Sdimvoid Input::scalarTag(std::string &Tag) { 345344779Sdim Tag = CurrentNode->_node->getVerbatimTag(); 346344779Sdim} 347344779Sdim 348249259Sdimvoid Input::setError(HNode *hnode, const Twine &message) { 349261991Sdim assert(hnode && "HNode must not be NULL"); 350344779Sdim setError(hnode->_node, message); 351249259Sdim} 352249259Sdim 353344779SdimNodeKind Input::getNodeKind() { 354344779Sdim if (isa<ScalarHNode>(CurrentNode)) 355344779Sdim return NodeKind::Scalar; 356344779Sdim else if (isa<MapHNode>(CurrentNode)) 357344779Sdim return NodeKind::Map; 358344779Sdim else if (isa<SequenceHNode>(CurrentNode)) 359344779Sdim return NodeKind::Sequence; 360344779Sdim llvm_unreachable("Unsupported node kind"); 361344779Sdim} 362344779Sdim 363249259Sdimvoid Input::setError(Node *node, const Twine &message) { 364249259Sdim Strm->printError(node, message); 365249259Sdim EC = make_error_code(errc::invalid_argument); 366249259Sdim} 367249259Sdim 368280031Sdimstd::unique_ptr<Input::HNode> Input::createHNodes(Node *N) { 369249259Sdim SmallString<128> StringStorage; 370249259Sdim if (ScalarNode *SN = dyn_cast<ScalarNode>(N)) { 371249259Sdim StringRef KeyStr = SN->getValue(StringStorage); 372249259Sdim if (!StringStorage.empty()) { 373249259Sdim // Copy string to permanent storage 374296417Sdim KeyStr = StringStorage.str().copy(StringAllocator); 375249259Sdim } 376280031Sdim return llvm::make_unique<ScalarHNode>(N, KeyStr); 377288943Sdim } else if (BlockScalarNode *BSN = dyn_cast<BlockScalarNode>(N)) { 378296417Sdim StringRef ValueCopy = BSN->getValue().copy(StringAllocator); 379296417Sdim return llvm::make_unique<ScalarHNode>(N, ValueCopy); 380249259Sdim } else if (SequenceNode *SQ = dyn_cast<SequenceNode>(N)) { 381280031Sdim auto SQHNode = llvm::make_unique<SequenceHNode>(N); 382276479Sdim for (Node &SN : *SQ) { 383344779Sdim auto Entry = createHNodes(&SN); 384249259Sdim if (EC) 385249259Sdim break; 386280031Sdim SQHNode->Entries.push_back(std::move(Entry)); 387249259Sdim } 388280031Sdim return std::move(SQHNode); 389249259Sdim } else if (MappingNode *Map = dyn_cast<MappingNode>(N)) { 390280031Sdim auto mapHNode = llvm::make_unique<MapHNode>(N); 391276479Sdim for (KeyValueNode &KVN : *Map) { 392280031Sdim Node *KeyNode = KVN.getKey(); 393327952Sdim ScalarNode *Key = dyn_cast<ScalarNode>(KeyNode); 394327952Sdim Node *Value = KVN.getValue(); 395327952Sdim if (!Key || !Value) { 396327952Sdim if (!Key) 397327952Sdim setError(KeyNode, "Map key must be a scalar"); 398327952Sdim if (!Value) 399327952Sdim setError(KeyNode, "Map value must not be empty"); 400280031Sdim break; 401280031Sdim } 402249259Sdim StringStorage.clear(); 403327952Sdim StringRef KeyStr = Key->getValue(StringStorage); 404249259Sdim if (!StringStorage.empty()) { 405249259Sdim // Copy string to permanent storage 406296417Sdim KeyStr = StringStorage.str().copy(StringAllocator); 407249259Sdim } 408344779Sdim auto ValueHNode = createHNodes(Value); 409249259Sdim if (EC) 410249259Sdim break; 411280031Sdim mapHNode->Mapping[KeyStr] = std::move(ValueHNode); 412249259Sdim } 413280031Sdim return std::move(mapHNode); 414249259Sdim } else if (isa<NullNode>(N)) { 415280031Sdim return llvm::make_unique<EmptyHNode>(N); 416249259Sdim } else { 417249259Sdim setError(N, "unknown node kind"); 418276479Sdim return nullptr; 419249259Sdim } 420249259Sdim} 421249259Sdim 422249259Sdimvoid Input::setError(const Twine &Message) { 423344779Sdim setError(CurrentNode, Message); 424249259Sdim} 425249259Sdim 426261991Sdimbool Input::canElideEmptySequence() { 427261991Sdim return false; 428261991Sdim} 429261991Sdim 430249259Sdim//===----------------------------------------------------------------------===// 431249259Sdim// Output 432249259Sdim//===----------------------------------------------------------------------===// 433249259Sdim 434288943SdimOutput::Output(raw_ostream &yout, void *context, int WrapColumn) 435321369Sdim : IO(context), Out(yout), WrapColumn(WrapColumn) {} 436249259Sdim 437321369SdimOutput::~Output() = default; 438249259Sdim 439276479Sdimbool Output::outputting() { 440249259Sdim return true; 441249259Sdim} 442249259Sdim 443249259Sdimvoid Output::beginMapping() { 444249259Sdim StateStack.push_back(inMapFirstKey); 445249259Sdim NeedsNewLine = true; 446249259Sdim} 447249259Sdim 448261991Sdimbool Output::mapTag(StringRef Tag, bool Use) { 449261991Sdim if (Use) { 450309124Sdim // If this tag is being written inside a sequence we should write the start 451309124Sdim // of the sequence before writing the tag, otherwise the tag won't be 452309124Sdim // attached to the element in the sequence, but rather the sequence itself. 453344779Sdim bool SequenceElement = false; 454344779Sdim if (StateStack.size() > 1) { 455344779Sdim auto &E = StateStack[StateStack.size() - 2]; 456344779Sdim SequenceElement = inSeqAnyElement(E) || inFlowSeqAnyElement(E); 457344779Sdim } 458309124Sdim if (SequenceElement && StateStack.back() == inMapFirstKey) { 459344779Sdim newLineCheck(); 460309124Sdim } else { 461344779Sdim output(" "); 462309124Sdim } 463344779Sdim output(Tag); 464309124Sdim if (SequenceElement) { 465309124Sdim // If we're writing the tag during the first element of a map, the tag 466309124Sdim // takes the place of the first element in the sequence. 467309124Sdim if (StateStack.back() == inMapFirstKey) { 468309124Sdim StateStack.pop_back(); 469309124Sdim StateStack.push_back(inMapOtherKey); 470309124Sdim } 471309124Sdim // Tags inside maps in sequences should act as keys in the map from a 472309124Sdim // formatting perspective, so we always want a newline in a sequence. 473309124Sdim NeedsNewLine = true; 474309124Sdim } 475261991Sdim } 476261991Sdim return Use; 477261991Sdim} 478261991Sdim 479249259Sdimvoid Output::endMapping() { 480344779Sdim // If we did not map anything, we should explicitly emit an empty map 481344779Sdim if (StateStack.back() == inMapFirstKey) 482344779Sdim output("{}"); 483249259Sdim StateStack.pop_back(); 484249259Sdim} 485249259Sdim 486314564Sdimstd::vector<StringRef> Output::keys() { 487314564Sdim report_fatal_error("invalid call"); 488314564Sdim} 489314564Sdim 490249259Sdimbool Output::preflightKey(const char *Key, bool Required, bool SameAsDefault, 491249259Sdim bool &UseDefault, void *&) { 492249259Sdim UseDefault = false; 493321369Sdim if (Required || !SameAsDefault || WriteDefaultValues) { 494288943Sdim auto State = StateStack.back(); 495288943Sdim if (State == inFlowMapFirstKey || State == inFlowMapOtherKey) { 496288943Sdim flowKey(Key); 497288943Sdim } else { 498344779Sdim newLineCheck(); 499344779Sdim paddedKey(Key); 500288943Sdim } 501249259Sdim return true; 502249259Sdim } 503249259Sdim return false; 504249259Sdim} 505249259Sdim 506249259Sdimvoid Output::postflightKey(void *) { 507249259Sdim if (StateStack.back() == inMapFirstKey) { 508249259Sdim StateStack.pop_back(); 509249259Sdim StateStack.push_back(inMapOtherKey); 510288943Sdim } else if (StateStack.back() == inFlowMapFirstKey) { 511288943Sdim StateStack.pop_back(); 512288943Sdim StateStack.push_back(inFlowMapOtherKey); 513249259Sdim } 514249259Sdim} 515249259Sdim 516288943Sdimvoid Output::beginFlowMapping() { 517288943Sdim StateStack.push_back(inFlowMapFirstKey); 518344779Sdim newLineCheck(); 519288943Sdim ColumnAtMapFlowStart = Column; 520288943Sdim output("{ "); 521288943Sdim} 522288943Sdim 523288943Sdimvoid Output::endFlowMapping() { 524288943Sdim StateStack.pop_back(); 525344779Sdim outputUpToEndOfLine(" }"); 526288943Sdim} 527288943Sdim 528249259Sdimvoid Output::beginDocuments() { 529344779Sdim outputUpToEndOfLine("---"); 530249259Sdim} 531249259Sdim 532249259Sdimbool Output::preflightDocument(unsigned index) { 533249259Sdim if (index > 0) 534344779Sdim outputUpToEndOfLine("\n---"); 535249259Sdim return true; 536249259Sdim} 537249259Sdim 538249259Sdimvoid Output::postflightDocument() { 539249259Sdim} 540249259Sdim 541249259Sdimvoid Output::endDocuments() { 542249259Sdim output("\n...\n"); 543249259Sdim} 544249259Sdim 545249259Sdimunsigned Output::beginSequence() { 546344779Sdim StateStack.push_back(inSeqFirstElement); 547249259Sdim NeedsNewLine = true; 548249259Sdim return 0; 549249259Sdim} 550249259Sdim 551249259Sdimvoid Output::endSequence() { 552344779Sdim // If we did not emit anything, we should explicitly emit an empty sequence 553344779Sdim if (StateStack.back() == inSeqFirstElement) 554344779Sdim output("[]"); 555249259Sdim StateStack.pop_back(); 556249259Sdim} 557249259Sdim 558249259Sdimbool Output::preflightElement(unsigned, void *&) { 559249259Sdim return true; 560249259Sdim} 561249259Sdim 562249259Sdimvoid Output::postflightElement(void *) { 563344779Sdim if (StateStack.back() == inSeqFirstElement) { 564344779Sdim StateStack.pop_back(); 565344779Sdim StateStack.push_back(inSeqOtherElement); 566344779Sdim } else if (StateStack.back() == inFlowSeqFirstElement) { 567344779Sdim StateStack.pop_back(); 568344779Sdim StateStack.push_back(inFlowSeqOtherElement); 569344779Sdim } 570249259Sdim} 571249259Sdim 572249259Sdimunsigned Output::beginFlowSequence() { 573344779Sdim StateStack.push_back(inFlowSeqFirstElement); 574344779Sdim newLineCheck(); 575249259Sdim ColumnAtFlowStart = Column; 576249259Sdim output("[ "); 577249259Sdim NeedFlowSequenceComma = false; 578249259Sdim return 0; 579249259Sdim} 580249259Sdim 581249259Sdimvoid Output::endFlowSequence() { 582249259Sdim StateStack.pop_back(); 583344779Sdim outputUpToEndOfLine(" ]"); 584249259Sdim} 585249259Sdim 586249259Sdimbool Output::preflightFlowElement(unsigned, void *&) { 587249259Sdim if (NeedFlowSequenceComma) 588249259Sdim output(", "); 589288943Sdim if (WrapColumn && Column > WrapColumn) { 590249259Sdim output("\n"); 591249259Sdim for (int i = 0; i < ColumnAtFlowStart; ++i) 592249259Sdim output(" "); 593249259Sdim Column = ColumnAtFlowStart; 594249259Sdim output(" "); 595249259Sdim } 596249259Sdim return true; 597249259Sdim} 598249259Sdim 599249259Sdimvoid Output::postflightFlowElement(void *) { 600249259Sdim NeedFlowSequenceComma = true; 601249259Sdim} 602249259Sdim 603249259Sdimvoid Output::beginEnumScalar() { 604249259Sdim EnumerationMatchFound = false; 605249259Sdim} 606249259Sdim 607249259Sdimbool Output::matchEnumScalar(const char *Str, bool Match) { 608249259Sdim if (Match && !EnumerationMatchFound) { 609344779Sdim newLineCheck(); 610344779Sdim outputUpToEndOfLine(Str); 611249259Sdim EnumerationMatchFound = true; 612249259Sdim } 613249259Sdim return false; 614249259Sdim} 615249259Sdim 616288943Sdimbool Output::matchEnumFallback() { 617288943Sdim if (EnumerationMatchFound) 618288943Sdim return false; 619288943Sdim EnumerationMatchFound = true; 620288943Sdim return true; 621288943Sdim} 622288943Sdim 623249259Sdimvoid Output::endEnumScalar() { 624249259Sdim if (!EnumerationMatchFound) 625249259Sdim llvm_unreachable("bad runtime enum value"); 626249259Sdim} 627249259Sdim 628249259Sdimbool Output::beginBitSetScalar(bool &DoClear) { 629344779Sdim newLineCheck(); 630249259Sdim output("[ "); 631249259Sdim NeedBitValueComma = false; 632249259Sdim DoClear = false; 633249259Sdim return true; 634249259Sdim} 635249259Sdim 636249259Sdimbool Output::bitSetMatch(const char *Str, bool Matches) { 637249259Sdim if (Matches) { 638249259Sdim if (NeedBitValueComma) 639249259Sdim output(", "); 640344779Sdim output(Str); 641249259Sdim NeedBitValueComma = true; 642249259Sdim } 643249259Sdim return false; 644249259Sdim} 645249259Sdim 646249259Sdimvoid Output::endBitSetScalar() { 647344779Sdim outputUpToEndOfLine(" ]"); 648249259Sdim} 649249259Sdim 650327952Sdimvoid Output::scalarString(StringRef &S, QuotingType MustQuote) { 651344779Sdim newLineCheck(); 652261991Sdim if (S.empty()) { 653261991Sdim // Print '' for the empty string because leaving the field empty is not 654261991Sdim // allowed. 655344779Sdim outputUpToEndOfLine("''"); 656261991Sdim return; 657261991Sdim } 658327952Sdim if (MustQuote == QuotingType::None) { 659276479Sdim // Only quote if we must. 660344779Sdim outputUpToEndOfLine(S); 661249259Sdim return; 662249259Sdim } 663327952Sdim 664249259Sdim unsigned i = 0; 665249259Sdim unsigned j = 0; 666249259Sdim unsigned End = S.size(); 667249259Sdim const char *Base = S.data(); 668327952Sdim 669327952Sdim const char *const Quote = MustQuote == QuotingType::Single ? "'" : "\""; 670327952Sdim output(Quote); // Starting quote. 671327952Sdim 672341825Sdim // When using double-quoted strings (and only in that case), non-printable characters may be 673341825Sdim // present, and will be escaped using a variety of unicode-scalar and special short-form 674341825Sdim // escapes. This is handled in yaml::escape. 675341825Sdim if (MustQuote == QuotingType::Double) { 676341825Sdim output(yaml::escape(Base, /* EscapePrintable= */ false)); 677344779Sdim outputUpToEndOfLine(Quote); 678341825Sdim return; 679341825Sdim } 680341825Sdim 681341825Sdim // When using single-quoted strings, any single quote ' must be doubled to be escaped. 682249259Sdim while (j < End) { 683341825Sdim if (S[j] == '\'') { // Escape quotes. 684341825Sdim output(StringRef(&Base[i], j - i)); // "flush". 685341825Sdim output(StringLiteral("''")); // Print it as '' 686249259Sdim i = j + 1; 687249259Sdim } 688249259Sdim ++j; 689249259Sdim } 690249259Sdim output(StringRef(&Base[i], j - i)); 691344779Sdim outputUpToEndOfLine(Quote); // Ending quote. 692249259Sdim} 693249259Sdim 694288943Sdimvoid Output::blockScalarString(StringRef &S) { 695288943Sdim if (!StateStack.empty()) 696288943Sdim newLineCheck(); 697288943Sdim output(" |"); 698288943Sdim outputNewLine(); 699288943Sdim 700288943Sdim unsigned Indent = StateStack.empty() ? 1 : StateStack.size(); 701288943Sdim 702288943Sdim auto Buffer = MemoryBuffer::getMemBuffer(S, "", false); 703288943Sdim for (line_iterator Lines(*Buffer, false); !Lines.is_at_end(); ++Lines) { 704288943Sdim for (unsigned I = 0; I < Indent; ++I) { 705288943Sdim output(" "); 706288943Sdim } 707288943Sdim output(*Lines); 708288943Sdim outputNewLine(); 709288943Sdim } 710288943Sdim} 711288943Sdim 712344779Sdimvoid Output::scalarTag(std::string &Tag) { 713344779Sdim if (Tag.empty()) 714344779Sdim return; 715344779Sdim newLineCheck(); 716344779Sdim output(Tag); 717344779Sdim output(" "); 718344779Sdim} 719344779Sdim 720249259Sdimvoid Output::setError(const Twine &message) { 721249259Sdim} 722249259Sdim 723261991Sdimbool Output::canElideEmptySequence() { 724261991Sdim // Normally, with an optional key/value where the value is an empty sequence, 725261991Sdim // the whole key/value can be not written. But, that produces wrong yaml 726261991Sdim // if the key/value is the only thing in the map and the map is used in 727261991Sdim // a sequence. This detects if the this sequence is the first key/value 728261991Sdim // in map that itself is embedded in a sequnce. 729261991Sdim if (StateStack.size() < 2) 730261991Sdim return true; 731261991Sdim if (StateStack.back() != inMapFirstKey) 732261991Sdim return true; 733344779Sdim return !inSeqAnyElement(StateStack[StateStack.size() - 2]); 734261991Sdim} 735261991Sdim 736249259Sdimvoid Output::output(StringRef s) { 737249259Sdim Column += s.size(); 738249259Sdim Out << s; 739249259Sdim} 740249259Sdim 741249259Sdimvoid Output::outputUpToEndOfLine(StringRef s) { 742344779Sdim output(s); 743344779Sdim if (StateStack.empty() || (!inFlowSeqAnyElement(StateStack.back()) && 744344779Sdim !inFlowMapAnyKey(StateStack.back()))) 745249259Sdim NeedsNewLine = true; 746249259Sdim} 747249259Sdim 748249259Sdimvoid Output::outputNewLine() { 749249259Sdim Out << "\n"; 750249259Sdim Column = 0; 751249259Sdim} 752249259Sdim 753249259Sdim// if seq at top, indent as if map, then add "- " 754249259Sdim// if seq in middle, use "- " if firstKey, else use " " 755249259Sdim// 756249259Sdim 757249259Sdimvoid Output::newLineCheck() { 758249259Sdim if (!NeedsNewLine) 759249259Sdim return; 760249259Sdim NeedsNewLine = false; 761249259Sdim 762344779Sdim outputNewLine(); 763249259Sdim 764344779Sdim if (StateStack.size() == 0) 765344779Sdim return; 766344779Sdim 767249259Sdim unsigned Indent = StateStack.size() - 1; 768249259Sdim bool OutputDash = false; 769249259Sdim 770344779Sdim if (StateStack.back() == inSeqFirstElement || 771344779Sdim StateStack.back() == inSeqOtherElement) { 772249259Sdim OutputDash = true; 773344779Sdim } else if ((StateStack.size() > 1) && 774344779Sdim ((StateStack.back() == inMapFirstKey) || 775344779Sdim inFlowSeqAnyElement(StateStack.back()) || 776344779Sdim (StateStack.back() == inFlowMapFirstKey)) && 777344779Sdim inSeqAnyElement(StateStack[StateStack.size() - 2])) { 778249259Sdim --Indent; 779249259Sdim OutputDash = true; 780249259Sdim } 781249259Sdim 782249259Sdim for (unsigned i = 0; i < Indent; ++i) { 783249259Sdim output(" "); 784249259Sdim } 785249259Sdim if (OutputDash) { 786249259Sdim output("- "); 787249259Sdim } 788249259Sdim 789249259Sdim} 790249259Sdim 791249259Sdimvoid Output::paddedKey(StringRef key) { 792249259Sdim output(key); 793249259Sdim output(":"); 794249259Sdim const char *spaces = " "; 795249259Sdim if (key.size() < strlen(spaces)) 796249259Sdim output(&spaces[key.size()]); 797249259Sdim else 798249259Sdim output(" "); 799249259Sdim} 800249259Sdim 801288943Sdimvoid Output::flowKey(StringRef Key) { 802288943Sdim if (StateStack.back() == inFlowMapOtherKey) 803288943Sdim output(", "); 804288943Sdim if (WrapColumn && Column > WrapColumn) { 805288943Sdim output("\n"); 806288943Sdim for (int I = 0; I < ColumnAtMapFlowStart; ++I) 807288943Sdim output(" "); 808288943Sdim Column = ColumnAtMapFlowStart; 809288943Sdim output(" "); 810288943Sdim } 811288943Sdim output(Key); 812288943Sdim output(": "); 813288943Sdim} 814288943Sdim 815344779SdimNodeKind Output::getNodeKind() { report_fatal_error("invalid call"); } 816344779Sdim 817344779Sdimbool Output::inSeqAnyElement(InState State) { 818344779Sdim return State == inSeqFirstElement || State == inSeqOtherElement; 819344779Sdim} 820344779Sdim 821344779Sdimbool Output::inFlowSeqAnyElement(InState State) { 822344779Sdim return State == inFlowSeqFirstElement || State == inFlowSeqOtherElement; 823344779Sdim} 824344779Sdim 825344779Sdimbool Output::inMapAnyKey(InState State) { 826344779Sdim return State == inMapFirstKey || State == inMapOtherKey; 827344779Sdim} 828344779Sdim 829344779Sdimbool Output::inFlowMapAnyKey(InState State) { 830344779Sdim return State == inFlowMapFirstKey || State == inFlowMapOtherKey; 831344779Sdim} 832344779Sdim 833249259Sdim//===----------------------------------------------------------------------===// 834249259Sdim// traits for built-in types 835249259Sdim//===----------------------------------------------------------------------===// 836249259Sdim 837249259Sdimvoid ScalarTraits<bool>::output(const bool &Val, void *, raw_ostream &Out) { 838249259Sdim Out << (Val ? "true" : "false"); 839249259Sdim} 840249259Sdim 841249259SdimStringRef ScalarTraits<bool>::input(StringRef Scalar, void *, bool &Val) { 842249259Sdim if (Scalar.equals("true")) { 843249259Sdim Val = true; 844249259Sdim return StringRef(); 845249259Sdim } else if (Scalar.equals("false")) { 846249259Sdim Val = false; 847249259Sdim return StringRef(); 848249259Sdim } 849249259Sdim return "invalid boolean"; 850249259Sdim} 851249259Sdim 852249259Sdimvoid ScalarTraits<StringRef>::output(const StringRef &Val, void *, 853249259Sdim raw_ostream &Out) { 854249259Sdim Out << Val; 855249259Sdim} 856249259Sdim 857249259SdimStringRef ScalarTraits<StringRef>::input(StringRef Scalar, void *, 858249259Sdim StringRef &Val) { 859249259Sdim Val = Scalar; 860249259Sdim return StringRef(); 861249259Sdim} 862288943Sdim 863276479Sdimvoid ScalarTraits<std::string>::output(const std::string &Val, void *, 864276479Sdim raw_ostream &Out) { 865276479Sdim Out << Val; 866276479Sdim} 867249259Sdim 868276479SdimStringRef ScalarTraits<std::string>::input(StringRef Scalar, void *, 869276479Sdim std::string &Val) { 870276479Sdim Val = Scalar.str(); 871276479Sdim return StringRef(); 872276479Sdim} 873276479Sdim 874249259Sdimvoid ScalarTraits<uint8_t>::output(const uint8_t &Val, void *, 875249259Sdim raw_ostream &Out) { 876249259Sdim // use temp uin32_t because ostream thinks uint8_t is a character 877249259Sdim uint32_t Num = Val; 878249259Sdim Out << Num; 879249259Sdim} 880249259Sdim 881249259SdimStringRef ScalarTraits<uint8_t>::input(StringRef Scalar, void *, uint8_t &Val) { 882249259Sdim unsigned long long n; 883249259Sdim if (getAsUnsignedInteger(Scalar, 0, n)) 884249259Sdim return "invalid number"; 885249259Sdim if (n > 0xFF) 886249259Sdim return "out of range number"; 887249259Sdim Val = n; 888249259Sdim return StringRef(); 889249259Sdim} 890249259Sdim 891249259Sdimvoid ScalarTraits<uint16_t>::output(const uint16_t &Val, void *, 892249259Sdim raw_ostream &Out) { 893249259Sdim Out << Val; 894249259Sdim} 895249259Sdim 896249259SdimStringRef ScalarTraits<uint16_t>::input(StringRef Scalar, void *, 897249259Sdim uint16_t &Val) { 898249259Sdim unsigned long long n; 899249259Sdim if (getAsUnsignedInteger(Scalar, 0, n)) 900249259Sdim return "invalid number"; 901249259Sdim if (n > 0xFFFF) 902249259Sdim return "out of range number"; 903249259Sdim Val = n; 904249259Sdim return StringRef(); 905249259Sdim} 906249259Sdim 907249259Sdimvoid ScalarTraits<uint32_t>::output(const uint32_t &Val, void *, 908249259Sdim raw_ostream &Out) { 909249259Sdim Out << Val; 910249259Sdim} 911249259Sdim 912249259SdimStringRef ScalarTraits<uint32_t>::input(StringRef Scalar, void *, 913249259Sdim uint32_t &Val) { 914249259Sdim unsigned long long n; 915249259Sdim if (getAsUnsignedInteger(Scalar, 0, n)) 916249259Sdim return "invalid number"; 917249259Sdim if (n > 0xFFFFFFFFUL) 918249259Sdim return "out of range number"; 919249259Sdim Val = n; 920249259Sdim return StringRef(); 921249259Sdim} 922249259Sdim 923249259Sdimvoid ScalarTraits<uint64_t>::output(const uint64_t &Val, void *, 924249259Sdim raw_ostream &Out) { 925249259Sdim Out << Val; 926249259Sdim} 927249259Sdim 928249259SdimStringRef ScalarTraits<uint64_t>::input(StringRef Scalar, void *, 929249259Sdim uint64_t &Val) { 930249259Sdim unsigned long long N; 931249259Sdim if (getAsUnsignedInteger(Scalar, 0, N)) 932249259Sdim return "invalid number"; 933249259Sdim Val = N; 934249259Sdim return StringRef(); 935249259Sdim} 936249259Sdim 937249259Sdimvoid ScalarTraits<int8_t>::output(const int8_t &Val, void *, raw_ostream &Out) { 938249259Sdim // use temp in32_t because ostream thinks int8_t is a character 939249259Sdim int32_t Num = Val; 940249259Sdim Out << Num; 941249259Sdim} 942249259Sdim 943249259SdimStringRef ScalarTraits<int8_t>::input(StringRef Scalar, void *, int8_t &Val) { 944249259Sdim long long N; 945249259Sdim if (getAsSignedInteger(Scalar, 0, N)) 946249259Sdim return "invalid number"; 947249259Sdim if ((N > 127) || (N < -128)) 948249259Sdim return "out of range number"; 949249259Sdim Val = N; 950249259Sdim return StringRef(); 951249259Sdim} 952249259Sdim 953249259Sdimvoid ScalarTraits<int16_t>::output(const int16_t &Val, void *, 954249259Sdim raw_ostream &Out) { 955249259Sdim Out << Val; 956249259Sdim} 957249259Sdim 958249259SdimStringRef ScalarTraits<int16_t>::input(StringRef Scalar, void *, int16_t &Val) { 959249259Sdim long long N; 960249259Sdim if (getAsSignedInteger(Scalar, 0, N)) 961249259Sdim return "invalid number"; 962249259Sdim if ((N > INT16_MAX) || (N < INT16_MIN)) 963249259Sdim return "out of range number"; 964249259Sdim Val = N; 965249259Sdim return StringRef(); 966249259Sdim} 967249259Sdim 968249259Sdimvoid ScalarTraits<int32_t>::output(const int32_t &Val, void *, 969249259Sdim raw_ostream &Out) { 970249259Sdim Out << Val; 971249259Sdim} 972249259Sdim 973249259SdimStringRef ScalarTraits<int32_t>::input(StringRef Scalar, void *, int32_t &Val) { 974249259Sdim long long N; 975249259Sdim if (getAsSignedInteger(Scalar, 0, N)) 976249259Sdim return "invalid number"; 977249259Sdim if ((N > INT32_MAX) || (N < INT32_MIN)) 978249259Sdim return "out of range number"; 979249259Sdim Val = N; 980249259Sdim return StringRef(); 981249259Sdim} 982249259Sdim 983249259Sdimvoid ScalarTraits<int64_t>::output(const int64_t &Val, void *, 984249259Sdim raw_ostream &Out) { 985249259Sdim Out << Val; 986249259Sdim} 987249259Sdim 988249259SdimStringRef ScalarTraits<int64_t>::input(StringRef Scalar, void *, int64_t &Val) { 989249259Sdim long long N; 990249259Sdim if (getAsSignedInteger(Scalar, 0, N)) 991249259Sdim return "invalid number"; 992249259Sdim Val = N; 993249259Sdim return StringRef(); 994249259Sdim} 995249259Sdim 996249259Sdimvoid ScalarTraits<double>::output(const double &Val, void *, raw_ostream &Out) { 997249259Sdim Out << format("%g", Val); 998249259Sdim} 999249259Sdim 1000249259SdimStringRef ScalarTraits<double>::input(StringRef Scalar, void *, double &Val) { 1001321369Sdim if (to_float(Scalar, Val)) 1002321369Sdim return StringRef(); 1003321369Sdim return "invalid floating point number"; 1004249259Sdim} 1005249259Sdim 1006249259Sdimvoid ScalarTraits<float>::output(const float &Val, void *, raw_ostream &Out) { 1007249259Sdim Out << format("%g", Val); 1008249259Sdim} 1009249259Sdim 1010249259SdimStringRef ScalarTraits<float>::input(StringRef Scalar, void *, float &Val) { 1011321369Sdim if (to_float(Scalar, Val)) 1012321369Sdim return StringRef(); 1013321369Sdim return "invalid floating point number"; 1014249259Sdim} 1015249259Sdim 1016249259Sdimvoid ScalarTraits<Hex8>::output(const Hex8 &Val, void *, raw_ostream &Out) { 1017249259Sdim uint8_t Num = Val; 1018249259Sdim Out << format("0x%02X", Num); 1019249259Sdim} 1020249259Sdim 1021249259SdimStringRef ScalarTraits<Hex8>::input(StringRef Scalar, void *, Hex8 &Val) { 1022249259Sdim unsigned long long n; 1023249259Sdim if (getAsUnsignedInteger(Scalar, 0, n)) 1024249259Sdim return "invalid hex8 number"; 1025249259Sdim if (n > 0xFF) 1026249259Sdim return "out of range hex8 number"; 1027249259Sdim Val = n; 1028249259Sdim return StringRef(); 1029249259Sdim} 1030249259Sdim 1031249259Sdimvoid ScalarTraits<Hex16>::output(const Hex16 &Val, void *, raw_ostream &Out) { 1032249259Sdim uint16_t Num = Val; 1033249259Sdim Out << format("0x%04X", Num); 1034249259Sdim} 1035249259Sdim 1036249259SdimStringRef ScalarTraits<Hex16>::input(StringRef Scalar, void *, Hex16 &Val) { 1037249259Sdim unsigned long long n; 1038249259Sdim if (getAsUnsignedInteger(Scalar, 0, n)) 1039249259Sdim return "invalid hex16 number"; 1040249259Sdim if (n > 0xFFFF) 1041249259Sdim return "out of range hex16 number"; 1042249259Sdim Val = n; 1043249259Sdim return StringRef(); 1044249259Sdim} 1045249259Sdim 1046249259Sdimvoid ScalarTraits<Hex32>::output(const Hex32 &Val, void *, raw_ostream &Out) { 1047249259Sdim uint32_t Num = Val; 1048249259Sdim Out << format("0x%08X", Num); 1049249259Sdim} 1050249259Sdim 1051249259SdimStringRef ScalarTraits<Hex32>::input(StringRef Scalar, void *, Hex32 &Val) { 1052249259Sdim unsigned long long n; 1053249259Sdim if (getAsUnsignedInteger(Scalar, 0, n)) 1054249259Sdim return "invalid hex32 number"; 1055249259Sdim if (n > 0xFFFFFFFFUL) 1056249259Sdim return "out of range hex32 number"; 1057249259Sdim Val = n; 1058249259Sdim return StringRef(); 1059249259Sdim} 1060249259Sdim 1061249259Sdimvoid ScalarTraits<Hex64>::output(const Hex64 &Val, void *, raw_ostream &Out) { 1062249259Sdim uint64_t Num = Val; 1063249259Sdim Out << format("0x%016llX", Num); 1064249259Sdim} 1065249259Sdim 1066249259SdimStringRef ScalarTraits<Hex64>::input(StringRef Scalar, void *, Hex64 &Val) { 1067249259Sdim unsigned long long Num; 1068249259Sdim if (getAsUnsignedInteger(Scalar, 0, Num)) 1069249259Sdim return "invalid hex64 number"; 1070249259Sdim Val = Num; 1071249259Sdim return StringRef(); 1072249259Sdim} 1073