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