libuav original
Dependents: UAVCAN UAVCAN_Subscriber
integer_spec.hpp
00001 /* 00002 * Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com> 00003 */ 00004 00005 #ifndef UAVCAN_MARSHAL_INTEGER_SPEC_HPP_INCLUDED 00006 #define UAVCAN_MARSHAL_INTEGER_SPEC_HPP_INCLUDED 00007 00008 #include <uavcan/std.hpp> 00009 #include <uavcan/data_type.hpp> 00010 #include <uavcan/util/templates.hpp> 00011 #include <uavcan/marshal/scalar_codec.hpp> 00012 #include <uavcan/marshal/type_util.hpp> 00013 00014 namespace uavcan 00015 { 00016 00017 enum Signedness { SignednessUnsigned, SignednessSigned }; 00018 00019 /** 00020 * This template will be used for signed and unsigned integers more than 1 bit long. 00021 * There are explicit specializations for booleans below. 00022 */ 00023 template <unsigned BitLen_, Signedness Signedness, CastMode CastMode> 00024 class UAVCAN_EXPORT IntegerSpec 00025 { 00026 struct ErrorNoSuchInteger; 00027 00028 public: 00029 enum { IsSigned = Signedness == SignednessSigned }; 00030 enum { BitLen = BitLen_ }; 00031 enum { MinBitLen = BitLen }; 00032 enum { MaxBitLen = BitLen }; 00033 enum { IsPrimitive = 1 }; 00034 00035 typedef typename Select<(BitLen <= 8), typename Select<IsSigned, int8_t, uint8_t>::Result, 00036 typename Select<(BitLen <= 16), typename Select<IsSigned, int16_t, uint16_t>::Result, 00037 typename Select<(BitLen <= 32), typename Select<IsSigned, int32_t, uint32_t>::Result, 00038 typename Select<(BitLen <= 64), typename Select<IsSigned, int64_t, uint64_t>::Result, 00039 ErrorNoSuchInteger>::Result>::Result>::Result>::Result StorageType; 00040 00041 typedef typename IntegerSpec<BitLen, SignednessUnsigned, CastMode>::StorageType UnsignedStorageType; 00042 00043 private: 00044 IntegerSpec(); 00045 00046 struct LimitsImplGeneric 00047 { 00048 static StorageType max() 00049 { 00050 StaticAssert<(sizeof(uintmax_t) >= 8)>::check(); 00051 if (IsSigned == 0) 00052 { 00053 return StorageType((uintmax_t(1) << static_cast<unsigned>(BitLen)) - 1U); 00054 } 00055 else 00056 { 00057 return StorageType((uintmax_t(1) << (static_cast<unsigned>(BitLen) - 1U)) - 1); 00058 } 00059 } 00060 static UnsignedStorageType mask() 00061 { 00062 StaticAssert<(sizeof(uintmax_t) >= 8U)>::check(); 00063 return UnsignedStorageType((uintmax_t(1) << static_cast<unsigned>(BitLen)) - 1U); 00064 } 00065 }; 00066 00067 struct LimitsImpl64 00068 { 00069 static StorageType max() 00070 { 00071 return StorageType((IsSigned == 0) ? 0xFFFFFFFFFFFFFFFFULL : 0x7FFFFFFFFFFFFFFFLL); 00072 } 00073 static UnsignedStorageType mask() { return 0xFFFFFFFFFFFFFFFFULL; } 00074 }; 00075 00076 typedef typename Select<(BitLen == 64), LimitsImpl64, LimitsImplGeneric>::Result Limits; 00077 00078 static void saturate(StorageType& value) 00079 { 00080 if (value > max()) 00081 { 00082 value = max(); 00083 } 00084 else if (value <= min()) // 'Less or Equal' allows to suppress compiler warning on unsigned types 00085 { 00086 value = min(); 00087 } 00088 else 00089 { 00090 ; // Valid range 00091 } 00092 } 00093 00094 static void truncate(StorageType& value) { value = value & StorageType(mask()); } 00095 00096 static void validate() 00097 { 00098 StaticAssert<(BitLen <= (sizeof(StorageType) * 8))>::check(); 00099 // coverity[result_independent_of_operands : FALSE] 00100 UAVCAN_ASSERT(max() <= NumericTraits<StorageType>::max()); 00101 // coverity[result_independent_of_operands : FALSE] 00102 UAVCAN_ASSERT(min() >= NumericTraits<StorageType>::min()); 00103 } 00104 00105 public: 00106 static StorageType max() { return Limits::max(); } 00107 static StorageType min() { return IsSigned ? StorageType(-max() - 1) : 0; } 00108 static UnsignedStorageType mask() { return Limits::mask(); } 00109 00110 static int encode(StorageType value, ScalarCodec& codec, TailArrayOptimizationMode) 00111 { 00112 validate(); 00113 // cppcheck-suppress duplicateExpression 00114 if (CastMode == CastModeSaturate) 00115 { 00116 saturate(value); 00117 } 00118 else 00119 { 00120 truncate(value); 00121 } 00122 return codec.encode<BitLen>(value); 00123 } 00124 00125 static int decode(StorageType& out_value, ScalarCodec& codec, TailArrayOptimizationMode) 00126 { 00127 validate(); 00128 return codec.decode<BitLen>(out_value); 00129 } 00130 00131 static void extendDataTypeSignature(DataTypeSignature&) { } 00132 }; 00133 00134 /** 00135 * Boolean specialization 00136 */ 00137 template <CastMode CastMode> 00138 class UAVCAN_EXPORT IntegerSpec<1, SignednessUnsigned, CastMode> 00139 { 00140 public: 00141 enum { IsSigned = 0 }; 00142 enum { BitLen = 1 }; 00143 enum { MinBitLen = 1 }; 00144 enum { MaxBitLen = 1 }; 00145 enum { IsPrimitive = 1 }; 00146 00147 typedef bool StorageType; 00148 typedef bool UnsignedStorageType; 00149 00150 private: 00151 IntegerSpec(); 00152 00153 public: 00154 static StorageType max() { return true; } 00155 static StorageType min() { return false; } 00156 static UnsignedStorageType mask() { return true; } 00157 00158 static int encode(StorageType value, ScalarCodec& codec, TailArrayOptimizationMode) 00159 { 00160 return codec.encode<BitLen>(value); 00161 } 00162 00163 static int decode(StorageType& out_value, ScalarCodec& codec, TailArrayOptimizationMode) 00164 { 00165 return codec.decode<BitLen>(out_value); 00166 } 00167 00168 static void extendDataTypeSignature(DataTypeSignature&) { } 00169 }; 00170 00171 template <CastMode CastMode> 00172 class IntegerSpec<1, SignednessSigned, CastMode>; // Invalid instantiation 00173 00174 template <Signedness Signedness, CastMode CastMode> 00175 class IntegerSpec<0, Signedness, CastMode>; // Invalid instantiation 00176 00177 00178 template <typename T> 00179 struct IsIntegerSpec 00180 { 00181 enum { Result = 0 }; 00182 }; 00183 00184 template <unsigned BitLen, Signedness Signedness, CastMode CastMode> 00185 struct IsIntegerSpec<IntegerSpec<BitLen, Signedness, CastMode> > 00186 { 00187 enum { Result = 1 }; 00188 }; 00189 00190 00191 template <unsigned BitLen, Signedness Signedness, CastMode CastMode> 00192 class UAVCAN_EXPORT YamlStreamer<IntegerSpec<BitLen, Signedness, CastMode> > 00193 { 00194 typedef IntegerSpec<BitLen, Signedness, CastMode> RawType; 00195 typedef typename RawType::StorageType StorageType; 00196 00197 public: 00198 template <typename Stream> // cppcheck-suppress passedByValue 00199 static void stream(Stream& s, const StorageType value, int) 00200 { 00201 // Get rid of character types - we want its integer representation, not ASCII code 00202 typedef typename Select<(sizeof(StorageType) >= sizeof(int)), StorageType, 00203 typename Select<RawType::IsSigned, int, unsigned>::Result >::Result TempType; 00204 s << TempType(value); 00205 } 00206 }; 00207 00208 } 00209 00210 #endif // UAVCAN_MARSHAL_INTEGER_SPEC_HPP_INCLUDED
Generated on Tue Jul 12 2022 17:17:32 by 1.7.2