Adaptive Framework  0.9.0
All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
afw_value_reference_by_key.c
Go to the documentation of this file.
1 // See the 'COPYING' file in the project root for licensing information.
2 /*
3  * Interface afw_value Implementation for reference_by_key
4  *
5  * Copyright (c) 2010-2023 Clemson University
6  *
7  */
8 
9 
15 #include "afw_internal.h"
16 
17 
18 #define impl_afw_value_optional_release NULL
19 #define impl_afw_value_get_reference NULL
20 
21 
22 
23 #define impl_afw_value_get_evaluated_metas \
24  afw_value_internal_get_evaluated_metas_default
25 
26 /* Declares and rti/inf defines for interface afw_value */
27 #define AFW_IMPLEMENTATION_ID "reference_by_key"
28 #define AFW_IMPLEMENTATION_INF_SPECIFIER AFW_DEFINE_CONST_DATA
29 #define AFW_IMPLEMENTATION_INF_LABEL afw_value_reference_by_key_inf
31 
35 /* Create function for reference_by_key value. */
36 AFW_DEFINE(const afw_value_t *)
38  const afw_compile_value_contextual_t *contextual,
39  const afw_value_t *aggregate_value,
40  const afw_value_t *key,
41  const afw_pool_t *p,
42  afw_xctx_t *xctx)
43 {
45 
47  result->inf = &afw_value_reference_by_key_inf;
48  result->contextual = contextual;
49  result->aggregate_value = aggregate_value;
50  result->key = key;
51 
52  /* Add backtrace detail. */
53  if (afw_value_is_string(key)) {
54  result->backtrace_detail = afw_utf8_printf(
55  p, xctx,
56  "[string %" AFW_UTF8_FMT "]",
57  AFW_UTF8_FMT_ARG(&((const afw_value_string_t *)key)->internal));
58  }
59  else if (afw_value_is_integer(key)) {
60  result->backtrace_detail = afw_utf8_printf(
61  p, xctx,
62  "[%" AFW_INTEGER_FMT "]",
63  ((const afw_value_integer_t *)key)->internal);
64  }
65  else if (!afw_value_is_defined_and_evaluated(key)) {
66  result->backtrace_detail = &afw_s_a_bracketed_value;
67  }
68  else {
69  AFW_THROW_ERROR_Z(general,
70  "index must be an integer, expression, or string",
71  xctx);
72  }
73 
74  /* Return adaptive value. */
75  return (afw_value_t *)result;
76 }
77 
78 
79 /*
80  * Implementation of method optional_evaluate for interface afw_value.
81  */
82 const afw_value_t *
84  const afw_value_t * instance,
85  const afw_pool_t * p,
86  afw_xctx_t *xctx)
87 {
88  const afw_value_reference_by_key_t *self =
89  (const afw_value_reference_by_key_t *)instance;
90 
91  const afw_value_t *v;
92  const afw_value_object_t *object_value;
93  const afw_value_list_t *list;
94  const afw_value_t *key;
95  const afw_utf8_t *name;
96  afw_size_t i;
97  const afw_value_t *result;
98  const afw_compile_value_contextual_t *saved_contextual;
99 
100  /* Push value on evaluation stack. */
101  afw_xctx_evaluation_stack_push_value(instance, xctx);
102  saved_contextual = xctx->error->contextual;
103  xctx->error->contextual = self->contextual;
104 
105  v = afw_value_evaluate(self->aggregate_value, p, xctx);
106 
107  /* If value is single object, index is property name. */
108  if (afw_value_is_object(v)) {
109  object_value = (const afw_value_object_t *)v;
110 
111  key = afw_value_evaluate(self->key, p, xctx);
112  if (afw_value_is_string(key)) {
113  name = &((const afw_value_string_t *)key)->internal;
114  }
115  else {
116  name = afw_value_as_utf8(key, p, xctx);
117  }
118 
119  v = afw_object_get_property(object_value->internal, name, xctx);
120  if (!v) {
121  return NULL;
122  }
123  result = afw_value_evaluate(v, p, xctx);
124  }
125 
126  /* If value is single list, index is index is index into list. */
127  else if (afw_value_is_list(v)) {
128  list = (const afw_value_list_t *)v;
129 
130  key = afw_value_evaluate(self->key, p, xctx);
131  if (!afw_value_is_integer(key)) {
132  AFW_THROW_ERROR_Z(evaluate,
133  "Index must be integer for list", xctx);
134  }
136  ((const afw_value_integer_t *)key)->internal,
137  xctx);
138 
139  result = afw_list_get_entry_value(list->internal,
140  i, p, xctx);
141  if (!result) {
142  AFW_THROW_ERROR_Z(evaluate,
143  "Index out of range for list", xctx);
144  }
145  }
146 
147  else {
148  AFW_THROW_ERROR_Z(evaluate,
149  "Expecting object or list", xctx);
150  }
151 
152  /* Pop value from evaluation stack and return result. */
154  xctx->error->contextual = saved_contextual;
155  return result;
156 }
157 
158 /*
159  * Implementation of method get_data_type for interface afw_value.
160  */
161 const afw_data_type_t *
162 impl_afw_value_get_data_type(
163  const afw_value_t * instance,
164  afw_xctx_t *xctx)
165 {
166  return NULL;
167 }
168 
169 /*
170  * Implementation of method get_evaluated_data_type for interface afw_value.
171  */
172 const afw_data_type_t *
173 impl_afw_value_get_evaluated_data_type(
174  const afw_value_t * instance,
175  afw_xctx_t *xctx)
176 {
177  return NULL;
178 }
179 
180 
181 /*
182  * Implementation of method get_evaluated_data_type_parameter for interface
183  * afw_value.
184  */
185 const afw_utf8_t *
186 impl_afw_value_get_evaluated_data_type_parameter(
187  const afw_value_t * instance,
188  afw_xctx_t *xctx)
189 {
190  return NULL;
191 }
192 
193 /*
194  * Implementation of method get_evaluated_meta for interface afw_value.
195  */
196 const afw_value_t *
198  const afw_value_t *instance,
199  const afw_pool_t *p,
200  afw_xctx_t *xctx)
201 {
202  const afw_value_reference_by_key_t *self =
203  (const afw_value_reference_by_key_t *)instance;
204  const afw_value_t *result;
205  const afw_value_t *key;
206  const afw_value_t *aggregate_value;
207 
208  key = afw_value_evaluate(self->key, p, xctx);
209  aggregate_value = afw_value_evaluate(self->aggregate_value, p, xctx);
210 
211  if (afw_value_is_object(aggregate_value)) {
212  key = afw_value_convert(key, afw_data_type_string, false, p, xctx);
213  if (!afw_value_is_string(key)) {
214  AFW_THROW_ERROR_Z(general,
215  "reference_by_key key for object must be a string",
216  xctx);
217  }
219  ((const afw_value_object_t *)aggregate_value)->internal,
220  &((const afw_value_string_t *)key)->internal,
221  p, xctx);
222  }
223  else if (afw_value_is_list(aggregate_value)) {
224  key = afw_value_convert(key, afw_data_type_integer, false, p, xctx);
225  if (!afw_value_is_integer(key)) {
226  AFW_THROW_ERROR_Z(general,
227  "reference_by_key key for list must be an integer",
228  xctx);
229  }
230  result = afw_list_get_entry_meta(
231  ((const afw_value_list_t *)aggregate_value)->internal,
232  ((const afw_value_integer_t *)key)->internal,
233  p, xctx);
234  }
235  else {
236  AFW_THROW_ERROR_Z(general,
237  "reference_by_key aggregate_value must be list or object",
238  xctx);
239  }
240 
241  return result;
242 }
243 
244 /*
245  * Implementation of method compiler_listing for interface afw_value.
246  */
247 void
248 impl_afw_value_produce_compiler_listing(
249  const afw_value_t *instance,
250  const afw_writer_t *writer,
251  afw_xctx_t *xctx)
252 {
253  const afw_value_reference_by_key_t *self =
254  (const afw_value_reference_by_key_t *)instance;
255 
256  afw_value_compiler_listing_begin_value(writer, instance,
257  self->contextual, xctx);
258  afw_writer_write_z(writer, ": [", xctx);
259  afw_writer_write_eol(writer, xctx);
260  afw_writer_increment_indent(writer, xctx);
261 
262  afw_writer_write_z(writer, "key: [", xctx);
263  afw_writer_write_eol(writer, xctx);
264  afw_writer_increment_indent(writer, xctx);
265  afw_value_compiler_listing_value(self->key, writer, xctx);
266  afw_writer_decrement_indent(writer, xctx);
267  afw_writer_write_z(writer, "]", xctx);
268  afw_writer_write_eol(writer, xctx);
269 
270  afw_value_produce_compiler_listing(self->aggregate_value, writer, xctx);
271 
272  afw_writer_decrement_indent(writer, xctx);
273  afw_writer_write_z(writer, "]", xctx);
274  afw_writer_write_eol(writer, xctx);
275 }
276 
277 /*
278  * Implementation of method decompile for interface afw_value.
279  */
280 void
281 impl_afw_value_decompile(
282  const afw_value_t * instance,
283  const afw_writer_t * writer,
284  afw_xctx_t *xctx)
285 {
286  const afw_value_reference_by_key_t *self =
287  (const afw_value_reference_by_key_t *)instance;
288 
289  afw_value_decompile(self->aggregate_value, writer, xctx);
290  afw_writer_write_z(writer, "[", xctx);
291  afw_value_decompile_value(self->key, writer, xctx);
292  afw_writer_write_z(writer, "]", xctx);
293 }
294 
295 
296 /*
297  * Implementation of method get_info for interface afw_value.
298  */
299 void
300 impl_afw_value_get_info(
301  const afw_value_t *instance,
302  afw_value_info_t *info,
303  const afw_pool_t *p,
304  afw_xctx_t *xctx)
305 {
306  const afw_value_reference_by_key_t *self =
307  (const afw_value_reference_by_key_t *)instance;
308 
309  afw_memory_clear(info);
310  info->value_inf_id = &instance->inf->rti.implementation_id;
311  info->contextual = self->contextual;
312  info->detail = self->backtrace_detail;
313 }
AFW_DEFINE(const afw_object_t *)
Adaptive Framework Core Internal.
Interface afw_interface implementation declares.
#define afw_value_is_integer(A_VALUE)
Macro to determine if value is evaluated integer.
afw_data_type_integer
Data type struct for integer.
#define afw_value_is_list(A_VALUE)
Macro to determine if value is evaluated list.
#define afw_value_is_object(A_VALUE)
Macro to determine if value is evaluated object.
afw_data_type_string
Data type struct for string.
#define afw_value_is_string(A_VALUE)
Macro to determine if value is evaluated string.
#define AFW_UTF8_FMT_ARG(A_STRING)
Convenience Macro for use with AFW_UTF8_FMT to specify arg.
Definition: afw_common.h:605
#define AFW_INTEGER_FMT
Format string specifier used for afw_integer_t.
Definition: afw_common.h:326
#define AFW_UTF8_FMT
Format string specifier used for afw_utf8_t.
Definition: afw_common.h:588
apr_size_t afw_size_t
size_t.
Definition: afw_common.h:151
#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_list_get_entry_value(instance, index, p, xctx)
Call method get_entry_value of interface afw_list.
#define afw_list_get_entry_meta(instance, index, p, xctx)
Call method get_entry_meta of interface afw_list.
#define afw_memory_clear(to)
Clear preallocated memory for sizeof(*(to)).
Definition: afw_memory.h:47
#define afw_object_get_property(instance, property_name, xctx)
Call method get_property of interface afw_object.
#define afw_object_get_property_meta(instance, property_name, p, xctx)
Call method get_property_meta of interface afw_object.
#define afw_pool_calloc_type(instance, type, xctx)
Macro to allocate cleared memory to hold type in pool.
Definition: afw_pool.h:167
afw_size_t afw_safe_cast_integer_to_size(afw_integer_t integer, afw_xctx_t *xctx)
Safely cast afw_integer_t to afw_size_t.
Definition: afw_safe_cast.h:68
afw_utf8_printf(const afw_pool_t *p, afw_xctx_t *xctx, const afw_utf8_z_t *format,...)
Create a utf-8 string using a c format string in specified pool.
Definition: afw_utf8.c:459
const afw_value_t * impl_afw_value_get_evaluated_meta(const afw_value_t *instance, const afw_pool_t *p, afw_xctx_t *xctx)
const afw_value_t * impl_afw_value_optional_evaluate(const afw_value_t *instance, const afw_pool_t *p, afw_xctx_t *xctx)
#define afw_value_produce_compiler_listing(instance, writer, xctx)
Call method produce_compiler_listing of interface afw_value.
#define afw_value_decompile(instance, writer, xctx)
Call method decompile of interface afw_value.
#define afw_value_evaluate(value, p, xctx)
Evaluate value if needed using specific pool.
Definition: afw_value.h:841
afw_value_reference_by_key_inf
Value evaluation_reference_by_key inf.
Definition: afw_value.h:297
afw_value_as_utf8(const afw_value_t *value, const afw_pool_t *p, afw_xctx_t *xctx)
Definition: afw_value.c:456
#define afw_value_is_defined_and_evaluated(A_VALUE)
Macro to determine if value is defined and evaluated.
Definition: afw_value.h:481
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
afw_value_decompile_value(const afw_value_t *instance, const afw_writer_t *writer, afw_xctx_t *xctx)
Decompile Value::.
afw_value_reference_by_key_create(const afw_compile_value_contextual_t *contextual, const afw_value_t *aggregate_value, const afw_value_t *key, const afw_pool_t *p, afw_xctx_t *xctx)
Create function for reference_by_key value.
#define afw_writer_increment_indent(instance, xctx)
Call method increment_indent of interface afw_writer.
#define afw_writer_write_eol(instance, xctx)
Call method write_eol of interface afw_writer.
#define afw_writer_decrement_indent(instance, xctx)
Call method decrement_indent of interface afw_writer.
#define afw_writer_write_z(writer, s_z, xctx)
Call afw_writer_write() with zero terminated string.
Definition: afw_writer.h:35
#define afw_xctx_evaluation_stack_push_value(VALUE, xctx)
Push VALUE onto execution stack.
Definition: afw_xctx.h:78
#define afw_xctx_evaluation_stack_pop_value(xctx)
Pop top VALUE off execution stack.
Definition: afw_xctx.h:113
Contextual information provided in some values.
Interface afw_data_type public struct.
const afw_compile_value_contextual_t * contextual
Contextual information or NULL.
Definition: afw_error.h:83
Interface afw_pool public struct.
NFC normalized UTF-8 string.
Definition: afw_common.h:545
Filled in by afw_value get_info method.
Definition: afw_value.h:49
struct for data type integer values.
struct for data type list values.
struct for data type object values.
Struct for reference_by_key value.
Interface afw_value public struct.
struct for data type string values.
Interface afw_writer public struct.
Interface afw_xctx public struct.