Adaptive Framework  0.9.0
All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
afw_function_list.c
Go to the documentation of this file.
1 // See the 'COPYING' file in the project root for licensing information.
2 /*
3  * afw_function_execute_* functions for List
4  *
5  * Copyright (c) 2010-2023 Clemson University
6  *
7  */
8 
14 #include "afw_internal.h"
15 
16 
17 
18 /*
19  * Adaptive function: add_entries
20  *
21  * afw_function_execute_add_entries
22  *
23  * See afw_function_bindings.h for more information.
24  *
25  * Add the entries of one or more lists to another.
26  *
27  * This function is not pure, so it may return a different result
28  * given exactly the same parameters and has side effects.
29  *
30  * Declaration:
31  *
32  * ```
33  * function add_entries(
34  * target: list,
35  * source_1: list,
36  * ...source_rest: (list of list)
37  * ): list;
38  * ```
39  *
40  * Parameters:
41  *
42  * target - (list) Target list. This list must not be immutable.
43  *
44  * source - (1 or more list) Source list(s).
45  *
46  * Returns:
47  *
48  * (list) The modified target list.
49  */
50 const afw_value_t *
53 {
54  const afw_value_list_t *target;
55  const afw_value_list_t *source;
56  const afw_iterator_t *iterator;
57  const afw_value_t *value;
58  afw_size_t count;
59 
61 
62  for (count = 2; count <= x->argc; count++) {
64  for (iterator = NULL;;) {
66  source->internal, &iterator, x->p, x->xctx);
67  if (!value) {
68  break;
69  }
70  afw_list_add_value(target->internal, value, x->xctx);
71  }
72  }
73 
74  return (const afw_value_t *)target;
75 }
76 
77 
78 
79 /*
80  * Adaptive function: list
81  *
82  * afw_function_execute_list
83  *
84  * See afw_function_bindings.h for more information.
85  *
86  * Construct a list with 0 or more elements.
87  *
88  * This function is pure, so it will always return the same result
89  * given exactly the same parameters and has no side effects.
90  *
91  * Declaration:
92  *
93  * ```
94  * function list(
95  * ...values: (list of any)
96  * ): list;
97  * ```
98  *
99  * Parameters:
100  *
101  * values - (0 or more any dataType) A value can refer to any adaptable value
102  * belonging to any data type or a list expression. In the case of a list
103  * expression, indicated by "..." followed by an expression that results
104  * in a list, every element within that list is included in the newly
105  * created list.
106  *
107  * Returns:
108  *
109  * (list) The constructed list.
110  *
111  * Errors thrown:
112  *
113  * cast_error - value could not be converted
114  */
115 const afw_value_t *
118 {
119  afw_size_t n;
120  const afw_list_t *list;
121  const afw_list_t *l;
122  const afw_value_t * const * arg;
123  const afw_value_t *entry;
124  const afw_value_t *value;
125  const afw_iterator_t *iterator;
126 
127  /* Construct a new list with elements passed as arguments. */
128  list = afw_list_create_generic(x->p, x->xctx);
129  for (n = 1, arg = &x->argv[1]; n <= x->argc; n++, arg++) {
131 
132  /* If list expression, add each element of list. */
133  if (afw_value_is_list_expression(*arg)) {
134  value = afw_value_evaluate(*arg, x->p, x->xctx);
135  if (value) {
136  l = afw_value_as_list(value, x->xctx);
137  for (iterator = NULL;;) {
138  entry = afw_list_get_next_value(l, &iterator,
139  x->p, x->xctx);
140  if (!entry) {
141  break;
142  }
143  entry = afw_value_evaluate(entry, x->p, x->xctx);
144  afw_list_add_value(list, entry, x->xctx);
145  }
146  }
147  }
148 
149  /* If not a list expression, add evaluated argument as element. */
150  else {
151  entry = afw_value_evaluate(*arg, x->p, x->xctx);
152  afw_list_add_value(list, entry, x->xctx);
153  }
154 
156  }
157 
158  /* Return constructed list. */
159  return afw_value_create_list(list, x->p, x->xctx);
160 }
161 
162 
163 
164 /*
165  * @brief Adaptive Function includes<list>
166  * @param function struct for this function.
167  * @param argc number of values in argv.
168  * @param argv list of values.
169  * @param p to use for result.
170  * @param xctx of caller.
171  *
172  * Checks whether or not a list contains any value.
173  *
174  * This function is pure, so it will always return the same result
175  * given exactly the same parameters and has no side effects.
176  *
177  * Declaration:
178  *
179  * function includes<list>(
180  * list: list,
181  * searchElement: any,
182  * fromIndex?: integer
183  * ): boolean;
184  *
185  * Parameters:
186  *
187  * list - (<Type>) The list to search.
188  *
189  * searchElement - (any dataType) Element to find.
190  *
191  * fromIndex - (optional integer) Index in the list to start search.
192  *
193  * Returns:
194  *
195  * (boolean) Indicates if the element is found in list.
196  *
197  */
198 const afw_value_t *
201 {
202  const afw_value_list_t *list;
203  const afw_value_t *searchElement;
204  const afw_value_integer_t *fromIndex;
205  const afw_value_t *item;
206  afw_xctx_t *xctx;
207  afw_size_t index;
208  afw_size_t len;
209 
212  AFW_FUNCTION_EVALUATE_DATA_TYPE_PARAMETER(fromIndex, 3, integer);
213 
214  xctx = x->xctx;
215  index = 0;
216  len = afw_list_get_count(list->internal, xctx);
217 
218  if (fromIndex) {
219  index = abs((int)fromIndex->internal) % len;
220 
221  if (fromIndex->internal < 0 && index != 0) {
222  index = len - index;
223  }
224  }
225 
226  for ( ; index < len; index++) {
227  item = afw_list_get_entry_value(list->internal, index, x->p, xctx);
228 
229  if (afw_value_equal(item, searchElement, xctx)) {
230  return afw_value_true;
231  }
232  }
233 
234  return afw_value_false;
235 }
236 
237 /*
238  * Adaptive function: join
239  *
240  * afw_function_execute_join
241  *
242  * See afw_function_bindings.h for more information.
243  *
244  * Concatenate the string values of the elements of a list with a separator.
245  *
246  * This function is pure, so it will always return the same result
247  * given exactly the same parameters and has no side effects.
248  *
249  * Declaration:
250  *
251  * ```
252  * function join(
253  * value: list,
254  * separator?: string
255  * ): string;
256  * ```
257  *
258  * Parameters:
259  *
260  * value - (list) A list of values of any data type.
261  *
262  * separator - (optional string) The separator to use. If not specified, a
263  * comma (,) is used.
264  *
265  * Returns:
266  *
267  * (string) Joined list values.
268  */
269 const afw_value_t *
272 {
273  const afw_value_list_t *value;
274  const afw_value_string_t *separator;
275  const afw_utf8_t *sep;
276  const afw_iterator_t *iterator;
277  const afw_list_t *list_of_string;
278  const afw_utf8_t *s;
279  afw_size_t len;
280  afw_value_string_t *result;
281  afw_utf8_octet_t *c;
282 
284 
285  sep = &afw_s_a_comma;
288  sep = &separator->internal;
289  }
290 
291  /* Create list of strings and get len of all stings and separators. */
292  list_of_string = afw_list_convert_to_list_of_strings(value->internal,
293  x->p, x->xctx);
294  for (iterator = NULL, len = 0;;) {
295  s = afw_list_of_string_get_next(list_of_string, &iterator, x->xctx);
296  if (!s) {
297  break;
298  }
299  len += s->len + sep->len;
300  }
301 
302  /* If len > 0 adjust len for extra separator, make result and return. */
303  if (len > 0) {
304  len -= sep->len;
305  c = afw_pool_malloc(x->p, len, x->xctx);
306  result = afw_value_allocate_string(x->p, x->xctx);
307  result->internal.len = len;
308  result->internal.s = c;
309  for (iterator = NULL, len = 0;;) {
311  list_of_string, &iterator, x->xctx);
312  if (!s) {
313  break;
314  }
315 
316  /* If not first time, add separator. */
317  if (c != result->internal.s) {
318  memcpy(c, sep->s, sep->len);
319  c += sep->len;
320  }
321 
322  /* Add this string. */
323  memcpy(c, s->s, s->len);
324  c += s->len;
325  }
326  return (const afw_value_t *)result;
327  }
328 
329  /* If len is zero, return empty string. */
330  else {
331  return afw_value_empty_string;
332  }
333 }
334 
335 
336 
337 /*
338  * Adaptive function: reverse
339  *
340  * afw_function_execute_reverse
341  *
342  * See afw_function_bindings.h for more information.
343  *
344  * Reverse the order of the elements in a list. If the list is typed, the
345  * resulting list will be the same type.
346  *
347  * This function is pure, so it will always return the same result
348  * given exactly the same parameters and has no side effects.
349  *
350  * Declaration:
351  *
352  * ```
353  * function reverse(
354  * list: list
355  * ): list;
356  * ```
357  *
358  * Parameters:
359  *
360  * list - (list) A list to reverse.
361  *
362  * Returns:
363  *
364  * (list) A list with elements reversed.
365  */
366 const afw_value_t *
369 {
370  const afw_value_list_t *list;
371  const afw_list_t *result_list;
372  const afw_iterator_t *iterator;
373  const afw_value_t *value;
374  const afw_list_setter_t *setter;
375  const afw_data_type_t *data_type;
376 
378 
379  data_type = afw_list_get_data_type(list->internal, x->xctx);
380  result_list = afw_list_create_with_options(0, data_type, x->p, x->xctx);
381  setter = afw_list_get_setter(result_list, x->xctx);
382  for (iterator = NULL;;) {
383  value = afw_list_get_next_value(list->internal, &iterator,
384  x->p, x->xctx);
385  if (!value) break;
386  afw_list_setter_insert_value(setter, value, 0, x->xctx);
387  }
388  return afw_value_create_list(result_list, x->p, x->xctx);
389 }
390 
391 
392 
393 /*
394  * Adaptive function: slice
395  *
396  * afw_function_execute_slice
397  *
398  * See afw_function_bindings.h for more information.
399  *
400  * This function extracts a consecutive slice of values from a list.
401  *
402  * This function is pure, so it will always return the same result
403  * given exactly the same parameters and has no side effects.
404  *
405  * Declaration:
406  *
407  * ```
408  * function slice(
409  * list: list,
410  * startIndex?: integer,
411  * endIndex?: integer
412  * ): list;
413  * ```
414  *
415  * Parameters:
416  *
417  * list - (list) The list to slice.
418  *
419  * startIndex - (optional integer) This is the zero based starting index. Use
420  * negative number to index from the end of the list. If not specified,
421  * an index of 0 is assumed.
422  *
423  * endIndex - (optional integer) This is the zero based ending index. If
424  * positive, this is one more than the index of the last value to include
425  * in the list. If negative, the index is from the end of the list. If
426  * not specified, the slice is from startIndex up to and including the
427  * end of the list.
428  *
429  * Returns:
430  *
431  * (list) A list containing the selected values. If all of the values are the
432  * same data type, the list will be a list of that data type.
433  */
434 const afw_value_t *
437 {
438  const afw_value_list_t *list;
439  const afw_list_t *result_list;
440  const afw_value_integer_t *integer;
441  const afw_iterator_t *iterator;
442  const afw_value_t *value;
443  afw_integer_t start;
444  afw_integer_t end;
445  afw_integer_t count;
446 
448  count = (afw_integer_t)afw_list_get_count(list->internal, x->xctx);
449 
450  /* Determine start index. */
451  start = 0;
454  start = integer->internal;
455  if (start < 0) {
456  start = count + start;
457  if (start < 0) {
458  start = 0;
459  }
460  }
461  }
462 
463  /* Determine end index. */
464  end = count;
467  end = integer->internal;
468  if (end < 0) {
469  end = count + end;
470  }
471  else if (end > count) {
472  end = count;
473  }
474  }
475 
476  /* Create and return a list with slice. */
477  result_list = afw_list_create_generic(x->p, x->xctx);
478  for (iterator = NULL, count = 0; count < end; count++) {
479  value = afw_list_get_next_value(list->internal, &iterator,
480  x->p, x->xctx);
481  if (!value) {
482  AFW_THROW_ERROR_Z(general, "Expecting a value", x->xctx);
483  }
484  if (start <= count) {
485  afw_list_add_value(result_list, value, x->xctx);
486  }
487  }
489  return afw_value_create_list(result_list, x->p, x->xctx);
490 }
Adaptive Framework Core Internal.
afw_value_create_list(const afw_list_t *internal, const afw_pool_t *p, afw_xctx_t *xctx)
Create function for unmanaged data type list value.
afw_value_as_list(const afw_value_t *value, afw_xctx_t *xctx)
Typesafe cast of data type list.
afw_value_allocate_string(const afw_pool_t *p, afw_xctx_t *xctx)
Allocate function for unmanaged data type string value.
#define afw_list_of_string_get_next(list, iterator, xctx)
Get next value from list of string.
struct afw_iterator_s afw_iterator_t
char afw_utf8_octet_t
8 bits of utf-8 codepoint.
Definition: afw_common.h:236
apr_size_t afw_size_t
size_t.
Definition: afw_common.h:151
apr_int64_t afw_integer_t
typedef for big signed int.
Definition: afw_common.h:321
#define AFW_THROW_ERROR_Z(code, message_z, xctx)
Macro used to set error and 0 rv in xctx and throw it.
Definition: afw_error.h:283
#define AFW_FUNCTION_EVALUATE_DATA_TYPE_PARAMETER(A_RESULT, A_N, A_TYPE)
Evaluate an arg for a particular data type.
Definition: afw_function.h:261
#define AFW_FUNCTION_EVALUATE_REQUIRED_DATA_TYPE_PARAMETER(A_RESULT, A_N, A_TYPE)
Evaluate an arg for a particular data type.
Definition: afw_function.h:328
#define AFW_FUNCTION_PARAMETER_IS_PRESENT(A_N)
Determine if a specific parameter value is present.
Definition: afw_function.h:242
#define AFW_FUNCTION_EVALUATE_REQUIRED_PARAMETER(A_RESULT, A_N)
Evaluate an required parameter.
Definition: afw_function.h:295
const afw_value_t * afw_function_execute_reverse(afw_function_execute_t *x)
Adaptive Function reverse
const afw_value_t * afw_function_execute_slice(afw_function_execute_t *x)
Adaptive Function slice
const afw_value_t * afw_function_execute_join(afw_function_execute_t *x)
Adaptive Function join
const afw_value_t * afw_function_execute_add_entries(afw_function_execute_t *x)
Adaptive Function add_entries
const afw_value_t * afw_function_execute_list(afw_function_execute_t *x)
Adaptive Function list
const afw_value_t * afw_function_execute_includes_list(afw_function_execute_t *x)
Function implementation function afw_function_execute_includes_list.
#define afw_list_get_setter(instance, xctx)
Call method get_setter of interface afw_list.
#define afw_list_get_entry_value(instance, index, p, xctx)
Call method get_entry_value of interface afw_list.
#define afw_list_get_next_value(instance, iterator, p, xctx)
Call method get_next_value of interface afw_list.
#define afw_list_get_data_type(instance, xctx)
Call method get_data_type of interface afw_list.
#define afw_list_get_count(instance, xctx)
Call method get_count of interface afw_list.
#define afw_list_setter_insert_value(instance, value, index, xctx)
Call method insert_value of interface afw_list_setter.
afw_list_determine_data_type_and_set_immutable(const afw_list_t *instance, afw_xctx_t *xctx)
Set list to immutable and determine data type of entries.
Definition: afw_list.c:60
const afw_list_t * afw_list_convert_to_list_of_strings(const afw_list_t *list, const afw_pool_t *p, afw_xctx_t *xctx)
Convert a list to a list of strings.
#define afw_list_create_generic(p, xctx)
Create an value list in memory.
Definition: afw_list.h:81
afw_list_add_value(const afw_list_t *instance, const afw_value_t *value, afw_xctx_t *xctx)
Call method add_value of interface afw_list_setter.
Definition: afw_list.c:104
const afw_list_t * afw_list_create_with_options(int options, const afw_data_type_t *data_type, const afw_pool_t *p, afw_xctx_t *xctx)
Create an list in memory with options.
#define afw_pool_malloc(instance, size, xctx)
Call method malloc of interface afw_pool.
#define afw_value_is_list_expression(A_VALUE)
Macro to determine if value is a list expression.
Definition: afw_value.h:640
#define afw_value_evaluate(value, p, xctx)
Evaluate value if needed using specific pool.
Definition: afw_value.h:841
afw_value_equal(const afw_value_t *value1, const afw_value_t *value2, afw_xctx_t *xctx)
Test whether two values are equal.
Definition: afw_value.c:851
afw_value_false
Adaptive value false.
Definition: afw_value.h:354
afw_value_empty_string
Adaptive value empty string.
Definition: afw_value.h:342
afw_value_true
Adaptive value true.
Definition: afw_value.h:348
#define afw_xctx_evaluation_stack_pop_parameter_number(xctx)
Pop top PARAMETER_NUMBER off execution stack.
Definition: afw_xctx.h:124
#define afw_xctx_evaluation_stack_push_parameter_number(PARAMETER_NUMBER, xctx)
Push PARAMETER_NUMBER onto execution stack.
Definition: afw_xctx.h:88
Interface afw_data_type public struct.
Function execute parameter.
Definition: afw_function.h:53
const afw_value_t *const * argv
This is the function parameters.
Definition: afw_function.h:86
afw_xctx_t * xctx
The execution context (xctx) of caller.
Definition: afw_function.h:62
const afw_pool_t * p
Pool for result.
Definition: afw_function.h:59
afw_size_t argc
This is the argv count not counting argv[0].
Definition: afw_function.h:89
Interface afw_list public struct.
Interface afw_list_setter public struct.
NFC normalized UTF-8 string.
Definition: afw_common.h:545
struct for data type integer values.
struct for data type list values.
Interface afw_value public struct.
struct for data type string values.
Interface afw_xctx public struct.