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 #define BUILDING_YAMLIO
11 #include "llvm/Support/YAMLTraits.h"
13 #include "llvm/ADT/Twine.h"
14 #include "llvm/Support/Casting.h"
15 #include "llvm/Support/ErrorHandling.h"
16 #include "llvm/Support/format.h"
17 #include "llvm/Support/raw_ostream.h"
18 #include "llvm/Support/YAMLParser.h"
27 //===----------------------------------------------------------------------===//
29 //===----------------------------------------------------------------------===//
31 IO::IO(void *Context) : Ctxt(Context) {
37 void *IO::getContext() {
41 void IO::setContext(void *Context) {
46 //===----------------------------------------------------------------------===//
48 //===----------------------------------------------------------------------===//
50 Input::Input(StringRef InputContent, void *Ctxt)
51 : IO(Ctxt), CurrentNode(NULL) {
52 Strm = new Stream(InputContent, SrcMgr);
53 DocIterator = Strm->begin();
57 llvm::error_code Input::error() {
61 void Input::setDiagHandler(llvm::SourceMgr::DiagHandlerTy Handler, void *Ctxt) {
62 SrcMgr.setDiagHandler(Handler, Ctxt);
65 bool Input::outputting() {
69 bool Input::setCurrentDocument() {
70 if ( DocIterator != Strm->end() ) {
71 Node *N = DocIterator->getRoot();
72 if (llvm::isa<NullNode>(N)) {
73 // Empty files are allowed and ignored
75 return setCurrentDocument();
77 CurrentNode = this->createHNodes(N);
83 void Input::nextDocument() {
87 void Input::beginMapping() {
90 MapHNode *MN = llvm::dyn_cast<MapHNode>(CurrentNode);
92 MN->ValidKeys.clear();
96 bool Input::preflightKey(const char *Key, bool Required, bool,
97 bool &UseDefault, void *&SaveInfo) {
101 MapHNode *MN = llvm::dyn_cast<MapHNode>(CurrentNode);
103 setError(CurrentNode, "not a mapping");
106 MN->ValidKeys.push_back(Key);
107 HNode *Value = MN->Mapping[Key];
110 setError(CurrentNode, Twine("missing required key '") + Key + "'");
115 SaveInfo = CurrentNode;
120 void Input::postflightKey(void *saveInfo) {
121 CurrentNode = reinterpret_cast<HNode*>(saveInfo);
124 void Input::endMapping() {
127 MapHNode *MN = llvm::dyn_cast<MapHNode>(CurrentNode);
130 for (MapHNode::NameToNode::iterator i=MN->Mapping.begin(),
131 End=MN->Mapping.end(); i != End; ++i) {
132 if ( ! MN->isValidKey(i->first) ) {
133 setError(i->second, Twine("unknown key '") + i->first + "'" );
140 unsigned Input::beginSequence() {
141 if ( SequenceHNode *SQ = llvm::dyn_cast<SequenceHNode>(CurrentNode) ) {
142 return SQ->Entries.size();
146 void Input::endSequence() {
148 bool Input::preflightElement(unsigned Index, void *&SaveInfo) {
151 if ( SequenceHNode *SQ = llvm::dyn_cast<SequenceHNode>(CurrentNode) ) {
152 SaveInfo = CurrentNode;
153 CurrentNode = SQ->Entries[Index];
158 void Input::postflightElement(void *SaveInfo) {
159 CurrentNode = reinterpret_cast<HNode*>(SaveInfo);
162 unsigned Input::beginFlowSequence() {
163 if ( SequenceHNode *SQ = llvm::dyn_cast<SequenceHNode>(CurrentNode) ) {
164 return SQ->Entries.size();
168 bool Input::preflightFlowElement(unsigned index, void *&SaveInfo) {
171 if ( SequenceHNode *SQ = llvm::dyn_cast<SequenceHNode>(CurrentNode) ) {
172 SaveInfo = CurrentNode;
173 CurrentNode = SQ->Entries[index];
178 void Input::postflightFlowElement(void *SaveInfo) {
179 CurrentNode = reinterpret_cast<HNode*>(SaveInfo);
181 void Input::endFlowSequence() {
185 void Input::beginEnumScalar() {
186 ScalarMatchFound = false;
189 bool Input::matchEnumScalar(const char *Str, bool) {
190 if ( ScalarMatchFound )
192 if ( ScalarHNode *SN = llvm::dyn_cast<ScalarHNode>(CurrentNode) ) {
193 if ( SN->value().equals(Str) ) {
194 ScalarMatchFound = true;
201 void Input::endEnumScalar() {
202 if ( !ScalarMatchFound ) {
203 setError(CurrentNode, "unknown enumerated scalar");
209 bool Input::beginBitSetScalar(bool &DoClear) {
210 BitValuesUsed.clear();
211 if ( SequenceHNode *SQ = llvm::dyn_cast<SequenceHNode>(CurrentNode) ) {
212 BitValuesUsed.insert(BitValuesUsed.begin(), SQ->Entries.size(), false);
215 setError(CurrentNode, "expected sequence of bit values");
221 bool Input::bitSetMatch(const char *Str, bool) {
224 if ( SequenceHNode *SQ = llvm::dyn_cast<SequenceHNode>(CurrentNode) ) {
226 for (std::vector<HNode*>::iterator i=SQ->Entries.begin(),
227 End=SQ->Entries.end(); i != End; ++i) {
228 if ( ScalarHNode *SN = llvm::dyn_cast<ScalarHNode>(*i) ) {
229 if ( SN->value().equals(Str) ) {
230 BitValuesUsed[Index] = true;
235 setError(CurrentNode, "unexpected scalar in sequence of bit values");
241 setError(CurrentNode, "expected sequence of bit values");
246 void Input::endBitSetScalar() {
249 if ( SequenceHNode *SQ = llvm::dyn_cast<SequenceHNode>(CurrentNode) ) {
250 assert(BitValuesUsed.size() == SQ->Entries.size());
251 for ( unsigned i=0; i < SQ->Entries.size(); ++i ) {
252 if ( !BitValuesUsed[i] ) {
253 setError(SQ->Entries[i], "unknown bit value");
261 void Input::scalarString(StringRef &S) {
262 if ( ScalarHNode *SN = llvm::dyn_cast<ScalarHNode>(CurrentNode) ) {
266 setError(CurrentNode, "unexpected scalar");
270 void Input::setError(HNode *hnode, const Twine &message) {
271 this->setError(hnode->_node, message);
274 void Input::setError(Node *node, const Twine &message) {
275 Strm->printError(node, message);
276 EC = make_error_code(errc::invalid_argument);
279 Input::HNode *Input::createHNodes(Node *N) {
280 llvm::SmallString<128> StringStorage;
281 if ( ScalarNode *SN = llvm::dyn_cast<ScalarNode>(N) ) {
282 StringRef KeyStr = SN->getValue(StringStorage);
283 if ( !StringStorage.empty() ) {
284 // Copy string to permanent storage
285 unsigned Len = StringStorage.size();
286 char* Buf = Allocator.Allocate<char>(Len);
287 memcpy(Buf, &StringStorage[0], Len);
288 KeyStr = StringRef(Buf, Len);
290 return new (Allocator) ScalarHNode(N, KeyStr);
292 else if ( SequenceNode *SQ = llvm::dyn_cast<SequenceNode>(N) ) {
293 SequenceHNode *SQHNode = new (Allocator) SequenceHNode(N);
294 for (SequenceNode::iterator i=SQ->begin(),End=SQ->end(); i != End; ++i ) {
295 HNode *Entry = this->createHNodes(i);
298 SQHNode->Entries.push_back(Entry);
302 else if ( MappingNode *Map = llvm::dyn_cast<MappingNode>(N) ) {
303 MapHNode *mapHNode = new (Allocator) MapHNode(N);
304 for (MappingNode::iterator i=Map->begin(), End=Map->end(); i != End; ++i ) {
305 ScalarNode *KeyScalar = llvm::dyn_cast<ScalarNode>(i->getKey());
306 StringStorage.clear();
307 llvm::StringRef KeyStr = KeyScalar->getValue(StringStorage);
308 if ( !StringStorage.empty() ) {
309 // Copy string to permanent storage
310 unsigned Len = StringStorage.size();
311 char* Buf = Allocator.Allocate<char>(Len);
312 memcpy(Buf, &StringStorage[0], Len);
313 KeyStr = StringRef(Buf, Len);
315 HNode *ValueHNode = this->createHNodes(i->getValue());
318 mapHNode->Mapping[KeyStr] = ValueHNode;
322 else if ( llvm::isa<NullNode>(N) ) {
323 return new (Allocator) EmptyHNode(N);
326 setError(N, "unknown node kind");
332 bool Input::MapHNode::isValidKey(StringRef Key) {
333 for (SmallVector<const char*, 6>::iterator i=ValidKeys.begin(),
334 End=ValidKeys.end(); i != End; ++i) {
335 if ( Key.equals(*i) )
341 void Input::setError(const Twine &Message) {
342 this->setError(CurrentNode, Message);
346 //===----------------------------------------------------------------------===//
348 //===----------------------------------------------------------------------===//
350 Output::Output(llvm::raw_ostream &yout, void *context)
351 : IO(context), Out(yout), Column(0), ColumnAtFlowStart(0),
352 NeedBitValueComma(false), NeedFlowSequenceComma(false),
353 EnumerationMatchFound(false), NeedsNewLine(false) {
359 bool Output::outputting() {
363 void Output::beginMapping() {
364 StateStack.push_back(inMapFirstKey);
368 void Output::endMapping() {
369 StateStack.pop_back();
373 bool Output::preflightKey(const char *Key, bool Required, bool SameAsDefault,
374 bool &UseDefault, void *&) {
376 if ( Required || !SameAsDefault ) {
377 this->newLineCheck();
378 this->paddedKey(Key);
384 void Output::postflightKey(void*) {
385 if ( StateStack.back() == inMapFirstKey ) {
386 StateStack.pop_back();
387 StateStack.push_back(inMapOtherKey);
391 void Output::beginDocuments() {
392 this->outputUpToEndOfLine("---");
395 bool Output::preflightDocument(unsigned index) {
397 this->outputUpToEndOfLine("\n---");
401 void Output::postflightDocument() {
404 void Output::endDocuments() {
408 unsigned Output::beginSequence() {
409 StateStack.push_back(inSeq);
413 void Output::endSequence() {
414 StateStack.pop_back();
416 bool Output::preflightElement(unsigned , void *&) {
419 void Output::postflightElement(void*) {
422 unsigned Output::beginFlowSequence() {
423 this->newLineCheck();
424 StateStack.push_back(inFlowSeq);
425 ColumnAtFlowStart = Column;
427 NeedFlowSequenceComma = false;
430 void Output::endFlowSequence() {
431 StateStack.pop_back();
432 this->outputUpToEndOfLine(" ]");
434 bool Output::preflightFlowElement(unsigned , void *&) {
435 if ( NeedFlowSequenceComma )
439 for(int i=0; i < ColumnAtFlowStart; ++i)
441 Column = ColumnAtFlowStart;
446 void Output::postflightFlowElement(void*) {
447 NeedFlowSequenceComma = true;
452 void Output::beginEnumScalar() {
453 EnumerationMatchFound = false;
456 bool Output::matchEnumScalar(const char *Str, bool Match) {
457 if ( Match && !EnumerationMatchFound ) {
458 this->newLineCheck();
459 this->outputUpToEndOfLine(Str);
460 EnumerationMatchFound = true;
465 void Output::endEnumScalar() {
466 if ( !EnumerationMatchFound )
467 llvm_unreachable("bad runtime enum value");
472 bool Output::beginBitSetScalar(bool &DoClear) {
473 this->newLineCheck();
475 NeedBitValueComma = false;
480 bool Output::bitSetMatch(const char *Str, bool Matches) {
482 if ( NeedBitValueComma )
485 NeedBitValueComma = true;
490 void Output::endBitSetScalar() {
491 this->outputUpToEndOfLine(" ]");
494 void Output::scalarString(StringRef &S) {
495 this->newLineCheck();
496 if (S.find('\n') == StringRef::npos) {
497 // No embedded new-line chars, just print string.
498 this->outputUpToEndOfLine(S);
503 unsigned End = S.size();
504 output("'"); // Starting single quote.
505 const char *Base = S.data();
507 // Escape a single quote by doubling it.
509 output(StringRef(&Base[i], j - i + 1));
515 output(StringRef(&Base[i], j - i));
516 this->outputUpToEndOfLine("'"); // Ending single quote.
519 void Output::setError(const Twine &message) {
523 void Output::output(StringRef s) {
528 void Output::outputUpToEndOfLine(StringRef s) {
530 if ( StateStack.back() != inFlowSeq )
534 void Output::outputNewLine() {
539 // if seq at top, indent as if map, then add "- "
540 // if seq in middle, use "- " if firstKey, else use " "
543 void Output::newLineCheck() {
544 if ( ! NeedsNewLine )
546 NeedsNewLine = false;
548 this->outputNewLine();
550 assert(StateStack.size() > 0);
551 unsigned Indent = StateStack.size() - 1;
552 bool OutputDash = false;
554 if ( StateStack.back() == inSeq ) {
557 else if ( (StateStack.size() > 1)
558 && (StateStack.back() == inMapFirstKey)
559 && (StateStack[StateStack.size()-2] == inSeq) ) {
564 for (unsigned i=0; i < Indent; ++i) {
573 void Output::paddedKey(StringRef key) {
576 const char *spaces = " ";
577 if ( key.size() < strlen(spaces) )
578 output(&spaces[key.size()]);
583 //===----------------------------------------------------------------------===//
584 // traits for built-in types
585 //===----------------------------------------------------------------------===//
588 struct ScalarTraits<bool> {
589 static void output(const bool &Val, void*, llvm::raw_ostream &Out) {
590 Out << ( Val ? "true" : "false");
592 static llvm::StringRef input(llvm::StringRef Scalar, void*, bool &Val) {
593 if ( Scalar.equals("true") ) {
597 else if ( Scalar.equals("false") ) {
601 return "invalid boolean";
607 struct ScalarTraits<StringRef> {
608 static void output(const StringRef &Val, void*, llvm::raw_ostream &Out) {
611 static llvm::StringRef input(llvm::StringRef Scalar, void*, StringRef &Val){
619 struct ScalarTraits<uint8_t> {
620 static void output(const uint8_t &Val, void*, llvm::raw_ostream &Out) {
621 // use temp uin32_t because ostream thinks uint8_t is a character
625 static llvm::StringRef input(llvm::StringRef Scalar, void*, uint8_t &Val) {
627 if ( getAsUnsignedInteger(Scalar, 0, n) )
628 return "invalid number";
630 return "out of range number";
638 struct ScalarTraits<uint16_t> {
639 static void output(const uint16_t &Val, void*, llvm::raw_ostream &Out) {
642 static llvm::StringRef input(llvm::StringRef Scalar, void*, uint16_t &Val) {
644 if ( getAsUnsignedInteger(Scalar, 0, n) )
645 return "invalid number";
647 return "out of range number";
654 struct ScalarTraits<uint32_t> {
655 static void output(const uint32_t &Val, void*, llvm::raw_ostream &Out) {
658 static llvm::StringRef input(llvm::StringRef Scalar, void*, uint32_t &Val) {
660 if ( getAsUnsignedInteger(Scalar, 0, n) )
661 return "invalid number";
662 if ( n > 0xFFFFFFFFUL )
663 return "out of range number";
671 struct ScalarTraits<uint64_t> {
672 static void output(const uint64_t &Val, void*, llvm::raw_ostream &Out) {
675 static llvm::StringRef input(llvm::StringRef Scalar, void*, uint64_t &Val) {
676 if ( getAsUnsignedInteger(Scalar, 0, Val) )
677 return "invalid number";
684 struct ScalarTraits<int8_t> {
685 static void output(const int8_t &Val, void*, llvm::raw_ostream &Out) {
686 // use temp in32_t because ostream thinks int8_t is a character
690 static llvm::StringRef input(llvm::StringRef Scalar, void*, int8_t &Val) {
692 if ( getAsSignedInteger(Scalar, 0, n) )
693 return "invalid number";
694 if ( (n > 127) || (n < -128) )
695 return "out of range number";
703 struct ScalarTraits<int16_t> {
704 static void output(const int16_t &Val, void*, llvm::raw_ostream &Out) {
707 static llvm::StringRef input(llvm::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";
720 struct ScalarTraits<int32_t> {
721 static void output(const int32_t &Val, void*, llvm::raw_ostream &Out) {
724 static llvm::StringRef input(llvm::StringRef Scalar, void*, int32_t &Val) {
726 if ( getAsSignedInteger(Scalar, 0, n) )
727 return "invalid number";
728 if ( (n > INT32_MAX) || (n < INT32_MIN) )
729 return "out of range number";
736 struct ScalarTraits<int64_t> {
737 static void output(const int64_t &Val, void*, llvm::raw_ostream &Out) {
740 static llvm::StringRef input(llvm::StringRef Scalar, void*, int64_t &Val) {
741 if ( getAsSignedInteger(Scalar, 0, Val) )
742 return "invalid number";
748 struct ScalarTraits<double> {
749 static void output(const double &Val, void*, llvm::raw_ostream &Out) {
750 Out << format("%g", Val);
752 static llvm::StringRef input(llvm::StringRef Scalar, void*, double &Val) {
753 SmallString<32> buff(Scalar.begin(), Scalar.end());
755 Val = strtod(buff.c_str(), &end);
757 return "invalid floating point number";
763 struct ScalarTraits<float> {
764 static void output(const float &Val, void*, llvm::raw_ostream &Out) {
765 Out << format("%g", Val);
767 static llvm::StringRef input(llvm::StringRef Scalar, void*, float &Val) {
768 SmallString<32> buff(Scalar.begin(), Scalar.end());
770 Val = strtod(buff.c_str(), &end);
772 return "invalid floating point number";
780 struct ScalarTraits<Hex8> {
781 static void output(const Hex8 &Val, void*, llvm::raw_ostream &Out) {
783 Out << format("0x%02X", Num);
785 static llvm::StringRef input(llvm::StringRef Scalar, void*, Hex8 &Val) {
787 if ( getAsUnsignedInteger(Scalar, 0, n) )
788 return "invalid hex8 number";
790 return "out of range hex8 number";
798 struct ScalarTraits<Hex16> {
799 static void output(const Hex16 &Val, void*, llvm::raw_ostream &Out) {
801 Out << format("0x%04X", Num);
803 static llvm::StringRef input(llvm::StringRef Scalar, void*, Hex16 &Val) {
805 if ( getAsUnsignedInteger(Scalar, 0, n) )
806 return "invalid hex16 number";
808 return "out of range hex16 number";
815 struct ScalarTraits<Hex32> {
816 static void output(const Hex32 &Val, void*, llvm::raw_ostream &Out) {
818 Out << format("0x%08X", Num);
820 static llvm::StringRef input(llvm::StringRef Scalar, void*, Hex32 &Val) {
822 if ( getAsUnsignedInteger(Scalar, 0, n) )
823 return "invalid hex32 number";
824 if ( n > 0xFFFFFFFFUL )
825 return "out of range hex32 number";
833 struct ScalarTraits<Hex64> {
834 static void output(const Hex64 &Val, void*, llvm::raw_ostream &Out) {
836 Out << format("0x%016llX", Num);
838 static llvm::StringRef input(llvm::StringRef Scalar, void*, Hex64 &Val) {
840 if ( getAsUnsignedInteger(Scalar, 0, Num) )
841 return "invalid hex64 number";
850 // We want all the ScalarTrait specialized on built-in types
851 // to be instantiated here.
852 template <typename T>
854 ForceUse() : oproc(ScalarTraits<T>::output), iproc(ScalarTraits<T>::input) {}
855 void (*oproc)(const T &, void*, llvm::raw_ostream &);
856 llvm::StringRef (*iproc)(llvm::StringRef, void*, T &);
859 static ForceUse<bool> Dummy1;
860 static ForceUse<llvm::StringRef> Dummy2;
861 static ForceUse<uint8_t> Dummy3;
862 static ForceUse<uint16_t> Dummy4;
863 static ForceUse<uint32_t> Dummy5;
864 static ForceUse<uint64_t> Dummy6;
865 static ForceUse<int8_t> Dummy7;
866 static ForceUse<int16_t> Dummy8;
867 static ForceUse<int32_t> Dummy9;
868 static ForceUse<int64_t> Dummy10;
869 static ForceUse<float> Dummy11;
870 static ForceUse<double> Dummy12;
871 static ForceUse<Hex8> Dummy13;
872 static ForceUse<Hex16> Dummy14;
873 static ForceUse<Hex32> Dummy15;
874 static ForceUse<Hex64> Dummy16;