Adaptive Framework  0.9.0
All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
afw_associative_array.c
Go to the documentation of this file.
1 // See the 'COPYING' file in the project root for licensing information.
2 /*
3  * Adaptive Framework Associative Array
4  *
5  * Copyright (c) 2010-2023 Clemson University
6  *
7  */
8 
14 #include "afw_internal.h"
15 
16 /* Self */
17 typedef struct impl_associative_array_s {
18 
19  const afw_pool_t *p;
20 
21  afw_associative_array_add_reference_value_cb add_reference_value;
22 
23  afw_associative_array_release_value_cb release_value;
24 
25  /* Hash table with key of key and value of object instance. */
26  apr_hash_t *values;
27 
28  /* Reference_count starting at 1 on create. */
29  AFW_ATOMIC afw_integer_t reference_count;
30 
32 
33 
34 
35 /* Create associative array. */
37 afw_associative_array_create(
38  afw_associative_array_add_reference_value_cb add_reference_value,
39  afw_associative_array_release_value_cb release_value,
40  const afw_pool_t *p, afw_xctx_t *xctx)
41 {
43  const afw_pool_t *new_p;
44 
45  /* Create new pool for object associative array. */
46  new_p = afw_pool_create(p, xctx);
47 
48  /* Allocate self and initialize. */
50  self->p = new_p;
51  self->reference_count = 1;
52  self->add_reference_value = add_reference_value;
53  self->release_value = release_value;
54  self->values = apr_hash_make(afw_pool_get_apr_pool(new_p));
55 
56  /*
57  * If either add_reference_value or release_value is specified,
58  * both must be specified.
59  */
60  if ((add_reference_value && !release_value) ||
61  (release_value && !add_reference_value))
62  {
63  AFW_THROW_ERROR_Z(general,
64  "If either add_reference_value or release_value is specified, "
65  "both must be specified.",
66  xctx);
67  }
68 
69  /* Return new instance. */
70  return (const afw_associative_array_t *)self;
71 }
72 
73 
74 /* Release. */
75 AFW_DEFINE(void)
76 afw_associative_array_release (
77  const afw_associative_array_t * instance,
78  afw_xctx_t *xctx)
79 {
81  apr_hash_index_t *hi;
82  const void *key;
83  apr_ssize_t klen;
84  void *value;
85 
86  /* Decrement reference count and release value and array's pool if zero. */
87  if (afw_atomic_integer_decrement(&self->reference_count) == 0) {
88 
89  /* If there is a release_value(), call it for each value. */
90  if (self->release_value) {
91  for (hi = apr_hash_first(
92  afw_pool_get_apr_pool(instance->p), self->values);
93  hi;
94  hi = apr_hash_next(hi))
95  {
96  apr_hash_this(hi, &key, &klen, (void **)&value);
97  self->release_value(value, xctx);
98  }
99  }
100 
101  /* Release pool. */
102  afw_pool_release(instance->p, xctx);
103  }
104 }
105 
106 
107 
108 /* Add reference. */
109 AFW_DEFINE(void)
110 afw_associative_array_add_reference (
111  const afw_associative_array_t *instance,
112  afw_xctx_t *xctx)
113 {
115 
116  /* Increment reference count. */
117  afw_atomic_integer_increment(&self->reference_count);
118 }
119 
120 
121 static void
122 impl_release_value(void *data, void *data2,
123  const afw_pool_t *p, afw_xctx_t *xctx)
124 {
125  afw_associative_array_release_value_cb cb = data2;
126 
127  cb(data, xctx);
128 }
129 
130 
131 
132 /*
133  * Implementation of method get of interface afw_object_associative_array.
134  */
135 AFW_DEFINE(const void *)
136 afw_associative_array_get (
137  const afw_associative_array_t *instance,
138  const afw_utf8_t *key, afw_xctx_t *xctx)
139 {
141  const void *value;
142 
143  /* Get value associated with key. */
144  value = apr_hash_get(self->values, key->s, key->len);
145 
146  /*
147  * If value found, add reference and register automatic release when
148  * xctx is released.
149  */
150  if (value && self->add_reference_value) {
151  self->add_reference_value(value, xctx);
152  afw_pool_register_cleanup_before(xctx->p, (void *)value, self->release_value,
153  impl_release_value, xctx);
154  }
155 
156  /* Return result. */
157  return value;
158 }
159 
160 
161 
162 /*
163  * Implementation of method get_reference of interface afw_object_associative_array.
164  */
165 AFW_DEFINE(const void *)
166 afw_associative_array_get_reference(
167  const afw_associative_array_t *instance,
168  const afw_utf8_t *key, afw_xctx_t *xctx)
169 {
171  const void *value;
172 
173  /* Get value associated with key. */
174  value = apr_hash_get(self->values, key->s, key->len);
175 
176  /* If value found, add reference. */
177  if (value && self->add_reference_value) {
178  self->add_reference_value(value, xctx);
179  }
180 
181  /* Return result. */
182  return value;
183 }
184 
185 
186 
187 /*
188  * Implementation of method get_reference of interface afw_object_associative_array.
189  */
190 AFW_DEFINE(void)
191 afw_associative_array_for_each(
192  const afw_associative_array_t *instance,
193  void *context, afw_value_cb_t callback, afw_xctx_t *xctx)
194 {
196  apr_hash_index_t *hi;
197  afw_object_t *value;
198 
199  for (hi = apr_hash_first(afw_pool_get_apr_pool(xctx->p), self->values);
200  hi;
201  hi = apr_hash_next(hi))
202  {
203  apr_hash_this(hi, NULL, NULL, (void **)&value);
204  if (callback(value, context, xctx)) {
205  return;
206  }
207  }
208 
209  callback(NULL, context, xctx);
210 }
211 
212 
213 
214 /*
215  * Implementation of method set of interface afw_object_associative_array.
216  */
217 AFW_DEFINE(void)
218 afw_associative_array_set(
219  const afw_associative_array_t *instance,
220  const afw_utf8_t *key, const void *value, afw_xctx_t *xctx)
221 {
223  const void *existing;
224 
225  /* If an value is associated with key, call its release(). */
226  existing = apr_hash_get(self->values, key->s, key->len);
227  if (existing && self->release_value) {
228  self->release_value(existing, xctx);
229  }
230 
231  /* If value passed, add reference. */
232  if (value && self->add_reference_value) {
233  self->add_reference_value(value, xctx);
234  }
235 
236  /* Set/remove association. */
237  apr_hash_set(self->values, key->s, key->len, value);
238 }
AFW_DEFINE(const afw_object_t *)
Adaptive Framework Core Internal.
afw_integer_t afw_atomic_integer_decrement(AFW_ATOMIC afw_integer_t *mem)
Integer atomic decrement.
Definition: afw_atomic.h:96
afw_integer_t afw_atomic_integer_increment(AFW_ATOMIC afw_integer_t *mem)
Integer atomic increment.
Definition: afw_atomic.h:127
afw_boolean_t(* afw_value_cb_t)(const void *value, void *context, afw_xctx_t *xctx)
Typedef for value callback.
Definition: afw_common.h:1190
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_pool_get_apr_pool(instance)
Call method get_apr_pool of interface afw_pool.
#define afw_pool_release(instance, xctx)
Call method release of interface afw_pool.
#define afw_pool_register_cleanup_before(instance, data, data2, cleanup, xctx)
Call method register_cleanup_before of interface afw_pool.
#define afw_pool_calloc_type(instance, type, xctx)
Macro to allocate cleared memory to hold type in pool.
Definition: afw_pool.h:167
const afw_pool_t * afw_pool_create(const afw_pool_t *parent, afw_xctx_t *xctx)
Create a new pool.
Interface afw_object public struct.
Interface afw_pool public struct.
NFC normalized UTF-8 string.
Definition: afw_common.h:545
Interface afw_xctx public struct.