YAMLTraits.h 44 KB

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