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