string_array.c
Go to the documentation of this file.
1 /*!**********************************************************************
2 *
3 * @copyright Copyright (C) 2016 Siemens Aktiengesellschaft.\n
4 * All rights reserved.
5 *
6 *************************************************************************
7 *
8 * @file string_array.c
9 * @date Aug 19, 2016
10 * @brief String array module implementation file.
11 *
12 ************************************************************************/
13 
14 #include "string_array.h"
15 #include "memory.h"
16 #include "definitions.h"
17 #include "log_util.h"
18 
20 {
21  VERBOSE_ENTRY("mcl_size_t count = <%u>, string_array_t **array = <%p>", count, array)
22 
23  string_array_t *new_array;
24  mcl_size_t index;
25 
26  ASSERT_CODE_MESSAGE(0 < count, MCL_INVALID_PARAMETER, "Count cannot be zero.");
27 
28  MCL_NEW(*array);
29  ASSERT_CODE_MESSAGE(MCL_NULL != *array, MCL_OUT_OF_MEMORY, "Not enough memory to allocate for array!");
30 
31  new_array = *array;
32 
33  // initialize the new array :
35  new_array->count = count;
36  new_array->index = 0;
37  new_array->total_length = 0;
38 
39  // not used calloc here since the items will be initialized below:
40  new_array->items = MCL_MALLOC(count * sizeof(string_array_item_t));
41  if (MCL_NULL == new_array->items)
42  {
43  MCL_FREE(*array);
44  MCL_ERROR_RETURN(MCL_OUT_OF_MEMORY, "Not enough memory to allocate array item !");
45  }
46 
47  // items has been allocated. Now intiialize its items :
48  for (index = 0; index < count; index++)
49  {
50  new_array->items[index].string = MCL_NULL;
51  new_array->items[index].destroy = MCL_FALSE;
52  }
53 
54  VERBOSE_LEAVE("retVal = <%d>", MCL_OK);
55  return MCL_OK;
56 }
57 
59 {
60  DEBUG_ENTRY("string_array_t *array = <%p>, mcl_size_t increment_value = <%u>", array, increment_value)
61 
62  ASSERT_CODE_MESSAGE(0 < increment_value, MCL_INVALID_PARAMETER, "Increment value cannot be equal to 0.");
63 
64  array->increment_value = increment_value;
65 
66  DEBUG_LEAVE("retVal = <%d>", MCL_OK);
67  return MCL_OK;
68 }
69 
71 {
72  DEBUG_ENTRY("string_array_t *array = <%p>, string_t *string = <%p>, mcl_bool_t destroy = <%u>", array, string, destroy)
73 
74  // check if array is full ( not expecting the index > count case but still used >= instead of ==. Feels more safe):
75  if (array->index >= array->count)
76  {
77  mcl_size_t new_count;
78  mcl_size_t new_size;
79  mcl_size_t index;
80 
81  MCL_DEBUG("Array is full. It will be resized by increment value");
82 
83  // if somehow increment value is 0, reset :
84  if (0 == array->increment_value)
85  {
87  }
88 
89  new_count = array->count + array->increment_value;
90  new_size = new_count * sizeof(string_array_item_t);
91  MCL_RESIZE(array->items, new_size);
92  ASSERT_CODE_MESSAGE(MCL_NULL != array->items, MCL_OUT_OF_MEMORY, "Array items couldn't be resized!");
93 
94  for (index = array->count; index < new_count; index++)
95  {
96  array->items[index].string = MCL_NULL;
97  array->items[index].destroy = MCL_FALSE;
98  }
99 
100  array->count = new_count;
101 
102  // items size have to be bigger now. No need to check again for index<count
103  }
104 
105  array->items[array->index].string = string;
106  array->items[array->index].destroy = destroy;
107  array->index++;
108  array->total_length += string->length;
109 
110  DEBUG_LEAVE("retVal = <%d>", MCL_OK);
111  return MCL_OK;
112 }
113 
115 {
116  DEBUG_ENTRY("string_array_t *array = <%p>, mcl_size_t index = <%u>", array, index)
117 
118  string_t *string_to_return;
119 
120  ASSERT_MESSAGE(MCL_NULL != array, "Received array is NULL!");
121  ASSERT_MESSAGE(MCL_NULL != array->items, "Received array's item array is NULL!");
122 
123  // index should be less than array->index not array->count !!
124  ASSERT_MESSAGE(index < array->index, "Received index is out of bounds!");
125 
126  string_to_return = array->items[index].string;
127 
128  DEBUG_LEAVE("retVal = <%p>", string_to_return);
129  return string_to_return;
130 }
131 
133 {
134  DEBUG_ENTRY("string_array_t *array = <%p>", array)
135 
136  char *final_buffer;
137  char *temp_buffer;
138  mcl_size_t index;
139  string_t *final_string = MCL_NULL;
140 
141  ASSERT_MESSAGE(MCL_NULL != array, "Received array is NULL!");
142  ASSERT_MESSAGE(MCL_NULL != array->items, "Received array's item array is NULL!");
143  ASSERT_MESSAGE(0 != array->total_length, "Received array's total length is 0!");
144 
145  // allocate buffer with total lenght
146  final_buffer = MCL_MALLOC(array->total_length + 1);
147  ASSERT_MESSAGE(MCL_NULL != final_buffer, "Not enough memory for final_buffer!");
148  final_buffer[0] = MCL_NULL_CHAR;
149 
150  // this is going to be used to increase strncat performance
151  temp_buffer = final_buffer;
152 
153  for (index = 0; index < array->index; index++)
154  {
155  string_util_strncat(temp_buffer, array->items[index].string->buffer, array->items[index].string->length);
156 
157  // increasing temp_buffer to make it point to the last null char put by strncat. This way in the next call to strncat,
158  // it is not going to search for nullchar from the beginning of the string. This will increase performance :
159  temp_buffer += array->items[index].string->length;
160  MCL_DEBUG("String at index <%d> has been added to the final buffer = <%s>", index, final_buffer);
161  }
162 
163  // initialize the string as dynamic : not re allocate again but will free the buffer during it's destroy :
164  if (MCL_OK != string_initialize_dynamic(final_buffer, array->total_length, &final_string))
165  {
166  MCL_FREE(final_buffer);
167  MCL_ERROR_RETURN_POINTER(MCL_NULL, "string initialize operation has been failed for final_string!");
168  }
169 
170  DEBUG_LEAVE("retVal = <%p>", final_string);
171  return final_string;
172 }
173 
175 {
176  DEBUG_ENTRY("string_array_t **array = <%p>", array)
177 
178  string_array_t *local_array = *array;
179 
180  if (MCL_NULL != local_array)
181  {
182  if (MCL_NULL != local_array->items)
183  {
184  mcl_size_t index;
185 
186  for (index = 0; index < local_array->count; index++)
187  {
188  if (MCL_TRUE == local_array->items[index].destroy)
189  {
190  // try to destroy it
191  string_destroy(&(local_array->items[index].string));
192  MCL_DEBUG("Current string item in string array has been destroyed.");
193  }
194  else
195  {
196  MCL_DEBUG("Current string item has been added to array as not destroyable. Not calling destroy.");
197  }
198  }
199 
200  MCL_DEBUG("String items in the array has been released. Now freeing the array.");
201  MCL_FREE(local_array->items);
202  }
203  MCL_FREE(*array);
204  }
205 
206  DEBUG_LEAVE("retVal = void");
207 }
void string_util_strncat(char *destination, const char *source, mcl_size_t count)
Standard library strncat wrapper.
Definition: string_util.c:61
void string_destroy(string_t **string)
Destroys the allocated resources of the string.
Definition: string_type.c:326
E_MCL_ERROR_CODE string_array_add(string_array_t *array, string_t *string, mcl_bool_t destroy)
Adds an string_t string object into the array.
Definition: string_array.c:70
Memory module header file.
#define VERBOSE_LEAVE(...)
Definition: log_util.h:66
#define DEBUG_LEAVE(...)
Definition: log_util.h:81
mcl_size_t total_length
Total length of string array.
Definition: string_array.h:49
mcl_size_t count
Item count.
Definition: string_array.h:46
#define DEBUG_ENTRY(...)
Definition: log_util.h:80
mcl_size_t index
Item index.
Definition: string_array.h:47
#define MCL_NEW(p)
Definition: memory.h:121
#define MCL_TRUE
Definition: mcl_common.h:54
char * buffer
Buffer of string handle.
Definition: string_type.h:45
void string_array_destroy(string_array_t **array)
Destroys the string array handle.
Definition: string_array.c:174
#define ASSERT_MESSAGE(condition,...)
Definition: definitions.h:82
#define MCL_DEBUG(...)
Definition: log_util.h:70
#define MCL_FALSE
MCL bool type.
Definition: mcl_common.h:53
string_t * string_array_get(string_array_t *array, mcl_size_t index)
To get the string_t string object at a specified index.
Definition: string_array.c:114
#define MCL_ERROR_RETURN_POINTER(return_value,...)
Definition: definitions.h:64
#define MCL_MALLOC(bytes)
Definition: memory.h:120
Log utility module header file.
E_MCL_ERROR_CODE
MCL Error code definitions. Every function returning an error code uses this enum values...
Definition: mcl_common.h:137
#define MCL_RESIZE(p, bytes)
Definition: memory.h:124
#define MCL_FREE(p)
Definition: memory.h:125
#define VERBOSE_ENTRY(...)
Definition: log_util.h:65
string_t * string_array_to_string(string_array_t *array)
To concatenate the strings in the array.
Definition: string_array.c:132
General invalid parameter fail.
Definition: mcl_common.h:144
string_array_item_t * items
Item of string array.
Definition: string_array.h:45
#define ASSERT_CODE_MESSAGE(condition, return_code,...)
Definition: definitions.h:105
mcl_bool_t destroy
To decide whether to call string_destroy() for specific item in the array when destroying the string ...
Definition: string_array.h:37
Definitions module header file.
E_MCL_ERROR_CODE string_initialize_dynamic(const char *value, mcl_size_t value_length, string_t **string)
Initializes a dynamic string_t object with the given value and length.
Definition: string_type.c:68
mcl_size_t length
Length of buffer.
Definition: string_type.h:46
size_t mcl_size_t
Definition: mcl_common.h:38
mcl_uint8_t mcl_bool_t
Definition: mcl_common.h:47
Success.
Definition: mcl_common.h:140
E_MCL_ERROR_CODE string_array_set_increment(string_array_t *array, mcl_size_t increment_value)
Sets the increment value of the array.
Definition: string_array.c:58
E_MCL_ERROR_CODE string_array_initialize(mcl_size_t count, string_array_t **array)
String array initialize method.
Definition: string_array.c:19
string_t * string
String object.
Definition: string_array.h:36
#define DEFAULT_INCREMENT_VALUE
Default increment value of the array.
Definition: string_array.h:28
String array module header file.
Memory allocation fail.
Definition: mcl_common.h:143
#define MCL_NULL
Definition: definitions.h:24
mcl_size_t increment_value
Increment value.
Definition: string_array.h:48
#define MCL_NULL_CHAR
Definition: definitions.h:26
#define MCL_ERROR_RETURN(return_value,...)
Definition: definitions.h:69