Adaptive Framework  0.9.0
All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
afw_memory.c
Go to the documentation of this file.
1 // See the 'COPYING' file in the project root for licensing information.
2 /*
3  * Adaptive framework memory functions
4  *
5  * Copyright (c) 2010-2023 Clemson University
6  *
7  */
8 
14 #include "afw_internal.h"
15 
16 
17 
18 /* Indexed by value from impl_base64_value. */
19 static const afw_utf8_octet_t
20 impl_base64_digits[] =
21 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
22 
23 
24 
25 /*
26  * 0-63 = index into impl_base64_digits
27  * 64 = '='
28  * 65 = invalid
29  */
30 static const afw_octet_t
31 impl_base64_value[256] =
32 {
33  /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
34  65,65,65,65, 65,65,65,65, 65,65,65,65, 65,65,65,65, /* 0 */
35  65,65,65,65, 65,65,65,65, 65,65,65,65, 65,65,65,65, /* 1 */
36  65,65,65,65, 65,65,65,65, 65,65,65,62, 65,65,65,63, /* 2 */
37  52,53,54,55, 56,57,58,59, 60,61,65,65, 65,64,65,65, /* 3 */
38  65, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11,12,13,14, /* 4 */
39  15,16,17,18, 19,20,21,22, 23,24,25,65, 65,65,65,65, /* 5 */
40  65,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40, /* 6 */
41  41,42,43,44, 45,46,47,48, 49,50,51,65, 65,65,65,65, /* 7 */
42  65,65,65,65, 65,65,65,65, 65,65,65,65, 65,65,65,65, /* 8 */
43  65,65,65,65, 65,65,65,65, 65,65,65,65, 65,65,65,65, /* 9 */
44  65,65,65,65, 65,65,65,65, 65,65,65,65, 65,65,65,65, /* a */
45  65,65,65,65, 65,65,65,65, 65,65,65,65, 65,65,65,65, /* b */
46  65,65,65,65, 65,65,65,65, 65,65,65,65, 65,65,65,65, /* c */
47  65,65,65,65, 65,65,65,65, 65,65,65,65, 65,65,65,65, /* d */
48  65,65,65,65, 65,65,65,65, 65,65,65,65, 65,65,65,65, /* e */
49  65,65,65,65, 65,65,65,65, 65,65,65,65, 65,65,65,65 /* f */
50 };
51 
52 
53 
54 static const char
55 impl_hex_digits[16] =
56 { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
57 
58 
59 
60 const afw_octet_t
61 impl_hex_lookup[256] = {
62 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
63 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
64 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
65 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 255, 255, 255, 255, 255, 255,
66 255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, 255,
67 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
68 255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, 255,
69 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
70 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
71 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
72 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
73 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
74 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
75 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
76 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
77 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255
78 };
79 
80 
81 
82 #define IMPL_BINARY_BUF_SEGMENT_SIZE 1000
83 
84 typedef struct impl_memory_buffer_segment_s
86 
89  afw_size_t used;
90  afw_octet_t s[IMPL_BINARY_BUF_SEGMENT_SIZE];
91 };
92 
93 
94 typedef struct {
96  const afw_pool_t *result_p;
100 
101 
102 
103 static afw_size_t impl_callback(void *context,
104  const void *buffer,
105  afw_size_t size,
106  const afw_pool_t *p,
107  afw_xctx_t *xctx)
108 {
109  impl_memory_self_t *self = context;
110  afw_size_t count;
111  const afw_octet_t *s;
113 
114  for (s = (const afw_octet_t *)buffer, count = size;
115  count > 0;
116  count--, s++)
117  {
118  if (self->last->used == IMPL_BINARY_BUF_SEGMENT_SIZE) {
119  segment = afw_pool_malloc_type(self->pub.p,
121  xctx);
122  segment->next = NULL;
123  segment->used = 0;
124  self->last->next = segment;
125  self->last = segment;
126  }
127  self->last->s[self->last->used++] = *s;
128  }
129 
130  return size;
131 }
132 
133 
134 
135 
136 /* Clone an object to a specified pool. */
137 AFW_DEFINE(const afw_object_t *)
139  const afw_object_t * object,
140  const afw_pool_t *p,
141  afw_xctx_t *xctx)
142 {
143  const afw_object_t *new_object = NULL;
144 
146  (void *)&new_object, &object, p, xctx);
147 
148  return new_object;
149 }
150 
151 
152 /* Create a memory object with properties from two other objects. */
154  const afw_object_t * primary,
155  const afw_object_t * secondary,
156  const afw_pool_t *p,
157  afw_xctx_t *xctx)
158 {
159  const afw_iterator_t *iterator;
160  const afw_object_t *result;
161  const afw_value_t *value;
162  const afw_utf8_t *property_name;
163 
164  result = afw_object_create_clone(primary, p, xctx);
165 
166  /* Merge */
167  iterator = NULL;
168  do {
169  value = afw_object_get_next_property(secondary, &iterator,
170  &property_name, xctx);
171  if (!value) break;
172  if (!afw_object_has_property(primary, property_name, xctx)) {
173  value = afw_value_clone(value, p, xctx);
174  afw_object_set_property(result, property_name, value, xctx);
175  }
176  } while (1);
177 
178  /* Return merged object. */
179  return result;
180 }
181 
182 
183 
184 AFW_DEFINE(void)
186  const afw_pool_t *p, afw_xctx_t *xctx)
187 {
188  afw_octet_t *s;
189  afw_octet_t d1, d2, d3, d4;
190  afw_size_t i;
191 
192  encoded->len = ((memory->size + 2) / 3) * 4;
193  if (encoded->len == 0) {
194  encoded->s = NULL;
195  return;
196  }
197 
198  s = afw_pool_malloc(p, encoded->len, xctx);
199  encoded->s = (const afw_utf8_octet_t*)s;
200 
201  for (i = 0; i < memory->size; i += 3) {
202  d1 = memory->ptr[i] >> 2;
203  d2 = (memory->ptr[i] & 0x03) << 4;
204  d3 = d4 = 64;
205  if ((i + 1) < memory->size) {
206  d2 |= memory->ptr[i + 1] >> 4;
207  d3 = (memory->ptr[i + 1] & 0x0f) << 2;
208  if ((i + 2) < memory->size) {
209  d3 |= memory->ptr[i + 2] >> 6;
210  d4 = memory->ptr[i + 2] & 0x3f;
211  }
212  }
213  *s++ = impl_base64_digits[d1];
214  *s++ = impl_base64_digits[d2];
215  *s++ = impl_base64_digits[d3];
216  *s++ = impl_base64_digits[d4];
217  }
218 }
219 
220 
221 
222 AFW_DEFINE(void)
224  afw_memory_t *memory, const afw_utf8_t *encoded,
225  const afw_pool_t *p, afw_xctx_t *xctx)
226 {
227  afw_size_t non_ws_len, equals;
228  const afw_octet_t *c;
229  afw_octet_t c1, c2, c3, c4;
230  afw_octet_t *b;
231  const afw_octet_t *end;
232 
233  /* Syntax check and determine number for non ws chars other than '=' */
234  for (non_ws_len = equals = 0, c = (const afw_octet_t *)encoded->s, end = c + encoded->len; ; c++)
235  {
236 
237  if (c >= end) {
238  if (non_ws_len % 4 == 0) break;
239  }
240 
241  else {
242 
243  if (afw_ascii_is_whitespace(*c)) {
244  continue;
245  }
246 
247  if (impl_base64_value[*c] <= 63) {
248  non_ws_len++;
249  continue;
250  }
251 
252  if (*c == '=') {
253  if (non_ws_len % 4 == 3) {
254  if (c + 1 == end) {
255  equals = 1;
256  non_ws_len++;
257  break;
258  }
259  }
260  else if (non_ws_len % 4 == 2) {
261  if (c + 2 == end && *(c + 1) == '=') {
262  equals = 2;
263  non_ws_len += 2;
264  break;
265  }
266  }
267  }
268 
269  }
270 
271  AFW_THROW_ERROR_Z(general, "Invalid base64 encoding", xctx);
272  }
273 
274  /* Allocate memory for result. Just return if length is 0. */
275  memory->size = (non_ws_len / 4) * 3 - equals;
276  if (memory->size == 0) {
277  memory->ptr = NULL;
278  return;
279  }
280  b = afw_pool_malloc(p, memory->size, xctx);
281  memory->ptr = b;
282 
283  /* Decode */
284  for (c = (const afw_octet_t *)encoded->s; c < end;)
285  {
286  for (c1 = *c++; afw_ascii_is_whitespace(c1); c1 = *c++);
287  for (c2 = *c++; afw_ascii_is_whitespace(c2); c2 = *c++);
288  for (c3 = *c++; afw_ascii_is_whitespace(c3); c3 = *c++);
289  for (c4 = *c++; afw_ascii_is_whitespace(c4); c4 = *c++);
290 
291  *b++ = (impl_base64_value[c1] << 2) |
292  (impl_base64_value[c2] >> 4);
293 
294  if (c3 == '=') break;
295 
296  *b++ = ((impl_base64_value[c2] << 4) & 0xF0) |
297  (impl_base64_value[c3] >> 2);
298 
299  if (c4 == '=') break;
300 
301  *b++ = ((impl_base64_value[c3] << 6) & 0xC0) |
302  (impl_base64_value[c4]);
303  }
304 }
305 
306 
307 
308 /* Encode memory to a printable hex string. */
309 AFW_DEFINE(void)
311  const afw_pool_t *p, afw_xctx_t *xctx)
312 {
313  const unsigned char *in;
314  afw_utf8_octet_t *out;
315  afw_size_t count;
316 
317  if (memory->size == 0) {
318  memset(encoded, 0, sizeof(afw_utf8_t));
319  return;
320  }
321 
322  encoded->len = memory->size * 2;
323  encoded->s = out = afw_pool_malloc(p, encoded->len, xctx);
324 
325  for (count = memory->size, in = memory->ptr; count > 0; count--, in++) {
326  *out = impl_hex_digits[(*in) >> 4];
327  out++;
328  *out = impl_hex_digits[(*in) & 0x0f];
329  out++;
330  }
331 }
332 
333 
334 
335 /* Encode memory to a printable hex string. */
336 AFW_DEFINE(void)
338  afw_memory_t *memory, const afw_utf8_t *encoded,
339  const afw_pool_t *p, afw_xctx_t *xctx)
340 {
341  const afw_octet_t *in;
342  afw_octet_t *out;
343  afw_size_t count;
344 
345  /* Length can not be odd. */
346  if (encoded->len & 1) goto error;
347 
348  if (encoded->len == 0) {
349  memset(memory, 0, sizeof(afw_memory_t));
350  return;
351  }
352 
353  count = encoded->len / 2;
354  memory->ptr = out = afw_pool_malloc(p, count, xctx);
355  memory->size = count;
356 
357  for (in = (const afw_octet_t *)encoded->s; count > 0; in += 2, out++, count--)
358  {
359  if (*in != 0x20 && *in != 0x09 && *in != 0x0a && *in != 0x0d) {
360  if (impl_hex_lookup[*in] == 255 || impl_hex_lookup[*(in + 1)] == 255)
361  goto error;
362  *out = (impl_hex_lookup[*in] << 4) + impl_hex_lookup[*(in + 1)];
363  }
364  }
365 
366  return;
367 
368 error:
369  AFW_THROW_ERROR_FZ(general, xctx,
370  "Invalid printable hex value %" AFW_UTF8_FMT ".",
371  AFW_UTF8_FMT_ARG(encoded));
372 }
373 
374 
375 
378  const afw_pool_t *p, afw_xctx_t *xctx)
379 {
380  impl_memory_self_t *self;
381  afw_memory_writer_t *writer;
382  const afw_pool_t *self_p;
383 
384  self_p = afw_pool_create(p, xctx);
385  self = afw_pool_calloc_type(self_p, impl_memory_self_t, xctx);
386  writer = (afw_memory_writer_t *)self;
387  writer->callback = impl_callback;
388  writer->context = self;
389  self->pub.p = self_p;
390  self->result_p = p;
391  self->first = self->last = afw_pool_malloc_type(self_p,
393  self->first->next = NULL;
394  self->first->used = 0;
395 
396  return writer;
397 }
398 
399 
402  const afw_memory_writer_t *writer, afw_xctx_t *xctx)
403 {
404  impl_memory_self_t *self = (impl_memory_self_t *)writer;
405  afw_size_t size;
407 
408  for (size = 0, segment = self->first; segment; segment = segment->next) {
409  size += segment->used;
410  }
411 
412  return size;
413 }
414 
415 
416 
419  const afw_memory_writer_t *writer,
420  void *context,
421  afw_write_cb_t callback,
422  afw_xctx_t *xctx)
423 {
424  impl_memory_self_t *self = (impl_memory_self_t *)writer;
426  afw_size_t size;
427 
428  for (size = 0, segment = self->first; segment; segment = segment->next)
429  {
430  callback(context, &segment->s[0], segment->used, self->result_p, xctx);
431  size += segment->used;
432  }
433  afw_pool_release(self->pub.p, xctx);
434 
435  return size;
436 }
437 
438 
439 
440 AFW_DEFINE(const afw_memory_t *)
442  const afw_memory_writer_t *writer, afw_xctx_t *xctx)
443 {
444  impl_memory_self_t *self = (impl_memory_self_t *)writer;
445  afw_memory_t *result;
447  afw_octet_t *ptr;
448 
449  result = afw_pool_calloc_type(self->result_p, afw_memory_t, xctx);
450 
451  for (segment = self->first; segment; segment = segment->next) {
452  result->size += segment->used;
453  }
454 
455  if (result->size > 0) {
456  result->ptr = ptr = afw_pool_malloc(self->result_p,
457  result->size, xctx);
458  for (segment = self->first; segment; segment = segment->next) {
459  memcpy(ptr, &segment->s[0], segment->used);
460  ptr += segment->used;
461  }
462  }
463 
464  afw_pool_release(self->pub.p, xctx);
465 
466  return result;
467 }
AFW_DEFINE(const afw_object_t *)
Adaptive Framework Core Internal.
#define afw_ascii_is_whitespace(v)
Determine if octet is white space.
Definition: afw_ascii.h:238
afw_data_type_object
Data type struct for object.
#define AFW_UTF8_FMT_ARG(A_STRING)
Convenience Macro for use with AFW_UTF8_FMT to specify arg.
Definition: afw_common.h:605
struct afw_iterator_s afw_iterator_t
#define AFW_UTF8_FMT
Format string specifier used for afw_utf8_t.
Definition: afw_common.h:588
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
unsigned char afw_octet_t
8 bits (unsigned).
Definition: afw_common.h:211
afw_size_t(* afw_write_cb_t)(void *context, const void *buffer, afw_size_t size, const afw_pool_t *p, afw_xctx_t *xctx)
Typedef for write callback function.
Definition: afw_common.h:1226
#define afw_data_type_clone_internal(instance, to_internal, from_internal, p, xctx)
Call method clone_internal of interface afw_data_type.
#define AFW_THROW_ERROR_FZ(code, xctx, format_z,...)
Macro used to set error and 0 rv in xctx and throw it.
Definition: afw_error.h:319
#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
afw_memory_decode_base64(afw_memory_t *memory, const afw_utf8_t *encoded, const afw_pool_t *p, afw_xctx_t *xctx)
Decode memory to a base64 string.
Definition: afw_memory.c:223
afw_memory_writer_retrieve_using_callback_and_release(const afw_memory_writer_t *writer, void *context, afw_write_cb_t callback, afw_xctx_t *xctx)
Retrieve memory as using callback.
Definition: afw_memory.c:418
afw_memory_encode_printable_hex(afw_utf8_t *encoded, const afw_memory_t *memory, const afw_pool_t *p, afw_xctx_t *xctx)
Encode memory to a printable hex string.
Definition: afw_memory.c:310
afw_memory_writer_get_current_size(const afw_memory_writer_t *writer, afw_xctx_t *xctx)
Retrieve memory as one chunk from memory writer and release writer.
Definition: afw_memory.c:401
afw_memory_writer_retrieve_and_release(const afw_memory_writer_t *writer, afw_xctx_t *xctx)
Retrieve memory as one chunk from memory writer and release writer.
Definition: afw_memory.c:441
afw_memory_encode_base64(afw_utf8_t *encoded, const afw_memory_t *memory, const afw_pool_t *p, afw_xctx_t *xctx)
Encode memory to as base64 string.
Definition: afw_memory.c:185
afw_memory_create_writer(const afw_pool_t *p, afw_xctx_t *xctx)
Create a memory writer.
Definition: afw_memory.c:377
afw_memory_decode_printable_hex(afw_memory_t *memory, const afw_utf8_t *encoded, const afw_pool_t *p, afw_xctx_t *xctx)
Decode memory to a printable hex string.
Definition: afw_memory.c:337
#define afw_object_get_next_property(instance, iterator, property_name, xctx)
Call method get_next_property of interface afw_object.
#define afw_object_has_property(instance, property_name, xctx)
Call method has_property of interface afw_object.
afw_object_create_clone(const afw_object_t *object, const afw_pool_t *p, afw_xctx_t *xctx)
Clone an object to a specified pool.
Definition: afw_memory.c:138
const afw_object_t * afw_object_create_merged(const afw_object_t *primary, const afw_object_t *secondary, const afw_pool_t *p, afw_xctx_t *xctx)
Create a memory object with properties from two other objects.
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
#define afw_pool_malloc(instance, size, xctx)
Call method malloc of interface afw_pool.
#define afw_pool_release(instance, xctx)
Call method release 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.
#define afw_pool_malloc_type(instance, type, xctx)
Macro to allocate uncleared memory to hold type in pool.
Definition: afw_pool.h:182
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
Struct for memory pointer and size.
Definition: afw_common.h:505
Return value from afw_memory_create_writer().
Definition: afw_memory.h:102
Interface afw_object public struct.
Interface afw_pool public struct.
NFC normalized UTF-8 string.
Definition: afw_common.h:545
Interface afw_value public struct.
Interface afw_xctx public struct.