Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: UAVCAN UAVCAN_Subscriber
libuavcan/include/uavcan/marshal/integer_spec.hpp
- Committer:
- RuslanUrya
- Date:
- 2018-04-14
- Revision:
- 0:dfe6edabb8ec
File content as of revision 0:dfe6edabb8ec:
/* * 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 }; /** * This template will be used for signed and unsigned integers more than 1 bit long. * There are explicit specializations for booleans below. */ 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&) { } }; /** * Boolean specialization */ template <CastMode CastMode> class UAVCAN_EXPORT IntegerSpec<1, SignednessUnsigned, CastMode> { public: enum { IsSigned = 0 }; enum { BitLen = 1 }; enum { MinBitLen = 1 }; enum { MaxBitLen = 1 }; enum { IsPrimitive = 1 }; typedef bool StorageType; typedef bool UnsignedStorageType; private: IntegerSpec(); public: static StorageType max() { return true; } static StorageType min() { return false; } static UnsignedStorageType mask() { return true; } static int encode(StorageType value, ScalarCodec& codec, TailArrayOptimizationMode) { return codec.encode<BitLen>(value); } static int decode(StorageType& out_value, ScalarCodec& codec, TailArrayOptimizationMode) { 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