1 //===- lib/Support/YAMLTraits.cpp -----------------------------------------===//
2 //
3 // The LLVM Linker
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "llvm/Support/YAMLTraits.h"
11 #include "llvm/ADT/SmallString.h"
12 #include "llvm/ADT/Twine.h"
13 #include "llvm/Support/Casting.h"
14 #include "llvm/Support/Errc.h"
15 #include "llvm/Support/ErrorHandling.h"
16 #include "llvm/Support/Format.h"
17 #include "llvm/Support/LineIterator.h"
18 #include "llvm/Support/YAMLParser.h"
19 #include "llvm/Support/raw_ostream.h"
20 #include <cctype>
21 #include <cstring>
22 using namespace llvm;
23 using namespace yaml;
24
25 //===----------------------------------------------------------------------===//
26 // IO
27 //===----------------------------------------------------------------------===//
28
IO(void * Context)29 IO::IO(void *Context) : Ctxt(Context) {
30 }
31
~IO()32 IO::~IO() {
33 }
34
getContext()35 void *IO::getContext() {
36 return Ctxt;
37 }
38
setContext(void * Context)39 void IO::setContext(void *Context) {
40 Ctxt = Context;
41 }
42
43 //===----------------------------------------------------------------------===//
44 // Input
45 //===----------------------------------------------------------------------===//
46
Input(StringRef InputContent,void * Ctxt,SourceMgr::DiagHandlerTy DiagHandler,void * DiagHandlerCtxt)47 Input::Input(StringRef InputContent,
48 void *Ctxt,
49 SourceMgr::DiagHandlerTy DiagHandler,
50 void *DiagHandlerCtxt)
51 : IO(Ctxt),
52 Strm(new Stream(InputContent, SrcMgr)),
53 CurrentNode(nullptr) {
54 if (DiagHandler)
55 SrcMgr.setDiagHandler(DiagHandler, DiagHandlerCtxt);
56 DocIterator = Strm->begin();
57 }
58
~Input()59 Input::~Input() {
60 }
61
error()62 std::error_code Input::error() { return EC; }
63
64 // Pin the vtables to this file.
anchor()65 void Input::HNode::anchor() {}
anchor()66 void Input::EmptyHNode::anchor() {}
anchor()67 void Input::ScalarHNode::anchor() {}
anchor()68 void Input::MapHNode::anchor() {}
anchor()69 void Input::SequenceHNode::anchor() {}
70
outputting()71 bool Input::outputting() {
72 return false;
73 }
74
setCurrentDocument()75 bool Input::setCurrentDocument() {
76 if (DocIterator != Strm->end()) {
77 Node *N = DocIterator->getRoot();
78 if (!N) {
79 assert(Strm->failed() && "Root is NULL iff parsing failed");
80 EC = make_error_code(errc::invalid_argument);
81 return false;
82 }
83
84 if (isa<NullNode>(N)) {
85 // Empty files are allowed and ignored
86 ++DocIterator;
87 return setCurrentDocument();
88 }
89 TopNode = this->createHNodes(N);
90 CurrentNode = TopNode.get();
91 return true;
92 }
93 return false;
94 }
95
nextDocument()96 bool Input::nextDocument() {
97 return ++DocIterator != Strm->end();
98 }
99
getCurrentNode() const100 const Node *Input::getCurrentNode() const {
101 return CurrentNode ? CurrentNode->_node : nullptr;
102 }
103
mapTag(StringRef Tag,bool Default)104 bool Input::mapTag(StringRef Tag, bool Default) {
105 std::string foundTag = CurrentNode->_node->getVerbatimTag();
106 if (foundTag.empty()) {
107 // If no tag found and 'Tag' is the default, say it was found.
108 return Default;
109 }
110 // Return true iff found tag matches supplied tag.
111 return Tag.equals(foundTag);
112 }
113
beginMapping()114 void Input::beginMapping() {
115 if (EC)
116 return;
117 // CurrentNode can be null if the document is empty.
118 MapHNode *MN = dyn_cast_or_null<MapHNode>(CurrentNode);
119 if (MN) {
120 MN->ValidKeys.clear();
121 }
122 }
123
preflightKey(const char * Key,bool Required,bool,bool & UseDefault,void * & SaveInfo)124 bool Input::preflightKey(const char *Key, bool Required, bool, bool &UseDefault,
125 void *&SaveInfo) {
126 UseDefault = false;
127 if (EC)
128 return false;
129
130 // CurrentNode is null for empty documents, which is an error in case required
131 // nodes are present.
132 if (!CurrentNode) {
133 if (Required)
134 EC = make_error_code(errc::invalid_argument);
135 return false;
136 }
137
138 MapHNode *MN = dyn_cast<MapHNode>(CurrentNode);
139 if (!MN) {
140 setError(CurrentNode, "not a mapping");
141 return false;
142 }
143 MN->ValidKeys.push_back(Key);
144 HNode *Value = MN->Mapping[Key].get();
145 if (!Value) {
146 if (Required)
147 setError(CurrentNode, Twine("missing required key '") + Key + "'");
148 else
149 UseDefault = true;
150 return false;
151 }
152 SaveInfo = CurrentNode;
153 CurrentNode = Value;
154 return true;
155 }
156
postflightKey(void * saveInfo)157 void Input::postflightKey(void *saveInfo) {
158 CurrentNode = reinterpret_cast<HNode *>(saveInfo);
159 }
160
endMapping()161 void Input::endMapping() {
162 if (EC)
163 return;
164 // CurrentNode can be null if the document is empty.
165 MapHNode *MN = dyn_cast_or_null<MapHNode>(CurrentNode);
166 if (!MN)
167 return;
168 for (const auto &NN : MN->Mapping) {
169 if (!MN->isValidKey(NN.first())) {
170 setError(NN.second.get(), Twine("unknown key '") + NN.first() + "'");
171 break;
172 }
173 }
174 }
175
beginFlowMapping()176 void Input::beginFlowMapping() { beginMapping(); }
177
endFlowMapping()178 void Input::endFlowMapping() { endMapping(); }
179
beginSequence()180 unsigned Input::beginSequence() {
181 if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode))
182 return SQ->Entries.size();
183 if (isa<EmptyHNode>(CurrentNode))
184 return 0;
185 // Treat case where there's a scalar "null" value as an empty sequence.
186 if (ScalarHNode *SN = dyn_cast<ScalarHNode>(CurrentNode)) {
187 if (isNull(SN->value()))
188 return 0;
189 }
190 // Any other type of HNode is an error.
191 setError(CurrentNode, "not a sequence");
192 return 0;
193 }
194
endSequence()195 void Input::endSequence() {
196 }
197
preflightElement(unsigned Index,void * & SaveInfo)198 bool Input::preflightElement(unsigned Index, void *&SaveInfo) {
199 if (EC)
200 return false;
201 if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) {
202 SaveInfo = CurrentNode;
203 CurrentNode = SQ->Entries[Index].get();
204 return true;
205 }
206 return false;
207 }
208
postflightElement(void * SaveInfo)209 void Input::postflightElement(void *SaveInfo) {
210 CurrentNode = reinterpret_cast<HNode *>(SaveInfo);
211 }
212
beginFlowSequence()213 unsigned Input::beginFlowSequence() { return beginSequence(); }
214
preflightFlowElement(unsigned index,void * & SaveInfo)215 bool Input::preflightFlowElement(unsigned index, void *&SaveInfo) {
216 if (EC)
217 return false;
218 if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) {
219 SaveInfo = CurrentNode;
220 CurrentNode = SQ->Entries[index].get();
221 return true;
222 }
223 return false;
224 }
225
postflightFlowElement(void * SaveInfo)226 void Input::postflightFlowElement(void *SaveInfo) {
227 CurrentNode = reinterpret_cast<HNode *>(SaveInfo);
228 }
229
endFlowSequence()230 void Input::endFlowSequence() {
231 }
232
beginEnumScalar()233 void Input::beginEnumScalar() {
234 ScalarMatchFound = false;
235 }
236
matchEnumScalar(const char * Str,bool)237 bool Input::matchEnumScalar(const char *Str, bool) {
238 if (ScalarMatchFound)
239 return false;
240 if (ScalarHNode *SN = dyn_cast<ScalarHNode>(CurrentNode)) {
241 if (SN->value().equals(Str)) {
242 ScalarMatchFound = true;
243 return true;
244 }
245 }
246 return false;
247 }
248
matchEnumFallback()249 bool Input::matchEnumFallback() {
250 if (ScalarMatchFound)
251 return false;
252 ScalarMatchFound = true;
253 return true;
254 }
255
endEnumScalar()256 void Input::endEnumScalar() {
257 if (!ScalarMatchFound) {
258 setError(CurrentNode, "unknown enumerated scalar");
259 }
260 }
261
beginBitSetScalar(bool & DoClear)262 bool Input::beginBitSetScalar(bool &DoClear) {
263 BitValuesUsed.clear();
264 if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) {
265 BitValuesUsed.insert(BitValuesUsed.begin(), SQ->Entries.size(), false);
266 } else {
267 setError(CurrentNode, "expected sequence of bit values");
268 }
269 DoClear = true;
270 return true;
271 }
272
bitSetMatch(const char * Str,bool)273 bool Input::bitSetMatch(const char *Str, bool) {
274 if (EC)
275 return false;
276 if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) {
277 unsigned Index = 0;
278 for (auto &N : SQ->Entries) {
279 if (ScalarHNode *SN = dyn_cast<ScalarHNode>(N.get())) {
280 if (SN->value().equals(Str)) {
281 BitValuesUsed[Index] = true;
282 return true;
283 }
284 } else {
285 setError(CurrentNode, "unexpected scalar in sequence of bit values");
286 }
287 ++Index;
288 }
289 } else {
290 setError(CurrentNode, "expected sequence of bit values");
291 }
292 return false;
293 }
294
endBitSetScalar()295 void Input::endBitSetScalar() {
296 if (EC)
297 return;
298 if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) {
299 assert(BitValuesUsed.size() == SQ->Entries.size());
300 for (unsigned i = 0; i < SQ->Entries.size(); ++i) {
301 if (!BitValuesUsed[i]) {
302 setError(SQ->Entries[i].get(), "unknown bit value");
303 return;
304 }
305 }
306 }
307 }
308
scalarString(StringRef & S,bool)309 void Input::scalarString(StringRef &S, bool) {
310 if (ScalarHNode *SN = dyn_cast<ScalarHNode>(CurrentNode)) {
311 S = SN->value();
312 } else {
313 setError(CurrentNode, "unexpected scalar");
314 }
315 }
316
blockScalarString(StringRef & S)317 void Input::blockScalarString(StringRef &S) { scalarString(S, false); }
318
setError(HNode * hnode,const Twine & message)319 void Input::setError(HNode *hnode, const Twine &message) {
320 assert(hnode && "HNode must not be NULL");
321 this->setError(hnode->_node, message);
322 }
323
setError(Node * node,const Twine & message)324 void Input::setError(Node *node, const Twine &message) {
325 Strm->printError(node, message);
326 EC = make_error_code(errc::invalid_argument);
327 }
328
createHNodes(Node * N)329 std::unique_ptr<Input::HNode> Input::createHNodes(Node *N) {
330 SmallString<128> StringStorage;
331 if (ScalarNode *SN = dyn_cast<ScalarNode>(N)) {
332 StringRef KeyStr = SN->getValue(StringStorage);
333 if (!StringStorage.empty()) {
334 // Copy string to permanent storage
335 unsigned Len = StringStorage.size();
336 char *Buf = StringAllocator.Allocate<char>(Len);
337 memcpy(Buf, &StringStorage[0], Len);
338 KeyStr = StringRef(Buf, Len);
339 }
340 return llvm::make_unique<ScalarHNode>(N, KeyStr);
341 } else if (BlockScalarNode *BSN = dyn_cast<BlockScalarNode>(N)) {
342 StringRef Value = BSN->getValue();
343 char *Buf = StringAllocator.Allocate<char>(Value.size());
344 memcpy(Buf, Value.data(), Value.size());
345 return llvm::make_unique<ScalarHNode>(N, StringRef(Buf, Value.size()));
346 } else if (SequenceNode *SQ = dyn_cast<SequenceNode>(N)) {
347 auto SQHNode = llvm::make_unique<SequenceHNode>(N);
348 for (Node &SN : *SQ) {
349 auto Entry = this->createHNodes(&SN);
350 if (EC)
351 break;
352 SQHNode->Entries.push_back(std::move(Entry));
353 }
354 return std::move(SQHNode);
355 } else if (MappingNode *Map = dyn_cast<MappingNode>(N)) {
356 auto mapHNode = llvm::make_unique<MapHNode>(N);
357 for (KeyValueNode &KVN : *Map) {
358 Node *KeyNode = KVN.getKey();
359 ScalarNode *KeyScalar = dyn_cast<ScalarNode>(KeyNode);
360 if (!KeyScalar) {
361 setError(KeyNode, "Map key must be a scalar");
362 break;
363 }
364 StringStorage.clear();
365 StringRef KeyStr = KeyScalar->getValue(StringStorage);
366 if (!StringStorage.empty()) {
367 // Copy string to permanent storage
368 unsigned Len = StringStorage.size();
369 char *Buf = StringAllocator.Allocate<char>(Len);
370 memcpy(Buf, &StringStorage[0], Len);
371 KeyStr = StringRef(Buf, Len);
372 }
373 auto ValueHNode = this->createHNodes(KVN.getValue());
374 if (EC)
375 break;
376 mapHNode->Mapping[KeyStr] = std::move(ValueHNode);
377 }
378 return std::move(mapHNode);
379 } else if (isa<NullNode>(N)) {
380 return llvm::make_unique<EmptyHNode>(N);
381 } else {
382 setError(N, "unknown node kind");
383 return nullptr;
384 }
385 }
386
isValidKey(StringRef Key)387 bool Input::MapHNode::isValidKey(StringRef Key) {
388 for (const char *K : ValidKeys) {
389 if (Key.equals(K))
390 return true;
391 }
392 return false;
393 }
394
setError(const Twine & Message)395 void Input::setError(const Twine &Message) {
396 this->setError(CurrentNode, Message);
397 }
398
canElideEmptySequence()399 bool Input::canElideEmptySequence() {
400 return false;
401 }
402
403 //===----------------------------------------------------------------------===//
404 // Output
405 //===----------------------------------------------------------------------===//
406
Output(raw_ostream & yout,void * context,int WrapColumn)407 Output::Output(raw_ostream &yout, void *context, int WrapColumn)
408 : IO(context),
409 Out(yout),
410 WrapColumn(WrapColumn),
411 Column(0),
412 ColumnAtFlowStart(0),
413 ColumnAtMapFlowStart(0),
414 NeedBitValueComma(false),
415 NeedFlowSequenceComma(false),
416 EnumerationMatchFound(false),
417 NeedsNewLine(false) {
418 }
419
~Output()420 Output::~Output() {
421 }
422
outputting()423 bool Output::outputting() {
424 return true;
425 }
426
beginMapping()427 void Output::beginMapping() {
428 StateStack.push_back(inMapFirstKey);
429 NeedsNewLine = true;
430 }
431
mapTag(StringRef Tag,bool Use)432 bool Output::mapTag(StringRef Tag, bool Use) {
433 if (Use) {
434 this->output(" ");
435 this->output(Tag);
436 }
437 return Use;
438 }
439
endMapping()440 void Output::endMapping() {
441 StateStack.pop_back();
442 }
443
preflightKey(const char * Key,bool Required,bool SameAsDefault,bool & UseDefault,void * &)444 bool Output::preflightKey(const char *Key, bool Required, bool SameAsDefault,
445 bool &UseDefault, void *&) {
446 UseDefault = false;
447 if (Required || !SameAsDefault) {
448 auto State = StateStack.back();
449 if (State == inFlowMapFirstKey || State == inFlowMapOtherKey) {
450 flowKey(Key);
451 } else {
452 this->newLineCheck();
453 this->paddedKey(Key);
454 }
455 return true;
456 }
457 return false;
458 }
459
postflightKey(void *)460 void Output::postflightKey(void *) {
461 if (StateStack.back() == inMapFirstKey) {
462 StateStack.pop_back();
463 StateStack.push_back(inMapOtherKey);
464 } else if (StateStack.back() == inFlowMapFirstKey) {
465 StateStack.pop_back();
466 StateStack.push_back(inFlowMapOtherKey);
467 }
468 }
469
beginFlowMapping()470 void Output::beginFlowMapping() {
471 StateStack.push_back(inFlowMapFirstKey);
472 this->newLineCheck();
473 ColumnAtMapFlowStart = Column;
474 output("{ ");
475 }
476
endFlowMapping()477 void Output::endFlowMapping() {
478 StateStack.pop_back();
479 this->outputUpToEndOfLine(" }");
480 }
481
beginDocuments()482 void Output::beginDocuments() {
483 this->outputUpToEndOfLine("---");
484 }
485
preflightDocument(unsigned index)486 bool Output::preflightDocument(unsigned index) {
487 if (index > 0)
488 this->outputUpToEndOfLine("\n---");
489 return true;
490 }
491
postflightDocument()492 void Output::postflightDocument() {
493 }
494
endDocuments()495 void Output::endDocuments() {
496 output("\n...\n");
497 }
498
beginSequence()499 unsigned Output::beginSequence() {
500 StateStack.push_back(inSeq);
501 NeedsNewLine = true;
502 return 0;
503 }
504
endSequence()505 void Output::endSequence() {
506 StateStack.pop_back();
507 }
508
preflightElement(unsigned,void * &)509 bool Output::preflightElement(unsigned, void *&) {
510 return true;
511 }
512
postflightElement(void *)513 void Output::postflightElement(void *) {
514 }
515
beginFlowSequence()516 unsigned Output::beginFlowSequence() {
517 StateStack.push_back(inFlowSeq);
518 this->newLineCheck();
519 ColumnAtFlowStart = Column;
520 output("[ ");
521 NeedFlowSequenceComma = false;
522 return 0;
523 }
524
endFlowSequence()525 void Output::endFlowSequence() {
526 StateStack.pop_back();
527 this->outputUpToEndOfLine(" ]");
528 }
529
preflightFlowElement(unsigned,void * &)530 bool Output::preflightFlowElement(unsigned, void *&) {
531 if (NeedFlowSequenceComma)
532 output(", ");
533 if (WrapColumn && Column > WrapColumn) {
534 output("\n");
535 for (int i = 0; i < ColumnAtFlowStart; ++i)
536 output(" ");
537 Column = ColumnAtFlowStart;
538 output(" ");
539 }
540 return true;
541 }
542
postflightFlowElement(void *)543 void Output::postflightFlowElement(void *) {
544 NeedFlowSequenceComma = true;
545 }
546
beginEnumScalar()547 void Output::beginEnumScalar() {
548 EnumerationMatchFound = false;
549 }
550
matchEnumScalar(const char * Str,bool Match)551 bool Output::matchEnumScalar(const char *Str, bool Match) {
552 if (Match && !EnumerationMatchFound) {
553 this->newLineCheck();
554 this->outputUpToEndOfLine(Str);
555 EnumerationMatchFound = true;
556 }
557 return false;
558 }
559
matchEnumFallback()560 bool Output::matchEnumFallback() {
561 if (EnumerationMatchFound)
562 return false;
563 EnumerationMatchFound = true;
564 return true;
565 }
566
endEnumScalar()567 void Output::endEnumScalar() {
568 if (!EnumerationMatchFound)
569 llvm_unreachable("bad runtime enum value");
570 }
571
beginBitSetScalar(bool & DoClear)572 bool Output::beginBitSetScalar(bool &DoClear) {
573 this->newLineCheck();
574 output("[ ");
575 NeedBitValueComma = false;
576 DoClear = false;
577 return true;
578 }
579
bitSetMatch(const char * Str,bool Matches)580 bool Output::bitSetMatch(const char *Str, bool Matches) {
581 if (Matches) {
582 if (NeedBitValueComma)
583 output(", ");
584 this->output(Str);
585 NeedBitValueComma = true;
586 }
587 return false;
588 }
589
endBitSetScalar()590 void Output::endBitSetScalar() {
591 this->outputUpToEndOfLine(" ]");
592 }
593
scalarString(StringRef & S,bool MustQuote)594 void Output::scalarString(StringRef &S, bool MustQuote) {
595 this->newLineCheck();
596 if (S.empty()) {
597 // Print '' for the empty string because leaving the field empty is not
598 // allowed.
599 this->outputUpToEndOfLine("''");
600 return;
601 }
602 if (!MustQuote) {
603 // Only quote if we must.
604 this->outputUpToEndOfLine(S);
605 return;
606 }
607 unsigned i = 0;
608 unsigned j = 0;
609 unsigned End = S.size();
610 output("'"); // Starting single quote.
611 const char *Base = S.data();
612 while (j < End) {
613 // Escape a single quote by doubling it.
614 if (S[j] == '\'') {
615 output(StringRef(&Base[i], j - i + 1));
616 output("'");
617 i = j + 1;
618 }
619 ++j;
620 }
621 output(StringRef(&Base[i], j - i));
622 this->outputUpToEndOfLine("'"); // Ending single quote.
623 }
624
blockScalarString(StringRef & S)625 void Output::blockScalarString(StringRef &S) {
626 if (!StateStack.empty())
627 newLineCheck();
628 output(" |");
629 outputNewLine();
630
631 unsigned Indent = StateStack.empty() ? 1 : StateStack.size();
632
633 auto Buffer = MemoryBuffer::getMemBuffer(S, "", false);
634 for (line_iterator Lines(*Buffer, false); !Lines.is_at_end(); ++Lines) {
635 for (unsigned I = 0; I < Indent; ++I) {
636 output(" ");
637 }
638 output(*Lines);
639 outputNewLine();
640 }
641 }
642
setError(const Twine & message)643 void Output::setError(const Twine &message) {
644 }
645
canElideEmptySequence()646 bool Output::canElideEmptySequence() {
647 // Normally, with an optional key/value where the value is an empty sequence,
648 // the whole key/value can be not written. But, that produces wrong yaml
649 // if the key/value is the only thing in the map and the map is used in
650 // a sequence. This detects if the this sequence is the first key/value
651 // in map that itself is embedded in a sequnce.
652 if (StateStack.size() < 2)
653 return true;
654 if (StateStack.back() != inMapFirstKey)
655 return true;
656 return (StateStack[StateStack.size()-2] != inSeq);
657 }
658
output(StringRef s)659 void Output::output(StringRef s) {
660 Column += s.size();
661 Out << s;
662 }
663
outputUpToEndOfLine(StringRef s)664 void Output::outputUpToEndOfLine(StringRef s) {
665 this->output(s);
666 if (StateStack.empty() || (StateStack.back() != inFlowSeq &&
667 StateStack.back() != inFlowMapFirstKey &&
668 StateStack.back() != inFlowMapOtherKey))
669 NeedsNewLine = true;
670 }
671
outputNewLine()672 void Output::outputNewLine() {
673 Out << "\n";
674 Column = 0;
675 }
676
677 // if seq at top, indent as if map, then add "- "
678 // if seq in middle, use "- " if firstKey, else use " "
679 //
680
newLineCheck()681 void Output::newLineCheck() {
682 if (!NeedsNewLine)
683 return;
684 NeedsNewLine = false;
685
686 this->outputNewLine();
687
688 assert(StateStack.size() > 0);
689 unsigned Indent = StateStack.size() - 1;
690 bool OutputDash = false;
691
692 if (StateStack.back() == inSeq) {
693 OutputDash = true;
694 } else if ((StateStack.size() > 1) && ((StateStack.back() == inMapFirstKey) ||
695 (StateStack.back() == inFlowSeq) ||
696 (StateStack.back() == inFlowMapFirstKey)) &&
697 (StateStack[StateStack.size() - 2] == inSeq)) {
698 --Indent;
699 OutputDash = true;
700 }
701
702 for (unsigned i = 0; i < Indent; ++i) {
703 output(" ");
704 }
705 if (OutputDash) {
706 output("- ");
707 }
708
709 }
710
paddedKey(StringRef key)711 void Output::paddedKey(StringRef key) {
712 output(key);
713 output(":");
714 const char *spaces = " ";
715 if (key.size() < strlen(spaces))
716 output(&spaces[key.size()]);
717 else
718 output(" ");
719 }
720
flowKey(StringRef Key)721 void Output::flowKey(StringRef Key) {
722 if (StateStack.back() == inFlowMapOtherKey)
723 output(", ");
724 if (WrapColumn && Column > WrapColumn) {
725 output("\n");
726 for (int I = 0; I < ColumnAtMapFlowStart; ++I)
727 output(" ");
728 Column = ColumnAtMapFlowStart;
729 output(" ");
730 }
731 output(Key);
732 output(": ");
733 }
734
735 //===----------------------------------------------------------------------===//
736 // traits for built-in types
737 //===----------------------------------------------------------------------===//
738
output(const bool & Val,void *,raw_ostream & Out)739 void ScalarTraits<bool>::output(const bool &Val, void *, raw_ostream &Out) {
740 Out << (Val ? "true" : "false");
741 }
742
input(StringRef Scalar,void *,bool & Val)743 StringRef ScalarTraits<bool>::input(StringRef Scalar, void *, bool &Val) {
744 if (Scalar.equals("true")) {
745 Val = true;
746 return StringRef();
747 } else if (Scalar.equals("false")) {
748 Val = false;
749 return StringRef();
750 }
751 return "invalid boolean";
752 }
753
output(const StringRef & Val,void *,raw_ostream & Out)754 void ScalarTraits<StringRef>::output(const StringRef &Val, void *,
755 raw_ostream &Out) {
756 Out << Val;
757 }
758
input(StringRef Scalar,void *,StringRef & Val)759 StringRef ScalarTraits<StringRef>::input(StringRef Scalar, void *,
760 StringRef &Val) {
761 Val = Scalar;
762 return StringRef();
763 }
764
output(const std::string & Val,void *,raw_ostream & Out)765 void ScalarTraits<std::string>::output(const std::string &Val, void *,
766 raw_ostream &Out) {
767 Out << Val;
768 }
769
input(StringRef Scalar,void *,std::string & Val)770 StringRef ScalarTraits<std::string>::input(StringRef Scalar, void *,
771 std::string &Val) {
772 Val = Scalar.str();
773 return StringRef();
774 }
775
output(const uint8_t & Val,void *,raw_ostream & Out)776 void ScalarTraits<uint8_t>::output(const uint8_t &Val, void *,
777 raw_ostream &Out) {
778 // use temp uin32_t because ostream thinks uint8_t is a character
779 uint32_t Num = Val;
780 Out << Num;
781 }
782
input(StringRef Scalar,void *,uint8_t & Val)783 StringRef ScalarTraits<uint8_t>::input(StringRef Scalar, void *, uint8_t &Val) {
784 unsigned long long n;
785 if (getAsUnsignedInteger(Scalar, 0, n))
786 return "invalid number";
787 if (n > 0xFF)
788 return "out of range number";
789 Val = n;
790 return StringRef();
791 }
792
output(const uint16_t & Val,void *,raw_ostream & Out)793 void ScalarTraits<uint16_t>::output(const uint16_t &Val, void *,
794 raw_ostream &Out) {
795 Out << Val;
796 }
797
input(StringRef Scalar,void *,uint16_t & Val)798 StringRef ScalarTraits<uint16_t>::input(StringRef Scalar, void *,
799 uint16_t &Val) {
800 unsigned long long n;
801 if (getAsUnsignedInteger(Scalar, 0, n))
802 return "invalid number";
803 if (n > 0xFFFF)
804 return "out of range number";
805 Val = n;
806 return StringRef();
807 }
808
output(const uint32_t & Val,void *,raw_ostream & Out)809 void ScalarTraits<uint32_t>::output(const uint32_t &Val, void *,
810 raw_ostream &Out) {
811 Out << Val;
812 }
813
input(StringRef Scalar,void *,uint32_t & Val)814 StringRef ScalarTraits<uint32_t>::input(StringRef Scalar, void *,
815 uint32_t &Val) {
816 unsigned long long n;
817 if (getAsUnsignedInteger(Scalar, 0, n))
818 return "invalid number";
819 if (n > 0xFFFFFFFFUL)
820 return "out of range number";
821 Val = n;
822 return StringRef();
823 }
824
output(const uint64_t & Val,void *,raw_ostream & Out)825 void ScalarTraits<uint64_t>::output(const uint64_t &Val, void *,
826 raw_ostream &Out) {
827 Out << Val;
828 }
829
input(StringRef Scalar,void *,uint64_t & Val)830 StringRef ScalarTraits<uint64_t>::input(StringRef Scalar, void *,
831 uint64_t &Val) {
832 unsigned long long N;
833 if (getAsUnsignedInteger(Scalar, 0, N))
834 return "invalid number";
835 Val = N;
836 return StringRef();
837 }
838
output(const int8_t & Val,void *,raw_ostream & Out)839 void ScalarTraits<int8_t>::output(const int8_t &Val, void *, raw_ostream &Out) {
840 // use temp in32_t because ostream thinks int8_t is a character
841 int32_t Num = Val;
842 Out << Num;
843 }
844
input(StringRef Scalar,void *,int8_t & Val)845 StringRef ScalarTraits<int8_t>::input(StringRef Scalar, void *, int8_t &Val) {
846 long long N;
847 if (getAsSignedInteger(Scalar, 0, N))
848 return "invalid number";
849 if ((N > 127) || (N < -128))
850 return "out of range number";
851 Val = N;
852 return StringRef();
853 }
854
output(const int16_t & Val,void *,raw_ostream & Out)855 void ScalarTraits<int16_t>::output(const int16_t &Val, void *,
856 raw_ostream &Out) {
857 Out << Val;
858 }
859
input(StringRef Scalar,void *,int16_t & Val)860 StringRef ScalarTraits<int16_t>::input(StringRef Scalar, void *, int16_t &Val) {
861 long long N;
862 if (getAsSignedInteger(Scalar, 0, N))
863 return "invalid number";
864 if ((N > INT16_MAX) || (N < INT16_MIN))
865 return "out of range number";
866 Val = N;
867 return StringRef();
868 }
869
output(const int32_t & Val,void *,raw_ostream & Out)870 void ScalarTraits<int32_t>::output(const int32_t &Val, void *,
871 raw_ostream &Out) {
872 Out << Val;
873 }
874
input(StringRef Scalar,void *,int32_t & Val)875 StringRef ScalarTraits<int32_t>::input(StringRef Scalar, void *, int32_t &Val) {
876 long long N;
877 if (getAsSignedInteger(Scalar, 0, N))
878 return "invalid number";
879 if ((N > INT32_MAX) || (N < INT32_MIN))
880 return "out of range number";
881 Val = N;
882 return StringRef();
883 }
884
output(const int64_t & Val,void *,raw_ostream & Out)885 void ScalarTraits<int64_t>::output(const int64_t &Val, void *,
886 raw_ostream &Out) {
887 Out << Val;
888 }
889
input(StringRef Scalar,void *,int64_t & Val)890 StringRef ScalarTraits<int64_t>::input(StringRef Scalar, void *, int64_t &Val) {
891 long long N;
892 if (getAsSignedInteger(Scalar, 0, N))
893 return "invalid number";
894 Val = N;
895 return StringRef();
896 }
897
output(const double & Val,void *,raw_ostream & Out)898 void ScalarTraits<double>::output(const double &Val, void *, raw_ostream &Out) {
899 Out << format("%g", Val);
900 }
901
input(StringRef Scalar,void *,double & Val)902 StringRef ScalarTraits<double>::input(StringRef Scalar, void *, double &Val) {
903 SmallString<32> buff(Scalar.begin(), Scalar.end());
904 char *end;
905 Val = strtod(buff.c_str(), &end);
906 if (*end != '\0')
907 return "invalid floating point number";
908 return StringRef();
909 }
910
output(const float & Val,void *,raw_ostream & Out)911 void ScalarTraits<float>::output(const float &Val, void *, raw_ostream &Out) {
912 Out << format("%g", Val);
913 }
914
input(StringRef Scalar,void *,float & Val)915 StringRef ScalarTraits<float>::input(StringRef Scalar, void *, float &Val) {
916 SmallString<32> buff(Scalar.begin(), Scalar.end());
917 char *end;
918 Val = strtod(buff.c_str(), &end);
919 if (*end != '\0')
920 return "invalid floating point number";
921 return StringRef();
922 }
923
output(const Hex8 & Val,void *,raw_ostream & Out)924 void ScalarTraits<Hex8>::output(const Hex8 &Val, void *, raw_ostream &Out) {
925 uint8_t Num = Val;
926 Out << format("0x%02X", Num);
927 }
928
input(StringRef Scalar,void *,Hex8 & Val)929 StringRef ScalarTraits<Hex8>::input(StringRef Scalar, void *, Hex8 &Val) {
930 unsigned long long n;
931 if (getAsUnsignedInteger(Scalar, 0, n))
932 return "invalid hex8 number";
933 if (n > 0xFF)
934 return "out of range hex8 number";
935 Val = n;
936 return StringRef();
937 }
938
output(const Hex16 & Val,void *,raw_ostream & Out)939 void ScalarTraits<Hex16>::output(const Hex16 &Val, void *, raw_ostream &Out) {
940 uint16_t Num = Val;
941 Out << format("0x%04X", Num);
942 }
943
input(StringRef Scalar,void *,Hex16 & Val)944 StringRef ScalarTraits<Hex16>::input(StringRef Scalar, void *, Hex16 &Val) {
945 unsigned long long n;
946 if (getAsUnsignedInteger(Scalar, 0, n))
947 return "invalid hex16 number";
948 if (n > 0xFFFF)
949 return "out of range hex16 number";
950 Val = n;
951 return StringRef();
952 }
953
output(const Hex32 & Val,void *,raw_ostream & Out)954 void ScalarTraits<Hex32>::output(const Hex32 &Val, void *, raw_ostream &Out) {
955 uint32_t Num = Val;
956 Out << format("0x%08X", Num);
957 }
958
input(StringRef Scalar,void *,Hex32 & Val)959 StringRef ScalarTraits<Hex32>::input(StringRef Scalar, void *, Hex32 &Val) {
960 unsigned long long n;
961 if (getAsUnsignedInteger(Scalar, 0, n))
962 return "invalid hex32 number";
963 if (n > 0xFFFFFFFFUL)
964 return "out of range hex32 number";
965 Val = n;
966 return StringRef();
967 }
968
output(const Hex64 & Val,void *,raw_ostream & Out)969 void ScalarTraits<Hex64>::output(const Hex64 &Val, void *, raw_ostream &Out) {
970 uint64_t Num = Val;
971 Out << format("0x%016llX", Num);
972 }
973
input(StringRef Scalar,void *,Hex64 & Val)974 StringRef ScalarTraits<Hex64>::input(StringRef Scalar, void *, Hex64 &Val) {
975 unsigned long long Num;
976 if (getAsUnsignedInteger(Scalar, 0, Num))
977 return "invalid hex64 number";
978 Val = Num;
979 return StringRef();
980 }
981