blob: f7f68e3a8013020836ca07e82cd864356ff9d575 [file] [log] [blame]
Nick Kledzik8ceb8b72012-12-12 20:46:15 +00001//===- 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#define BUILDING_YAMLIO
11#include "llvm/Support/YAMLTraits.h"
Nick Kledzik8ceb8b72012-12-12 20:46:15 +000012#include "llvm/ADT/Twine.h"
13#include "llvm/Support/Casting.h"
14#include "llvm/Support/ErrorHandling.h"
Benjamin Kramer11b07f62012-12-12 20:55:44 +000015#include "llvm/Support/Format.h"
Nick Kledzik8ceb8b72012-12-12 20:46:15 +000016#include "llvm/Support/YAMLParser.h"
Benjamin Kramer11b07f62012-12-12 20:55:44 +000017#include "llvm/Support/raw_ostream.h"
Nick Kledzik8ceb8b72012-12-12 20:46:15 +000018#include <cstring>
19
20namespace llvm {
21namespace yaml {
22
23
24
25//===----------------------------------------------------------------------===//
26// IO
27//===----------------------------------------------------------------------===//
28
29IO::IO(void *Context) : Ctxt(Context) {
30}
31
32IO::~IO() {
33}
34
35void *IO::getContext() {
36 return Ctxt;
37}
38
39void IO::setContext(void *Context) {
40 Ctxt = Context;
41}
42
43
44//===----------------------------------------------------------------------===//
45// Input
46//===----------------------------------------------------------------------===//
47
48Input::Input(StringRef InputContent, void *Ctxt)
49 : IO(Ctxt), CurrentNode(NULL) {
50 Strm = new Stream(InputContent, SrcMgr);
51 DocIterator = Strm->begin();
52}
53
54
55llvm::error_code Input::error() {
56 return EC;
57}
58
59void Input::setDiagHandler(llvm::SourceMgr::DiagHandlerTy Handler, void *Ctxt) {
60 SrcMgr.setDiagHandler(Handler, Ctxt);
61}
62
63bool Input::outputting() {
64 return false;
65}
66
67bool Input::setCurrentDocument() {
68 if ( DocIterator != Strm->end() ) {
69 Node *N = DocIterator->getRoot();
70 if (llvm::isa<NullNode>(N)) {
71 // Empty files are allowed and ignored
72 ++DocIterator;
73 return setCurrentDocument();
74 }
75 CurrentNode = this->createHNodes(N);
76 return true;
77 }
78 return false;
79}
80
81void Input::nextDocument() {
82 ++DocIterator;
83}
84
85void Input::beginMapping() {
86 if ( EC )
87 return;
88 MapHNode *MN = llvm::dyn_cast<MapHNode>(CurrentNode);
89 if ( MN ) {
90 MN->ValidKeys.clear();
91 }
92}
93
94bool Input::preflightKey(const char *Key, bool Required, bool,
95 bool &UseDefault, void *&SaveInfo) {
96 UseDefault = false;
97 if ( EC )
98 return false;
99 MapHNode *MN = llvm::dyn_cast<MapHNode>(CurrentNode);
100 if ( !MN ) {
101 setError(CurrentNode, "not a mapping");
102 return false;
103 }
104 MN->ValidKeys.push_back(Key);
105 HNode *Value = MN->Mapping[Key];
106 if ( !Value ) {
107 if ( Required )
108 setError(CurrentNode, Twine("missing required key '") + Key + "'");
109 else
110 UseDefault = true;
111 return false;
112 }
113 SaveInfo = CurrentNode;
114 CurrentNode = Value;
115 return true;
116}
117
118void Input::postflightKey(void *saveInfo) {
119 CurrentNode = reinterpret_cast<HNode*>(saveInfo);
120}
121
122void Input::endMapping() {
123 if ( EC )
124 return;
125 MapHNode *MN = llvm::dyn_cast<MapHNode>(CurrentNode);
126 if ( !MN )
127 return;
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 + "'" );
132 break;
133 }
134 }
135}
136
137
138unsigned Input::beginSequence() {
139 if ( SequenceHNode *SQ = llvm::dyn_cast<SequenceHNode>(CurrentNode) ) {
140 return SQ->Entries.size();
141 }
142 return 0;
143}
144void Input::endSequence() {
145}
146bool Input::preflightElement(unsigned Index, void *&SaveInfo) {
147 if ( EC )
148 return false;
149 if ( SequenceHNode *SQ = llvm::dyn_cast<SequenceHNode>(CurrentNode) ) {
150 SaveInfo = CurrentNode;
151 CurrentNode = SQ->Entries[Index];
152 return true;
153 }
154 return false;
155}
156void Input::postflightElement(void *SaveInfo) {
157 CurrentNode = reinterpret_cast<HNode*>(SaveInfo);
158}
159
160unsigned Input::beginFlowSequence() {
161 if ( SequenceHNode *SQ = llvm::dyn_cast<SequenceHNode>(CurrentNode) ) {
162 return SQ->Entries.size();
163 }
164 return 0;
165}
166bool Input::preflightFlowElement(unsigned index, void *&SaveInfo) {
167 if ( EC )
168 return false;
169 if ( SequenceHNode *SQ = llvm::dyn_cast<SequenceHNode>(CurrentNode) ) {
170 SaveInfo = CurrentNode;
171 CurrentNode = SQ->Entries[index];
172 return true;
173 }
174 return false;
175}
176void Input::postflightFlowElement(void *SaveInfo) {
177 CurrentNode = reinterpret_cast<HNode*>(SaveInfo);
178}
179void Input::endFlowSequence() {
180}
181
182
183void Input::beginEnumScalar() {
184 ScalarMatchFound = false;
185}
186
187bool Input::matchEnumScalar(const char *Str, bool) {
188 if ( ScalarMatchFound )
189 return false;
190 if ( ScalarHNode *SN = llvm::dyn_cast<ScalarHNode>(CurrentNode) ) {
191 if ( SN->value().equals(Str) ) {
192 ScalarMatchFound = true;
193 return true;
194 }
195 }
196 return false;
197}
198
199void Input::endEnumScalar() {
200 if ( !ScalarMatchFound ) {
201 setError(CurrentNode, "unknown enumerated scalar");
202 }
203}
204
205
206
207bool Input::beginBitSetScalar(bool &DoClear) {
208 BitValuesUsed.clear();
209 if ( SequenceHNode *SQ = llvm::dyn_cast<SequenceHNode>(CurrentNode) ) {
210 BitValuesUsed.insert(BitValuesUsed.begin(), SQ->Entries.size(), false);
211 }
212 else {
213 setError(CurrentNode, "expected sequence of bit values");
214 }
215 DoClear = true;
216 return true;
217}
218
219bool Input::bitSetMatch(const char *Str, bool) {
220 if ( EC )
221 return false;
222 if ( SequenceHNode *SQ = llvm::dyn_cast<SequenceHNode>(CurrentNode) ) {
223 unsigned Index = 0;
224 for (std::vector<HNode*>::iterator i=SQ->Entries.begin(),
225 End=SQ->Entries.end(); i != End; ++i) {
226 if ( ScalarHNode *SN = llvm::dyn_cast<ScalarHNode>(*i) ) {
227 if ( SN->value().equals(Str) ) {
228 BitValuesUsed[Index] = true;
229 return true;
230 }
231 }
232 else {
233 setError(CurrentNode, "unexpected scalar in sequence of bit values");
234 }
235 ++Index;
236 }
237 }
238 else {
239 setError(CurrentNode, "expected sequence of bit values");
240 }
241 return false;
242}
243
244void Input::endBitSetScalar() {
245 if ( EC )
246 return;
247 if ( SequenceHNode *SQ = llvm::dyn_cast<SequenceHNode>(CurrentNode) ) {
248 assert(BitValuesUsed.size() == SQ->Entries.size());
249 for ( unsigned i=0; i < SQ->Entries.size(); ++i ) {
250 if ( !BitValuesUsed[i] ) {
251 setError(SQ->Entries[i], "unknown bit value");
252 return;
253 }
254 }
255 }
256}
257
258
259void Input::scalarString(StringRef &S) {
260 if ( ScalarHNode *SN = llvm::dyn_cast<ScalarHNode>(CurrentNode) ) {
261 S = SN->value();
262 }
263 else {
264 setError(CurrentNode, "unexpected scalar");
265 }
266}
267
268void Input::setError(HNode *hnode, const Twine &message) {
269 this->setError(hnode->_node, message);
270}
271
272void Input::setError(Node *node, const Twine &message) {
273 Strm->printError(node, message);
274 EC = make_error_code(errc::invalid_argument);
275}
276
277Input::HNode *Input::createHNodes(Node *N) {
278 llvm::SmallString<128> StringStorage;
279 if ( ScalarNode *SN = llvm::dyn_cast<ScalarNode>(N) ) {
280 StringRef KeyStr = SN->getValue(StringStorage);
281 if ( !StringStorage.empty() ) {
282 // Copy string to permanent storage
283 unsigned Len = StringStorage.size();
284 char* Buf = Allocator.Allocate<char>(Len);
285 memcpy(Buf, &StringStorage[0], Len);
286 KeyStr = StringRef(Buf, Len);
287 }
288 return new (Allocator) ScalarHNode(N, KeyStr);
289 }
290 else if ( SequenceNode *SQ = llvm::dyn_cast<SequenceNode>(N) ) {
291 SequenceHNode *SQHNode = new (Allocator) SequenceHNode(N);
292 for (SequenceNode::iterator i=SQ->begin(),End=SQ->end(); i != End; ++i ) {
293 HNode *Entry = this->createHNodes(i);
294 if ( EC )
295 break;
296 SQHNode->Entries.push_back(Entry);
297 }
298 return SQHNode;
299 }
300 else if ( MappingNode *Map = llvm::dyn_cast<MappingNode>(N) ) {
301 MapHNode *mapHNode = new (Allocator) MapHNode(N);
302 for (MappingNode::iterator i=Map->begin(), End=Map->end(); i != End; ++i ) {
303 ScalarNode *KeyScalar = llvm::dyn_cast<ScalarNode>(i->getKey());
304 StringStorage.clear();
305 llvm::StringRef KeyStr = KeyScalar->getValue(StringStorage);
306 if ( !StringStorage.empty() ) {
307 // Copy string to permanent storage
308 unsigned Len = StringStorage.size();
309 char* Buf = Allocator.Allocate<char>(Len);
310 memcpy(Buf, &StringStorage[0], Len);
311 KeyStr = StringRef(Buf, Len);
312 }
313 HNode *ValueHNode = this->createHNodes(i->getValue());
314 if ( EC )
315 break;
316 mapHNode->Mapping[KeyStr] = ValueHNode;
317 }
318 return mapHNode;
319 }
320 else if ( llvm::isa<NullNode>(N) ) {
321 return new (Allocator) EmptyHNode(N);
322 }
323 else {
324 setError(N, "unknown node kind");
325 return NULL;
326 }
327}
328
329
330bool Input::MapHNode::isValidKey(StringRef Key) {
331 for (SmallVector<const char*, 6>::iterator i=ValidKeys.begin(),
332 End=ValidKeys.end(); i != End; ++i) {
333 if ( Key.equals(*i) )
334 return true;
335 }
336 return false;
337}
338
339void Input::setError(const Twine &Message) {
340 this->setError(CurrentNode, Message);
341}
342
343
344//===----------------------------------------------------------------------===//
345// Output
346//===----------------------------------------------------------------------===//
347
348Output::Output(llvm::raw_ostream &yout, void *context)
349 : IO(context), Out(yout), Column(0), ColumnAtFlowStart(0),
350 NeedBitValueComma(false), NeedFlowSequenceComma(false),
351 EnumerationMatchFound(false), NeedsNewLine(false) {
352}
353
354Output::~Output() {
355}
356
357bool Output::outputting() {
358 return true;
359}
360
361void Output::beginMapping() {
362 StateStack.push_back(inMapFirstKey);
363 NeedsNewLine = true;
364}
365
366void Output::endMapping() {
367 StateStack.pop_back();
368}
369
370
371bool Output::preflightKey(const char *Key, bool Required, bool SameAsDefault,
372 bool &UseDefault, void *&) {
373 UseDefault = false;
374 if ( Required || !SameAsDefault ) {
375 this->newLineCheck();
376 this->paddedKey(Key);
377 return true;
378 }
379 return false;
380}
381
382void Output::postflightKey(void*) {
383 if ( StateStack.back() == inMapFirstKey ) {
384 StateStack.pop_back();
385 StateStack.push_back(inMapOtherKey);
386 }
387}
388
389void Output::beginDocuments() {
390 this->outputUpToEndOfLine("---");
391}
392
393bool Output::preflightDocument(unsigned index) {
394 if ( index > 0 )
395 this->outputUpToEndOfLine("\n---");
396 return true;
397}
398
399void Output::postflightDocument() {
400}
401
402void Output::endDocuments() {
403 output("\n...\n");
404}
405
406unsigned Output::beginSequence() {
407 StateStack.push_back(inSeq);
408 NeedsNewLine = true;
409 return 0;
410}
411void Output::endSequence() {
412 StateStack.pop_back();
413}
414bool Output::preflightElement(unsigned , void *&) {
415 return true;
416}
417void Output::postflightElement(void*) {
418}
419
420unsigned Output::beginFlowSequence() {
421 this->newLineCheck();
422 StateStack.push_back(inFlowSeq);
423 ColumnAtFlowStart = Column;
424 output("[ ");
425 NeedFlowSequenceComma = false;
426 return 0;
427}
428void Output::endFlowSequence() {
429 StateStack.pop_back();
430 this->outputUpToEndOfLine(" ]");
431}
432bool Output::preflightFlowElement(unsigned , void *&) {
433 if ( NeedFlowSequenceComma )
434 output(", ");
435 if ( Column > 70 ) {
436 output("\n");
437 for(int i=0; i < ColumnAtFlowStart; ++i)
438 output(" ");
439 Column = ColumnAtFlowStart;
440 output(" ");
441 }
442 return true;
443}
444void Output::postflightFlowElement(void*) {
445 NeedFlowSequenceComma = true;
446}
447
448
449
450void Output::beginEnumScalar() {
451 EnumerationMatchFound = false;
452}
453
454bool Output::matchEnumScalar(const char *Str, bool Match) {
455 if ( Match && !EnumerationMatchFound ) {
456 this->newLineCheck();
457 this->outputUpToEndOfLine(Str);
458 EnumerationMatchFound = true;
459 }
460 return false;
461}
462
463void Output::endEnumScalar() {
464 if ( !EnumerationMatchFound )
465 llvm_unreachable("bad runtime enum value");
466}
467
468
469
470bool Output::beginBitSetScalar(bool &DoClear) {
471 this->newLineCheck();
472 output("[ ");
473 NeedBitValueComma = false;
474 DoClear = false;
475 return true;
476}
477
478bool Output::bitSetMatch(const char *Str, bool Matches) {
479 if ( Matches ) {
480 if ( NeedBitValueComma )
481 output(", ");
482 this->output(Str);
483 NeedBitValueComma = true;
484 }
485 return false;
486}
487
488void Output::endBitSetScalar() {
489 this->outputUpToEndOfLine(" ]");
490}
491
492void Output::scalarString(StringRef &S) {
493 this->newLineCheck();
494 if (S.find('\n') == StringRef::npos) {
495 // No embedded new-line chars, just print string.
496 this->outputUpToEndOfLine(S);
497 return;
498 }
499 unsigned i = 0;
500 unsigned j = 0;
501 unsigned End = S.size();
502 output("'"); // Starting single quote.
503 const char *Base = S.data();
504 while (j < End) {
505 // Escape a single quote by doubling it.
506 if (S[j] == '\'') {
507 output(StringRef(&Base[i], j - i + 1));
508 output("'");
509 i = j + 1;
510 }
511 ++j;
512 }
513 output(StringRef(&Base[i], j - i));
514 this->outputUpToEndOfLine("'"); // Ending single quote.
515}
516
517void Output::setError(const Twine &message) {
518}
519
520
521void Output::output(StringRef s) {
522 Column += s.size();
523 Out << s;
524}
525
526void Output::outputUpToEndOfLine(StringRef s) {
527 this->output(s);
528 if ( StateStack.back() != inFlowSeq )
529 NeedsNewLine = true;
530}
531
532void Output::outputNewLine() {
533 Out << "\n";
534 Column = 0;
535}
536
537// if seq at top, indent as if map, then add "- "
538// if seq in middle, use "- " if firstKey, else use " "
539//
540
541void Output::newLineCheck() {
542 if ( ! NeedsNewLine )
543 return;
544 NeedsNewLine = false;
545
546 this->outputNewLine();
547
548 assert(StateStack.size() > 0);
549 unsigned Indent = StateStack.size() - 1;
550 bool OutputDash = false;
551
552 if ( StateStack.back() == inSeq ) {
553 OutputDash = true;
554 }
555 else if ( (StateStack.size() > 1)
556 && (StateStack.back() == inMapFirstKey)
557 && (StateStack[StateStack.size()-2] == inSeq) ) {
558 --Indent;
559 OutputDash = true;
560 }
561
562 for (unsigned i=0; i < Indent; ++i) {
563 output(" ");
564 }
565 if ( OutputDash ) {
566 output("- ");
567 }
568
569}
570
571void Output::paddedKey(StringRef key) {
572 output(key);
573 output(":");
574 const char *spaces = " ";
575 if ( key.size() < strlen(spaces) )
576 output(&spaces[key.size()]);
577 else
578 output(" ");
579}
580
581//===----------------------------------------------------------------------===//
582// traits for built-in types
583//===----------------------------------------------------------------------===//
584
585template<>
586struct ScalarTraits<bool> {
587 static void output(const bool &Val, void*, llvm::raw_ostream &Out) {
588 Out << ( Val ? "true" : "false");
589 }
590 static llvm::StringRef input(llvm::StringRef Scalar, void*, bool &Val) {
591 if ( Scalar.equals("true") ) {
592 Val = true;
593 return StringRef();
594 }
595 else if ( Scalar.equals("false") ) {
596 Val = false;
597 return StringRef();
598 }
599 return "invalid boolean";
600 }
601};
602
603
604template<>
605struct ScalarTraits<StringRef> {
606 static void output(const StringRef &Val, void*, llvm::raw_ostream &Out) {
607 Out << Val;
608 }
609 static llvm::StringRef input(llvm::StringRef Scalar, void*, StringRef &Val){
610 Val = Scalar;
611 return StringRef();
612 }
613};
614
615
616template<>
617struct ScalarTraits<uint8_t> {
618 static void output(const uint8_t &Val, void*, llvm::raw_ostream &Out) {
619 // use temp uin32_t because ostream thinks uint8_t is a character
620 uint32_t Num = Val;
621 Out << Num;
622 }
623 static llvm::StringRef input(llvm::StringRef Scalar, void*, uint8_t &Val) {
Nick Kledzik1ebae9a2012-12-12 21:42:49 +0000624 unsigned long long n;
Nick Kledzik8ceb8b72012-12-12 20:46:15 +0000625 if ( getAsUnsignedInteger(Scalar, 0, n) )
626 return "invalid number";
627 if ( n > 0xFF )
628 return "out of range number";
629 Val = n;
630 return StringRef();
631 }
632};
633
634
635template<>
636struct ScalarTraits<uint16_t> {
637 static void output(const uint16_t &Val, void*, llvm::raw_ostream &Out) {
638 Out << Val;
639 }
640 static llvm::StringRef input(llvm::StringRef Scalar, void*, uint16_t &Val) {
Nick Kledzik1ebae9a2012-12-12 21:42:49 +0000641 unsigned long long n;
Nick Kledzik8ceb8b72012-12-12 20:46:15 +0000642 if ( getAsUnsignedInteger(Scalar, 0, n) )
643 return "invalid number";
644 if ( n > 0xFFFF )
645 return "out of range number";
646 Val = n;
647 return StringRef();
648 }
649};
650
651template<>
652struct ScalarTraits<uint32_t> {
653 static void output(const uint32_t &Val, void*, llvm::raw_ostream &Out) {
654 Out << Val;
655 }
656 static llvm::StringRef input(llvm::StringRef Scalar, void*, uint32_t &Val) {
Nick Kledzik1ebae9a2012-12-12 21:42:49 +0000657 unsigned long long n;
Nick Kledzik8ceb8b72012-12-12 20:46:15 +0000658 if ( getAsUnsignedInteger(Scalar, 0, n) )
659 return "invalid number";
660 if ( n > 0xFFFFFFFFUL )
661 return "out of range number";
662 Val = n;
663 return StringRef();
664 }
665};
666
667
668template<>
669struct ScalarTraits<uint64_t> {
670 static void output(const uint64_t &Val, void*, llvm::raw_ostream &Out) {
671 Out << Val;
672 }
673 static llvm::StringRef input(llvm::StringRef Scalar, void*, uint64_t &Val) {
Nick Kledzik1ebae9a2012-12-12 21:42:49 +0000674 unsigned long long N;
675 if ( getAsUnsignedInteger(Scalar, 0, N) )
Nick Kledzik8ceb8b72012-12-12 20:46:15 +0000676 return "invalid number";
Nick Kledzik1ebae9a2012-12-12 21:42:49 +0000677 Val = N;
Nick Kledzik8ceb8b72012-12-12 20:46:15 +0000678 return StringRef();
679 }
680};
681
682
683template<>
684struct 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
687 int32_t Num = Val;
688 Out << Num;
689 }
690 static llvm::StringRef input(llvm::StringRef Scalar, void*, int8_t &Val) {
Nick Kledzik1ebae9a2012-12-12 21:42:49 +0000691 long long N;
692 if ( getAsSignedInteger(Scalar, 0, N) )
Nick Kledzik8ceb8b72012-12-12 20:46:15 +0000693 return "invalid number";
Nick Kledzik1ebae9a2012-12-12 21:42:49 +0000694 if ( (N > 127) || (N < -128) )
Nick Kledzik8ceb8b72012-12-12 20:46:15 +0000695 return "out of range number";
Nick Kledzik1ebae9a2012-12-12 21:42:49 +0000696 Val = N;
Nick Kledzik8ceb8b72012-12-12 20:46:15 +0000697 return StringRef();
698 }
699};
700
701
702template<>
703struct ScalarTraits<int16_t> {
704 static void output(const int16_t &Val, void*, llvm::raw_ostream &Out) {
705 Out << Val;
706 }
707 static llvm::StringRef input(llvm::StringRef Scalar, void*, int16_t &Val) {
Nick Kledzik1ebae9a2012-12-12 21:42:49 +0000708 long long N;
709 if ( getAsSignedInteger(Scalar, 0, N) )
Nick Kledzik8ceb8b72012-12-12 20:46:15 +0000710 return "invalid number";
Nick Kledzik1ebae9a2012-12-12 21:42:49 +0000711 if ( (N > INT16_MAX) || (N < INT16_MIN) )
Nick Kledzik8ceb8b72012-12-12 20:46:15 +0000712 return "out of range number";
Nick Kledzik1ebae9a2012-12-12 21:42:49 +0000713 Val = N;
Nick Kledzik8ceb8b72012-12-12 20:46:15 +0000714 return StringRef();
715 }
716};
717
718
719template<>
720struct ScalarTraits<int32_t> {
721 static void output(const int32_t &Val, void*, llvm::raw_ostream &Out) {
722 Out << Val;
723 }
724 static llvm::StringRef input(llvm::StringRef Scalar, void*, int32_t &Val) {
Nick Kledzik1ebae9a2012-12-12 21:42:49 +0000725 long long N;
726 if ( getAsSignedInteger(Scalar, 0, N) )
Nick Kledzik8ceb8b72012-12-12 20:46:15 +0000727 return "invalid number";
Nick Kledzik1ebae9a2012-12-12 21:42:49 +0000728 if ( (N > INT32_MAX) || (N < INT32_MIN) )
Nick Kledzik8ceb8b72012-12-12 20:46:15 +0000729 return "out of range number";
Nick Kledzik1ebae9a2012-12-12 21:42:49 +0000730 Val = N;
Nick Kledzik8ceb8b72012-12-12 20:46:15 +0000731 return StringRef();
732 }
733};
734
735template<>
736struct ScalarTraits<int64_t> {
737 static void output(const int64_t &Val, void*, llvm::raw_ostream &Out) {
738 Out << Val;
739 }
740 static llvm::StringRef input(llvm::StringRef Scalar, void*, int64_t &Val) {
Nick Kledzik1ebae9a2012-12-12 21:42:49 +0000741 long long N;
742 if ( getAsSignedInteger(Scalar, 0, N) )
Nick Kledzik8ceb8b72012-12-12 20:46:15 +0000743 return "invalid number";
Nick Kledzik1ebae9a2012-12-12 21:42:49 +0000744 Val = N;
Nick Kledzik8ceb8b72012-12-12 20:46:15 +0000745 return StringRef();
746 }
747};
748
749template<>
750struct ScalarTraits<double> {
751 static void output(const double &Val, void*, llvm::raw_ostream &Out) {
752 Out << format("%g", Val);
753 }
754 static llvm::StringRef input(llvm::StringRef Scalar, void*, double &Val) {
755 SmallString<32> buff(Scalar.begin(), Scalar.end());
756 char *end;
757 Val = strtod(buff.c_str(), &end);
758 if ( *end != '\0' )
759 return "invalid floating point number";
760 return StringRef();
761 }
762};
763
764template<>
765struct ScalarTraits<float> {
766 static void output(const float &Val, void*, llvm::raw_ostream &Out) {
767 Out << format("%g", Val);
768 }
769 static llvm::StringRef input(llvm::StringRef Scalar, void*, float &Val) {
770 SmallString<32> buff(Scalar.begin(), Scalar.end());
771 char *end;
772 Val = strtod(buff.c_str(), &end);
773 if ( *end != '\0' )
774 return "invalid floating point number";
775 return StringRef();
776 }
777};
778
779
780
781template<>
782struct ScalarTraits<Hex8> {
783 static void output(const Hex8 &Val, void*, llvm::raw_ostream &Out) {
784 uint8_t Num = Val;
785 Out << format("0x%02X", Num);
786 }
787 static llvm::StringRef input(llvm::StringRef Scalar, void*, Hex8 &Val) {
Nick Kledzik1ebae9a2012-12-12 21:42:49 +0000788 unsigned long long n;
Nick Kledzik8ceb8b72012-12-12 20:46:15 +0000789 if ( getAsUnsignedInteger(Scalar, 0, n) )
790 return "invalid hex8 number";
791 if ( n > 0xFF )
792 return "out of range hex8 number";
793 Val = n;
794 return StringRef();
795 }
796};
797
798
799template<>
800struct ScalarTraits<Hex16> {
801 static void output(const Hex16 &Val, void*, llvm::raw_ostream &Out) {
802 uint16_t Num = Val;
803 Out << format("0x%04X", Num);
804 }
805 static llvm::StringRef input(llvm::StringRef Scalar, void*, Hex16 &Val) {
Nick Kledzik1ebae9a2012-12-12 21:42:49 +0000806 unsigned long long n;
Nick Kledzik8ceb8b72012-12-12 20:46:15 +0000807 if ( getAsUnsignedInteger(Scalar, 0, n) )
808 return "invalid hex16 number";
809 if ( n > 0xFFFF )
810 return "out of range hex16 number";
811 Val = n;
812 return StringRef();
813 }
814};
815
816template<>
817struct ScalarTraits<Hex32> {
818 static void output(const Hex32 &Val, void*, llvm::raw_ostream &Out) {
819 uint32_t Num = Val;
820 Out << format("0x%08X", Num);
821 }
822 static llvm::StringRef input(llvm::StringRef Scalar, void*, Hex32 &Val) {
Nick Kledzik1ebae9a2012-12-12 21:42:49 +0000823 unsigned long long n;
Nick Kledzik8ceb8b72012-12-12 20:46:15 +0000824 if ( getAsUnsignedInteger(Scalar, 0, n) )
825 return "invalid hex32 number";
826 if ( n > 0xFFFFFFFFUL )
827 return "out of range hex32 number";
828 Val = n;
829 return StringRef();
830 }
831};
832
833
834template<>
835struct ScalarTraits<Hex64> {
836 static void output(const Hex64 &Val, void*, llvm::raw_ostream &Out) {
837 uint64_t Num = Val;
838 Out << format("0x%016llX", Num);
839 }
840 static llvm::StringRef input(llvm::StringRef Scalar, void*, Hex64 &Val) {
Nick Kledzik1ebae9a2012-12-12 21:42:49 +0000841 unsigned long long Num;
Nick Kledzik8ceb8b72012-12-12 20:46:15 +0000842 if ( getAsUnsignedInteger(Scalar, 0, Num) )
843 return "invalid hex64 number";
844 Val = Num;
845 return StringRef();
846 }
847};
848
849
850
851
852// We want all the ScalarTrait specialized on built-in types
853// to be instantiated here.
854template <typename T>
855struct ForceUse {
856 ForceUse() : oproc(ScalarTraits<T>::output), iproc(ScalarTraits<T>::input) {}
857 void (*oproc)(const T &, void*, llvm::raw_ostream &);
858 llvm::StringRef (*iproc)(llvm::StringRef, void*, T &);
859};
860
861static ForceUse<bool> Dummy1;
862static ForceUse<llvm::StringRef> Dummy2;
863static ForceUse<uint8_t> Dummy3;
864static ForceUse<uint16_t> Dummy4;
865static ForceUse<uint32_t> Dummy5;
866static ForceUse<uint64_t> Dummy6;
867static ForceUse<int8_t> Dummy7;
868static ForceUse<int16_t> Dummy8;
869static ForceUse<int32_t> Dummy9;
870static ForceUse<int64_t> Dummy10;
871static ForceUse<float> Dummy11;
872static ForceUse<double> Dummy12;
873static ForceUse<Hex8> Dummy13;
874static ForceUse<Hex16> Dummy14;
875static ForceUse<Hex32> Dummy15;
876static ForceUse<Hex64> Dummy16;
877
878
879
880} // namespace yaml
881} // namespace llvm
882
883