LCOV - code coverage report
Current view: top level - libs/testitall/src - trim_trailing_eol.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 78.1 % 32 25
Test Date: 2026-01-12 05:34:38 Functions: 100.0 % 1 1

            Line data    Source code
       1              : #include "testitall.h"
       2              : 
       3              : /**
       4              :  * @brief Remove a trailing EOL (\r, \n, or \r\n sequence) from a memory buffer.
       5              :  *
       6              :  * @param buffer Pointer to a memory descriptor containing text.
       7              :  *
       8              :  * @return SUCCESS if trimming succeeded or nothing to trim; FAILURE on invalid input.
       9              :  *
      10              :  * @details
      11              :  * - Works with buffers that already have a trailing '\0' or without it.
      12              :  * - Removes a Windows EOL pair (\r\n) at the end if present.
      13              :  * - Removes a single \n or \r at the end if present.
      14              :  * - Does nothing for empty or very short buffers.
      15              :  */
      16            1 : Return trim_trailing_eol(memory *buffer)
      17              : {
      18            1 :         Return status = SUCCESS;
      19              : 
      20            1 :         if(buffer == NULL)
      21              :         {
      22            0 :                 return(FAILURE);
      23              :         }
      24              : 
      25              :         /* Nothing to trim if length is less than one byte */
      26            1 :         if(buffer->length < 1U)
      27              :         {
      28            0 :                 return(SUCCESS);
      29              :         }
      30              : 
      31            1 :         size_t len = buffer->length;
      32            1 :         char *data_ptr = data(char,buffer);
      33              : 
      34            1 :         if(data_ptr == NULL)
      35              :         {
      36            0 :                 return(FAILURE);
      37              :         }
      38              : 
      39              :         /* If there is a trailing '\0', operate on the actual string payload */
      40            1 :         if(len > 0U && data_ptr[len - 1U] == '\0')
      41              :         {
      42            1 :                 len -= 1U;
      43              :         }
      44              : 
      45              :         /* After trimming a possible '\0' we might end up empty */
      46            1 :         if(len == 0U)
      47              :         {
      48            0 :                 return(SUCCESS);
      49              :         }
      50              : 
      51            1 :         size_t new_len = len;
      52              : 
      53              :         /* Check for Windows EOL (\r\n) */
      54            1 :         if(len >= 2U && data_ptr[len - 2U] == '\r' && data_ptr[len - 1U] == '\n')
      55              :         {
      56            0 :                 new_len = len - 2U;
      57              : 
      58            1 :         } else if(data_ptr[len - 1U] == '\n' || data_ptr[len - 1U] == '\r'){
      59              :                 /* Single \n or \r */
      60            1 :                 new_len = len - 1U;
      61              :         }
      62              : 
      63              :         /* No change means no trailing EOL */
      64            1 :         if(new_len == len)
      65              :         {
      66            0 :                 return(SUCCESS);
      67              :         }
      68              : 
      69              :         /* Restore trailing '\0' if it originally existed */
      70            1 :         const bool had_null_terminator = (buffer->length > 0U && data_ptr[buffer->length - 1U] == '\0');
      71            1 :         size_t target_length = new_len;
      72              : 
      73            1 :         if(had_null_terminator)
      74              :         {
      75              :                 /* Reserve +1 for the terminator */
      76            1 :                 target_length = new_len + 1U;
      77              :         }
      78              : 
      79            1 :         run(resize(buffer,target_length));
      80              : 
      81            1 :         if(SUCCESS == status && had_null_terminator)
      82              :         {
      83            1 :                 char *ptr = data(char,buffer);
      84              : 
      85            1 :                 if(ptr == NULL)
      86              :                 {
      87            0 :                         status = FAILURE;
      88              :                 } else {
      89            1 :                         ptr[target_length - 1U] = '\0';
      90              :                 }
      91              :         }
      92              : 
      93            1 :         provide(status);
      94              : }
        

Generated by: LCOV version 2.0-1