LCOV - code coverage report
Current view: top level - libs/bsw/cpp2someip/include/someip - PrimitiveTypes.h (source / functions) Coverage Total Hit
Test: coverage.info Lines: 92.6 % 81 75
Test Date: 2026-11-13 15:04:32 Functions: 100.0 % 35 35

            Line data    Source code
       1              : /********************************************************************************
       2              :  * Copyright (c) 2026 Accenture
       3              :  *
       4              :  * This program and the accompanying materials are made available under the
       5              :  * terms of the Apache License Version 2.0 which is available at
       6              :  * https://www.apache.org/licenses/LICENSE-2.0
       7              :  *
       8              :  * SPDX-License-Identifier: Apache-2.0
       9              :  ********************************************************************************/
      10              : 
      11              : #pragma once
      12              : 
      13              : #include "someip/StringEncoding.h"
      14              : 
      15              : #include <etl/memory.h>
      16              : #include <etl/type_list.h>
      17              : #include <util/meta/Bitmask.h>
      18              : 
      19              : #include <cmath>
      20              : #include <cstdint>
      21              : // etl::numeric_limits hardcodes is_iec559 == false, so <limits> is kept here: the
      22              : // IEEE754 pack/unpack dispatch below relies on the real is_iec559 of the platform.
      23              : #include <limits>
      24              : 
      25              : namespace someip
      26              : {
      27              : /** List of SOME/IP base types */
      28              : using BaseTypes = ::etl::type_list<
      29              :     char,
      30              :     uint8_t,
      31              :     uint16_t,
      32              :     uint32_t,
      33              :     uint64_t,
      34              :     int8_t,
      35              :     int16_t,
      36              :     int32_t,
      37              :     int64_t,
      38              :     bool,
      39              :     float_t,
      40              :     double_t>;
      41              : 
      42              : } // namespace someip
      43              : 
      44              : namespace someip
      45              : {
      46              : namespace internal
      47              : {
      48              : /// \cond internal
      49              : enum
      50              : {
      51              :     IEC559_NOT_SUPPORTED = false,
      52              :     IEC559_SUPPORTED     = true
      53              : };
      54              : 
      55              : template<typename RT, typename T>
      56           90 : static RT conversion(T const value)
      57              : {
      58              :     static_assert(
      59              :         sizeof(T) == sizeof(RT),
      60              :         "floating point to/from integral conversion type not the same size");
      61              : 
      62              :     // in C it is possible to use unions to convert from one type to another (type-punning)
      63              :     // in C++ this behavior is compiler dependent and can therefore be undefined behavior
      64              :     // as a solution a byte-wise copy can be used to convert from one type into another type
      65           90 :     RT dest{};
      66           90 :     ::etl::mem_copy(
      67              :         reinterpret_cast<unsigned char const*>(&value),
      68              :         sizeof(value),
      69              :         reinterpret_cast<unsigned char*>(&dest));
      70           90 :     return dest;
      71              : }
      72              : 
      73              : template<typename T>
      74              : struct IEEE756Traits;
      75              : 
      76              : template<>
      77              : struct IEEE756Traits<float_t>
      78              : {
      79              :     enum
      80              :     {
      81              :         MAX_EXP = 256
      82              :     };
      83              : 
      84              :     static uint32_t const IEEE756_ZERO              = 0x00000000U;
      85              :     static uint32_t const IEEE756_NEGATIVE_ZERO     = 0x80000000U;
      86              :     static uint32_t const IEEE756_INFINITY          = 0x7F800000U;
      87              :     static uint32_t const IEEE756_NEGATIVE_INFINITY = 0xFF800000U;
      88              :     static uint32_t const IEEE756_NAN               = 0x7FFFFFFFU;
      89              : };
      90              : 
      91              : template<>
      92              : struct IEEE756Traits<double_t>
      93              : {
      94              :     enum
      95              :     {
      96              :         MAX_EXP = 2048
      97              :     };
      98              : 
      99              :     static uint64_t const IEEE756_ZERO              = 0x0000000000000000U;
     100              :     static uint64_t const IEEE756_NEGATIVE_ZERO     = 0x8000000000000000U;
     101              :     static uint64_t const IEEE756_INFINITY          = 0x7FF0000000000000U;
     102              :     static uint64_t const IEEE756_NEGATIVE_INFINITY = 0xFFF0000000000000U;
     103              :     static uint64_t const IEEE756_NAN               = 0x7FFFFFFFFFFFFFFFU;
     104              : };
     105              : 
     106              : template<bool IS_IEC599>
     107              : struct PackIEEE754Dispatcher;
     108              : 
     109              : template<>
     110              : struct PackIEEE754Dispatcher<IEC559_SUPPORTED>
     111              : {
     112              :     template<typename RT, typename T, uint32_t EXP_BITS>
     113           51 :     static RT packIEEE754(T const value)
     114              :     {
     115           51 :         return conversion<RT, T>(value);
     116              :     }
     117              : };
     118              : 
     119              : template<>
     120              : struct PackIEEE754Dispatcher<IEC559_NOT_SUPPORTED>
     121              : {
     122              :     template<typename RT, typename T, uint32_t EXP_BITS>
     123           16 :     static RT packIEEE754(T const value)
     124              :     {
     125           16 :         uint32_t const BITS          = (static_cast<uint32_t>(sizeof(T)) * 8U);
     126           16 :         uint32_t const FRACTION_BITS = BITS - EXP_BITS - 1U;
     127           16 :         if (value == static_cast<T>(0.0))
     128              :         {
     129            4 :             if (conversion<RT, T>(value) == static_cast<RT>(0.0))
     130              :             {
     131            2 :                 return IEEE756Traits<T>::IEEE756_ZERO;
     132              :             }
     133              : 
     134            2 :             return IEEE756Traits<T>::IEEE756_NEGATIVE_ZERO;
     135              :         }
     136           12 :         if (value == std::numeric_limits<T>::infinity())
     137              :         {
     138            2 :             return IEEE756Traits<T>::IEEE756_INFINITY;
     139              :         }
     140           10 :         if (value == -std::numeric_limits<T>::infinity())
     141              :         {
     142            2 :             return IEEE756Traits<T>::IEEE756_NEGATIVE_INFINITY;
     143              :         }
     144            8 :         if (value != value)
     145              :         {
     146            0 :             return IEEE756Traits<T>::IEEE756_NAN;
     147              :         }
     148              : 
     149            8 :         T valueNormalized = value;
     150            8 :         RT sign           = 0U;
     151            8 :         if (value < static_cast<T>(0))
     152              :         {
     153            4 :             sign            = 1U;
     154            4 :             valueNormalized = -valueNormalized;
     155              :         }
     156            8 :         int32_t shift = 0;
     157           20 :         while ((valueNormalized >= static_cast<T>(2.0)) && (shift < IEEE756Traits<T>::MAX_EXP))
     158              :         {
     159           12 :             valueNormalized /= static_cast<T>(2.0);
     160           12 :             ++shift;
     161              :         }
     162            8 :         int32_t rounds = 0;
     163            8 :         while ((valueNormalized < 1.0) && (rounds < IEEE756Traits<T>::MAX_EXP))
     164              :         {
     165            0 :             valueNormalized *= static_cast<T>(2.0);
     166            0 :             --shift;
     167            0 :             ++rounds;
     168              :         }
     169            8 :         valueNormalized = valueNormalized - static_cast<T>(1.0);
     170            8 :         RT const fraction
     171            8 :             = valueNormalized * ((static_cast<RT>(1) << FRACTION_BITS) + static_cast<T>(0.5));
     172            8 :         RT const exponent
     173            8 :             = shift + static_cast<int32_t>(((static_cast<uint32_t>(1U) << (EXP_BITS - 1U)) - 1U));
     174              : 
     175            8 :         return (sign << (BITS - 1U)) | (exponent << FRACTION_BITS) | fraction;
     176              :     }
     177              : };
     178              : 
     179              : template<bool IS_IEC599>
     180              : struct UnpackIEEE754Dispatcher;
     181              : 
     182              : template<>
     183              : struct UnpackIEEE754Dispatcher<IEC559_SUPPORTED>
     184              : {
     185              :     template<typename RT, typename T, uint32_t EXP_BITS>
     186           35 :     static RT unpackIEEE754(T const value)
     187              :     {
     188           35 :         return conversion<RT, T>(value);
     189              :     }
     190              : };
     191              : 
     192              : template<>
     193              : struct UnpackIEEE754Dispatcher<IEC559_NOT_SUPPORTED>
     194              : {
     195              :     template<typename RT, typename T, uint32_t EXP_BITS>
     196           18 :     static RT unpackIEEE754(T const value)
     197              :     {
     198           18 :         uint32_t const BITS          = static_cast<uint32_t>(sizeof(T) * 8U);
     199           18 :         uint32_t const FRACTION_BITS = BITS - EXP_BITS - 1U;
     200           18 :         if (value == IEEE756Traits<RT>::IEEE756_ZERO)
     201              :         {
     202            2 :             return static_cast<RT>(0.0);
     203              :         }
     204           16 :         if (value == IEEE756Traits<RT>::IEEE756_NEGATIVE_ZERO)
     205              :         {
     206            2 :             return -static_cast<RT>(0.0);
     207              :         }
     208           14 :         if (value == IEEE756Traits<RT>::IEEE756_INFINITY)
     209              :         {
     210            2 :             return std::numeric_limits<RT>::infinity();
     211              :         }
     212           12 :         if (value == IEEE756Traits<RT>::IEEE756_NEGATIVE_INFINITY)
     213              :         {
     214            2 :             return -std::numeric_limits<RT>::infinity();
     215              :         }
     216           10 :         T const sign = (value >> (BITS - 1U));
     217           10 :         T const exponent
     218              :             = (value & static_cast<T>(::util::meta::Bitmask<uint64_t, BITS - 1U>::value))
     219           10 :               >> FRACTION_BITS;
     220           10 :         T const fraction
     221              :             = (value & static_cast<T>(::util::meta::Bitmask<uint64_t, FRACTION_BITS>::value));
     222              : 
     223           10 :         if ((::util::meta::Bitmask<uint64_t, EXP_BITS>::value == exponent) && (fraction > 0U))
     224              :         {
     225            2 :             return std::numeric_limits<RT>::quiet_NaN();
     226              :         }
     227            8 :         RT valueNormalized = static_cast<RT>(fraction);
     228            8 :         int32_t shift      = static_cast<int32_t>(
     229            8 :             exponent - static_cast<T>(::util::meta::Bitmask<uint64_t, EXP_BITS - 1U>::value));
     230              : 
     231              :         valueNormalized
     232            8 :             /= static_cast<T>(static_cast<T>(1U) << FRACTION_BITS) + static_cast<RT>(0.5);
     233            8 :         valueNormalized += static_cast<RT>(1.0);
     234              : 
     235            8 :         while (shift < 0)
     236              :         {
     237            0 :             valueNormalized /= static_cast<RT>(2.0);
     238            0 :             ++shift;
     239              :         }
     240           20 :         while (shift > 0)
     241              :         {
     242           12 :             valueNormalized *= static_cast<RT>(2.0);
     243           12 :             --shift;
     244              :         }
     245            8 :         if (sign != 0U)
     246              :         {
     247            4 :             valueNormalized = -valueNormalized;
     248              :         }
     249            8 :         return valueNormalized;
     250              :     }
     251              : };
     252              : 
     253              : template<typename RT, typename T, uint32_t EXP_BITS>
     254           17 : RT packIEEE754(T const value)
     255              : {
     256              :     return PackIEEE754Dispatcher<
     257           17 :         std::numeric_limits<T>::is_iec559>::template packIEEE754<RT, T, EXP_BITS>(value);
     258              : }
     259              : 
     260              : template<typename RT, typename T, uint32_t EXP_BITS>
     261           17 : RT unpackIEEE754(T const value)
     262              : {
     263              :     return UnpackIEEE754Dispatcher<
     264           17 :         std::numeric_limits<RT>::is_iec559>::template unpackIEEE754<RT, T, EXP_BITS>(value);
     265              : }
     266              : 
     267              : template<typename T, bool IS_BASIC_TYPE>
     268              : struct GetSizeDispatcher;
     269              : 
     270              : template<typename T>
     271              : struct GetSizeDispatcher<T, true>
     272              : {
     273           90 :     static uint32_t getSize(T const& /* t */) { return static_cast<uint32_t>(sizeof(T)); }
     274              : };
     275              : 
     276              : template<typename T>
     277              : struct GetSizeDispatcher<T, false>
     278              : {
     279              :     static uint32_t getSize(T const& t) { return t.getSize(); }
     280              : };
     281              : 
     282              : template<typename T>
     283              : struct GetSizeHelper
     284              : {
     285           81 :     static uint32_t getSize(T const& t, uint32_t const /* lengthSize */)
     286              :     {
     287           81 :         return GetSizeDispatcher<T, ::etl::type_list_contains<BaseTypes, T>::value>::getSize(t);
     288              :     }
     289              : 
     290              :     static uint32_t
     291            9 :     getSize(T const& t, uint32_t const /* lengthSize */, Encoding const /* encoding */)
     292              :     {
     293            9 :         return GetSizeDispatcher<T, ::etl::type_list_contains<BaseTypes, T>::value>::getSize(t);
     294              :     }
     295              : };
     296              : 
     297              : /// \endcond
     298              : } // namespace internal
     299              : } // namespace someip
        

Generated by: LCOV version 2.0-1