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