LCOV - code coverage report
Current view: top level - libs/mem/src - mem_convert_data_to_string.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 90.0 % 50 45
Test Date: 2026-07-12 01:01:34 Functions: 100.0 % 1 1
Branches: 86.4 % 44 38

             Branch data     Line data    Source code
       1                 :             : #include "mem.h"
       2                 :             : #include "mem_internal.h"
       3                 :             : #include <string.h>
       4                 :             : 
       5                 :             : /**
       6                 :             :  * @brief Convert a data descriptor into string mode and cache the visible length
       7                 :             :  *
       8                 :             :  * Use this helper when a descriptor currently holds raw data, but from now on
       9                 :             :  * should behave like a string. The function scans the current logical range
      10                 :             :  * until it finds the first zero-valued element and treats that position as the
      11                 :             :  * end of the visible string. A zero-valued element means that every byte in
      12                 :             :  * that element is zero
      13                 :             :  *
      14                 :             :  * If the descriptor is not empty and there is not enough logical room for one
      15                 :             :  * trailing terminator, the helper grows it and writes that terminator for you.
      16                 :             :  * Empty descriptors are promoted to string mode without allocating storage.
      17                 :             :  * Descriptors that are already in string mode are accepted as a no-op only
      18                 :             :  * when their cached string metadata is internally consistent
      19                 :             :  *
      20                 :             :  * The helper rejects inconsistent descriptors instead of guessing what the user
      21                 :             :  * meant. Examples include `length > 0` with `data == NULL`, `single_element_size == 0`,
      22                 :             :  * or stale `string_length` while the descriptor is still in data mode
      23                 :             :  *
      24                 :             :  * Small example:
      25                 :             :  * @code
      26                 :             :  * m_create(char,buffer);
      27                 :             :  * if((TRIUMPH & mem_copy_buffer(buffer,sizeof("abc"),"abc")) == 0) { return FAILURE; }
      28                 :             :  * if((TRIUMPH & mem_convert_data_to_string(buffer)) == 0) { return FAILURE; }
      29                 :             :  * // buffer->length == 4, buffer->string_length == 3, buffer->is_string == true
      30                 :             :  * @endcode
      31                 :             :  *
      32                 :             :  * @param memory_structure Mutable descriptor that should start behaving like a string
      33                 :             :  * @return `SUCCESS` on success; `FAILURE` if the descriptor is inconsistent or cannot be resized
      34                 :             :  */
      35                 :         248 : Return mem_convert_data_to_string(memory *memory_structure)
      36                 :             : {
      37                 :             :         /* This function was reviewed line by line by a human and is not AI-generated
      38                 :             :            Any change to this function requires separate explicit approval */
      39                 :             : 
      40                 :             :         /* Status returned by this function through provide()
      41                 :             :            Default value assumes successful completion */
      42                 :         248 :         Return status = SUCCESS;
      43                 :             : 
      44                 :             :         /* Visible prefix length used to update string_length and place the terminator */
      45                 :         248 :         size_t measured_length = 0;
      46                 :             : 
      47         [ -  + ]:         248 :         if(memory_structure == NULL)
      48                 :             :         {
      49                 :           0 :                 report("Memory management; Invalid arguments for string conversion");
      50                 :           0 :                 provide(FAILURE);
      51                 :             :         }
      52                 :             : 
      53   [ +  +  +  + ]:         248 :         if(memory_structure->length > 0 && memory_structure->data == NULL)
      54                 :             :         {
      55                 :           1 :                 report("Memory management; Descriptor has non-zero length with NULL data pointer");
      56                 :           1 :                 provide(FAILURE);
      57                 :             :         }
      58                 :             : 
      59         [ +  + ]:         247 :         if(memory_structure->is_string == false &&
      60         [ +  + ]:          39 :                 memory_structure->string_length != 0)
      61                 :             :         {
      62                 :           1 :                 report("Memory management; Data descriptor has non-zero string_length during string conversion");
      63                 :           1 :                 provide(FAILURE);
      64                 :             :         }
      65                 :             : 
      66         [ +  + ]:         246 :         if(memory_structure->single_element_size == 0)
      67                 :             :         {
      68                 :           1 :                 report("Memory management; Descriptor element size is zero during string conversion");
      69                 :           1 :                 provide(FAILURE);
      70                 :             :         }
      71                 :             : 
      72         [ +  + ]:         245 :         if(memory_structure->is_string == true &&
      73         [ +  + ]:         207 :                 memory_structure->length == 0 &&
      74         [ +  + ]:           2 :                 memory_structure->string_length != 0)
      75                 :             :         {
      76                 :           1 :                 report("Memory management; String descriptor has non-zero string_length with zero length during string conversion");
      77                 :           1 :                 provide(FAILURE);
      78                 :             :         }
      79                 :             : 
      80         [ +  + ]:         244 :         if(memory_structure->is_string == true &&
      81         [ +  + ]:         206 :                 memory_structure->length > 0 &&
      82         [ +  + ]:         205 :                 memory_structure->string_length >= memory_structure->length)
      83                 :             :         {
      84                 :           1 :                 report("Memory management; String descriptor cache is inconsistent during string conversion");
      85                 :           1 :                 provide(FAILURE);
      86                 :             :         }
      87                 :             : 
      88         [ +  + ]:         243 :         if(memory_structure->is_string == true)
      89                 :             :         {
      90                 :         205 :                 provide(status);
      91                 :             :         }
      92                 :             : 
      93         [ +  + ]:          38 :         if(memory_structure->length == 0)
      94                 :             :         {
      95                 :          22 :                 memory_structure->string_length = 0;
      96                 :          22 :                 memory_structure->is_string = true;
      97                 :             :         }
      98                 :             : 
      99         [ +  + ]:          38 :         if(memory_structure->length > 0)
     100                 :             :         {
     101                 :             :                 /* Reserve room for exactly one trailing string terminator.
     102                 :             :                    This block first measures how much payload is currently visible before the first zero-valued element.
     103                 :             :                    It then computes payload plus one terminator slot and grows the descriptor only when the current logical length is too small */
     104                 :          16 :                 size_t required_elements = 0;
     105                 :             : 
     106                 :          16 :                 run(mem_find_zero_terminator(memory_structure,&measured_length));
     107                 :          16 :                 run(mem_guarded_add(measured_length,1,&required_elements));
     108                 :             : 
     109         [ -  + ]:          16 :                 if(CRITICAL & status)
     110                 :             :                 {
     111                 :           0 :                         report("Memory management; Not enough room for string terminator");
     112                 :             :                 }
     113                 :             : 
     114                 :             :                 /* Grow only when the current logical length cannot hold both the visible payload and one final zero-valued terminator.
     115                 :             :                    If enough logical space already exists, conversion keeps the current descriptor size and reuses it as is */
     116   [ +  -  +  + ]:          16 :                 if((TRIUMPH & status) && memory_structure->length < required_elements)
     117                 :             :                 {
     118                 :           5 :                         run(m_resize(memory_structure,required_elements));
     119                 :             :                 }
     120                 :             :         }
     121                 :             : 
     122   [ +  -  +  + ]:          38 :         if((TRIUMPH & status) && memory_structure->length > 0)
     123                 :             :         {
     124                 :             :                 /* Materialize a well-formed string view in the current buffer.
     125                 :             :                    This block writes the final zero-valued terminator at the measured boundary,
     126                 :             :                    then stores the visible payload length in string_length and marks the descriptor as a string */
     127                 :          16 :                 unsigned char *memory_structure_data_rewritable = (unsigned char *)memory_structure->data;
     128                 :             : 
     129         [ -  + ]:          16 :                 if(memory_structure_data_rewritable == NULL)
     130                 :             :                 {
     131                 :           0 :                         report("Memory management; Data pointer is NULL while converting data to string");
     132                 :           0 :                         status = FAILURE;
     133                 :             :                 } else {
     134                 :             :                         /* Finalize the descriptor as a usable string.
     135                 :             :                            This writes the terminating zero element at the measured boundary,
     136                 :             :                            caches how many payload elements stay visible before that terminator,
     137                 :             :                            and switches the descriptor into string mode for future string-aware helpers */
     138                 :          16 :                         run(mem_write_zero_terminator(memory_structure,measured_length));
     139                 :          16 :                         memory_structure->string_length = measured_length;
     140                 :          16 :                         memory_structure->is_string = true;
     141                 :             :                 }
     142                 :             :         }
     143                 :             : 
     144         [ +  - ]:          38 :         if(TRIUMPH & status)
     145                 :             :         {
     146                 :          38 :                 telemetry_data_to_string_conversions();
     147                 :             :         }
     148                 :             : 
     149                 :          38 :         provide(status);
     150                 :             : }
        

Generated by: LCOV version 2.0-1