LCOV - code coverage report
Current view: top level - externals/zcbor/src - zcbor_common.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 68 170 40.0 %
Date: 2024-09-16 20:15:30 Functions: 9 17 52.9 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 27 120 22.5 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright (c) 2020 Nordic Semiconductor ASA
       3                 :            :  *
       4                 :            :  * SPDX-License-Identifier: Apache-2.0
       5                 :            :  */
       6                 :            : 
       7                 :            : #include <stddef.h>
       8                 :            : #include <stdbool.h>
       9                 :            : #include <stdint.h>
      10                 :            : #include <string.h>
      11                 :            : #include "zcbor_common.h"
      12                 :            : #include "zcbor_print.h"
      13                 :            : 
      14                 :            : _Static_assert((sizeof(size_t) == sizeof(void *)),
      15                 :            :         "This code needs size_t to be the same length as pointers.");
      16                 :            : 
      17                 :            : _Static_assert((sizeof(zcbor_state_t) >= sizeof(struct zcbor_state_constant)),
      18                 :            :         "This code needs zcbor_state_t to be at least as large as zcbor_backups_t.");
      19                 :            : 
      20                 :        206 : bool zcbor_new_backup(zcbor_state_t *state, size_t new_elem_count)
      21                 :            : {
      22                 :        206 :         ZCBOR_CHECK_ERROR();
      23                 :            : 
      24                 :        206 :         if ((state->constant_state->current_backup)
      25         [ -  + ]:        206 :                 >= state->constant_state->num_backups) {
      26                 :          0 :                 ZCBOR_ERR(ZCBOR_ERR_NO_BACKUP_MEM);
      27                 :            :         }
      28                 :            : 
      29                 :        206 :         state->payload_moved = false;
      30                 :            : 
      31                 :        206 :         (state->constant_state->current_backup)++;
      32                 :            : 
      33                 :            :         /* use the backup at current_backup - 1, since otherwise, the 0th
      34                 :            :          * backup would be unused. */
      35                 :        206 :         size_t i = (state->constant_state->current_backup) - 1;
      36                 :            : 
      37                 :        206 :         memcpy(&state->constant_state->backup_list[i], state,
      38                 :            :                 sizeof(zcbor_state_t));
      39                 :            : 
      40                 :        206 :         state->elem_count = new_elem_count;
      41                 :            : 
      42                 :        206 :         zcbor_log("New backup (level %zu)\n", i);
      43                 :            : 
      44                 :        206 :         return true;
      45                 :            : }
      46                 :            : 
      47                 :            : 
      48                 :        209 : bool zcbor_process_backup(zcbor_state_t *state, uint32_t flags,
      49                 :            :                 size_t max_elem_count)
      50                 :            : {
      51                 :        209 :         ZCBOR_CHECK_ERROR();
      52                 :        209 :         zcbor_state_t local_copy = *state;
      53                 :            : 
      54         [ -  + ]:        209 :         if (state->constant_state->current_backup == 0) {
      55                 :          0 :                 zcbor_log("No backups available.\r\n");
      56                 :          0 :                 ZCBOR_ERR(ZCBOR_ERR_NO_BACKUP_ACTIVE);
      57                 :            :         }
      58                 :            : 
      59                 :            :         /* use the backup at current_backup - 1, since otherwise, the
      60                 :            :                 * 0th backup would be unused. */
      61                 :        209 :         size_t i = state->constant_state->current_backup - 1;
      62                 :            : 
      63                 :        209 :         zcbor_log("Process backup (level %zu, flags 0x%x)\n", i, flags);
      64                 :            : 
      65         [ +  + ]:        209 :         if (flags & ZCBOR_FLAG_RESTORE) {
      66         [ +  + ]:        182 :                 if (!(flags & ZCBOR_FLAG_KEEP_PAYLOAD)) {
      67         [ -  + ]:        152 :                         if (state->constant_state->backup_list[i].payload_moved) {
      68                 :          0 :                                 zcbor_log("Payload pointer out of date.\r\n");
      69                 :          0 :                                 ZCBOR_ERR(ZCBOR_ERR_PAYLOAD_OUTDATED);
      70                 :            :                         }
      71                 :            :                 }
      72                 :        182 :                 memcpy(state, &state->constant_state->backup_list[i],
      73                 :            :                         sizeof(zcbor_state_t));
      74                 :            :         }
      75                 :            : 
      76         [ +  + ]:        209 :         if (flags & ZCBOR_FLAG_CONSUME) {
      77                 :        206 :                 state->constant_state->current_backup--;
      78                 :            :         }
      79                 :            : 
      80         [ -  + ]:        209 :         if (local_copy.elem_count > max_elem_count) {
      81                 :            :                 zcbor_log("elem_count: %zu (expected max %zu)\r\n",
      82                 :          0 :                         local_copy.elem_count, max_elem_count);
      83                 :          0 :                 ZCBOR_ERR(ZCBOR_ERR_HIGH_ELEM_COUNT);
      84                 :            :         }
      85                 :            : 
      86         [ +  + ]:        209 :         if (flags & ZCBOR_FLAG_KEEP_PAYLOAD) {
      87                 :         30 :                 state->payload = local_copy.payload;
      88                 :            :         }
      89                 :            : 
      90         [ -  + ]:        209 :         if (flags & ZCBOR_FLAG_KEEP_DECODE_STATE) {
      91                 :            :                 /* Copy decode state */
      92                 :          0 :                 state->decode_state = local_copy.decode_state;
      93                 :            :         }
      94                 :            : 
      95                 :            :         return true;
      96                 :            : }
      97                 :            : 
      98                 :          0 : static void update_backups(zcbor_state_t *state, uint8_t const *new_payload_end)
      99                 :            : {
     100         [ #  # ]:          0 :         if (state->constant_state) {
     101         [ #  # ]:          0 :                 for (unsigned int i = 0; i < state->constant_state->current_backup; i++) {
     102                 :          0 :                         state->constant_state->backup_list[i].payload_end = new_payload_end;
     103                 :          0 :                         state->constant_state->backup_list[i].payload_moved = true;
     104                 :            :                 }
     105                 :            :         }
     106                 :          0 : }
     107                 :            : 
     108                 :            : 
     109                 :         27 : bool zcbor_union_start_code(zcbor_state_t *state)
     110                 :            : {
     111         [ -  + ]:         27 :         if (!zcbor_new_backup(state, state->elem_count)) {
     112                 :          0 :                 ZCBOR_FAIL();
     113                 :            :         }
     114                 :            :         return true;
     115                 :            : }
     116                 :            : 
     117                 :            : 
     118                 :          3 : bool zcbor_union_elem_code(zcbor_state_t *state)
     119                 :            : {
     120         [ -  + ]:          3 :         if (!zcbor_process_backup(state, ZCBOR_FLAG_RESTORE, state->elem_count)) {
     121                 :          0 :                 ZCBOR_FAIL();
     122                 :            :         }
     123                 :            :         return true;
     124                 :            : }
     125                 :            : 
     126                 :         27 : bool zcbor_union_end_code(zcbor_state_t *state)
     127                 :            : {
     128         [ -  + ]:         27 :         if (!zcbor_process_backup(state, ZCBOR_FLAG_CONSUME, state->elem_count)) {
     129                 :          0 :                 ZCBOR_FAIL();
     130                 :            :         }
     131                 :            :         return true;
     132                 :            : }
     133                 :            : 
     134                 :        267 : void zcbor_new_state(zcbor_state_t *state_array, size_t n_states,
     135                 :            :                 const uint8_t *payload, size_t payload_len, size_t elem_count,
     136                 :            :                 uint8_t *flags, size_t flags_bytes)
     137                 :            : {
     138                 :        267 :         state_array[0].payload = payload;
     139                 :        267 :         state_array[0].payload_end = payload + payload_len;
     140                 :        267 :         state_array[0].elem_count = elem_count;
     141                 :        267 :         state_array[0].payload_moved = false;
     142                 :        267 :         state_array[0].decode_state.indefinite_length_array = false;
     143                 :            : #ifdef ZCBOR_MAP_SMART_SEARCH
     144                 :            :         state_array[0].decode_state.map_search_elem_state = flags;
     145                 :            :         state_array[0].decode_state.map_elem_count = 0;
     146                 :            : #else
     147                 :        267 :         state_array[0].decode_state.map_elems_processed = 0;
     148                 :        267 :         (void)flags;
     149                 :        267 :         (void)flags_bytes;
     150                 :            : #endif
     151                 :        267 :         state_array[0].constant_state = NULL;
     152                 :            : 
     153         [ +  - ]:        267 :         if (n_states < 2) {
     154                 :            :                 return;
     155                 :            :         }
     156                 :            : 
     157                 :            :         /* Use the last state as a struct zcbor_state_constant object. */
     158                 :        267 :         state_array[0].constant_state = (struct zcbor_state_constant *)&state_array[n_states - 1];
     159                 :        267 :         state_array[0].constant_state->backup_list = NULL;
     160                 :        267 :         state_array[0].constant_state->num_backups = n_states - 2;
     161                 :        267 :         state_array[0].constant_state->current_backup = 0;
     162                 :        267 :         state_array[0].constant_state->error = ZCBOR_SUCCESS;
     163                 :            : #ifdef ZCBOR_STOP_ON_ERROR
     164                 :            :         state_array[0].constant_state->stop_on_error = false;
     165                 :            : #endif
     166                 :        267 :         state_array[0].constant_state->enforce_canonical = ZCBOR_ENFORCE_CANONICAL_DEFAULT;
     167                 :        267 :         state_array[0].constant_state->manually_process_elem = ZCBOR_MANUALLY_PROCESS_ELEM_DEFAULT;
     168                 :            : #ifdef ZCBOR_MAP_SMART_SEARCH
     169                 :            :         state_array[0].constant_state->map_search_elem_state_end = flags + flags_bytes;
     170                 :            : #endif
     171         [ +  + ]:        267 :         if (n_states > 2) {
     172                 :        141 :                 state_array[0].constant_state->backup_list = &state_array[1];
     173                 :            :         }
     174                 :            : }
     175                 :            : 
     176                 :          0 : void zcbor_update_state(zcbor_state_t *state,
     177                 :            :                 const uint8_t *payload, size_t payload_len)
     178                 :            : {
     179                 :          0 :         state->payload = payload;
     180                 :          0 :         state->payload_end = payload + payload_len;
     181                 :            : 
     182                 :          0 :         update_backups(state, state->payload_end);
     183                 :          0 : }
     184                 :            : 
     185                 :            : 
     186                 :          0 : bool zcbor_validate_string_fragments(struct zcbor_string_fragment *fragments,
     187                 :            :                 size_t num_fragments)
     188                 :            : {
     189                 :          0 :         size_t total_len = 0;
     190                 :            : 
     191         [ #  # ]:          0 :         if (fragments == NULL) {
     192                 :            :                 return false;
     193                 :            :         }
     194                 :            : 
     195         [ #  # ]:          0 :         for (size_t i = 0; i < num_fragments; i++) {
     196         [ #  # ]:          0 :                 if (fragments[i].offset != total_len) {
     197                 :            :                         return false;
     198                 :            :                 }
     199         [ #  # ]:          0 :                 if (fragments[i].fragment.value == NULL) {
     200                 :            :                         return false;
     201                 :            :                 }
     202         [ #  # ]:          0 :                 if (fragments[i].total_len != fragments[0].total_len) {
     203                 :            :                         return false;
     204                 :            :                 }
     205                 :          0 :                 total_len += fragments[i].fragment.len;
     206         [ #  # ]:          0 :                 if (total_len > fragments[0].total_len) {
     207                 :            :                         return false;
     208                 :            :                 }
     209                 :            :         }
     210                 :            : 
     211   [ #  #  #  # ]:          0 :         if (num_fragments && total_len != fragments[0].total_len) {
     212                 :            :                 return false;
     213                 :            :         }
     214                 :            : 
     215   [ #  #  #  # ]:          0 :         if (num_fragments && (fragments[0].total_len == ZCBOR_STRING_FRAGMENT_UNKNOWN_LENGTH)) {
     216         [ #  # ]:          0 :                 for (size_t i = 0; i < num_fragments; i++) {
     217                 :          0 :                         fragments[i].total_len = total_len;
     218                 :            :                 }
     219                 :            :         }
     220                 :            : 
     221                 :            :         return true;
     222                 :            : }
     223                 :            : 
     224                 :          0 : bool zcbor_splice_string_fragments(struct zcbor_string_fragment *fragments,
     225                 :            :                 size_t num_fragments, uint8_t *result, size_t *result_len)
     226                 :            : {
     227                 :          0 :         size_t total_len = 0;
     228                 :            : 
     229         [ #  # ]:          0 :         if (!fragments) {
     230                 :            :                 return false;
     231                 :            :         }
     232                 :            : 
     233         [ #  # ]:          0 :         for (size_t i = 0; i < num_fragments; i++) {
     234         [ #  # ]:          0 :                 if ((total_len > *result_len)
     235         [ #  # ]:          0 :                         || (fragments[i].fragment.len > (*result_len - total_len))) {
     236                 :            :                         return false;
     237                 :            :                 }
     238                 :          0 :                 memcpy(&result[total_len],
     239                 :          0 :                         fragments[i].fragment.value, fragments[i].fragment.len);
     240                 :          0 :                 total_len += fragments[i].fragment.len;
     241                 :            :         }
     242                 :            : 
     243                 :          0 :         *result_len = total_len;
     244                 :          0 :         return true;
     245                 :            : }
     246                 :            : 
     247                 :            : 
     248                 :          0 : bool zcbor_compare_strings(const struct zcbor_string *str1,
     249                 :            :                 const struct zcbor_string *str2)
     250                 :            : {
     251                 :          0 :         return (str1 != NULL) && (str2 != NULL)
     252   [ #  #  #  #  :          0 :                 && (str1->value != NULL) && (str2->value != NULL) && (str1->len == str2->len)
                   #  # ]
     253   [ #  #  #  # ]:          0 :                 && (memcmp(str1->value, str2->value, str1->len) == 0);
     254                 :            : }
     255                 :            : 
     256                 :            : 
     257                 :       1787 : size_t zcbor_header_len(uint64_t value)
     258                 :            : {
     259         [ +  + ]:       1787 :         if (value <= ZCBOR_VALUE_IN_HEADER) {
     260                 :            :                 return 1;
     261         [ +  + ]:        403 :         } else if (value <= 0xFF) {
     262                 :            :                 return 2;
     263         [ -  + ]:         78 :         } else if (value <= 0xFFFF) {
     264                 :            :                 return 3;
     265         [ #  # ]:          0 :         } else if (value <= 0xFFFFFFFF) {
     266                 :            :                 return 5;
     267                 :            :         } else {
     268                 :          0 :                 return 9;
     269                 :            :         }
     270                 :            : }
     271                 :            : 
     272                 :            : 
     273                 :       1787 : size_t zcbor_header_len_ptr(const void *const value, size_t value_len)
     274                 :            : {
     275                 :       1787 :         uint64_t val64 = 0;
     276                 :            : 
     277         [ +  - ]:       1787 :         if (value_len > sizeof(val64)) {
     278                 :            :                 return 0;
     279                 :            :         }
     280                 :            : 
     281                 :       1787 :         memcpy(((uint8_t*)&val64) + ZCBOR_ECPY_OFFS(sizeof(val64), value_len), value, value_len);
     282                 :       1787 :         return zcbor_header_len(val64);
     283                 :            : }
     284                 :            : 
     285                 :            : 
     286                 :        267 : int zcbor_entry_function(const uint8_t *payload, size_t payload_len,
     287                 :            :         void *result, size_t *payload_len_out, zcbor_state_t *state, zcbor_decoder_t func,
     288                 :            :         size_t n_states, size_t elem_count)
     289                 :            : {
     290                 :        267 :         zcbor_new_state(state, n_states, payload, payload_len, elem_count, NULL, 0);
     291                 :            : 
     292                 :        267 :         bool ret = func(state, result);
     293                 :            : 
     294         [ -  + ]:        267 :         if (!ret) {
     295                 :          0 :                 int err = zcbor_pop_error(state);
     296                 :            : 
     297         [ #  # ]:          0 :                 err = (err == ZCBOR_SUCCESS) ? ZCBOR_ERR_UNKNOWN : err;
     298                 :          0 :                 return err;
     299                 :            :         }
     300                 :            : 
     301         [ +  - ]:        267 :         if (payload_len_out != NULL) {
     302                 :        267 :                 *payload_len_out = MIN(payload_len,
     303                 :            :                                 (size_t)state[0].payload - (size_t)payload);
     304                 :            :         }
     305                 :            :         return ZCBOR_SUCCESS;
     306                 :            : }
     307                 :            : 
     308                 :            : 
     309                 :            : /* Float16: */
     310                 :            : #define F16_SIGN_OFFS 15 /* Bit offset of the sign bit. */
     311                 :            : #define F16_EXPO_OFFS 10 /* Bit offset of the exponent. */
     312                 :            : #define F16_EXPO_MSK 0x1F /* Bitmask for the exponent (right shifted by F16_EXPO_OFFS). */
     313                 :            : #define F16_MANTISSA_MSK 0x3FF /* Bitmask for the mantissa. */
     314                 :            : #define F16_MAX 65520 /* Lowest float32 value that rounds up to float16 infinity.
     315                 :            :                        * (65519.996 rounds to 65504) */
     316                 :            : #define F16_MIN_EXPO 24 /* Negative exponent of the non-zero float16 value closest to 0 (2^-24) */
     317                 :            : #define F16_MIN (1.0f / (1 << F16_MIN_EXPO)) /* The non-zero float16 value closest to 0 (2^-24) */
     318                 :            : #define F16_MIN_NORM (1.0f / (1 << 14)) /* The normalized float16 value closest to 0 (2^-14) */
     319                 :            : #define F16_BIAS 15 /* The exponent bias of normalized float16 values. */
     320                 :            : 
     321                 :            : /* Float32: */
     322                 :            : #define F32_SIGN_OFFS 31 /* Bit offset of the sign bit. */
     323                 :            : #define F32_EXPO_OFFS 23 /* Bit offset of the exponent. */
     324                 :            : #define F32_EXPO_MSK 0xFF /* Bitmask for the exponent (right shifted by F32_EXPO_OFFS). */
     325                 :            : #define F32_MANTISSA_MSK 0x7FFFFF /* Bitmask for the mantissa. */
     326                 :            : #define F32_BIAS 127 /* The exponent bias of normalized float32 values. */
     327                 :            : 
     328                 :            : /* Rounding: */
     329                 :            : #define SUBNORM_ROUND_MSK (F32_MANTISSA_MSK | (1 << F32_EXPO_OFFS)) /* mantissa + lsb of expo for
     330                 :            :                                                                      * tiebreak. */
     331                 :            : #define SUBNORM_ROUND_BIT_MSK (1 << (F32_EXPO_OFFS - 1)) /* msb of mantissa (0x400000) */
     332                 :            : #define NORM_ROUND_MSK (F32_MANTISSA_MSK >> (F16_EXPO_OFFS - 1)) /* excess mantissa when going from
     333                 :            :                                                                   * float32 to float16 + 1 extra bit
     334                 :            :                                                                   * for tiebreak. */
     335                 :            : #define NORM_ROUND_BIT_MSK (1 << (F32_EXPO_OFFS - F16_EXPO_OFFS - 1)) /* bit 12 (0x1000) */
     336                 :            : 
     337                 :            : 
     338                 :          0 : float zcbor_float16_to_32(uint16_t input)
     339                 :            : {
     340                 :          0 :         uint32_t sign = input >> F16_SIGN_OFFS;
     341                 :          0 :         uint32_t expo = (input >> F16_EXPO_OFFS) & F16_EXPO_MSK;
     342                 :          0 :         uint32_t mantissa = input & F16_MANTISSA_MSK;
     343                 :            : 
     344         [ #  # ]:          0 :         if ((expo == 0) && (mantissa != 0)) {
     345                 :            :                 /* Subnormal float16 - convert to normalized float32 */
     346         [ #  # ]:          0 :                 return ((float)mantissa * F16_MIN) * (sign ? -1 : 1);
     347                 :            :         } else {
     348                 :            :                 /* Normalized / zero / Infinity / NaN */
     349                 :          0 :                 uint32_t new_expo = (expo == 0 /* zero */) ? 0
     350         [ #  # ]:          0 :                         : (expo == F16_EXPO_MSK /* inf/NaN */) ? F32_EXPO_MSK
     351         [ #  # ]:          0 :                                 : (expo + (F32_BIAS - F16_BIAS));
     352                 :          0 :                 uint32_t value32 = (sign << F32_SIGN_OFFS) | (new_expo << F32_EXPO_OFFS)
     353                 :          0 :                         | (mantissa << (F32_EXPO_OFFS - F16_EXPO_OFFS));
     354                 :          0 :                 return *(float *)&value32;
     355                 :            :         }
     356                 :            : }
     357                 :            : 
     358                 :            : 
     359                 :          0 : uint16_t zcbor_float32_to_16(float input)
     360                 :            : {
     361                 :          0 :         uint32_t value32 = *(uint32_t *)&input;
     362                 :            : 
     363                 :          0 :         uint32_t sign = value32 >> F32_SIGN_OFFS;
     364                 :          0 :         uint32_t expo = (value32 >> F32_EXPO_OFFS) & F32_EXPO_MSK;
     365                 :          0 :         uint32_t mantissa = value32 & F32_MANTISSA_MSK;
     366                 :            : 
     367                 :          0 :         uint16_t value16 = (uint16_t)(sign << F16_SIGN_OFFS);
     368                 :            : 
     369                 :          0 :         float abs_input;
     370                 :          0 :         *(uint32_t *)&abs_input = value32 & ~(1 << F32_SIGN_OFFS);
     371                 :            : 
     372         [ #  # ]:          0 :         if (abs_input <= (F16_MIN / 2)) {
     373                 :            :                 /* 0 or too small for float16. Round down to 0. value16 is already correct. */
     374         [ #  # ]:          0 :         } else if (abs_input < F16_MIN) {
     375                 :            :                 /* Round up to 2^(-24) (F16_MIN), has other rounding rules than larger values. */
     376                 :          0 :                 value16 |= 0x0001;
     377         [ #  # ]:          0 :         } else if (abs_input < F16_MIN_NORM) {
     378                 :            :                 /* Subnormal float16 (normal float32) */
     379                 :          0 :                 uint32_t adjusted_mantissa =
     380                 :            :                         /* Adjust for the purposes of checking rounding. */
     381                 :            :                         /* The lsb of expo is needed for the cases where expo is 103 (minimum). */
     382                 :          0 :                         ((value32 << (expo - (F32_BIAS - F16_MIN_EXPO))) & SUBNORM_ROUND_MSK);
     383                 :          0 :                 uint16_t rounding_bit =
     384                 :            :                         /* "Round to nearest, ties to even". */
     385                 :            :                         /* 0x400000 means ties go down towards even. (0xC00000 means ties go up.) */
     386                 :          0 :                         (adjusted_mantissa & SUBNORM_ROUND_BIT_MSK)
     387   [ #  #  #  # ]:          0 :                                 && (adjusted_mantissa != SUBNORM_ROUND_BIT_MSK);
     388                 :          0 :                 value16 |= ((uint16_t)(abs_input * (1 << 24)) + rounding_bit); /* expo is 0 */
     389         [ #  # ]:          0 :         } else if (abs_input < F16_MAX) {
     390                 :            :                 /* Normal float16 (normal float32) */
     391                 :          0 :                 uint16_t rounding_bit =
     392                 :            :                         /* Bit 13 of the mantissa represents which way to round, except for the */
     393                 :            :                         /* special case where bits 0-12 and 14 are 0. */
     394                 :            :                         /* This is because of "Round to nearest, ties to even". */
     395                 :            :                         /* 0x1000 means ties go down towards even. (0x3000 means ties go up.) */
     396                 :          0 :                         ((mantissa & NORM_ROUND_BIT_MSK)
     397   [ #  #  #  # ]:          0 :                                 && ((mantissa & NORM_ROUND_MSK) != NORM_ROUND_BIT_MSK));
     398                 :          0 :                 value16 |= (uint16_t)((expo - (F32_BIAS - F16_BIAS)) << F16_EXPO_OFFS);
     399                 :          0 :                 value16 |= (uint16_t)(mantissa >> (F32_EXPO_OFFS - F16_EXPO_OFFS));
     400                 :          0 :                 value16 += rounding_bit; /* Might propagate to exponent. */
     401         [ #  # ]:          0 :         } else if (expo != F32_EXPO_MSK || !mantissa) {
     402                 :            :                 /* Infinite, or finite normal float32 too large for float16. Round up to inf. */
     403                 :          0 :                 value16 |= (F16_EXPO_MSK << F16_EXPO_OFFS);
     404                 :            :         } else {
     405                 :            :                 /* NaN */
     406                 :            :                 /* Preserve msbit of mantissa. */
     407                 :          0 :                 uint16_t new_mantissa = (uint16_t)(mantissa >> (F32_EXPO_OFFS - F16_EXPO_OFFS));
     408         [ #  # ]:          0 :                 value16 |= (F16_EXPO_MSK << F16_EXPO_OFFS) | (new_mantissa ? new_mantissa : 1);
     409                 :            :         }
     410                 :            : 
     411                 :          0 :         return value16;
     412                 :            : }
     413                 :            : 
     414                 :            : 
     415                 :            : /** Weak strnlen() implementation in case it is not available.
     416                 :            :  *
     417                 :            :  * This function is in the public domain, according to:
     418                 :            :  * https://github.com/arm-embedded/gcc-arm-none-eabi.debian/blob/master/src/libiberty/strnlen.c
     419                 :            :  */
     420                 :            : __attribute__((__weak__))
     421                 :          0 : size_t strnlen (const char *s, size_t maxlen)
     422                 :            : {
     423                 :          0 :         size_t i;
     424                 :            : 
     425         [ #  # ]:          0 :         for (i = 0; i < maxlen; ++i) {
     426         [ #  # ]:          0 :                 if (s[i] == '\0') {
     427                 :            :                         break;
     428                 :            :                 }
     429                 :            :         }
     430                 :          0 :         return i;
     431                 :            : }

Generated by: LCOV version 1.14