Adaptive Framework  0.9.0
All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
afw_list_memory.c
Go to the documentation of this file.
1 // See the 'COPYING' file in the project root for licensing information.
2 /*
3  * Implementation of afw_list interface
4  *
5  * Copyright (c) 2010-2023 Clemson University
6  *
7  */
8 
9 
15 #include "afw_internal.h"
16 
17 
18 
19 #define impl_afw_list_get_entry_meta afw_list_impl_get_entry_meta
20 #define impl_afw_list_get_next_entry_meta afw_list_impl_get_next_entry_meta
21 
22 /* Declares and rti/inf defines for interface afw_list */
23 #define AFW_IMPLEMENTATION_ID "memory"
24 #include "afw_list_impl_declares.h"
26 
27 typedef struct afw_memory_internal_list_s
29 
32 
33 typedef struct afw_memory_internal_list_ring_s
34 afw_memory_internal_list_ring_t;
35 
37  APR_RING_ENTRY(afw_memory_internal_list_entry_s) link;
38  const afw_value_t *value;
39 };
40 
41 APR_RING_HEAD(afw_memory_internal_list_ring_s,
43 
45  afw_list_t pub;
46  const afw_pool_t *p;
47  const afw_data_type_t *data_type;
48  afw_list_setter_t setter;
49  afw_memory_internal_list_ring_t *ring;
50  afw_boolean_t immutable;
51  afw_boolean_t generic;
52 };
53 
54 
55 AFW_DEFINE(const afw_list_t *)
57  int options,
58  const afw_data_type_t *data_type,
59  const afw_pool_t *p,
60  afw_xctx_t *xctx)
61 {
62 
64  afw_memory_internal_list_ring_t *ring;
65 
66  /* Allocate memory for self. */
68 
69  /* Allocate memory for value list ring container. */
70  ring = afw_pool_calloc_type(p, afw_memory_internal_list_ring_t, xctx);
71 
72  /* Initialize self. */
73  self->pub.inf = &impl_afw_list_inf;
74  self->p = p;
75  self->data_type = data_type;
76  self->generic = data_type == NULL;
77  APR_RING_INIT(ring, afw_memory_internal_list_entry_s, link);
78  self->ring = ring;
79  self->setter.inf = &impl_afw_list_setter_inf;
80  self->setter.list = (const afw_list_t *)self;
81 
82  /* Return new object. */
83  return (const afw_list_t *)self;
84 
85 }
86 
87 
88 
89 /*
90  * Implementation of method release of interface afw_list.
91  */
92 void
94  const afw_list_t * instance,
95  afw_xctx_t *xctx) {
96 
97  /*
98  * Continue release, even if there is already an error. Don't overwrite
99  * existing error.
100  */
101 
102  /*
103  * Storage for value list is allocated in the pool provided, so nothing
104  * needs to be done.
105  */
106 }
107 
108 
109 
110 /*
111  * Implementation of method get_count for interface afw_list.
112  */
115  const afw_list_t * instance,
116  afw_xctx_t *xctx)
117 {
120  afw_size_t count;
121 
122  count = 0;
123  APR_RING_FOREACH(ep, self->ring, afw_memory_internal_list_entry_s,
124  link)
125  {
126  count++;
127  }
128 
129  return count;
130 }
131 
132 
133 
134 /*
135  * Implementation of method get_data_type for interface afw_list.
136  */
137 const afw_data_type_t *
139  const afw_list_t * instance,
140  afw_xctx_t *xctx)
141 {
143 
144  return self->data_type;
145 }
146 
147 
148 
149 /*
150  * Implementation of method get_entry_internal for interface afw_list.
151  */
154  const afw_list_t * instance,
155  afw_integer_t index,
156  const afw_data_type_t * * data_type,
157  const void * * internal,
158  afw_xctx_t *xctx)
159 {
160  const afw_value_t *value;
161 
162  value = impl_afw_list_get_entry_value(instance, index, NULL, xctx);
163  if (value) {
164  *internal = AFW_VALUE_INTERNAL(value);
165  if (data_type) {
166  *data_type = afw_value_get_data_type(value, xctx);
167  }
168  return true;
169  }
170  else {
171  *internal = NULL;
172  if (data_type) {
173  *data_type = NULL;
174  }
175  return false;
176  }
177 }
178 
179 
180 
181 /*
182  * Implementation of method get_entry_value for interface afw_list.
183  */
184 const afw_value_t *
186  const afw_list_t * instance,
187  afw_integer_t index,
188  const afw_pool_t * p,
189  afw_xctx_t *xctx)
190 {
193  afw_size_t count;
194  const afw_value_t *value;
195  afw_size_t i;
196 
197  /* Return NULL if negative index or it doesn't fit in afw_size_t. */
198  i = (afw_size_t)index;
199  if (index < 0 || i != index) {
200  return NULL;
201  }
202 
203  count = 0;
204  value = NULL;
205  APR_RING_FOREACH(ep, self->ring, afw_memory_internal_list_entry_s,
206  link)
207  {
208  if (count >= i) {
209  value = ep->value;
210  break;
211  }
212  count++;
213  }
214 
215  return value;
216 }
217 
218 
219 
220 /*
221  * Implementation of method get_next_internal for interface afw_list.
222  */
225  const afw_list_t * instance,
226  const afw_iterator_t * * iterator,
227  const afw_data_type_t * * data_type,
228  const void * * internal,
229  afw_xctx_t *xctx)
230 {
233 
234  /* If iterator is NULL, locate first else locate next and update iterator. */
235  if (!*iterator) {
236  ep = APR_RING_FIRST(self->ring);
237  }
238  else {
239  ep = (afw_memory_internal_list_entry_t *)*iterator;
240  ep = APR_RING_NEXT(ep, link);
241  }
242  *iterator = (afw_iterator_t *)ep;
243 
244 
245  /* If sentinel, return !found. */
246  if (ep == APR_RING_SENTINEL(self->ring,
248  {
249  *internal = NULL;
250  if (data_type) {
251  *data_type = NULL;
252  }
253  return false;
254  }
255 
256  /* Return next value. */
257  *iterator = (afw_iterator_t *)ep;
258  *internal = AFW_VALUE_INTERNAL(ep->value);
259  if (data_type) {
260  *data_type = afw_value_get_data_type(ep->value, xctx);
261 
262  }
263  return true;
264 }
265 
266 
267 
268 /*
269  * Implementation of method get_next_value for interface afw_list.
270  */
271 const afw_value_t *
273  const afw_list_t * instance,
274  const afw_iterator_t * * iterator,
275  const afw_pool_t * p,
276  afw_xctx_t *xctx)
277 {
280 
281  /* If iterator is NULL, locate first else locate next and update iterator. */
282  if (!*iterator) {
283  ep = APR_RING_FIRST(self->ring);
284  }
285  else {
286  ep = (afw_memory_internal_list_entry_t *)*iterator;
287  ep = APR_RING_NEXT(ep, link);
288  }
289 
290  /* If sentinel, return !found. */
291  if (ep == APR_RING_SENTINEL(self->ring,
293  {
294  *iterator = NULL;
295  return NULL;
296  }
297 
298  /* Return next value. */
299  *iterator = (afw_iterator_t *)ep;
300  return ep->value;
301 }
302 
303 
304 
305 /*
306  * Implementation of method get_setter for interface afw_list.
307  */
308 const afw_list_setter_t *
310  const afw_list_t * instance,
311  afw_xctx_t *xctx)
312 {
314 
315  return (self->immutable) ? NULL : &self->setter;
316 }
317 
318 
319 
320 /*
321  * Implementation of method set_immutable for interface afw_list_setter.
322  */
323 void
324 impl_afw_list_setter_set_immutable(
325  const afw_list_setter_t * instance,
326  afw_xctx_t *xctx)
327 {
329  (afw_memory_internal_list_t *)((afw_list_setter_t *)instance)->list;
330 
331  self->immutable = true;
332 }
333 
334 
335 
336 /*
337  * Implementation of method determine_data_type_and_set_immutable for
338  * interface afw_list_setter.
339  */
340 const afw_data_type_t *
341 impl_afw_list_setter_determine_data_type_and_set_immutable(
342  const afw_list_setter_t * instance,
343  afw_xctx_t *xctx)
344 {
346  (afw_memory_internal_list_t *)((afw_list_setter_t *)instance)->list;
348 
349  /* Make immutable if not already. */
350  if (self->immutable) {
351  AFW_LIST_ERROR_OBJECT_IMMUTABLE;
352  }
353  self->immutable = true;
354 
355  /* If data type not known yet, try to determine it. */
356  if (!self->data_type) {
357  for (ep = APR_RING_FIRST(self->ring);
358  ep != APR_RING_SENTINEL(self->ring,
360  ep = APR_RING_NEXT(ep, link))
361  {
362  if (!self->data_type) {
363  self->data_type =
364  afw_value_get_data_type(ep->value, xctx);
365  }
366  else {
367  if (self->data_type !=
368  afw_value_get_data_type(ep->value, xctx))
369  {
370  self->data_type = NULL;
371  break;
372  }
373  }
374  }
375  }
376 
377  /* Return next value. */
378  return self->data_type;
379 }
380 
381 
382 
383 /*
384  * Implementation of method add_internal for interface afw_list_setter.
385  */
386 void
387 impl_afw_list_setter_add_internal(
388  const afw_list_setter_t * instance,
389  const afw_data_type_t *data_type,
390  const void * internal,
391  afw_xctx_t *xctx)
392 {
394  (afw_memory_internal_list_t *)((afw_list_setter_t *)instance)->list;
395  const afw_value_t *value;
396 
397  value = afw_value_evaluated_create(internal, data_type, self->p, xctx);
398  impl_afw_list_setter_add_value(instance, value, xctx);
399 }
400 
401 
402 /*
403  * Implementation of method add_value of interface afw_list_setter.
404  */
405 void
406 impl_afw_list_setter_add_value(
407  const afw_list_setter_t * instance,
408  const afw_value_t * value,
409  afw_xctx_t *xctx)
410 {
412  (afw_memory_internal_list_t *)((afw_list_setter_t *)instance)->list;
414 
415  /*
416  * If generic, set data type on first entry and set to NULL if any entry
417  * after that has a different data type.
418  */
419  if (self->generic) {
420  if (APR_RING_EMPTY(self->ring, afw_memory_internal_list_entry_s, link))
421  {
422  if (value) {
423  self->data_type = afw_value_get_data_type(value, xctx);;
424  }
425  }
426  else if (
427  !value ||
428  (self->data_type &&
429  self->data_type != afw_value_get_data_type(value, xctx)))
430  {
431  self->data_type = NULL;
432  }
433  }
434 
435  /* If not generic, make sure data type of value is okay. */
436  else if (self->data_type && self->data_type !=
437  afw_value_get_data_type(value, xctx))
438  {
439  AFW_THROW_ERROR_Z(general,
440  "Value data_type is not list's data type.", xctx);
441  }
442 
443  /* Add value. */
445  ep->value = value;
446  APR_RING_INSERT_TAIL(self->ring, ep, afw_memory_internal_list_entry_s, link);
447 }
448 
449 
450 
451 /*
452  * Implementation of method insert_internal for interface afw_list_setter.
453  */
454 void
455 impl_afw_list_setter_insert_internal(
456  const afw_list_setter_t * instance,
457  const afw_data_type_t * data_type,
458  const void * internal,
459  afw_size_t index,
460  afw_xctx_t *xctx)
461 {
463  (afw_memory_internal_list_t *)((afw_list_setter_t *)instance)->list;
464  const afw_value_t *value;
465 
466  value = afw_value_evaluated_create(internal, data_type, self->p, xctx);
467  impl_afw_list_setter_insert_value(instance, value, index, xctx);
468 }
469 
470 
471 
472 /*
473  * Implementation of method insert_value for interface afw_list_setter.
474  */
475 void
476 impl_afw_list_setter_insert_value(
477  const afw_list_setter_t * instance,
478  const afw_value_t * value,
479  afw_size_t index,
480  afw_xctx_t *xctx)
481 {
483  (afw_memory_internal_list_t *)((afw_list_setter_t *)instance)->list;
486  afw_size_t count;
487 
488  /* Add value. */
490  nep->value = value;
491 
492  /*
493  * If generic, set data type on first entry and set to NULL if any entry
494  * after that has a different data type.
495  */
496  if (self->generic) {
497  if (APR_RING_EMPTY(self->ring, afw_memory_internal_list_entry_s, link))
498  {
499  self->data_type = afw_value_get_data_type(value, xctx);;
500  }
501  else if (
502  self->data_type &&
503  self->data_type != afw_value_get_data_type(value, xctx))
504  {
505  self->data_type = NULL;
506  }
507  }
508 
509  /* If not generic, make sure data type of value is okay. */
510  else if (self->data_type && self->data_type !=
511  afw_value_get_data_type(value, xctx))
512  {
513  AFW_THROW_ERROR_Z(general,
514  "Value data_type is not list's data type.", xctx);
515  }
516 
517  /* If index is 0, insert at head. */
518  if (index == 0) {
519  APR_RING_INSERT_HEAD(self->ring, nep, afw_memory_internal_list_entry_s, link);
520  return;
521  }
522 
523  /* Insert before the current entry at index if not past end. */
524  count = 0;
525  APR_RING_FOREACH(lep, self->ring, afw_memory_internal_list_entry_s,
526  link)
527  {
528  if (index == count) {
529  APR_RING_INSERT_BEFORE(lep, nep, link);
530  return;
531  }
532  count++;
533  }
534 
535  /* If index past end, insert at tail. */
536  APR_RING_INSERT_TAIL(self->ring, nep, afw_memory_internal_list_entry_s, link);
537 }
538 
539 
540 
541 /*
542  * Implementation of method remove_all_values of interface afw_list_setter.
543  */
544 void
545 impl_afw_list_setter_remove_all_values(
546  const afw_list_setter_t * instance,
547  afw_xctx_t *xctx)
548 
549 {
551  (afw_memory_internal_list_t *)((afw_list_setter_t *)instance)->list;
552 
553  /* Clear list. */
554  APR_RING_INIT(self->ring, afw_memory_internal_list_entry_s, link);
555 
556  /* If generic, clear data type. */
557  if (self->generic) {
558  self->data_type = NULL;
559  }
560 }
561 
562 
563 
564 /*
565  * Implementation of method remove_internal for interface afw_list_setter.
566  */
567 void
568 impl_afw_list_setter_remove_internal(
569  const afw_list_setter_t * instance,
570  const afw_data_type_t *data_type,
571  const void * internal,
572  afw_xctx_t *xctx)
573 {
575  (afw_memory_internal_list_t *)((afw_list_setter_t *)instance)->list;
577 
578  /* Search for matching value. If found, remove it. */
579  APR_RING_FOREACH(ep, self->ring, afw_memory_internal_list_entry_s,
580  link)
581  {
582  if (afw_value_get_data_type(ep->value, xctx) == data_type &&
583  memcmp(
584  &((const afw_value_evaluated_t *)ep->value)->internal,
585  internal, data_type->c_type_size) == 0)
586  {
587  APR_RING_REMOVE(ep, link);
588  return;
589  }
590  }
591 
592  AFW_THROW_ERROR_Z(general, "Value not in list", xctx);
593 }
594 
595 
596 
597 /*
598  * Implementation of method remove_value of interface afw_list_setter.
599  */
600 void
601 impl_afw_list_setter_remove_value(
602  const afw_list_setter_t * instance,
603  const afw_value_t * value,
604  afw_xctx_t *xctx)
605 {
607  (afw_memory_internal_list_t *)((afw_list_setter_t *)instance)->list;
609 
610  /* Search for matching value. If found, remove it. */
611  APR_RING_FOREACH(ep, self->ring, afw_memory_internal_list_entry_s,
612  link)
613  {
614  if (afw_value_equal(value, ep->value, xctx)) {
615  APR_RING_REMOVE(ep, link);
616  /* If generic and no more entries, set data type to NULL. */
617  if (self->generic &&
618  APR_RING_EMPTY(self->ring,
620  {
621  self->data_type = NULL;
622  }
623  return;
624  }
625  }
626 
627  AFW_THROW_ERROR_Z(general, "Value not in list", xctx);
628 }
629 
630 
631 
632 /*
633  * Implementation of method set_value_by_index for interface afw_list_setter.
634  */
635 void
637  const afw_list_setter_t *instance,
638  afw_size_t index,
639  const afw_value_t *value,
640  afw_xctx_t *xctx)
641 {
643  (afw_memory_internal_list_t *)((afw_list_setter_t *)instance)->list;
645  afw_size_t count;
646 
647  /*
648  * If generic, set data type on first entry and set to NULL if any entry
649  * after that has a different data type.
650  */
651  if (self->generic) {
652  if (APR_RING_EMPTY(self->ring, afw_memory_internal_list_entry_s, link))
653  {
654  self->data_type = afw_value_get_data_type(value, xctx);;
655  }
656  else if (
657  self->data_type &&
658  self->data_type != afw_value_get_data_type(value, xctx))
659  {
660  self->data_type = NULL;
661  }
662  }
663 
664  /* If not generic, make sure data type of value is okay. */
665  else if (self->data_type && self->data_type !=
666  afw_value_get_data_type(value, xctx))
667  {
668  AFW_THROW_ERROR_Z(general,
669  "Value data_type is not list's data type.", xctx);
670  }
671 
672  /* Insert before the current entry at index if not past end. */
673  count = 0;
674  APR_RING_FOREACH(lep, self->ring, afw_memory_internal_list_entry_s,
675  link)
676  {
677  if (index == count) {
679  lep->value = value;
680  return;
681  }
682  count++;
683  }
684 
685  /* Throw error if index past end. */
686  AFW_THROW_ERROR_Z(general, "Index out of bounds", xctx);
687 }
688 
689 
690 /* Create or clone of a list. */
691 AFW_DEFINE(const afw_list_t *)
693  const afw_list_t *list,
694  const afw_data_type_t *data_type,
695  afw_boolean_t clone_values,
696  const afw_pool_t *p, afw_xctx_t *xctx)
697 {
698  const afw_iterator_t *iterator;
699  const afw_list_t *result;
700  const afw_value_t *value;
701  const afw_data_type_t *use_data_type;
702 
703  use_data_type = data_type;
704  if (list) {
705  use_data_type = afw_list_get_data_type(list, xctx);
706  if (data_type && use_data_type && data_type != use_data_type)
707  {
708  AFW_THROW_ERROR_Z(general, "data_type does not match", xctx);
709  }
710  }
711  result = afw_list_of_create(use_data_type, p, xctx);
712  if (list) for (iterator = NULL;;)
713  {
714  value = afw_list_get_next_value(list, &iterator, p, xctx);
715  if (!value) {
716  break;
717  }
718  if (clone_values) {
719  value = afw_value_clone(value, p, xctx);
720  }
721  afw_list_add_value(result, value, xctx);
722  }
723 
724  return result;
725 }
726 
727 
728 
729 /* Create a typed list from a value. */
730 AFW_DEFINE(const afw_list_t *)
732  const afw_data_type_t *data_type,
733  const afw_value_t *value,
734  const afw_pool_t *p, afw_xctx_t *xctx)
735 {
736  const afw_data_type_t *value_data_type;
737  const afw_list_t *value_list;
738  const afw_list_t *old_list;
739  const afw_iterator_t *iterator;
740  const afw_value_t *v;
741 
742  value_data_type = afw_value_get_data_type(value, xctx);
743 
744  if (value_data_type == afw_data_type_list) {
745  value_list = ((afw_value_list_t *)value)->internal;
746  value_data_type = afw_list_get_data_type(value_list, xctx);
747  if (value_data_type != data_type) {
748  old_list = value_list;
749  value_list = afw_list_of_create(data_type, p, xctx);
750  for (iterator = NULL;;) {
751  v = afw_list_get_next_value(old_list, &iterator, p, xctx);
752  if (!v) {
753  break;
754  }
755  v = afw_value_convert(v, data_type, true, p, xctx);
756  afw_list_add_value(value_list, v, xctx);
757  }
758  }
759  }
760  else {
761  v = afw_value_convert(value, data_type, true, p, xctx);
763  AFW_VALUE_INTERNAL(v), false, data_type, 1, p, xctx);
764  }
765 
766  return value_list;
767 }
AFW_DEFINE(const afw_object_t *)
Adaptive Framework Core Internal.
Interface afw_interface implementation declares.
Interface afw_interface implementation declares.
afw_data_type_list
Data type struct for list.
struct afw_iterator_s afw_iterator_t
_Bool afw_boolean_t
Definition: afw_common.h:373
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
impl_afw_list_get_next_value(const afw_list_t *instance, const afw_iterator_t **iterator, const afw_pool_t *p, afw_xctx_t *xctx)
impl_afw_list_get_entry_internal(const afw_list_t *instance, afw_integer_t index, const afw_data_type_t **data_type, const void **internal, afw_xctx_t *xctx)
impl_afw_list_get_data_type(const afw_list_t *instance, afw_xctx_t *xctx)
impl_afw_list_release(const afw_list_t *instance, afw_xctx_t *xctx)
impl_afw_list_get_next_internal(const afw_list_t *instance, const afw_iterator_t **iterator, const afw_data_type_t **data_type, const void **internal, afw_xctx_t *xctx)
impl_afw_list_get_setter(const afw_list_t *instance, afw_xctx_t *xctx)
impl_afw_list_get_count(const afw_list_t *instance, afw_xctx_t *xctx)
impl_afw_list_get_entry_value(const afw_list_t *instance, afw_integer_t index, const afw_pool_t *p, afw_xctx_t *xctx)
#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.
void impl_afw_list_setter_set_value_by_index(const afw_list_setter_t *instance, afw_size_t index, const afw_value_t *value, afw_xctx_t *xctx)
afw_list_create_wrapper_for_array(const void *array, afw_boolean_t indirect, const afw_data_type_t *data_type, afw_size_t count, const afw_pool_t *p, afw_xctx_t *xctx)
Create a immutable list wrapper for an array.
afw_list_create_or_clone(const afw_list_t *list, const afw_data_type_t *data_type, afw_boolean_t clone_values, const afw_pool_t *p, afw_xctx_t *xctx)
Create a clone of a list in memory.
afw_list_of_create_from_value(const afw_data_type_t *data_type, const afw_value_t *value, const afw_pool_t *p, afw_xctx_t *xctx)
Create a typed list from a value.
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
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_list_of_create(data_type, p, xctx)
Create an list of a specific data type in memory.
Definition: afw_list.h:64
#define afw_pool_calloc_type(instance, type, xctx)
Macro to allocate cleared memory to hold type in pool.
Definition: afw_pool.h:167
#define afw_value_get_data_type(instance, xctx)
Call method get_data_type of interface afw_value.
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_clone(const afw_value_t *value, const afw_pool_t *p, afw_xctx_t *xctx)
Clone a value to specified pool.
Definition: afw_value.c:282
const afw_value_t * afw_value_evaluated_create(const void *value, const afw_data_type_t *data_type, const afw_pool_t *p, afw_xctx_t *xctx)
Create function for an evaluated data type value.
afw_value_convert(const afw_value_t *value, const afw_data_type_t *to_data_type, afw_boolean_t required, const afw_pool_t *p, afw_xctx_t *xctx)
Convert a value to a value/data type.
Definition: afw_value.c:584
#define AFW_VALUE_INTERNAL(_VALUE_)
Macro to get const void * of the internal of a value.
Definition: afw_value.h:856
Interface afw_data_type public struct.
Interface afw_list public struct.
Interface afw_list_setter public struct.
Interface afw_pool public struct.
Struct to access internal of all evaluated values.
Definition: afw_value.h:60
struct for data type list values.
Interface afw_value public struct.
Interface afw_xctx public struct.