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

Generated by: LCOV version 2.0-1