#pragma once // // This file is distributed under the MIT License. See LICENSE.md for details. // #include "llvm/Support/YAMLTraits.h" #include "revng/Support/Assert.h" template concept HasScalarTraits = llvm::yaml::has_ScalarTraits::value; template concept HasScalarEnumTraits = llvm::yaml::has_ScalarEnumerationTraits::value; template concept HasScalarOrEnumTraits = HasScalarTraits or HasScalarEnumTraits; template inline llvm::StringRef getNameFromYAMLEnumScalar(T V) { using namespace llvm::yaml; struct GetScalarIO { llvm::StringRef Result; void enumCase(const T &V, llvm::StringRef Name, const T &M, llvm::yaml::QuotingType = llvm::yaml::QuotingType::None) { if (V == M) { Result = Name; } } }; GetScalarIO ExtractName; llvm::yaml::ScalarEnumerationTraits::enumeration(ExtractName, V); return ExtractName.Result; } template inline std::string getNameFromYAMLScalar(T V) { using namespace llvm::yaml; if constexpr (has_ScalarTraits::value) { std::string Buffer; llvm::raw_string_ostream Stream(Buffer); llvm::yaml::ScalarTraits::output(V, nullptr, Stream); return Buffer; } else { return getNameFromYAMLEnumScalar(V).str(); } } template T getInvalidValueFromYAMLScalar() { // Default action: abort. Users can override this behavior. revng_abort(); } template inline T getValueFromYAMLScalar(llvm::StringRef Name) { using namespace llvm::yaml; T Result; if constexpr (has_ScalarTraits::value) { llvm::yaml::ScalarTraits::input(Name, nullptr, Result); } else { struct GetScalarIO { bool Found = false; llvm::StringRef TargetName; void enumCase(T &V, llvm::StringRef Name, const T &M, llvm::yaml::QuotingType = llvm::yaml::QuotingType::None) { if (TargetName == Name) { revng_assert(not Found); Found = true; V = M; } } }; GetScalarIO ExtractValue{ false, Name }; llvm::yaml::ScalarEnumerationTraits::enumeration(ExtractValue, Result); if (not ExtractValue.Found) Result = getInvalidValueFromYAMLScalar(); } return Result; } template struct CompositeScalar { static_assert(std::tuple_size_v >= 0); template static void output(const T &Value, void *Ctx, llvm::raw_ostream &Output) { if constexpr (I < std::tuple_size_v) { if constexpr (I != 0) { Output << Separator; } using element = std::tuple_element_t; Output << getNameFromYAMLScalar(get(Value)); CompositeScalar::output(Value, Ctx, Output); } } template static llvm::StringRef input(llvm::StringRef Scalar, void *Ctx, T &Value) { if constexpr (I < std::tuple_size_v) { auto [Before, After] = Scalar.split(Separator); using element = std::tuple_element_t; get(Value) = getValueFromYAMLScalar(Before); return CompositeScalar::input(After, Ctx, Value); } else { revng_assert(Scalar.size() == 0); return Scalar; } } static llvm::yaml::QuotingType mustQuote(llvm::StringRef) { return llvm::yaml::QuotingType::Double; } };