string_type.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_type.c
9 * @date Aug 2, 2016
10 * @brief String type module implementation file.
11 *
12 ************************************************************************/
13 
14 #include "string_type.h"
15 #include "memory.h"
16 #include "log_util.h"
17 #include "definitions.h"
18 
19 const char *hex_table = "0123456789ABCDEF";
20 
22 E_MCL_ERROR_CODE _initialize(string_t *string, const char *value, mcl_size_t value_length);
23 
25 {
26  VERBOSE_ENTRY("const string_t *other = <%p>, string_t **string = <%p>", other, string)
27 
28  E_MCL_ERROR_CODE result;
29  MCL_NEW(*string);
30  ASSERT_CODE_MESSAGE(MCL_NULL != *string, MCL_OUT_OF_MEMORY, "Not enough memory to allocate for string_t!");
31 
32  (*string)->type = MCL_STRING_COPY_DESTROY;
33 
34  result = _initialize(*string, other->buffer, other->length);
35 
36  if (MCL_OK != result)
37  {
38  MCL_ERROR("_initialize_with_option() failed!. Freeing the string_t!");
39  MCL_FREE(*string);
40  }
41 
42  VERBOSE_LEAVE("retVal = <%d>", result);
43  return result;
44 }
45 
46 E_MCL_ERROR_CODE string_initialize_new(const char *value, mcl_size_t value_length, string_t **string)
47 {
48  VERBOSE_ENTRY("const char *value = <%s>, mcl_size_t value_length = <%u>, string_t **string = <%p>", value, value_length, string)
49 
50  E_MCL_ERROR_CODE result;
51  MCL_NEW(*string);
52  ASSERT_CODE_MESSAGE(MCL_NULL != *string, MCL_OUT_OF_MEMORY, "Not enough memory to allocate for string_t!");
53 
54  (*string)->type = MCL_STRING_COPY_DESTROY;
55 
56  result = _initialize(*string, value, value_length);
57 
58  if (MCL_OK != result)
59  {
60  MCL_ERROR("_initialize_with_option() failed!. Freeing the string_t!");
61  MCL_FREE(*string);
62  }
63 
64  VERBOSE_LEAVE("retVal = <%d>", result);
65  return result;
66 }
67 
68 E_MCL_ERROR_CODE string_initialize_dynamic(const char *value, mcl_size_t value_length, string_t **string)
69 {
70  VERBOSE_ENTRY("const char *value = <%s>, mcl_size_t value_length = <%u>, string_t **string = <%p>", value, value_length, string)
71 
72  E_MCL_ERROR_CODE result;
73  MCL_NEW(*string);
74  ASSERT_CODE_MESSAGE(MCL_NULL != *string, MCL_OUT_OF_MEMORY, "Not enough memory to allocate for string_t!");
75 
76  (*string)->type = MCL_STRING_NOT_COPY_DESTROY;
77 
78  result = _initialize(*string, value, value_length);
79 
80  if (MCL_OK != result)
81  {
82  MCL_ERROR("_initialize_with_option() failed!. Freeing the string_t!");
83  MCL_FREE(*string);
84  }
85 
86  VERBOSE_LEAVE("retVal = <%d>", result);
87  return result;
88 }
89 
90 E_MCL_ERROR_CODE string_initialize_static(const char *value, mcl_size_t value_length, string_t **string)
91 {
92  VERBOSE_ENTRY("const char *value = <%s>, mcl_size_t value_length = <%u>, string_t **string = <%p>", value, value_length, string)
93 
94  E_MCL_ERROR_CODE result;
95  MCL_NEW(*string);
96  ASSERT_CODE_MESSAGE(MCL_NULL != *string, MCL_OUT_OF_MEMORY, "Not enough memory to allocate for string_t!");
97 
98  (*string)->type = MCL_STRING_NOT_COPY_NOT_DESTROY;
99 
100  result = _initialize(*string, value, value_length);
101 
102  if (MCL_OK != result)
103  {
104  MCL_ERROR("_initialize_with_option() failed!. Freeing the string_t!");
105  MCL_FREE(*string);
106  }
107 
108  VERBOSE_LEAVE("retVal = <%d>", result);
109  return result;
110 }
111 
112 E_MCL_ERROR_CODE string_set(string_t *string, const char *value, mcl_size_t value_length)
113 {
114  VERBOSE_ENTRY("string_t *string = <%p>, const char *value = <%s>, mcl_size_t value_length = <%u>", string, value, value_length)
115 
116  E_MCL_ERROR_CODE result;
117 
118  // first call release to release the buffer :
119  string_release(string);
120 
121  result = _initialize(string, value, value_length);
122 
123  ASSERT_CODE_MESSAGE(MCL_OK == result, result, "initialize_with_option failed! Not freeing the string but it's buffer has already been freed!");
124 
125  VERBOSE_LEAVE("retVal = <%d>", MCL_OK);
126  return MCL_OK;
127 }
128 
129 E_MCL_ERROR_CODE string_compare(const string_t *string, const string_t *other)
130 {
131  DEBUG_ENTRY("const string_t *string = <%p>, const string_t *other = <%p>", string, other)
132 
133  E_MCL_ERROR_CODE result = string_compare_with_cstr(string, other->buffer);
134 
135  DEBUG_LEAVE("retVal = <%d>", result);
136  return result;
137 }
138 
139 E_MCL_ERROR_CODE string_compare_with_cstr(const string_t *string, const char *other)
140 {
141  DEBUG_ENTRY("const string_t *string = <%p>, const char *other = <%s>", string, other)
142 
143  E_MCL_ERROR_CODE result = MCL_FAIL;
144  mcl_size_t length = 0;
145 
146  if ((MCL_NULL != string) && (MCL_NULL != string->buffer))
147  {
148  if (MCL_NULL != other)
149  {
150  // first check if both are pointing the same memory space
151  if (string->buffer == other)
152  {
153  MCL_DEBUG("string->buffer and other are pointing to the same memory space");
154  result = MCL_OK;
155  }
156  else
157  {
158  length = string_util_strlen(other);
159  if (length == string->length)
160  {
161  result = string_util_strncmp(string->buffer, other, string->length);
162  }
163  }
164  }
165  else
166  {
167  MCL_DEBUG("Received compare string (other) is NULL.");
168  }
169  }
170  else
171  {
172  MCL_DEBUG("Received string object or it's buffer is NULL");
173  }
174 
175  DEBUG_LEAVE("retVal = <%d>", result);
176  return result;
177 }
178 
179 E_MCL_ERROR_CODE string_split(string_t *string, const char token, list_t **string_list)
180 {
181  DEBUG_ENTRY("string_t *string = <%p>, const char token = <%c>, list_t **string_list = <%p>", string, token, string_list)
182 
183  E_MCL_ERROR_CODE result = MCL_OK;
184  list_t *list = MCL_NULL;
185 
186  // buf might be at most as string->length ( C99 allows this )
187  char *temp_buffer = string->buffer;
188  mcl_size_t temp_length = 0;
189  string_t *current_part;
190  mcl_size_t index;
191 
192  result = list_initialize(string_list);
193  ASSERT_CODE_MESSAGE(MCL_OK == result, result, "mcl_list initialize failed!");
194 
195  list = *string_list;
196 
197  for (index = 0; index < string->length; index++)
198  {
199  if (string->buffer[index] != token)
200  {
201  temp_length++;
202  }
203  else
204  {
205  // add contents of temp_buffer into the list ( if any ):
206  if (temp_length > 0)
207  {
208  if (MCL_OK != (result = string_initialize_new(temp_buffer, temp_length, &current_part)))
209  {
210  MCL_ERROR("string_initialize_new failed!");
211  temp_length = 0;
212 
213  break;
214  }
215 
216  if (MCL_OK != (result = list_add(list, current_part)))
217  {
218  MCL_ERROR("Current split part of the string couldn't be added to the list!");
219  string_destroy(&current_part);
220  temp_length = 0;
221 
222  break;
223  }
224 
225  MCL_DEBUG("Current split part has been added to the list = <%s>", current_part->buffer);
226 
227  // now reset the temp buffers for the next one :
228  temp_buffer += temp_length + 1;
229  temp_length = 0;
230  }
231  else
232  {
233  // this means current char is token but there is no unlisted parts before.
234  // we need to shift temp_buffer pointer to the next one :
235  temp_buffer++;
236  }
237  }
238  }
239 
240  // check if there is still something to add :
241  if ((MCL_OK == result) && ((temp_length > 0) && (MCL_NULL_CHAR != *temp_buffer)))
242  {
243  if (MCL_OK != (result = string_initialize_new(temp_buffer, temp_length, &current_part)))
244  {
245  MCL_ERROR("string_initialize_new failed!");
246  }
247  else
248  {
249  if (MCL_OK != (result = list_add(list, current_part)))
250  {
251  MCL_ERROR("Last split part of the string couldn't be added to the list!");
252  string_destroy(&current_part);
253  }
254  else
255  {
256  MCL_DEBUG("Last split part has been added to the list = <%s>", current_part->buffer);
257  }
258  }
259  }
260 
261  // If something wrong happened, destroy the content of the list before return
262  if ((MCL_OK != result) && (MCL_NULL != *string_list))
263  {
264  MCL_DEBUG("Result is NOT successful. Clearing the content of the list if there is any");
266  }
267 
268  DEBUG_LEAVE("retVal = <%p>", result);
269  return result;
270 }
271 
273 {
274  VERBOSE_ENTRY("const mcl_uint8_t *buffer = <%p>, mcl_size_t buffer_size = <%u>, string_t **hex_data = <%p>", buffer, buffer_size, hex_data)
275 
276  // initialize with empty string
277  E_MCL_ERROR_CODE code = string_initialize_new(MCL_NULL, 0, hex_data);
278  mcl_size_t i;
279  ASSERT_CODE_MESSAGE(MCL_OK == code, code, "Initialization of hex string failed!");
280 
281  // allocate space for hex result (zero terminated)
282  (*hex_data)->length = 2 * buffer_size;
283  (*hex_data)->buffer = MCL_CALLOC(1, (*hex_data)->length + 1);
284  ASSERT_CODE_MESSAGE(MCL_NULL != (*hex_data)->buffer, MCL_OUT_OF_MEMORY, "Memory to store hex string couldn't be allocated!");
285 
286  // convert byte to hex using table
287  for (i = 0; i < buffer_size; i++)
288  {
289  ((*hex_data)->buffer)[i * 2 + 0] = hex_table[(buffer[i] >> 4) & 0x0F];
290  ((*hex_data)->buffer)[i * 2 + 1] = hex_table[buffer[i] & 0x0F];
291  }
292  ((*hex_data)->buffer)[buffer_size * 2] = MCL_NULL_CHAR;
293 
294  VERBOSE_LEAVE("retVal = <%d>", MCL_OK);
295  return MCL_OK;
296 }
297 
299 {
300  VERBOSE_ENTRY("string_t *string = <%p>", string)
301 
302  if (MCL_NULL != string->buffer)
303  {
304  // free the buffer according to the type :
305  if ((MCL_STRING_COPY_DESTROY == string->type) || (MCL_STRING_NOT_COPY_DESTROY == string->type))
306  {
307  MCL_VERBOSE("Type is MCL_STRING_COPY_DESTROY or MCL_STRING_NOT_COPY_DESTROY. Freeing the buffer.");
308  MCL_FREE(string->buffer);
309  }
310  else
311  {
312  MCL_VERBOSE("Type is MCL_STRING_NOT_COPY_NOT_DESTROY. Not freeing the buffer.");
313  string->buffer = MCL_NULL;
314  }
315 
316  string->length = 0;
317  }
318  else
319  {
320  MCL_VERBOSE("String buffer is already NULL!");
321  }
322 
323  VERBOSE_LEAVE("retVal = void");
324 }
325 
326 void string_destroy(string_t **string)
327 {
328  VERBOSE_ENTRY("string_t **string = <%p>", string)
329 
330  if (MCL_NULL != *string)
331  {
332  string_release(*string);
333  MCL_FREE(*string);
334  }
335 
336  VERBOSE_LEAVE("retVal = void");
337 }
338 
339 E_MCL_ERROR_CODE _initialize(string_t *string, const char *value, mcl_size_t value_length)
340 {
341  VERBOSE_ENTRY("string_t *string = <%p>, const char *value = <%s>, mcl_size_t value_length = <%u>", string, value, value_length)
342 
343  // set the buffer and length :
344  if (MCL_NULL != value)
345  {
346  mcl_size_t length = 0;
347 
348  MCL_VERBOSE("Not NULL value received. String will be initialized with it.");
349 
350  if (value_length > 0)
351  {
352  length = value_length;
353  }
354  else
355  {
356  // calculate length :
357  length = string_util_strlen(value);
358  }
359 
360  // copy the value into string buffer if requested :
361  if (MCL_STRING_COPY_DESTROY == string->type)
362  {
363  MCL_VERBOSE("Copy Flag is TRUE : Given value parameter will be copied into the buffer");
364 
365  // allocate buffer
366  string->buffer = MCL_MALLOC(length + 1);
367  ASSERT_CODE_MESSAGE(MCL_NULL != string->buffer, MCL_OUT_OF_MEMORY, "Memory couldn't be allocated for string_t");
368 
369  // set empty right away otherwise might corrupts the mem in _strncpy since it tries to log the input parameters:
370  string->buffer[0] = MCL_NULL_CHAR;
371 
372  // copy the string :
373  string_util_strncpy(string->buffer, value, length);
374 
375  // finalize the buffer:
376  string->buffer[length] = MCL_NULL_CHAR;
377  }
378  else
379  {
380  MCL_VERBOSE("Copy Flag is FALSE : Given value parameters address will be assigned to the buffer");
381 
382  // to avoid compilers const warning, explicitly casting to (char *):
383  string->buffer = (char *)value;
384  }
385 
386  // set the length :
387  string->length = length;
388 
389  MCL_VERBOSE("String buffer has been prepared. Buffer = <%s>, Length = <%d>", string->buffer, string->length);
390  }
391  else if ((0 < value_length) && (MCL_STRING_COPY_DESTROY == string->type))
392  {
393  MCL_VERBOSE("NULL value received, but new string with given length (> 0) requested. Buffer for string will be allocated and zero-terminated. Buffer remains uninitialized.");
394 
395  string->buffer = MCL_MALLOC(value_length + 1);
396  ASSERT_CODE_MESSAGE(MCL_NULL != string->buffer, MCL_OUT_OF_MEMORY, "Memory couldn't be allocated for string_t");
397 
398  string->length = value_length;
399 
400  // finalize the buffer and set it's length:
401  string->buffer[value_length] = MCL_NULL_CHAR;
402  }
403  else
404  {
405  MCL_VERBOSE("NULL value received. String will be initialized as empty.");
406 
407  // init value is null. we are not going to allocate memory for internal buffer
408  string->buffer = MCL_NULL;
409  string->length = 0;
410  }
411 
412  VERBOSE_LEAVE("retVal = <%d>", MCL_OK);
413  return MCL_OK;
414 }
415 
417 {
418  VERBOSE_ENTRY("string_t *string_1 = <%p>, string_t *string_2 = <%p>, string_t **result = <%p>", string_1, string_2, result)
419 
420  E_MCL_ERROR_CODE code = MCL_FAIL;
421  mcl_size_t result_length = string_1->length + string_2->length;
422 
423  if (MCL_OK == (code = string_initialize_new(MCL_NULL, result_length, result)))
424  {
425  code = string_util_snprintf((*result)->buffer, result_length + 1, "%s%s", string_1->buffer, string_2->buffer);
426  ASSERT_STATEMENT_CODE_MESSAGE(MCL_OK == code, string_destroy(result), code, "Cannot concatenate strings.");
427  }
428 
429  VERBOSE_LEAVE("retVal = <%d>", code);
430  return code;
431 }
432 
433 E_MCL_ERROR_CODE string_replace(string_t *source, const char *old_string, const char *new_string, string_t **result)
434 {
435  VERBOSE_ENTRY("string_t *source = <%p>, const char *old_string = <%p>, const char *new_string = <%p>, string_t **result = <%p>", source, old_string, new_string, result)
436 
437  E_MCL_ERROR_CODE code;
438  mcl_size_t start_index;
439  mcl_size_t old_string_length;
440  mcl_size_t new_string_length;
441  mcl_size_t target_string_length;
442  mcl_bool_t register_keyword_found;
443  char *target_string;
444 
445  old_string_length = string_util_strlen(old_string);
446  new_string_length = string_util_strlen(new_string);
447  target_string_length = source->length - old_string_length + new_string_length;
448 
449  target_string = MCL_CALLOC(target_string_length + 1, 1);
450  ASSERT_CODE_MESSAGE(MCL_NULL != target_string, MCL_OUT_OF_MEMORY, "Could not allocate memory for target_string");
451 
452  register_keyword_found = string_util_find(source->buffer, old_string, &start_index);
453  ASSERT_STATEMENT_CODE_MESSAGE(MCL_TRUE == register_keyword_found, MCL_FREE(target_string), MCL_FAIL, "String does not contain old_string");
454 
455  string_util_strncat(target_string, source->buffer, start_index);
456  string_util_strncat(target_string, new_string, new_string_length);
457  string_util_strncat(target_string, source->buffer + start_index + old_string_length, source->length - (start_index + old_string_length));
458 
459  code = string_initialize_dynamic(target_string, target_string_length, result);
460 
461  VERBOSE_LEAVE("retVal = <%d>", code);
462  return code;
463 }
464 
465 E_MCL_ERROR_CODE string_concatenate_cstr(string_t *string, char *c_string, string_t **result)
466 {
467  VERBOSE_ENTRY("string_t *string = <%p>, char *cstring = <%p>, string_t **result = <%p>", string, c_string, result)
468 
469  E_MCL_ERROR_CODE code;
470  mcl_size_t c_string_length;
471  mcl_size_t result_length;
472 
473  c_string_length = string_util_strlen(c_string);
474  result_length = string->length + c_string_length;
475 
476  code = string_initialize_new(MCL_NULL, result_length, result);
477  (code == MCL_OK) && (code = string_util_snprintf((*result)->buffer, result_length + 1, "%s%s", string->buffer, c_string));
478  ASSERT_STATEMENT_CODE_MESSAGE(MCL_OK == code, string_destroy(result), code, "Cannot concatenate strings.");
479 
480  VERBOSE_LEAVE("retVal = <%d>", code);
481  return code;
482 }
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_replace(string_t *source, const char *old_string, const char *new_string, string_t **result)
Replaces old_string with new_string.
Definition: string_type.c:433
Internal failure in MCL.
Definition: mcl_common.h:141
Memory module header file.
#define VERBOSE_LEAVE(...)
Definition: log_util.h:66
#define DEBUG_LEAVE(...)
Definition: log_util.h:81
#define DEBUG_ENTRY(...)
Definition: log_util.h:80
#define MCL_NEW(p)
Definition: memory.h:121
E_MCL_ERROR_CODE string_initialize_new(const char *value, mcl_size_t value_length, string_t **string)
Initializes a new string_t object with the given value and length.
Definition: string_type.c:46
#define MCL_TRUE
Definition: mcl_common.h:54
char * buffer
Buffer of string handle.
Definition: string_type.h:45
E_MCL_ERROR_CODE string_split(string_t *string, const char token, list_t **string_list)
Splits the string with the given char and returns the result as an list_t of string_t&#39;s.
Definition: string_type.c:179
mcl_bool_t string_util_find(const char *source, const char *target, mcl_size_t *start_index)
Finds the first occurence of target in source and puts it&#39;s first index to start_index.
Definition: string_util.c:156
void string_util_strncpy(char *destination, const char *source, mcl_size_t count)
Standard library strncpy wrapper. Also sets the terminating null char at the end if source is not lon...
Definition: string_util.c:48
#define MCL_DEBUG(...)
Definition: log_util.h:70
E_MCL_ERROR_CODE string_compare_with_cstr(const string_t *string, const char *other)
Compare the contents of string_t with a C string.
Definition: string_type.c:139
#define MCL_MALLOC(bytes)
Definition: memory.h:120
Log utility module header file.
E_MCL_ERROR_CODE list_initialize(list_t **list)
Initializes the list.
Definition: list.c:139
E_MCL_ERROR_CODE
MCL Error code definitions. Every function returning an error code uses this enum values...
Definition: mcl_common.h:137
E_MCL_ERROR_CODE string_util_snprintf(char *string, mcl_size_t length, const char *format,...)
Standard library snprintf wrapper.
Definition: string_util.c:95
Strings with this type will NOT allocate its buffer during initialization (buffer only points of the ...
Definition: string_type.h:36
E_MCL_STRING_TYPE type
Type of copy and destroy.
Definition: string_type.h:47
#define MCL_FREE(p)
Definition: memory.h:125
#define VERBOSE_ENTRY(...)
Definition: log_util.h:65
#define ASSERT_STATEMENT_CODE_MESSAGE(condition, statement, return_code,...)
Definition: definitions.h:121
E_MCL_ERROR_CODE string_compare(const string_t *string, const string_t *other)
Compare the contents of two string_t&#39;s.
Definition: string_type.c:129
uint8_t mcl_uint8_t
Definition: mcl_common.h:43
const char * hex_table
Definition: string_type.c:19
Strings with this type will allocates its buffer during initialization (copies the initial value to i...
Definition: string_type.h:35
#define MCL_CALLOC(count, bytes)
Definition: memory.h:122
#define ASSERT_CODE_MESSAGE(condition, return_code,...)
Definition: definitions.h:105
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
E_MCL_ERROR_CODE string_convert_binary_to_hex(const mcl_uint8_t *buffer, mcl_size_t buffer_size, string_t **hex_data)
Definition: string_type.c:272
E_MCL_ERROR_CODE string_concatenate_cstr(string_t *string, char *c_string, string_t **result)
Concatenates two strings of type string_t into a string_t.
Definition: string_type.c:465
E_MCL_ERROR_CODE string_initialize(const string_t *other, string_t **string)
Initializes an string_t object with another one.
Definition: string_type.c:24
mcl_size_t length
Length of buffer.
Definition: string_type.h:46
void string_release(string_t *string)
Clears the content of the string. And deallocates the memory.
Definition: string_type.c:298
E_MCL_ERROR_CODE string_util_strncmp(const char *string_1, const char *string_2, mcl_size_t count)
Standard library strncmp wrapper.
Definition: string_util.c:74
E_MCL_ERROR_CODE string_set(string_t *string, const char *value, mcl_size_t value_length)
Sets the buffer of the string with a new value.
Definition: string_type.c:112
size_t mcl_size_t
Definition: mcl_common.h:38
mcl_uint8_t mcl_bool_t
Definition: mcl_common.h:47
#define MCL_VERBOSE(...)
Definition: log_util.h:57
Success.
Definition: mcl_common.h:140
void list_destroy_with_content(list_t **list, list_item_destroy_callback callback)
To destroy the list and its items with a given callback function.
Definition: list.c:373
#define MCL_ERROR(...)
Definition: log_util.h:97
E_MCL_ERROR_CODE string_initialize_static(const char *value, mcl_size_t value_length, string_t **string)
Initializes a static string_t object with the given value and length.
Definition: string_type.c:90
E_MCL_ERROR_CODE _initialize(string_t *string, const char *value, mcl_size_t value_length)
Private Function Prototypes:
Definition: string_type.c:339
String type module header file.
E_MCL_ERROR_CODE list_add(list_t *list, void *data)
Adds a new list item.
Definition: list.c:159
Memory allocation fail.
Definition: mcl_common.h:143
#define MCL_NULL
Definition: definitions.h:24
mcl_list_item_destroy_callback list_item_destroy_callback
Definition: list.h:24
E_MCL_ERROR_CODE string_concatenate(string_t *string_1, string_t *string_2, string_t **result)
Concatenates a C string (i.e. a char array)
Definition: string_type.c:416
mcl_size_t string_util_strlen(const char *buffer)
Standard library strlen wrapper.
Definition: string_util.c:24
#define MCL_NULL_CHAR
Definition: definitions.h:26
Strings with this type will NOT allocate its buffer during initialization (buffer only points of the ...
Definition: string_type.h:37