Branch data Line data Source code
1 : : #include "precizer.h"
2 : :
3 : : /**
4 : : * @brief Append a string to a dynamically allocated NULL-terminated string array
5 : : *
6 : : * @details The array must remain NULL-terminated to allow safe iteration
7 : : * The function grows the array as needed and stores the resulting pointer
8 : : * back through `array_ptr`
9 : : *
10 : : * @param[in,out] array_ptr Pointer to the caller-owned array pointer
11 : : * @param[in] new_string String to append
12 : : *
13 : : * @return SUCCESS if the string was appended successfully
14 : : * @return FAILURE if validation or allocation fails
15 : : *
16 : : * @note `*array_ptr` may be `NULL` on input
17 : : *
18 : : * @warning On allocation failure the function frees the current array and sets
19 : : * `*array_ptr` to `NULL`
20 : : */
21 : 380 : Return add_string_to_array(
22 : : char ***array_ptr,
23 : : const char *new_string)
24 : : {
25 : : /* Status returned by this function through provide()
26 : : Default value assumes successful completion */
27 : 380 : Return status = SUCCESS;
28 : :
29 [ - + ]: 380 : if(array_ptr == NULL)
30 : : {
31 : 0 : report("Invalid parameter: array_ptr is NULL");
32 : 0 : provide(FAILURE);
33 : : }
34 : :
35 [ - + ]: 380 : if(new_string == NULL)
36 : : {
37 : 0 : report("Invalid parameter: new_string is NULL");
38 : 0 : provide(FAILURE);
39 : : }
40 : :
41 : : // Measure the current array length
42 : 380 : size_t size = 0;
43 : 380 : char **array = *array_ptr;
44 : :
45 [ + + ]: 380 : if(array != NULL)
46 : : {
47 [ + + ]: 301 : while(array[size] != NULL)
48 : : {
49 : 153 : size++;
50 : : }
51 : : }
52 : :
53 : : // Use a temporary variable so realloc() cannot overwrite the only live pointer
54 : 380 : char **tmp = (char **)realloc(array,(size + 2) * sizeof(char *));
55 : :
56 [ - + ]: 380 : if(tmp == NULL)
57 : : {
58 : : // Reallocation failed, free the current array and clear the caller-owned pointer
59 : 0 : report("Memory allocation failed, requested size: %zu bytes",(size + 2) * sizeof(char *));
60 : :
61 : 0 : free_string_array(&array);
62 : 0 : *array_ptr = NULL;
63 : 0 : provide(FAILURE);
64 : : } else {
65 : 380 : array = tmp;
66 : : }
67 : :
68 : : // Allocate memory for the appended string
69 : 380 : const size_t new_string_len = strlen(new_string) + 1;
70 : 380 : array[size] = (char *)malloc(new_string_len * sizeof(char));
71 : :
72 [ - + ]: 380 : if(array[size] == NULL)
73 : : {
74 : 0 : report("Memory allocation failed, requested size: %zu bytes",new_string_len * sizeof(char));
75 : :
76 : : // String allocation failed, free the current array and clear the caller-owned pointer
77 : 0 : free_string_array(&array);
78 : 0 : *array_ptr = NULL;
79 : 0 : provide(FAILURE);
80 : : }
81 : :
82 : 380 : memcpy(array[size],new_string,new_string_len);
83 : :
84 : : // Keep the array NULL-terminated
85 : 380 : array[size + 1] = NULL;
86 : :
87 : : // Publish the possibly reallocated array back to the caller
88 : 380 : *array_ptr = array;
89 : :
90 : 380 : provide(status);
91 : : }
|