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

             Branch data     Line data    Source code
       1                 :             : #include "mem_internal.h"
       2                 :             : #include <string.h>
       3                 :             : 
       4                 :             : /**
       5                 :             :  * @brief Count visible elements in a raw zero-terminated string
       6                 :             :  *
       7                 :             :  * This internal helper measures a raw source string without requiring a
       8                 :             :  * `memory` descriptor. It supports two scan modes. In bounded mode, it inspects
       9                 :             :  * at most @p source_limit_bytes bytes and reports either the first zero-valued
      10                 :             :  * element position or the number of whole elements that fit into that byte
      11                 :             :  * range. In unbounded mode, it scans until the first zero-valued element
      12                 :             :  *
      13                 :             :  * A zero-valued element means that every byte in that element is zero. For
      14                 :             :  * byte-sized elements the helper delegates to libc `memchr` in bounded mode and
      15                 :             :  * `strlen` in unbounded mode. Wider elements are scanned element by element so
      16                 :             :  * a zero byte inside a wider element does not accidentally terminate the string
      17                 :             :  *
      18                 :             :  * @warning Unbounded mode has the same safety contract as `strlen`. The caller
      19                 :             :  * must guarantee that @p source_string is non-NULL and truly terminated by a
      20                 :             :  * zero-valued element of width @p single_element_size
      21                 :             :  *
      22                 :             :  * @param source_string Raw source bytes to inspect
      23                 :             :  * @param source_limit_bytes Maximum byte range to inspect in bounded mode
      24                 :             :  * @param single_element_size Size of one logical string element in bytes
      25                 :             :  * @param source_limit_is_active Whether @p source_limit_bytes limits the scan
      26                 :             :  * @param length_out Output pointer receiving the visible element count
      27                 :             :  * @param terminator_found_out Optional output pointer receiving whether a
      28                 :             :  *        zero-valued terminator was found
      29                 :             :  * @return `SUCCESS` on success; `FAILURE` otherwise
      30                 :             :  */
      31                 :       27184 : Return mem_string_measure_length(
      32                 :             :         const void *const source_string,
      33                 :             :         const size_t      source_limit_bytes,
      34                 :             :         const size_t      single_element_size,
      35                 :             :         const bool        source_limit_is_active,
      36                 :             :         size_t *const     length_out,
      37                 :             :         bool *const       terminator_found_out)
      38                 :             : {
      39                 :             :         /* Status returned by this function through provide()
      40                 :             :            Default value assumes successful completion */
      41                 :       27184 :         Return status = SUCCESS;
      42                 :             : 
      43                 :             :         /* Visible source prefix length measured in elements */
      44                 :       27184 :         size_t measured_length = 0;
      45                 :             : 
      46                 :             :         /* Becomes true once a zero-valued terminator element is found */
      47                 :       27184 :         bool terminator_found = false;
      48                 :             : 
      49   [ +  -  -  + ]:       27184 :         if(source_string == NULL || length_out == NULL)
      50                 :             :         {
      51                 :           0 :                 report("Memory management; Invalid arguments for raw string length counter");
      52                 :           0 :                 status = FAILURE;
      53                 :             :         }
      54                 :             : 
      55   [ +  -  -  + ]:       27184 :         if((TRIUMPH & status) && single_element_size == 0)
      56                 :             :         {
      57                 :           0 :                 report("Memory management; Raw string element size is zero");
      58                 :           0 :                 status = FAILURE;
      59                 :             :         }
      60                 :             : 
      61   [ +  -  +  + ]:       27184 :         if((TRIUMPH & status) && single_element_size == sizeof(char))
      62                 :             :         {
      63                 :       27169 :                 const unsigned char *const source_data_view = (const unsigned char *)source_string;
      64                 :             : 
      65         [ +  + ]:       27169 :                 if(source_limit_is_active == true)
      66                 :             :                 {
      67                 :             :                         /* Address of the first zero byte found by the byte-sized fast path */
      68                 :       13187 :                         const void *found_terminator = memchr(source_data_view,0,source_limit_bytes);
      69                 :             : 
      70         [ +  + ]:       13187 :                         if(found_terminator == NULL)
      71                 :             :                         {
      72                 :           7 :                                 measured_length = source_limit_bytes;
      73                 :             :                         } else {
      74                 :       13180 :                                 measured_length = (size_t)((const unsigned char *)found_terminator - source_data_view);
      75                 :       13180 :                                 terminator_found = true;
      76                 :             :                         }
      77                 :             :                 } else {
      78                 :       13982 :                         measured_length = strlen((const char *)source_string);
      79                 :       13982 :                         terminator_found = true;
      80                 :             :                 }
      81                 :             :         }
      82                 :             : 
      83   [ +  -  +  + ]:       27184 :         if((TRIUMPH & status) && single_element_size != sizeof(char))
      84                 :             :         {
      85                 :          15 :                 const unsigned char *source_data_view = (const unsigned char *)source_string;
      86                 :             : 
      87         [ +  + ]:          15 :                 if(source_limit_is_active == true)
      88                 :             :                 {
      89                 :             :                         /* Byte offset of the current logical element being inspected */
      90                 :          14 :                         size_t element_offset = 0;
      91                 :             : 
      92         [ +  + ]:          42 :                         while(element_offset + single_element_size <= source_limit_bytes)
      93                 :             :                         {
      94         [ +  + ]:          40 :                                 if(mem_is_zero_element(source_data_view + element_offset,single_element_size) == true)
      95                 :             :                                 {
      96                 :          12 :                                         terminator_found = true;
      97                 :          12 :                                         break;
      98                 :             :                                 }
      99                 :             : 
     100                 :          28 :                                 ++measured_length;
     101                 :          28 :                                 element_offset += single_element_size;
     102                 :             :                         }
     103                 :             :                 } else {
     104         [ +  + ]:           3 :                         while(mem_is_zero_element(source_data_view,single_element_size) == false)
     105                 :             :                         {
     106                 :           2 :                                 source_data_view += single_element_size;
     107                 :           2 :                                 ++measured_length;
     108                 :             :                         }
     109                 :             : 
     110                 :           1 :                         terminator_found = true;
     111                 :             :                 }
     112                 :             :         }
     113                 :             : 
     114         [ +  - ]:       27184 :         if(TRIUMPH & status)
     115                 :             :         {
     116                 :       27184 :                 *length_out = measured_length;
     117                 :             : 
     118         [ -  + ]:       27184 :                 if(terminator_found_out != NULL)
     119                 :             :                 {
     120                 :           0 :                         *terminator_found_out = terminator_found;
     121                 :             :                 }
     122                 :             :         }
     123                 :             : 
     124                 :       27184 :         provide(status);
     125                 :             : }
        

Generated by: LCOV version 2.0-1