/* * Copyright (C) 2014 Pavel Kirienko */ #pragma once #include #include #include #include #include namespace uavcan { enum Signedness { SignednessUnsigned, SignednessSigned }; template class IntegerSpec { enum { IsSigned = Signedness == SignednessSigned }; struct ErrorNoSuchInteger; public: enum { BitLen = BitLen_ }; enum { MinBitLen = BitLen }; enum { MaxBitLen = BitLen }; typedef typename StaticIf<(BitLen <= 8), typename StaticIf::Result, typename StaticIf<(BitLen <= 16), typename StaticIf::Result, typename StaticIf<(BitLen <= 32), typename StaticIf::Result, typename StaticIf<(BitLen <= 64), typename StaticIf::Result, ErrorNoSuchInteger>::Result>::Result>::Result>::Result StorageType; private: typedef typename IntegerSpec::StorageType UnsignedStorageType; IntegerSpec(); struct ExactSizeLimits { static StorageType max() { return std::numeric_limits::max(); } static StorageType min() { return std::numeric_limits::min(); } static UnsignedStorageType mask() { return ~UnsignedStorageType(0); } }; struct NonExactSizeLimits { static StorageType max() { return IsSigned ? ((StorageType(1) << (BitLen - 1)) - 1) : ((StorageType(1) << BitLen) - 1); } static StorageType min() { return IsSigned ? -(StorageType(1) << (BitLen - 1)) : 0; } static UnsignedStorageType mask() { return (UnsignedStorageType(1) << BitLen) - 1; } }; enum { IsExactSize = (BitLen == 8) || (BitLen == 16) || (BitLen == 32) || (BitLen == 64) }; typedef typename StaticIf::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(); } static void truncate(StorageType& value) { // cppcheck-suppress duplicateExpression value &= Limits::mask(); } public: // cppcheck-suppress duplicateExpression static StorageType max() { return Limits::max(); } // cppcheck-suppress duplicateExpression static StorageType min() { return Limits::min(); } static int encode(StorageType value, ScalarCodec& codec, TailArrayOptimizationMode) { // cppcheck-suppress duplicateExpression if (CastMode == CastModeSaturate) saturate(value); else truncate(value); return codec.encode(value); } static int decode(StorageType& out_value, ScalarCodec& codec, TailArrayOptimizationMode) { return codec.decode(out_value); } }; template class IntegerSpec<1, SignednessSigned, CastMode>; // Invalid instantiation }