9 #ifndef LLVM_SUPPORT_YAMLTRAITS_H
10 #define LLVM_SUPPORT_YAMLTRAITS_H
31 #include <system_error>
32 #include <type_traits>
47 struct EmptyContext {};
60 struct MappingTraits {
83 template <
class T,
class Context>
struct MappingContextTraits {
105 template <
typename T,
typename Enable =
void>
struct ScalarEnumerationTraits {
121 template <
typename T,
typename Enable =
void>
struct ScalarBitSetTraits {
147 template <
typename T,
typename Enable =
void>
struct ScalarTraits {
177 template <
typename T>
178 struct BlockScalarTraits {
214 template <
typename T>
struct TaggedScalarTraits {
244 template<
typename T,
typename EnableIf =
void>
245 struct SequenceTraits {
257 template<
typename T,
typename EnableIf =
void>
258 struct SequenceElementTraits {
266 struct DocumentListTraits {
275 template <
typename T>
276 struct CustomMappingTraits {
298 template <
typename T>
struct PolymorphicTraits {
307 template <
typename T>
312 struct has_ScalarEnumerationTraits
314 using Signature_enumeration = void (*)(
class IO&,
T&);
316 template <
typename U>
317 static char test(SameType<Signature_enumeration, &U::enumeration>*);
319 template <
typename U>
320 static double test(...);
322 static bool const value =
323 (
sizeof(test<ScalarEnumerationTraits<T>>(
nullptr)) == 1);
328 struct has_ScalarBitSetTraits
330 using Signature_bitset = void (*)(
class IO&,
T&);
332 template <
typename U>
333 static char test(SameType<Signature_bitset, &U::bitset>*);
335 template <
typename U>
336 static double test(...);
338 static bool const value = (
sizeof(test<ScalarBitSetTraits<T>>(
nullptr)) == 1);
343 struct has_ScalarTraits
345 using Signature_input = StringRef (*)(StringRef,
void*,
T&);
346 using Signature_output = void (*)(
const T&,
void*, raw_ostream&);
347 using Signature_mustQuote = QuotingType (*)(StringRef);
349 template <
typename U>
350 static char test(SameType<Signature_input, &U::input> *,
351 SameType<Signature_output, &U::output> *,
352 SameType<Signature_mustQuote, &U::mustQuote> *);
354 template <
typename U>
355 static double test(...);
357 static bool const value =
358 (
sizeof(test<ScalarTraits<T>>(
nullptr,
nullptr,
nullptr)) == 1);
363 struct has_BlockScalarTraits
365 using Signature_input = StringRef (*)(StringRef,
void *,
T &);
366 using Signature_output = void (*)(
const T &,
void *, raw_ostream &);
368 template <
typename U>
369 static char test(SameType<Signature_input, &U::input> *,
370 SameType<Signature_output, &U::output> *);
372 template <
typename U>
373 static double test(...);
375 static bool const value =
376 (
sizeof(test<BlockScalarTraits<T>>(
nullptr,
nullptr)) == 1);
380 template <
class T>
struct has_TaggedScalarTraits {
381 using Signature_input = StringRef (*)(StringRef, StringRef,
void *,
T &);
382 using Signature_output = void (*)(
const T &,
void *, raw_ostream &,
384 using Signature_mustQuote = QuotingType (*)(
const T &, StringRef);
386 template <
typename U>
387 static char test(SameType<Signature_input, &U::input> *,
388 SameType<Signature_output, &U::output> *,
389 SameType<Signature_mustQuote, &U::mustQuote> *);
391 template <
typename U>
static double test(...);
393 static bool const value =
394 (
sizeof(test<TaggedScalarTraits<T>>(
nullptr,
nullptr,
nullptr)) == 1);
398 template <
class T,
class Context>
struct has_MappingTraits {
399 using Signature_mapping = void (*)(
class IO &,
T &,
Context &);
401 template <
typename U>
402 static char test(SameType<Signature_mapping, &U::mapping>*);
404 template <
typename U>
405 static double test(...);
407 static bool const value =
408 (
sizeof(test<MappingContextTraits<T, Context>>(
nullptr)) == 1);
412 template <
class T>
struct has_MappingTraits<
T, EmptyContext> {
413 using Signature_mapping = void (*)(
class IO &,
T &);
415 template <
typename U>
416 static char test(SameType<Signature_mapping, &U::mapping> *);
418 template <
typename U>
static double test(...);
420 static bool const value = (
sizeof(test<MappingTraits<T>>(
nullptr)) == 1);
424 template <
class T,
class Context>
struct has_MappingValidateTraits {
425 using Signature_validate = std::string (*)(
class IO &,
T &,
Context &);
427 template <
typename U>
428 static char test(SameType<Signature_validate, &U::validate>*);
430 template <
typename U>
431 static double test(...);
433 static bool const value =
434 (
sizeof(test<MappingContextTraits<T, Context>>(
nullptr)) == 1);
438 template <
class T>
struct has_MappingValidateTraits<
T, EmptyContext> {
439 using Signature_validate = std::string (*)(
class IO &,
T &);
441 template <
typename U>
442 static char test(SameType<Signature_validate, &U::validate> *);
444 template <
typename U>
static double test(...);
446 static bool const value = (
sizeof(test<MappingTraits<T>>(
nullptr)) == 1);
450 template <
class T,
class Context>
struct has_MappingEnumInputTraits {
451 using Signature_validate = void (*)(
class IO &,
T &);
453 template <
typename U>
454 static char test(SameType<Signature_validate, &U::enumInput> *);
456 template <
typename U>
static double test(...);
458 static bool const value =
459 (
sizeof(test<MappingContextTraits<T, Context>>(
nullptr)) == 1);
463 template <
class T>
struct has_MappingEnumInputTraits<
T, EmptyContext> {
464 using Signature_validate = void (*)(
class IO &,
T &);
466 template <
typename U>
467 static char test(SameType<Signature_validate, &U::enumInput> *);
469 template <
typename U>
static double test(...);
471 static bool const value = (
sizeof(test<MappingTraits<T>>(
nullptr)) == 1);
476 struct has_SequenceMethodTraits
478 using Signature_size =
size_t (*)(
class IO&,
T&);
480 template <
typename U>
481 static char test(SameType<Signature_size, &U::size>*);
483 template <
typename U>
484 static double test(...);
486 static bool const value = (
sizeof(test<SequenceTraits<T>>(
nullptr)) == 1);
491 struct has_CustomMappingTraits
493 using Signature_input = void (*)(IO &io, StringRef key,
T &v);
495 template <
typename U>
496 static char test(SameType<Signature_input, &U::inputOne>*);
498 template <
typename U>
499 static double test(...);
501 static bool const value =
502 (
sizeof(test<CustomMappingTraits<T>>(
nullptr)) == 1);
508 template <typename T, bool Enabled = std::is_class<T>::value>
512 static const bool value =
false;
519 struct has_FlowTraits<
T,
true>
525 static char (&
f(SameType<bool Fallback::*, &C::flow>*))[1];
528 static char (&
f(...))[2];
530 static bool const value =
sizeof(f<Derived>(
nullptr)) == 2;
535 struct has_SequenceTraits :
public std::integral_constant<bool,
536 has_SequenceMethodTraits<T>::value > { };
540 struct has_DocumentListTraits
542 using Signature_size =
size_t (*)(
class IO &,
T &);
544 template <
typename U>
545 static char test(SameType<Signature_size, &U::size>*);
547 template <
typename U>
548 static double test(...);
550 static bool const value = (
sizeof(test<DocumentListTraits<T>>(
nullptr))==1);
553 template <
class T>
struct has_PolymorphicTraits {
554 using Signature_getKind =
NodeKind (*)(
const T &);
556 template <
typename U>
557 static char test(SameType<Signature_getKind, &U::getKind> *);
559 template <
typename U>
static double test(...);
561 static bool const value = (
sizeof(test<PolymorphicTraits<T>>(
nullptr)) == 1);
564 inline bool isNumeric(StringRef
S) {
565 const auto skipDigits = [](StringRef
Input) {
566 return Input.ltrim(
"0123456789");
571 if (
S.empty() ||
S.equals(
"+") ||
S.equals(
"-"))
574 if (
S.equals(
".nan") ||
S.equals(
".NaN") ||
S.equals(
".NAN"))
578 StringRef
Tail = (
S.front() ==
'-' ||
S.front() ==
'+') ?
S.drop_front() :
S;
582 if (
Tail.equals(
".inf") ||
Tail.equals(
".Inf") ||
Tail.equals(
".INF"))
588 if (
S.startswith(
"0o"))
589 return S.size() > 2 &&
592 if (
S.startswith(
"0x"))
593 return S.size() > 2 &&
S.drop_front(2).find_first_not_of(
602 if (
S.startswith(
".") &&
604 (
S.size() > 1 && std::strchr(
"0123456789",
S[1]) ==
nullptr)))
607 if (
S.startswith(
"E") ||
S.startswith(
"e"))
623 if (
S.front() ==
'.') {
626 }
else if (
S.front() ==
'e' ||
S.front() ==
'E') {
627 State = FoundExponent;
633 if (State == FoundDot) {
638 if (
S.front() ==
'e' ||
S.front() ==
'E') {
639 State = FoundExponent;
646 assert(State == FoundExponent &&
"Should have found exponent at this point.");
650 if (
S.front() ==
'+' ||
S.front() ==
'-') {
656 return skipDigits(
S).empty();
659 inline bool isNull(StringRef
S) {
660 return S.equals(
"null") ||
S.equals(
"Null") ||
S.equals(
"NULL") ||
664 inline bool isBool(StringRef
S) {
666 return S.equals(
"true") ||
S.equals(
"True") ||
S.equals(
"TRUE") ||
667 S.equals(
"false") ||
S.equals(
"False") ||
S.equals(
"FALSE");
675 inline QuotingType needsQuotes(StringRef
S) {
680 if (isSpace(
static_cast<unsigned char>(
S.front())) ||
681 isSpace(
static_cast<unsigned char>(
S.back())))
693 if (std::strchr(R
"(-?:\,[]{}#&*!|>'"%@`)", S[0]) != nullptr)
696 for (
unsigned char C :
S) {
743 return MaxQuotingNeeded;
746 template <
typename T,
typename Context>
748 :
public std::integral_constant<bool,
749 !has_ScalarEnumerationTraits<T>::value &&
750 !has_ScalarBitSetTraits<T>::value &&
751 !has_ScalarTraits<T>::value &&
752 !has_BlockScalarTraits<T>::value &&
753 !has_TaggedScalarTraits<T>::value &&
754 !has_MappingTraits<T, Context>::value &&
755 !has_SequenceTraits<T>::value &&
756 !has_CustomMappingTraits<T>::value &&
757 !has_DocumentListTraits<T>::value &&
758 !has_PolymorphicTraits<T>::value> {};
760 template <
typename T,
typename Context>
761 struct validatedMappingTraits
762 :
public std::integral_constant<
763 bool, has_MappingTraits<T, Context>::value &&
764 has_MappingValidateTraits<T, Context>::value> {};
766 template <
typename T,
typename Context>
767 struct unvalidatedMappingTraits
768 :
public std::integral_constant<
769 bool, has_MappingTraits<T, Context>::value &&
770 !has_MappingValidateTraits<T, Context>::value> {};
775 IO(
void *Ctxt =
nullptr);
778 virtual bool outputting()
const = 0;
780 virtual unsigned beginSequence() = 0;
781 virtual bool preflightElement(
unsigned,
void *&) = 0;
782 virtual void postflightElement(
void*) = 0;
783 virtual void endSequence() = 0;
784 virtual bool canElideEmptySequence() = 0;
786 virtual unsigned beginFlowSequence() = 0;
787 virtual bool preflightFlowElement(
unsigned,
void *&) = 0;
788 virtual void postflightFlowElement(
void*) = 0;
789 virtual void endFlowSequence() = 0;
791 virtual bool mapTag(StringRef Tag,
bool Default=
false) = 0;
792 virtual void beginMapping() = 0;
793 virtual void endMapping() = 0;
794 virtual bool preflightKey(
const char*,
bool,
bool,
bool &,
void *&) = 0;
795 virtual void postflightKey(
void*) = 0;
796 virtual std::vector<StringRef> keys() = 0;
798 virtual void beginFlowMapping() = 0;
799 virtual void endFlowMapping() = 0;
801 virtual void beginEnumScalar() = 0;
802 virtual bool matchEnumScalar(
const char*,
bool) = 0;
803 virtual bool matchEnumFallback() = 0;
804 virtual void endEnumScalar() = 0;
806 virtual bool beginBitSetScalar(
bool &) = 0;
807 virtual bool bitSetMatch(
const char*,
bool) = 0;
808 virtual void endBitSetScalar() = 0;
810 virtual void scalarString(StringRef &, QuotingType) = 0;
811 virtual void blockScalarString(StringRef &) = 0;
812 virtual void scalarTag(std::string &) = 0;
816 virtual void setError(
const Twine &) = 0;
817 virtual void setAllowUnknownKeys(
bool Allow);
819 template <
typename T>
820 void enumCase(T &Val,
const char* Str,
const T ConstVal) {
821 if ( matchEnumScalar(Str, outputting() && Val == ConstVal) ) {
827 template <
typename T>
828 void enumCase(T &Val,
const char* Str,
const uint32_t ConstVal) {
829 if ( matchEnumScalar(Str, outputting() && Val ==
static_cast<T>(ConstVal)) ) {
834 template <
typename FBT,
typename T>
835 void enumFallback(T &Val) {
836 if (matchEnumFallback()) {
840 yamlize(*
this, Res,
true,
Context);
845 template <
typename T>
846 void bitSetCase(T &Val,
const char* Str,
const T ConstVal) {
847 if ( bitSetMatch(Str, outputting() && (Val & ConstVal) == ConstVal) ) {
848 Val =
static_cast<T>(Val | ConstVal);
853 template <
typename T>
854 void bitSetCase(T &Val,
const char* Str,
const uint32_t ConstVal) {
855 if ( bitSetMatch(Str, outputting() && (Val & ConstVal) == ConstVal) ) {
856 Val =
static_cast<T>(Val | ConstVal);
860 template <
typename T>
861 void maskedBitSetCase(T &Val,
const char *Str, T ConstVal, T
Mask) {
862 if (bitSetMatch(Str, outputting() && (Val &
Mask) == ConstVal))
863 Val = Val | ConstVal;
866 template <
typename T>
867 void maskedBitSetCase(T &Val,
const char *Str,
uint32_t ConstVal,
869 if (bitSetMatch(Str, outputting() && (Val &
Mask) == ConstVal))
870 Val = Val | ConstVal;
873 void *getContext()
const;
874 void setContext(
void *);
876 template <
typename T>
void mapRequired(
const char *
Key, T &Val) {
878 this->processKey(
Key, Val,
true, Ctx);
881 template <
typename T,
typename Context>
882 void mapRequired(
const char *
Key, T &Val,
Context &Ctx) {
883 this->processKey(
Key, Val,
true, Ctx);
888 mapOptionalWithContext(
Key, Val, Ctx);
891 template <
typename T,
typename DefaultT>
892 void mapOptional(
const char *
Key, T &Val,
const DefaultT &Default) {
894 mapOptionalWithContext(
Key, Val, Default, Ctx);
897 template <
typename T,
typename Context>
898 std::enable_if_t<has_SequenceTraits<T>::value,
void>
899 mapOptionalWithContext(
const char *
Key, T &Val,
Context &Ctx) {
901 if (this->canElideEmptySequence() && !(Val.begin() != Val.end()))
903 this->processKey(
Key, Val,
false, Ctx);
906 template <
typename T,
typename Context>
907 void mapOptionalWithContext(
const char *
Key, Optional<T> &Val,
Context &Ctx) {
908 this->processKeyWithDefault(
Key, Val, Optional<T>(),
false,
912 template <
typename T,
typename Context>
913 std::enable_if_t<!has_SequenceTraits<T>::value,
void>
914 mapOptionalWithContext(
const char *
Key, T &Val,
Context &Ctx) {
915 this->processKey(
Key, Val,
false, Ctx);
918 template <
typename T,
typename Context,
typename DefaultT>
919 void mapOptionalWithContext(
const char *
Key, T &Val,
const DefaultT &Default,
921 static_assert(std::is_convertible<DefaultT, T>::value,
922 "Default type must be implicitly convertible to value type!");
923 this->processKeyWithDefault(
Key, Val,
static_cast<const T &
>(Default),
928 template <
typename T,
typename Context>
929 void processKeyWithDefault(
const char *
Key, Optional<T> &Val,
930 const Optional<T> &DefaultValue,
bool Required,
933 template <
typename T,
typename Context>
934 void processKeyWithDefault(
const char *
Key, T &Val,
const T &DefaultValue,
938 const bool sameAsDefault = outputting() && Val == DefaultValue;
939 if ( this->preflightKey(
Key,
Required, sameAsDefault, UseDefault,
942 this->postflightKey(SaveInfo);
950 template <
typename T,
typename Context>
954 if ( this->preflightKey(
Key,
Required,
false, UseDefault, SaveInfo) ) {
956 this->postflightKey(SaveInfo);
966 template <
typename T,
typename Context>
967 void doMapping(IO &io, T &Val,
Context &Ctx) {
968 MappingContextTraits<T, Context>::mapping(io, Val, Ctx);
971 template <
typename T>
void doMapping(IO &io, T &Val, EmptyContext &Ctx) {
972 MappingTraits<T>::mapping(io, Val);
977 template <
typename T>
978 std::enable_if_t<has_ScalarEnumerationTraits<T>::value,
void>
979 yamlize(IO &io, T &Val,
bool, EmptyContext &Ctx) {
980 io.beginEnumScalar();
981 ScalarEnumerationTraits<T>::enumeration(io, Val);
985 template <
typename T>
986 std::enable_if_t<has_ScalarBitSetTraits<T>::value,
void>
987 yamlize(IO &io, T &Val,
bool, EmptyContext &Ctx) {
989 if ( io.beginBitSetScalar(DoClear) ) {
992 ScalarBitSetTraits<T>::bitset(io, Val);
993 io.endBitSetScalar();
997 template <
typename T>
998 std::enable_if_t<has_ScalarTraits<T>::value,
void> yamlize(IO &io, T &Val,
bool,
1000 if ( io.outputting() ) {
1001 std::string Storage;
1002 raw_string_ostream Buffer(Storage);
1004 StringRef Str = Buffer.str();
1005 io.scalarString(Str, ScalarTraits<T>::mustQuote(Str));
1009 io.scalarString(Str, ScalarTraits<T>::mustQuote(Str));
1012 io.setError(Twine(Result));
1017 template <
typename T>
1018 std::enable_if_t<has_BlockScalarTraits<T>::value,
void>
1019 yamlize(IO &
YamlIO, T &Val,
bool, EmptyContext &Ctx) {
1020 if (
YamlIO.outputting()) {
1021 std::string Storage;
1022 raw_string_ostream Buffer(Storage);
1024 StringRef Str = Buffer.str();
1025 YamlIO.blockScalarString(Str);
1028 YamlIO.blockScalarString(Str);
1032 YamlIO.setError(Twine(Result));
1036 template <
typename T>
1037 std::enable_if_t<has_TaggedScalarTraits<T>::value,
void>
1038 yamlize(IO &io, T &Val,
bool, EmptyContext &Ctx) {
1039 if (io.outputting()) {
1040 std::string ScalarStorage, TagStorage;
1041 raw_string_ostream ScalarBuffer(ScalarStorage), TagBuffer(TagStorage);
1044 io.scalarTag(TagBuffer.str());
1045 StringRef ScalarStr = ScalarBuffer.str();
1046 io.scalarString(ScalarStr,
1047 TaggedScalarTraits<T>::mustQuote(Val, ScalarStr));
1056 io.setError(Twine(Result));
1061 template <
typename T,
typename Context>
1062 std::enable_if_t<validatedMappingTraits<T, Context>::value,
void>
1063 yamlize(IO &io, T &Val,
bool,
Context &Ctx) {
1064 if (has_FlowTraits<MappingTraits<T>>::value)
1065 io.beginFlowMapping();
1068 if (io.outputting()) {
1071 errs() << Err <<
"\n";
1072 assert(Err.empty() &&
"invalid struct trying to be written as yaml");
1075 detail::doMapping(io, Val, Ctx);
1076 if (!io.outputting()) {
1081 if (has_FlowTraits<MappingTraits<T>>::value)
1082 io.endFlowMapping();
1087 template <
typename T,
typename Context>
1088 std::enable_if_t<!has_MappingEnumInputTraits<T, Context>::value,
bool>
1089 yamlizeMappingEnumInput(IO &io, T &Val) {
1093 template <
typename T,
typename Context>
1094 std::enable_if_t<has_MappingEnumInputTraits<T, Context>::value,
bool>
1095 yamlizeMappingEnumInput(IO &io, T &Val) {
1096 if (io.outputting())
1099 io.beginEnumScalar();
1100 MappingTraits<T>::enumInput(io, Val);
1101 bool Matched = !io.matchEnumFallback();
1106 template <
typename T,
typename Context>
1107 std::enable_if_t<unvalidatedMappingTraits<T, Context>::value,
void>
1108 yamlize(IO &io, T &Val,
bool,
Context &Ctx) {
1109 if (yamlizeMappingEnumInput<T, Context>(io, Val))
1111 if (has_FlowTraits<MappingTraits<T>>::value) {
1112 io.beginFlowMapping();
1113 detail::doMapping(io, Val, Ctx);
1114 io.endFlowMapping();
1117 detail::doMapping(io, Val, Ctx);
1122 template <
typename T>
1123 std::enable_if_t<has_CustomMappingTraits<T>::value,
void>
1124 yamlize(IO &io, T &Val,
bool, EmptyContext &Ctx) {
1125 if ( io.outputting() ) {
1131 for (StringRef key : io.keys())
1132 CustomMappingTraits<T>::inputOne(io, key, Val);
1137 template <
typename T>
1138 std::enable_if_t<has_PolymorphicTraits<T>::value,
void>
1139 yamlize(IO &io, T &Val,
bool, EmptyContext &Ctx) {
1140 switch (io.outputting() ? PolymorphicTraits<T>::getKind(Val)
1141 : io.getNodeKind()) {
1143 return yamlize(io, PolymorphicTraits<T>::getAsScalar(Val),
true, Ctx);
1145 return yamlize(io, PolymorphicTraits<T>::getAsMap(Val),
true, Ctx);
1147 return yamlize(io, PolymorphicTraits<T>::getAsSequence(Val),
true, Ctx);
1151 template <
typename T>
1152 std::enable_if_t<missingTraits<T, EmptyContext>::value,
void>
1153 yamlize(IO &io, T &Val,
bool, EmptyContext &Ctx) {
1154 char missing_yaml_trait_for_type[
sizeof(MissingTrait<T>)];
1157 template <
typename T,
typename Context>
1158 std::enable_if_t<has_SequenceTraits<T>::value,
void>
1159 yamlize(IO &io, T &Seq,
bool,
Context &Ctx) {
1160 if ( has_FlowTraits< SequenceTraits<T>>::value ) {
1161 unsigned incnt = io.beginFlowSequence();
1163 for(
unsigned i=0;
i <
count; ++
i) {
1165 if ( io.preflightFlowElement(
i, SaveInfo) ) {
1166 yamlize(io, SequenceTraits<T>::element(io, Seq,
i),
true, Ctx);
1167 io.postflightFlowElement(SaveInfo);
1170 io.endFlowSequence();
1173 unsigned incnt = io.beginSequence();
1175 for(
unsigned i=0;
i <
count; ++
i) {
1177 if ( io.preflightElement(
i, SaveInfo) ) {
1178 yamlize(io, SequenceTraits<T>::element(io, Seq,
i),
true, Ctx);
1179 io.postflightElement(SaveInfo);
1187 struct ScalarTraits<bool> {
1188 static void output(
const bool &,
void* , raw_ostream &);
1189 static StringRef
input(StringRef,
void *,
bool &);
1194 struct ScalarTraits<StringRef> {
1195 static void output(
const StringRef &,
void *, raw_ostream &);
1196 static StringRef
input(StringRef,
void *, StringRef &);
1197 static QuotingType mustQuote(StringRef
S) {
return needsQuotes(
S); }
1202 static void output(
const std::string &,
void *, raw_ostream &);
1203 static StringRef
input(StringRef,
void *, std::string &);
1204 static QuotingType mustQuote(StringRef
S) {
return needsQuotes(
S); }
1208 struct ScalarTraits<uint8_t> {
1209 static void output(
const uint8_t &,
void *, raw_ostream &);
1210 static StringRef
input(StringRef,
void *, uint8_t &);
1236 struct ScalarTraits<int8_t> {
1237 static void output(
const int8_t &,
void *, raw_ostream &);
1238 static StringRef
input(StringRef,
void *, int8_t &);
1243 struct ScalarTraits<int16_t> {
1244 static void output(
const int16_t &,
void *, raw_ostream &);
1245 static StringRef
input(StringRef,
void *, int16_t &);
1250 struct ScalarTraits<int32_t> {
1251 static void output(
const int32_t &,
void *, raw_ostream &);
1252 static StringRef
input(StringRef,
void *, int32_t &);
1257 struct ScalarTraits<int64_t> {
1258 static void output(
const int64_t &,
void *, raw_ostream &);
1259 static StringRef
input(StringRef,
void *, int64_t &);
1264 struct ScalarTraits<float> {
1265 static void output(
const float &,
void *, raw_ostream &);
1266 static StringRef
input(StringRef,
void *,
float &);
1271 struct ScalarTraits<
double> {
1272 static void output(
const double &,
void *, raw_ostream &);
1273 static StringRef
input(StringRef,
void *,
double &);
1280 template <
typename value_type, support::endianness endian,
size_t alignment>
1281 struct ScalarTraits<
support::detail::packed_endian_specific_integral<
1282 value_type, endian, alignment>,
1283 std::enable_if_t<has_ScalarTraits<value_type>::value>> {
1285 support::detail::packed_endian_specific_integral<value_type,
endian,
1288 static void output(
const endian_type &
E,
void *Ctx, raw_ostream &Stream) {
1292 static StringRef
input(StringRef Str,
void *Ctx, endian_type &
E) {
1295 E =
static_cast<endian_type
>(V);
1299 static QuotingType mustQuote(StringRef Str) {
1300 return ScalarTraits<value_type>::mustQuote(Str);
1304 template <
typename value_type, support::endianness endian,
size_t alignment>
1305 struct ScalarEnumerationTraits<
1306 support::detail::packed_endian_specific_integral<value_type, endian,
1308 std::enable_if_t<has_ScalarEnumerationTraits<value_type>::value>> {
1310 support::detail::packed_endian_specific_integral<value_type,
endian,
1313 static void enumeration(IO &io, endian_type &
E) {
1315 ScalarEnumerationTraits<value_type>::enumeration(io, V);
1320 template <
typename value_type, support::endianness endian,
size_t alignment>
1321 struct ScalarBitSetTraits<
1322 support::detail::packed_endian_specific_integral<value_type, endian,
1324 std::enable_if_t<has_ScalarBitSetTraits<value_type>::value>> {
1326 support::detail::packed_endian_specific_integral<value_type,
endian,
1328 static void bitset(IO &io, endian_type &
E) {
1330 ScalarBitSetTraits<value_type>::bitset(io, V);
1337 template <
typename TNorm,
typename TFinal>
1338 struct MappingNormalization {
1339 MappingNormalization(IO &i_o, TFinal &Obj)
1340 : io(i_o), BufPtr(nullptr),
Result(Obj) {
1341 if ( io.outputting() ) {
1342 BufPtr =
new (&Buffer) TNorm(io, Obj);
1345 BufPtr =
new (&Buffer) TNorm(io);
1349 ~MappingNormalization() {
1350 if ( ! io.outputting() ) {
1351 Result = BufPtr->denormalize(io);
1356 TNorm* operator->() {
return BufPtr; }
1359 using Storage = AlignedCharArrayUnion<TNorm>;
1369 template <
typename TNorm,
typename TFinal>
1370 struct MappingNormalizationHeap {
1371 MappingNormalizationHeap(IO &i_o, TFinal &Obj,
BumpPtrAllocator *allocator)
1373 if ( io.outputting() ) {
1374 BufPtr =
new (&Buffer) TNorm(io, Obj);
1376 else if (allocator) {
1378 new (BufPtr) TNorm(io);
1380 BufPtr =
new TNorm(io);
1384 ~MappingNormalizationHeap() {
1385 if ( io.outputting() ) {
1389 Result = BufPtr->denormalize(io);
1393 TNorm* operator->() {
return BufPtr; }
1396 using Storage = AlignedCharArrayUnion<TNorm>;
1400 TNorm *BufPtr =
nullptr;
1416 class Input :
public IO {
1421 Input(StringRef InputContent,
1422 void *Ctxt =
nullptr,
1424 void *DiagHandlerCtxt =
nullptr);
1425 Input(MemoryBufferRef Input,
1426 void *Ctxt =
nullptr,
1428 void *DiagHandlerCtxt =
nullptr);
1432 std::error_code
error();
1435 bool outputting()
const override;
1436 bool mapTag(StringRef,
bool)
override;
1437 void beginMapping()
override;
1438 void endMapping()
override;
1439 bool preflightKey(
const char *,
bool,
bool,
bool &,
void *&)
override;
1440 void postflightKey(
void *)
override;
1441 std::vector<StringRef> keys()
override;
1442 void beginFlowMapping()
override;
1443 void endFlowMapping()
override;
1444 unsigned beginSequence()
override;
1445 void endSequence()
override;
1446 bool preflightElement(
unsigned index,
void *&)
override;
1447 void postflightElement(
void *)
override;
1448 unsigned beginFlowSequence()
override;
1449 bool preflightFlowElement(
unsigned ,
void *&)
override;
1450 void postflightFlowElement(
void *)
override;
1451 void endFlowSequence()
override;
1452 void beginEnumScalar()
override;
1453 bool matchEnumScalar(
const char*,
bool)
override;
1454 bool matchEnumFallback()
override;
1455 void endEnumScalar()
override;
1456 bool beginBitSetScalar(
bool &)
override;
1457 bool bitSetMatch(
const char *,
bool )
override;
1458 void endBitSetScalar()
override;
1459 void scalarString(StringRef &, QuotingType)
override;
1460 void blockScalarString(StringRef &)
override;
1461 void scalarTag(std::string &)
override;
1463 void setError(
const Twine &
message)
override;
1464 bool canElideEmptySequence()
override;
1467 virtual void anchor();
1470 HNode(
Node *
n) : _node(
n) { }
1471 virtual ~HNode() =
default;
1473 static bool classof(
const HNode *) {
return true; }
1478 class EmptyHNode :
public HNode {
1479 void anchor()
override;
1482 EmptyHNode(
Node *
n) : HNode(
n) { }
1486 static bool classof(
const EmptyHNode *) {
return true; }
1489 class ScalarHNode :
public HNode {
1490 void anchor()
override;
1493 ScalarHNode(
Node *
n, StringRef
s) : HNode(
n), _value(
s) { }
1495 StringRef value()
const {
return _value; }
1497 static bool classof(
const HNode *
n) {
1502 static bool classof(
const ScalarHNode *) {
return true; }
1508 class MapHNode :
public HNode {
1509 void anchor()
override;
1512 MapHNode(
Node *
n) : HNode(
n) { }
1514 static bool classof(
const HNode *
n) {
1518 static bool classof(
const MapHNode *) {
return true; }
1520 using NameToNodeAndLoc =
1521 StringMap<std::pair<std::unique_ptr<HNode>, SMRange>>;
1523 NameToNodeAndLoc Mapping;
1524 SmallVector<std::string, 6> ValidKeys;
1527 class SequenceHNode :
public HNode {
1528 void anchor()
override;
1531 SequenceHNode(
Node *
n) : HNode(
n) { }
1533 static bool classof(
const HNode *
n) {
1537 static bool classof(
const SequenceHNode *) {
return true; }
1539 std::vector<std::unique_ptr<HNode>> Entries;
1542 std::unique_ptr<Input::HNode> createHNodes(
Node *
node);
1543 void setError(HNode *hnode,
const Twine &
message);
1545 void setError(
const SMRange &Range,
const Twine &
message);
1547 void reportWarning(HNode *hnode,
const Twine &
message);
1548 void reportWarning(
Node *hnode,
const Twine &
message);
1549 void reportWarning(
const SMRange &Range,
const Twine &
message);
1554 bool setCurrentDocument();
1555 bool nextDocument();
1558 const Node *getCurrentNode()
const;
1560 void setAllowUnknownKeys(
bool Allow)
override;
1564 std::unique_ptr<llvm::yaml::Stream> Strm;
1565 std::unique_ptr<HNode> TopNode;
1568 document_iterator DocIterator;
1570 HNode *CurrentNode =
nullptr;
1571 bool ScalarMatchFound =
false;
1572 bool AllowUnknownKeys =
false;
1579 class Output :
public IO {
1581 Output(raw_ostream &,
void *Ctxt =
nullptr,
int WrapColumn = 70);
1589 void setWriteDefaultValues(
bool Write) { WriteDefaultValues =
Write; }
1591 bool outputting()
const override;
1592 bool mapTag(StringRef,
bool)
override;
1593 void beginMapping()
override;
1594 void endMapping()
override;
1595 bool preflightKey(
const char *key,
bool,
bool,
bool &,
void *&)
override;
1596 void postflightKey(
void *)
override;
1597 std::vector<StringRef> keys()
override;
1598 void beginFlowMapping()
override;
1599 void endFlowMapping()
override;
1600 unsigned beginSequence()
override;
1601 void endSequence()
override;
1602 bool preflightElement(
unsigned,
void *&)
override;
1603 void postflightElement(
void *)
override;
1604 unsigned beginFlowSequence()
override;
1605 bool preflightFlowElement(
unsigned,
void *&)
override;
1606 void postflightFlowElement(
void *)
override;
1607 void endFlowSequence()
override;
1608 void beginEnumScalar()
override;
1609 bool matchEnumScalar(
const char*,
bool)
override;
1610 bool matchEnumFallback()
override;
1611 void endEnumScalar()
override;
1612 bool beginBitSetScalar(
bool &)
override;
1613 bool bitSetMatch(
const char *,
bool )
override;
1614 void endBitSetScalar()
override;
1615 void scalarString(StringRef &, QuotingType)
override;
1616 void blockScalarString(StringRef &)
override;
1617 void scalarTag(std::string &)
override;
1619 void setError(
const Twine &
message)
override;
1620 bool canElideEmptySequence()
override;
1624 void beginDocuments();
1625 bool preflightDocument(
unsigned);
1626 void postflightDocument();
1627 void endDocuments();
1631 void outputUpToEndOfLine(StringRef
s);
1632 void newLineCheck(
bool EmptySequence =
false);
1633 void outputNewLine();
1634 void paddedKey(StringRef key);
1635 void flowKey(StringRef
Key);
1640 inFlowSeqFirstElement,
1641 inFlowSeqOtherElement,
1648 static bool inSeqAnyElement(InState State);
1649 static bool inFlowSeqAnyElement(InState State);
1650 static bool inMapAnyKey(InState State);
1651 static bool inFlowMapAnyKey(InState State);
1655 SmallVector<InState, 8> StateStack;
1657 int ColumnAtFlowStart = 0;
1658 int ColumnAtMapFlowStart = 0;
1659 bool NeedBitValueComma =
false;
1660 bool NeedFlowSequenceComma =
false;
1661 bool EnumerationMatchFound =
false;
1662 bool WriteDefaultValues =
false;
1664 StringRef PaddingBeforeContainer;
1667 template <
typename T,
typename Context>
1668 void IO::processKeyWithDefault(
const char *
Key, Optional<T> &Val,
1669 const Optional<T> &DefaultValue,
bool Required,
1671 assert(DefaultValue.hasValue() ==
false &&
1672 "Optional<T> shouldn't have a value!");
1674 bool UseDefault =
true;
1675 const bool sameAsDefault = outputting() && !Val.hasValue();
1676 if (!outputting() && !Val.hasValue())
1678 if (Val.hasValue() &&
1679 this->preflightKey(
Key,
Required, sameAsDefault, UseDefault, SaveInfo)) {
1685 bool IsNone =
false;
1687 if (
const auto *
Node = dyn_cast<ScalarNode>(((Input *)
this)->getCurrentNode()))
1690 IsNone =
Node->getRawValue().rtrim(
' ') ==
"<none>";
1695 yamlize(*
this, *Val,
Required, Ctx);
1696 this->postflightKey(SaveInfo);
1711 #define LLVM_YAML_STRONG_TYPEDEF(_base, _type) \
1713 _type() = default; \
1714 _type(const _base v) : value(v) {} \
1715 _type(const _type &v) = default; \
1716 _type &operator=(const _type &rhs) = default; \
1717 _type &operator=(const _base &rhs) { value = rhs; return *this; } \
1718 operator const _base & () const { return value; } \
1719 bool operator==(const _type &rhs) const { return value == rhs.value; } \
1720 bool operator==(const _base &rhs) const { return value == rhs; } \
1721 bool operator<(const _type &rhs) const { return value < rhs.value; } \
1723 using BaseType = _base; \
1736 struct ScalarTraits<Hex8> {
1737 static void output(
const Hex8 &,
void *, raw_ostream &);
1738 static StringRef
input(StringRef,
void *, Hex8 &);
1743 struct ScalarTraits<Hex16> {
1744 static void output(
const Hex16 &,
void *, raw_ostream &);
1745 static StringRef
input(StringRef,
void *, Hex16 &);
1750 struct ScalarTraits<Hex32> {
1751 static void output(
const Hex32 &,
void *, raw_ostream &);
1752 static StringRef
input(StringRef,
void *, Hex32 &);
1757 struct ScalarTraits<Hex64> {
1758 static void output(
const Hex64 &,
void *, raw_ostream &);
1759 static StringRef
input(StringRef,
void *, Hex64 &);
1763 template <>
struct ScalarTraits<VersionTuple> {
1765 static StringRef
input(StringRef,
void *, VersionTuple &);
1770 template <
typename T>
1771 inline std::enable_if_t<has_DocumentListTraits<T>::value,
Input &>
1775 while ( yin.setCurrentDocument() ) {
1776 yamlize(yin, DocumentListTraits<T>::element(yin, docList,
i),
true, Ctx);
1786 template <
typename T>
1787 inline std::enable_if_t<has_MappingTraits<T, EmptyContext>::value,
Input &>
1790 yin.setCurrentDocument();
1791 yamlize(yin, docMap,
true, Ctx);
1797 template <
typename T>
1798 inline std::enable_if_t<has_SequenceTraits<T>::value,
Input &>
1801 if (yin.setCurrentDocument())
1802 yamlize(yin, docSeq,
true, Ctx);
1807 template <
typename T>
1808 inline std::enable_if_t<has_BlockScalarTraits<T>::value,
Input &>
1811 if (
In.setCurrentDocument())
1812 yamlize(
In, Val,
true, Ctx);
1817 template <
typename T>
1818 inline std::enable_if_t<has_CustomMappingTraits<T>::value,
Input &>
1821 if (
In.setCurrentDocument())
1822 yamlize(
In, Val,
true, Ctx);
1827 template <
typename T>
1828 inline std::enable_if_t<has_PolymorphicTraits<T>::value,
Input &>
1831 if (
In.setCurrentDocument())
1832 yamlize(
In, Val,
true, Ctx);
1837 template <
typename T>
1838 inline std::enable_if_t<missingTraits<T, EmptyContext>::value,
Input &>
1840 char missing_yaml_trait_for_type[
sizeof(MissingTrait<T>)];
1845 template <
typename T>
1846 inline std::enable_if_t<has_DocumentListTraits<T>::value,
Output &>
1849 yout.beginDocuments();
1852 if ( yout.preflightDocument(
i) ) {
1853 yamlize(yout, DocumentListTraits<T>::element(yout, docList,
i),
true,
1855 yout.postflightDocument();
1858 yout.endDocuments();
1863 template <
typename T>
1864 inline std::enable_if_t<has_MappingTraits<T, EmptyContext>::value,
Output &>
1867 yout.beginDocuments();
1868 if ( yout.preflightDocument(0) ) {
1869 yamlize(yout, map,
true, Ctx);
1870 yout.postflightDocument();
1872 yout.endDocuments();
1877 template <
typename T>
1878 inline std::enable_if_t<has_SequenceTraits<T>::value,
Output &>
1881 yout.beginDocuments();
1882 if ( yout.preflightDocument(0) ) {
1883 yamlize(yout,
seq,
true, Ctx);
1884 yout.postflightDocument();
1886 yout.endDocuments();
1891 template <
typename T>
1892 inline std::enable_if_t<has_BlockScalarTraits<T>::value,
Output &>
1895 Out.beginDocuments();
1896 if (Out.preflightDocument(0)) {
1897 yamlize(Out, Val,
true, Ctx);
1898 Out.postflightDocument();
1905 template <
typename T>
1906 inline std::enable_if_t<has_CustomMappingTraits<T>::value,
Output &>
1909 Out.beginDocuments();
1910 if (Out.preflightDocument(0)) {
1911 yamlize(Out, Val,
true, Ctx);
1912 Out.postflightDocument();
1920 template <
typename T>
1921 inline std::enable_if_t<has_PolymorphicTraits<T>::value,
Output &>
1924 Out.beginDocuments();
1925 if (Out.preflightDocument(0)) {
1928 assert(PolymorphicTraits<T>::getKind(Val) !=
NodeKind::Scalar &&
"plain scalar documents are not supported");
1929 yamlize(Out, Val,
true, Ctx);
1930 Out.postflightDocument();
1937 template <
typename T>
1938 inline std::enable_if_t<missingTraits<T, EmptyContext>::value,
Output &>
1940 char missing_yaml_trait_for_type[
sizeof(MissingTrait<T>)];
1944 template <
bool B>
struct IsFlowSequenceBase {};
1945 template <>
struct IsFlowSequenceBase<
true> {
static const bool flow =
true; };
1947 template <
typename T,
bool Flow>
1948 struct SequenceTraitsImpl : IsFlowSequenceBase<Flow> {
1950 using type =
typename T::value_type;
1953 static size_t size(IO &io, T &
seq) {
return seq.size(); }
1964 template <
bool>
struct CheckIsBool {
static const bool value =
true; };
1968 template <
typename T>
1969 struct SequenceTraits<
1971 std::enable_if_t<CheckIsBool<SequenceElementTraits<T>::flow>::value>>
1972 : SequenceTraitsImpl<std::vector<T>, SequenceElementTraits<T>::flow> {};
1973 template <
typename T,
unsigned N>
1974 struct SequenceTraits<
1976 std::enable_if_t<CheckIsBool<SequenceElementTraits<T>::flow>::value>>
1977 : SequenceTraitsImpl<SmallVector<T, N>, SequenceElementTraits<T>::flow> {};
1978 template <
typename T>
1979 struct SequenceTraits<
1981 std::enable_if_t<CheckIsBool<SequenceElementTraits<T>::flow>::value>>
1982 : SequenceTraitsImpl<SmallVectorImpl<T>, SequenceElementTraits<T>::flow> {};
1985 template <
typename T>
1986 struct SequenceElementTraits<
T,
1987 std::enable_if_t<std::is_fundamental<T>::value>> {
1988 static const bool flow =
true;
1992 template<>
struct SequenceElementTraits<
std::
string> {
1993 static const bool flow =
false;
1995 template<>
struct SequenceElementTraits<StringRef> {
1996 static const bool flow =
false;
1998 template<>
struct SequenceElementTraits<
std::pair<std::string, std::string>> {
1999 static const bool flow =
false;
2003 template <
typename T>
struct StdMapStringCustomMappingTraitsImpl {
2004 using map_type = std::map<std::string, T>;
2006 static void inputOne(IO &io, StringRef key, map_type &v) {
2007 io.mapRequired(key.str().c_str(), v[std::string(key)]);
2010 static void output(IO &io, map_type &v) {
2012 io.mapRequired(
p.first.c_str(),
p.second);
2019 #define LLVM_YAML_IS_SEQUENCE_VECTOR_IMPL(TYPE, FLOW) \
2023 !std::is_fundamental<TYPE>::value && \
2024 !std::is_same<TYPE, std::string>::value && \
2025 !std::is_same<TYPE, llvm::StringRef>::value, \
2026 "only use LLVM_YAML_IS_SEQUENCE_VECTOR for types you control"); \
2027 template <> struct SequenceElementTraits<TYPE> { \
2028 static const bool flow = FLOW; \
2035 #define LLVM_YAML_IS_SEQUENCE_VECTOR(type) \
2036 LLVM_YAML_IS_SEQUENCE_VECTOR_IMPL(type, false)
2040 #define LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(type) \
2041 LLVM_YAML_IS_SEQUENCE_VECTOR_IMPL(type, true)
2043 #define LLVM_YAML_DECLARE_MAPPING_TRAITS(Type) \
2046 template <> struct MappingTraits<Type> { \
2047 static void mapping(IO &IO, Type &Obj); \
2052 #define LLVM_YAML_DECLARE_ENUM_TRAITS(Type) \
2055 template <> struct ScalarEnumerationTraits<Type> { \
2056 static void enumeration(IO &io, Type &Value); \
2061 #define LLVM_YAML_DECLARE_BITSET_TRAITS(Type) \
2064 template <> struct ScalarBitSetTraits<Type> { \
2065 static void bitset(IO &IO, Type &Options); \
2070 #define LLVM_YAML_DECLARE_SCALAR_TRAITS(Type, MustQuote) \
2073 template <> struct ScalarTraits<Type> { \
2074 static void output(const Type &Value, void *ctx, raw_ostream &Out); \
2075 static StringRef input(StringRef Scalar, void *ctxt, Type &Value); \
2076 static QuotingType mustQuote(StringRef) { return MustQuote; } \
2083 #define LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(_type) \
2086 template <unsigned N> \
2087 struct DocumentListTraits<SmallVector<_type, N>> \
2088 : public SequenceTraitsImpl<SmallVector<_type, N>, false> {}; \
2090 struct DocumentListTraits<std::vector<_type>> \
2091 : public SequenceTraitsImpl<std::vector<_type>, false> {}; \
2097 #define LLVM_YAML_IS_STRING_MAP(_type) \
2101 struct CustomMappingTraits<std::map<std::string, _type>> \
2102 : public StdMapStringCustomMappingTraitsImpl<_type> {}; \
2111 #endif // LLVM_SUPPORT_YAMLTRAITS_H