]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - include/llvm/Support/YAMLTraits.h
Vendor import of llvm trunk r291012:
[FreeBSD/FreeBSD.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 #include "llvm/ADT/Optional.h"
14 #include "llvm/ADT/SmallVector.h"
15 #include "llvm/ADT/StringMap.h"
16 #include "llvm/ADT/StringRef.h"
17 #include "llvm/ADT/Twine.h"
18 #include "llvm/Support/AlignOf.h"
19 #include "llvm/Support/Allocator.h"
20 #include "llvm/Support/Endian.h"
21 #include "llvm/Support/Regex.h"
22 #include "llvm/Support/SourceMgr.h"
23 #include "llvm/Support/YAMLParser.h"
24 #include "llvm/Support/raw_ostream.h"
25 #include <cassert>
26 #include <cctype>
27 #include <cstddef>
28 #include <cstdint>
29 #include <memory>
30 #include <new>
31 #include <string>
32 #include <system_error>
33 #include <type_traits>
34 #include <vector>
35
36 namespace llvm {
37 namespace yaml {
38
39 struct EmptyContext {};
40
41 /// This class should be specialized by any type that needs to be converted
42 /// to/from a YAML mapping.  For example:
43 ///
44 ///     struct MappingTraits<MyStruct> {
45 ///       static void mapping(IO &io, MyStruct &s) {
46 ///         io.mapRequired("name", s.name);
47 ///         io.mapRequired("size", s.size);
48 ///         io.mapOptional("age",  s.age);
49 ///       }
50 ///     };
51 template<class T>
52 struct MappingTraits {
53   // Must provide:
54   // static void mapping(IO &io, T &fields);
55   // Optionally may provide:
56   // static StringRef validate(IO &io, T &fields);
57   //
58   // The optional flow flag will cause generated YAML to use a flow mapping
59   // (e.g. { a: 0, b: 1 }):
60   // static const bool flow = true;
61 };
62
63 /// This class is similar to MappingTraits<T> but allows you to pass in
64 /// additional context for each map operation.  For example:
65 ///
66 ///     struct MappingContextTraits<MyStruct, MyContext> {
67 ///       static void mapping(IO &io, MyStruct &s, MyContext &c) {
68 ///         io.mapRequired("name", s.name);
69 ///         io.mapRequired("size", s.size);
70 ///         io.mapOptional("age",  s.age);
71 ///         ++c.TimesMapped;
72 ///       }
73 ///     };
74 template <class T, class Context> struct MappingContextTraits {
75   // Must provide:
76   // static void mapping(IO &io, T &fields, Context &Ctx);
77   // Optionally may provide:
78   // static StringRef validate(IO &io, T &fields, Context &Ctx);
79   //
80   // The optional flow flag will cause generated YAML to use a flow mapping
81   // (e.g. { a: 0, b: 1 }):
82   // static const bool flow = true;
83 };
84
85 /// This class should be specialized by any integral type that converts
86 /// to/from a YAML scalar where there is a one-to-one mapping between
87 /// in-memory values and a string in YAML.  For example:
88 ///
89 ///     struct ScalarEnumerationTraits<Colors> {
90 ///         static void enumeration(IO &io, Colors &value) {
91 ///           io.enumCase(value, "red",   cRed);
92 ///           io.enumCase(value, "blue",  cBlue);
93 ///           io.enumCase(value, "green", cGreen);
94 ///         }
95 ///       };
96 template<typename T>
97 struct ScalarEnumerationTraits {
98   // Must provide:
99   // static void enumeration(IO &io, T &value);
100 };
101
102 /// This class should be specialized by any integer type that is a union
103 /// of bit values and the YAML representation is a flow sequence of
104 /// strings.  For example:
105 ///
106 ///      struct ScalarBitSetTraits<MyFlags> {
107 ///        static void bitset(IO &io, MyFlags &value) {
108 ///          io.bitSetCase(value, "big",   flagBig);
109 ///          io.bitSetCase(value, "flat",  flagFlat);
110 ///          io.bitSetCase(value, "round", flagRound);
111 ///        }
112 ///      };
113 template<typename T>
114 struct ScalarBitSetTraits {
115   // Must provide:
116   // static void bitset(IO &io, T &value);
117 };
118
119 /// This class should be specialized by type that requires custom conversion
120 /// to/from a yaml scalar.  For example:
121 ///
122 ///    template<>
123 ///    struct ScalarTraits<MyType> {
124 ///      static void output(const MyType &val, void*, llvm::raw_ostream &out) {
125 ///        // stream out custom formatting
126 ///        out << llvm::format("%x", val);
127 ///      }
128 ///      static StringRef input(StringRef scalar, void*, MyType &value) {
129 ///        // parse scalar and set `value`
130 ///        // return empty string on success, or error string
131 ///        return StringRef();
132 ///      }
133 ///      static bool mustQuote(StringRef) { return true; }
134 ///    };
135 template<typename T>
136 struct ScalarTraits {
137   // Must provide:
138   //
139   // Function to write the value as a string:
140   //static void output(const T &value, void *ctxt, llvm::raw_ostream &out);
141   //
142   // Function to convert a string to a value.  Returns the empty
143   // StringRef on success or an error string if string is malformed:
144   //static StringRef input(StringRef scalar, void *ctxt, T &value);
145   //
146   // Function to determine if the value should be quoted.
147   //static bool mustQuote(StringRef);
148 };
149
150 /// This class should be specialized by type that requires custom conversion
151 /// to/from a YAML literal block scalar. For example:
152 ///
153 ///    template <>
154 ///    struct BlockScalarTraits<MyType> {
155 ///      static void output(const MyType &Value, void*, llvm::raw_ostream &Out)
156 ///      {
157 ///        // stream out custom formatting
158 ///        Out << Val;
159 ///      }
160 ///      static StringRef input(StringRef Scalar, void*, MyType &Value) {
161 ///        // parse scalar and set `value`
162 ///        // return empty string on success, or error string
163 ///        return StringRef();
164 ///      }
165 ///    };
166 template <typename T>
167 struct BlockScalarTraits {
168   // Must provide:
169   //
170   // Function to write the value as a string:
171   // static void output(const T &Value, void *ctx, llvm::raw_ostream &Out);
172   //
173   // Function to convert a string to a value.  Returns the empty
174   // StringRef on success or an error string if string is malformed:
175   // static StringRef input(StringRef Scalar, void *ctxt, T &Value);
176 };
177
178 /// This class should be specialized by any type that needs to be converted
179 /// to/from a YAML sequence.  For example:
180 ///
181 ///    template<>
182 ///    struct SequenceTraits< std::vector<MyType>> {
183 ///      static size_t size(IO &io, std::vector<MyType> &seq) {
184 ///        return seq.size();
185 ///      }
186 ///      static MyType& element(IO &, std::vector<MyType> &seq, size_t index) {
187 ///        if ( index >= seq.size() )
188 ///          seq.resize(index+1);
189 ///        return seq[index];
190 ///      }
191 ///    };
192 template<typename T>
193 struct SequenceTraits {
194   // Must provide:
195   // static size_t size(IO &io, T &seq);
196   // static T::value_type& element(IO &io, T &seq, size_t index);
197   //
198   // The following is option and will cause generated YAML to use
199   // a flow sequence (e.g. [a,b,c]).
200   // static const bool flow = true;
201 };
202
203 /// This class should be specialized by any type that needs to be converted
204 /// to/from a list of YAML documents.
205 template<typename T>
206 struct DocumentListTraits {
207   // Must provide:
208   // static size_t size(IO &io, T &seq);
209   // static T::value_type& element(IO &io, T &seq, size_t index);
210 };
211
212 /// This class should be specialized by any type that needs to be converted
213 /// to/from a YAML mapping in the case where the names of the keys are not known
214 /// in advance, e.g. a string map.
215 template <typename T>
216 struct CustomMappingTraits {
217   // static void inputOne(IO &io, StringRef key, T &elem);
218   // static void output(IO &io, T &elem);
219 };
220
221 // Only used for better diagnostics of missing traits
222 template <typename T>
223 struct MissingTrait;
224
225 // Test if ScalarEnumerationTraits<T> is defined on type T.
226 template <class T>
227 struct has_ScalarEnumerationTraits
228 {
229   typedef void (*Signature_enumeration)(class IO&, T&);
230
231   template <typename U>
232   static char test(SameType<Signature_enumeration, &U::enumeration>*);
233
234   template <typename U>
235   static double test(...);
236
237 public:
238   static bool const value =
239     (sizeof(test<ScalarEnumerationTraits<T>>(nullptr)) == 1);
240 };
241
242 // Test if ScalarBitSetTraits<T> is defined on type T.
243 template <class T>
244 struct has_ScalarBitSetTraits
245 {
246   typedef void (*Signature_bitset)(class IO&, T&);
247
248   template <typename U>
249   static char test(SameType<Signature_bitset, &U::bitset>*);
250
251   template <typename U>
252   static double test(...);
253
254 public:
255   static bool const value = (sizeof(test<ScalarBitSetTraits<T>>(nullptr)) == 1);
256 };
257
258 // Test if ScalarTraits<T> is defined on type T.
259 template <class T>
260 struct has_ScalarTraits
261 {
262   typedef StringRef (*Signature_input)(StringRef, void*, T&);
263   typedef void (*Signature_output)(const T&, void*, llvm::raw_ostream&);
264   typedef bool (*Signature_mustQuote)(StringRef);
265
266   template <typename U>
267   static char test(SameType<Signature_input, &U::input> *,
268                    SameType<Signature_output, &U::output> *,
269                    SameType<Signature_mustQuote, &U::mustQuote> *);
270
271   template <typename U>
272   static double test(...);
273
274 public:
275   static bool const value =
276       (sizeof(test<ScalarTraits<T>>(nullptr, nullptr, nullptr)) == 1);
277 };
278
279 // Test if BlockScalarTraits<T> is defined on type T.
280 template <class T>
281 struct has_BlockScalarTraits
282 {
283   typedef StringRef (*Signature_input)(StringRef, void *, T &);
284   typedef void (*Signature_output)(const T &, void *, llvm::raw_ostream &);
285
286   template <typename U>
287   static char test(SameType<Signature_input, &U::input> *,
288                    SameType<Signature_output, &U::output> *);
289
290   template <typename U>
291   static double test(...);
292
293 public:
294   static bool const value =
295       (sizeof(test<BlockScalarTraits<T>>(nullptr, nullptr)) == 1);
296 };
297
298 // Test if MappingContextTraits<T> is defined on type T.
299 template <class T, class Context> struct has_MappingTraits {
300   typedef void (*Signature_mapping)(class IO &, T &, Context &);
301
302   template <typename U>
303   static char test(SameType<Signature_mapping, &U::mapping>*);
304
305   template <typename U>
306   static double test(...);
307
308 public:
309   static bool const value =
310       (sizeof(test<MappingContextTraits<T, Context>>(nullptr)) == 1);
311 };
312
313 // Test if MappingTraits<T> is defined on type T.
314 template <class T> struct has_MappingTraits<T, EmptyContext> {
315   typedef void (*Signature_mapping)(class IO &, T &);
316
317   template <typename U>
318   static char test(SameType<Signature_mapping, &U::mapping> *);
319
320   template <typename U> static double test(...);
321
322 public:
323   static bool const value = (sizeof(test<MappingTraits<T>>(nullptr)) == 1);
324 };
325
326 // Test if MappingContextTraits<T>::validate() is defined on type T.
327 template <class T, class Context> struct has_MappingValidateTraits {
328   typedef StringRef (*Signature_validate)(class IO &, T &, Context &);
329
330   template <typename U>
331   static char test(SameType<Signature_validate, &U::validate>*);
332
333   template <typename U>
334   static double test(...);
335
336 public:
337   static bool const value =
338       (sizeof(test<MappingContextTraits<T, Context>>(nullptr)) == 1);
339 };
340
341 // Test if MappingTraits<T>::validate() is defined on type T.
342 template <class T> struct has_MappingValidateTraits<T, EmptyContext> {
343   typedef StringRef (*Signature_validate)(class IO &, T &);
344
345   template <typename U>
346   static char test(SameType<Signature_validate, &U::validate> *);
347
348   template <typename U> static double test(...);
349
350 public:
351   static bool const value = (sizeof(test<MappingTraits<T>>(nullptr)) == 1);
352 };
353
354 // Test if SequenceTraits<T> is defined on type T.
355 template <class T>
356 struct has_SequenceMethodTraits
357 {
358   typedef size_t (*Signature_size)(class IO&, T&);
359
360   template <typename U>
361   static char test(SameType<Signature_size, &U::size>*);
362
363   template <typename U>
364   static double test(...);
365
366 public:
367   static bool const value =  (sizeof(test<SequenceTraits<T>>(nullptr)) == 1);
368 };
369
370 // Test if CustomMappingTraits<T> is defined on type T.
371 template <class T>
372 struct has_CustomMappingTraits
373 {
374   typedef void (*Signature_input)(IO &io, StringRef key, T &v);
375
376   template <typename U>
377   static char test(SameType<Signature_input, &U::inputOne>*);
378
379   template <typename U>
380   static double test(...);
381
382 public:
383   static bool const value =
384       (sizeof(test<CustomMappingTraits<T>>(nullptr)) == 1);
385 };
386
387 // has_FlowTraits<int> will cause an error with some compilers because
388 // it subclasses int.  Using this wrapper only instantiates the
389 // real has_FlowTraits only if the template type is a class.
390 template <typename T, bool Enabled = std::is_class<T>::value>
391 class has_FlowTraits
392 {
393 public:
394    static const bool value = false;
395 };
396
397 // Some older gcc compilers don't support straight forward tests
398 // for members, so test for ambiguity cause by the base and derived
399 // classes both defining the member.
400 template <class T>
401 struct has_FlowTraits<T, true>
402 {
403   struct Fallback { bool flow; };
404   struct Derived : T, Fallback { };
405
406   template<typename C>
407   static char (&f(SameType<bool Fallback::*, &C::flow>*))[1];
408
409   template<typename C>
410   static char (&f(...))[2];
411
412 public:
413   static bool const value = sizeof(f<Derived>(nullptr)) == 2;
414 };
415
416 // Test if SequenceTraits<T> is defined on type T
417 template<typename T>
418 struct has_SequenceTraits : public std::integral_constant<bool,
419                                       has_SequenceMethodTraits<T>::value > { };
420
421 // Test if DocumentListTraits<T> is defined on type T
422 template <class T>
423 struct has_DocumentListTraits
424 {
425   typedef size_t (*Signature_size)(class IO&, T&);
426
427   template <typename U>
428   static char test(SameType<Signature_size, &U::size>*);
429
430   template <typename U>
431   static double test(...);
432
433 public:
434   static bool const value = (sizeof(test<DocumentListTraits<T>>(nullptr))==1);
435 };
436
437 inline bool isNumber(StringRef S) {
438   static const char OctalChars[] = "01234567";
439   if (S.startswith("0") &&
440       S.drop_front().find_first_not_of(OctalChars) == StringRef::npos)
441     return true;
442
443   if (S.startswith("0o") &&
444       S.drop_front(2).find_first_not_of(OctalChars) == StringRef::npos)
445     return true;
446
447   static const char HexChars[] = "0123456789abcdefABCDEF";
448   if (S.startswith("0x") &&
449       S.drop_front(2).find_first_not_of(HexChars) == StringRef::npos)
450     return true;
451
452   static const char DecChars[] = "0123456789";
453   if (S.find_first_not_of(DecChars) == StringRef::npos)
454     return true;
455
456   if (S.equals(".inf") || S.equals(".Inf") || S.equals(".INF"))
457     return true;
458
459   Regex FloatMatcher("^(\\.[0-9]+|[0-9]+(\\.[0-9]*)?)([eE][-+]?[0-9]+)?$");
460   if (FloatMatcher.match(S))
461     return true;
462
463   return false;
464 }
465
466 inline bool isNumeric(StringRef S) {
467   if ((S.front() == '-' || S.front() == '+') && isNumber(S.drop_front()))
468     return true;
469
470   if (isNumber(S))
471     return true;
472
473   if (S.equals(".nan") || S.equals(".NaN") || S.equals(".NAN"))
474     return true;
475
476   return false;
477 }
478
479 inline bool isNull(StringRef S) {
480   return S.equals("null") || S.equals("Null") || S.equals("NULL") ||
481          S.equals("~");
482 }
483
484 inline bool isBool(StringRef S) {
485   return S.equals("true") || S.equals("True") || S.equals("TRUE") ||
486          S.equals("false") || S.equals("False") || S.equals("FALSE");
487 }
488
489 inline bool needsQuotes(StringRef S) {
490   if (S.empty())
491     return true;
492   if (isspace(S.front()) || isspace(S.back()))
493     return true;
494   if (S.front() == ',')
495     return true;
496
497   static const char ScalarSafeChars[] =
498       "abcdefghijklmnopqrstuvwxyz"
499       "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-/^., \t";
500   if (S.find_first_not_of(ScalarSafeChars) != StringRef::npos)
501     return true;
502
503   if (isNull(S))
504     return true;
505   if (isBool(S))
506     return true;
507   if (isNumeric(S))
508     return true;
509
510   return false;
511 }
512
513 template <typename T, typename Context>
514 struct missingTraits
515     : public std::integral_constant<bool,
516                                     !has_ScalarEnumerationTraits<T>::value &&
517                                         !has_ScalarBitSetTraits<T>::value &&
518                                         !has_ScalarTraits<T>::value &&
519                                         !has_BlockScalarTraits<T>::value &&
520                                         !has_MappingTraits<T, Context>::value &&
521                                         !has_SequenceTraits<T>::value &&
522                                         !has_CustomMappingTraits<T>::value &&
523                                         !has_DocumentListTraits<T>::value> {};
524
525 template <typename T, typename Context>
526 struct validatedMappingTraits
527     : public std::integral_constant<
528           bool, has_MappingTraits<T, Context>::value &&
529                     has_MappingValidateTraits<T, Context>::value> {};
530
531 template <typename T, typename Context>
532 struct unvalidatedMappingTraits
533     : public std::integral_constant<
534           bool, has_MappingTraits<T, Context>::value &&
535                     !has_MappingValidateTraits<T, Context>::value> {};
536
537 // Base class for Input and Output.
538 class IO {
539 public:
540   IO(void *Ctxt=nullptr);
541   virtual ~IO();
542
543   virtual bool outputting() = 0;
544
545   virtual unsigned beginSequence() = 0;
546   virtual bool preflightElement(unsigned, void *&) = 0;
547   virtual void postflightElement(void*) = 0;
548   virtual void endSequence() = 0;
549   virtual bool canElideEmptySequence() = 0;
550
551   virtual unsigned beginFlowSequence() = 0;
552   virtual bool preflightFlowElement(unsigned, void *&) = 0;
553   virtual void postflightFlowElement(void*) = 0;
554   virtual void endFlowSequence() = 0;
555
556   virtual bool mapTag(StringRef Tag, bool Default=false) = 0;
557   virtual void beginMapping() = 0;
558   virtual void endMapping() = 0;
559   virtual bool preflightKey(const char*, bool, bool, bool &, void *&) = 0;
560   virtual void postflightKey(void*) = 0;
561   virtual std::vector<StringRef> keys() = 0;
562
563   virtual void beginFlowMapping() = 0;
564   virtual void endFlowMapping() = 0;
565
566   virtual void beginEnumScalar() = 0;
567   virtual bool matchEnumScalar(const char*, bool) = 0;
568   virtual bool matchEnumFallback() = 0;
569   virtual void endEnumScalar() = 0;
570
571   virtual bool beginBitSetScalar(bool &) = 0;
572   virtual bool bitSetMatch(const char*, bool) = 0;
573   virtual void endBitSetScalar() = 0;
574
575   virtual void scalarString(StringRef &, bool) = 0;
576   virtual void blockScalarString(StringRef &) = 0;
577
578   virtual void setError(const Twine &) = 0;
579
580   template <typename T>
581   void enumCase(T &Val, const char* Str, const T ConstVal) {
582     if ( matchEnumScalar(Str, outputting() && Val == ConstVal) ) {
583       Val = ConstVal;
584     }
585   }
586
587   // allow anonymous enum values to be used with LLVM_YAML_STRONG_TYPEDEF
588   template <typename T>
589   void enumCase(T &Val, const char* Str, const uint32_t ConstVal) {
590     if ( matchEnumScalar(Str, outputting() && Val == static_cast<T>(ConstVal)) ) {
591       Val = ConstVal;
592     }
593   }
594
595   template <typename FBT, typename T>
596   void enumFallback(T &Val) {
597     if (matchEnumFallback()) {
598       EmptyContext Context;
599       // FIXME: Force integral conversion to allow strong typedefs to convert.
600       FBT Res = static_cast<typename FBT::BaseType>(Val);
601       yamlize(*this, Res, true, Context);
602       Val = static_cast<T>(static_cast<typename FBT::BaseType>(Res));
603     }
604   }
605
606   template <typename T>
607   void bitSetCase(T &Val, const char* Str, const T ConstVal) {
608     if ( bitSetMatch(Str, outputting() && (Val & ConstVal) == ConstVal) ) {
609       Val = Val | ConstVal;
610     }
611   }
612
613   // allow anonymous enum values to be used with LLVM_YAML_STRONG_TYPEDEF
614   template <typename T>
615   void bitSetCase(T &Val, const char* Str, const uint32_t ConstVal) {
616     if ( bitSetMatch(Str, outputting() && (Val & ConstVal) == ConstVal) ) {
617       Val = Val | ConstVal;
618     }
619   }
620
621   template <typename T>
622   void maskedBitSetCase(T &Val, const char *Str, T ConstVal, T Mask) {
623     if (bitSetMatch(Str, outputting() && (Val & Mask) == ConstVal))
624       Val = Val | ConstVal;
625   }
626
627   template <typename T>
628   void maskedBitSetCase(T &Val, const char *Str, uint32_t ConstVal,
629                         uint32_t Mask) {
630     if (bitSetMatch(Str, outputting() && (Val & Mask) == ConstVal))
631       Val = Val | ConstVal;
632   }
633
634   void *getContext();
635   void setContext(void *);
636
637   template <typename T> void mapRequired(const char *Key, T &Val) {
638     EmptyContext Ctx;
639     this->processKey(Key, Val, true, Ctx);
640   }
641   template <typename T, typename Context>
642   void mapRequired(const char *Key, T &Val, Context &Ctx) {
643     this->processKey(Key, Val, true, Ctx);
644   }
645
646   template <typename T> void mapOptional(const char *Key, T &Val) {
647     EmptyContext Ctx;
648     mapOptionalWithContext(Key, Val, Ctx);
649   }
650
651   template <typename T>
652   void mapOptional(const char *Key, T &Val, const T &Default) {
653     EmptyContext Ctx;
654     mapOptionalWithContext(Key, Val, Default, Ctx);
655   }
656
657   template <typename T, typename Context>
658   typename std::enable_if<has_SequenceTraits<T>::value, void>::type
659   mapOptionalWithContext(const char *Key, T &Val, Context &Ctx) {
660     // omit key/value instead of outputting empty sequence
661     if (this->canElideEmptySequence() && !(Val.begin() != Val.end()))
662       return;
663     this->processKey(Key, Val, false, Ctx);
664   }
665
666   template <typename T, typename Context>
667   void mapOptionalWithContext(const char *Key, Optional<T> &Val, Context &Ctx) {
668     this->processKeyWithDefault(Key, Val, Optional<T>(), /*Required=*/false,
669                                 Ctx);
670   }
671
672   template <typename T, typename Context>
673   typename std::enable_if<!has_SequenceTraits<T>::value, void>::type
674   mapOptionalWithContext(const char *Key, T &Val, Context &Ctx) {
675     this->processKey(Key, Val, false, Ctx);
676   }
677
678   template <typename T, typename Context>
679   void mapOptionalWithContext(const char *Key, T &Val, const T &Default,
680                               Context &Ctx) {
681     this->processKeyWithDefault(Key, Val, Default, false, Ctx);
682   }
683
684 private:
685   template <typename T, typename Context>
686   void processKeyWithDefault(const char *Key, Optional<T> &Val,
687                              const Optional<T> &DefaultValue, bool Required,
688                              Context &Ctx) {
689     assert(DefaultValue.hasValue() == false &&
690            "Optional<T> shouldn't have a value!");
691     void *SaveInfo;
692     bool UseDefault;
693     const bool sameAsDefault = outputting() && !Val.hasValue();
694     if (!outputting() && !Val.hasValue())
695       Val = T();
696     if (this->preflightKey(Key, Required, sameAsDefault, UseDefault,
697                            SaveInfo)) {
698       yamlize(*this, Val.getValue(), Required, Ctx);
699       this->postflightKey(SaveInfo);
700     } else {
701       if (UseDefault)
702         Val = DefaultValue;
703     }
704   }
705
706   template <typename T, typename Context>
707   void processKeyWithDefault(const char *Key, T &Val, const T &DefaultValue,
708                              bool Required, Context &Ctx) {
709     void *SaveInfo;
710     bool UseDefault;
711     const bool sameAsDefault = outputting() && Val == DefaultValue;
712     if ( this->preflightKey(Key, Required, sameAsDefault, UseDefault,
713                                                                   SaveInfo) ) {
714       yamlize(*this, Val, Required, Ctx);
715       this->postflightKey(SaveInfo);
716     }
717     else {
718       if ( UseDefault )
719         Val = DefaultValue;
720     }
721   }
722
723   template <typename T, typename Context>
724   void processKey(const char *Key, T &Val, bool Required, Context &Ctx) {
725     void *SaveInfo;
726     bool UseDefault;
727     if ( this->preflightKey(Key, Required, false, UseDefault, SaveInfo) ) {
728       yamlize(*this, Val, Required, Ctx);
729       this->postflightKey(SaveInfo);
730     }
731   }
732
733 private:
734   void  *Ctxt;
735 };
736
737 namespace detail {
738
739 template <typename T, typename Context>
740 void doMapping(IO &io, T &Val, Context &Ctx) {
741   MappingContextTraits<T, Context>::mapping(io, Val, Ctx);
742 }
743
744 template <typename T> void doMapping(IO &io, T &Val, EmptyContext &Ctx) {
745   MappingTraits<T>::mapping(io, Val);
746 }
747
748 } // end namespace detail
749
750 template <typename T>
751 typename std::enable_if<has_ScalarEnumerationTraits<T>::value, void>::type
752 yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
753   io.beginEnumScalar();
754   ScalarEnumerationTraits<T>::enumeration(io, Val);
755   io.endEnumScalar();
756 }
757
758 template <typename T>
759 typename std::enable_if<has_ScalarBitSetTraits<T>::value, void>::type
760 yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
761   bool DoClear;
762   if ( io.beginBitSetScalar(DoClear) ) {
763     if ( DoClear )
764       Val = static_cast<T>(0);
765     ScalarBitSetTraits<T>::bitset(io, Val);
766     io.endBitSetScalar();
767   }
768 }
769
770 template <typename T>
771 typename std::enable_if<has_ScalarTraits<T>::value, void>::type
772 yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
773   if ( io.outputting() ) {
774     std::string Storage;
775     llvm::raw_string_ostream Buffer(Storage);
776     ScalarTraits<T>::output(Val, io.getContext(), Buffer);
777     StringRef Str = Buffer.str();
778     io.scalarString(Str, ScalarTraits<T>::mustQuote(Str));
779   }
780   else {
781     StringRef Str;
782     io.scalarString(Str, ScalarTraits<T>::mustQuote(Str));
783     StringRef Result = ScalarTraits<T>::input(Str, io.getContext(), Val);
784     if ( !Result.empty() ) {
785       io.setError(llvm::Twine(Result));
786     }
787   }
788 }
789
790 template <typename T>
791 typename std::enable_if<has_BlockScalarTraits<T>::value, void>::type
792 yamlize(IO &YamlIO, T &Val, bool, EmptyContext &Ctx) {
793   if (YamlIO.outputting()) {
794     std::string Storage;
795     llvm::raw_string_ostream Buffer(Storage);
796     BlockScalarTraits<T>::output(Val, YamlIO.getContext(), Buffer);
797     StringRef Str = Buffer.str();
798     YamlIO.blockScalarString(Str);
799   } else {
800     StringRef Str;
801     YamlIO.blockScalarString(Str);
802     StringRef Result =
803         BlockScalarTraits<T>::input(Str, YamlIO.getContext(), Val);
804     if (!Result.empty())
805       YamlIO.setError(llvm::Twine(Result));
806   }
807 }
808
809 template <typename T, typename Context>
810 typename std::enable_if<validatedMappingTraits<T, Context>::value, void>::type
811 yamlize(IO &io, T &Val, bool, Context &Ctx) {
812   if (has_FlowTraits<MappingTraits<T>>::value)
813     io.beginFlowMapping();
814   else
815     io.beginMapping();
816   if (io.outputting()) {
817     StringRef Err = MappingTraits<T>::validate(io, Val);
818     if (!Err.empty()) {
819       llvm::errs() << Err << "\n";
820       assert(Err.empty() && "invalid struct trying to be written as yaml");
821     }
822   }
823   detail::doMapping(io, Val, Ctx);
824   if (!io.outputting()) {
825     StringRef Err = MappingTraits<T>::validate(io, Val);
826     if (!Err.empty())
827       io.setError(Err);
828   }
829   if (has_FlowTraits<MappingTraits<T>>::value)
830     io.endFlowMapping();
831   else
832     io.endMapping();
833 }
834
835 template <typename T, typename Context>
836 typename std::enable_if<unvalidatedMappingTraits<T, Context>::value, void>::type
837 yamlize(IO &io, T &Val, bool, Context &Ctx) {
838   if (has_FlowTraits<MappingTraits<T>>::value) {
839     io.beginFlowMapping();
840     detail::doMapping(io, Val, Ctx);
841     io.endFlowMapping();
842   } else {
843     io.beginMapping();
844     detail::doMapping(io, Val, Ctx);
845     io.endMapping();
846   }
847 }
848
849 template <typename T>
850 typename std::enable_if<has_CustomMappingTraits<T>::value, void>::type
851 yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
852   if ( io.outputting() ) {
853     io.beginMapping();
854     CustomMappingTraits<T>::output(io, Val);
855     io.endMapping();
856   } else {
857     io.beginMapping();
858     for (StringRef key : io.keys())
859       CustomMappingTraits<T>::inputOne(io, key, Val);
860     io.endMapping();
861   }
862 }
863
864 template <typename T>
865 typename std::enable_if<missingTraits<T, EmptyContext>::value, void>::type
866 yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
867   char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)];
868 }
869
870 template <typename T, typename Context>
871 typename std::enable_if<has_SequenceTraits<T>::value, void>::type
872 yamlize(IO &io, T &Seq, bool, Context &Ctx) {
873   if ( has_FlowTraits< SequenceTraits<T> >::value ) {
874     unsigned incnt = io.beginFlowSequence();
875     unsigned count = io.outputting() ? SequenceTraits<T>::size(io, Seq) : incnt;
876     for(unsigned i=0; i < count; ++i) {
877       void *SaveInfo;
878       if ( io.preflightFlowElement(i, SaveInfo) ) {
879         yamlize(io, SequenceTraits<T>::element(io, Seq, i), true, Ctx);
880         io.postflightFlowElement(SaveInfo);
881       }
882     }
883     io.endFlowSequence();
884   }
885   else {
886     unsigned incnt = io.beginSequence();
887     unsigned count = io.outputting() ? SequenceTraits<T>::size(io, Seq) : incnt;
888     for(unsigned i=0; i < count; ++i) {
889       void *SaveInfo;
890       if ( io.preflightElement(i, SaveInfo) ) {
891         yamlize(io, SequenceTraits<T>::element(io, Seq, i), true, Ctx);
892         io.postflightElement(SaveInfo);
893       }
894     }
895     io.endSequence();
896   }
897 }
898
899 template<>
900 struct ScalarTraits<bool> {
901   static void output(const bool &, void*, llvm::raw_ostream &);
902   static StringRef input(StringRef, void*, bool &);
903   static bool mustQuote(StringRef) { return false; }
904 };
905
906 template<>
907 struct ScalarTraits<StringRef> {
908   static void output(const StringRef &, void*, llvm::raw_ostream &);
909   static StringRef input(StringRef, void*, StringRef &);
910   static bool mustQuote(StringRef S) { return needsQuotes(S); }
911 };
912
913 template<>
914 struct ScalarTraits<std::string> {
915   static void output(const std::string &, void*, llvm::raw_ostream &);
916   static StringRef input(StringRef, void*, std::string &);
917   static bool mustQuote(StringRef S) { return needsQuotes(S); }
918 };
919
920 template<>
921 struct ScalarTraits<uint8_t> {
922   static void output(const uint8_t &, void*, llvm::raw_ostream &);
923   static StringRef input(StringRef, void*, uint8_t &);
924   static bool mustQuote(StringRef) { return false; }
925 };
926
927 template<>
928 struct ScalarTraits<uint16_t> {
929   static void output(const uint16_t &, void*, llvm::raw_ostream &);
930   static StringRef input(StringRef, void*, uint16_t &);
931   static bool mustQuote(StringRef) { return false; }
932 };
933
934 template<>
935 struct ScalarTraits<uint32_t> {
936   static void output(const uint32_t &, void*, llvm::raw_ostream &);
937   static StringRef input(StringRef, void*, uint32_t &);
938   static bool mustQuote(StringRef) { return false; }
939 };
940
941 template<>
942 struct ScalarTraits<uint64_t> {
943   static void output(const uint64_t &, void*, llvm::raw_ostream &);
944   static StringRef input(StringRef, void*, uint64_t &);
945   static bool mustQuote(StringRef) { return false; }
946 };
947
948 template<>
949 struct ScalarTraits<int8_t> {
950   static void output(const int8_t &, void*, llvm::raw_ostream &);
951   static StringRef input(StringRef, void*, int8_t &);
952   static bool mustQuote(StringRef) { return false; }
953 };
954
955 template<>
956 struct ScalarTraits<int16_t> {
957   static void output(const int16_t &, void*, llvm::raw_ostream &);
958   static StringRef input(StringRef, void*, int16_t &);
959   static bool mustQuote(StringRef) { return false; }
960 };
961
962 template<>
963 struct ScalarTraits<int32_t> {
964   static void output(const int32_t &, void*, llvm::raw_ostream &);
965   static StringRef input(StringRef, void*, int32_t &);
966   static bool mustQuote(StringRef) { return false; }
967 };
968
969 template<>
970 struct ScalarTraits<int64_t> {
971   static void output(const int64_t &, void*, llvm::raw_ostream &);
972   static StringRef input(StringRef, void*, int64_t &);
973   static bool mustQuote(StringRef) { return false; }
974 };
975
976 template<>
977 struct ScalarTraits<float> {
978   static void output(const float &, void*, llvm::raw_ostream &);
979   static StringRef input(StringRef, void*, float &);
980   static bool mustQuote(StringRef) { return false; }
981 };
982
983 template<>
984 struct ScalarTraits<double> {
985   static void output(const double &, void*, llvm::raw_ostream &);
986   static StringRef input(StringRef, void*, double &);
987   static bool mustQuote(StringRef) { return false; }
988 };
989
990 // For endian types, we just use the existing ScalarTraits for the underlying
991 // type.  This way endian aware types are supported whenever a ScalarTraits
992 // is defined for the underlying type.
993 template <typename value_type, support::endianness endian, size_t alignment>
994 struct ScalarTraits<support::detail::packed_endian_specific_integral<
995     value_type, endian, alignment>> {
996   typedef support::detail::packed_endian_specific_integral<value_type, endian,
997                                                            alignment>
998       endian_type;
999
1000   static void output(const endian_type &E, void *Ctx,
1001                      llvm::raw_ostream &Stream) {
1002     ScalarTraits<value_type>::output(static_cast<value_type>(E), Ctx, Stream);
1003   }
1004
1005   static StringRef input(StringRef Str, void *Ctx, endian_type &E) {
1006     value_type V;
1007     auto R = ScalarTraits<value_type>::input(Str, Ctx, V);
1008     E = static_cast<endian_type>(V);
1009     return R;
1010   }
1011
1012   static bool mustQuote(StringRef Str) {
1013     return ScalarTraits<value_type>::mustQuote(Str);
1014   }
1015 };
1016
1017 // Utility for use within MappingTraits<>::mapping() method
1018 // to [de]normalize an object for use with YAML conversion.
1019 template <typename TNorm, typename TFinal>
1020 struct MappingNormalization {
1021   MappingNormalization(IO &i_o, TFinal &Obj)
1022       : io(i_o), BufPtr(nullptr), Result(Obj) {
1023     if ( io.outputting() ) {
1024       BufPtr = new (&Buffer) TNorm(io, Obj);
1025     }
1026     else {
1027       BufPtr = new (&Buffer) TNorm(io);
1028     }
1029   }
1030
1031   ~MappingNormalization() {
1032     if ( ! io.outputting() ) {
1033       Result = BufPtr->denormalize(io);
1034     }
1035     BufPtr->~TNorm();
1036   }
1037
1038   TNorm* operator->() { return BufPtr; }
1039
1040 private:
1041   typedef llvm::AlignedCharArrayUnion<TNorm> Storage;
1042
1043   Storage       Buffer;
1044   IO           &io;
1045   TNorm        *BufPtr;
1046   TFinal       &Result;
1047 };
1048
1049 // Utility for use within MappingTraits<>::mapping() method
1050 // to [de]normalize an object for use with YAML conversion.
1051 template <typename TNorm, typename TFinal>
1052 struct MappingNormalizationHeap {
1053   MappingNormalizationHeap(IO &i_o, TFinal &Obj,
1054                            llvm::BumpPtrAllocator *allocator)
1055     : io(i_o), BufPtr(nullptr), Result(Obj) {
1056     if ( io.outputting() ) {
1057       BufPtr = new (&Buffer) TNorm(io, Obj);
1058     }
1059     else if (allocator) {
1060       BufPtr = allocator->Allocate<TNorm>();
1061       new (BufPtr) TNorm(io);
1062     } else {
1063       BufPtr = new TNorm(io);
1064     }
1065   }
1066
1067   ~MappingNormalizationHeap() {
1068     if ( io.outputting() ) {
1069       BufPtr->~TNorm();
1070     }
1071     else {
1072       Result = BufPtr->denormalize(io);
1073     }
1074   }
1075
1076   TNorm* operator->() { return BufPtr; }
1077
1078 private:
1079   typedef llvm::AlignedCharArrayUnion<TNorm> Storage;
1080
1081   Storage       Buffer;
1082   IO           &io;
1083   TNorm        *BufPtr;
1084   TFinal       &Result;
1085 };
1086
1087 ///
1088 /// The Input class is used to parse a yaml document into in-memory structs
1089 /// and vectors.
1090 ///
1091 /// It works by using YAMLParser to do a syntax parse of the entire yaml
1092 /// document, then the Input class builds a graph of HNodes which wraps
1093 /// each yaml Node.  The extra layer is buffering.  The low level yaml
1094 /// parser only lets you look at each node once.  The buffering layer lets
1095 /// you search and interate multiple times.  This is necessary because
1096 /// the mapRequired() method calls may not be in the same order
1097 /// as the keys in the document.
1098 ///
1099 class Input : public IO {
1100 public:
1101   // Construct a yaml Input object from a StringRef and optional
1102   // user-data. The DiagHandler can be specified to provide
1103   // alternative error reporting.
1104   Input(StringRef InputContent,
1105         void *Ctxt = nullptr,
1106         SourceMgr::DiagHandlerTy DiagHandler = nullptr,
1107         void *DiagHandlerCtxt = nullptr);
1108   ~Input() override;
1109
1110   // Check if there was an syntax or semantic error during parsing.
1111   std::error_code error();
1112
1113 private:
1114   bool outputting() override;
1115   bool mapTag(StringRef, bool) override;
1116   void beginMapping() override;
1117   void endMapping() override;
1118   bool preflightKey(const char *, bool, bool, bool &, void *&) override;
1119   void postflightKey(void *) override;
1120   std::vector<StringRef> keys() override;
1121   void beginFlowMapping() override;
1122   void endFlowMapping() override;
1123   unsigned beginSequence() override;
1124   void endSequence() override;
1125   bool preflightElement(unsigned index, void *&) override;
1126   void postflightElement(void *) override;
1127   unsigned beginFlowSequence() override;
1128   bool preflightFlowElement(unsigned , void *&) override;
1129   void postflightFlowElement(void *) override;
1130   void endFlowSequence() override;
1131   void beginEnumScalar() override;
1132   bool matchEnumScalar(const char*, bool) override;
1133   bool matchEnumFallback() override;
1134   void endEnumScalar() override;
1135   bool beginBitSetScalar(bool &) override;
1136   bool bitSetMatch(const char *, bool ) override;
1137   void endBitSetScalar() override;
1138   void scalarString(StringRef &, bool) override;
1139   void blockScalarString(StringRef &) override;
1140   void setError(const Twine &message) override;
1141   bool canElideEmptySequence() override;
1142
1143   class HNode {
1144     virtual void anchor();
1145
1146   public:
1147     HNode(Node *n) : _node(n) { }
1148     virtual ~HNode() = default;
1149
1150     static inline bool classof(const HNode *) { return true; }
1151
1152     Node *_node;
1153   };
1154
1155   class EmptyHNode : public HNode {
1156     void anchor() override;
1157
1158   public:
1159     EmptyHNode(Node *n) : HNode(n) { }
1160
1161     static inline bool classof(const HNode *n) {
1162       return NullNode::classof(n->_node);
1163     }
1164
1165     static inline bool classof(const EmptyHNode *) { return true; }
1166   };
1167
1168   class ScalarHNode : public HNode {
1169     void anchor() override;
1170
1171   public:
1172     ScalarHNode(Node *n, StringRef s) : HNode(n), _value(s) { }
1173
1174     StringRef value() const { return _value; }
1175
1176     static inline bool classof(const HNode *n) {
1177       return ScalarNode::classof(n->_node) ||
1178              BlockScalarNode::classof(n->_node);
1179     }
1180
1181     static inline bool classof(const ScalarHNode *) { return true; }
1182
1183   protected:
1184     StringRef _value;
1185   };
1186
1187   class MapHNode : public HNode {
1188     void anchor() override;
1189
1190   public:
1191     MapHNode(Node *n) : HNode(n) { }
1192
1193     static inline bool classof(const HNode *n) {
1194       return MappingNode::classof(n->_node);
1195     }
1196
1197     static inline bool classof(const MapHNode *) { return true; }
1198
1199     typedef llvm::StringMap<std::unique_ptr<HNode>> NameToNode;
1200
1201     NameToNode                        Mapping;
1202     llvm::SmallVector<std::string, 6> ValidKeys;
1203   };
1204
1205   class SequenceHNode : public HNode {
1206     void anchor() override;
1207
1208   public:
1209     SequenceHNode(Node *n) : HNode(n) { }
1210
1211     static inline bool classof(const HNode *n) {
1212       return SequenceNode::classof(n->_node);
1213     }
1214
1215     static inline bool classof(const SequenceHNode *) { return true; }
1216
1217     std::vector<std::unique_ptr<HNode>> Entries;
1218   };
1219
1220   std::unique_ptr<Input::HNode> createHNodes(Node *node);
1221   void setError(HNode *hnode, const Twine &message);
1222   void setError(Node *node, const Twine &message);
1223
1224 public:
1225   // These are only used by operator>>. They could be private
1226   // if those templated things could be made friends.
1227   bool setCurrentDocument();
1228   bool nextDocument();
1229
1230   /// Returns the current node that's being parsed by the YAML Parser.
1231   const Node *getCurrentNode() const;
1232
1233 private:
1234   llvm::SourceMgr                     SrcMgr; // must be before Strm
1235   std::unique_ptr<llvm::yaml::Stream> Strm;
1236   std::unique_ptr<HNode>              TopNode;
1237   std::error_code                     EC;
1238   llvm::BumpPtrAllocator              StringAllocator;
1239   llvm::yaml::document_iterator       DocIterator;
1240   std::vector<bool>                   BitValuesUsed;
1241   HNode                              *CurrentNode;
1242   bool                                ScalarMatchFound;
1243 };
1244
1245 ///
1246 /// The Output class is used to generate a yaml document from in-memory structs
1247 /// and vectors.
1248 ///
1249 class Output : public IO {
1250 public:
1251   Output(llvm::raw_ostream &, void *Ctxt = nullptr, int WrapColumn = 70);
1252   ~Output() override;
1253
1254   bool outputting() override;
1255   bool mapTag(StringRef, bool) override;
1256   void beginMapping() override;
1257   void endMapping() override;
1258   bool preflightKey(const char *key, bool, bool, bool &, void *&) override;
1259   void postflightKey(void *) override;
1260   std::vector<StringRef> keys() override;
1261   void beginFlowMapping() override;
1262   void endFlowMapping() override;
1263   unsigned beginSequence() override;
1264   void endSequence() override;
1265   bool preflightElement(unsigned, void *&) override;
1266   void postflightElement(void *) override;
1267   unsigned beginFlowSequence() override;
1268   bool preflightFlowElement(unsigned, void *&) override;
1269   void postflightFlowElement(void *) override;
1270   void endFlowSequence() override;
1271   void beginEnumScalar() override;
1272   bool matchEnumScalar(const char*, bool) override;
1273   bool matchEnumFallback() override;
1274   void endEnumScalar() override;
1275   bool beginBitSetScalar(bool &) override;
1276   bool bitSetMatch(const char *, bool ) override;
1277   void endBitSetScalar() override;
1278   void scalarString(StringRef &, bool) override;
1279   void blockScalarString(StringRef &) override;
1280   void setError(const Twine &message) override;
1281   bool canElideEmptySequence() override;
1282
1283   // These are only used by operator<<. They could be private
1284   // if that templated operator could be made a friend.
1285   void beginDocuments();
1286   bool preflightDocument(unsigned);
1287   void postflightDocument();
1288   void endDocuments();
1289
1290 private:
1291   void output(StringRef s);
1292   void outputUpToEndOfLine(StringRef s);
1293   void newLineCheck();
1294   void outputNewLine();
1295   void paddedKey(StringRef key);
1296   void flowKey(StringRef Key);
1297
1298   enum InState {
1299     inSeq,
1300     inFlowSeq,
1301     inMapFirstKey,
1302     inMapOtherKey,
1303     inFlowMapFirstKey,
1304     inFlowMapOtherKey
1305   };
1306
1307   llvm::raw_ostream       &Out;
1308   int                      WrapColumn;
1309   SmallVector<InState, 8>  StateStack;
1310   int                      Column;
1311   int                      ColumnAtFlowStart;
1312   int                      ColumnAtMapFlowStart;
1313   bool                     NeedBitValueComma;
1314   bool                     NeedFlowSequenceComma;
1315   bool                     EnumerationMatchFound;
1316   bool                     NeedsNewLine;
1317 };
1318
1319 /// YAML I/O does conversion based on types. But often native data types
1320 /// are just a typedef of built in intergral types (e.g. int).  But the C++
1321 /// type matching system sees through the typedef and all the typedefed types
1322 /// look like a built in type. This will cause the generic YAML I/O conversion
1323 /// to be used. To provide better control over the YAML conversion, you can
1324 /// use this macro instead of typedef.  It will create a class with one field
1325 /// and automatic conversion operators to and from the base type.
1326 /// Based on BOOST_STRONG_TYPEDEF
1327 #define LLVM_YAML_STRONG_TYPEDEF(_base, _type)                                 \
1328     struct _type {                                                             \
1329         _type() = default;                                                     \
1330         _type(const _base v) : value(v) {}                                     \
1331         _type(const _type &v) = default;                                       \
1332         _type &operator=(const _type &rhs) = default;                          \
1333         _type &operator=(const _base &rhs) { value = rhs; return *this; }      \
1334         operator const _base & () const { return value; }                      \
1335         bool operator==(const _type &rhs) const { return value == rhs.value; } \
1336         bool operator==(const _base &rhs) const { return value == rhs; }       \
1337         bool operator<(const _type &rhs) const { return value < rhs.value; }   \
1338         _base value;                                                           \
1339         typedef _base BaseType;                                                \
1340     };
1341
1342 ///
1343 /// Use these types instead of uintXX_t in any mapping to have
1344 /// its yaml output formatted as hexadecimal.
1345 ///
1346 LLVM_YAML_STRONG_TYPEDEF(uint8_t, Hex8)
1347 LLVM_YAML_STRONG_TYPEDEF(uint16_t, Hex16)
1348 LLVM_YAML_STRONG_TYPEDEF(uint32_t, Hex32)
1349 LLVM_YAML_STRONG_TYPEDEF(uint64_t, Hex64)
1350
1351 template<>
1352 struct ScalarTraits<Hex8> {
1353   static void output(const Hex8 &, void*, llvm::raw_ostream &);
1354   static StringRef input(StringRef, void*, Hex8 &);
1355   static bool mustQuote(StringRef) { return false; }
1356 };
1357
1358 template<>
1359 struct ScalarTraits<Hex16> {
1360   static void output(const Hex16 &, void*, llvm::raw_ostream &);
1361   static StringRef input(StringRef, void*, Hex16 &);
1362   static bool mustQuote(StringRef) { return false; }
1363 };
1364
1365 template<>
1366 struct ScalarTraits<Hex32> {
1367   static void output(const Hex32 &, void*, llvm::raw_ostream &);
1368   static StringRef input(StringRef, void*, Hex32 &);
1369   static bool mustQuote(StringRef) { return false; }
1370 };
1371
1372 template<>
1373 struct ScalarTraits<Hex64> {
1374   static void output(const Hex64 &, void*, llvm::raw_ostream &);
1375   static StringRef input(StringRef, void*, Hex64 &);
1376   static bool mustQuote(StringRef) { return false; }
1377 };
1378
1379 // Define non-member operator>> so that Input can stream in a document list.
1380 template <typename T>
1381 inline
1382 typename std::enable_if<has_DocumentListTraits<T>::value, Input &>::type
1383 operator>>(Input &yin, T &docList) {
1384   int i = 0;
1385   EmptyContext Ctx;
1386   while ( yin.setCurrentDocument() ) {
1387     yamlize(yin, DocumentListTraits<T>::element(yin, docList, i), true, Ctx);
1388     if ( yin.error() )
1389       return yin;
1390     yin.nextDocument();
1391     ++i;
1392   }
1393   return yin;
1394 }
1395
1396 // Define non-member operator>> so that Input can stream in a map as a document.
1397 template <typename T>
1398 inline typename std::enable_if<has_MappingTraits<T, EmptyContext>::value,
1399                                Input &>::type
1400 operator>>(Input &yin, T &docMap) {
1401   EmptyContext Ctx;
1402   yin.setCurrentDocument();
1403   yamlize(yin, docMap, true, Ctx);
1404   return yin;
1405 }
1406
1407 // Define non-member operator>> so that Input can stream in a sequence as
1408 // a document.
1409 template <typename T>
1410 inline
1411 typename std::enable_if<has_SequenceTraits<T>::value, Input &>::type
1412 operator>>(Input &yin, T &docSeq) {
1413   EmptyContext Ctx;
1414   if (yin.setCurrentDocument())
1415     yamlize(yin, docSeq, true, Ctx);
1416   return yin;
1417 }
1418
1419 // Define non-member operator>> so that Input can stream in a block scalar.
1420 template <typename T>
1421 inline
1422 typename std::enable_if<has_BlockScalarTraits<T>::value, Input &>::type
1423 operator>>(Input &In, T &Val) {
1424   EmptyContext Ctx;
1425   if (In.setCurrentDocument())
1426     yamlize(In, Val, true, Ctx);
1427   return In;
1428 }
1429
1430 // Define non-member operator>> so that Input can stream in a string map.
1431 template <typename T>
1432 inline
1433 typename std::enable_if<has_CustomMappingTraits<T>::value, Input &>::type
1434 operator>>(Input &In, T &Val) {
1435   EmptyContext Ctx;
1436   if (In.setCurrentDocument())
1437     yamlize(In, Val, true, Ctx);
1438   return In;
1439 }
1440
1441 // Provide better error message about types missing a trait specialization
1442 template <typename T>
1443 inline typename std::enable_if<missingTraits<T, EmptyContext>::value,
1444                                Input &>::type
1445 operator>>(Input &yin, T &docSeq) {
1446   char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)];
1447   return yin;
1448 }
1449
1450 // Define non-member operator<< so that Output can stream out document list.
1451 template <typename T>
1452 inline
1453 typename std::enable_if<has_DocumentListTraits<T>::value, Output &>::type
1454 operator<<(Output &yout, T &docList) {
1455   EmptyContext Ctx;
1456   yout.beginDocuments();
1457   const size_t count = DocumentListTraits<T>::size(yout, docList);
1458   for(size_t i=0; i < count; ++i) {
1459     if ( yout.preflightDocument(i) ) {
1460       yamlize(yout, DocumentListTraits<T>::element(yout, docList, i), true,
1461               Ctx);
1462       yout.postflightDocument();
1463     }
1464   }
1465   yout.endDocuments();
1466   return yout;
1467 }
1468
1469 // Define non-member operator<< so that Output can stream out a map.
1470 template <typename T>
1471 inline typename std::enable_if<has_MappingTraits<T, EmptyContext>::value,
1472                                Output &>::type
1473 operator<<(Output &yout, T &map) {
1474   EmptyContext Ctx;
1475   yout.beginDocuments();
1476   if ( yout.preflightDocument(0) ) {
1477     yamlize(yout, map, true, Ctx);
1478     yout.postflightDocument();
1479   }
1480   yout.endDocuments();
1481   return yout;
1482 }
1483
1484 // Define non-member operator<< so that Output can stream out a sequence.
1485 template <typename T>
1486 inline
1487 typename std::enable_if<has_SequenceTraits<T>::value, Output &>::type
1488 operator<<(Output &yout, T &seq) {
1489   EmptyContext Ctx;
1490   yout.beginDocuments();
1491   if ( yout.preflightDocument(0) ) {
1492     yamlize(yout, seq, true, Ctx);
1493     yout.postflightDocument();
1494   }
1495   yout.endDocuments();
1496   return yout;
1497 }
1498
1499 // Define non-member operator<< so that Output can stream out a block scalar.
1500 template <typename T>
1501 inline
1502 typename std::enable_if<has_BlockScalarTraits<T>::value, Output &>::type
1503 operator<<(Output &Out, T &Val) {
1504   EmptyContext Ctx;
1505   Out.beginDocuments();
1506   if (Out.preflightDocument(0)) {
1507     yamlize(Out, Val, true, Ctx);
1508     Out.postflightDocument();
1509   }
1510   Out.endDocuments();
1511   return Out;
1512 }
1513
1514 // Define non-member operator<< so that Output can stream out a string map.
1515 template <typename T>
1516 inline
1517 typename std::enable_if<has_CustomMappingTraits<T>::value, Output &>::type
1518 operator<<(Output &Out, T &Val) {
1519   EmptyContext Ctx;
1520   Out.beginDocuments();
1521   if (Out.preflightDocument(0)) {
1522     yamlize(Out, Val, true, Ctx);
1523     Out.postflightDocument();
1524   }
1525   Out.endDocuments();
1526   return Out;
1527 }
1528
1529 // Provide better error message about types missing a trait specialization
1530 template <typename T>
1531 inline typename std::enable_if<missingTraits<T, EmptyContext>::value,
1532                                Output &>::type
1533 operator<<(Output &yout, T &seq) {
1534   char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)];
1535   return yout;
1536 }
1537
1538 template <typename T> struct SequenceTraitsImpl {
1539   typedef typename T::value_type _type;
1540   static size_t size(IO &io, T &seq) { return seq.size(); }
1541   static _type &element(IO &io, T &seq, size_t index) {
1542     if (index >= seq.size())
1543       seq.resize(index + 1);
1544     return seq[index];
1545   }
1546 };
1547
1548 /// Implementation of CustomMappingTraits for std::map<std::string, T>.
1549 template <typename T> struct StdMapStringCustomMappingTraitsImpl {
1550   typedef std::map<std::string, T> map_type;
1551   static void inputOne(IO &io, StringRef key, map_type &v) {
1552     io.mapRequired(key.str().c_str(), v[key]);
1553   }
1554   static void output(IO &io, map_type &v) {
1555     for (auto &p : v)
1556       io.mapRequired(p.first.c_str(), p.second);
1557   }
1558 };
1559
1560 } // end namespace yaml
1561 } // end namespace llvm
1562
1563 /// Utility for declaring that a std::vector of a particular type
1564 /// should be considered a YAML sequence.
1565 #define LLVM_YAML_IS_SEQUENCE_VECTOR(_type)                                    \
1566   namespace llvm {                                                             \
1567   namespace yaml {                                                             \
1568   template <>                                                                  \
1569   struct SequenceTraits<std::vector<_type>>                                    \
1570       : public SequenceTraitsImpl<std::vector<_type>> {};                      \
1571   template <unsigned N>                                                        \
1572   struct SequenceTraits<SmallVector<_type, N>>                                 \
1573       : public SequenceTraitsImpl<SmallVector<_type, N>> {};                   \
1574   }                                                                            \
1575   }
1576
1577 /// Utility for declaring that a std::vector of a particular type
1578 /// should be considered a YAML flow sequence.
1579 /// We need to do a partial specialization on the vector version, not a full.
1580 /// If this is a full specialization, the compiler is a bit too "smart" and
1581 /// decides to warn on -Wunused-const-variable.  This workaround can be
1582 /// removed and we can do a full specialization on std::vector<T> once
1583 /// PR28878 is fixed.
1584 #define LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(_type)                               \
1585   namespace llvm {                                                             \
1586   namespace yaml {                                                             \
1587   template <unsigned N>                                                        \
1588   struct SequenceTraits<SmallVector<_type, N>>                                 \
1589       : public SequenceTraitsImpl<SmallVector<_type, N>> {                     \
1590     static const bool flow = true;                                             \
1591   };                                                                           \
1592   template <typename Allocator>                                                \
1593   struct SequenceTraits<std::vector<_type, Allocator>>                         \
1594       : public SequenceTraitsImpl<std::vector<_type, Allocator>> {             \
1595     static const bool flow = true;                                             \
1596   };                                                                           \
1597   }                                                                            \
1598   }
1599
1600 /// Utility for declaring that a std::vector of a particular type
1601 /// should be considered a YAML document list.
1602 #define LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(_type)                               \
1603   namespace llvm {                                                             \
1604   namespace yaml {                                                             \
1605   template <unsigned N>                                                        \
1606   struct DocumentListTraits<SmallVector<_type, N>>                             \
1607       : public SequenceTraitsImpl<SmallVector<_type, N>> {};                   \
1608   template <>                                                                  \
1609   struct DocumentListTraits<std::vector<_type>>                                \
1610       : public SequenceTraitsImpl<std::vector<_type>> {};                      \
1611   }                                                                            \
1612   }
1613
1614 /// Utility for declaring that std::map<std::string, _type> should be considered
1615 /// a YAML map.
1616 #define LLVM_YAML_IS_STRING_MAP(_type)                                         \
1617   namespace llvm {                                                             \
1618   namespace yaml {                                                             \
1619   template <>                                                                  \
1620   struct CustomMappingTraits<std::map<std::string, _type>>                     \
1621       : public StdMapStringCustomMappingTraitsImpl<_type> {};                  \
1622   }                                                                            \
1623   }
1624
1625 #endif // LLVM_SUPPORT_YAMLTRAITS_H