forked from OSchip/llvm-project
[yaml] Add a ScalarTraits for mapping endian aware types.
This allows mapping of any endian-aware type whose underlying type (e.g. uint32_t) provides a ScalarTraits specialization. Reviewed by: majnemer Differential Revision: http://reviews.llvm.org/D21057 llvm-svn: 272049
This commit is contained in:
parent
8b61759c05
commit
4fbf61d518
|
@ -17,6 +17,7 @@
|
|||
#include "llvm/ADT/StringSwitch.h"
|
||||
#include "llvm/ADT/Twine.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include "llvm/Support/Endian.h"
|
||||
#include "llvm/Support/Regex.h"
|
||||
#include "llvm/Support/SourceMgr.h"
|
||||
#include "llvm/Support/YAMLParser.h"
|
||||
|
@ -856,6 +857,32 @@ struct ScalarTraits<double> {
|
|||
static bool mustQuote(StringRef) { return false; }
|
||||
};
|
||||
|
||||
// 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.
|
||||
template <typename value_type, support::endianness endian, size_t alignment>
|
||||
struct ScalarTraits<support::detail::packed_endian_specific_integral<
|
||||
value_type, endian, alignment>> {
|
||||
typedef support::detail::packed_endian_specific_integral<value_type, endian,
|
||||
alignment>
|
||||
endian_type;
|
||||
|
||||
static void output(const endian_type &E, void *Ctx,
|
||||
llvm::raw_ostream &Stream) {
|
||||
ScalarTraits<value_type>::output(static_cast<value_type>(E), Ctx, Stream);
|
||||
}
|
||||
static StringRef input(StringRef Str, void *Ctx, endian_type &E) {
|
||||
value_type V;
|
||||
auto R = ScalarTraits<value_type>::input(Str, Ctx, V);
|
||||
E = static_cast<endian_type>(V);
|
||||
return R;
|
||||
}
|
||||
|
||||
static bool mustQuote(StringRef Str) {
|
||||
return ScalarTraits<value_type>::mustQuote(Str);
|
||||
}
|
||||
};
|
||||
|
||||
// Utility for use within MappingTraits<>::mapping() method
|
||||
// to [de]normalize an object for use with YAML conversion.
|
||||
template <typename TNorm, typename TFinal>
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include "llvm/ADT/Twine.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
#include "llvm/Support/Endian.h"
|
||||
#include "llvm/Support/Format.h"
|
||||
#include "llvm/Support/YAMLTraits.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
@ -388,6 +389,111 @@ TEST(YAMLIO, TestReadWriteBuiltInTypes) {
|
|||
}
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Test endian-aware types
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
struct EndianTypes {
|
||||
typedef llvm::support::detail::packed_endian_specific_integral<
|
||||
float, llvm::support::little, llvm::support::unaligned>
|
||||
ulittle_float;
|
||||
typedef llvm::support::detail::packed_endian_specific_integral<
|
||||
double, llvm::support::little, llvm::support::unaligned>
|
||||
ulittle_double;
|
||||
|
||||
llvm::support::ulittle64_t u64;
|
||||
llvm::support::ulittle32_t u32;
|
||||
llvm::support::ulittle16_t u16;
|
||||
llvm::support::little64_t s64;
|
||||
llvm::support::little32_t s32;
|
||||
llvm::support::little16_t s16;
|
||||
ulittle_float f;
|
||||
ulittle_double d;
|
||||
};
|
||||
|
||||
namespace llvm {
|
||||
namespace yaml {
|
||||
template <> struct MappingTraits<EndianTypes> {
|
||||
static void mapping(IO &io, EndianTypes &et) {
|
||||
io.mapRequired("u64", et.u64);
|
||||
io.mapRequired("u32", et.u32);
|
||||
io.mapRequired("u16", et.u16);
|
||||
io.mapRequired("s64", et.s64);
|
||||
io.mapRequired("s32", et.s32);
|
||||
io.mapRequired("s16", et.s16);
|
||||
io.mapRequired("f", et.f);
|
||||
io.mapRequired("d", et.d);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Test the reading of all endian scalar conversions
|
||||
//
|
||||
TEST(YAMLIO, TestReadEndianTypes) {
|
||||
EndianTypes map;
|
||||
Input yin("---\n"
|
||||
"u64: 5000000000\n"
|
||||
"u32: 4000000000\n"
|
||||
"u16: 65000\n"
|
||||
"s64: -5000000000\n"
|
||||
"s32: -2000000000\n"
|
||||
"s16: -32000\n"
|
||||
"f: 3.25\n"
|
||||
"d: -2.8625\n"
|
||||
"...\n");
|
||||
yin >> map;
|
||||
|
||||
EXPECT_FALSE(yin.error());
|
||||
EXPECT_EQ(map.u64, 5000000000ULL);
|
||||
EXPECT_EQ(map.u32, 4000000000U);
|
||||
EXPECT_EQ(map.u16, 65000);
|
||||
EXPECT_EQ(map.s64, -5000000000LL);
|
||||
EXPECT_EQ(map.s32, -2000000000L);
|
||||
EXPECT_EQ(map.s16, -32000);
|
||||
EXPECT_EQ(map.f, 3.25f);
|
||||
EXPECT_EQ(map.d, -2.8625);
|
||||
}
|
||||
|
||||
//
|
||||
// Test writing then reading back all endian-aware scalar types
|
||||
//
|
||||
TEST(YAMLIO, TestReadWriteEndianTypes) {
|
||||
std::string intermediate;
|
||||
{
|
||||
EndianTypes map;
|
||||
map.u64 = 6000000000ULL;
|
||||
map.u32 = 3000000000U;
|
||||
map.u16 = 50000;
|
||||
map.s64 = -6000000000LL;
|
||||
map.s32 = -2000000000;
|
||||
map.s16 = -32000;
|
||||
map.f = 3.25f;
|
||||
map.d = -2.8625;
|
||||
|
||||
llvm::raw_string_ostream ostr(intermediate);
|
||||
Output yout(ostr);
|
||||
yout << map;
|
||||
}
|
||||
|
||||
{
|
||||
Input yin(intermediate);
|
||||
EndianTypes map;
|
||||
yin >> map;
|
||||
|
||||
EXPECT_FALSE(yin.error());
|
||||
EXPECT_EQ(map.u64, 6000000000ULL);
|
||||
EXPECT_EQ(map.u32, 3000000000U);
|
||||
EXPECT_EQ(map.u16, 50000);
|
||||
EXPECT_EQ(map.s64, -6000000000LL);
|
||||
EXPECT_EQ(map.s32, -2000000000L);
|
||||
EXPECT_EQ(map.s16, -32000);
|
||||
EXPECT_EQ(map.f, 3.25f);
|
||||
EXPECT_EQ(map.d, -2.8625);
|
||||
}
|
||||
}
|
||||
|
||||
struct StringTypes {
|
||||
llvm::StringRef str1;
|
||||
llvm::StringRef str2;
|
||||
|
|
Loading…
Reference in New Issue