]>
git.proxmox.com Git - rustc.git/blob - src/llvm/lib/Support/YAMLTraits.cpp
1 //===- lib/Support/YAMLTraits.cpp -----------------------------------------===//
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "llvm/Support/YAMLTraits.h"
11 #include "llvm/ADT/Twine.h"
12 #include "llvm/Support/Casting.h"
13 #include "llvm/Support/ErrorHandling.h"
14 #include "llvm/Support/Format.h"
15 #include "llvm/Support/YAMLParser.h"
16 #include "llvm/Support/raw_ostream.h"
21 //===----------------------------------------------------------------------===//
23 //===----------------------------------------------------------------------===//
25 IO::IO(void *Context
) : Ctxt(Context
) {
31 void *IO::getContext() {
35 void IO::setContext(void *Context
) {
39 //===----------------------------------------------------------------------===//
41 //===----------------------------------------------------------------------===//
43 Input::Input(StringRef InputContent
, void *Ctxt
)
45 Strm(new Stream(InputContent
, SrcMgr
)),
47 DocIterator
= Strm
->begin();
54 error_code
Input::error() {
58 void Input::setDiagHandler(SourceMgr::DiagHandlerTy Handler
, void *Ctxt
) {
59 SrcMgr
.setDiagHandler(Handler
, Ctxt
);
62 bool Input::outputting() {
66 bool Input::setCurrentDocument() {
67 if (DocIterator
!= Strm
->end()) {
68 Node
*N
= DocIterator
->getRoot();
69 if (isa
<NullNode
>(N
)) {
70 // Empty files are allowed and ignored
72 return setCurrentDocument();
74 TopNode
.reset(this->createHNodes(N
));
75 CurrentNode
= TopNode
.get();
81 void Input::nextDocument() {
85 void Input::beginMapping() {
88 MapHNode
*MN
= dyn_cast
<MapHNode
>(CurrentNode
);
90 MN
->ValidKeys
.clear();
94 bool Input::preflightKey(const char *Key
, bool Required
, bool, bool &UseDefault
,
99 MapHNode
*MN
= dyn_cast
<MapHNode
>(CurrentNode
);
101 setError(CurrentNode
, "not a mapping");
104 MN
->ValidKeys
.push_back(Key
);
105 HNode
*Value
= MN
->Mapping
[Key
];
108 setError(CurrentNode
, Twine("missing required key '") + Key
+ "'");
113 SaveInfo
= CurrentNode
;
118 void Input::postflightKey(void *saveInfo
) {
119 CurrentNode
= reinterpret_cast<HNode
*>(saveInfo
);
122 void Input::endMapping() {
125 MapHNode
*MN
= dyn_cast
<MapHNode
>(CurrentNode
);
128 for (MapHNode::NameToNode::iterator i
= MN
->Mapping
.begin(),
129 End
= MN
->Mapping
.end(); i
!= End
; ++i
) {
130 if (!MN
->isValidKey(i
->first
)) {
131 setError(i
->second
, Twine("unknown key '") + i
->first
+ "'");
137 unsigned Input::beginSequence() {
138 if (SequenceHNode
*SQ
= dyn_cast
<SequenceHNode
>(CurrentNode
)) {
139 return SQ
->Entries
.size();
144 void Input::endSequence() {
147 bool Input::preflightElement(unsigned Index
, void *&SaveInfo
) {
150 if (SequenceHNode
*SQ
= dyn_cast
<SequenceHNode
>(CurrentNode
)) {
151 SaveInfo
= CurrentNode
;
152 CurrentNode
= SQ
->Entries
[Index
];
158 void Input::postflightElement(void *SaveInfo
) {
159 CurrentNode
= reinterpret_cast<HNode
*>(SaveInfo
);
162 unsigned Input::beginFlowSequence() {
163 if (SequenceHNode
*SQ
= dyn_cast
<SequenceHNode
>(CurrentNode
)) {
164 return SQ
->Entries
.size();
169 bool Input::preflightFlowElement(unsigned index
, void *&SaveInfo
) {
172 if (SequenceHNode
*SQ
= dyn_cast
<SequenceHNode
>(CurrentNode
)) {
173 SaveInfo
= CurrentNode
;
174 CurrentNode
= SQ
->Entries
[index
];
180 void Input::postflightFlowElement(void *SaveInfo
) {
181 CurrentNode
= reinterpret_cast<HNode
*>(SaveInfo
);
184 void Input::endFlowSequence() {
187 void Input::beginEnumScalar() {
188 ScalarMatchFound
= false;
191 bool Input::matchEnumScalar(const char *Str
, bool) {
192 if (ScalarMatchFound
)
194 if (ScalarHNode
*SN
= dyn_cast
<ScalarHNode
>(CurrentNode
)) {
195 if (SN
->value().equals(Str
)) {
196 ScalarMatchFound
= true;
203 void Input::endEnumScalar() {
204 if (!ScalarMatchFound
) {
205 setError(CurrentNode
, "unknown enumerated scalar");
209 bool Input::beginBitSetScalar(bool &DoClear
) {
210 BitValuesUsed
.clear();
211 if (SequenceHNode
*SQ
= dyn_cast
<SequenceHNode
>(CurrentNode
)) {
212 BitValuesUsed
.insert(BitValuesUsed
.begin(), SQ
->Entries
.size(), false);
214 setError(CurrentNode
, "expected sequence of bit values");
220 bool Input::bitSetMatch(const char *Str
, bool) {
223 if (SequenceHNode
*SQ
= dyn_cast
<SequenceHNode
>(CurrentNode
)) {
225 for (std::vector
<HNode
*>::iterator i
= SQ
->Entries
.begin(),
226 End
= SQ
->Entries
.end(); i
!= End
; ++i
) {
227 if (ScalarHNode
*SN
= dyn_cast
<ScalarHNode
>(*i
)) {
228 if (SN
->value().equals(Str
)) {
229 BitValuesUsed
[Index
] = true;
233 setError(CurrentNode
, "unexpected scalar in sequence of bit values");
238 setError(CurrentNode
, "expected sequence of bit values");
243 void Input::endBitSetScalar() {
246 if (SequenceHNode
*SQ
= dyn_cast
<SequenceHNode
>(CurrentNode
)) {
247 assert(BitValuesUsed
.size() == SQ
->Entries
.size());
248 for (unsigned i
= 0; i
< SQ
->Entries
.size(); ++i
) {
249 if (!BitValuesUsed
[i
]) {
250 setError(SQ
->Entries
[i
], "unknown bit value");
257 void Input::scalarString(StringRef
&S
) {
258 if (ScalarHNode
*SN
= dyn_cast
<ScalarHNode
>(CurrentNode
)) {
261 setError(CurrentNode
, "unexpected scalar");
265 void Input::setError(HNode
*hnode
, const Twine
&message
) {
266 this->setError(hnode
->_node
, message
);
269 void Input::setError(Node
*node
, const Twine
&message
) {
270 Strm
->printError(node
, message
);
271 EC
= make_error_code(errc::invalid_argument
);
274 Input::HNode
*Input::createHNodes(Node
*N
) {
275 SmallString
<128> StringStorage
;
276 if (ScalarNode
*SN
= dyn_cast
<ScalarNode
>(N
)) {
277 StringRef KeyStr
= SN
->getValue(StringStorage
);
278 if (!StringStorage
.empty()) {
279 // Copy string to permanent storage
280 unsigned Len
= StringStorage
.size();
281 char *Buf
= StringAllocator
.Allocate
<char>(Len
);
282 memcpy(Buf
, &StringStorage
[0], Len
);
283 KeyStr
= StringRef(Buf
, Len
);
285 return new ScalarHNode(N
, KeyStr
);
286 } else if (SequenceNode
*SQ
= dyn_cast
<SequenceNode
>(N
)) {
287 SequenceHNode
*SQHNode
= new SequenceHNode(N
);
288 for (SequenceNode::iterator i
= SQ
->begin(), End
= SQ
->end(); i
!= End
;
290 HNode
*Entry
= this->createHNodes(i
);
293 SQHNode
->Entries
.push_back(Entry
);
296 } else if (MappingNode
*Map
= dyn_cast
<MappingNode
>(N
)) {
297 MapHNode
*mapHNode
= new MapHNode(N
);
298 for (MappingNode::iterator i
= Map
->begin(), End
= Map
->end(); i
!= End
;
300 ScalarNode
*KeyScalar
= dyn_cast
<ScalarNode
>(i
->getKey());
301 StringStorage
.clear();
302 StringRef KeyStr
= KeyScalar
->getValue(StringStorage
);
303 if (!StringStorage
.empty()) {
304 // Copy string to permanent storage
305 unsigned Len
= StringStorage
.size();
306 char *Buf
= StringAllocator
.Allocate
<char>(Len
);
307 memcpy(Buf
, &StringStorage
[0], Len
);
308 KeyStr
= StringRef(Buf
, Len
);
310 HNode
*ValueHNode
= this->createHNodes(i
->getValue());
313 mapHNode
->Mapping
[KeyStr
] = ValueHNode
;
316 } else if (isa
<NullNode
>(N
)) {
317 return new EmptyHNode(N
);
319 setError(N
, "unknown node kind");
324 bool Input::MapHNode::isValidKey(StringRef Key
) {
325 for (SmallVector
<const char *, 6>::iterator i
= ValidKeys
.begin(),
326 End
= ValidKeys
.end(); i
!= End
; ++i
) {
333 void Input::setError(const Twine
&Message
) {
334 this->setError(CurrentNode
, Message
);
337 Input::MapHNode::~MapHNode() {
338 for (MapHNode::NameToNode::iterator i
= Mapping
.begin(), End
= Mapping
.end();
344 Input::SequenceHNode::~SequenceHNode() {
345 for (std::vector
<HNode
*>::iterator i
= Entries
.begin(), End
= Entries
.end();
353 //===----------------------------------------------------------------------===//
355 //===----------------------------------------------------------------------===//
357 Output::Output(raw_ostream
&yout
, void *context
)
361 ColumnAtFlowStart(0),
362 NeedBitValueComma(false),
363 NeedFlowSequenceComma(false),
364 EnumerationMatchFound(false),
365 NeedsNewLine(false) {
371 bool Output::outputting() {
375 void Output::beginMapping() {
376 StateStack
.push_back(inMapFirstKey
);
380 void Output::endMapping() {
381 StateStack
.pop_back();
384 bool Output::preflightKey(const char *Key
, bool Required
, bool SameAsDefault
,
385 bool &UseDefault
, void *&) {
387 if (Required
|| !SameAsDefault
) {
388 this->newLineCheck();
389 this->paddedKey(Key
);
395 void Output::postflightKey(void *) {
396 if (StateStack
.back() == inMapFirstKey
) {
397 StateStack
.pop_back();
398 StateStack
.push_back(inMapOtherKey
);
402 void Output::beginDocuments() {
403 this->outputUpToEndOfLine("---");
406 bool Output::preflightDocument(unsigned index
) {
408 this->outputUpToEndOfLine("\n---");
412 void Output::postflightDocument() {
415 void Output::endDocuments() {
419 unsigned Output::beginSequence() {
420 StateStack
.push_back(inSeq
);
425 void Output::endSequence() {
426 StateStack
.pop_back();
429 bool Output::preflightElement(unsigned, void *&) {
433 void Output::postflightElement(void *) {
436 unsigned Output::beginFlowSequence() {
437 StateStack
.push_back(inFlowSeq
);
438 this->newLineCheck();
439 ColumnAtFlowStart
= Column
;
441 NeedFlowSequenceComma
= false;
445 void Output::endFlowSequence() {
446 StateStack
.pop_back();
447 this->outputUpToEndOfLine(" ]");
450 bool Output::preflightFlowElement(unsigned, void *&) {
451 if (NeedFlowSequenceComma
)
455 for (int i
= 0; i
< ColumnAtFlowStart
; ++i
)
457 Column
= ColumnAtFlowStart
;
463 void Output::postflightFlowElement(void *) {
464 NeedFlowSequenceComma
= true;
467 void Output::beginEnumScalar() {
468 EnumerationMatchFound
= false;
471 bool Output::matchEnumScalar(const char *Str
, bool Match
) {
472 if (Match
&& !EnumerationMatchFound
) {
473 this->newLineCheck();
474 this->outputUpToEndOfLine(Str
);
475 EnumerationMatchFound
= true;
480 void Output::endEnumScalar() {
481 if (!EnumerationMatchFound
)
482 llvm_unreachable("bad runtime enum value");
485 bool Output::beginBitSetScalar(bool &DoClear
) {
486 this->newLineCheck();
488 NeedBitValueComma
= false;
493 bool Output::bitSetMatch(const char *Str
, bool Matches
) {
495 if (NeedBitValueComma
)
498 NeedBitValueComma
= true;
503 void Output::endBitSetScalar() {
504 this->outputUpToEndOfLine(" ]");
507 void Output::scalarString(StringRef
&S
) {
508 this->newLineCheck();
509 if (S
.find('\n') == StringRef::npos
) {
510 // No embedded new-line chars, just print string.
511 this->outputUpToEndOfLine(S
);
516 unsigned End
= S
.size();
517 output("'"); // Starting single quote.
518 const char *Base
= S
.data();
520 // Escape a single quote by doubling it.
522 output(StringRef(&Base
[i
], j
- i
+ 1));
528 output(StringRef(&Base
[i
], j
- i
));
529 this->outputUpToEndOfLine("'"); // Ending single quote.
532 void Output::setError(const Twine
&message
) {
535 void Output::output(StringRef s
) {
540 void Output::outputUpToEndOfLine(StringRef s
) {
542 if (StateStack
.empty() || StateStack
.back() != inFlowSeq
)
546 void Output::outputNewLine() {
551 // if seq at top, indent as if map, then add "- "
552 // if seq in middle, use "- " if firstKey, else use " "
555 void Output::newLineCheck() {
558 NeedsNewLine
= false;
560 this->outputNewLine();
562 assert(StateStack
.size() > 0);
563 unsigned Indent
= StateStack
.size() - 1;
564 bool OutputDash
= false;
566 if (StateStack
.back() == inSeq
) {
568 } else if ((StateStack
.size() > 1) && (StateStack
.back() == inMapFirstKey
) &&
569 (StateStack
[StateStack
.size() - 2] == inSeq
)) {
574 for (unsigned i
= 0; i
< Indent
; ++i
) {
583 void Output::paddedKey(StringRef key
) {
586 const char *spaces
= " ";
587 if (key
.size() < strlen(spaces
))
588 output(&spaces
[key
.size()]);
593 //===----------------------------------------------------------------------===//
594 // traits for built-in types
595 //===----------------------------------------------------------------------===//
597 void ScalarTraits
<bool>::output(const bool &Val
, void *, raw_ostream
&Out
) {
598 Out
<< (Val
? "true" : "false");
601 StringRef ScalarTraits
<bool>::input(StringRef Scalar
, void *, bool &Val
) {
602 if (Scalar
.equals("true")) {
605 } else if (Scalar
.equals("false")) {
609 return "invalid boolean";
612 void ScalarTraits
<StringRef
>::output(const StringRef
&Val
, void *,
617 StringRef ScalarTraits
<StringRef
>::input(StringRef Scalar
, void *,
623 void ScalarTraits
<uint8_t>::output(const uint8_t &Val
, void *,
625 // use temp uin32_t because ostream thinks uint8_t is a character
630 StringRef ScalarTraits
<uint8_t>::input(StringRef Scalar
, void *, uint8_t &Val
) {
631 unsigned long long n
;
632 if (getAsUnsignedInteger(Scalar
, 0, n
))
633 return "invalid number";
635 return "out of range number";
640 void ScalarTraits
<uint16_t>::output(const uint16_t &Val
, void *,
645 StringRef ScalarTraits
<uint16_t>::input(StringRef Scalar
, void *,
647 unsigned long long n
;
648 if (getAsUnsignedInteger(Scalar
, 0, n
))
649 return "invalid number";
651 return "out of range number";
656 void ScalarTraits
<uint32_t>::output(const uint32_t &Val
, void *,
661 StringRef ScalarTraits
<uint32_t>::input(StringRef Scalar
, void *,
663 unsigned long long n
;
664 if (getAsUnsignedInteger(Scalar
, 0, n
))
665 return "invalid number";
666 if (n
> 0xFFFFFFFFUL
)
667 return "out of range number";
672 void ScalarTraits
<uint64_t>::output(const uint64_t &Val
, void *,
677 StringRef ScalarTraits
<uint64_t>::input(StringRef Scalar
, void *,
679 unsigned long long N
;
680 if (getAsUnsignedInteger(Scalar
, 0, N
))
681 return "invalid number";
686 void ScalarTraits
<int8_t>::output(const int8_t &Val
, void *, raw_ostream
&Out
) {
687 // use temp in32_t because ostream thinks int8_t is a character
692 StringRef ScalarTraits
<int8_t>::input(StringRef Scalar
, void *, int8_t &Val
) {
694 if (getAsSignedInteger(Scalar
, 0, N
))
695 return "invalid number";
696 if ((N
> 127) || (N
< -128))
697 return "out of range number";
702 void ScalarTraits
<int16_t>::output(const int16_t &Val
, void *,
707 StringRef ScalarTraits
<int16_t>::input(StringRef Scalar
, void *, int16_t &Val
) {
709 if (getAsSignedInteger(Scalar
, 0, N
))
710 return "invalid number";
711 if ((N
> INT16_MAX
) || (N
< INT16_MIN
))
712 return "out of range number";
717 void ScalarTraits
<int32_t>::output(const int32_t &Val
, void *,
722 StringRef ScalarTraits
<int32_t>::input(StringRef Scalar
, void *, int32_t &Val
) {
724 if (getAsSignedInteger(Scalar
, 0, N
))
725 return "invalid number";
726 if ((N
> INT32_MAX
) || (N
< INT32_MIN
))
727 return "out of range number";
732 void ScalarTraits
<int64_t>::output(const int64_t &Val
, void *,
737 StringRef ScalarTraits
<int64_t>::input(StringRef Scalar
, void *, int64_t &Val
) {
739 if (getAsSignedInteger(Scalar
, 0, N
))
740 return "invalid number";
745 void ScalarTraits
<double>::output(const double &Val
, void *, raw_ostream
&Out
) {
746 Out
<< format("%g", Val
);
749 StringRef ScalarTraits
<double>::input(StringRef Scalar
, void *, double &Val
) {
750 SmallString
<32> buff(Scalar
.begin(), Scalar
.end());
752 Val
= strtod(buff
.c_str(), &end
);
754 return "invalid floating point number";
758 void ScalarTraits
<float>::output(const float &Val
, void *, raw_ostream
&Out
) {
759 Out
<< format("%g", Val
);
762 StringRef ScalarTraits
<float>::input(StringRef Scalar
, void *, float &Val
) {
763 SmallString
<32> buff(Scalar
.begin(), Scalar
.end());
765 Val
= strtod(buff
.c_str(), &end
);
767 return "invalid floating point number";
771 void ScalarTraits
<Hex8
>::output(const Hex8
&Val
, void *, raw_ostream
&Out
) {
773 Out
<< format("0x%02X", Num
);
776 StringRef ScalarTraits
<Hex8
>::input(StringRef Scalar
, void *, Hex8
&Val
) {
777 unsigned long long n
;
778 if (getAsUnsignedInteger(Scalar
, 0, n
))
779 return "invalid hex8 number";
781 return "out of range hex8 number";
786 void ScalarTraits
<Hex16
>::output(const Hex16
&Val
, void *, raw_ostream
&Out
) {
788 Out
<< format("0x%04X", Num
);
791 StringRef ScalarTraits
<Hex16
>::input(StringRef Scalar
, void *, Hex16
&Val
) {
792 unsigned long long n
;
793 if (getAsUnsignedInteger(Scalar
, 0, n
))
794 return "invalid hex16 number";
796 return "out of range hex16 number";
801 void ScalarTraits
<Hex32
>::output(const Hex32
&Val
, void *, raw_ostream
&Out
) {
803 Out
<< format("0x%08X", Num
);
806 StringRef ScalarTraits
<Hex32
>::input(StringRef Scalar
, void *, Hex32
&Val
) {
807 unsigned long long n
;
808 if (getAsUnsignedInteger(Scalar
, 0, n
))
809 return "invalid hex32 number";
810 if (n
> 0xFFFFFFFFUL
)
811 return "out of range hex32 number";
816 void ScalarTraits
<Hex64
>::output(const Hex64
&Val
, void *, raw_ostream
&Out
) {
818 Out
<< format("0x%016llX", Num
);
821 StringRef ScalarTraits
<Hex64
>::input(StringRef Scalar
, void *, Hex64
&Val
) {
822 unsigned long long Num
;
823 if (getAsUnsignedInteger(Scalar
, 0, Num
))
824 return "invalid hex64 number";