[C++11] Replace LLVM-style type traits with C++11 standard ones.
[oota-llvm.git] / include / llvm / Support / YAMLTraits.h
1 //===- llvm/Support/YAMLTraits.h --------------------------------*- C++ -*-===//
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 #ifndef LLVM_SUPPORT_YAMLTRAITS_H
11 #define LLVM_SUPPORT_YAMLTRAITS_H
12
13
14 #include "llvm/ADT/DenseMap.h"
15 #include "llvm/ADT/DenseMapInfo.h"
16 #include "llvm/ADT/SmallVector.h"
17 #include "llvm/ADT/StringMap.h"
18 #include "llvm/ADT/StringRef.h"
19 #include "llvm/ADT/StringSwitch.h"
20 #include "llvm/ADT/Twine.h"
21 #include "llvm/Support/Compiler.h"
22 #include "llvm/Support/SourceMgr.h"
23 #include "llvm/Support/YAMLParser.h"
24 #include "llvm/Support/raw_ostream.h"
25 #include "llvm/Support/system_error.h"
26
27 namespace llvm {
28 namespace yaml {
29
30
31 /// This class should be specialized by any type that needs to be converted
32 /// to/from a YAML mapping.  For example:
33 ///
34 ///     struct ScalarBitSetTraits<MyStruct> {
35 ///       static void mapping(IO &io, MyStruct &s) {
36 ///         io.mapRequired("name", s.name);
37 ///         io.mapRequired("size", s.size);
38 ///         io.mapOptional("age",  s.age);
39 ///       }
40 ///     };
41 template<class T>
42 struct MappingTraits {
43   // Must provide:
44   // static void mapping(IO &io, T &fields);
45   // Optionally may provide:
46   // static StringRef validate(IO &io, T &fields);
47 };
48
49
50 /// This class should be specialized by any integral type that converts
51 /// to/from a YAML scalar where there is a one-to-one mapping between
52 /// in-memory values and a string in YAML.  For example:
53 ///
54 ///     struct ScalarEnumerationTraits<Colors> {
55 ///         static void enumeration(IO &io, Colors &value) {
56 ///           io.enumCase(value, "red",   cRed);
57 ///           io.enumCase(value, "blue",  cBlue);
58 ///           io.enumCase(value, "green", cGreen);
59 ///         }
60 ///       };
61 template<typename T>
62 struct ScalarEnumerationTraits {
63   // Must provide:
64   // static void enumeration(IO &io, T &value);
65 };
66
67
68 /// This class should be specialized by any integer type that is a union
69 /// of bit values and the YAML representation is a flow sequence of
70 /// strings.  For example:
71 ///
72 ///      struct ScalarBitSetTraits<MyFlags> {
73 ///        static void bitset(IO &io, MyFlags &value) {
74 ///          io.bitSetCase(value, "big",   flagBig);
75 ///          io.bitSetCase(value, "flat",  flagFlat);
76 ///          io.bitSetCase(value, "round", flagRound);
77 ///        }
78 ///      };
79 template<typename T>
80 struct ScalarBitSetTraits {
81   // Must provide:
82   // static void bitset(IO &io, T &value);
83 };
84
85
86 /// This class should be specialized by type that requires custom conversion
87 /// to/from a yaml scalar.  For example:
88 ///
89 ///    template<>
90 ///    struct ScalarTraits<MyType> {
91 ///      static void output(const MyType &val, void*, llvm::raw_ostream &out) {
92 ///        // stream out custom formatting
93 ///        out << llvm::format("%x", val);
94 ///      }
95 ///      static StringRef input(StringRef scalar, void*, MyType &value) {
96 ///        // parse scalar and set `value`
97 ///        // return empty string on success, or error string
98 ///        return StringRef();
99 ///      }
100 ///    };
101 template<typename T>
102 struct ScalarTraits {
103   // Must provide:
104   //
105   // Function to write the value as a string:
106   //static void output(const T &value, void *ctxt, llvm::raw_ostream &out);
107   //
108   // Function to convert a string to a value.  Returns the empty
109   // StringRef on success or an error string if string is malformed:
110   //static StringRef input(StringRef scalar, void *ctxt, T &value);
111 };
112
113
114 /// This class should be specialized by any type that needs to be converted
115 /// to/from a YAML sequence.  For example:
116 ///
117 ///    template<>
118 ///    struct SequenceTraits< std::vector<MyType> > {
119 ///      static size_t size(IO &io, std::vector<MyType> &seq) {
120 ///        return seq.size();
121 ///      }
122 ///      static MyType& element(IO &, std::vector<MyType> &seq, size_t index) {
123 ///        if ( index >= seq.size() )
124 ///          seq.resize(index+1);
125 ///        return seq[index];
126 ///      }
127 ///    };
128 template<typename T>
129 struct SequenceTraits {
130   // Must provide:
131   // static size_t size(IO &io, T &seq);
132   // static T::value_type& element(IO &io, T &seq, size_t index);
133   //
134   // The following is option and will cause generated YAML to use
135   // a flow sequence (e.g. [a,b,c]).
136   // static const bool flow = true;
137 };
138
139
140 /// This class should be specialized by any type that needs to be converted
141 /// to/from a list of YAML documents.
142 template<typename T>
143 struct DocumentListTraits {
144   // Must provide:
145   // static size_t size(IO &io, T &seq);
146   // static T::value_type& element(IO &io, T &seq, size_t index);
147 };
148
149
150 // Only used by compiler if both template types are the same
151 template <typename T, T>
152 struct SameType;
153
154 // Only used for better diagnostics of missing traits
155 template <typename T>
156 struct MissingTrait;
157
158
159
160 // Test if ScalarEnumerationTraits<T> is defined on type T.
161 template <class T>
162 struct has_ScalarEnumerationTraits
163 {
164   typedef void (*Signature_enumeration)(class IO&, T&);
165
166   template <typename U>
167   static char test(SameType<Signature_enumeration, &U::enumeration>*);
168
169   template <typename U>
170   static double test(...);
171
172 public:
173   static bool const value = (sizeof(test<ScalarEnumerationTraits<T> >(0)) == 1);
174 };
175
176
177 // Test if ScalarBitSetTraits<T> is defined on type T.
178 template <class T>
179 struct has_ScalarBitSetTraits
180 {
181   typedef void (*Signature_bitset)(class IO&, T&);
182
183   template <typename U>
184   static char test(SameType<Signature_bitset, &U::bitset>*);
185
186   template <typename U>
187   static double test(...);
188
189 public:
190   static bool const value = (sizeof(test<ScalarBitSetTraits<T> >(0)) == 1);
191 };
192
193
194 // Test if ScalarTraits<T> is defined on type T.
195 template <class T>
196 struct has_ScalarTraits
197 {
198   typedef StringRef (*Signature_input)(StringRef, void*, T&);
199   typedef void (*Signature_output)(const T&, void*, llvm::raw_ostream&);
200
201   template <typename U>
202   static char test(SameType<Signature_input, &U::input>*,
203                    SameType<Signature_output, &U::output>*);
204
205   template <typename U>
206   static double test(...);
207
208 public:
209   static bool const value = (sizeof(test<ScalarTraits<T> >(0,0)) == 1);
210 };
211
212
213 // Test if MappingTraits<T> is defined on type T.
214 template <class T>
215 struct has_MappingTraits
216 {
217   typedef void (*Signature_mapping)(class IO&, T&);
218
219   template <typename U>
220   static char test(SameType<Signature_mapping, &U::mapping>*);
221
222   template <typename U>
223   static double test(...);
224
225 public:
226   static bool const value = (sizeof(test<MappingTraits<T> >(0)) == 1);
227 };
228
229 // Test if MappingTraits<T>::validate() is defined on type T.
230 template <class T>
231 struct has_MappingValidateTraits
232 {
233   typedef StringRef (*Signature_validate)(class IO&, T&);
234
235   template <typename U>
236   static char test(SameType<Signature_validate, &U::validate>*);
237
238   template <typename U>
239   static double test(...);
240
241 public:
242   static bool const value = (sizeof(test<MappingTraits<T> >(0)) == 1);
243 };
244
245
246
247 // Test if SequenceTraits<T> is defined on type T.
248 template <class T>
249 struct has_SequenceMethodTraits
250 {
251   typedef size_t (*Signature_size)(class IO&, T&);
252
253   template <typename U>
254   static char test(SameType<Signature_size, &U::size>*);
255
256   template <typename U>
257   static double test(...);
258
259 public:
260   static bool const value =  (sizeof(test<SequenceTraits<T> >(0)) == 1);
261 };
262
263
264 // has_FlowTraits<int> will cause an error with some compilers because
265 // it subclasses int.  Using this wrapper only instantiates the
266 // real has_FlowTraits only if the template type is a class.
267 template <typename T, bool Enabled = std::is_class<T>::value>
268 class has_FlowTraits
269 {
270 public:
271    static const bool value = false;
272 };
273
274 // Some older gcc compilers don't support straight forward tests
275 // for members, so test for ambiguity cause by the base and derived
276 // classes both defining the member.
277 template <class T>
278 struct has_FlowTraits<T, true>
279 {
280   struct Fallback { bool flow; };
281   struct Derived : T, Fallback { };
282
283   template<typename C>
284   static char (&f(SameType<bool Fallback::*, &C::flow>*))[1];
285
286   template<typename C>
287   static char (&f(...))[2];
288
289 public:
290   static bool const value = sizeof(f<Derived>(0)) == 2;
291 };
292
293
294
295 // Test if SequenceTraits<T> is defined on type T
296 template<typename T>
297 struct has_SequenceTraits : public std::integral_constant<bool,
298                                       has_SequenceMethodTraits<T>::value > { };
299
300
301 // Test if DocumentListTraits<T> is defined on type T
302 template <class T>
303 struct has_DocumentListTraits
304 {
305   typedef size_t (*Signature_size)(class IO&, T&);
306
307   template <typename U>
308   static char test(SameType<Signature_size, &U::size>*);
309
310   template <typename U>
311   static double test(...);
312
313 public:
314   static bool const value =  (sizeof(test<DocumentListTraits<T> >(0)) == 1);
315 };
316
317
318
319
320 template<typename T>
321 struct missingTraits : public std::integral_constant<bool,
322                                          !has_ScalarEnumerationTraits<T>::value
323                                       && !has_ScalarBitSetTraits<T>::value
324                                       && !has_ScalarTraits<T>::value
325                                       && !has_MappingTraits<T>::value
326                                       && !has_SequenceTraits<T>::value
327                                       && !has_DocumentListTraits<T>::value >  {};
328
329 template<typename T>
330 struct validatedMappingTraits : public std::integral_constant<bool,
331                                        has_MappingTraits<T>::value
332                                     && has_MappingValidateTraits<T>::value> {};
333
334 template<typename T>
335 struct unvalidatedMappingTraits : public std::integral_constant<bool,
336                                         has_MappingTraits<T>::value
337                                     && !has_MappingValidateTraits<T>::value> {};
338 // Base class for Input and Output.
339 class IO {
340 public:
341
342   IO(void *Ctxt=NULL);
343   virtual ~IO();
344
345   virtual bool outputting() = 0;
346
347   virtual unsigned beginSequence() = 0;
348   virtual bool preflightElement(unsigned, void *&) = 0;
349   virtual void postflightElement(void*) = 0;
350   virtual void endSequence() = 0;
351   virtual bool canElideEmptySequence() = 0;
352
353   virtual unsigned beginFlowSequence() = 0;
354   virtual bool preflightFlowElement(unsigned, void *&) = 0;
355   virtual void postflightFlowElement(void*) = 0;
356   virtual void endFlowSequence() = 0;
357
358   virtual bool mapTag(StringRef Tag, bool Default=false) = 0;
359   virtual void beginMapping() = 0;
360   virtual void endMapping() = 0;
361   virtual bool preflightKey(const char*, bool, bool, bool &, void *&) = 0;
362   virtual void postflightKey(void*) = 0;
363
364   virtual void beginEnumScalar() = 0;
365   virtual bool matchEnumScalar(const char*, bool) = 0;
366   virtual void endEnumScalar() = 0;
367
368   virtual bool beginBitSetScalar(bool &) = 0;
369   virtual bool bitSetMatch(const char*, bool) = 0;
370   virtual void endBitSetScalar() = 0;
371
372   virtual void scalarString(StringRef &) = 0;
373
374   virtual void setError(const Twine &) = 0;
375
376   template <typename T>
377   void enumCase(T &Val, const char* Str, const T ConstVal) {
378     if ( matchEnumScalar(Str, outputting() && Val == ConstVal) ) {
379       Val = ConstVal;
380     }
381   }
382
383   // allow anonymous enum values to be used with LLVM_YAML_STRONG_TYPEDEF
384   template <typename T>
385   void enumCase(T &Val, const char* Str, const uint32_t ConstVal) {
386     if ( matchEnumScalar(Str, outputting() && Val == static_cast<T>(ConstVal)) ) {
387       Val = ConstVal;
388     }
389   }
390
391   template <typename T>
392   void bitSetCase(T &Val, const char* Str, const T ConstVal) {
393     if ( bitSetMatch(Str, outputting() && (Val & ConstVal) == ConstVal) ) {
394       Val = Val | ConstVal;
395     }
396   }
397
398   // allow anonymous enum values to be used with LLVM_YAML_STRONG_TYPEDEF
399   template <typename T>
400   void bitSetCase(T &Val, const char* Str, const uint32_t ConstVal) {
401     if ( bitSetMatch(Str, outputting() && (Val & ConstVal) == ConstVal) ) {
402       Val = Val | ConstVal;
403     }
404   }
405
406   void *getContext();
407   void setContext(void *);
408
409   template <typename T>
410   void mapRequired(const char* Key, T& Val) {
411     this->processKey(Key, Val, true);
412   }
413
414   template <typename T>
415   typename std::enable_if<has_SequenceTraits<T>::value,void>::type
416   mapOptional(const char* Key, T& Val) {
417     // omit key/value instead of outputting empty sequence
418     if ( this->canElideEmptySequence() && !(Val.begin() != Val.end()) )
419       return;
420     this->processKey(Key, Val, false);
421   }
422
423   template <typename T>
424   typename std::enable_if<!has_SequenceTraits<T>::value,void>::type
425   mapOptional(const char* Key, T& Val) {
426     this->processKey(Key, Val, false);
427   }
428
429   template <typename T>
430   void mapOptional(const char* Key, T& Val, const T& Default) {
431     this->processKeyWithDefault(Key, Val, Default, false);
432   }
433   
434 private:
435   template <typename T>
436   void processKeyWithDefault(const char *Key, T &Val, const T& DefaultValue,
437                                                                 bool Required) {
438     void *SaveInfo;
439     bool UseDefault;
440     const bool sameAsDefault = outputting() && Val == DefaultValue;
441     if ( this->preflightKey(Key, Required, sameAsDefault, UseDefault,
442                                                                   SaveInfo) ) {
443       yamlize(*this, Val, Required);
444       this->postflightKey(SaveInfo);
445     }
446     else {
447       if ( UseDefault )
448         Val = DefaultValue;
449     }
450   }
451
452   template <typename T>
453   void processKey(const char *Key, T &Val, bool Required) {
454     void *SaveInfo;
455     bool UseDefault;
456     if ( this->preflightKey(Key, Required, false, UseDefault, SaveInfo) ) {
457       yamlize(*this, Val, Required);
458       this->postflightKey(SaveInfo);
459     }
460   }
461
462 private:
463   void  *Ctxt;
464 };
465
466
467
468 template<typename T>
469 typename std::enable_if<has_ScalarEnumerationTraits<T>::value,void>::type
470 yamlize(IO &io, T &Val, bool) {
471   io.beginEnumScalar();
472   ScalarEnumerationTraits<T>::enumeration(io, Val);
473   io.endEnumScalar();
474 }
475
476 template<typename T>
477 typename std::enable_if<has_ScalarBitSetTraits<T>::value,void>::type
478 yamlize(IO &io, T &Val, bool) {
479   bool DoClear;
480   if ( io.beginBitSetScalar(DoClear) ) {
481     if ( DoClear )
482       Val = static_cast<T>(0);
483     ScalarBitSetTraits<T>::bitset(io, Val);
484     io.endBitSetScalar();
485   }
486 }
487
488
489 template<typename T>
490 typename std::enable_if<has_ScalarTraits<T>::value,void>::type
491 yamlize(IO &io, T &Val, bool) {
492   if ( io.outputting() ) {
493     std::string Storage;
494     llvm::raw_string_ostream Buffer(Storage);
495     ScalarTraits<T>::output(Val, io.getContext(), Buffer);
496     StringRef Str = Buffer.str();
497     io.scalarString(Str);
498   }
499   else {
500     StringRef Str;
501     io.scalarString(Str);
502     StringRef Result = ScalarTraits<T>::input(Str, io.getContext(), Val);
503     if ( !Result.empty() ) {
504       io.setError(llvm::Twine(Result));
505     }
506   }
507 }
508
509
510 template<typename T>
511 typename std::enable_if<validatedMappingTraits<T>::value, void>::type
512 yamlize(IO &io, T &Val, bool) {
513   io.beginMapping();
514   if (io.outputting()) {
515     StringRef Err = MappingTraits<T>::validate(io, Val);
516     if (!Err.empty()) {
517       llvm::errs() << Err << "\n";
518       assert(Err.empty() && "invalid struct trying to be written as yaml");
519     }
520   }
521   MappingTraits<T>::mapping(io, Val);
522   if (!io.outputting()) {
523     StringRef Err = MappingTraits<T>::validate(io, Val);
524     if (!Err.empty())
525       io.setError(Err);
526   }
527   io.endMapping();
528 }
529
530 template<typename T>
531 typename std::enable_if<unvalidatedMappingTraits<T>::value, void>::type
532 yamlize(IO &io, T &Val, bool) {
533   io.beginMapping();
534   MappingTraits<T>::mapping(io, Val);
535   io.endMapping();
536 }
537
538 template<typename T>
539 typename std::enable_if<missingTraits<T>::value, void>::type
540 yamlize(IO &io, T &Val, bool) {
541   char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)];
542 }
543
544 template<typename T>
545 typename std::enable_if<has_SequenceTraits<T>::value,void>::type
546 yamlize(IO &io, T &Seq, bool) {
547   if ( has_FlowTraits< SequenceTraits<T> >::value ) {
548     unsigned incnt = io.beginFlowSequence();
549     unsigned count = io.outputting() ? SequenceTraits<T>::size(io, Seq) : incnt;
550     for(unsigned i=0; i < count; ++i) {
551       void *SaveInfo;
552       if ( io.preflightFlowElement(i, SaveInfo) ) {
553         yamlize(io, SequenceTraits<T>::element(io, Seq, i), true);
554         io.postflightFlowElement(SaveInfo);
555       }
556     }
557     io.endFlowSequence();
558   }
559   else {
560     unsigned incnt = io.beginSequence();
561     unsigned count = io.outputting() ? SequenceTraits<T>::size(io, Seq) : incnt;
562     for(unsigned i=0; i < count; ++i) {
563       void *SaveInfo;
564       if ( io.preflightElement(i, SaveInfo) ) {
565         yamlize(io, SequenceTraits<T>::element(io, Seq, i), true);
566         io.postflightElement(SaveInfo);
567       }
568     }
569     io.endSequence();
570   }
571 }
572
573
574 template<>
575 struct ScalarTraits<bool> {
576   static void output(const bool &, void*, llvm::raw_ostream &);
577   static StringRef input(StringRef, void*, bool &);
578 };
579
580 template<>
581 struct ScalarTraits<StringRef> {
582   static void output(const StringRef &, void*, llvm::raw_ostream &);
583   static StringRef input(StringRef, void*, StringRef &);
584 };
585  
586 template<>
587 struct ScalarTraits<std::string> {
588   static void output(const std::string &, void*, llvm::raw_ostream &);
589   static StringRef input(StringRef, void*, std::string &);
590 };
591
592 template<>
593 struct ScalarTraits<uint8_t> {
594   static void output(const uint8_t &, void*, llvm::raw_ostream &);
595   static StringRef input(StringRef, void*, uint8_t &);
596 };
597
598 template<>
599 struct ScalarTraits<uint16_t> {
600   static void output(const uint16_t &, void*, llvm::raw_ostream &);
601   static StringRef input(StringRef, void*, uint16_t &);
602 };
603
604 template<>
605 struct ScalarTraits<uint32_t> {
606   static void output(const uint32_t &, void*, llvm::raw_ostream &);
607   static StringRef input(StringRef, void*, uint32_t &);
608 };
609
610 template<>
611 struct ScalarTraits<uint64_t> {
612   static void output(const uint64_t &, void*, llvm::raw_ostream &);
613   static StringRef input(StringRef, void*, uint64_t &);
614 };
615
616 template<>
617 struct ScalarTraits<int8_t> {
618   static void output(const int8_t &, void*, llvm::raw_ostream &);
619   static StringRef input(StringRef, void*, int8_t &);
620 };
621
622 template<>
623 struct ScalarTraits<int16_t> {
624   static void output(const int16_t &, void*, llvm::raw_ostream &);
625   static StringRef input(StringRef, void*, int16_t &);
626 };
627
628 template<>
629 struct ScalarTraits<int32_t> {
630   static void output(const int32_t &, void*, llvm::raw_ostream &);
631   static StringRef input(StringRef, void*, int32_t &);
632 };
633
634 template<>
635 struct ScalarTraits<int64_t> {
636   static void output(const int64_t &, void*, llvm::raw_ostream &);
637   static StringRef input(StringRef, void*, int64_t &);
638 };
639
640 template<>
641 struct ScalarTraits<float> {
642   static void output(const float &, void*, llvm::raw_ostream &);
643   static StringRef input(StringRef, void*, float &);
644 };
645
646 template<>
647 struct ScalarTraits<double> {
648   static void output(const double &, void*, llvm::raw_ostream &);
649   static StringRef input(StringRef, void*, double &);
650 };
651
652
653
654 // Utility for use within MappingTraits<>::mapping() method
655 // to [de]normalize an object for use with YAML conversion.
656 template <typename TNorm, typename TFinal>
657 struct MappingNormalization {
658   MappingNormalization(IO &i_o, TFinal &Obj)
659       : io(i_o), BufPtr(NULL), Result(Obj) {
660     if ( io.outputting() ) {
661       BufPtr = new (&Buffer) TNorm(io, Obj);
662     }
663     else {
664       BufPtr = new (&Buffer) TNorm(io);
665     }
666   }
667
668   ~MappingNormalization() {
669     if ( ! io.outputting() ) {
670       Result = BufPtr->denormalize(io);
671     }
672     BufPtr->~TNorm();
673   }
674
675   TNorm* operator->() { return BufPtr; }
676
677 private:
678   typedef llvm::AlignedCharArrayUnion<TNorm> Storage;
679
680   Storage       Buffer;
681   IO           &io;
682   TNorm        *BufPtr;
683   TFinal       &Result;
684 };
685
686
687
688 // Utility for use within MappingTraits<>::mapping() method
689 // to [de]normalize an object for use with YAML conversion.
690 template <typename TNorm, typename TFinal>
691 struct MappingNormalizationHeap {
692   MappingNormalizationHeap(IO &i_o, TFinal &Obj)
693     : io(i_o), BufPtr(NULL), Result(Obj) {
694     if ( io.outputting() ) {
695       BufPtr = new (&Buffer) TNorm(io, Obj);
696     }
697     else {
698       BufPtr = new TNorm(io);
699     }
700   }
701
702   ~MappingNormalizationHeap() {
703     if ( io.outputting() ) {
704       BufPtr->~TNorm();
705     }
706     else {
707       Result = BufPtr->denormalize(io);
708     }
709   }
710
711   TNorm* operator->() { return BufPtr; }
712
713 private:
714   typedef llvm::AlignedCharArrayUnion<TNorm> Storage;
715
716   Storage       Buffer;
717   IO           &io;
718   TNorm        *BufPtr;
719   TFinal       &Result;
720 };
721
722
723
724 ///
725 /// The Input class is used to parse a yaml document into in-memory structs
726 /// and vectors.
727 ///
728 /// It works by using YAMLParser to do a syntax parse of the entire yaml
729 /// document, then the Input class builds a graph of HNodes which wraps
730 /// each yaml Node.  The extra layer is buffering.  The low level yaml
731 /// parser only lets you look at each node once.  The buffering layer lets
732 /// you search and interate multiple times.  This is necessary because
733 /// the mapRequired() method calls may not be in the same order
734 /// as the keys in the document.
735 ///
736 class Input : public IO {
737 public:
738   // Construct a yaml Input object from a StringRef and optional
739   // user-data. The DiagHandler can be specified to provide
740   // alternative error reporting.
741   Input(StringRef InputContent,
742         void *Ctxt = NULL,
743         SourceMgr::DiagHandlerTy DiagHandler = NULL,
744         void *DiagHandlerCtxt = NULL);
745   ~Input();
746
747   // Check if there was an syntax or semantic error during parsing.
748   llvm::error_code error();
749
750 private:
751   bool outputting() override;
752   bool mapTag(StringRef, bool) override;
753   void beginMapping() override;
754   void endMapping() override;
755   bool preflightKey(const char *, bool, bool, bool &, void *&) override;
756   void postflightKey(void *) override;
757   unsigned beginSequence() override;
758   void endSequence() override;
759   bool preflightElement(unsigned index, void *&) override;
760   void postflightElement(void *) override;
761   unsigned beginFlowSequence() override;
762   bool preflightFlowElement(unsigned , void *&) override;
763   void postflightFlowElement(void *) override;
764   void endFlowSequence() override;
765   void beginEnumScalar() override;
766   bool matchEnumScalar(const char*, bool) override;
767   void endEnumScalar() override;
768   bool beginBitSetScalar(bool &) override;
769   bool bitSetMatch(const char *, bool ) override;
770   void endBitSetScalar() override;
771   void scalarString(StringRef &) override;
772   void setError(const Twine &message) override;
773   bool canElideEmptySequence() override;
774
775   class HNode {
776     virtual void anchor();
777   public:
778     HNode(Node *n) : _node(n) { }
779     virtual ~HNode() { }
780     static inline bool classof(const HNode *) { return true; }
781
782     Node *_node;
783   };
784
785   class EmptyHNode : public HNode {
786     void anchor() override;
787   public:
788     EmptyHNode(Node *n) : HNode(n) { }
789     static inline bool classof(const HNode *n) {
790       return NullNode::classof(n->_node);
791     }
792     static inline bool classof(const EmptyHNode *) { return true; }
793   };
794
795   class ScalarHNode : public HNode {
796     void anchor() override;
797   public:
798     ScalarHNode(Node *n, StringRef s) : HNode(n), _value(s) { }
799
800     StringRef value() const { return _value; }
801
802     static inline bool classof(const HNode *n) {
803       return ScalarNode::classof(n->_node);
804     }
805     static inline bool classof(const ScalarHNode *) { return true; }
806   protected:
807     StringRef _value;
808   };
809
810   class MapHNode : public HNode {
811   public:
812     MapHNode(Node *n) : HNode(n) { }
813     virtual ~MapHNode();
814
815     static inline bool classof(const HNode *n) {
816       return MappingNode::classof(n->_node);
817     }
818     static inline bool classof(const MapHNode *) { return true; }
819
820     typedef llvm::StringMap<HNode*> NameToNode;
821
822     bool isValidKey(StringRef key);
823
824     NameToNode                        Mapping;
825     llvm::SmallVector<const char*, 6> ValidKeys;
826   };
827
828   class SequenceHNode : public HNode {
829   public:
830     SequenceHNode(Node *n) : HNode(n) { }
831     virtual ~SequenceHNode();
832
833     static inline bool classof(const HNode *n) {
834       return SequenceNode::classof(n->_node);
835     }
836     static inline bool classof(const SequenceHNode *) { return true; }
837
838     std::vector<HNode*> Entries;
839   };
840
841   Input::HNode *createHNodes(Node *node);
842   void setError(HNode *hnode, const Twine &message);
843   void setError(Node *node, const Twine &message);
844
845
846 public:
847   // These are only used by operator>>. They could be private
848   // if those templated things could be made friends.
849   bool setCurrentDocument();
850   void nextDocument();
851
852 private:
853   llvm::SourceMgr                     SrcMgr; // must be before Strm
854   std::unique_ptr<llvm::yaml::Stream> Strm;
855   std::unique_ptr<HNode>              TopNode;
856   llvm::error_code                    EC;
857   llvm::BumpPtrAllocator              StringAllocator;
858   llvm::yaml::document_iterator       DocIterator;
859   std::vector<bool>                   BitValuesUsed;
860   HNode                              *CurrentNode;
861   bool                                ScalarMatchFound;
862 };
863
864
865
866
867 ///
868 /// The Output class is used to generate a yaml document from in-memory structs
869 /// and vectors.
870 ///
871 class Output : public IO {
872 public:
873   Output(llvm::raw_ostream &, void *Ctxt=NULL);
874   virtual ~Output();
875
876   bool outputting() override;
877   bool mapTag(StringRef, bool) override;
878   void beginMapping() override;
879   void endMapping() override;
880   bool preflightKey(const char *key, bool, bool, bool &, void *&) override;
881   void postflightKey(void *) override;
882   unsigned beginSequence() override;
883   void endSequence() override;
884   bool preflightElement(unsigned, void *&) override;
885   void postflightElement(void *) override;
886   unsigned beginFlowSequence() override;
887   bool preflightFlowElement(unsigned, void *&) override;
888   void postflightFlowElement(void *) override;
889   void endFlowSequence() override;
890   void beginEnumScalar() override;
891   bool matchEnumScalar(const char*, bool) override;
892   void endEnumScalar() override;
893   bool beginBitSetScalar(bool &) override;
894   bool bitSetMatch(const char *, bool ) override;
895   void endBitSetScalar() override;
896   void scalarString(StringRef &) override;
897   void setError(const Twine &message) override;
898   bool canElideEmptySequence() override;
899 public:
900   // These are only used by operator<<. They could be private
901   // if that templated operator could be made a friend.
902   void beginDocuments();
903   bool preflightDocument(unsigned);
904   void postflightDocument();
905   void endDocuments();
906
907 private:
908   void output(StringRef s);
909   void outputUpToEndOfLine(StringRef s);
910   void newLineCheck();
911   void outputNewLine();
912   void paddedKey(StringRef key);
913
914   enum InState { inSeq, inFlowSeq, inMapFirstKey, inMapOtherKey };
915
916   llvm::raw_ostream       &Out;
917   SmallVector<InState, 8>  StateStack;
918   int                      Column;
919   int                      ColumnAtFlowStart;
920   bool                     NeedBitValueComma;
921   bool                     NeedFlowSequenceComma;
922   bool                     EnumerationMatchFound;
923   bool                     NeedsNewLine;
924 };
925
926
927
928
929 /// YAML I/O does conversion based on types. But often native data types
930 /// are just a typedef of built in intergral types (e.g. int).  But the C++
931 /// type matching system sees through the typedef and all the typedefed types
932 /// look like a built in type. This will cause the generic YAML I/O conversion
933 /// to be used. To provide better control over the YAML conversion, you can
934 /// use this macro instead of typedef.  It will create a class with one field
935 /// and automatic conversion operators to and from the base type.
936 /// Based on BOOST_STRONG_TYPEDEF
937 #define LLVM_YAML_STRONG_TYPEDEF(_base, _type)                                 \
938     struct _type {                                                             \
939         _type() { }                                                            \
940         _type(const _base v) : value(v) { }                                    \
941         _type(const _type &v) : value(v.value) {}                              \
942         _type &operator=(const _type &rhs) { value = rhs.value; return *this; }\
943         _type &operator=(const _base &rhs) { value = rhs; return *this; }      \
944         operator const _base & () const { return value; }                      \
945         bool operator==(const _type &rhs) const { return value == rhs.value; } \
946         bool operator==(const _base &rhs) const { return value == rhs; }       \
947         bool operator<(const _type &rhs) const { return value < rhs.value; }   \
948         _base value;                                                           \
949     };
950
951
952
953 ///
954 /// Use these types instead of uintXX_t in any mapping to have
955 /// its yaml output formatted as hexadecimal.
956 ///
957 LLVM_YAML_STRONG_TYPEDEF(uint8_t, Hex8)
958 LLVM_YAML_STRONG_TYPEDEF(uint16_t, Hex16)
959 LLVM_YAML_STRONG_TYPEDEF(uint32_t, Hex32)
960 LLVM_YAML_STRONG_TYPEDEF(uint64_t, Hex64)
961
962
963 template<>
964 struct ScalarTraits<Hex8> {
965   static void output(const Hex8 &, void*, llvm::raw_ostream &);
966   static StringRef input(StringRef, void*, Hex8 &);
967 };
968
969 template<>
970 struct ScalarTraits<Hex16> {
971   static void output(const Hex16 &, void*, llvm::raw_ostream &);
972   static StringRef input(StringRef, void*, Hex16 &);
973 };
974
975 template<>
976 struct ScalarTraits<Hex32> {
977   static void output(const Hex32 &, void*, llvm::raw_ostream &);
978   static StringRef input(StringRef, void*, Hex32 &);
979 };
980
981 template<>
982 struct ScalarTraits<Hex64> {
983   static void output(const Hex64 &, void*, llvm::raw_ostream &);
984   static StringRef input(StringRef, void*, Hex64 &);
985 };
986
987
988 // Define non-member operator>> so that Input can stream in a document list.
989 template <typename T>
990 inline
991 typename std::enable_if<has_DocumentListTraits<T>::value, Input &>::type
992 operator>>(Input &yin, T &docList) {
993   int i = 0;
994   while ( yin.setCurrentDocument() ) {
995     yamlize(yin, DocumentListTraits<T>::element(yin, docList, i), true);
996     if ( yin.error() )
997       return yin;
998     yin.nextDocument();
999     ++i;
1000   }
1001   return yin;
1002 }
1003
1004 // Define non-member operator>> so that Input can stream in a map as a document.
1005 template <typename T>
1006 inline
1007 typename std::enable_if<has_MappingTraits<T>::value, Input &>::type
1008 operator>>(Input &yin, T &docMap) {
1009   yin.setCurrentDocument();
1010   yamlize(yin, docMap, true);
1011   return yin;
1012 }
1013
1014 // Define non-member operator>> so that Input can stream in a sequence as
1015 // a document.
1016 template <typename T>
1017 inline
1018 typename std::enable_if<has_SequenceTraits<T>::value, Input &>::type
1019 operator>>(Input &yin, T &docSeq) {
1020   if (yin.setCurrentDocument())
1021     yamlize(yin, docSeq, true);
1022   return yin;
1023 }
1024
1025 // Provide better error message about types missing a trait specialization
1026 template <typename T>
1027 inline
1028 typename std::enable_if<missingTraits<T>::value, Input &>::type
1029 operator>>(Input &yin, T &docSeq) {
1030   char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)];
1031   return yin;
1032 }
1033
1034
1035 // Define non-member operator<< so that Output can stream out document list.
1036 template <typename T>
1037 inline
1038 typename std::enable_if<has_DocumentListTraits<T>::value, Output &>::type
1039 operator<<(Output &yout, T &docList) {
1040   yout.beginDocuments();
1041   const size_t count = DocumentListTraits<T>::size(yout, docList);
1042   for(size_t i=0; i < count; ++i) {
1043     if ( yout.preflightDocument(i) ) {
1044       yamlize(yout, DocumentListTraits<T>::element(yout, docList, i), true);
1045       yout.postflightDocument();
1046     }
1047   }
1048   yout.endDocuments();
1049   return yout;
1050 }
1051
1052 // Define non-member operator<< so that Output can stream out a map.
1053 template <typename T>
1054 inline
1055 typename std::enable_if<has_MappingTraits<T>::value, Output &>::type
1056 operator<<(Output &yout, T &map) {
1057   yout.beginDocuments();
1058   if ( yout.preflightDocument(0) ) {
1059     yamlize(yout, map, true);
1060     yout.postflightDocument();
1061   }
1062   yout.endDocuments();
1063   return yout;
1064 }
1065
1066 // Define non-member operator<< so that Output can stream out a sequence.
1067 template <typename T>
1068 inline
1069 typename std::enable_if<has_SequenceTraits<T>::value, Output &>::type
1070 operator<<(Output &yout, T &seq) {
1071   yout.beginDocuments();
1072   if ( yout.preflightDocument(0) ) {
1073     yamlize(yout, seq, true);
1074     yout.postflightDocument();
1075   }
1076   yout.endDocuments();
1077   return yout;
1078 }
1079
1080 // Provide better error message about types missing a trait specialization
1081 template <typename T>
1082 inline
1083 typename std::enable_if<missingTraits<T>::value, Output &>::type
1084 operator<<(Output &yout, T &seq) {
1085   char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)];
1086   return yout;
1087 }
1088
1089
1090 } // namespace yaml
1091 } // namespace llvm
1092
1093
1094 /// Utility for declaring that a std::vector of a particular type
1095 /// should be considered a YAML sequence.
1096 #define LLVM_YAML_IS_SEQUENCE_VECTOR(_type)                                 \
1097   namespace llvm {                                                          \
1098   namespace yaml {                                                          \
1099     template<>                                                              \
1100     struct SequenceTraits< std::vector<_type> > {                           \
1101       static size_t size(IO &io, std::vector<_type> &seq) {                 \
1102         return seq.size();                                                  \
1103       }                                                                     \
1104       static _type& element(IO &io, std::vector<_type> &seq, size_t index) {\
1105         if ( index >= seq.size() )                                          \
1106           seq.resize(index+1);                                              \
1107         return seq[index];                                                  \
1108       }                                                                     \
1109     };                                                                      \
1110   }                                                                         \
1111   }
1112
1113 /// Utility for declaring that a std::vector of a particular type
1114 /// should be considered a YAML flow sequence.
1115 #define LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(_type)                            \
1116   namespace llvm {                                                          \
1117   namespace yaml {                                                          \
1118     template<>                                                              \
1119     struct SequenceTraits< std::vector<_type> > {                           \
1120       static size_t size(IO &io, std::vector<_type> &seq) {                 \
1121         return seq.size();                                                  \
1122       }                                                                     \
1123       static _type& element(IO &io, std::vector<_type> &seq, size_t index) {\
1124         (void)flow; /* Remove this workaround after PR17897 is fixed */     \
1125         if ( index >= seq.size() )                                          \
1126           seq.resize(index+1);                                              \
1127         return seq[index];                                                  \
1128       }                                                                     \
1129       static const bool flow = true;                                        \
1130     };                                                                      \
1131   }                                                                         \
1132   }
1133
1134 /// Utility for declaring that a std::vector of a particular type
1135 /// should be considered a YAML document list.
1136 #define LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(_type)                            \
1137   namespace llvm {                                                          \
1138   namespace yaml {                                                          \
1139     template<>                                                              \
1140     struct DocumentListTraits< std::vector<_type> > {                       \
1141       static size_t size(IO &io, std::vector<_type> &seq) {                 \
1142         return seq.size();                                                  \
1143       }                                                                     \
1144       static _type& element(IO &io, std::vector<_type> &seq, size_t index) {\
1145         if ( index >= seq.size() )                                          \
1146           seq.resize(index+1);                                              \
1147         return seq[index];                                                  \
1148       }                                                                     \
1149     };                                                                      \
1150   }                                                                         \
1151   }
1152
1153
1154
1155 #endif // LLVM_SUPPORT_YAMLTRAITS_H