Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1104 lines
34 KiB

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