/// io.enumCase(value, "green", cGreen);
/// }
/// };
-template<typename T>
-struct ScalarEnumerationTraits {
+template <typename T, typename Enable = void> struct ScalarEnumerationTraits {
// Must provide:
// static void enumeration(IO &io, T &value);
};
/// io.bitSetCase(value, "round", flagRound);
/// }
/// };
-template<typename T>
-struct ScalarBitSetTraits {
+template <typename T, typename Enable = void> struct ScalarBitSetTraits {
// Must provide:
// static void bitset(IO &io, T &value);
};
/// }
/// static QuotingType mustQuote(StringRef) { return QuotingType::Single; }
/// };
-template<typename T>
-struct ScalarTraits {
+template <typename T, typename Enable = void> struct ScalarTraits {
// Must provide:
//
// Function to write the value as a string:
bool DoClear;
if ( io.beginBitSetScalar(DoClear) ) {
if ( DoClear )
- Val = static_cast<T>(0);
+ Val = T();
ScalarBitSetTraits<T>::bitset(io, Val);
io.endBitSetScalar();
}
static QuotingType mustQuote(StringRef) { return QuotingType::None; }
};
-// For endian types, we just use the existing ScalarTraits for the underlying
-// type. This way endian aware types are supported whenever a ScalarTraits
-// is defined for the underlying type.
+// For endian types, we use existing scalar Traits class for the underlying
+// type. This way endian aware types are supported whenever the traits are
+// defined for the underlying type.
template <typename value_type, support::endianness endian, size_t alignment>
-struct ScalarTraits<support::detail::packed_endian_specific_integral<
- value_type, endian, alignment>> {
+struct ScalarTraits<
+ support::detail::packed_endian_specific_integral<value_type, endian,
+ alignment>,
+ typename std::enable_if<has_ScalarTraits<value_type>::value>::type> {
using endian_type =
support::detail::packed_endian_specific_integral<value_type, endian,
alignment>;
}
};
+template <typename value_type, support::endianness endian, size_t alignment>
+struct ScalarEnumerationTraits<
+ support::detail::packed_endian_specific_integral<value_type, endian,
+ alignment>,
+ typename std::enable_if<
+ has_ScalarEnumerationTraits<value_type>::value>::type> {
+ using endian_type =
+ support::detail::packed_endian_specific_integral<value_type, endian,
+ alignment>;
+
+ static void enumeration(IO &io, endian_type &E) {
+ value_type V = E;
+ ScalarEnumerationTraits<value_type>::enumeration(io, V);
+ E = V;
+ }
+};
+
+template <typename value_type, support::endianness endian, size_t alignment>
+struct ScalarBitSetTraits<
+ support::detail::packed_endian_specific_integral<value_type, endian,
+ alignment>,
+ typename std::enable_if<has_ScalarBitSetTraits<value_type>::value>::type> {
+ using endian_type =
+ support::detail::packed_endian_specific_integral<value_type, endian,
+ alignment>;
+ static void bitset(IO &io, endian_type &E) {
+ value_type V = E;
+ ScalarBitSetTraits<value_type>::bitset(io, V);
+ E = V;
+ }
+};
+
// Utility for use within MappingTraits<>::mapping() method
// to [de]normalize an object for use with YAML conversion.
template <typename TNorm, typename TFinal>
//
//===----------------------------------------------------------------------===//
+#include "llvm/ADT/BitmaskEnum.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
}
}
+enum class Enum : uint16_t { One, Two };
+enum class BitsetEnum : uint16_t {
+ ZeroOne = 0x01,
+ OneZero = 0x10,
+ LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue*/ OneZero),
+};
+LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
+struct EndianEnums {
+ llvm::support::little_t<Enum> LittleEnum;
+ llvm::support::big_t<Enum> BigEnum;
+ llvm::support::little_t<BitsetEnum> LittleBitset;
+ llvm::support::big_t<BitsetEnum> BigBitset;
+};
+namespace llvm {
+namespace yaml {
+template <> struct ScalarEnumerationTraits<Enum> {
+ static void enumeration(IO &io, Enum &E) {
+ io.enumCase(E, "One", Enum::One);
+ io.enumCase(E, "Two", Enum::Two);
+ }
+};
+
+template <> struct ScalarBitSetTraits<BitsetEnum> {
+ static void bitset(IO &io, BitsetEnum &E) {
+ io.bitSetCase(E, "ZeroOne", BitsetEnum::ZeroOne);
+ io.bitSetCase(E, "OneZero", BitsetEnum::OneZero);
+ }
+};
+
+template <> struct MappingTraits<EndianEnums> {
+ static void mapping(IO &io, EndianEnums &EE) {
+ io.mapRequired("LittleEnum", EE.LittleEnum);
+ io.mapRequired("BigEnum", EE.BigEnum);
+ io.mapRequired("LittleBitset", EE.LittleBitset);
+ io.mapRequired("BigBitset", EE.BigBitset);
+ }
+};
+} // namespace yaml
+} // namespace llvm
+
+TEST(YAMLIO, TestReadEndianEnums) {
+ EndianEnums map;
+ Input yin("---\n"
+ "LittleEnum: One\n"
+ "BigEnum: Two\n"
+ "LittleBitset: [ ZeroOne ]\n"
+ "BigBitset: [ ZeroOne, OneZero ]\n"
+ "...\n");
+ yin >> map;
+
+ EXPECT_FALSE(yin.error());
+ EXPECT_EQ(Enum::One, map.LittleEnum);
+ EXPECT_EQ(Enum::Two, map.BigEnum);
+ EXPECT_EQ(BitsetEnum::ZeroOne, map.LittleBitset);
+ EXPECT_EQ(BitsetEnum::ZeroOne | BitsetEnum::OneZero, map.BigBitset);
+}
+
+TEST(YAMLIO, TestReadWriteEndianEnums) {
+ std::string intermediate;
+ {
+ EndianEnums map;
+ map.LittleEnum = Enum::Two;
+ map.BigEnum = Enum::One;
+ map.LittleBitset = BitsetEnum::OneZero | BitsetEnum::ZeroOne;
+ map.BigBitset = BitsetEnum::OneZero;
+
+ llvm::raw_string_ostream ostr(intermediate);
+ Output yout(ostr);
+ yout << map;
+ }
+
+ {
+ Input yin(intermediate);
+ EndianEnums map;
+ yin >> map;
+
+ EXPECT_FALSE(yin.error());
+ EXPECT_EQ(Enum::Two, map.LittleEnum);
+ EXPECT_EQ(Enum::One, map.BigEnum);
+ EXPECT_EQ(BitsetEnum::OneZero | BitsetEnum::ZeroOne, map.LittleBitset);
+ EXPECT_EQ(BitsetEnum::OneZero, map.BigBitset);
+ }
+}
+
struct StringTypes {
llvm::StringRef str1;
llvm::StringRef str2;