Adaptive Framework  0.9.0
All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
afw_ubjson_to_value.c
1 // See the 'COPYING' file in the project root for licensing information.
2 /*
3  * AFW ubjson conversion functions.
4  *
5  * Copyright (c) 2010-2023 Clemson University
6  *
7  */
8 
15 #include "afw.h"
16 #include "afw_ubjson.h"
17 
22 typedef struct afw_ubjson_parser_s {
23  const afw_memory_t *input;
24  const unsigned char *ptr;
25  size_t cursor;
26  const afw_utf8_t *path;
27  const afw_object_t *embedding_object;
28  const afw_utf8_t *property_name;
29  const afw_pool_t *p;
30  afw_boolean_t cede_p;
32 
33 
34 static const afw_value_t * afw_ubjson_parse_value(
35  afw_ubjson_parser_t *parser,
36  char type,
37  afw_xctx_t *xctx);
38 
39 static const afw_object_t * afw_ubjson_parse_object(
40  afw_ubjson_parser_t *parser,
41  afw_xctx_t *xctx);
42 
43 static const afw_list_t * afw_ubjson_parse_array(
44  afw_ubjson_parser_t *parser,
45  afw_xctx_t *xctx);
46 
47 static const afw_utf8_t * afw_ubjson_parse_string(
48  afw_ubjson_parser_t *parser,
49  afw_xctx_t *xctx);
50 
51 const afw_value_t * afw_ubjson_parse_number(
52  afw_ubjson_parser_t *parser,
53  char type,
54  afw_xctx_t *xctx);
55 
56 size_t afw_ubjson_parse_length(
57  afw_ubjson_parser_t *parser,
58  afw_xctx_t *xctx);
59 
60 
61 
62 
63 static unsigned char afw_ubjson_peek_byte(
64  afw_ubjson_parser_t *parser, afw_xctx_t *xctx)
65 {
66  if (parser->cursor > parser->input->size) {
67  AFW_THROW_ERROR_Z(general, "Error: expected end of document.", xctx);
68  }
69 
70  return *(parser->ptr);
71 }
72 
73 static unsigned char afw_ubjson_next_byte(
74  afw_ubjson_parser_t *parser, afw_xctx_t *xctx)
75 {
76  unsigned char c;
77 
78  if (parser->cursor > parser->input->size) {
79  AFW_THROW_ERROR_Z(general, "Error: expected end of document.", xctx);
80  }
81 
82  c = *(parser->ptr);
83 
84  parser->ptr++;
85  parser->cursor++;
86 
87  return c;
88 }
89 
90 static void afw_ubjson_next_bytes(
91  afw_ubjson_parser_t *parser, unsigned char *buf,
92  size_t len, afw_xctx_t *xctx)
93 {
94  if (parser->cursor + len > parser->input->size) {
95  AFW_THROW_ERROR_Z(general, "Error: expected end of document.", xctx);
96  }
97 
98  memcpy(buf, parser->ptr, len);
99  parser->ptr += len;
100  parser->cursor += len;
101 }
102 
103 size_t afw_ubjson_parse_length(
104  afw_ubjson_parser_t *parser, afw_xctx_t *xctx)
105 {
106  unsigned char c;
107  afw_c_types_t c_type;
108  size_t d;
109 
110  c = afw_ubjson_next_byte(parser, xctx);
111 
112  switch (c) {
113  case AFW_UBJSON_MARKER_INT8:
114  afw_ubjson_next_bytes(parser, (unsigned char*) &c_type, 1, xctx);
115  d = c_type.int8;
116  break;
117 
118  case AFW_UBJSON_MARKER_UINT8:
119  afw_ubjson_next_bytes(parser, (unsigned char*) &c_type, 1, xctx);
120  d = c_type.uint8;
121  break;
122 
123  case AFW_UBJSON_MARKER_INT16:
124  afw_ubjson_next_bytes(parser, (unsigned char*) &c_type, 2, xctx);
125  AFW_ENDIAN_BIG_TO_NATIVE(&c_type, 16);
126  d = c_type.int16;
127  break;
128 
129  case AFW_UBJSON_MARKER_INT32:
130  afw_ubjson_next_bytes(parser, (unsigned char*) &c_type, 4, xctx);
131  AFW_ENDIAN_BIG_TO_NATIVE(&c_type, 32);
132  d = c_type.int32;
133  break;
134 
135  default:
136  AFW_THROW_ERROR_RV_Z(general, ubjson_marker, c,
137  "Error: invalid numeric type for string length", xctx);
138  break;
139  }
140 
141  return d;
142 }
143 
144 const afw_value_t * afw_ubjson_parse_number(
145  afw_ubjson_parser_t *parser,
146  char type,
147  afw_xctx_t *xctx)
148 {
149  afw_c_types_t c_type;
150  const afw_value_t *value;
151 
152  switch (type) {
153  case AFW_UBJSON_MARKER_CHAR:
154  afw_ubjson_next_bytes(parser, (unsigned char*) &c_type, 1, xctx);
155  value = afw_value_create_integer(c_type.int8, parser->p, xctx);
156  break;
157 
158  case AFW_UBJSON_MARKER_INT8:
159  afw_ubjson_next_bytes(parser, (unsigned char*) &c_type, 1, xctx);
160  value = afw_value_create_integer(c_type.int8, parser->p, xctx);
161  break;
162 
163  case AFW_UBJSON_MARKER_UINT8:
164  afw_ubjson_next_bytes(parser, (unsigned char*) &c_type, 1, xctx);
165  value = afw_value_create_integer(c_type.uint8, parser->p, xctx);
166  break;
167 
168  case AFW_UBJSON_MARKER_INT16:
169  afw_ubjson_next_bytes(parser, (unsigned char*) &c_type, 2, xctx);
170  AFW_ENDIAN_BIG_TO_NATIVE(&c_type, 16);
171  value = afw_value_create_integer(c_type.int16, parser->p, xctx);
172  break;
173 
174  case AFW_UBJSON_MARKER_INT32:
175  afw_ubjson_next_bytes(parser, (unsigned char*) &c_type, 4, xctx);
176  AFW_ENDIAN_BIG_TO_NATIVE(&c_type, 32);
177  value = afw_value_create_integer(c_type.int32, parser->p, xctx);
178  break;
179 
180  case AFW_UBJSON_MARKER_INT64:
181  afw_ubjson_next_bytes(parser, (unsigned char*) &c_type, 8, xctx);
182  AFW_ENDIAN_BIG_TO_NATIVE(&c_type, 64);
183  value = afw_value_create_integer(c_type.int64, parser->p, xctx);
184  break;
185 
186  case AFW_UBJSON_MARKER_FLOAT32:
187  afw_ubjson_next_bytes(parser, (unsigned char*) &c_type, 4, xctx);
188  AFW_ENDIAN_BIG_TO_NATIVE(&c_type, 32);
189  value = afw_value_create_double(c_type.float32, parser->p, xctx);
190  break;
191 
192  case AFW_UBJSON_MARKER_FLOAT64:
193  afw_ubjson_next_bytes(parser, (unsigned char*) &c_type, 8, xctx);
194  AFW_ENDIAN_BIG_TO_NATIVE(&c_type, 64);
195  value = afw_value_create_double(c_type.float64, parser->p, xctx);
196  break;
197 
198  default:
199  AFW_THROW_ERROR_RV_Z(general, ubjson_marker, type,
200  "Error: invalid numeric type.", xctx);
201  break;
202  }
203 
204  return value;
205 }
206 
207 const afw_utf8_t * afw_ubjson_parse_string(
208  afw_ubjson_parser_t *parser,
209  afw_xctx_t *xctx)
210 {
211  const afw_utf8_t *string = NULL;
212  size_t len;
213 
214  len = afw_ubjson_parse_length(parser, xctx);
215 
216  if (parser->cursor + len > parser->input->size) {
217  AFW_THROW_ERROR_Z(general,
218  "Error: string length exceeds input.", xctx);
219  }
220 
221  string = afw_utf8_create_copy((const afw_utf8_octet_t *)parser->ptr, len, parser->p, xctx);
222 
223  parser->ptr += len;
224  parser->cursor += len;
225 
226  return string;
227 }
228 
229 const afw_list_t * afw_ubjson_parse_array(
230  afw_ubjson_parser_t *parser,
231  afw_xctx_t *xctx)
232 {
233  const afw_list_t *list;
234  const afw_value_t *value;
235  char c;
236  char type = 0;AFW_POSSIBLY_UNUSED_VARIABLE size_t count = 0;
238 
239  list = afw_list_create_generic(parser->p, xctx);
240 
241  c = afw_ubjson_peek_byte(parser, xctx);
242 
243  /* check if we have a count or type specified */
244  if (c == AFW_UBJSON_MARKER_TYPE) {
245  /* optimized type specified */
246  type = afw_ubjson_next_byte(parser, xctx);
247 
248  c = afw_ubjson_peek_byte(parser, xctx);
249  if (c == AFW_UBJSON_MARKER_COUNT) {
250  /* optimized count specified */
251  count = afw_ubjson_parse_length(parser, xctx);
252  }
253  } else if (c == AFW_UBJSON_MARKER_COUNT) {
254  /* optimized count specified */
255  count = afw_ubjson_parse_length(parser, xctx);
256  }
257 
258  while (c != AFW_UBJSON_MARKER_ARRAY_) {
259  value = afw_ubjson_parse_value(parser, type, xctx);
260 
261  afw_list_add_value(list, value, xctx);
262 
263  c = afw_ubjson_peek_byte(parser, xctx);
264  }
265 
266  c = afw_ubjson_next_byte(parser, xctx);
267 
268  /* Return. */
269  return list;
270 }
271 
272 const afw_object_t * afw_ubjson_parse_object(
273  afw_ubjson_parser_t *parser,
274  afw_xctx_t *xctx)
275 {
276  const afw_object_t * obj;
277  const afw_utf8_t * property_name;
278  const afw_value_t *property_value;
279  char type = 0;AFW_POSSIBLY_UNUSED_VARIABLE size_t count = 0;
281  char c;AFW_POSSIBLY_UNUSED_VARIABLE const afw_utf8_t *default_path;
283  const afw_object_t *saved_embedding_object;
284  const afw_utf8_t *saved_property_name;
285  const afw_object_t *_meta_;
286 
287  /* Create new memory object.*/
289  parser->embedding_object,
290  parser->property_name,
291  false, parser->cede_p, parser->p, xctx);
292  _meta_ = NULL;
293 
294  /*
295  * Save parser->embedding_object and set to new object.
296  *
297  * Save parser->property_name and set to NULL.
298  *
299  * If entity, default path is supplied by caller, otherwise it's NULL.
300  */
301  saved_embedding_object = parser->embedding_object;
302  parser->embedding_object = obj;
303  saved_property_name = parser->property_name;
304  parser->property_name = NULL;
305  default_path = (!saved_embedding_object) ? parser->path : NULL;
306 
307  c = afw_ubjson_peek_byte(parser, xctx);
308 
309  /* check if we have a count or type specified */
310  if (c == AFW_UBJSON_MARKER_TYPE) {
311  /* optimized type specified */
312  type = afw_ubjson_next_byte(parser, xctx);
313 
314  c = afw_ubjson_peek_byte(parser, xctx);
315  if (c == AFW_UBJSON_MARKER_COUNT) {
316  /* optimized count specified */
317  count = afw_ubjson_parse_length(parser, xctx);
318  }
319  } else if (c == AFW_UBJSON_MARKER_COUNT) {
320  /* optimized count specified */
321  count = afw_ubjson_parse_length(parser, xctx);
322  }
323 
324  c = afw_ubjson_peek_byte(parser, xctx);
325  while (c != AFW_UBJSON_MARKER_OBJECT_) {
326  property_name = afw_ubjson_parse_string(parser, xctx);
327  parser->property_name = property_name;
328  property_value = afw_ubjson_parse_value(parser, type, xctx);
329 
330  /* check if this is a meta property */
331  if (afw_utf8_equal(property_name, &afw_s__meta_)) {
332  if (!afw_value_is_object(property_value)) {
333  AFW_THROW_ERROR_Z(general, "_meta_ property must be an object", xctx);
334  }
335  _meta_ = ((const afw_value_object_t *)property_value)->internal;
336  }
337 
338  /*
339  * If not _meta_ property, set property in new object to this
340  * value if it's not an object. Object will already have been
341  * added by afw_object_create_embedded().
342  */
343  else if (!afw_value_is_object(property_value)) {
344  afw_object_set_property(obj, property_name,
345  property_value, xctx);
346  }
347 
348  c = afw_ubjson_peek_byte(parser, xctx);
349  }
350 
351  c = afw_ubjson_next_byte(parser, xctx);
352 
353  /* Set meta. Note: must be called after properties are set. */
354  afw_object_meta_set_meta_object(obj, _meta_, xctx);
355 
356  /* Set parser->embedding_object to previous value and return object. */
357  parser->embedding_object = saved_embedding_object;
358  parser->property_name = saved_property_name;
359 
360  return obj;
361 }
362 
363 const afw_value_t * afw_ubjson_parse_value(
364  afw_ubjson_parser_t *parser,
365  char type,
366  afw_xctx_t *xctx)
367 {
368  const afw_value_t *value = NULL;
369  const afw_object_t *obj;
370  const afw_list_t *list;
371  const afw_utf8_t *string;
372  unsigned char c;
373 
374  /* if type has been specified, do not look at the input */
375  if (type)
376  c = type;
377  else
378  c = afw_ubjson_next_byte(parser, xctx);
379 
380  switch (c) {
381  /* Null */
382  case AFW_UBJSON_MARKER_NULL:
383  value = afw_value_create_null(NULL, parser->p, xctx);
384  break;
385 
386  /* No-op */
387  case AFW_UBJSON_MARKER_NOOP:
388  value = afw_value_create_null(NULL, parser->p, xctx);
389  break;
390 
391  /* Boolean true */
392  case AFW_UBJSON_MARKER_TRUE:
393  value = afw_value_create_boolean(AFW_TRUE, parser->p, xctx);
394  break;
395 
396  /* Boolean false */
397  case AFW_UBJSON_MARKER_FALSE:
398  value = afw_value_create_boolean(AFW_FALSE, parser->p, xctx);
399  break;
400 
401  /* Numeric types */
402  case AFW_UBJSON_MARKER_INT8:
403  case AFW_UBJSON_MARKER_UINT8:
404  case AFW_UBJSON_MARKER_INT16:
405  case AFW_UBJSON_MARKER_INT32:
406  case AFW_UBJSON_MARKER_INT64:
407  case AFW_UBJSON_MARKER_FLOAT32:
408  case AFW_UBJSON_MARKER_FLOAT64:
409  value = afw_ubjson_parse_number(parser, c, xctx);
410  break;
411 
412  /* High-precision number */
413  case AFW_UBJSON_MARKER_HIGH_PRECISION:
415  AFW_THROW_ERROR_Z(general,
416  "Error: high-precision numbers not implemented.", xctx);
417  break;
418 
419  /* Char */
420  case AFW_UBJSON_MARKER_CHAR:
421  c = afw_ubjson_next_byte(parser, xctx);
422  string = afw_utf8_create_copy((const afw_utf8_octet_t *)&c, 1, parser->p, xctx);
423  value = afw_value_create_string(string, parser->p, xctx);
424  break;
425 
426  case AFW_UBJSON_MARKER_STRING:
427  string = afw_ubjson_parse_string(parser, xctx);
428  value = afw_value_create_string(string, parser->p, xctx);
429  break;
430 
431  /* Array */
432  case AFW_UBJSON_MARKER_ARRAY:
433  list = afw_ubjson_parse_array(parser, xctx);
434  value = afw_value_create_list(list, parser->p, xctx);
435  break;
436 
437  /* Object */
438  case AFW_UBJSON_MARKER_OBJECT:
439  obj = afw_ubjson_parse_object(parser, xctx);
440  value = afw_value_create_object(obj, parser->p, xctx);
441  break;
442 
443  default:
444  AFW_THROW_ERROR_RV_Z(general, ubjson_marker, c,
445  "Error: unknown value type marker.", xctx);
446  break;
447  }
448 
449  return value;
450 }
451 
452 /*
453  * Create an adaptive object from ubjson.
454  */
456  const afw_memory_t *ubjson,
457  const afw_utf8_t *path,
458  const afw_pool_t *p,
459  afw_xctx_t *xctx)
460 {
461  const afw_value_t *value;
462  afw_ubjson_parser_t parser;
463 
464  parser.input = ubjson;
465  parser.ptr = parser.input->ptr;
466  parser.cursor = 0;
467  parser.embedding_object = NULL;
468  parser.property_name = NULL;
469  parser.p = p;
470  parser.path = path;
471  parser.cede_p = false;
472 
473  value = afw_ubjson_parse_value(&parser, 0, xctx);
474 
475  return value;
476 }
477 
478 
479 /*
480  * Implementation of method raw_to_object of interface afw_content_type.
481  */
482 const afw_object_t *
484  const afw_memory_t *ubjson,
485  const afw_utf8_t *source_location,
486  const afw_utf8_t * adaptor_id,
487  const afw_utf8_t * object_type_id,
488  const afw_utf8_t * object_id,
489  afw_boolean_t cede_p,
490  const afw_pool_t * p,
491  afw_xctx_t *xctx)
492 {
493  afw_ubjson_parser_t parser;
494 
495  parser.input = ubjson;
496  parser.ptr = parser.input->ptr;
497  parser.cursor = 0;
498  parser.embedding_object = NULL;
499  parser.property_name = NULL;
500  parser.p = (cede_p) ? p : afw_pool_create(p, xctx);
501  parser.cede_p = true;
502  parser.path = afw_object_path_make(
503  adaptor_id, object_type_id, object_id, parser.p, xctx);
504 
505  /* go ahead and read the first byte, since we assume it's an object. */
506  afw_ubjson_next_byte(&parser, xctx);
507 
508  /* Parse and return object. */
509  return afw_ubjson_parse_object(&parser, xctx);
510 }
Adaptive Framework Core API.
Header file for Adaptive Framework UBJSON.
afw_value_create_boolean(afw_boolean_t internal, const afw_pool_t *p, afw_xctx_t *xctx)
Create function for unmanaged data type boolean value.
afw_value_create_double(double internal, const afw_pool_t *p, afw_xctx_t *xctx)
Create function for unmanaged data type double value.
afw_value_create_integer(afw_integer_t internal, const afw_pool_t *p, afw_xctx_t *xctx)
Create function for unmanaged data type integer value.
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_create_null(void *internal, const afw_pool_t *p, afw_xctx_t *xctx)
Create function for unmanaged data type null value.
#define afw_value_is_object(A_VALUE)
Macro to determine if value is evaluated object.
afw_value_create_object(const afw_object_t *internal, const afw_pool_t *p, afw_xctx_t *xctx)
Create function for unmanaged data type object value.
afw_value_create_string(const afw_utf8_t *internal, const afw_pool_t *p, afw_xctx_t *xctx)
Create function for unmanaged data type string value.
#define AFW_FALSE
Definition: afw_common.h:392
#define AFW_TRUE
Definition: afw_common.h:383
_Bool afw_boolean_t
Definition: afw_common.h:373
char afw_utf8_octet_t
8 bits of utf-8 codepoint.
Definition: afw_common.h:236
#define AFW_POSSIBLY_UNUSED_VARIABLE
Macro to avoid unused variable warning.
Definition: afw_common.h:127
#define AFW_THROW_ERROR_RV_Z(code, rv_source_id, rv, message_z, xctx)
Macro used to set error and rv in xctx and throw it.
Definition: afw_error.h:301
#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_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
afw_object_meta_set_meta_object(const afw_object_t *instance, const afw_object_t *meta, afw_xctx_t *xctx)
Set an object's meta from a meta object.
afw_object_path_make(const afw_utf8_t *adaptor_id, const afw_utf8_t *object_type_id, const afw_utf8_t *object_id, const afw_pool_t *p, afw_xctx_t *xctx)
Construct an object path in a specified pool.
#define AFW_OBJECT_CREATE_ENTITY_OR_EMBEDDED(result, embedding_object, property_name, always_create_unmanaged, cede_p, entity_p, xctx)
Helper macro to create a new entity or embedded object.
Definition: afw_object.h:1015
afw_object_set_property(const afw_object_t *instance, const afw_utf8_t *property_name, const afw_value_t *value, afw_xctx_t *xctx)
Set the value of an object's property.
Definition: afw_object.c:46
const afw_pool_t * afw_pool_create(const afw_pool_t *parent, afw_xctx_t *xctx)
Create a new pool.
const afw_object_t * afw_ubjson_to_object(const afw_memory_t *ubjson, const afw_utf8_t *source_location, const afw_utf8_t *adaptor_id, const afw_utf8_t *object_type_id, const afw_utf8_t *object_id, afw_boolean_t cede_p, const afw_pool_t *p, afw_xctx_t *xctx)
Convert from UBJSON to adaptive object.
const afw_value_t * afw_ubjson_to_value(const afw_memory_t *ubjson, const afw_utf8_t *path, const afw_pool_t *p, afw_xctx_t *xctx)
Convert UBJSON to an adaptive value.
#define afw_utf8_create_copy(s, len, p, xctx)
Make a utf-8 sting from chars in pool specified.
Definition: afw_utf8.h:369
afw_boolean_t afw_utf8_equal(const afw_utf8_t *s1, const afw_utf8_t *s2)
Check to see if a string equals another string.
Interface afw_list public struct.
Struct for memory pointer and size.
Definition: afw_common.h:505
Interface afw_object public struct.
Interface afw_pool public struct.
NFC normalized UTF-8 string.
Definition: afw_common.h:545
struct for data type object values.
Interface afw_value public struct.
Interface afw_xctx public struct.
Typedef for union of all cType.
Definition: afw_common.h:1581