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