YAML streaming for generated types

This commit is contained in:
Pavel Kirienko
2014-03-07 00:43:36 +04:00
parent da6e25a708
commit 4753d4ac79
10 changed files with 386 additions and 5 deletions
@@ -115,7 +115,11 @@ class ArrayImpl : public StaticIf<ArrayMode == ArrayModeDynamic,
StaticArrayBase<MaxSize> >::Result Base;
public:
enum { IsStringLike = IsIntegerSpec<T>::Result && (T::MaxBitLen == 8 || T::MaxBitLen == 7) };
enum
{
IsStringLike = IsIntegerSpec<T>::Result && (T::MaxBitLen == 8 || T::MaxBitLen == 7)
&& (ArrayMode == ArrayModeDynamic)
};
private:
typedef typename StorageType<T>::Type BufferType[MaxSize + (IsStringLike ? 1 : 0)];
@@ -410,4 +414,114 @@ inline bool operator!=(const R& rhs, const Array<T, ArrayMode, MaxSize>& lhs)
return lhs.operator!=(rhs);
}
template <typename T, ArrayMode ArrayMode, unsigned int MaxSize>
class YamlStreamer<Array<T, ArrayMode, MaxSize> >
{
typedef Array<T, ArrayMode, MaxSize> ArrayType;
template <typename Stream>
static void streamPrimitives(Stream& s, const ArrayType& array)
{
s << '[';
for (std::size_t i = 0; i < array.size(); i++)
{
YamlStreamer<T>::stream(s, array.at(i), 0);
if ((i + 1) < array.size())
s << ", ";
}
s << ']';
}
template <typename Stream>
static void streamCharacters(Stream& s, const ArrayType& array)
{
s << '"';
for (std::size_t i = 0; i < array.size(); i++)
{
const unsigned int c = array.at(i);
if (c < 32 || c > 126) // Non-printable characters
{
char nibbles[2] = {(c >> 4) & 0xF, c & 0xF};
for (int i = 0; i < 2; i++)
{
nibbles[i] += '0';
if (nibbles[i] > '9')
nibbles[i] += 'A' - '9' - 1;
}
s << "\\x" << nibbles[0] << nibbles[1];
}
else
{
if (c == '"' || c == '\\') // YAML requires to escape these two
s << '\\';
s << char(c);
}
}
s << '"';
}
struct SelectorStringLike { };
struct SelectorPrimitives { };
struct SelectorObjects { };
template <typename Stream>
static void genericStreamImpl(Stream& s, const ArrayType& array, int, SelectorStringLike)
{
bool printable_only = true;
for (int i = 0; i < array.size(); i++)
{
if (array[i] < 32 || array[i] > 126)
{
printable_only = false;
break;
}
}
if (printable_only)
{
streamCharacters(s, array);
}
else
{
streamPrimitives(s, array);
s << " # ";
streamCharacters(s, array);
}
}
template <typename Stream>
static void genericStreamImpl(Stream& s, const ArrayType& array, int, SelectorPrimitives)
{
streamPrimitives(s, array);
}
template <typename Stream>
static void genericStreamImpl(Stream& s, const ArrayType& array, int level, SelectorObjects)
{
if (array.empty())
{
s << "[]";
return;
}
for (std::size_t i = 0; i < array.size(); i++)
{
s << '\n';
for (int pos = 0; pos < level; pos++)
s << " ";
s << "- ";
YamlStreamer<T>::stream(s, array.at(i), level + 1);
}
}
public:
template <typename Stream>
static void stream(Stream& s, const ArrayType& array, int level)
{
typedef typename StaticIf<ArrayType::IsStringLike, SelectorStringLike,
typename StaticIf<IsPrimitiveType<typename ArrayType::RawValueType>::Result, SelectorPrimitives,
SelectorObjects>::Result >::Result Type;
genericStreamImpl(s, array, level, Type());
}
};
}
@@ -102,6 +102,7 @@ public:
enum { BitLen = BitLen_ };
enum { MinBitLen = BitLen };
enum { MaxBitLen = BitLen };
enum { IsPrimitive = 1 };
typedef typename NativeFloatSelector<BitLen>::Type StorageType;
@@ -157,4 +158,17 @@ private:
}
};
template <unsigned int BitLen, CastMode CastMode>
struct YamlStreamer<FloatSpec<BitLen, CastMode> >
{
typedef typename FloatSpec<BitLen, CastMode>::StorageType StorageType;
template <typename Stream>
static void stream(Stream& s, const StorageType value, int)
{
s << value;
}
};
}
@@ -19,14 +19,14 @@ enum Signedness { SignednessUnsigned, SignednessSigned };
template <unsigned int BitLen_, Signedness Signedness, CastMode CastMode>
class IntegerSpec
{
enum { IsSigned = Signedness == SignednessSigned };
struct ErrorNoSuchInteger;
public:
enum { IsSigned = Signedness == SignednessSigned };
enum { BitLen = BitLen_ };
enum { MinBitLen = BitLen };
enum { MaxBitLen = BitLen };
enum { IsPrimitive = 1 };
typedef typename StaticIf<(BitLen <= 8), typename StaticIf<IsSigned, int8_t, uint8_t>::Result,
typename StaticIf<(BitLen <= 16), typename StaticIf<IsSigned, int16_t, uint16_t>::Result,
@@ -116,4 +116,21 @@ struct IsIntegerSpec { enum { Result = 0 }; };
template <unsigned int BitLen, Signedness Signedness, CastMode CastMode>
struct IsIntegerSpec<IntegerSpec<BitLen, Signedness, CastMode> > { enum { Result = 1 }; };
template <unsigned int BitLen, Signedness Signedness, CastMode CastMode>
struct YamlStreamer<IntegerSpec<BitLen, Signedness, CastMode> >
{
typedef IntegerSpec<BitLen, Signedness, CastMode> RawType;
typedef typename RawType::StorageType StorageType;
template <typename Stream>
static void stream(Stream& s, const StorageType value, int)
{
// Get rid of character types - we want its integer representation, not ASCII code
typedef typename StaticIf<(sizeof(StorageType) >= sizeof(int)), StorageType,
typename StaticIf<RawType::IsSigned, int, unsigned int>::Result >::Result TempType;
s << TempType(value);
}
};
}
@@ -29,4 +29,25 @@ struct StorageType<T, typename EnableIfType<typename T::StorageType>::Type>
typedef typename T::StorageType Type;
};
template <typename T>
class IsPrimitiveType
{
typedef char Yes;
struct No { Yes dummy[8]; };
template <typename U>
static typename EnableIf<U::IsPrimitive, Yes>::Type test(int);
template <typename>
static No test(...);
public:
enum { Result = sizeof(test<T>(0)) == sizeof(Yes) };
};
template <typename T>
struct YamlStreamer;
}