1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to you under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * https://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
14 * implied. See the License for the specific language governing
15 * permissions and limitations under the License.
16 */
17
18 #include <avro/platform.h>
19 #include <stdlib.h>
20 #include <string.h>
21
22 #include "avro/allocation.h"
23 #include "avro/basics.h"
24 #include "avro/errors.h"
25 #include "avro/legacy.h"
26 #include "avro/refcount.h"
27 #include "avro/schema.h"
28 #include "avro/value.h"
29 #include "avro_private.h"
30
31 extern avro_value_iface_t AVRO_DATUM_VALUE_CLASS;
32
33 avro_value_iface_t *
avro_datum_class(void)34 avro_datum_class(void)
35 {
36 return &AVRO_DATUM_VALUE_CLASS;
37 }
38
39 int
avro_datum_as_value(avro_value_t * value,avro_datum_t src)40 avro_datum_as_value(avro_value_t *value, avro_datum_t src)
41 {
42 value->iface = &AVRO_DATUM_VALUE_CLASS;
43 value->self = avro_datum_incref(src);
44 return 0;
45 }
46
47 static int
avro_datum_as_child_value(avro_value_t * value,avro_datum_t src)48 avro_datum_as_child_value(avro_value_t *value, avro_datum_t src)
49 {
50 value->iface = &AVRO_DATUM_VALUE_CLASS;
51 value->self = src;
52 return 0;
53 }
54
55 static void
avro_datum_value_incref(avro_value_t * value)56 avro_datum_value_incref(avro_value_t *value)
57 {
58 avro_datum_t self = (avro_datum_t) value->self;
59 avro_datum_incref(self);
60 }
61
62 static void
avro_datum_value_decref(avro_value_t * value)63 avro_datum_value_decref(avro_value_t *value)
64 {
65 avro_datum_t self = (avro_datum_t) value->self;
66 avro_datum_decref(self);
67 }
68
69 static int
avro_datum_value_reset(const avro_value_iface_t * iface,void * vself)70 avro_datum_value_reset(const avro_value_iface_t *iface, void *vself)
71 {
72 AVRO_UNUSED(iface);
73 avro_datum_t self = (avro_datum_t) vself;
74 check_param(EINVAL, self, "datum instance");
75 return avro_datum_reset(self);
76 }
77
78 static avro_type_t
avro_datum_value_get_type(const avro_value_iface_t * iface,const void * vself)79 avro_datum_value_get_type(const avro_value_iface_t *iface, const void *vself)
80 {
81 AVRO_UNUSED(iface);
82 const avro_datum_t self = (const avro_datum_t) vself;
83 #ifdef _WIN32
84 #pragma message("#warning: Bug: EINVAL is not of type avro_type_t.")
85 #else
86 #warning "Bug: EINVAL is not of type avro_type_t."
87 #endif
88 /* We shouldn't use EINVAL as the return value to
89 * check_param(), because EINVAL (= 22) is not a valid enum
90 * avro_type_t. This is a structural issue -- we would need a
91 * different interface on all the get_type functions to fix
92 * this. For now, suppressing the error by casting EINVAL to
93 * (avro_type_t) so the code compiles under C++.
94 */
95 check_param((avro_type_t) EINVAL, self, "datum instance");
96 return avro_typeof(self);
97 }
98
99 static avro_schema_t
avro_datum_value_get_schema(const avro_value_iface_t * iface,const void * vself)100 avro_datum_value_get_schema(const avro_value_iface_t *iface, const void *vself)
101 {
102 AVRO_UNUSED(iface);
103 const avro_datum_t self = (const avro_datum_t) vself;
104 check_param(NULL, self, "datum instance");
105 return avro_datum_get_schema(self);
106 }
107
108
109 static int
avro_datum_value_get_boolean(const avro_value_iface_t * iface,const void * vself,int * out)110 avro_datum_value_get_boolean(const avro_value_iface_t *iface,
111 const void *vself, int *out)
112 {
113 AVRO_UNUSED(iface);
114 const avro_datum_t self = (const avro_datum_t) vself;
115 check_param(EINVAL, self, "datum instance");
116
117 int rval;
118 int8_t value;
119 check(rval, avro_boolean_get(self, &value));
120 *out = value;
121 return 0;
122 }
123
124 static int
avro_datum_value_get_bytes(const avro_value_iface_t * iface,const void * vself,const void ** buf,size_t * size)125 avro_datum_value_get_bytes(const avro_value_iface_t *iface,
126 const void *vself, const void **buf, size_t *size)
127 {
128 AVRO_UNUSED(iface);
129 const avro_datum_t self = (const avro_datum_t) vself;
130 check_param(EINVAL, self, "datum instance");
131
132 int rval;
133 char *bytes;
134 int64_t sz;
135 check(rval, avro_bytes_get(self, &bytes, &sz));
136 if (buf != NULL) {
137 *buf = (const void *) bytes;
138 }
139 if (size != NULL) {
140 *size = sz;
141 }
142 return 0;
143 }
144
145 static int
avro_datum_value_grab_bytes(const avro_value_iface_t * iface,const void * vself,avro_wrapped_buffer_t * dest)146 avro_datum_value_grab_bytes(const avro_value_iface_t *iface,
147 const void *vself, avro_wrapped_buffer_t *dest)
148 {
149 AVRO_UNUSED(iface);
150 const avro_datum_t self = (const avro_datum_t) vself;
151 check_param(EINVAL, self, "datum instance");
152
153 int rval;
154 char *bytes;
155 int64_t sz;
156 check(rval, avro_bytes_get(self, &bytes, &sz));
157
158 /* nothing clever, just make a copy */
159 return avro_wrapped_buffer_new_copy(dest, bytes, sz);
160 }
161
162 static int
avro_datum_value_get_double(const avro_value_iface_t * iface,const void * vself,double * out)163 avro_datum_value_get_double(const avro_value_iface_t *iface,
164 const void *vself, double *out)
165 {
166 AVRO_UNUSED(iface);
167 const avro_datum_t self = (const avro_datum_t) vself;
168 check_param(EINVAL, self, "datum instance");
169
170 int rval;
171 double value;
172 check(rval, avro_double_get(self, &value));
173 *out = value;
174 return 0;
175 }
176
177 static int
avro_datum_value_get_float(const avro_value_iface_t * iface,const void * vself,float * out)178 avro_datum_value_get_float(const avro_value_iface_t *iface,
179 const void *vself, float *out)
180 {
181 AVRO_UNUSED(iface);
182 const avro_datum_t self = (const avro_datum_t) vself;
183 check_param(EINVAL, self, "datum instance");
184
185 int rval;
186 float value;
187 check(rval, avro_float_get(self, &value));
188 *out = value;
189 return 0;
190 }
191
192 static int
avro_datum_value_get_int(const avro_value_iface_t * iface,const void * vself,int32_t * out)193 avro_datum_value_get_int(const avro_value_iface_t *iface,
194 const void *vself, int32_t *out)
195 {
196 AVRO_UNUSED(iface);
197 const avro_datum_t self = (const avro_datum_t) vself;
198 check_param(EINVAL, self, "datum instance");
199
200 int rval;
201 int32_t value;
202 check(rval, avro_int32_get(self, &value));
203 *out = value;
204 return 0;
205 }
206
207 static int
avro_datum_value_get_long(const avro_value_iface_t * iface,const void * vself,int64_t * out)208 avro_datum_value_get_long(const avro_value_iface_t *iface,
209 const void *vself, int64_t *out)
210 {
211 AVRO_UNUSED(iface);
212 const avro_datum_t self = (const avro_datum_t) vself;
213 check_param(EINVAL, self, "datum instance");
214
215 int rval;
216 int64_t value;
217 check(rval, avro_int64_get(self, &value));
218 *out = value;
219 return 0;
220 }
221
222 static int
avro_datum_value_get_null(const avro_value_iface_t * iface,const void * vself)223 avro_datum_value_get_null(const avro_value_iface_t *iface,
224 const void *vself)
225 {
226 AVRO_UNUSED(iface);
227 const avro_datum_t self = (const avro_datum_t) vself;
228 check_param(EINVAL, is_avro_null(self), "datum instance");
229 return 0;
230 }
231
232 static int
avro_datum_value_get_string(const avro_value_iface_t * iface,const void * vself,const char ** str,size_t * size)233 avro_datum_value_get_string(const avro_value_iface_t *iface,
234 const void *vself, const char **str, size_t *size)
235 {
236 AVRO_UNUSED(iface);
237 const avro_datum_t self = (const avro_datum_t) vself;
238 check_param(EINVAL, self, "datum instance");
239
240 int rval;
241 char *value;
242 check(rval, avro_string_get(self, &value));
243 if (str != NULL) {
244 *str = (const char *) value;
245 }
246 if (size != NULL) {
247 *size = strlen(value)+1;
248 }
249 return 0;
250 }
251
252 static int
avro_datum_value_grab_string(const avro_value_iface_t * iface,const void * vself,avro_wrapped_buffer_t * dest)253 avro_datum_value_grab_string(const avro_value_iface_t *iface,
254 const void *vself, avro_wrapped_buffer_t *dest)
255 {
256 AVRO_UNUSED(iface);
257 const avro_datum_t self = (const avro_datum_t) vself;
258 check_param(EINVAL, self, "datum instance");
259
260 int rval;
261 char *str;
262 size_t sz;
263 check(rval, avro_string_get(self, &str));
264 sz = strlen(str);
265
266 /* nothing clever, just make a copy */
267 /* sz doesn't contain NUL terminator */
268 return avro_wrapped_buffer_new_copy(dest, str, sz+1);
269 }
270
271 static int
avro_datum_value_get_enum(const avro_value_iface_t * iface,const void * vself,int * out)272 avro_datum_value_get_enum(const avro_value_iface_t *iface,
273 const void *vself, int *out)
274 {
275 AVRO_UNUSED(iface);
276 const avro_datum_t self = (const avro_datum_t) vself;
277 check_param(EINVAL, is_avro_enum(self), "datum instance");
278 *out = avro_enum_get(self);
279 return 0;
280 }
281
282 static int
avro_datum_value_get_fixed(const avro_value_iface_t * iface,const void * vself,const void ** buf,size_t * size)283 avro_datum_value_get_fixed(const avro_value_iface_t *iface,
284 const void *vself, const void **buf, size_t *size)
285 {
286 AVRO_UNUSED(iface);
287 const avro_datum_t self = (const avro_datum_t) vself;
288 check_param(EINVAL, self, "datum instance");
289
290 int rval;
291 char *bytes;
292 int64_t sz;
293 check(rval, avro_fixed_get(self, &bytes, &sz));
294 if (buf != NULL) {
295 *buf = (const void *) bytes;
296 }
297 if (size != NULL) {
298 *size = sz;
299 }
300 return 0;
301 }
302
303 static int
avro_datum_value_grab_fixed(const avro_value_iface_t * iface,const void * vself,avro_wrapped_buffer_t * dest)304 avro_datum_value_grab_fixed(const avro_value_iface_t *iface,
305 const void *vself, avro_wrapped_buffer_t *dest)
306 {
307 AVRO_UNUSED(iface);
308 const avro_datum_t self = (const avro_datum_t) vself;
309 check_param(EINVAL, self, "datum instance");
310
311 int rval;
312 char *bytes;
313 int64_t sz;
314 check(rval, avro_fixed_get(self, &bytes, &sz));
315
316 /* nothing clever, just make a copy */
317 return avro_wrapped_buffer_new_copy(dest, bytes, sz);
318 }
319
320
321 static int
avro_datum_value_set_boolean(const avro_value_iface_t * iface,void * vself,int val)322 avro_datum_value_set_boolean(const avro_value_iface_t *iface,
323 void *vself, int val)
324 {
325 AVRO_UNUSED(iface);
326 avro_datum_t self = (avro_datum_t) vself;
327 check_param(EINVAL, self, "datum instance");
328 return avro_boolean_set(self, val);
329 }
330
331 static int
avro_datum_value_set_bytes(const avro_value_iface_t * iface,void * vself,void * buf,size_t size)332 avro_datum_value_set_bytes(const avro_value_iface_t *iface,
333 void *vself, void *buf, size_t size)
334 {
335 AVRO_UNUSED(iface);
336 avro_datum_t self = (avro_datum_t) vself;
337 check_param(EINVAL, self, "datum instance");
338 return avro_bytes_set(self, (const char *) buf, size);
339 }
340
341 static int
avro_datum_value_give_bytes(const avro_value_iface_t * iface,void * vself,avro_wrapped_buffer_t * buf)342 avro_datum_value_give_bytes(const avro_value_iface_t *iface,
343 void *vself, avro_wrapped_buffer_t *buf)
344 {
345 /*
346 * We actually can't use avro_givebytes_set, since it can't
347 * handle the extra free_ud parameter. Ah well, this is
348 * deprecated, so go ahead and make a copy.
349 */
350
351 int rval = avro_datum_value_set_bytes
352 (iface, vself, (void *) buf->buf, buf->size);
353 avro_wrapped_buffer_free(buf);
354 return rval;
355 }
356
357 static int
avro_datum_value_set_double(const avro_value_iface_t * iface,void * vself,double val)358 avro_datum_value_set_double(const avro_value_iface_t *iface,
359 void *vself, double val)
360 {
361 AVRO_UNUSED(iface);
362 avro_datum_t self = (avro_datum_t) vself;
363 check_param(EINVAL, self, "datum instance");
364 return avro_double_set(self, val);
365 }
366
367 static int
avro_datum_value_set_float(const avro_value_iface_t * iface,void * vself,float val)368 avro_datum_value_set_float(const avro_value_iface_t *iface,
369 void *vself, float val)
370 {
371 AVRO_UNUSED(iface);
372 avro_datum_t self = (avro_datum_t) vself;
373 check_param(EINVAL, self, "datum instance");
374 return avro_float_set(self, val);
375 }
376
377 static int
avro_datum_value_set_int(const avro_value_iface_t * iface,void * vself,int32_t val)378 avro_datum_value_set_int(const avro_value_iface_t *iface,
379 void *vself, int32_t val)
380 {
381 AVRO_UNUSED(iface);
382 avro_datum_t self = (avro_datum_t) vself;
383 check_param(EINVAL, self, "datum instance");
384 return avro_int32_set(self, val);
385 }
386
387 static int
avro_datum_value_set_long(const avro_value_iface_t * iface,void * vself,int64_t val)388 avro_datum_value_set_long(const avro_value_iface_t *iface,
389 void *vself, int64_t val)
390 {
391 AVRO_UNUSED(iface);
392 avro_datum_t self = (avro_datum_t) vself;
393 check_param(EINVAL, self, "datum instance");
394 return avro_int64_set(self, val);
395 }
396
397 static int
avro_datum_value_set_null(const avro_value_iface_t * iface,void * vself)398 avro_datum_value_set_null(const avro_value_iface_t *iface, void *vself)
399 {
400 AVRO_UNUSED(iface);
401 avro_datum_t self = (avro_datum_t) vself;
402 check_param(EINVAL, is_avro_null(self), "datum instance");
403 return 0;
404 }
405
406 static int
avro_datum_value_set_string(const avro_value_iface_t * iface,void * vself,const char * str)407 avro_datum_value_set_string(const avro_value_iface_t *iface,
408 void *vself, const char *str)
409 {
410 AVRO_UNUSED(iface);
411 avro_datum_t self = (avro_datum_t) vself;
412 check_param(EINVAL, self, "datum instance");
413 return avro_string_set(self, str);
414 }
415
416 static int
avro_datum_value_set_string_len(const avro_value_iface_t * iface,void * vself,const char * str,size_t size)417 avro_datum_value_set_string_len(const avro_value_iface_t *iface,
418 void *vself, const char *str, size_t size)
419 {
420 AVRO_UNUSED(iface);
421 AVRO_UNUSED(size);
422 avro_datum_t self = (avro_datum_t) vself;
423 check_param(EINVAL, self, "datum instance");
424 return avro_string_set(self, str);
425 }
426
427 static int
avro_datum_value_give_string_len(const avro_value_iface_t * iface,void * vself,avro_wrapped_buffer_t * buf)428 avro_datum_value_give_string_len(const avro_value_iface_t *iface,
429 void *vself, avro_wrapped_buffer_t *buf)
430 {
431 /*
432 * We actually can't use avro_givestring_set, since it can't
433 * handle the extra free_ud parameter. Ah well, this is
434 * deprecated, so go ahead and make a copy.
435 */
436
437 int rval = avro_datum_value_set_string_len
438 (iface, vself, (char *) buf->buf, buf->size-1);
439 avro_wrapped_buffer_free(buf);
440 return rval;
441 }
442
443 static int
avro_datum_value_set_enum(const avro_value_iface_t * iface,void * vself,int val)444 avro_datum_value_set_enum(const avro_value_iface_t *iface,
445 void *vself, int val)
446 {
447 AVRO_UNUSED(iface);
448 avro_datum_t self = (avro_datum_t) vself;
449 check_param(EINVAL, self, "datum instance");
450 return avro_enum_set(self, val);
451 }
452
453 static int
avro_datum_value_set_fixed(const avro_value_iface_t * iface,void * vself,void * buf,size_t size)454 avro_datum_value_set_fixed(const avro_value_iface_t *iface,
455 void *vself, void *buf, size_t size)
456 {
457 AVRO_UNUSED(iface);
458 avro_datum_t self = (avro_datum_t) vself;
459 check_param(EINVAL, self, "datum instance");
460 return avro_fixed_set(self, (const char *) buf, size);
461 }
462
463 static int
avro_datum_value_give_fixed(const avro_value_iface_t * iface,void * vself,avro_wrapped_buffer_t * buf)464 avro_datum_value_give_fixed(const avro_value_iface_t *iface,
465 void *vself, avro_wrapped_buffer_t *buf)
466 {
467 /*
468 * We actually can't use avro_givefixed_set, since it can't
469 * handle the extra free_ud parameter. Ah well, this is
470 * deprecated, so go ahead and make a copy.
471 */
472
473 int rval = avro_datum_value_set_fixed
474 (iface, vself, (void *) buf->buf, buf->size);
475 avro_wrapped_buffer_free(buf);
476 return rval;
477 }
478
479
480 static int
avro_datum_value_get_size(const avro_value_iface_t * iface,const void * vself,size_t * size)481 avro_datum_value_get_size(const avro_value_iface_t *iface,
482 const void *vself, size_t *size)
483 {
484 AVRO_UNUSED(iface);
485 const avro_datum_t self = (const avro_datum_t) vself;
486 check_param(EINVAL, self, "datum instance");
487
488 if (is_avro_array(self)) {
489 *size = avro_array_size(self);
490 return 0;
491 }
492
493 if (is_avro_map(self)) {
494 *size = avro_map_size(self);
495 return 0;
496 }
497
498 if (is_avro_record(self)) {
499 avro_schema_t schema = avro_datum_get_schema(self);
500 *size = avro_schema_record_size(schema);
501 return 0;
502 }
503
504 avro_set_error("Can only get size of array, map, or record, %d", avro_typeof(self));
505 return EINVAL;
506 }
507
508 static int
avro_datum_value_get_by_index(const avro_value_iface_t * iface,const void * vself,size_t index,avro_value_t * child,const char ** name)509 avro_datum_value_get_by_index(const avro_value_iface_t *iface,
510 const void *vself, size_t index,
511 avro_value_t *child, const char **name)
512 {
513 AVRO_UNUSED(iface);
514 const avro_datum_t self = (const avro_datum_t) vself;
515 check_param(EINVAL, self, "datum instance");
516
517 int rval;
518 avro_datum_t child_datum;
519
520 if (is_avro_array(self)) {
521 check(rval, avro_array_get(self, index, &child_datum));
522 return avro_datum_as_child_value(child, child_datum);
523 }
524
525 if (is_avro_map(self)) {
526 const char *real_key;
527 check(rval, avro_map_get_key(self, index, &real_key));
528 if (name != NULL) {
529 *name = real_key;
530 }
531 check(rval, avro_map_get(self, real_key, &child_datum));
532 return avro_datum_as_child_value(child, child_datum);
533 }
534
535 if (is_avro_record(self)) {
536 avro_schema_t schema = avro_datum_get_schema(self);
537 const char *field_name =
538 avro_schema_record_field_name(schema, index);
539 if (field_name == NULL) {
540 return EINVAL;
541 }
542 if (name != NULL) {
543 *name = field_name;
544 }
545 check(rval, avro_record_get(self, field_name, &child_datum));
546 return avro_datum_as_child_value(child, child_datum);
547 }
548
549 avro_set_error("Can only get by index from array, map, or record");
550 return EINVAL;
551 }
552
553 static int
avro_datum_value_get_by_name(const avro_value_iface_t * iface,const void * vself,const char * name,avro_value_t * child,size_t * index)554 avro_datum_value_get_by_name(const avro_value_iface_t *iface,
555 const void *vself, const char *name,
556 avro_value_t *child, size_t *index)
557 {
558 AVRO_UNUSED(iface);
559 const avro_datum_t self = (const avro_datum_t) vself;
560 check_param(EINVAL, self, "datum instance");
561
562 int rval;
563 avro_datum_t child_datum;
564
565 if (is_avro_map(self)) {
566 if (index != NULL) {
567 int real_index;
568 check(rval, avro_map_get_index(self, name, &real_index));
569 *index = real_index;
570 }
571
572 check(rval, avro_map_get(self, name, &child_datum));
573 return avro_datum_as_child_value(child, child_datum);
574 }
575
576 if (is_avro_record(self)) {
577 if (index != NULL) {
578 avro_schema_t schema = avro_datum_get_schema(self);
579 *index = avro_schema_record_field_get_index(schema, name);
580 }
581
582 check(rval, avro_record_get(self, name, &child_datum));
583 return avro_datum_as_child_value(child, child_datum);
584 }
585
586 avro_set_error("Can only get by name from map or record");
587 return EINVAL;
588 }
589
590 static int
avro_datum_value_get_discriminant(const avro_value_iface_t * iface,const void * vself,int * out)591 avro_datum_value_get_discriminant(const avro_value_iface_t *iface,
592 const void *vself, int *out)
593 {
594 AVRO_UNUSED(iface);
595 const avro_datum_t self = (const avro_datum_t) vself;
596 check_param(EINVAL, self, "datum instance");
597
598 if (!is_avro_union(self)) {
599 avro_set_error("Can only get discriminant of union");
600 return EINVAL;
601 }
602
603 *out = avro_union_discriminant(self);
604 return 0;
605 }
606
607 static int
avro_datum_value_get_current_branch(const avro_value_iface_t * iface,const void * vself,avro_value_t * branch)608 avro_datum_value_get_current_branch(const avro_value_iface_t *iface,
609 const void *vself, avro_value_t *branch)
610 {
611 AVRO_UNUSED(iface);
612 const avro_datum_t self = (const avro_datum_t) vself;
613 check_param(EINVAL, self, "datum instance");
614
615 if (!is_avro_union(self)) {
616 avro_set_error("Can only get current branch of union");
617 return EINVAL;
618 }
619
620 avro_datum_t child_datum = avro_union_current_branch(self);
621 return avro_datum_as_child_value(branch, child_datum);
622 }
623
624
625 static int
avro_datum_value_append(const avro_value_iface_t * iface,void * vself,avro_value_t * child_out,size_t * new_index)626 avro_datum_value_append(const avro_value_iface_t *iface,
627 void *vself, avro_value_t *child_out, size_t *new_index)
628 {
629 AVRO_UNUSED(iface);
630 avro_datum_t self = (avro_datum_t) vself;
631 check_param(EINVAL, self, "datum instance");
632
633 if (!is_avro_array(self)) {
634 avro_set_error("Can only append to array");
635 return EINVAL;
636 }
637
638 int rval;
639
640 avro_schema_t array_schema = avro_datum_get_schema(self);
641 avro_schema_t child_schema = avro_schema_array_items(array_schema);
642 avro_datum_t child_datum = avro_datum_from_schema(child_schema);
643 if (child_datum == NULL) {
644 return ENOMEM;
645 }
646
647 rval = avro_array_append_datum(self, child_datum);
648 avro_datum_decref(child_datum);
649 if (rval != 0) {
650 return rval;
651 }
652
653 if (new_index != NULL) {
654 *new_index = avro_array_size(self) - 1;
655 }
656 return avro_datum_as_child_value(child_out, child_datum);
657 }
658
659 static int
avro_datum_value_add(const avro_value_iface_t * iface,void * vself,const char * key,avro_value_t * child,size_t * index,int * is_new)660 avro_datum_value_add(const avro_value_iface_t *iface,
661 void *vself, const char *key,
662 avro_value_t *child, size_t *index, int *is_new)
663 {
664 AVRO_UNUSED(iface);
665 avro_datum_t self = (avro_datum_t) vself;
666 check_param(EINVAL, self, "datum instance");
667
668 if (!is_avro_map(self)) {
669 avro_set_error("Can only add to map");
670 return EINVAL;
671 }
672
673 int rval;
674 avro_datum_t child_datum;
675
676 if (avro_map_get(self, key, &child_datum) == 0) {
677 /* key already exists */
678 if (is_new != NULL) {
679 *is_new = 0;
680 }
681 if (index != NULL) {
682 int real_index;
683 avro_map_get_index(self, key, &real_index);
684 *index = real_index;
685 }
686 return avro_datum_as_child_value(child, child_datum);
687 }
688
689 /* key is new */
690 avro_schema_t map_schema = avro_datum_get_schema(self);
691 avro_schema_t child_schema = avro_schema_map_values(map_schema);
692 child_datum = avro_datum_from_schema(child_schema);
693 if (child_datum == NULL) {
694 return ENOMEM;
695 }
696
697 rval = avro_map_set(self, key, child_datum);
698 avro_datum_decref(child_datum);
699 if (rval != 0) {
700 return rval;
701 }
702
703 if (is_new != NULL) {
704 *is_new = 1;
705 }
706 if (index != NULL) {
707 *index = avro_map_size(self) - 1;
708 }
709
710 return avro_datum_as_child_value(child, child_datum);
711 }
712
713 static int
avro_datum_value_set_branch(const avro_value_iface_t * iface,void * vself,int discriminant,avro_value_t * branch)714 avro_datum_value_set_branch(const avro_value_iface_t *iface,
715 void *vself, int discriminant,
716 avro_value_t *branch)
717 {
718 AVRO_UNUSED(iface);
719 const avro_datum_t self = (const avro_datum_t) vself;
720 check_param(EINVAL, self, "datum instance");
721
722 if (!is_avro_union(self)) {
723 avro_set_error("Can only set branch of union");
724 return EINVAL;
725 }
726
727 int rval;
728 avro_datum_t child_datum;
729 check(rval, avro_union_set_discriminant(self, discriminant, &child_datum));
730 return avro_datum_as_child_value(branch, child_datum);
731 }
732
733
734 avro_value_iface_t AVRO_DATUM_VALUE_CLASS =
735 {
736 /* "class" methods */
737 NULL, /* incref */
738 NULL, /* decref */
739 /* general "instance" methods */
740 avro_datum_value_incref,
741 avro_datum_value_decref,
742 avro_datum_value_reset,
743 avro_datum_value_get_type,
744 avro_datum_value_get_schema,
745 /* primitive getters */
746 avro_datum_value_get_boolean,
747 avro_datum_value_get_bytes,
748 avro_datum_value_grab_bytes,
749 avro_datum_value_get_double,
750 avro_datum_value_get_float,
751 avro_datum_value_get_int,
752 avro_datum_value_get_long,
753 avro_datum_value_get_null,
754 avro_datum_value_get_string,
755 avro_datum_value_grab_string,
756 avro_datum_value_get_enum,
757 avro_datum_value_get_fixed,
758 avro_datum_value_grab_fixed,
759 /* primitive setters */
760 avro_datum_value_set_boolean,
761 avro_datum_value_set_bytes,
762 avro_datum_value_give_bytes,
763 avro_datum_value_set_double,
764 avro_datum_value_set_float,
765 avro_datum_value_set_int,
766 avro_datum_value_set_long,
767 avro_datum_value_set_null,
768 avro_datum_value_set_string,
769 avro_datum_value_set_string_len,
770 avro_datum_value_give_string_len,
771 avro_datum_value_set_enum,
772 avro_datum_value_set_fixed,
773 avro_datum_value_give_fixed,
774 /* compound getters */
775 avro_datum_value_get_size,
776 avro_datum_value_get_by_index,
777 avro_datum_value_get_by_name,
778 avro_datum_value_get_discriminant,
779 avro_datum_value_get_current_branch,
780 /* compound setters */
781 avro_datum_value_append,
782 avro_datum_value_add,
783 avro_datum_value_set_branch
784 };
785