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

             Branch data     Line data    Source code
       1                 :             : #include "mem.h"
       2                 :             : #include "mem_internal.h"
       3                 :             : 
       4                 :             : /**
       5                 :             :  * @brief Finalize a direct string-buffer write by caching the visible length
       6                 :             :  *
       7                 :             :  * Use this helper after low-level code has written string payload directly into
       8                 :             :  * a descriptor's existing writable buffer. The descriptor must already be in
       9                 :             :  * string mode. On return the descriptor is always zero-terminated at
      10                 :             :  * @p written_length; @p flags only selects how the terminator is produced.
      11                 :             :  * With @ref WRITE_TERMINATOR_ALWAYS the helper always writes the zero
      12                 :             :  * terminator unconditionally. With @ref WRITE_TERMINATOR_IF_MISSING the
      13                 :             :  * helper first inspects the element at @p written_length and writes a
      14                 :             :  * terminator only when one is not already present. Either way
      15                 :             :  * @ref memory::string_length is then updated to @p written_length
      16                 :             :  *
      17                 :             :  * Small example:
      18                 :             :  * @code
      19                 :             :  * m_create(char,title,MEMORY_STRING);
      20                 :             :  * const char draft[] = "draft";
      21                 :             :  *
      22                 :             :  * if((TRIUMPH & m_resize(title,sizeof(draft))) == 0) { return FAILURE; }
      23                 :             :  *
      24                 :             :  * char *title_view = m_data(char,title);
      25                 :             :  * if(title_view == NULL) { return FAILURE; }
      26                 :             :  *
      27                 :             :  * memcpy(title_view,draft,sizeof(draft));
      28                 :             :  *
      29                 :             :  * if((TRIUMPH & m_finalize_string(title,sizeof(draft) - 1U)) == 0) { return FAILURE; }
      30                 :             :  * @endcode
      31                 :             :  *
      32                 :             :  * @param destination String descriptor whose direct write should become visible
      33                 :             :  * @param written_length Visible string length measured in whole elements
      34                 :             :  * @param flags Whether the helper should write the zero terminator unconditionally or only when it is missing
      35                 :             :  * @return `SUCCESS` on success; `FAILURE` otherwise
      36                 :             :  */
      37                 :       25230 : Return mem_finalize_string(
      38                 :             :         memory                *destination,
      39                 :             :         size_t                written_length,
      40                 :             :         TERMINATOR_WRITE_MODE flags)
      41                 :             : {
      42                 :             :         /* Status returned by this function through provide()
      43                 :             :            Default value assumes successful completion */
      44                 :       25230 :         Return status = SUCCESS;
      45                 :             : 
      46                 :             :         /* Byte offset of the terminator slot within the data buffer
      47                 :             :            Computed by mem_guarded_byte_size as written_length * single_element_size */
      48                 :       25230 :         size_t terminator_offset = 0;
      49                 :             : 
      50                 :             :         /* Total bytes needed from the start of the buffer through the terminator
      51                 :             :            Computed as terminator_offset + single_element_size */
      52                 :       25230 :         size_t required_bytes = 0;
      53                 :             : 
      54         [ -  + ]:       25230 :         if(destination == NULL)
      55                 :             :         {
      56                 :           0 :                 report("Memory management; String write finalization destination must be non-NULL");
      57                 :           0 :                 status = FAILURE;
      58                 :             :         }
      59                 :             : 
      60   [ +  -  -  + ]:       25230 :         if((TRIUMPH & status) && destination->single_element_size == 0)
      61                 :             :         {
      62                 :           0 :                 report("Memory management; String write finalization destination element size is zero");
      63                 :           0 :                 status = FAILURE;
      64                 :             :         }
      65                 :             : 
      66   [ +  -  +  -  :       25230 :         if((TRIUMPH & status) && destination->length > 0 && destination->data == NULL)
                   -  + ]
      67                 :             :         {
      68                 :           0 :                 report("Memory management; Descriptor has non-zero length with NULL data pointer");
      69                 :           0 :                 status = FAILURE;
      70                 :             :         }
      71                 :             : 
      72         [ +  - ]:       25230 :         if((TRIUMPH & status) &&
      73         [ +  - ]:       25230 :                 destination->actually_allocated_bytes > 0 &&
      74         [ -  + ]:       25230 :                 destination->data == NULL)
      75                 :             :         {
      76                 :           0 :                 report("Memory management; Descriptor has reserved bytes with NULL data pointer during string write finalization");
      77                 :           0 :                 status = FAILURE;
      78                 :             :         }
      79                 :             : 
      80   [ +  -  +  + ]:       25230 :         if((TRIUMPH & status) && destination->is_string == false)
      81                 :             :         {
      82                 :           1 :                 report("Memory management; String write finalization requires a string descriptor");
      83                 :           1 :                 status = FAILURE;
      84                 :             :         }
      85                 :             : 
      86   [ +  +  +  + ]:       25230 :         if((TRIUMPH & status) &&
      87         [ -  + ]:        1701 :                 flags != WRITE_TERMINATOR_IF_MISSING &&
      88                 :             :                 flags != WRITE_TERMINATOR_ALWAYS)
      89                 :             :         {
      90                 :           0 :                 report("Memory management; Unknown string write finalization flag");
      91                 :           0 :                 status = FAILURE;
      92                 :             :         }
      93                 :             : 
      94         [ +  + ]:       25230 :         if(TRIUMPH & status)
      95                 :             :         {
      96         [ -  + ]:       25229 :                 if(destination->length == 0)
      97                 :             :                 {
      98                 :           0 :                         report("Memory management; String write finalization requires reserved space for the visible string and terminator");
      99                 :           0 :                         status = FAILURE;
     100         [ -  + ]:       25229 :                 } else if(written_length >= destination->length){
     101                 :           0 :                         report("Memory management; String write finalization visible length exceeds descriptor capacity");
     102                 :           0 :                         status = FAILURE;
     103                 :             :                 }
     104                 :             :         }
     105                 :             : 
     106         [ +  + ]:       25230 :         if(TRIUMPH & status)
     107                 :             :         {
     108                 :       25229 :                 run(mem_guarded_byte_size(destination,written_length,&terminator_offset));
     109                 :       25229 :                 run(mem_guarded_add(terminator_offset,destination->single_element_size,&required_bytes));
     110                 :             : 
     111   [ +  -  -  + ]:       25229 :                 if((TRIUMPH & status) && required_bytes > destination->actually_allocated_bytes)
     112                 :             :                 {
     113                 :           0 :                         report("Memory management; String write finalization exceeds reserved capacity");
     114                 :           0 :                         status = FAILURE;
     115                 :             :                 }
     116                 :             :         }
     117                 :             : 
     118         [ +  + ]:       25230 :         if(TRIUMPH & status)
     119                 :             :         {
     120         [ +  + ]:       25229 :                 if(flags == WRITE_TERMINATOR_ALWAYS)
     121                 :             :                 {
     122                 :        1701 :                         run(mem_write_zero_terminator(destination,written_length));
     123                 :             :                 } else {
     124                 :             :                         /* Read-only view of the raw buffer used to inspect
     125                 :             :                            whether a zero terminator already exists at the expected slot */
     126                 :       23528 :                         const unsigned char *destination_data_view = (const unsigned char *)destination->data;
     127                 :             : 
     128         [ +  + ]:       23528 :                         if(mem_is_zero_element(destination_data_view + terminator_offset,destination->single_element_size) == false)
     129                 :             :                         {
     130                 :           2 :                                 run(mem_write_zero_terminator(destination,written_length));
     131                 :             : 
     132         [ +  - ]:           2 :                                 if(TRIUMPH & status)
     133                 :             :                                 {
     134                 :           2 :                                         telemetry_finalize_string_terminator_written_when_missing();
     135                 :             :                                 }
     136                 :             :                         } else {
     137                 :       23526 :                                 telemetry_finalize_string_terminator_already_present();
     138                 :             :                         }
     139                 :             :                 }
     140                 :             :         }
     141                 :             : 
     142         [ +  + ]:       25230 :         if(TRIUMPH & status)
     143                 :             :         {
     144                 :       25229 :                 destination->string_length = written_length;
     145                 :             :         }
     146                 :             : 
     147                 :       25230 :         provide(status);
     148                 :             : }
        

Generated by: LCOV version 2.0-1