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
scalar_codec.hpp
00001 /* 00002 * Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com> 00003 */ 00004 00005 #ifndef UAVCAN_MARSHAL_SCALAR_CODEC_HPP_INCLUDED 00006 #define UAVCAN_MARSHAL_SCALAR_CODEC_HPP_INCLUDED 00007 00008 #include <cassert> 00009 #include <uavcan/std.hpp> 00010 #include <uavcan/build_config.hpp> 00011 #include <uavcan/util/templates.hpp> 00012 #include <uavcan/marshal/bit_stream.hpp> 00013 00014 namespace uavcan 00015 { 00016 /** 00017 * This class implements fast encoding/decoding of primitive type scalars into/from bit arrays. 00018 * It uses the compile-time type information to eliminate run-time operations where possible. 00019 */ 00020 class UAVCAN_EXPORT ScalarCodec 00021 { 00022 BitStream& stream_; 00023 00024 static void swapByteOrder(uint8_t* bytes, unsigned len); 00025 00026 template <unsigned BitLen, unsigned Size> 00027 static typename EnableIf<(BitLen > 8)>::Type 00028 convertByteOrder(uint8_t (&bytes)[Size]) 00029 { 00030 #if defined(BYTE_ORDER) && defined(BIG_ENDIAN) 00031 static const bool big_endian = BYTE_ORDER == BIG_ENDIAN; 00032 #else 00033 union { long int l; char c[sizeof(long int)]; } u; 00034 u.l = 1; 00035 const bool big_endian = u.c[sizeof(long int) - 1] == 1; 00036 #endif 00037 /* 00038 * I didn't have any big endian machine nearby, so big endian support wasn't tested yet. 00039 * It is likely to be OK anyway, so feel free to remove this UAVCAN_ASSERT() as needed. 00040 */ 00041 UAVCAN_ASSERT(big_endian == false); 00042 if (big_endian) 00043 { 00044 swapByteOrder(bytes, Size); 00045 } 00046 } 00047 00048 template <unsigned BitLen, unsigned Size> 00049 static typename EnableIf<(BitLen <= 8)>::Type 00050 convertByteOrder(uint8_t (&)[Size]) { } 00051 00052 template <unsigned BitLen, typename T> 00053 static typename EnableIf<static_cast<bool>(NumericTraits<T>::IsSigned) && ((sizeof(T) * 8) > BitLen)>::Type 00054 fixTwosComplement(T& value) 00055 { 00056 StaticAssert<NumericTraits<T>::IsInteger>::check(); // Not applicable to floating point types 00057 if (value & (T(1) << (BitLen - 1))) // The most significant bit is set --> negative 00058 { 00059 value |= T(T(0xFFFFFFFFFFFFFFFFULL) & ~((T(1) << BitLen) - 1)); 00060 } 00061 } 00062 00063 template <unsigned BitLen, typename T> 00064 static typename EnableIf<!static_cast<bool>(NumericTraits<T>::IsSigned) || ((sizeof(T) * 8) == BitLen)>::Type 00065 fixTwosComplement(T&) { } 00066 00067 template <unsigned BitLen, typename T> 00068 static typename EnableIf<((sizeof(T) * 8) > BitLen)>::Type 00069 clearExtraBits(T& value) 00070 { 00071 value &= (T(1) << BitLen) - 1; // Signedness doesn't matter 00072 } 00073 00074 template <unsigned BitLen, typename T> 00075 static typename EnableIf<((sizeof(T) * 8) == BitLen)>::Type 00076 clearExtraBits(T&) { } 00077 00078 template <unsigned BitLen, typename T> 00079 void validate() 00080 { 00081 StaticAssert<((sizeof(T) * 8) >= BitLen)>::check(); 00082 StaticAssert<(BitLen <= BitStream::MaxBitsPerRW)>::check(); 00083 StaticAssert<static_cast<bool>(NumericTraits<T>::IsSigned) ? (BitLen > 1) : true>::check(); 00084 } 00085 00086 int encodeBytesImpl(uint8_t* bytes, unsigned bitlen); 00087 int decodeBytesImpl(uint8_t* bytes, unsigned bitlen); 00088 00089 public: 00090 explicit ScalarCodec(BitStream& stream) 00091 : stream_(stream) 00092 { } 00093 00094 template <unsigned BitLen, typename T> 00095 int encode(const T value); 00096 00097 template <unsigned BitLen, typename T> 00098 int decode(T& value); 00099 }; 00100 00101 // ---------------------------------------------------------------------------- 00102 00103 template <unsigned BitLen, typename T> 00104 int ScalarCodec::encode(const T value) 00105 { 00106 validate<BitLen, T>(); 00107 union ByteUnion 00108 { 00109 T value; 00110 uint8_t bytes[sizeof(T)]; 00111 } byte_union; 00112 byte_union.value = value; 00113 clearExtraBits<BitLen, T>(byte_union.value); 00114 convertByteOrder<BitLen>(byte_union.bytes); 00115 return encodeBytesImpl(byte_union.bytes, BitLen); 00116 } 00117 00118 template <unsigned BitLen, typename T> 00119 int ScalarCodec::decode(T& value) 00120 { 00121 validate<BitLen, T>(); 00122 union ByteUnion 00123 { 00124 T value; 00125 uint8_t bytes[sizeof(T)]; 00126 } byte_union; 00127 byte_union.value = T(); 00128 const int read_res = decodeBytesImpl(byte_union.bytes, BitLen); 00129 if (read_res > 0) 00130 { 00131 convertByteOrder<BitLen>(byte_union.bytes); 00132 fixTwosComplement<BitLen, T>(byte_union.value); 00133 value = byte_union.value; 00134 } 00135 return read_res; 00136 } 00137 00138 } 00139 00140 #endif // UAVCAN_MARSHAL_SCALAR_CODEC_HPP_INCLUDED
Generated on Tue Jul 12 2022 17:17:33 by
