libamxc  1.10.3
C Generic Data Containers
amxc_utils.c
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** SPDX-License-Identifier: BSD-2-Clause-Patent
4 **
5 ** SPDX-FileCopyrightText: Copyright (c) 2023 SoftAtHome
6 **
7 ** Redistribution and use in source and binary forms, with or without modification,
8 ** are permitted provided that the following conditions are met:
9 **
10 ** 1. Redistributions of source code must retain the above copyright notice,
11 ** this list of conditions and the following disclaimer.
12 **
13 ** 2. Redistributions in binary form must reproduce the above copyright notice,
14 ** this list of conditions and the following disclaimer in the documentation
15 ** and/or other materials provided with the distribution.
16 **
17 ** Subject to the terms and conditions of this license, each copyright holder
18 ** and contributor hereby grants to those receiving rights under this license
19 ** a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable
20 ** (except for failure to satisfy the conditions of this license) patent license
21 ** to make, have made, use, offer to sell, sell, import, and otherwise transfer
22 ** this software, where such license applies only to those patent claims, already
23 ** acquired or hereafter acquired, licensable by such copyright holder or contributor
24 ** that are necessarily infringed by:
25 **
26 ** (a) their Contribution(s) (the licensed copyrights of copyright holders and
27 ** non-copyrightable additions of contributors, in source or binary form) alone;
28 ** or
29 **
30 ** (b) combination of their Contribution(s) with the work of authorship to which
31 ** such Contribution(s) was added by such copyright holder or contributor, if,
32 ** at the time the Contribution is added, such addition causes such combination
33 ** to be necessarily infringed. The patent license shall not apply to any other
34 ** combinations which include the Contribution.
35 **
36 ** Except as expressly stated above, no rights or licenses from any copyright
37 ** holder or contributor is granted under this license, whether expressly, by
38 ** implication, estoppel or otherwise.
39 **
40 ** DISCLAIMER
41 **
42 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
43 ** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
44 ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
45 ** ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
46 ** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
47 ** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
48 ** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
49 ** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
50 ** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
51 ** USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
52 **
53 ****************************************************************************/
54 
55 #include <stdlib.h>
56 #include <stdio.h>
57 #include <stdarg.h>
58 #include <string.h>
59 #include <ctype.h>
60 
61 #include <amxc/amxc_variant.h>
62 #include <amxc/amxc_string.h>
63 #include <amxc/amxc_utils.h>
64 #include <amxc/amxc_macros.h>
65 
66 typedef void (* amxc_string_replace_cb_t) (amxc_string_t* const string,
67  size_t pos,
68  size_t length,
69  const char* txt,
70  const void* priv);
71 
73  size_t pos,
74  size_t length,
75  const char* txt,
76  UNUSED const void* priv) {
77  char* value = getenv(txt);
78  amxc_string_remove_at(string, pos, length);
79  if(value) {
80  amxc_string_insert_at(string, pos, value, strlen(value));
81  }
82 }
83 
85  size_t pos,
86  size_t length,
87  const char* txt,
88  const void* priv) {
89  amxc_var_t* data = (amxc_var_t*) priv;
90  char* value = amxc_var_dyncast(cstring_t,
92  txt,
94  amxc_string_remove_at(string, pos, length);
95  if(value) {
96  amxc_string_insert_at(string, pos, value, strlen(value));
97  }
98  free(value);
99 
100 }
101 
103  const char* start_string,
104  const char* end_string,
106  const void* priv) {
107  int retval = 0;
108  size_t start_length = strlen(start_string);
109  size_t end_length = strlen(end_string);
110  size_t start = 0;
111  size_t end = 0;
112 
113  for(size_t i = 0; i < string->last_used;) {
114  if(strncmp(string->buffer + i, start_string, start_length) != 0) {
115  i++;
116  continue;
117  }
118  if((i > 0) && (string->buffer[i - 1] == '\\')) {
119  i++;
120  continue;
121  }
122  start = i;
123  end = 0;
124  i++;
125  while(i + end_length <= string->last_used) {
126  if(strncmp(string->buffer + i, end_string, end_length) == 0) {
127  end = i + end_length;
128  string->buffer[i] = 0;
129  break;
130  }
131  i++;
132  }
133  if(i + end_length > string->last_used) {
134  break;
135  }
136  fn(string,
137  start,
138  (end - start),
139  string->buffer + start + start_length,
140  priv);
141  retval++;
142  i = start;
143  }
144 
145  return retval;
146 }
147 
149  int retval = 0;
150 
151  when_null(string, exit);
152  when_true(amxc_string_is_empty(string), exit);
153 
154  retval = amxc_string_generic_resolve(string,
155  "$(",
156  ")",
158  NULL);
159 
160 exit:
161  return retval;
162 }
163 
165  const amxc_var_t* const data) {
166  int retval = 0;
167 
168  when_null(string, exit);
169  when_true(amxc_string_is_empty(string), exit);
170  when_null(data, exit);
172 
173  retval = amxc_string_generic_resolve(string,
174  "${",
175  "}",
177  data);
178 
179 exit:
180  return retval;
181 }
182 
184  int retval = 0;
185  amxc_string_t resolved;
186  size_t length = 0;
187  char* buffer = NULL;
188 
189  amxc_string_init(&resolved, amxc_string_buffer_length(string));
190  for(uint32_t i = 0; i < amxc_string_text_length(string); i++) {
191  if(string->buffer[i] != '\\') {
192  amxc_string_append(&resolved, string->buffer + i, 1);
193  continue;
194  }
195  if(i + 1 >= amxc_string_text_length(string)) {
196  amxc_string_append(&resolved, string->buffer, 1);
197  break;
198  }
199  switch(string->buffer[i + 1]) {
200  case 'n':
201  amxc_string_append(&resolved, "\n", 1);
202  i++;
203  retval++;
204  break;
205  case 't':
206  amxc_string_append(&resolved, "\t", 1);
207  i++;
208  retval++;
209  break;
210  default:
211  amxc_string_append(&resolved, string->buffer + i + 1, 1);
212  i++;
213  retval++;
214  break;
215  }
216  }
217 
218  length = amxc_string_buffer_length(&resolved);
219  buffer = amxc_string_take_buffer(&resolved);
220  amxc_string_push_buffer(string, buffer, length);
221 
222  amxc_string_clean(&resolved);
223  return retval;
224 }
225 
226 int amxc_string_esc(amxc_string_t* const string) {
227  int retval = 0;
228 
229  retval += amxc_string_replace(string, "\\", "\\\\", UINT32_MAX);
230  retval += amxc_string_replace(string, "(", "\\(", UINT32_MAX);
231  retval += amxc_string_replace(string, ")", "\\)", UINT32_MAX);
232  retval += amxc_string_replace(string, "{", "\\{", UINT32_MAX);
233  retval += amxc_string_replace(string, "}", "\\}", UINT32_MAX);
234  retval += amxc_string_replace(string, "\"", "\\\"", UINT32_MAX);
235  retval += amxc_string_replace(string, "'", "\\'", UINT32_MAX);
236  retval += amxc_string_replace(string, "\n", "\\n", UINT32_MAX);
237  retval += amxc_string_replace(string, "\t", "\\t", UINT32_MAX);
238 
239  return retval;
240 }
241 
243  const amxc_var_t* const data) {
244  int changes = 0;
245  int total = 0;
246  do {
247  total += changes;
248  changes = 0;
249  changes += amxc_string_resolve_env(string);
250  changes += amxc_string_resolve_var(string, data);
251  } while(changes > 0);
252 
253  total += amxc_string_resolve_esc(string);
254 
255  return total;
256 }
257 
259  const char* text,
260  const amxc_var_t* const data) {
261  int retval = 0;
262  size_t length = 0;
263  size_t i = 0;
264 
265  when_null(text, exit);
266  when_true(*text == 0, exit);
267  when_null(string, exit);
268 
269  amxc_string_reset(string);
270  length = strlen(text);
271  for(i = 0; i < length; i++) {
272  if(text[i] == '$') {
273  break;
274  }
275  }
276 
277  if(i < length) {
278  amxc_string_appendf(string, "%s", text);
279  retval = amxc_string_resolve(string, data);
280  if(retval == 0) {
281  amxc_string_reset(string);
282  }
283  }
284 
285 exit:
286  return retval;
287 }
288 
290  const char* text,
291  const amxc_var_t* const data) {
292  int retval = -1;
293 
294  when_null(string, exit);
295  when_failed(amxc_string_new(string, 0), exit);
296 
297  retval = amxc_string_set_resolved(*string, text, data);
298  if(retval == 0) {
299  amxc_string_delete(string);
300  }
301 
302 exit:
303  return retval;
304 }
305 
307  const char* text) {
308  amxc_llist_it_t* it = NULL;
309  amxc_string_t* string = NULL;
310 
311  when_null(llist, exit);
312  when_null(text, exit);
313 
314  when_failed(amxc_string_new(&string, 0), exit);
315  when_failed(amxc_string_append(string, text, strlen(text)), exit);
316  amxc_llist_append(llist, &string->it);
317 
318  it = &string->it;
319 
320 exit:
321  if(it == NULL) {
322  amxc_string_delete(&string);
323  }
324  return it;
325 }
326 
329  amxc_string_delete(&part);
330 }
#define when_failed(x, l)
Definition: amxc_macros.h:142
#define when_true(x, l)
Definition: amxc_macros.h:134
#define when_null(x, l)
Definition: amxc_macros.h:126
#define UNUSED
Definition: amxc_macros.h:70
Ambiorix string API header file.
void(* amxc_string_replace_cb_t)(amxc_string_t *const string, size_t pos, size_t length, const char *txt, const void *priv)
Definition: amxc_utils.c:66
static void amxc_string_resolve_replace_env(amxc_string_t *const string, size_t pos, size_t length, const char *txt, UNUSED const void *priv)
Definition: amxc_utils.c:72
static int amxc_string_generic_resolve(amxc_string_t *const string, const char *start_string, const char *end_string, amxc_string_replace_cb_t fn, const void *priv)
Definition: amxc_utils.c:102
static void amxc_string_resolve_replace_var(amxc_string_t *const string, size_t pos, size_t length, const char *txt, const void *priv)
Definition: amxc_utils.c:84
Ambiorix variant API header file.
#define cstring_t
Convenience macro.
Definition: amxc_variant.h:584
int amxc_llist_append(amxc_llist_t *const llist, amxc_llist_it_t *const it)
Adds an item to the end of the linked list.
Definition: amxc_llist.c:169
amxc_llist_it_t * amxc_llist_add_string(amxc_llist_t *const llist, const char *text)
Adds a string (char*) to a linked list of amxc_string_t structures.
Definition: amxc_utils.c:306
int amxc_string_set_resolved(amxc_string_t *string, const char *text, const amxc_var_t *const data)
Sets the resolved string.
Definition: amxc_utils.c:258
int amxc_string_esc(amxc_string_t *const string)
Add escape characters to a string.
Definition: amxc_utils.c:226
int amxc_string_new_resolved(amxc_string_t **string, const char *text, const amxc_var_t *const data)
Sets the resolved string.
Definition: amxc_utils.c:289
int amxc_string_resolve_var(amxc_string_t *const string, const amxc_var_t *const data)
Resolves variant path variables.
Definition: amxc_utils.c:164
int amxc_string_resolve(amxc_string_t *const string, const amxc_var_t *const data)
Resolves variant paths and environment variables.
Definition: amxc_utils.c:242
void amxc_string_list_it_free(amxc_llist_it_t *it)
Helper function to delete an item in a linked list.
Definition: amxc_utils.c:327
int amxc_string_resolve_esc(amxc_string_t *const string)
Resolves escaped characters in a string.
Definition: amxc_utils.c:183
int amxc_string_resolve_env(amxc_string_t *const string)
Resolves environment variables.
Definition: amxc_utils.c:148
void amxc_string_delete(amxc_string_t **string)
Frees the previously allocated string.
Definition: amxc_string.c:150
AMXC_INLINE size_t amxc_string_buffer_length(const amxc_string_t *const string)
Gets the current size of the allocate string buffer.
Definition: amxc_string.h:976
int amxc_string_push_buffer(amxc_string_t *const string, char *buffer, size_t length)
Sets the string buffer.
Definition: amxc_string.c:372
AMXC_INLINE int amxc_string_append(amxc_string_t *const string, const char *const text, const size_t length)
Appends text to the end of the current content of the string buffer.
Definition: amxc_string.h:920
#define amxc_string_from_llist_it(ll_it)
Get the pointer to a string structure from an amxc linked list iterator.
Definition: amxc_string.h:95
int amxc_string_replace(amxc_string_t *const string, const char *needle, const char *newstr, uint32_t max)
Replaces a number of sub-string occurrences in a string.
Definition: amxc_string.c:789
void amxc_string_reset(amxc_string_t *const string)
Resets the buffer, reset the content to all 0.
Definition: amxc_string.c:203
AMXC_INLINE int amxc_string_insert_at(amxc_string_t *const string, const size_t pos, const char *text, size_t length)
Inserts a string of the given length into a string at a certain position.
Definition: amxc_string.h:1035
int amxc_string_new(amxc_string_t **string, const size_t length)
Allocates a string.
Definition: amxc_string.c:118
AMXC_INLINE size_t amxc_string_text_length(const amxc_string_t *const string)
Gets the current size of the used string buffer.
Definition: amxc_string.h:997
int amxc_string_init(amxc_string_t *const string, const size_t length)
Initializes a string.
Definition: amxc_string.c:163
int amxc_string_appendf(amxc_string_t *const string, const char *fmt,...) __attribute__((format(printf
Appends a formatted string to a string.
int amxc_string_remove_at(amxc_string_t *const string, const size_t pos, size_t length)
Removes part of the text in the string buffer.
Definition: amxc_string.c:314
AMXC_INLINE bool amxc_string_is_empty(const amxc_string_t *const string)
Checks if the string is empty.
Definition: amxc_string.h:1015
void amxc_string_clean(amxc_string_t *const string)
Frees the string buffer and reset length attributes.
Definition: amxc_string.c:189
char * amxc_string_take_buffer(amxc_string_t *const string)
Takes the string buffer.
Definition: amxc_string.c:356
#define AMXC_VAR_FLAG_DEFAULT
The default flag, do not copy, use variant as is.
Definition: amxc_variant.h:392
#define AMXC_VAR_ID_HTABLE
Ambiorix Hash Table variant id.
Definition: amxc_variant.h:212
uint32_t amxc_var_type_of(const amxc_var_t *const var)
Gets the variant type id of a variant.
Definition: amxc_variant.c:668
amxc_var_t * amxc_var_get_path(const amxc_var_t *const var, const char *const path, const int flags)
Retrieves the variant at the given path of a composite variant.
Definition: amxc_variant.c:573
#define amxc_var_dyncast(type, var)
Dynamic cast a variant to a certain type.
Definition: amxc_variant.h:678
The linked list iterator structure.
Definition: amxc_llist.h:215
The linked list structure.
Definition: amxc_llist.h:228
The string structure.
Definition: amxc_string.h:103
char * buffer
Definition: amxc_string.h:104
amxc_llist_it_t it
Definition: amxc_string.h:108
size_t last_used
Definition: amxc_string.h:106
The variant struct definition.
Definition: amxc_variant.h:861
char data[]
static amxc_htable_it_t it[2000]
static amxc_llist_t * llist