mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-06-28 00:40:35 +08:00
170 lines
5.2 KiB
C++
170 lines
5.2 KiB
C++
/*
|
|
* Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
|
|
*/
|
|
|
|
#ifndef UAVCAN_MARSHAL_INTEGER_SPEC_HPP_INCLUDED
|
|
#define UAVCAN_MARSHAL_INTEGER_SPEC_HPP_INCLUDED
|
|
|
|
#include <uavcan/std.hpp>
|
|
#include <uavcan/data_type.hpp>
|
|
#include <uavcan/util/templates.hpp>
|
|
#include <uavcan/marshal/scalar_codec.hpp>
|
|
#include <uavcan/marshal/type_util.hpp>
|
|
|
|
namespace uavcan
|
|
{
|
|
|
|
enum Signedness { SignednessUnsigned, SignednessSigned };
|
|
|
|
template <unsigned BitLen_, Signedness Signedness, CastMode CastMode>
|
|
class UAVCAN_EXPORT IntegerSpec
|
|
{
|
|
struct ErrorNoSuchInteger;
|
|
|
|
public:
|
|
enum { IsSigned = Signedness == SignednessSigned };
|
|
enum { BitLen = BitLen_ };
|
|
enum { MinBitLen = BitLen };
|
|
enum { MaxBitLen = BitLen };
|
|
enum { IsPrimitive = 1 };
|
|
|
|
typedef typename Select<(BitLen <= 8), typename Select<IsSigned, int8_t, uint8_t>::Result,
|
|
typename Select<(BitLen <= 16), typename Select<IsSigned, int16_t, uint16_t>::Result,
|
|
typename Select<(BitLen <= 32), typename Select<IsSigned, int32_t, uint32_t>::Result,
|
|
typename Select<(BitLen <= 64), typename Select<IsSigned, int64_t, uint64_t>::Result,
|
|
ErrorNoSuchInteger>::Result>::Result>::Result>::Result StorageType;
|
|
|
|
typedef typename IntegerSpec<BitLen, SignednessUnsigned, CastMode>::StorageType UnsignedStorageType;
|
|
|
|
private:
|
|
IntegerSpec();
|
|
|
|
struct LimitsImplGeneric
|
|
{
|
|
static StorageType max()
|
|
{
|
|
StaticAssert<(sizeof(uintmax_t) >= 8)>::check();
|
|
if (IsSigned == 0)
|
|
{
|
|
return StorageType((uintmax_t(1) << static_cast<unsigned>(BitLen)) - 1U);
|
|
}
|
|
else
|
|
{
|
|
return StorageType((uintmax_t(1) << (static_cast<unsigned>(BitLen) - 1U)) - 1);
|
|
}
|
|
}
|
|
static UnsignedStorageType mask()
|
|
{
|
|
StaticAssert<(sizeof(uintmax_t) >= 8U)>::check();
|
|
return UnsignedStorageType((uintmax_t(1) << static_cast<unsigned>(BitLen)) - 1U);
|
|
}
|
|
};
|
|
|
|
struct LimitsImpl64
|
|
{
|
|
static StorageType max()
|
|
{
|
|
return StorageType((IsSigned == 0) ? 0xFFFFFFFFFFFFFFFFULL : 0x7FFFFFFFFFFFFFFFLL);
|
|
}
|
|
static UnsignedStorageType mask() { return 0xFFFFFFFFFFFFFFFFULL; }
|
|
};
|
|
|
|
typedef typename Select<(BitLen == 64), LimitsImpl64, LimitsImplGeneric>::Result Limits;
|
|
|
|
static void saturate(StorageType& value)
|
|
{
|
|
if (value > max())
|
|
{
|
|
value = max();
|
|
}
|
|
else if (value <= min()) // 'Less or Equal' allows to suppress compiler warning on unsigned types
|
|
{
|
|
value = min();
|
|
}
|
|
else
|
|
{
|
|
; // Valid range
|
|
}
|
|
}
|
|
|
|
static void truncate(StorageType& value) { value = value & StorageType(mask()); }
|
|
|
|
static void validate()
|
|
{
|
|
StaticAssert<(BitLen <= (sizeof(StorageType) * 8))>::check();
|
|
// coverity[result_independent_of_operands : FALSE]
|
|
UAVCAN_ASSERT(max() <= NumericTraits<StorageType>::max());
|
|
// coverity[result_independent_of_operands : FALSE]
|
|
UAVCAN_ASSERT(min() >= NumericTraits<StorageType>::min());
|
|
}
|
|
|
|
public:
|
|
static StorageType max() { return Limits::max(); }
|
|
static StorageType min() { return IsSigned ? StorageType(-max() - 1) : 0; }
|
|
static UnsignedStorageType mask() { return Limits::mask(); }
|
|
|
|
static int encode(StorageType value, ScalarCodec& codec, TailArrayOptimizationMode)
|
|
{
|
|
validate();
|
|
// cppcheck-suppress duplicateExpression
|
|
if (CastMode == CastModeSaturate)
|
|
{
|
|
saturate(value);
|
|
}
|
|
else
|
|
{
|
|
truncate(value);
|
|
}
|
|
return codec.encode<BitLen>(value);
|
|
}
|
|
|
|
static int decode(StorageType& out_value, ScalarCodec& codec, TailArrayOptimizationMode)
|
|
{
|
|
validate();
|
|
return codec.decode<BitLen>(out_value);
|
|
}
|
|
|
|
static void extendDataTypeSignature(DataTypeSignature&) { }
|
|
};
|
|
|
|
template <CastMode CastMode>
|
|
class IntegerSpec<1, SignednessSigned, CastMode>; // Invalid instantiation
|
|
|
|
template <Signedness Signedness, CastMode CastMode>
|
|
class IntegerSpec<0, Signedness, CastMode>; // Invalid instantiation
|
|
|
|
|
|
template <typename T>
|
|
struct IsIntegerSpec
|
|
{
|
|
enum { Result = 0 };
|
|
};
|
|
|
|
template <unsigned BitLen, Signedness Signedness, CastMode CastMode>
|
|
struct IsIntegerSpec<IntegerSpec<BitLen, Signedness, CastMode> >
|
|
{
|
|
enum { Result = 1 };
|
|
};
|
|
|
|
|
|
template <unsigned BitLen, Signedness Signedness, CastMode CastMode>
|
|
class UAVCAN_EXPORT YamlStreamer<IntegerSpec<BitLen, Signedness, CastMode> >
|
|
{
|
|
typedef IntegerSpec<BitLen, Signedness, CastMode> RawType;
|
|
typedef typename RawType::StorageType StorageType;
|
|
|
|
public:
|
|
template <typename Stream> // cppcheck-suppress passedByValue
|
|
static void stream(Stream& s, const StorageType value, int)
|
|
{
|
|
// Get rid of character types - we want its integer representation, not ASCII code
|
|
typedef typename Select<(sizeof(StorageType) >= sizeof(int)), StorageType,
|
|
typename Select<RawType::IsSigned, int, unsigned>::Result >::Result TempType;
|
|
s << TempType(value);
|
|
}
|
|
};
|
|
|
|
}
|
|
|
|
#endif // UAVCAN_MARSHAL_INTEGER_SPEC_HPP_INCLUDED
|