1//===- lib/Support/YAMLTraits.cpp -----------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "llvm/Support/YAMLTraits.h"
10#include "llvm/ADT/STLExtras.h"
11#include "llvm/ADT/SmallString.h"
12#include "llvm/ADT/StringExtras.h"
13#include "llvm/ADT/StringRef.h"
14#include "llvm/ADT/Twine.h"
15#include "llvm/Support/Casting.h"
16#include "llvm/Support/Errc.h"
17#include "llvm/Support/ErrorHandling.h"
18#include "llvm/Support/Format.h"
19#include "llvm/Support/LineIterator.h"
20#include "llvm/Support/MemoryBuffer.h"
21#include "llvm/Support/VersionTuple.h"
22#include "llvm/Support/YAMLParser.h"
23#include "llvm/Support/raw_ostream.h"
24#include <algorithm>
25#include <cassert>
26#include <cstdint>
27#include <cstring>
28#include <string>
29#include <vector>
30
31using namespace llvm;
32using namespace yaml;
33
34//===----------------------------------------------------------------------===//
35//  IO
36//===----------------------------------------------------------------------===//
37
38IO::IO(void *Context) : Ctxt(Context) {}
39
40IO::~IO() = default;
41
42void *IO::getContext() const {
43  return Ctxt;
44}
45
46void IO::setContext(void *Context) {
47  Ctxt = Context;
48}
49
50void IO::setAllowUnknownKeys(bool Allow) {
51  llvm_unreachable("Only supported for Input");
52}
53
54//===----------------------------------------------------------------------===//
55//  Input
56//===----------------------------------------------------------------------===//
57
58Input::Input(StringRef InputContent, void *Ctxt,
59             SourceMgr::DiagHandlerTy DiagHandler, void *DiagHandlerCtxt)
60    : IO(Ctxt), Strm(new Stream(InputContent, SrcMgr, false, &EC)) {
61  if (DiagHandler)
62    SrcMgr.setDiagHandler(DiagHandler, DiagHandlerCtxt);
63  DocIterator = Strm->begin();
64}
65
66Input::Input(MemoryBufferRef Input, void *Ctxt,
67             SourceMgr::DiagHandlerTy DiagHandler, void *DiagHandlerCtxt)
68    : IO(Ctxt), Strm(new Stream(Input, SrcMgr, false, &EC)) {
69  if (DiagHandler)
70    SrcMgr.setDiagHandler(DiagHandler, DiagHandlerCtxt);
71  DocIterator = Strm->begin();
72}
73
74Input::~Input() = default;
75
76std::error_code Input::error() { return EC; }
77
78bool Input::outputting() const {
79  return false;
80}
81
82bool Input::setCurrentDocument() {
83  if (DocIterator != Strm->end()) {
84    Node *N = DocIterator->getRoot();
85    if (!N) {
86      EC = make_error_code(errc::invalid_argument);
87      return false;
88    }
89
90    if (isa<NullNode>(N)) {
91      // Empty files are allowed and ignored
92      ++DocIterator;
93      return setCurrentDocument();
94    }
95    releaseHNodeBuffers();
96    TopNode = createHNodes(N);
97    CurrentNode = TopNode;
98    return true;
99  }
100  return false;
101}
102
103bool Input::nextDocument() {
104  return ++DocIterator != Strm->end();
105}
106
107const Node *Input::getCurrentNode() const {
108  return CurrentNode ? CurrentNode->_node : nullptr;
109}
110
111bool Input::mapTag(StringRef Tag, bool Default) {
112  // CurrentNode can be null if setCurrentDocument() was unable to
113  // parse the document because it was invalid or empty.
114  if (!CurrentNode)
115    return false;
116
117  std::string foundTag = CurrentNode->_node->getVerbatimTag();
118  if (foundTag.empty()) {
119    // If no tag found and 'Tag' is the default, say it was found.
120    return Default;
121  }
122  // Return true iff found tag matches supplied tag.
123  return Tag.equals(foundTag);
124}
125
126void Input::beginMapping() {
127  if (EC)
128    return;
129  // CurrentNode can be null if the document is empty.
130  MapHNode *MN = dyn_cast_or_null<MapHNode>(CurrentNode);
131  if (MN) {
132    MN->ValidKeys.clear();
133  }
134}
135
136std::vector<StringRef> Input::keys() {
137  MapHNode *MN = dyn_cast<MapHNode>(CurrentNode);
138  std::vector<StringRef> Ret;
139  if (!MN) {
140    setError(CurrentNode, "not a mapping");
141    return Ret;
142  }
143  for (auto &P : MN->Mapping)
144    Ret.push_back(P.first());
145  return Ret;
146}
147
148bool Input::preflightKey(const char *Key, bool Required, bool, bool &UseDefault,
149                         void *&SaveInfo) {
150  UseDefault = false;
151  if (EC)
152    return false;
153
154  // CurrentNode is null for empty documents, which is an error in case required
155  // nodes are present.
156  if (!CurrentNode) {
157    if (Required)
158      EC = make_error_code(errc::invalid_argument);
159    else
160      UseDefault = true;
161    return false;
162  }
163
164  MapHNode *MN = dyn_cast<MapHNode>(CurrentNode);
165  if (!MN) {
166    if (Required || !isa<EmptyHNode>(CurrentNode))
167      setError(CurrentNode, "not a mapping");
168    else
169      UseDefault = true;
170    return false;
171  }
172  MN->ValidKeys.push_back(Key);
173  HNode *Value = MN->Mapping[Key].first;
174  if (!Value) {
175    if (Required)
176      setError(CurrentNode, Twine("missing required key '") + Key + "'");
177    else
178      UseDefault = true;
179    return false;
180  }
181  SaveInfo = CurrentNode;
182  CurrentNode = Value;
183  return true;
184}
185
186void Input::postflightKey(void *saveInfo) {
187  CurrentNode = reinterpret_cast<HNode *>(saveInfo);
188}
189
190void Input::endMapping() {
191  if (EC)
192    return;
193  // CurrentNode can be null if the document is empty.
194  MapHNode *MN = dyn_cast_or_null<MapHNode>(CurrentNode);
195  if (!MN)
196    return;
197  for (const auto &NN : MN->Mapping) {
198    if (!is_contained(MN->ValidKeys, NN.first())) {
199      const SMRange &ReportLoc = NN.second.second;
200      if (!AllowUnknownKeys) {
201        setError(ReportLoc, Twine("unknown key '") + NN.first() + "'");
202        break;
203      } else
204        reportWarning(ReportLoc, Twine("unknown key '") + NN.first() + "'");
205    }
206  }
207}
208
209void Input::beginFlowMapping() { beginMapping(); }
210
211void Input::endFlowMapping() { endMapping(); }
212
213unsigned Input::beginSequence() {
214  if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode))
215    return SQ->Entries.size();
216  if (isa<EmptyHNode>(CurrentNode))
217    return 0;
218  // Treat case where there's a scalar "null" value as an empty sequence.
219  if (ScalarHNode *SN = dyn_cast<ScalarHNode>(CurrentNode)) {
220    if (isNull(SN->value()))
221      return 0;
222  }
223  // Any other type of HNode is an error.
224  setError(CurrentNode, "not a sequence");
225  return 0;
226}
227
228void Input::endSequence() {
229}
230
231bool Input::preflightElement(unsigned Index, void *&SaveInfo) {
232  if (EC)
233    return false;
234  if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) {
235    SaveInfo = CurrentNode;
236    CurrentNode = SQ->Entries[Index];
237    return true;
238  }
239  return false;
240}
241
242void Input::postflightElement(void *SaveInfo) {
243  CurrentNode = reinterpret_cast<HNode *>(SaveInfo);
244}
245
246unsigned Input::beginFlowSequence() { return beginSequence(); }
247
248bool Input::preflightFlowElement(unsigned index, void *&SaveInfo) {
249  if (EC)
250    return false;
251  if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) {
252    SaveInfo = CurrentNode;
253    CurrentNode = SQ->Entries[index];
254    return true;
255  }
256  return false;
257}
258
259void Input::postflightFlowElement(void *SaveInfo) {
260  CurrentNode = reinterpret_cast<HNode *>(SaveInfo);
261}
262
263void Input::endFlowSequence() {
264}
265
266void Input::beginEnumScalar() {
267  ScalarMatchFound = false;
268}
269
270bool Input::matchEnumScalar(const char *Str, bool) {
271  if (ScalarMatchFound)
272    return false;
273  if (ScalarHNode *SN = dyn_cast<ScalarHNode>(CurrentNode)) {
274    if (SN->value().equals(Str)) {
275      ScalarMatchFound = true;
276      return true;
277    }
278  }
279  return false;
280}
281
282bool Input::matchEnumFallback() {
283  if (ScalarMatchFound)
284    return false;
285  ScalarMatchFound = true;
286  return true;
287}
288
289void Input::endEnumScalar() {
290  if (!ScalarMatchFound) {
291    setError(CurrentNode, "unknown enumerated scalar");
292  }
293}
294
295bool Input::beginBitSetScalar(bool &DoClear) {
296  BitValuesUsed.clear();
297  if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) {
298    BitValuesUsed.resize(SQ->Entries.size());
299  } else {
300    setError(CurrentNode, "expected sequence of bit values");
301  }
302  DoClear = true;
303  return true;
304}
305
306bool Input::bitSetMatch(const char *Str, bool) {
307  if (EC)
308    return false;
309  if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) {
310    unsigned Index = 0;
311    for (auto &N : SQ->Entries) {
312      if (ScalarHNode *SN = dyn_cast<ScalarHNode>(N)) {
313        if (SN->value().equals(Str)) {
314          BitValuesUsed[Index] = true;
315          return true;
316        }
317      } else {
318        setError(CurrentNode, "unexpected scalar in sequence of bit values");
319      }
320      ++Index;
321    }
322  } else {
323    setError(CurrentNode, "expected sequence of bit values");
324  }
325  return false;
326}
327
328void Input::endBitSetScalar() {
329  if (EC)
330    return;
331  if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) {
332    assert(BitValuesUsed.size() == SQ->Entries.size());
333    for (unsigned i = 0; i < SQ->Entries.size(); ++i) {
334      if (!BitValuesUsed[i]) {
335        setError(SQ->Entries[i], "unknown bit value");
336        return;
337      }
338    }
339  }
340}
341
342void Input::scalarString(StringRef &S, QuotingType) {
343  if (ScalarHNode *SN = dyn_cast<ScalarHNode>(CurrentNode)) {
344    S = SN->value();
345  } else {
346    setError(CurrentNode, "unexpected scalar");
347  }
348}
349
350void Input::blockScalarString(StringRef &S) { scalarString(S, QuotingType::None); }
351
352void Input::scalarTag(std::string &Tag) {
353  Tag = CurrentNode->_node->getVerbatimTag();
354}
355
356void Input::setError(HNode *hnode, const Twine &message) {
357  assert(hnode && "HNode must not be NULL");
358  setError(hnode->_node, message);
359}
360
361NodeKind Input::getNodeKind() {
362  if (isa<ScalarHNode>(CurrentNode))
363    return NodeKind::Scalar;
364  else if (isa<MapHNode>(CurrentNode))
365    return NodeKind::Map;
366  else if (isa<SequenceHNode>(CurrentNode))
367    return NodeKind::Sequence;
368  llvm_unreachable("Unsupported node kind");
369}
370
371void Input::setError(Node *node, const Twine &message) {
372  Strm->printError(node, message);
373  EC = make_error_code(errc::invalid_argument);
374}
375
376void Input::setError(const SMRange &range, const Twine &message) {
377  Strm->printError(range, message);
378  EC = make_error_code(errc::invalid_argument);
379}
380
381void Input::reportWarning(HNode *hnode, const Twine &message) {
382  assert(hnode && "HNode must not be NULL");
383  Strm->printError(hnode->_node, message, SourceMgr::DK_Warning);
384}
385
386void Input::reportWarning(Node *node, const Twine &message) {
387  Strm->printError(node, message, SourceMgr::DK_Warning);
388}
389
390void Input::reportWarning(const SMRange &range, const Twine &message) {
391  Strm->printError(range, message, SourceMgr::DK_Warning);
392}
393
394void Input::releaseHNodeBuffers() {
395  EmptyHNodeAllocator.DestroyAll();
396  ScalarHNodeAllocator.DestroyAll();
397  SequenceHNodeAllocator.DestroyAll();
398  MapHNodeAllocator.DestroyAll();
399}
400
401Input::HNode *Input::createHNodes(Node *N) {
402  SmallString<128> StringStorage;
403  switch (N->getType()) {
404  case Node::NK_Scalar: {
405    ScalarNode *SN = dyn_cast<ScalarNode>(N);
406    StringRef KeyStr = SN->getValue(StringStorage);
407    if (!StringStorage.empty()) {
408      // Copy string to permanent storage
409      KeyStr = StringStorage.str().copy(StringAllocator);
410    }
411    return new (ScalarHNodeAllocator.Allocate()) ScalarHNode(N, KeyStr);
412  }
413  case Node::NK_BlockScalar: {
414    BlockScalarNode *BSN = dyn_cast<BlockScalarNode>(N);
415    StringRef ValueCopy = BSN->getValue().copy(StringAllocator);
416    return new (ScalarHNodeAllocator.Allocate()) ScalarHNode(N, ValueCopy);
417  }
418  case Node::NK_Sequence: {
419    SequenceNode *SQ = dyn_cast<SequenceNode>(N);
420    auto SQHNode = new (SequenceHNodeAllocator.Allocate()) SequenceHNode(N);
421    for (Node &SN : *SQ) {
422      auto Entry = createHNodes(&SN);
423      if (EC)
424        break;
425      SQHNode->Entries.push_back(Entry);
426    }
427    return SQHNode;
428  }
429  case Node::NK_Mapping: {
430    MappingNode *Map = dyn_cast<MappingNode>(N);
431    auto mapHNode = new (MapHNodeAllocator.Allocate()) MapHNode(N);
432    for (KeyValueNode &KVN : *Map) {
433      Node *KeyNode = KVN.getKey();
434      ScalarNode *Key = dyn_cast_or_null<ScalarNode>(KeyNode);
435      Node *Value = KVN.getValue();
436      if (!Key || !Value) {
437        if (!Key)
438          setError(KeyNode, "Map key must be a scalar");
439        if (!Value)
440          setError(KeyNode, "Map value must not be empty");
441        break;
442      }
443      StringStorage.clear();
444      StringRef KeyStr = Key->getValue(StringStorage);
445      if (!StringStorage.empty()) {
446        // Copy string to permanent storage
447        KeyStr = StringStorage.str().copy(StringAllocator);
448      }
449      if (mapHNode->Mapping.count(KeyStr))
450        // From YAML spec: "The content of a mapping node is an unordered set of
451        // key/value node pairs, with the restriction that each of the keys is
452        // unique."
453        setError(KeyNode, Twine("duplicated mapping key '") + KeyStr + "'");
454      auto ValueHNode = createHNodes(Value);
455      if (EC)
456        break;
457      mapHNode->Mapping[KeyStr] =
458          std::make_pair(std::move(ValueHNode), KeyNode->getSourceRange());
459    }
460    return std::move(mapHNode);
461  }
462  case Node::NK_Null:
463    return new (EmptyHNodeAllocator.Allocate()) EmptyHNode(N);
464  default:
465    setError(N, "unknown node kind");
466    return nullptr;
467  }
468}
469
470void Input::setError(const Twine &Message) {
471  setError(CurrentNode, Message);
472}
473
474void Input::setAllowUnknownKeys(bool Allow) { AllowUnknownKeys = Allow; }
475
476bool Input::canElideEmptySequence() {
477  return false;
478}
479
480//===----------------------------------------------------------------------===//
481//  Output
482//===----------------------------------------------------------------------===//
483
484Output::Output(raw_ostream &yout, void *context, int WrapColumn)
485    : IO(context), Out(yout), WrapColumn(WrapColumn) {}
486
487Output::~Output() = default;
488
489bool Output::outputting() const {
490  return true;
491}
492
493void Output::beginMapping() {
494  StateStack.push_back(inMapFirstKey);
495  PaddingBeforeContainer = Padding;
496  Padding = "\n";
497}
498
499bool Output::mapTag(StringRef Tag, bool Use) {
500  if (Use) {
501    // If this tag is being written inside a sequence we should write the start
502    // of the sequence before writing the tag, otherwise the tag won't be
503    // attached to the element in the sequence, but rather the sequence itself.
504    bool SequenceElement = false;
505    if (StateStack.size() > 1) {
506      auto &E = StateStack[StateStack.size() - 2];
507      SequenceElement = inSeqAnyElement(E) || inFlowSeqAnyElement(E);
508    }
509    if (SequenceElement && StateStack.back() == inMapFirstKey) {
510      newLineCheck();
511    } else {
512      output(" ");
513    }
514    output(Tag);
515    if (SequenceElement) {
516      // If we're writing the tag during the first element of a map, the tag
517      // takes the place of the first element in the sequence.
518      if (StateStack.back() == inMapFirstKey) {
519        StateStack.pop_back();
520        StateStack.push_back(inMapOtherKey);
521      }
522      // Tags inside maps in sequences should act as keys in the map from a
523      // formatting perspective, so we always want a newline in a sequence.
524      Padding = "\n";
525    }
526  }
527  return Use;
528}
529
530void Output::endMapping() {
531  // If we did not map anything, we should explicitly emit an empty map
532  if (StateStack.back() == inMapFirstKey) {
533    Padding = PaddingBeforeContainer;
534    newLineCheck();
535    output("{}");
536    Padding = "\n";
537  }
538  StateStack.pop_back();
539}
540
541std::vector<StringRef> Output::keys() {
542  report_fatal_error("invalid call");
543}
544
545bool Output::preflightKey(const char *Key, bool Required, bool SameAsDefault,
546                          bool &UseDefault, void *&SaveInfo) {
547  UseDefault = false;
548  SaveInfo = nullptr;
549  if (Required || !SameAsDefault || WriteDefaultValues) {
550    auto State = StateStack.back();
551    if (State == inFlowMapFirstKey || State == inFlowMapOtherKey) {
552      flowKey(Key);
553    } else {
554      newLineCheck();
555      paddedKey(Key);
556    }
557    return true;
558  }
559  return false;
560}
561
562void Output::postflightKey(void *) {
563  if (StateStack.back() == inMapFirstKey) {
564    StateStack.pop_back();
565    StateStack.push_back(inMapOtherKey);
566  } else if (StateStack.back() == inFlowMapFirstKey) {
567    StateStack.pop_back();
568    StateStack.push_back(inFlowMapOtherKey);
569  }
570}
571
572void Output::beginFlowMapping() {
573  StateStack.push_back(inFlowMapFirstKey);
574  newLineCheck();
575  ColumnAtMapFlowStart = Column;
576  output("{ ");
577}
578
579void Output::endFlowMapping() {
580  StateStack.pop_back();
581  outputUpToEndOfLine(" }");
582}
583
584void Output::beginDocuments() {
585  outputUpToEndOfLine("---");
586}
587
588bool Output::preflightDocument(unsigned index) {
589  if (index > 0)
590    outputUpToEndOfLine("\n---");
591  return true;
592}
593
594void Output::postflightDocument() {
595}
596
597void Output::endDocuments() {
598  output("\n...\n");
599}
600
601unsigned Output::beginSequence() {
602  StateStack.push_back(inSeqFirstElement);
603  PaddingBeforeContainer = Padding;
604  Padding = "\n";
605  return 0;
606}
607
608void Output::endSequence() {
609  // If we did not emit anything, we should explicitly emit an empty sequence
610  if (StateStack.back() == inSeqFirstElement) {
611    Padding = PaddingBeforeContainer;
612    newLineCheck(/*EmptySequence=*/true);
613    output("[]");
614    Padding = "\n";
615  }
616  StateStack.pop_back();
617}
618
619bool Output::preflightElement(unsigned, void *&SaveInfo) {
620  SaveInfo = nullptr;
621  return true;
622}
623
624void Output::postflightElement(void *) {
625  if (StateStack.back() == inSeqFirstElement) {
626    StateStack.pop_back();
627    StateStack.push_back(inSeqOtherElement);
628  } else if (StateStack.back() == inFlowSeqFirstElement) {
629    StateStack.pop_back();
630    StateStack.push_back(inFlowSeqOtherElement);
631  }
632}
633
634unsigned Output::beginFlowSequence() {
635  StateStack.push_back(inFlowSeqFirstElement);
636  newLineCheck();
637  ColumnAtFlowStart = Column;
638  output("[ ");
639  NeedFlowSequenceComma = false;
640  return 0;
641}
642
643void Output::endFlowSequence() {
644  StateStack.pop_back();
645  outputUpToEndOfLine(" ]");
646}
647
648bool Output::preflightFlowElement(unsigned, void *&SaveInfo) {
649  if (NeedFlowSequenceComma)
650    output(", ");
651  if (WrapColumn && Column > WrapColumn) {
652    output("\n");
653    for (int i = 0; i < ColumnAtFlowStart; ++i)
654      output(" ");
655    Column = ColumnAtFlowStart;
656    output("  ");
657  }
658  SaveInfo = nullptr;
659  return true;
660}
661
662void Output::postflightFlowElement(void *) {
663  NeedFlowSequenceComma = true;
664}
665
666void Output::beginEnumScalar() {
667  EnumerationMatchFound = false;
668}
669
670bool Output::matchEnumScalar(const char *Str, bool Match) {
671  if (Match && !EnumerationMatchFound) {
672    newLineCheck();
673    outputUpToEndOfLine(Str);
674    EnumerationMatchFound = true;
675  }
676  return false;
677}
678
679bool Output::matchEnumFallback() {
680  if (EnumerationMatchFound)
681    return false;
682  EnumerationMatchFound = true;
683  return true;
684}
685
686void Output::endEnumScalar() {
687  if (!EnumerationMatchFound)
688    llvm_unreachable("bad runtime enum value");
689}
690
691bool Output::beginBitSetScalar(bool &DoClear) {
692  newLineCheck();
693  output("[ ");
694  NeedBitValueComma = false;
695  DoClear = false;
696  return true;
697}
698
699bool Output::bitSetMatch(const char *Str, bool Matches) {
700  if (Matches) {
701    if (NeedBitValueComma)
702      output(", ");
703    output(Str);
704    NeedBitValueComma = true;
705  }
706  return false;
707}
708
709void Output::endBitSetScalar() {
710  outputUpToEndOfLine(" ]");
711}
712
713void Output::scalarString(StringRef &S, QuotingType MustQuote) {
714  newLineCheck();
715  if (S.empty()) {
716    // Print '' for the empty string because leaving the field empty is not
717    // allowed.
718    outputUpToEndOfLine("''");
719    return;
720  }
721  if (MustQuote == QuotingType::None) {
722    // Only quote if we must.
723    outputUpToEndOfLine(S);
724    return;
725  }
726
727  const char *const Quote = MustQuote == QuotingType::Single ? "'" : "\"";
728  output(Quote); // Starting quote.
729
730  // When using double-quoted strings (and only in that case), non-printable characters may be
731  // present, and will be escaped using a variety of unicode-scalar and special short-form
732  // escapes. This is handled in yaml::escape.
733  if (MustQuote == QuotingType::Double) {
734    output(yaml::escape(S, /* EscapePrintable= */ false));
735    outputUpToEndOfLine(Quote);
736    return;
737  }
738
739  unsigned i = 0;
740  unsigned j = 0;
741  unsigned End = S.size();
742  const char *Base = S.data();
743
744  // When using single-quoted strings, any single quote ' must be doubled to be escaped.
745  while (j < End) {
746    if (S[j] == '\'') {                    // Escape quotes.
747      output(StringRef(&Base[i], j - i));  // "flush".
748      output(StringLiteral("''"));         // Print it as ''
749      i = j + 1;
750    }
751    ++j;
752  }
753  output(StringRef(&Base[i], j - i));
754  outputUpToEndOfLine(Quote); // Ending quote.
755}
756
757void Output::blockScalarString(StringRef &S) {
758  if (!StateStack.empty())
759    newLineCheck();
760  output(" |");
761  outputNewLine();
762
763  unsigned Indent = StateStack.empty() ? 1 : StateStack.size();
764
765  auto Buffer = MemoryBuffer::getMemBuffer(S, "", false);
766  for (line_iterator Lines(*Buffer, false); !Lines.is_at_end(); ++Lines) {
767    for (unsigned I = 0; I < Indent; ++I) {
768      output("  ");
769    }
770    output(*Lines);
771    outputNewLine();
772  }
773}
774
775void Output::scalarTag(std::string &Tag) {
776  if (Tag.empty())
777    return;
778  newLineCheck();
779  output(Tag);
780  output(" ");
781}
782
783void Output::setError(const Twine &message) {
784}
785
786bool Output::canElideEmptySequence() {
787  // Normally, with an optional key/value where the value is an empty sequence,
788  // the whole key/value can be not written.  But, that produces wrong yaml
789  // if the key/value is the only thing in the map and the map is used in
790  // a sequence.  This detects if the this sequence is the first key/value
791  // in map that itself is embedded in a sequence.
792  if (StateStack.size() < 2)
793    return true;
794  if (StateStack.back() != inMapFirstKey)
795    return true;
796  return !inSeqAnyElement(StateStack[StateStack.size() - 2]);
797}
798
799void Output::output(StringRef s) {
800  Column += s.size();
801  Out << s;
802}
803
804void Output::outputUpToEndOfLine(StringRef s) {
805  output(s);
806  if (StateStack.empty() || (!inFlowSeqAnyElement(StateStack.back()) &&
807                             !inFlowMapAnyKey(StateStack.back())))
808    Padding = "\n";
809}
810
811void Output::outputNewLine() {
812  Out << "\n";
813  Column = 0;
814}
815
816// if seq at top, indent as if map, then add "- "
817// if seq in middle, use "- " if firstKey, else use "  "
818//
819
820void Output::newLineCheck(bool EmptySequence) {
821  if (Padding != "\n") {
822    output(Padding);
823    Padding = {};
824    return;
825  }
826  outputNewLine();
827  Padding = {};
828
829  if (StateStack.size() == 0 || EmptySequence)
830    return;
831
832  unsigned Indent = StateStack.size() - 1;
833  bool OutputDash = false;
834
835  if (StateStack.back() == inSeqFirstElement ||
836      StateStack.back() == inSeqOtherElement) {
837    OutputDash = true;
838  } else if ((StateStack.size() > 1) &&
839             ((StateStack.back() == inMapFirstKey) ||
840              inFlowSeqAnyElement(StateStack.back()) ||
841              (StateStack.back() == inFlowMapFirstKey)) &&
842             inSeqAnyElement(StateStack[StateStack.size() - 2])) {
843    --Indent;
844    OutputDash = true;
845  }
846
847  for (unsigned i = 0; i < Indent; ++i) {
848    output("  ");
849  }
850  if (OutputDash) {
851    output("- ");
852  }
853}
854
855void Output::paddedKey(StringRef key) {
856  output(key);
857  output(":");
858  const char *spaces = "                ";
859  if (key.size() < strlen(spaces))
860    Padding = &spaces[key.size()];
861  else
862    Padding = " ";
863}
864
865void Output::flowKey(StringRef Key) {
866  if (StateStack.back() == inFlowMapOtherKey)
867    output(", ");
868  if (WrapColumn && Column > WrapColumn) {
869    output("\n");
870    for (int I = 0; I < ColumnAtMapFlowStart; ++I)
871      output(" ");
872    Column = ColumnAtMapFlowStart;
873    output("  ");
874  }
875  output(Key);
876  output(": ");
877}
878
879NodeKind Output::getNodeKind() { report_fatal_error("invalid call"); }
880
881bool Output::inSeqAnyElement(InState State) {
882  return State == inSeqFirstElement || State == inSeqOtherElement;
883}
884
885bool Output::inFlowSeqAnyElement(InState State) {
886  return State == inFlowSeqFirstElement || State == inFlowSeqOtherElement;
887}
888
889bool Output::inMapAnyKey(InState State) {
890  return State == inMapFirstKey || State == inMapOtherKey;
891}
892
893bool Output::inFlowMapAnyKey(InState State) {
894  return State == inFlowMapFirstKey || State == inFlowMapOtherKey;
895}
896
897//===----------------------------------------------------------------------===//
898//  traits for built-in types
899//===----------------------------------------------------------------------===//
900
901void ScalarTraits<bool>::output(const bool &Val, void *, raw_ostream &Out) {
902  Out << (Val ? "true" : "false");
903}
904
905StringRef ScalarTraits<bool>::input(StringRef Scalar, void *, bool &Val) {
906  if (std::optional<bool> Parsed = parseBool(Scalar)) {
907    Val = *Parsed;
908    return StringRef();
909  }
910  return "invalid boolean";
911}
912
913void ScalarTraits<StringRef>::output(const StringRef &Val, void *,
914                                     raw_ostream &Out) {
915  Out << Val;
916}
917
918StringRef ScalarTraits<StringRef>::input(StringRef Scalar, void *,
919                                         StringRef &Val) {
920  Val = Scalar;
921  return StringRef();
922}
923
924void ScalarTraits<std::string>::output(const std::string &Val, void *,
925                                       raw_ostream &Out) {
926  Out << Val;
927}
928
929StringRef ScalarTraits<std::string>::input(StringRef Scalar, void *,
930                                           std::string &Val) {
931  Val = Scalar.str();
932  return StringRef();
933}
934
935void ScalarTraits<uint8_t>::output(const uint8_t &Val, void *,
936                                   raw_ostream &Out) {
937  // use temp uin32_t because ostream thinks uint8_t is a character
938  uint32_t Num = Val;
939  Out << Num;
940}
941
942StringRef ScalarTraits<uint8_t>::input(StringRef Scalar, void *, uint8_t &Val) {
943  unsigned long long n;
944  if (getAsUnsignedInteger(Scalar, 0, n))
945    return "invalid number";
946  if (n > 0xFF)
947    return "out of range number";
948  Val = n;
949  return StringRef();
950}
951
952void ScalarTraits<uint16_t>::output(const uint16_t &Val, void *,
953                                    raw_ostream &Out) {
954  Out << Val;
955}
956
957StringRef ScalarTraits<uint16_t>::input(StringRef Scalar, void *,
958                                        uint16_t &Val) {
959  unsigned long long n;
960  if (getAsUnsignedInteger(Scalar, 0, n))
961    return "invalid number";
962  if (n > 0xFFFF)
963    return "out of range number";
964  Val = n;
965  return StringRef();
966}
967
968void ScalarTraits<uint32_t>::output(const uint32_t &Val, void *,
969                                    raw_ostream &Out) {
970  Out << Val;
971}
972
973StringRef ScalarTraits<uint32_t>::input(StringRef Scalar, void *,
974                                        uint32_t &Val) {
975  unsigned long long n;
976  if (getAsUnsignedInteger(Scalar, 0, n))
977    return "invalid number";
978  if (n > 0xFFFFFFFFUL)
979    return "out of range number";
980  Val = n;
981  return StringRef();
982}
983
984void ScalarTraits<uint64_t>::output(const uint64_t &Val, void *,
985                                    raw_ostream &Out) {
986  Out << Val;
987}
988
989StringRef ScalarTraits<uint64_t>::input(StringRef Scalar, void *,
990                                        uint64_t &Val) {
991  unsigned long long N;
992  if (getAsUnsignedInteger(Scalar, 0, N))
993    return "invalid number";
994  Val = N;
995  return StringRef();
996}
997
998void ScalarTraits<int8_t>::output(const int8_t &Val, void *, raw_ostream &Out) {
999  // use temp in32_t because ostream thinks int8_t is a character
1000  int32_t Num = Val;
1001  Out << Num;
1002}
1003
1004StringRef ScalarTraits<int8_t>::input(StringRef Scalar, void *, int8_t &Val) {
1005  long long N;
1006  if (getAsSignedInteger(Scalar, 0, N))
1007    return "invalid number";
1008  if ((N > 127) || (N < -128))
1009    return "out of range number";
1010  Val = N;
1011  return StringRef();
1012}
1013
1014void ScalarTraits<int16_t>::output(const int16_t &Val, void *,
1015                                   raw_ostream &Out) {
1016  Out << Val;
1017}
1018
1019StringRef ScalarTraits<int16_t>::input(StringRef Scalar, void *, int16_t &Val) {
1020  long long N;
1021  if (getAsSignedInteger(Scalar, 0, N))
1022    return "invalid number";
1023  if ((N > INT16_MAX) || (N < INT16_MIN))
1024    return "out of range number";
1025  Val = N;
1026  return StringRef();
1027}
1028
1029void ScalarTraits<int32_t>::output(const int32_t &Val, void *,
1030                                   raw_ostream &Out) {
1031  Out << Val;
1032}
1033
1034StringRef ScalarTraits<int32_t>::input(StringRef Scalar, void *, int32_t &Val) {
1035  long long N;
1036  if (getAsSignedInteger(Scalar, 0, N))
1037    return "invalid number";
1038  if ((N > INT32_MAX) || (N < INT32_MIN))
1039    return "out of range number";
1040  Val = N;
1041  return StringRef();
1042}
1043
1044void ScalarTraits<int64_t>::output(const int64_t &Val, void *,
1045                                   raw_ostream &Out) {
1046  Out << Val;
1047}
1048
1049StringRef ScalarTraits<int64_t>::input(StringRef Scalar, void *, int64_t &Val) {
1050  long long N;
1051  if (getAsSignedInteger(Scalar, 0, N))
1052    return "invalid number";
1053  Val = N;
1054  return StringRef();
1055}
1056
1057void ScalarTraits<double>::output(const double &Val, void *, raw_ostream &Out) {
1058  Out << format("%g", Val);
1059}
1060
1061StringRef ScalarTraits<double>::input(StringRef Scalar, void *, double &Val) {
1062  if (to_float(Scalar, Val))
1063    return StringRef();
1064  return "invalid floating point number";
1065}
1066
1067void ScalarTraits<float>::output(const float &Val, void *, raw_ostream &Out) {
1068  Out << format("%g", Val);
1069}
1070
1071StringRef ScalarTraits<float>::input(StringRef Scalar, void *, float &Val) {
1072  if (to_float(Scalar, Val))
1073    return StringRef();
1074  return "invalid floating point number";
1075}
1076
1077void ScalarTraits<Hex8>::output(const Hex8 &Val, void *, raw_ostream &Out) {
1078  Out << format("0x%" PRIX8, (uint8_t)Val);
1079}
1080
1081StringRef ScalarTraits<Hex8>::input(StringRef Scalar, void *, Hex8 &Val) {
1082  unsigned long long n;
1083  if (getAsUnsignedInteger(Scalar, 0, n))
1084    return "invalid hex8 number";
1085  if (n > 0xFF)
1086    return "out of range hex8 number";
1087  Val = n;
1088  return StringRef();
1089}
1090
1091void ScalarTraits<Hex16>::output(const Hex16 &Val, void *, raw_ostream &Out) {
1092  Out << format("0x%" PRIX16, (uint16_t)Val);
1093}
1094
1095StringRef ScalarTraits<Hex16>::input(StringRef Scalar, void *, Hex16 &Val) {
1096  unsigned long long n;
1097  if (getAsUnsignedInteger(Scalar, 0, n))
1098    return "invalid hex16 number";
1099  if (n > 0xFFFF)
1100    return "out of range hex16 number";
1101  Val = n;
1102  return StringRef();
1103}
1104
1105void ScalarTraits<Hex32>::output(const Hex32 &Val, void *, raw_ostream &Out) {
1106  Out << format("0x%" PRIX32, (uint32_t)Val);
1107}
1108
1109StringRef ScalarTraits<Hex32>::input(StringRef Scalar, void *, Hex32 &Val) {
1110  unsigned long long n;
1111  if (getAsUnsignedInteger(Scalar, 0, n))
1112    return "invalid hex32 number";
1113  if (n > 0xFFFFFFFFUL)
1114    return "out of range hex32 number";
1115  Val = n;
1116  return StringRef();
1117}
1118
1119void ScalarTraits<Hex64>::output(const Hex64 &Val, void *, raw_ostream &Out) {
1120  Out << format("0x%" PRIX64, (uint64_t)Val);
1121}
1122
1123StringRef ScalarTraits<Hex64>::input(StringRef Scalar, void *, Hex64 &Val) {
1124  unsigned long long Num;
1125  if (getAsUnsignedInteger(Scalar, 0, Num))
1126    return "invalid hex64 number";
1127  Val = Num;
1128  return StringRef();
1129}
1130
1131void ScalarTraits<VersionTuple>::output(const VersionTuple &Val, void *,
1132                                        llvm::raw_ostream &Out) {
1133  Out << Val.getAsString();
1134}
1135
1136StringRef ScalarTraits<VersionTuple>::input(StringRef Scalar, void *,
1137                                            VersionTuple &Val) {
1138  if (Val.tryParse(Scalar))
1139    return "invalid version format";
1140  return StringRef();
1141}
1142