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 : }
|