LLVM API Documentation

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