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/data.h" 24 #include "avro/errors.h" 25 #include "avro/generic.h" 26 #include "avro/refcount.h" 27 #include "avro/schema.h" 28 #include "avro/value.h" 29 #include "avro_generic_internal.h" 30 #include "avro_private.h" 31 32 33 /*----------------------------------------------------------------------- 34 * Forward definitions 35 */ 36 37 typedef struct avro_generic_link_value_iface avro_generic_link_value_iface_t; 38 39 typedef struct memoize_state_t { 40 avro_memoize_t mem; 41 avro_generic_link_value_iface_t *links; 42 } memoize_state_t; 43 44 static avro_generic_value_iface_t * 45 avro_generic_class_from_schema_memoized(avro_schema_t schema, 46 memoize_state_t *state); 47 48 49 /*----------------------------------------------------------------------- 50 * Generic support functions 51 */ 52 53 int 54 avro_generic_value_new(avro_value_iface_t *iface, avro_value_t *dest) 55 { 56 int rval; 57 avro_generic_value_iface_t *giface = 58 container_of(iface, avro_generic_value_iface_t, parent); 59 size_t instance_size = avro_value_instance_size(giface); 60 void *self = avro_malloc(instance_size + sizeof(volatile int)); 61 if (self == NULL) { 62 avro_set_error(strerror(ENOMEM)); 63 dest->iface = NULL; 64 dest->self = NULL; 65 return ENOMEM; 66 } 67 68 volatile int *refcount = (volatile int *) self; 69 self = (char *) self + sizeof(volatile int); 70 71 *refcount = 1; 72 rval = avro_value_init(giface, self); 73 if (rval != 0) { 74 avro_free(self, instance_size); 75 dest->iface = NULL; 76 dest->self = NULL; 77 return rval; 78 } 79 80 dest->iface = avro_value_iface_incref(&giface->parent); 81 dest->self = self; 82 return 0; 83 } 84 85 static void 86 avro_generic_value_free(const avro_value_iface_t *iface, void *self) 87 { 88 if (self != NULL) { 89 const avro_generic_value_iface_t *giface = 90 container_of(iface, avro_generic_value_iface_t, parent); 91 size_t instance_size = avro_value_instance_size(giface); 92 avro_value_done(giface, self); 93 self = (char *) self - sizeof(volatile int); 94 avro_free(self, instance_size + sizeof(volatile int)); 95 } 96 } 97 98 static void 99 avro_generic_value_incref(avro_value_t *value) 100 { 101 /* 102 * This only works if you pass in the top-level value. 103 */ 104 105 volatile int *refcount = (volatile int *) ((char *) value->self - sizeof(volatile int)); 106 avro_refcount_inc(refcount); 107 } 108 109 static void 110 avro_generic_value_decref(avro_value_t *value) 111 { 112 /* 113 * This only works if you pass in the top-level value. 114 */ 115 116 volatile int *refcount = (volatile int *) ((char *) value->self - sizeof(volatile int)); 117 if (avro_refcount_dec(refcount)) { 118 avro_generic_value_free(value->iface, value->self); 119 } 120 } 121 122 123 /*----------------------------------------------------------------------- 124 * Recursive schemas 125 */ 126 127 /* 128 * Recursive schemas are handled specially; the value implementation for 129 * an AVRO_LINK schema is simply a wrapper around the value 130 * implementation for the link's target schema. The value methods all 131 * delegate to the wrapped implementation. 132 * 133 * We don't set the target_iface pointer when the link implementation is 134 * first created, since we might not have finished creating the 135 * implementation for the target schema. (We create the implementations 136 * for child schemas depth-first, so the target schema's implementation 137 * won't be done until all of its descendants — including the link 138 * schema — have been instantiated.) 139 * 140 * So anyway, we set the target_iface pointer to NULL at first. And 141 * then in a fix-up stage, once all of the non-link schemas have been 142 * instantiated, we go through and set the target_iface pointers for any 143 * link schemas we encountered. 144 */ 145 146 struct avro_generic_link_value_iface { 147 avro_generic_value_iface_t parent; 148 149 /** The reference count for this interface. */ 150 volatile int refcount; 151 152 /** The schema for this interface. */ 153 avro_schema_t schema; 154 155 /** The target's implementation. */ 156 avro_generic_value_iface_t *target_giface; 157 158 /** 159 * A pointer to the “next” link interface that we've had to 160 * create. We use this as we're creating the overall top-level 161 * value interface to keep track of which ones we have to fix up 162 * afterwards. 163 */ 164 avro_generic_link_value_iface_t *next; 165 }; 166 167 168 static avro_value_iface_t * 169 avro_generic_link_incref_iface(avro_value_iface_t *viface) 170 { 171 avro_generic_link_value_iface_t *iface = 172 container_of(viface, avro_generic_link_value_iface_t, parent); 173 avro_refcount_inc(&iface->refcount); 174 return viface; 175 } 176 177 static void 178 avro_generic_link_decref_iface(avro_value_iface_t *viface) 179 { 180 avro_generic_link_value_iface_t *iface = 181 container_of(viface, avro_generic_link_value_iface_t, parent.parent); 182 183 if (avro_refcount_dec(&iface->refcount)) { 184 /* We don't keep a reference to the target 185 * implementation, since that would give us a reference 186 * cycle. */ 187 /* We do however keep a reference to the target 188 * schema, which we need to decrement before freeing 189 * the link */ 190 avro_schema_decref(iface->schema); 191 avro_freet(avro_generic_link_value_iface_t, iface); 192 } 193 } 194 195 196 static int 197 avro_generic_link_reset(const avro_value_iface_t *iface, void *vself) 198 { 199 AVRO_UNUSED(iface); 200 avro_value_t *self = (avro_value_t *) vself; 201 return avro_value_reset(self); 202 } 203 204 static avro_type_t 205 avro_generic_link_get_type(const avro_value_iface_t *viface, const void *vself) 206 { 207 AVRO_UNUSED(viface); 208 const avro_value_t *self = (const avro_value_t *) vself; 209 return avro_value_get_type(self); 210 } 211 212 static avro_schema_t 213 avro_generic_link_get_schema(const avro_value_iface_t *viface, const void *vself) 214 { 215 AVRO_UNUSED(viface); 216 const avro_value_t *self = (const avro_value_t *) vself; 217 return avro_value_get_schema(self); 218 } 219 220 static int 221 avro_generic_link_get_boolean(const avro_value_iface_t *iface, 222 const void *vself, int *out) 223 { 224 AVRO_UNUSED(iface); 225 const avro_value_t *self = (const avro_value_t *) vself; 226 return avro_value_get_boolean(self, out); 227 } 228 229 static int 230 avro_generic_link_get_bytes(const avro_value_iface_t *iface, 231 const void *vself, const void **buf, size_t *size) 232 { 233 AVRO_UNUSED(iface); 234 const avro_value_t *self = (const avro_value_t *) vself; 235 return avro_value_get_bytes(self, buf, size); 236 } 237 238 static int 239 avro_generic_link_grab_bytes(const avro_value_iface_t *iface, 240 const void *vself, avro_wrapped_buffer_t *dest) 241 { 242 AVRO_UNUSED(iface); 243 const avro_value_t *self = (const avro_value_t *) vself; 244 return avro_value_grab_bytes(self, dest); 245 } 246 247 static int 248 avro_generic_link_get_double(const avro_value_iface_t *iface, 249 const void *vself, double *out) 250 { 251 AVRO_UNUSED(iface); 252 const avro_value_t *self = (const avro_value_t *) vself; 253 return avro_value_get_double(self, out); 254 } 255 256 static int 257 avro_generic_link_get_float(const avro_value_iface_t *iface, 258 const void *vself, float *out) 259 { 260 AVRO_UNUSED(iface); 261 const avro_value_t *self = (const avro_value_t *) vself; 262 return avro_value_get_float(self, out); 263 } 264 265 static int 266 avro_generic_link_get_int(const avro_value_iface_t *iface, 267 const void *vself, int32_t *out) 268 { 269 AVRO_UNUSED(iface); 270 const avro_value_t *self = (const avro_value_t *) vself; 271 return avro_value_get_int(self, out); 272 } 273 274 static int 275 avro_generic_link_get_long(const avro_value_iface_t *iface, 276 const void *vself, int64_t *out) 277 { 278 AVRO_UNUSED(iface); 279 const avro_value_t *self = (const avro_value_t *) vself; 280 return avro_value_get_long(self, out); 281 } 282 283 static int 284 avro_generic_link_get_null(const avro_value_iface_t *iface, const void *vself) 285 { 286 AVRO_UNUSED(iface); 287 const avro_value_t *self = (const avro_value_t *) vself; 288 return avro_value_get_null(self); 289 } 290 291 static int 292 avro_generic_link_get_string(const avro_value_iface_t *iface, 293 const void *vself, const char **str, size_t *size) 294 { 295 AVRO_UNUSED(iface); 296 const avro_value_t *self = (const avro_value_t *) vself; 297 return avro_value_get_string(self, str, size); 298 } 299 300 static int 301 avro_generic_link_grab_string(const avro_value_iface_t *iface, 302 const void *vself, avro_wrapped_buffer_t *dest) 303 { 304 AVRO_UNUSED(iface); 305 const avro_value_t *self = (const avro_value_t *) vself; 306 return avro_value_grab_string(self, dest); 307 } 308 309 static int 310 avro_generic_link_get_enum(const avro_value_iface_t *iface, 311 const void *vself, int *out) 312 { 313 AVRO_UNUSED(iface); 314 const avro_value_t *self = (const avro_value_t *) vself; 315 return avro_value_get_enum(self, out); 316 } 317 318 static int 319 avro_generic_link_get_fixed(const avro_value_iface_t *iface, 320 const void *vself, const void **buf, size_t *size) 321 { 322 AVRO_UNUSED(iface); 323 const avro_value_t *self = (const avro_value_t *) vself; 324 return avro_value_get_fixed(self, buf, size); 325 } 326 327 static int 328 avro_generic_link_grab_fixed(const avro_value_iface_t *iface, 329 const void *vself, avro_wrapped_buffer_t *dest) 330 { 331 AVRO_UNUSED(iface); 332 const avro_value_t *self = (const avro_value_t *) vself; 333 return avro_value_grab_fixed(self, dest); 334 } 335 336 static int 337 avro_generic_link_set_boolean(const avro_value_iface_t *iface, 338 void *vself, int val) 339 { 340 AVRO_UNUSED(iface); 341 avro_value_t *self = (avro_value_t *) vself; 342 return avro_value_set_boolean(self, val); 343 } 344 345 static int 346 avro_generic_link_set_bytes(const avro_value_iface_t *iface, 347 void *vself, void *buf, size_t size) 348 { 349 AVRO_UNUSED(iface); 350 avro_value_t *self = (avro_value_t *) vself; 351 return avro_value_set_bytes(self, buf, size); 352 } 353 354 static int 355 avro_generic_link_give_bytes(const avro_value_iface_t *iface, 356 void *vself, avro_wrapped_buffer_t *buf) 357 { 358 AVRO_UNUSED(iface); 359 avro_value_t *self = (avro_value_t *) vself; 360 return avro_value_give_bytes(self, buf); 361 } 362 363 static int 364 avro_generic_link_set_double(const avro_value_iface_t *iface, 365 void *vself, double val) 366 { 367 AVRO_UNUSED(iface); 368 avro_value_t *self = (avro_value_t *) vself; 369 return avro_value_set_double(self, val); 370 } 371 372 static int 373 avro_generic_link_set_float(const avro_value_iface_t *iface, 374 void *vself, float val) 375 { 376 AVRO_UNUSED(iface); 377 avro_value_t *self = (avro_value_t *) vself; 378 return avro_value_set_float(self, val); 379 } 380 381 static int 382 avro_generic_link_set_int(const avro_value_iface_t *iface, 383 void *vself, int32_t val) 384 { 385 AVRO_UNUSED(iface); 386 avro_value_t *self = (avro_value_t *) vself; 387 return avro_value_set_int(self, val); 388 } 389 390 static int 391 avro_generic_link_set_long(const avro_value_iface_t *iface, 392 void *vself, int64_t val) 393 { 394 AVRO_UNUSED(iface); 395 avro_value_t *self = (avro_value_t *) vself; 396 return avro_value_set_long(self, val); 397 } 398 399 static int 400 avro_generic_link_set_null(const avro_value_iface_t *iface, void *vself) 401 { 402 AVRO_UNUSED(iface); 403 avro_value_t *self = (avro_value_t *) vself; 404 return avro_value_set_null(self); 405 } 406 407 static int 408 avro_generic_link_set_string(const avro_value_iface_t *iface, 409 void *vself, const char *str) 410 { 411 AVRO_UNUSED(iface); 412 avro_value_t *self = (avro_value_t *) vself; 413 return avro_value_set_string(self, str); 414 } 415 416 static int 417 avro_generic_link_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_value_t *self = (avro_value_t *) vself; 422 return avro_value_set_string_len(self, str, size); 423 } 424 425 static int 426 avro_generic_link_give_string_len(const avro_value_iface_t *iface, 427 void *vself, avro_wrapped_buffer_t *buf) 428 { 429 AVRO_UNUSED(iface); 430 avro_value_t *self = (avro_value_t *) vself; 431 return avro_value_give_string_len(self, buf); 432 } 433 434 static int 435 avro_generic_link_set_enum(const avro_value_iface_t *iface, 436 void *vself, int val) 437 { 438 AVRO_UNUSED(iface); 439 avro_value_t *self = (avro_value_t *) vself; 440 return avro_value_set_enum(self, val); 441 } 442 443 static int 444 avro_generic_link_set_fixed(const avro_value_iface_t *iface, 445 void *vself, void *buf, size_t size) 446 { 447 AVRO_UNUSED(iface); 448 avro_value_t *self = (avro_value_t *) vself; 449 return avro_value_set_fixed(self, buf, size); 450 } 451 452 static int 453 avro_generic_link_give_fixed(const avro_value_iface_t *iface, 454 void *vself, avro_wrapped_buffer_t *buf) 455 { 456 AVRO_UNUSED(iface); 457 avro_value_t *self = (avro_value_t *) vself; 458 return avro_value_give_fixed(self, buf); 459 } 460 461 static int 462 avro_generic_link_get_size(const avro_value_iface_t *iface, 463 const void *vself, size_t *size) 464 { 465 AVRO_UNUSED(iface); 466 const avro_value_t *self = (const avro_value_t *) vself; 467 return avro_value_get_size(self, size); 468 } 469 470 static int 471 avro_generic_link_get_by_index(const avro_value_iface_t *iface, 472 const void *vself, size_t index, 473 avro_value_t *child, const char **name) 474 { 475 AVRO_UNUSED(iface); 476 const avro_value_t *self = (const avro_value_t *) vself; 477 return avro_value_get_by_index(self, index, child, name); 478 } 479 480 static int 481 avro_generic_link_get_by_name(const avro_value_iface_t *iface, 482 const void *vself, const char *name, 483 avro_value_t *child, size_t *index) 484 { 485 AVRO_UNUSED(iface); 486 const avro_value_t *self = (const avro_value_t *) vself; 487 return avro_value_get_by_name(self, name, child, index); 488 } 489 490 static int 491 avro_generic_link_get_discriminant(const avro_value_iface_t *iface, 492 const void *vself, int *out) 493 { 494 AVRO_UNUSED(iface); 495 const avro_value_t *self = (const avro_value_t *) vself; 496 return avro_value_get_discriminant(self, out); 497 } 498 499 static int 500 avro_generic_link_get_current_branch(const avro_value_iface_t *iface, 501 const void *vself, avro_value_t *branch) 502 { 503 AVRO_UNUSED(iface); 504 const avro_value_t *self = (const avro_value_t *) vself; 505 return avro_value_get_current_branch(self, branch); 506 } 507 508 static int 509 avro_generic_link_append(const avro_value_iface_t *iface, 510 void *vself, avro_value_t *child_out, 511 size_t *new_index) 512 { 513 AVRO_UNUSED(iface); 514 avro_value_t *self = (avro_value_t *) vself; 515 return avro_value_append(self, child_out, new_index); 516 } 517 518 static int 519 avro_generic_link_add(const avro_value_iface_t *iface, 520 void *vself, const char *key, 521 avro_value_t *child, size_t *index, int *is_new) 522 { 523 AVRO_UNUSED(iface); 524 avro_value_t *self = (avro_value_t *) vself; 525 return avro_value_add(self, key, child, index, is_new); 526 } 527 528 static int 529 avro_generic_link_set_branch(const avro_value_iface_t *iface, 530 void *vself, int discriminant, 531 avro_value_t *branch) 532 { 533 AVRO_UNUSED(iface); 534 avro_value_t *self = (avro_value_t *) vself; 535 return avro_value_set_branch(self, discriminant, branch); 536 } 537 538 static size_t 539 avro_generic_link_instance_size(const avro_value_iface_t *viface) 540 { 541 AVRO_UNUSED(viface); 542 return sizeof(avro_value_t); 543 } 544 545 static int 546 avro_generic_link_init(const avro_value_iface_t *viface, void *vself) 547 { 548 int rval; 549 550 avro_generic_link_value_iface_t *iface = 551 container_of(viface, avro_generic_link_value_iface_t, parent.parent); 552 553 avro_value_t *self = (avro_value_t *) vself; 554 ssize_t target_instance_size = 555 avro_value_instance_size(iface->target_giface); 556 if (target_instance_size < 0) { 557 return EINVAL; 558 } 559 560 self->iface = &iface->target_giface->parent; 561 562 if (target_instance_size == 0) { 563 self->self = NULL; 564 } else { 565 self->self = avro_malloc(target_instance_size); 566 if (self->self == NULL) { 567 return ENOMEM; 568 } 569 } 570 571 rval = avro_value_init(iface->target_giface, self->self); 572 if (rval != 0) { 573 avro_free(self->self, target_instance_size); 574 } 575 return rval; 576 } 577 578 static void 579 avro_generic_link_done(const avro_value_iface_t *iface, void *vself) 580 { 581 AVRO_UNUSED(iface); 582 avro_value_t *self = (avro_value_t *) vself; 583 avro_generic_value_iface_t *target_giface = 584 container_of(self->iface, avro_generic_value_iface_t, parent); 585 size_t target_instance_size = avro_value_instance_size(target_giface); 586 avro_value_done(target_giface, self->self); 587 avro_free(self->self, target_instance_size); 588 self->iface = NULL; 589 self->self = NULL; 590 } 591 592 static avro_generic_value_iface_t AVRO_GENERIC_LINK_CLASS = 593 { 594 { 595 /* "class" methods */ 596 avro_generic_link_incref_iface, 597 avro_generic_link_decref_iface, 598 /* general "instance" methods */ 599 avro_generic_value_incref, 600 avro_generic_value_decref, 601 avro_generic_link_reset, 602 avro_generic_link_get_type, 603 avro_generic_link_get_schema, 604 /* primitive getters */ 605 avro_generic_link_get_boolean, 606 avro_generic_link_get_bytes, 607 avro_generic_link_grab_bytes, 608 avro_generic_link_get_double, 609 avro_generic_link_get_float, 610 avro_generic_link_get_int, 611 avro_generic_link_get_long, 612 avro_generic_link_get_null, 613 avro_generic_link_get_string, 614 avro_generic_link_grab_string, 615 avro_generic_link_get_enum, 616 avro_generic_link_get_fixed, 617 avro_generic_link_grab_fixed, 618 /* primitive setters */ 619 avro_generic_link_set_boolean, 620 avro_generic_link_set_bytes, 621 avro_generic_link_give_bytes, 622 avro_generic_link_set_double, 623 avro_generic_link_set_float, 624 avro_generic_link_set_int, 625 avro_generic_link_set_long, 626 avro_generic_link_set_null, 627 avro_generic_link_set_string, 628 avro_generic_link_set_string_len, 629 avro_generic_link_give_string_len, 630 avro_generic_link_set_enum, 631 avro_generic_link_set_fixed, 632 avro_generic_link_give_fixed, 633 /* compound getters */ 634 avro_generic_link_get_size, 635 avro_generic_link_get_by_index, 636 avro_generic_link_get_by_name, 637 avro_generic_link_get_discriminant, 638 avro_generic_link_get_current_branch, 639 /* compound setters */ 640 avro_generic_link_append, 641 avro_generic_link_add, 642 avro_generic_link_set_branch 643 }, 644 avro_generic_link_instance_size, 645 avro_generic_link_init, 646 avro_generic_link_done 647 }; 648 649 static avro_generic_link_value_iface_t * 650 avro_generic_link_class(avro_schema_t schema) 651 { 652 if (!is_avro_link(schema)) { 653 avro_set_error("Expected link schema"); 654 return NULL; 655 } 656 657 avro_generic_link_value_iface_t *iface = 658 (avro_generic_link_value_iface_t *) avro_new(avro_generic_link_value_iface_t); 659 if (iface == NULL) { 660 return NULL; 661 } 662 663 iface->parent = AVRO_GENERIC_LINK_CLASS; 664 iface->refcount = 1; 665 iface->schema = avro_schema_incref(schema); 666 iface->next = NULL; 667 return iface; 668 } 669 670 671 /*----------------------------------------------------------------------- 672 * boolean 673 */ 674 675 static int 676 avro_generic_boolean_reset(const avro_value_iface_t *iface, void *vself) 677 { 678 AVRO_UNUSED(iface); 679 int *self = (int *) vself; 680 *self = 0; 681 return 0; 682 } 683 684 static avro_type_t 685 avro_generic_boolean_get_type(const avro_value_iface_t *iface, const void *vself) 686 { 687 AVRO_UNUSED(iface); 688 AVRO_UNUSED(vself); 689 return AVRO_BOOLEAN; 690 } 691 692 static avro_schema_t 693 avro_generic_boolean_get_schema(const avro_value_iface_t *iface, const void *vself) 694 { 695 AVRO_UNUSED(iface); 696 AVRO_UNUSED(vself); 697 return avro_schema_boolean(); 698 } 699 700 static int 701 avro_generic_boolean_get(const avro_value_iface_t *iface, 702 const void *vself, int *out) 703 { 704 AVRO_UNUSED(iface); 705 const int *self = (const int *) vself; 706 *out = *self; 707 return 0; 708 } 709 710 static int 711 avro_generic_boolean_set(const avro_value_iface_t *iface, 712 void *vself, int val) 713 { 714 AVRO_UNUSED(iface); 715 int *self = (int *) vself; 716 *self = val; 717 return 0; 718 } 719 720 static size_t 721 avro_generic_boolean_instance_size(const avro_value_iface_t *iface) 722 { 723 AVRO_UNUSED(iface); 724 return sizeof(int); 725 } 726 727 static int 728 avro_generic_boolean_init(const avro_value_iface_t *iface, void *vself) 729 { 730 AVRO_UNUSED(iface); 731 int *self = (int *) vself; 732 *self = 0; 733 return 0; 734 } 735 736 static void 737 avro_generic_boolean_done(const avro_value_iface_t *iface, void *vself) 738 { 739 AVRO_UNUSED(iface); 740 AVRO_UNUSED(vself); 741 } 742 743 static avro_generic_value_iface_t AVRO_GENERIC_BOOLEAN_CLASS = 744 { 745 { 746 /* "class" methods */ 747 NULL, /* incref_iface */ 748 NULL, /* decref_iface */ 749 /* general "instance" methods */ 750 avro_generic_value_incref, 751 avro_generic_value_decref, 752 avro_generic_boolean_reset, 753 avro_generic_boolean_get_type, 754 avro_generic_boolean_get_schema, 755 /* primitive getters */ 756 avro_generic_boolean_get, 757 NULL, /* get_bytes */ 758 NULL, /* grab_bytes */ 759 NULL, /* get_double */ 760 NULL, /* get_float */ 761 NULL, /* get_int */ 762 NULL, /* get_long */ 763 NULL, /* get_null */ 764 NULL, /* get_string */ 765 NULL, /* grab_string */ 766 NULL, /* get_enum */ 767 NULL, /* get_fixed */ 768 NULL, /* grab_fixed */ 769 /* primitive setters */ 770 avro_generic_boolean_set, 771 NULL, /* set_bytes */ 772 NULL, /* give_bytes */ 773 NULL, /* set_double */ 774 NULL, /* set_float */ 775 NULL, /* set_int */ 776 NULL, /* set_long */ 777 NULL, /* set_null */ 778 NULL, /* set_string */ 779 NULL, /* set_string_length */ 780 NULL, /* give_string_length */ 781 NULL, /* set_enum */ 782 NULL, /* set_fixed */ 783 NULL, /* give_fixed */ 784 /* compound getters */ 785 NULL, /* get_size */ 786 NULL, /* get_by_index */ 787 NULL, /* get_by_name */ 788 NULL, /* get_discriminant */ 789 NULL, /* get_current_branch */ 790 /* compound setters */ 791 NULL, /* append */ 792 NULL, /* add */ 793 NULL /* set_branch */ 794 }, 795 avro_generic_boolean_instance_size, 796 avro_generic_boolean_init, 797 avro_generic_boolean_done 798 }; 799 800 avro_value_iface_t * 801 avro_generic_boolean_class(void) 802 { 803 return &AVRO_GENERIC_BOOLEAN_CLASS.parent; 804 } 805 806 int 807 avro_generic_boolean_new(avro_value_t *value, int val) 808 { 809 int rval; 810 check(rval, avro_generic_value_new(&AVRO_GENERIC_BOOLEAN_CLASS.parent, value)); 811 return avro_generic_boolean_set(value->iface, value->self, val); 812 } 813 814 /*----------------------------------------------------------------------- 815 * bytes 816 */ 817 818 static int 819 avro_generic_bytes_reset(const avro_value_iface_t *iface, void *vself) 820 { 821 AVRO_UNUSED(iface); 822 avro_raw_string_t *self = (avro_raw_string_t *) vself; 823 avro_raw_string_clear(self); 824 return 0; 825 } 826 827 static avro_type_t 828 avro_generic_bytes_get_type(const avro_value_iface_t *iface, const void *vself) 829 { 830 AVRO_UNUSED(iface); 831 AVRO_UNUSED(vself); 832 return AVRO_BYTES; 833 } 834 835 static avro_schema_t 836 avro_generic_bytes_get_schema(const avro_value_iface_t *iface, const void *vself) 837 { 838 AVRO_UNUSED(iface); 839 AVRO_UNUSED(vself); 840 return avro_schema_bytes(); 841 } 842 843 static int 844 avro_generic_bytes_get(const avro_value_iface_t *iface, 845 const void *vself, const void **buf, size_t *size) 846 { 847 AVRO_UNUSED(iface); 848 const avro_raw_string_t *self = (const avro_raw_string_t *) vself; 849 if (buf != NULL) { 850 *buf = avro_raw_string_get(self); 851 } 852 if (size != NULL) { 853 *size = avro_raw_string_length(self); 854 } 855 return 0; 856 } 857 858 static int 859 avro_generic_bytes_grab(const avro_value_iface_t *iface, 860 const void *vself, avro_wrapped_buffer_t *dest) 861 { 862 AVRO_UNUSED(iface); 863 const avro_raw_string_t *self = (const avro_raw_string_t *) vself; 864 return avro_raw_string_grab(self, dest); 865 } 866 867 static int 868 avro_generic_bytes_set(const avro_value_iface_t *iface, 869 void *vself, void *buf, size_t size) 870 { 871 AVRO_UNUSED(iface); 872 check_param(EINVAL, buf != NULL, "bytes contents"); 873 avro_raw_string_t *self = (avro_raw_string_t *) vself; 874 avro_raw_string_set_length(self, buf, size); 875 return 0; 876 } 877 878 static int 879 avro_generic_bytes_give(const avro_value_iface_t *iface, 880 void *vself, avro_wrapped_buffer_t *buf) 881 { 882 AVRO_UNUSED(iface); 883 avro_raw_string_t *self = (avro_raw_string_t *) vself; 884 avro_raw_string_give(self, buf); 885 return 0; 886 } 887 888 static size_t 889 avro_generic_bytes_instance_size(const avro_value_iface_t *iface) 890 { 891 AVRO_UNUSED(iface); 892 return sizeof(avro_raw_string_t); 893 } 894 895 static int 896 avro_generic_bytes_init(const avro_value_iface_t *iface, void *vself) 897 { 898 AVRO_UNUSED(iface); 899 avro_raw_string_t *self = (avro_raw_string_t *) vself; 900 avro_raw_string_init(self); 901 return 0; 902 } 903 904 static void 905 avro_generic_bytes_done(const avro_value_iface_t *iface, void *vself) 906 { 907 AVRO_UNUSED(iface); 908 avro_raw_string_t *self = (avro_raw_string_t *) vself; 909 avro_raw_string_done(self); 910 } 911 912 static avro_generic_value_iface_t AVRO_GENERIC_BYTES_CLASS = 913 { 914 { 915 /* "class" methods */ 916 NULL, /* incref_iface */ 917 NULL, /* decref_iface */ 918 /* general "instance" methods */ 919 avro_generic_value_incref, 920 avro_generic_value_decref, 921 avro_generic_bytes_reset, 922 avro_generic_bytes_get_type, 923 avro_generic_bytes_get_schema, 924 /* primitive getters */ 925 NULL, /* get_boolean */ 926 avro_generic_bytes_get, 927 avro_generic_bytes_grab, 928 NULL, /* get_double */ 929 NULL, /* get_float */ 930 NULL, /* get_int */ 931 NULL, /* get_long */ 932 NULL, /* get_null */ 933 NULL, /* get_string */ 934 NULL, /* grab_string */ 935 NULL, /* get_enum */ 936 NULL, /* get_fixed */ 937 NULL, /* grab_fixed */ 938 /* primitive setters */ 939 NULL, /* set_boolean */ 940 avro_generic_bytes_set, 941 avro_generic_bytes_give, 942 NULL, /* set_double */ 943 NULL, /* set_float */ 944 NULL, /* set_int */ 945 NULL, /* set_long */ 946 NULL, /* set_null */ 947 NULL, /* set_string */ 948 NULL, /* set_string_length */ 949 NULL, /* give_string_length */ 950 NULL, /* set_enum */ 951 NULL, /* set_fixed */ 952 NULL, /* give_fixed */ 953 /* compound getters */ 954 NULL, /* get_size */ 955 NULL, /* get_by_index */ 956 NULL, /* get_by_name */ 957 NULL, /* get_discriminant */ 958 NULL, /* get_current_branch */ 959 /* compound setters */ 960 NULL, /* append */ 961 NULL, /* add */ 962 NULL /* set_branch */ 963 }, 964 avro_generic_bytes_instance_size, 965 avro_generic_bytes_init, 966 avro_generic_bytes_done 967 }; 968 969 avro_value_iface_t * 970 avro_generic_bytes_class(void) 971 { 972 return &AVRO_GENERIC_BYTES_CLASS.parent; 973 } 974 975 int 976 avro_generic_bytes_new(avro_value_t *value, void *buf, size_t size) 977 { 978 int rval; 979 check(rval, avro_generic_value_new(&AVRO_GENERIC_BYTES_CLASS.parent, value)); 980 return avro_generic_bytes_set(value->iface, value->self, buf, size); 981 } 982 983 /*----------------------------------------------------------------------- 984 * double 985 */ 986 987 static int 988 avro_generic_double_reset(const avro_value_iface_t *iface, void *vself) 989 { 990 AVRO_UNUSED(iface); 991 double *self = (double *) vself; 992 *self = 0.0; 993 return 0; 994 } 995 996 static avro_type_t 997 avro_generic_double_get_type(const avro_value_iface_t *iface, const void *vself) 998 { 999 AVRO_UNUSED(iface); 1000 AVRO_UNUSED(vself); 1001 return AVRO_DOUBLE; 1002 } 1003 1004 static avro_schema_t 1005 avro_generic_double_get_schema(const avro_value_iface_t *iface, const void *vself) 1006 { 1007 AVRO_UNUSED(iface); 1008 AVRO_UNUSED(vself); 1009 return avro_schema_double(); 1010 } 1011 1012 static int 1013 avro_generic_double_get(const avro_value_iface_t *iface, 1014 const void *vself, double *out) 1015 { 1016 AVRO_UNUSED(iface); 1017 const double *self = (const double *) vself; 1018 *out = *self; 1019 return 0; 1020 } 1021 1022 static int 1023 avro_generic_double_set(const avro_value_iface_t *iface, 1024 void *vself, double val) 1025 { 1026 AVRO_UNUSED(iface); 1027 double *self = (double *) vself; 1028 *self = val; 1029 return 0; 1030 } 1031 1032 static size_t 1033 avro_generic_double_instance_size(const avro_value_iface_t *iface) 1034 { 1035 AVRO_UNUSED(iface); 1036 return sizeof(double); 1037 } 1038 1039 static int 1040 avro_generic_double_init(const avro_value_iface_t *iface, void *vself) 1041 { 1042 AVRO_UNUSED(iface); 1043 double *self = (double *) vself; 1044 *self = 0.0; 1045 return 0; 1046 } 1047 1048 static void 1049 avro_generic_double_done(const avro_value_iface_t *iface, void *vself) 1050 { 1051 AVRO_UNUSED(iface); 1052 AVRO_UNUSED(vself); 1053 } 1054 1055 static avro_generic_value_iface_t AVRO_GENERIC_DOUBLE_CLASS = 1056 { 1057 { 1058 /* "class" methods */ 1059 NULL, /* incref_iface */ 1060 NULL, /* decref_iface */ 1061 /* general "instance" methods */ 1062 avro_generic_value_incref, 1063 avro_generic_value_decref, 1064 avro_generic_double_reset, 1065 avro_generic_double_get_type, 1066 avro_generic_double_get_schema, 1067 /* primitive getters */ 1068 NULL, /* get_boolean */ 1069 NULL, /* get_bytes */ 1070 NULL, /* grab_bytes */ 1071 avro_generic_double_get, 1072 NULL, /* get_float */ 1073 NULL, /* get_int */ 1074 NULL, /* get_long */ 1075 NULL, /* get_null */ 1076 NULL, /* get_string */ 1077 NULL, /* grab_string */ 1078 NULL, /* get_enum */ 1079 NULL, /* get_fixed */ 1080 NULL, /* grab_fixed */ 1081 /* primitive setters */ 1082 NULL, /* set_boolean */ 1083 NULL, /* set_bytes */ 1084 NULL, /* give_bytes */ 1085 avro_generic_double_set, 1086 NULL, /* set_float */ 1087 NULL, /* set_int */ 1088 NULL, /* set_long */ 1089 NULL, /* set_null */ 1090 NULL, /* set_string */ 1091 NULL, /* set_string_length */ 1092 NULL, /* give_string_length */ 1093 NULL, /* set_enum */ 1094 NULL, /* set_fixed */ 1095 NULL, /* give_fixed */ 1096 /* compound getters */ 1097 NULL, /* get_size */ 1098 NULL, /* get_by_index */ 1099 NULL, /* get_by_name */ 1100 NULL, /* get_discriminant */ 1101 NULL, /* get_current_branch */ 1102 /* compound setters */ 1103 NULL, /* append */ 1104 NULL, /* add */ 1105 NULL /* set_branch */ 1106 }, 1107 avro_generic_double_instance_size, 1108 avro_generic_double_init, 1109 avro_generic_double_done 1110 }; 1111 1112 avro_value_iface_t * 1113 avro_generic_double_class(void) 1114 { 1115 return &AVRO_GENERIC_DOUBLE_CLASS.parent; 1116 } 1117 1118 int 1119 avro_generic_double_new(avro_value_t *value, double val) 1120 { 1121 int rval; 1122 check(rval, avro_generic_value_new(&AVRO_GENERIC_DOUBLE_CLASS.parent, value)); 1123 return avro_generic_double_set(value->iface, value->self, val); 1124 } 1125 1126 /*----------------------------------------------------------------------- 1127 * float 1128 */ 1129 1130 static int 1131 avro_generic_float_reset(const avro_value_iface_t *iface, void *vself) 1132 { 1133 AVRO_UNUSED(iface); 1134 float *self = (float *) vself; 1135 *self = 0.0f; 1136 return 0; 1137 } 1138 1139 static avro_type_t 1140 avro_generic_float_get_type(const avro_value_iface_t *iface, const void *vself) 1141 { 1142 AVRO_UNUSED(iface); 1143 AVRO_UNUSED(vself); 1144 return AVRO_FLOAT; 1145 } 1146 1147 static avro_schema_t 1148 avro_generic_float_get_schema(const avro_value_iface_t *iface, const void *vself) 1149 { 1150 AVRO_UNUSED(iface); 1151 AVRO_UNUSED(vself); 1152 return avro_schema_float(); 1153 } 1154 1155 static int 1156 avro_generic_float_get(const avro_value_iface_t *iface, 1157 const void *vself, float *out) 1158 { 1159 AVRO_UNUSED(iface); 1160 const float *self = (const float *) vself; 1161 *out = *self; 1162 return 0; 1163 } 1164 1165 static int 1166 avro_generic_float_set(const avro_value_iface_t *iface, 1167 void *vself, float val) 1168 { 1169 AVRO_UNUSED(iface); 1170 float *self = (float *) vself; 1171 *self = val; 1172 return 0; 1173 } 1174 1175 static size_t 1176 avro_generic_float_instance_size(const avro_value_iface_t *iface) 1177 { 1178 AVRO_UNUSED(iface); 1179 return sizeof(float); 1180 } 1181 1182 static int 1183 avro_generic_float_init(const avro_value_iface_t *iface, void *vself) 1184 { 1185 AVRO_UNUSED(iface); 1186 float *self = (float *) vself; 1187 *self = 0.0f; 1188 return 0; 1189 } 1190 1191 static void 1192 avro_generic_float_done(const avro_value_iface_t *iface, void *vself) 1193 { 1194 AVRO_UNUSED(iface); 1195 AVRO_UNUSED(vself); 1196 } 1197 1198 static avro_generic_value_iface_t AVRO_GENERIC_FLOAT_CLASS = 1199 { 1200 { 1201 /* "class" methods */ 1202 NULL, /* incref_iface */ 1203 NULL, /* decref_iface */ 1204 /* general "instance" methods */ 1205 avro_generic_value_incref, 1206 avro_generic_value_decref, 1207 avro_generic_float_reset, 1208 avro_generic_float_get_type, 1209 avro_generic_float_get_schema, 1210 /* primitive getters */ 1211 NULL, /* get_boolean */ 1212 NULL, /* get_bytes */ 1213 NULL, /* grab_bytes */ 1214 NULL, /* get_double */ 1215 avro_generic_float_get, 1216 NULL, /* get_int */ 1217 NULL, /* get_long */ 1218 NULL, /* get_null */ 1219 NULL, /* get_string */ 1220 NULL, /* grab_string */ 1221 NULL, /* get_enum */ 1222 NULL, /* get_fixed */ 1223 NULL, /* grab_fixed */ 1224 /* primitive setters */ 1225 NULL, /* set_boolean */ 1226 NULL, /* set_bytes */ 1227 NULL, /* give_bytes */ 1228 NULL, /* set_double */ 1229 avro_generic_float_set, 1230 NULL, /* set_int */ 1231 NULL, /* set_long */ 1232 NULL, /* set_null */ 1233 NULL, /* set_string */ 1234 NULL, /* set_string_length */ 1235 NULL, /* give_string_length */ 1236 NULL, /* set_enum */ 1237 NULL, /* set_fixed */ 1238 NULL, /* give_fixed */ 1239 /* compound getters */ 1240 NULL, /* get_size */ 1241 NULL, /* get_by_index */ 1242 NULL, /* get_by_name */ 1243 NULL, /* get_discriminant */ 1244 NULL, /* get_current_branch */ 1245 /* compound setters */ 1246 NULL, /* append */ 1247 NULL, /* add */ 1248 NULL /* set_branch */ 1249 }, 1250 avro_generic_float_instance_size, 1251 avro_generic_float_init, 1252 avro_generic_float_done 1253 }; 1254 1255 avro_value_iface_t * 1256 avro_generic_float_class(void) 1257 { 1258 return &AVRO_GENERIC_FLOAT_CLASS.parent; 1259 } 1260 1261 int 1262 avro_generic_float_new(avro_value_t *value, float val) 1263 { 1264 int rval; 1265 check(rval, avro_generic_value_new(&AVRO_GENERIC_FLOAT_CLASS.parent, value)); 1266 return avro_generic_float_set(value->iface, value->self, val); 1267 } 1268 1269 /*----------------------------------------------------------------------- 1270 * int 1271 */ 1272 1273 static int 1274 avro_generic_int_reset(const avro_value_iface_t *iface, void *vself) 1275 { 1276 AVRO_UNUSED(iface); 1277 int32_t *self = (int32_t *) vself; 1278 *self = 0; 1279 return 0; 1280 } 1281 1282 static avro_type_t 1283 avro_generic_int_get_type(const avro_value_iface_t *iface, const void *vself) 1284 { 1285 AVRO_UNUSED(iface); 1286 AVRO_UNUSED(vself); 1287 return AVRO_INT32; 1288 } 1289 1290 static avro_schema_t 1291 avro_generic_int_get_schema(const avro_value_iface_t *iface, const void *vself) 1292 { 1293 AVRO_UNUSED(iface); 1294 AVRO_UNUSED(vself); 1295 return avro_schema_int(); 1296 } 1297 1298 static int 1299 avro_generic_int_get(const avro_value_iface_t *iface, 1300 const void *vself, int32_t *out) 1301 { 1302 AVRO_UNUSED(iface); 1303 const int32_t *self = (const int32_t *) vself; 1304 *out = *self; 1305 return 0; 1306 } 1307 1308 static int 1309 avro_generic_int_set(const avro_value_iface_t *iface, 1310 void *vself, int32_t val) 1311 { 1312 AVRO_UNUSED(iface); 1313 int32_t *self = (int32_t *) vself; 1314 *self = val; 1315 return 0; 1316 } 1317 1318 static size_t 1319 avro_generic_int_instance_size(const avro_value_iface_t *iface) 1320 { 1321 AVRO_UNUSED(iface); 1322 return sizeof(int32_t); 1323 } 1324 1325 static int 1326 avro_generic_int_init(const avro_value_iface_t *iface, void *vself) 1327 { 1328 AVRO_UNUSED(iface); 1329 int32_t *self = (int32_t *) vself; 1330 *self = 0; 1331 return 0; 1332 } 1333 1334 static void 1335 avro_generic_int_done(const avro_value_iface_t *iface, void *vself) 1336 { 1337 AVRO_UNUSED(iface); 1338 AVRO_UNUSED(vself); 1339 } 1340 1341 static avro_generic_value_iface_t AVRO_GENERIC_INT_CLASS = 1342 { 1343 { 1344 /* "class" methods */ 1345 NULL, /* incref_iface */ 1346 NULL, /* decref_iface */ 1347 /* general "instance" methods */ 1348 avro_generic_value_incref, 1349 avro_generic_value_decref, 1350 avro_generic_int_reset, 1351 avro_generic_int_get_type, 1352 avro_generic_int_get_schema, 1353 /* primitive getters */ 1354 NULL, /* get_boolean */ 1355 NULL, /* get_bytes */ 1356 NULL, /* grab_bytes */ 1357 NULL, /* get_double */ 1358 NULL, /* get_float */ 1359 avro_generic_int_get, 1360 NULL, /* get_long */ 1361 NULL, /* get_null */ 1362 NULL, /* get_string */ 1363 NULL, /* grab_string */ 1364 NULL, /* get_enum */ 1365 NULL, /* get_fixed */ 1366 NULL, /* grab_fixed */ 1367 /* primitive setters */ 1368 NULL, /* set_boolean */ 1369 NULL, /* set_bytes */ 1370 NULL, /* give_bytes */ 1371 NULL, /* set_double */ 1372 NULL, /* set_float */ 1373 avro_generic_int_set, 1374 NULL, /* set_long */ 1375 NULL, /* set_null */ 1376 NULL, /* set_string */ 1377 NULL, /* set_string_length */ 1378 NULL, /* give_string_length */ 1379 NULL, /* set_enum */ 1380 NULL, /* set_fixed */ 1381 NULL, /* give_fixed */ 1382 /* compound getters */ 1383 NULL, /* get_size */ 1384 NULL, /* get_by_index */ 1385 NULL, /* get_by_name */ 1386 NULL, /* get_discriminant */ 1387 NULL, /* get_current_branch */ 1388 /* compound setters */ 1389 NULL, /* append */ 1390 NULL, /* add */ 1391 NULL /* set_branch */ 1392 }, 1393 avro_generic_int_instance_size, 1394 avro_generic_int_init, 1395 avro_generic_int_done 1396 }; 1397 1398 avro_value_iface_t * 1399 avro_generic_int_class(void) 1400 { 1401 return &AVRO_GENERIC_INT_CLASS.parent; 1402 } 1403 1404 int 1405 avro_generic_int_new(avro_value_t *value, int32_t val) 1406 { 1407 int rval; 1408 check(rval, avro_generic_value_new(&AVRO_GENERIC_INT_CLASS.parent, value)); 1409 return avro_generic_int_set(value->iface, value->self, val); 1410 } 1411 1412 /*----------------------------------------------------------------------- 1413 * long 1414 */ 1415 1416 static int 1417 avro_generic_long_reset(const avro_value_iface_t *iface, void *vself) 1418 { 1419 AVRO_UNUSED(iface); 1420 int64_t *self = (int64_t *) vself; 1421 *self = 0; 1422 return 0; 1423 } 1424 1425 static avro_type_t 1426 avro_generic_long_get_type(const avro_value_iface_t *iface, const void *vself) 1427 { 1428 AVRO_UNUSED(iface); 1429 AVRO_UNUSED(vself); 1430 return AVRO_INT64; 1431 } 1432 1433 static avro_schema_t 1434 avro_generic_long_get_schema(const avro_value_iface_t *iface, const void *vself) 1435 { 1436 AVRO_UNUSED(iface); 1437 AVRO_UNUSED(vself); 1438 return avro_schema_long(); 1439 } 1440 1441 static int 1442 avro_generic_long_get(const avro_value_iface_t *iface, 1443 const void *vself, int64_t *out) 1444 { 1445 AVRO_UNUSED(iface); 1446 const int64_t *self = (const int64_t *) vself; 1447 *out = *self; 1448 return 0; 1449 } 1450 1451 static int 1452 avro_generic_long_set(const avro_value_iface_t *iface, 1453 void *vself, int64_t val) 1454 { 1455 AVRO_UNUSED(iface); 1456 int64_t *self = (int64_t *) vself; 1457 *self = val; 1458 return 0; 1459 } 1460 1461 static size_t 1462 avro_generic_long_instance_size(const avro_value_iface_t *iface) 1463 { 1464 AVRO_UNUSED(iface); 1465 return sizeof(int64_t); 1466 } 1467 1468 static int 1469 avro_generic_long_init(const avro_value_iface_t *iface, void *vself) 1470 { 1471 AVRO_UNUSED(iface); 1472 int64_t *self = (int64_t *) vself; 1473 *self = 0; 1474 return 0; 1475 } 1476 1477 static void 1478 avro_generic_long_done(const avro_value_iface_t *iface, void *vself) 1479 { 1480 AVRO_UNUSED(iface); 1481 AVRO_UNUSED(vself); 1482 } 1483 1484 static avro_generic_value_iface_t AVRO_GENERIC_LONG_CLASS = 1485 { 1486 { 1487 /* "class" methods */ 1488 NULL, /* incref_iface */ 1489 NULL, /* decref_iface */ 1490 /* general "instance" methods */ 1491 avro_generic_value_incref, 1492 avro_generic_value_decref, 1493 avro_generic_long_reset, 1494 avro_generic_long_get_type, 1495 avro_generic_long_get_schema, 1496 /* primitive getters */ 1497 NULL, /* get_boolean */ 1498 NULL, /* get_bytes */ 1499 NULL, /* grab_bytes */ 1500 NULL, /* get_double */ 1501 NULL, /* get_float */ 1502 NULL, /* get_int */ 1503 avro_generic_long_get, 1504 NULL, /* get_null */ 1505 NULL, /* get_string */ 1506 NULL, /* grab_string */ 1507 NULL, /* get_enum */ 1508 NULL, /* get_fixed */ 1509 NULL, /* grab_fixed */ 1510 /* primitive setters */ 1511 NULL, /* set_boolean */ 1512 NULL, /* set_bytes */ 1513 NULL, /* give_bytes */ 1514 NULL, /* set_double */ 1515 NULL, /* set_float */ 1516 NULL, /* set_int */ 1517 avro_generic_long_set, 1518 NULL, /* set_null */ 1519 NULL, /* set_string */ 1520 NULL, /* set_string_length */ 1521 NULL, /* give_string_length */ 1522 NULL, /* set_enum */ 1523 NULL, /* set_fixed */ 1524 NULL, /* give_fixed */ 1525 /* compound getters */ 1526 NULL, /* get_size */ 1527 NULL, /* get_by_index */ 1528 NULL, /* get_by_name */ 1529 NULL, /* get_discriminant */ 1530 NULL, /* get_current_branch */ 1531 /* compound setters */ 1532 NULL, /* append */ 1533 NULL, /* add */ 1534 NULL /* set_branch */ 1535 }, 1536 avro_generic_long_instance_size, 1537 avro_generic_long_init, 1538 avro_generic_long_done 1539 }; 1540 1541 avro_value_iface_t * 1542 avro_generic_long_class(void) 1543 { 1544 return &AVRO_GENERIC_LONG_CLASS.parent; 1545 } 1546 1547 int 1548 avro_generic_long_new(avro_value_t *value, int64_t val) 1549 { 1550 int rval; 1551 check(rval, avro_generic_value_new(&AVRO_GENERIC_LONG_CLASS.parent, value)); 1552 return avro_generic_long_set(value->iface, value->self, val); 1553 } 1554 1555 /*----------------------------------------------------------------------- 1556 * null 1557 */ 1558 1559 static int 1560 avro_generic_null_reset(const avro_value_iface_t *iface, void *vself) 1561 { 1562 AVRO_UNUSED(iface); 1563 int *self = (int *) vself; 1564 *self = 0; 1565 return 0; 1566 } 1567 1568 static avro_type_t 1569 avro_generic_null_get_type(const avro_value_iface_t *iface, const void *vself) 1570 { 1571 AVRO_UNUSED(iface); 1572 AVRO_UNUSED(vself); 1573 return AVRO_NULL; 1574 } 1575 1576 static avro_schema_t 1577 avro_generic_null_get_schema(const avro_value_iface_t *iface, const void *vself) 1578 { 1579 AVRO_UNUSED(iface); 1580 AVRO_UNUSED(vself); 1581 return avro_schema_null(); 1582 } 1583 1584 static int 1585 avro_generic_null_get(const avro_value_iface_t *iface, const void *vself) 1586 { 1587 AVRO_UNUSED(iface); 1588 AVRO_UNUSED(vself); 1589 return 0; 1590 } 1591 1592 static int 1593 avro_generic_null_set(const avro_value_iface_t *iface, void *vself) 1594 { 1595 AVRO_UNUSED(iface); 1596 AVRO_UNUSED(vself); 1597 return 0; 1598 } 1599 1600 static size_t 1601 avro_generic_null_instance_size(const avro_value_iface_t *iface) 1602 { 1603 AVRO_UNUSED(iface); 1604 return sizeof(int); 1605 } 1606 1607 static int 1608 avro_generic_null_init(const avro_value_iface_t *iface, void *vself) 1609 { 1610 AVRO_UNUSED(iface); 1611 int *self = (int *) vself; 1612 *self = 0; 1613 return 0; 1614 } 1615 1616 static void 1617 avro_generic_null_done(const avro_value_iface_t *iface, void *vself) 1618 { 1619 AVRO_UNUSED(iface); 1620 AVRO_UNUSED(vself); 1621 } 1622 1623 static avro_generic_value_iface_t AVRO_GENERIC_NULL_CLASS = 1624 { 1625 { 1626 /* "class" methods */ 1627 NULL, /* incref_iface */ 1628 NULL, /* decref_iface */ 1629 /* general "instance" methods */ 1630 avro_generic_value_incref, 1631 avro_generic_value_decref, 1632 avro_generic_null_reset, 1633 avro_generic_null_get_type, 1634 avro_generic_null_get_schema, 1635 /* primitive getters */ 1636 NULL, /* get_boolean */ 1637 NULL, /* get_bytes */ 1638 NULL, /* grab_bytes */ 1639 NULL, /* get_double */ 1640 NULL, /* get_float */ 1641 NULL, /* get_int */ 1642 NULL, /* get_long */ 1643 avro_generic_null_get, 1644 NULL, /* get_string */ 1645 NULL, /* grab_string */ 1646 NULL, /* get_enum */ 1647 NULL, /* get_fixed */ 1648 NULL, /* grab_fixed */ 1649 /* primitive setters */ 1650 NULL, /* set_boolean */ 1651 NULL, /* set_bytes */ 1652 NULL, /* give_bytes */ 1653 NULL, /* set_double */ 1654 NULL, /* set_float */ 1655 NULL, /* set_int */ 1656 NULL, /* set_long */ 1657 avro_generic_null_set, 1658 NULL, /* set_string */ 1659 NULL, /* set_string_length */ 1660 NULL, /* give_string_length */ 1661 NULL, /* set_enum */ 1662 NULL, /* set_fixed */ 1663 NULL, /* give_fixed */ 1664 /* compound getters */ 1665 NULL, /* get_size */ 1666 NULL, /* get_by_index */ 1667 NULL, /* get_by_name */ 1668 NULL, /* get_discriminant */ 1669 NULL, /* get_current_branch */ 1670 /* compound setters */ 1671 NULL, /* append */ 1672 NULL, /* add */ 1673 NULL /* set_branch */ 1674 }, 1675 avro_generic_null_instance_size, 1676 avro_generic_null_init, 1677 avro_generic_null_done 1678 }; 1679 1680 avro_value_iface_t * 1681 avro_generic_null_class(void) 1682 { 1683 return &AVRO_GENERIC_NULL_CLASS.parent; 1684 } 1685 1686 int 1687 avro_generic_null_new(avro_value_t *value) 1688 { 1689 return avro_generic_value_new(&AVRO_GENERIC_NULL_CLASS.parent, value); 1690 } 1691 1692 /*----------------------------------------------------------------------- 1693 * string 1694 */ 1695 1696 static int 1697 avro_generic_string_reset(const avro_value_iface_t *iface, void *vself) 1698 { 1699 AVRO_UNUSED(iface); 1700 avro_raw_string_t *self = (avro_raw_string_t *) vself; 1701 avro_raw_string_clear(self); 1702 return 0; 1703 } 1704 1705 static avro_type_t 1706 avro_generic_string_get_type(const avro_value_iface_t *iface, const void *vself) 1707 { 1708 AVRO_UNUSED(iface); 1709 AVRO_UNUSED(vself); 1710 return AVRO_STRING; 1711 } 1712 1713 static avro_schema_t 1714 avro_generic_string_get_schema(const avro_value_iface_t *iface, const void *vself) 1715 { 1716 AVRO_UNUSED(iface); 1717 AVRO_UNUSED(vself); 1718 return avro_schema_string(); 1719 } 1720 1721 static int 1722 avro_generic_string_get(const avro_value_iface_t *iface, 1723 const void *vself, const char **str, size_t *size) 1724 { 1725 AVRO_UNUSED(iface); 1726 const avro_raw_string_t *self = (const avro_raw_string_t *) vself; 1727 const char *contents = (const char *) avro_raw_string_get(self); 1728 1729 if (str != NULL) { 1730 /* 1731 * We can't return a NULL string, we have to return an 1732 * *empty* string 1733 */ 1734 1735 *str = (contents == NULL)? "": contents; 1736 } 1737 if (size != NULL) { 1738 /* raw_string's length includes the NUL terminator, 1739 * unless it's empty */ 1740 *size = (contents == NULL)? 1: avro_raw_string_length(self); 1741 } 1742 return 0; 1743 } 1744 1745 static int 1746 avro_generic_string_grab(const avro_value_iface_t *iface, 1747 const void *vself, avro_wrapped_buffer_t *dest) 1748 { 1749 AVRO_UNUSED(iface); 1750 const avro_raw_string_t *self = (const avro_raw_string_t *) vself; 1751 const char *contents = (const char *) avro_raw_string_get(self); 1752 1753 if (contents == NULL) { 1754 return avro_wrapped_buffer_new(dest, "", 1); 1755 } else { 1756 return avro_raw_string_grab(self, dest); 1757 } 1758 } 1759 1760 static int 1761 avro_generic_string_set(const avro_value_iface_t *iface, 1762 void *vself, const char *val) 1763 { 1764 AVRO_UNUSED(iface); 1765 check_param(EINVAL, val != NULL, "string contents"); 1766 1767 /* 1768 * This raw_string method ensures that we copy the NUL 1769 * terminator from val, and will include the NUL terminator in 1770 * the raw_string's length, which is what we want. 1771 */ 1772 avro_raw_string_t *self = (avro_raw_string_t *) vself; 1773 avro_raw_string_set(self, val); 1774 return 0; 1775 } 1776 1777 static int 1778 avro_generic_string_set_length(const avro_value_iface_t *iface, 1779 void *vself, const char *val, size_t size) 1780 { 1781 AVRO_UNUSED(iface); 1782 check_param(EINVAL, val != NULL, "string contents"); 1783 avro_raw_string_t *self = (avro_raw_string_t *) vself; 1784 avro_raw_string_set_length(self, val, size); 1785 return 0; 1786 } 1787 1788 static int 1789 avro_generic_string_give_length(const avro_value_iface_t *iface, 1790 void *vself, avro_wrapped_buffer_t *buf) 1791 { 1792 AVRO_UNUSED(iface); 1793 avro_raw_string_t *self = (avro_raw_string_t *) vself; 1794 avro_raw_string_give(self, buf); 1795 return 0; 1796 } 1797 1798 static size_t 1799 avro_generic_string_instance_size(const avro_value_iface_t *iface) 1800 { 1801 AVRO_UNUSED(iface); 1802 return sizeof(avro_raw_string_t); 1803 } 1804 1805 static int 1806 avro_generic_string_init(const avro_value_iface_t *iface, void *vself) 1807 { 1808 AVRO_UNUSED(iface); 1809 avro_raw_string_t *self = (avro_raw_string_t *) vself; 1810 avro_raw_string_init(self); 1811 return 0; 1812 } 1813 1814 static void 1815 avro_generic_string_done(const avro_value_iface_t *iface, void *vself) 1816 { 1817 AVRO_UNUSED(iface); 1818 avro_raw_string_t *self = (avro_raw_string_t *) vself; 1819 avro_raw_string_done(self); 1820 } 1821 1822 static avro_generic_value_iface_t AVRO_GENERIC_STRING_CLASS = 1823 { 1824 { 1825 /* "class" methods */ 1826 NULL, /* incref_iface */ 1827 NULL, /* decref_iface */ 1828 /* general "instance" methods */ 1829 avro_generic_value_incref, 1830 avro_generic_value_decref, 1831 avro_generic_string_reset, 1832 avro_generic_string_get_type, 1833 avro_generic_string_get_schema, 1834 /* primitive getters */ 1835 NULL, /* get_boolean */ 1836 NULL, /* get_bytes */ 1837 NULL, /* grab_bytes */ 1838 NULL, /* get_double */ 1839 NULL, /* get_float */ 1840 NULL, /* get_int */ 1841 NULL, /* get_long */ 1842 NULL, /* get_null */ 1843 avro_generic_string_get, 1844 avro_generic_string_grab, 1845 NULL, /* get_enum */ 1846 NULL, /* get_fixed */ 1847 NULL, /* grab_fixed */ 1848 /* primitive setters */ 1849 NULL, /* set_boolean */ 1850 NULL, /* set_bytes */ 1851 NULL, /* give_bytes */ 1852 NULL, /* set_double */ 1853 NULL, /* set_float */ 1854 NULL, /* set_int */ 1855 NULL, /* set_long */ 1856 NULL, /* set_null */ 1857 avro_generic_string_set, 1858 avro_generic_string_set_length, 1859 avro_generic_string_give_length, 1860 NULL, /* set_enum */ 1861 NULL, /* set_fixed */ 1862 NULL, /* give_fixed */ 1863 /* compound getters */ 1864 NULL, /* get_size */ 1865 NULL, /* get_by_index */ 1866 NULL, /* get_by_name */ 1867 NULL, /* get_discriminant */ 1868 NULL, /* get_current_branch */ 1869 /* compound setters */ 1870 NULL, /* append */ 1871 NULL, /* add */ 1872 NULL /* set_branch */ 1873 }, 1874 avro_generic_string_instance_size, 1875 avro_generic_string_init, 1876 avro_generic_string_done 1877 }; 1878 1879 avro_value_iface_t * 1880 avro_generic_string_class(void) 1881 { 1882 return &AVRO_GENERIC_STRING_CLASS.parent; 1883 } 1884 1885 int 1886 avro_generic_string_new(avro_value_t *value, const char *str) 1887 { 1888 int rval; 1889 check(rval, avro_generic_value_new(&AVRO_GENERIC_STRING_CLASS.parent, value)); 1890 return avro_generic_string_set(value->iface, value->self, str); 1891 } 1892 1893 int 1894 avro_generic_string_new_length(avro_value_t *value, const char *str, size_t size) 1895 { 1896 int rval; 1897 check(rval, avro_generic_value_new(&AVRO_GENERIC_STRING_CLASS.parent, value)); 1898 return avro_generic_string_set_length(value->iface, value->self, str, size); 1899 } 1900 1901 1902 /*----------------------------------------------------------------------- 1903 * array 1904 */ 1905 1906 /* 1907 * For generic arrays, we need to store the value implementation for the 1908 * array's elements. 1909 */ 1910 1911 typedef struct avro_generic_array_value_iface { 1912 avro_generic_value_iface_t parent; 1913 volatile int refcount; 1914 avro_schema_t schema; 1915 avro_generic_value_iface_t *child_giface; 1916 } avro_generic_array_value_iface_t; 1917 1918 typedef struct avro_generic_array { 1919 avro_raw_array_t array; 1920 } avro_generic_array_t; 1921 1922 1923 static avro_value_iface_t * 1924 avro_generic_array_incref_iface(avro_value_iface_t *viface) 1925 { 1926 avro_generic_array_value_iface_t *iface = 1927 container_of(viface, avro_generic_array_value_iface_t, parent); 1928 avro_refcount_inc(&iface->refcount); 1929 return viface; 1930 } 1931 1932 static void 1933 avro_generic_array_decref_iface(avro_value_iface_t *viface) 1934 { 1935 avro_generic_array_value_iface_t *iface = 1936 container_of(viface, avro_generic_array_value_iface_t, parent); 1937 if (avro_refcount_dec(&iface->refcount)) { 1938 avro_schema_decref(iface->schema); 1939 avro_value_iface_decref(&iface->child_giface->parent); 1940 avro_freet(avro_generic_array_value_iface_t, iface); 1941 } 1942 } 1943 1944 1945 static void 1946 avro_generic_array_free_elements(const avro_generic_value_iface_t *child_giface, 1947 avro_generic_array_t *self) 1948 { 1949 size_t i; 1950 for (i = 0; i < avro_raw_array_size(&self->array); i++) { 1951 void *child_self = avro_raw_array_get_raw(&self->array, i); 1952 avro_value_done(child_giface, child_self); 1953 } 1954 } 1955 1956 static int 1957 avro_generic_array_reset(const avro_value_iface_t *viface, void *vself) 1958 { 1959 const avro_generic_array_value_iface_t *iface = 1960 container_of(viface, avro_generic_array_value_iface_t, parent); 1961 avro_generic_array_t *self = (avro_generic_array_t *) vself; 1962 avro_generic_array_free_elements(iface->child_giface, self); 1963 avro_raw_array_clear(&self->array); 1964 return 0; 1965 } 1966 1967 static avro_type_t 1968 avro_generic_array_get_type(const avro_value_iface_t *viface, const void *vself) 1969 { 1970 AVRO_UNUSED(viface); 1971 AVRO_UNUSED(vself); 1972 return AVRO_ARRAY; 1973 } 1974 1975 static avro_schema_t 1976 avro_generic_array_get_schema(const avro_value_iface_t *viface, const void *vself) 1977 { 1978 const avro_generic_array_value_iface_t *iface = 1979 container_of(viface, avro_generic_array_value_iface_t, parent); 1980 AVRO_UNUSED(vself); 1981 return iface->schema; 1982 } 1983 1984 static int 1985 avro_generic_array_get_size(const avro_value_iface_t *viface, 1986 const void *vself, size_t *size) 1987 { 1988 AVRO_UNUSED(viface); 1989 const avro_generic_array_t *self = (const avro_generic_array_t *) vself; 1990 if (size != NULL) { 1991 *size = avro_raw_array_size(&self->array); 1992 } 1993 return 0; 1994 } 1995 1996 static int 1997 avro_generic_array_get_by_index(const avro_value_iface_t *viface, 1998 const void *vself, size_t index, 1999 avro_value_t *child, const char **name) 2000 { 2001 const avro_generic_array_value_iface_t *iface = 2002 container_of(viface, avro_generic_array_value_iface_t, parent); 2003 AVRO_UNUSED(name); 2004 const avro_generic_array_t *self = (avro_generic_array_t *) vself; 2005 if (index >= avro_raw_array_size(&self->array)) { 2006 avro_set_error("Array index %" PRIsz " out of range", index); 2007 return EINVAL; 2008 } 2009 child->iface = &iface->child_giface->parent; 2010 child->self = avro_raw_array_get_raw(&self->array, index); 2011 return 0; 2012 } 2013 2014 static int 2015 avro_generic_array_append(const avro_value_iface_t *viface, 2016 void *vself, avro_value_t *child, 2017 size_t *new_index) 2018 { 2019 int rval; 2020 const avro_generic_array_value_iface_t *iface = 2021 container_of(viface, avro_generic_array_value_iface_t, parent); 2022 avro_generic_array_t *self = (avro_generic_array_t *) vself; 2023 child->iface = &iface->child_giface->parent; 2024 child->self = avro_raw_array_append(&self->array); 2025 if (child->self == NULL) { 2026 avro_set_error("Couldn't expand array"); 2027 return ENOMEM; 2028 } 2029 check(rval, avro_value_init(iface->child_giface, child->self)); 2030 if (new_index != NULL) { 2031 *new_index = avro_raw_array_size(&self->array) - 1; 2032 } 2033 return 0; 2034 } 2035 2036 static size_t 2037 avro_generic_array_instance_size(const avro_value_iface_t *viface) 2038 { 2039 AVRO_UNUSED(viface); 2040 return sizeof(avro_generic_array_t); 2041 } 2042 2043 static int 2044 avro_generic_array_init(const avro_value_iface_t *viface, void *vself) 2045 { 2046 const avro_generic_array_value_iface_t *iface = 2047 container_of(viface, avro_generic_array_value_iface_t, parent); 2048 avro_generic_array_t *self = (avro_generic_array_t *) vself; 2049 2050 size_t child_size = avro_value_instance_size(iface->child_giface); 2051 avro_raw_array_init(&self->array, child_size); 2052 return 0; 2053 } 2054 2055 static void 2056 avro_generic_array_done(const avro_value_iface_t *viface, void *vself) 2057 { 2058 const avro_generic_array_value_iface_t *iface = 2059 container_of(viface, avro_generic_array_value_iface_t, parent); 2060 avro_generic_array_t *self = (avro_generic_array_t *) vself; 2061 avro_generic_array_free_elements(iface->child_giface, self); 2062 avro_raw_array_done(&self->array); 2063 } 2064 2065 static avro_generic_value_iface_t AVRO_GENERIC_ARRAY_CLASS = 2066 { 2067 { 2068 /* "class" methods */ 2069 avro_generic_array_incref_iface, 2070 avro_generic_array_decref_iface, 2071 /* general "instance" methods */ 2072 avro_generic_value_incref, 2073 avro_generic_value_decref, 2074 avro_generic_array_reset, 2075 avro_generic_array_get_type, 2076 avro_generic_array_get_schema, 2077 /* primitive getters */ 2078 NULL, /* get_boolean */ 2079 NULL, /* get_bytes */ 2080 NULL, /* grab_bytes */ 2081 NULL, /* get_double */ 2082 NULL, /* get_float */ 2083 NULL, /* get_int */ 2084 NULL, /* get_long */ 2085 NULL, /* get_null */ 2086 NULL, /* get_string */ 2087 NULL, /* grab_string */ 2088 NULL, /* get_enum */ 2089 NULL, /* get_fixed */ 2090 NULL, /* grab_fixed */ 2091 /* primitive setters */ 2092 NULL, /* set_boolean */ 2093 NULL, /* set_bytes */ 2094 NULL, /* give_bytes */ 2095 NULL, /* set_double */ 2096 NULL, /* set_float */ 2097 NULL, /* set_int */ 2098 NULL, /* set_long */ 2099 NULL, /* set_null */ 2100 NULL, /* set_string */ 2101 NULL, /* set_string_length */ 2102 NULL, /* give_string_length */ 2103 NULL, /* set_enum */ 2104 NULL, /* set_fixed */ 2105 NULL, /* give_fixed */ 2106 /* compound getters */ 2107 avro_generic_array_get_size, 2108 avro_generic_array_get_by_index, 2109 NULL, /* get_by_name */ 2110 NULL, /* get_discriminant */ 2111 NULL, /* get_current_branch */ 2112 /* compound setters */ 2113 avro_generic_array_append, 2114 NULL, /* add */ 2115 NULL /* set_branch */ 2116 }, 2117 avro_generic_array_instance_size, 2118 avro_generic_array_init, 2119 avro_generic_array_done 2120 }; 2121 2122 static avro_generic_value_iface_t * 2123 avro_generic_array_class(avro_schema_t schema, memoize_state_t *state) 2124 { 2125 avro_schema_t child_schema = avro_schema_array_items(schema); 2126 avro_generic_value_iface_t *child_giface = 2127 avro_generic_class_from_schema_memoized(child_schema, state); 2128 if (child_giface == NULL) { 2129 return NULL; 2130 } 2131 2132 ssize_t child_size = avro_value_instance_size(child_giface); 2133 if (child_size < 0) { 2134 avro_set_error("Array item class must provide instance_size"); 2135 avro_value_iface_decref(&child_giface->parent); 2136 return NULL; 2137 } 2138 2139 avro_generic_array_value_iface_t *iface = 2140 (avro_generic_array_value_iface_t *) avro_new(avro_generic_array_value_iface_t); 2141 if (iface == NULL) { 2142 avro_value_iface_decref(&child_giface->parent); 2143 return NULL; 2144 } 2145 2146 /* 2147 * TODO: Maybe check that schema.items matches 2148 * child_iface.get_schema? 2149 */ 2150 2151 iface->parent = AVRO_GENERIC_ARRAY_CLASS; 2152 iface->refcount = 1; 2153 iface->schema = avro_schema_incref(schema); 2154 iface->child_giface = child_giface; 2155 return &iface->parent; 2156 } 2157 2158 2159 /*----------------------------------------------------------------------- 2160 * enum 2161 */ 2162 2163 typedef struct avro_generic_enum_value_iface { 2164 avro_generic_value_iface_t parent; 2165 volatile int refcount; 2166 avro_schema_t schema; 2167 } avro_generic_enum_value_iface_t; 2168 2169 2170 static avro_value_iface_t * 2171 avro_generic_enum_incref_iface(avro_value_iface_t *viface) 2172 { 2173 avro_generic_enum_value_iface_t *iface = 2174 (avro_generic_enum_value_iface_t *) viface; 2175 avro_refcount_inc(&iface->refcount); 2176 return viface; 2177 } 2178 2179 static void 2180 avro_generic_enum_decref_iface(avro_value_iface_t *viface) 2181 { 2182 avro_generic_enum_value_iface_t *iface = 2183 (avro_generic_enum_value_iface_t *) viface; 2184 if (avro_refcount_dec(&iface->refcount)) { 2185 avro_schema_decref(iface->schema); 2186 avro_freet(avro_generic_enum_value_iface_t, iface); 2187 } 2188 } 2189 2190 static int 2191 avro_generic_enum_reset(const avro_value_iface_t *viface, void *vself) 2192 { 2193 AVRO_UNUSED(viface); 2194 int *self = (int *) vself; 2195 *self = 0; 2196 return 0; 2197 } 2198 2199 static avro_type_t 2200 avro_generic_enum_get_type(const avro_value_iface_t *iface, const void *vself) 2201 { 2202 AVRO_UNUSED(iface); 2203 AVRO_UNUSED(vself); 2204 return AVRO_ENUM; 2205 } 2206 2207 static avro_schema_t 2208 avro_generic_enum_get_schema(const avro_value_iface_t *viface, const void *vself) 2209 { 2210 const avro_generic_enum_value_iface_t *iface = 2211 container_of(viface, avro_generic_enum_value_iface_t, parent); 2212 AVRO_UNUSED(vself); 2213 return iface->schema; 2214 } 2215 2216 static int 2217 avro_generic_enum_get(const avro_value_iface_t *viface, 2218 const void *vself, int *out) 2219 { 2220 AVRO_UNUSED(viface); 2221 const int *self = (const int *) vself; 2222 *out = *self; 2223 return 0; 2224 } 2225 2226 static int 2227 avro_generic_enum_set(const avro_value_iface_t *viface, 2228 void *vself, int val) 2229 { 2230 AVRO_UNUSED(viface); 2231 int *self = (int *) vself; 2232 *self = val; 2233 return 0; 2234 } 2235 2236 static size_t 2237 avro_generic_enum_instance_size(const avro_value_iface_t *viface) 2238 { 2239 AVRO_UNUSED(viface); 2240 return sizeof(int); 2241 } 2242 2243 static int 2244 avro_generic_enum_init(const avro_value_iface_t *viface, void *vself) 2245 { 2246 AVRO_UNUSED(viface); 2247 int *self = (int *) vself; 2248 *self = 0; 2249 return 0; 2250 } 2251 2252 static void 2253 avro_generic_enum_done(const avro_value_iface_t *viface, void *vself) 2254 { 2255 AVRO_UNUSED(viface); 2256 AVRO_UNUSED(vself); 2257 } 2258 2259 static avro_generic_value_iface_t AVRO_GENERIC_ENUM_CLASS = 2260 { 2261 { 2262 /* "class" methods */ 2263 avro_generic_enum_incref_iface, 2264 avro_generic_enum_decref_iface, 2265 /* general "instance" methods */ 2266 avro_generic_value_incref, 2267 avro_generic_value_decref, 2268 avro_generic_enum_reset, 2269 avro_generic_enum_get_type, 2270 avro_generic_enum_get_schema, 2271 /* primitive getters */ 2272 NULL, /* get_boolean */ 2273 NULL, /* get_bytes */ 2274 NULL, /* grab_bytes */ 2275 NULL, /* get_double */ 2276 NULL, /* get_float */ 2277 NULL, /* get_int */ 2278 NULL, /* get_long */ 2279 NULL, /* get_null */ 2280 NULL, /* get_string */ 2281 NULL, /* grab_string */ 2282 avro_generic_enum_get, 2283 NULL, /* get_fixed */ 2284 NULL, /* grab_fixed */ 2285 /* primitive setters */ 2286 NULL, /* set_boolean */ 2287 NULL, /* set_bytes */ 2288 NULL, /* give_bytes */ 2289 NULL, /* set_double */ 2290 NULL, /* set_float */ 2291 NULL, /* set_int */ 2292 NULL, /* set_long */ 2293 NULL, /* set_null */ 2294 NULL, /* set_string */ 2295 NULL, /* set_string_length */ 2296 NULL, /* give_string_length */ 2297 avro_generic_enum_set, 2298 NULL, /* set_fixed */ 2299 NULL, /* give_fixed */ 2300 /* compound getters */ 2301 NULL, /* get_size */ 2302 NULL, /* get_by_index */ 2303 NULL, /* get_by_name */ 2304 NULL, /* get_discriminant */ 2305 NULL, /* get_current_branch */ 2306 /* compound setters */ 2307 NULL, /* append */ 2308 NULL, /* add */ 2309 NULL /* set_branch */ 2310 }, 2311 avro_generic_enum_instance_size, 2312 avro_generic_enum_init, 2313 avro_generic_enum_done 2314 }; 2315 2316 static avro_generic_value_iface_t * 2317 avro_generic_enum_class(avro_schema_t schema) 2318 { 2319 avro_generic_enum_value_iface_t *iface = 2320 (avro_generic_enum_value_iface_t *) avro_new(avro_generic_enum_value_iface_t); 2321 if (iface == NULL) { 2322 return NULL; 2323 } 2324 2325 iface->parent = AVRO_GENERIC_ENUM_CLASS; 2326 iface->refcount = 1; 2327 iface->schema = avro_schema_incref(schema); 2328 return &iface->parent; 2329 } 2330 2331 2332 /*----------------------------------------------------------------------- 2333 * fixed 2334 */ 2335 2336 typedef struct avro_generic_fixed_value_iface { 2337 avro_generic_value_iface_t parent; 2338 volatile int refcount; 2339 avro_schema_t schema; 2340 size_t data_size; 2341 } avro_generic_fixed_value_iface_t; 2342 2343 2344 static avro_value_iface_t * 2345 avro_generic_fixed_incref_iface(avro_value_iface_t *viface) 2346 { 2347 avro_generic_fixed_value_iface_t *iface = 2348 container_of(viface, avro_generic_fixed_value_iface_t, parent); 2349 avro_refcount_inc(&iface->refcount); 2350 return viface; 2351 } 2352 2353 static void 2354 avro_generic_fixed_decref_iface(avro_value_iface_t *viface) 2355 { 2356 avro_generic_fixed_value_iface_t *iface = 2357 container_of(viface, avro_generic_fixed_value_iface_t, parent); 2358 if (avro_refcount_dec(&iface->refcount)) { 2359 avro_schema_decref(iface->schema); 2360 avro_freet(avro_generic_fixed_value_iface_t, iface); 2361 } 2362 } 2363 2364 static int 2365 avro_generic_fixed_reset(const avro_value_iface_t *viface, void *vself) 2366 { 2367 const avro_generic_fixed_value_iface_t *iface = 2368 container_of(viface, avro_generic_fixed_value_iface_t, parent); 2369 memset(vself, 0, iface->data_size); 2370 return 0; 2371 } 2372 2373 static avro_type_t 2374 avro_generic_fixed_get_type(const avro_value_iface_t *iface, const void *vself) 2375 { 2376 AVRO_UNUSED(iface); 2377 AVRO_UNUSED(vself); 2378 return AVRO_FIXED; 2379 } 2380 2381 static avro_schema_t 2382 avro_generic_fixed_get_schema(const avro_value_iface_t *viface, const void *vself) 2383 { 2384 const avro_generic_fixed_value_iface_t *iface = 2385 container_of(viface, avro_generic_fixed_value_iface_t, parent); 2386 AVRO_UNUSED(vself); 2387 return iface->schema; 2388 } 2389 2390 static int 2391 avro_generic_fixed_get(const avro_value_iface_t *viface, 2392 const void *vself, const void **buf, size_t *size) 2393 { 2394 const avro_generic_fixed_value_iface_t *iface = 2395 container_of(viface, avro_generic_fixed_value_iface_t, parent); 2396 if (buf != NULL) { 2397 *buf = vself; 2398 } 2399 if (size != NULL) { 2400 *size = iface->data_size; 2401 } 2402 return 0; 2403 } 2404 2405 static int 2406 avro_generic_fixed_grab(const avro_value_iface_t *viface, 2407 const void *vself, avro_wrapped_buffer_t *dest) 2408 { 2409 const avro_generic_fixed_value_iface_t *iface = 2410 container_of(viface, avro_generic_fixed_value_iface_t, parent); 2411 return avro_wrapped_buffer_new(dest, vself, iface->data_size); 2412 } 2413 2414 static int 2415 avro_generic_fixed_set(const avro_value_iface_t *viface, 2416 void *vself, void *buf, size_t size) 2417 { 2418 check_param(EINVAL, buf != NULL, "fixed contents"); 2419 const avro_generic_fixed_value_iface_t *iface = 2420 container_of(viface, avro_generic_fixed_value_iface_t, parent); 2421 if (size != iface->data_size) { 2422 avro_set_error("Invalid data size in set_fixed"); 2423 return EINVAL; 2424 } 2425 memcpy(vself, buf, size); 2426 return 0; 2427 } 2428 2429 static int 2430 avro_generic_fixed_give(const avro_value_iface_t *viface, 2431 void *vself, avro_wrapped_buffer_t *buf) 2432 { 2433 int rval = avro_generic_fixed_set 2434 (viface, vself, (void *) buf->buf, buf->size); 2435 avro_wrapped_buffer_free(buf); 2436 return rval; 2437 } 2438 2439 static size_t 2440 avro_generic_fixed_instance_size(const avro_value_iface_t *viface) 2441 { 2442 const avro_generic_fixed_value_iface_t *iface = 2443 container_of(viface, avro_generic_fixed_value_iface_t, parent); 2444 return iface->data_size; 2445 } 2446 2447 static int 2448 avro_generic_fixed_init(const avro_value_iface_t *viface, void *vself) 2449 { 2450 const avro_generic_fixed_value_iface_t *iface = 2451 container_of(viface, avro_generic_fixed_value_iface_t, parent); 2452 memset(vself, 0, iface->data_size); 2453 return 0; 2454 } 2455 2456 static void 2457 avro_generic_fixed_done(const avro_value_iface_t *viface, void *vself) 2458 { 2459 AVRO_UNUSED(viface); 2460 AVRO_UNUSED(vself); 2461 } 2462 2463 static avro_generic_value_iface_t AVRO_GENERIC_FIXED_CLASS = 2464 { 2465 { 2466 /* "class" methods */ 2467 avro_generic_fixed_incref_iface, 2468 avro_generic_fixed_decref_iface, 2469 /* general "instance" methods */ 2470 avro_generic_value_incref, 2471 avro_generic_value_decref, 2472 avro_generic_fixed_reset, 2473 avro_generic_fixed_get_type, 2474 avro_generic_fixed_get_schema, 2475 /* primitive getters */ 2476 NULL, /* get_boolean */ 2477 NULL, /* get_bytes */ 2478 NULL, /* grab_bytes */ 2479 NULL, /* get_double */ 2480 NULL, /* get_float */ 2481 NULL, /* get_int */ 2482 NULL, /* get_long */ 2483 NULL, /* get_null */ 2484 NULL, /* get_string */ 2485 NULL, /* grab_string */ 2486 NULL, /* get_enum */ 2487 avro_generic_fixed_get, 2488 avro_generic_fixed_grab, 2489 /* primitive setters */ 2490 NULL, /* set_boolean */ 2491 NULL, /* set_bytes */ 2492 NULL, /* give_bytes */ 2493 NULL, /* set_double */ 2494 NULL, /* set_float */ 2495 NULL, /* set_int */ 2496 NULL, /* set_long */ 2497 NULL, /* set_null */ 2498 NULL, /* set_string */ 2499 NULL, /* set_string_length */ 2500 NULL, /* give_string_length */ 2501 NULL, /* set_enum */ 2502 avro_generic_fixed_set, 2503 avro_generic_fixed_give, 2504 /* compound getters */ 2505 NULL, /* get_size */ 2506 NULL, /* get_by_index */ 2507 NULL, /* get_by_name */ 2508 NULL, /* get_discriminant */ 2509 NULL, /* get_current_branch */ 2510 /* compound setters */ 2511 NULL, /* append */ 2512 NULL, /* add */ 2513 NULL /* set_branch */ 2514 }, 2515 avro_generic_fixed_instance_size, 2516 avro_generic_fixed_init, 2517 avro_generic_fixed_done 2518 }; 2519 2520 static avro_generic_value_iface_t * 2521 avro_generic_fixed_class(avro_schema_t schema) 2522 { 2523 avro_generic_fixed_value_iface_t *iface = 2524 (avro_generic_fixed_value_iface_t *) avro_new(avro_generic_fixed_value_iface_t); 2525 if (iface == NULL) { 2526 return NULL; 2527 } 2528 2529 iface->parent = AVRO_GENERIC_FIXED_CLASS; 2530 iface->refcount = 1; 2531 iface->schema = avro_schema_incref(schema); 2532 iface->data_size = avro_schema_fixed_size(schema); 2533 return &iface->parent; 2534 } 2535 2536 2537 /*----------------------------------------------------------------------- 2538 * map 2539 */ 2540 2541 /* 2542 * For generic maps, we need to store the value implementation for the 2543 * map's elements. 2544 */ 2545 2546 typedef struct avro_generic_map_value_iface { 2547 avro_generic_value_iface_t parent; 2548 volatile int refcount; 2549 avro_schema_t schema; 2550 avro_generic_value_iface_t *child_giface; 2551 } avro_generic_map_value_iface_t; 2552 2553 typedef struct avro_generic_map { 2554 avro_raw_map_t map; 2555 } avro_generic_map_t; 2556 2557 2558 static avro_value_iface_t * 2559 avro_generic_map_incref_iface(avro_value_iface_t *viface) 2560 { 2561 avro_generic_map_value_iface_t *iface = 2562 container_of(viface, avro_generic_map_value_iface_t, parent); 2563 avro_refcount_inc(&iface->refcount); 2564 return viface; 2565 } 2566 2567 static void 2568 avro_generic_map_decref_iface(avro_value_iface_t *viface) 2569 { 2570 avro_generic_map_value_iface_t *iface = 2571 container_of(viface, avro_generic_map_value_iface_t, parent); 2572 if (avro_refcount_dec(&iface->refcount)) { 2573 avro_schema_decref(iface->schema); 2574 avro_value_iface_decref(&iface->child_giface->parent); 2575 avro_freet(avro_generic_map_value_iface_t, iface); 2576 } 2577 } 2578 2579 2580 static void 2581 avro_generic_map_free_elements(const avro_generic_value_iface_t *child_giface, 2582 avro_generic_map_t *self) 2583 { 2584 size_t i; 2585 for (i = 0; i < avro_raw_map_size(&self->map); i++) { 2586 void *child_self = avro_raw_map_get_raw(&self->map, i); 2587 avro_value_done(child_giface, child_self); 2588 } 2589 } 2590 2591 static int 2592 avro_generic_map_reset(const avro_value_iface_t *viface, void *vself) 2593 { 2594 const avro_generic_map_value_iface_t *iface = 2595 container_of(viface, avro_generic_map_value_iface_t, parent); 2596 avro_generic_map_t *self = (avro_generic_map_t *) vself; 2597 avro_generic_map_free_elements(iface->child_giface, self); 2598 avro_raw_map_clear(&self->map); 2599 return 0; 2600 } 2601 2602 static avro_type_t 2603 avro_generic_map_get_type(const avro_value_iface_t *viface, const void *vself) 2604 { 2605 AVRO_UNUSED(viface); 2606 AVRO_UNUSED(vself); 2607 return AVRO_MAP; 2608 } 2609 2610 static avro_schema_t 2611 avro_generic_map_get_schema(const avro_value_iface_t *viface, const void *vself) 2612 { 2613 const avro_generic_map_value_iface_t *iface = 2614 container_of(viface, avro_generic_map_value_iface_t, parent); 2615 AVRO_UNUSED(vself); 2616 return iface->schema; 2617 } 2618 2619 static int 2620 avro_generic_map_get_size(const avro_value_iface_t *viface, 2621 const void *vself, size_t *size) 2622 { 2623 AVRO_UNUSED(viface); 2624 const avro_generic_map_t *self = (const avro_generic_map_t *) vself; 2625 if (size != NULL) { 2626 *size = avro_raw_map_size(&self->map); 2627 } 2628 return 0; 2629 } 2630 2631 static int 2632 avro_generic_map_get_by_index(const avro_value_iface_t *viface, 2633 const void *vself, size_t index, 2634 avro_value_t *child, const char **name) 2635 { 2636 const avro_generic_map_value_iface_t *iface = 2637 container_of(viface, avro_generic_map_value_iface_t, parent); 2638 const avro_generic_map_t *self = (const avro_generic_map_t *) vself; 2639 if (index >= avro_raw_map_size(&self->map)) { 2640 avro_set_error("Map index %" PRIsz " out of range", index); 2641 return EINVAL; 2642 } 2643 child->iface = &iface->child_giface->parent; 2644 child->self = avro_raw_map_get_raw(&self->map, index); 2645 if (name != NULL) { 2646 *name = avro_raw_map_get_key(&self->map, index); 2647 } 2648 return 0; 2649 } 2650 2651 static int 2652 avro_generic_map_get_by_name(const avro_value_iface_t *viface, 2653 const void *vself, const char *name, 2654 avro_value_t *child, size_t *index) 2655 { 2656 const avro_generic_map_value_iface_t *iface = 2657 container_of(viface, avro_generic_map_value_iface_t, parent); 2658 const avro_generic_map_t *self = (const avro_generic_map_t *) vself; 2659 child->iface = &iface->child_giface->parent; 2660 child->self = avro_raw_map_get(&self->map, name, index); 2661 if (child->self == NULL) { 2662 avro_set_error("No map element named %s", name); 2663 return EINVAL; 2664 } 2665 return 0; 2666 } 2667 2668 static int 2669 avro_generic_map_add(const avro_value_iface_t *viface, 2670 void *vself, const char *key, 2671 avro_value_t *child, size_t *index, int *is_new) 2672 { 2673 const avro_generic_map_value_iface_t *iface = 2674 container_of(viface, avro_generic_map_value_iface_t, parent); 2675 int rval; 2676 avro_generic_map_t *self = (avro_generic_map_t *) vself; 2677 child->iface = &iface->child_giface->parent; 2678 rval = avro_raw_map_get_or_create(&self->map, key, 2679 &child->self, index); 2680 if (rval < 0) { 2681 return -rval; 2682 } 2683 if (is_new != NULL) { 2684 *is_new = rval; 2685 } 2686 if (rval) { 2687 check(rval, avro_value_init(iface->child_giface, child->self)); 2688 } 2689 return 0; 2690 } 2691 2692 static size_t 2693 avro_generic_map_instance_size(const avro_value_iface_t *viface) 2694 { 2695 AVRO_UNUSED(viface); 2696 return sizeof(avro_generic_map_t); 2697 } 2698 2699 static int 2700 avro_generic_map_init(const avro_value_iface_t *viface, void *vself) 2701 { 2702 const avro_generic_map_value_iface_t *iface = 2703 container_of(viface, avro_generic_map_value_iface_t, parent); 2704 avro_generic_map_t *self = (avro_generic_map_t *) vself; 2705 2706 size_t child_size = avro_value_instance_size(iface->child_giface); 2707 avro_raw_map_init(&self->map, child_size); 2708 return 0; 2709 } 2710 2711 static void 2712 avro_generic_map_done(const avro_value_iface_t *viface, void *vself) 2713 { 2714 const avro_generic_map_value_iface_t *iface = 2715 container_of(viface, avro_generic_map_value_iface_t, parent); 2716 avro_generic_map_t *self = (avro_generic_map_t *) vself; 2717 avro_generic_map_free_elements(iface->child_giface, self); 2718 avro_raw_map_done(&self->map); 2719 } 2720 2721 static avro_generic_value_iface_t AVRO_GENERIC_MAP_CLASS = 2722 { 2723 { 2724 /* "class" methods */ 2725 avro_generic_map_incref_iface, 2726 avro_generic_map_decref_iface, 2727 /* general "instance" methods */ 2728 avro_generic_value_incref, 2729 avro_generic_value_decref, 2730 avro_generic_map_reset, 2731 avro_generic_map_get_type, 2732 avro_generic_map_get_schema, 2733 /* primitive getters */ 2734 NULL, /* get_boolean */ 2735 NULL, /* get_bytes */ 2736 NULL, /* grab_bytes */ 2737 NULL, /* get_double */ 2738 NULL, /* get_float */ 2739 NULL, /* get_int */ 2740 NULL, /* get_long */ 2741 NULL, /* get_null */ 2742 NULL, /* get_string */ 2743 NULL, /* grab_string */ 2744 NULL, /* get_enum */ 2745 NULL, /* get_fixed */ 2746 NULL, /* grab_fixed */ 2747 /* primitive setters */ 2748 NULL, /* set_boolean */ 2749 NULL, /* set_bytes */ 2750 NULL, /* give_bytes */ 2751 NULL, /* set_double */ 2752 NULL, /* set_float */ 2753 NULL, /* set_int */ 2754 NULL, /* set_long */ 2755 NULL, /* set_null */ 2756 NULL, /* set_string */ 2757 NULL, /* set_string_length */ 2758 NULL, /* give_string_length */ 2759 NULL, /* set_enum */ 2760 NULL, /* set_fixed */ 2761 NULL, /* give_fixed */ 2762 /* compound getters */ 2763 avro_generic_map_get_size, 2764 avro_generic_map_get_by_index, 2765 avro_generic_map_get_by_name, 2766 NULL, /* get_discriminant */ 2767 NULL, /* get_current_branch */ 2768 /* compound setters */ 2769 NULL, /* append */ 2770 avro_generic_map_add, 2771 NULL /* set_branch */ 2772 }, 2773 avro_generic_map_instance_size, 2774 avro_generic_map_init, 2775 avro_generic_map_done 2776 }; 2777 2778 static avro_generic_value_iface_t * 2779 avro_generic_map_class(avro_schema_t schema, memoize_state_t *state) 2780 { 2781 avro_schema_t child_schema = avro_schema_array_items(schema); 2782 avro_generic_value_iface_t *child_giface = 2783 avro_generic_class_from_schema_memoized(child_schema, state); 2784 if (child_giface == NULL) { 2785 return NULL; 2786 } 2787 2788 ssize_t child_size = avro_value_instance_size(child_giface); 2789 if (child_size < 0) { 2790 avro_set_error("Map value class must provide instance_size"); 2791 avro_value_iface_decref(&child_giface->parent); 2792 return NULL; 2793 } 2794 2795 avro_generic_map_value_iface_t *iface = 2796 (avro_generic_map_value_iface_t *) avro_new(avro_generic_map_value_iface_t); 2797 if (iface == NULL) { 2798 avro_value_iface_decref(&child_giface->parent); 2799 return NULL; 2800 } 2801 2802 /* 2803 * TODO: Maybe check that schema.items matches 2804 * child_iface.get_schema? 2805 */ 2806 2807 iface->parent = AVRO_GENERIC_MAP_CLASS; 2808 iface->refcount = 1; 2809 iface->schema = avro_schema_incref(schema); 2810 iface->child_giface = child_giface; 2811 return &iface->parent; 2812 } 2813 2814 2815 /*----------------------------------------------------------------------- 2816 * record 2817 */ 2818 2819 #ifndef DEBUG_FIELD_OFFSETS 2820 #define DEBUG_FIELD_OFFSETS 0 2821 #endif 2822 2823 #if DEBUG_FIELD_OFFSETS 2824 #include <stdio.h> 2825 #endif 2826 2827 /* 2828 * For generic records, we need to store the value implementation for 2829 * each field. We also need to store an offset for each field, since 2830 * we're going to store the contents of each field directly in the 2831 * record, rather than via pointers. 2832 */ 2833 2834 typedef struct avro_generic_record_value_iface { 2835 avro_generic_value_iface_t parent; 2836 volatile int refcount; 2837 avro_schema_t schema; 2838 2839 /** The total size of each value struct for this record. */ 2840 size_t instance_size; 2841 2842 /** The number of fields in this record. Yes, we could get this 2843 * from schema, but this is easier. */ 2844 size_t field_count; 2845 2846 /** The offset of each field within the record struct. */ 2847 size_t *field_offsets; 2848 2849 /** The value implementation for each field. */ 2850 avro_generic_value_iface_t **field_ifaces; 2851 } avro_generic_record_value_iface_t; 2852 2853 typedef struct avro_generic_record { 2854 /* The rest of the struct is taken up by the inline storage 2855 * needed for each field. */ 2856 } avro_generic_record_t; 2857 2858 2859 /** Return a pointer to the given field within a record struct. */ 2860 #define avro_generic_record_field(iface, rec, index) \ 2861 (((char *) (rec)) + (iface)->field_offsets[(index)]) 2862 2863 2864 static avro_value_iface_t * 2865 avro_generic_record_incref_iface(avro_value_iface_t *viface) 2866 { 2867 avro_generic_record_value_iface_t *iface = 2868 container_of(viface, avro_generic_record_value_iface_t, parent); 2869 avro_refcount_inc(&iface->refcount); 2870 return viface; 2871 } 2872 2873 static void 2874 avro_generic_record_decref_iface(avro_value_iface_t *viface) 2875 { 2876 avro_generic_record_value_iface_t *iface = 2877 container_of(viface, avro_generic_record_value_iface_t, parent); 2878 2879 if (avro_refcount_dec(&iface->refcount)) { 2880 size_t i; 2881 for (i = 0; i < iface->field_count; i++) { 2882 avro_value_iface_decref(&iface->field_ifaces[i]->parent); 2883 } 2884 2885 avro_schema_decref(iface->schema); 2886 avro_free(iface->field_offsets, 2887 sizeof(size_t) * iface->field_count); 2888 avro_free(iface->field_ifaces, 2889 sizeof(avro_generic_value_iface_t *) * iface->field_count); 2890 2891 avro_freet(avro_generic_record_value_iface_t, iface); 2892 } 2893 } 2894 2895 2896 static int 2897 avro_generic_record_reset(const avro_value_iface_t *viface, void *vself) 2898 { 2899 const avro_generic_record_value_iface_t *iface = 2900 container_of(viface, avro_generic_record_value_iface_t, parent); 2901 int rval; 2902 avro_generic_record_t *self = (avro_generic_record_t *) vself; 2903 size_t i; 2904 for (i = 0; i < iface->field_count; i++) { 2905 avro_value_t value = { 2906 &iface->field_ifaces[i]->parent, 2907 avro_generic_record_field(iface, self, i) 2908 }; 2909 check(rval, avro_value_reset(&value)); 2910 } 2911 return 0; 2912 } 2913 2914 static avro_type_t 2915 avro_generic_record_get_type(const avro_value_iface_t *viface, const void *vself) 2916 { 2917 AVRO_UNUSED(viface); 2918 AVRO_UNUSED(vself); 2919 return AVRO_RECORD; 2920 } 2921 2922 static avro_schema_t 2923 avro_generic_record_get_schema(const avro_value_iface_t *viface, const void *vself) 2924 { 2925 const avro_generic_record_value_iface_t *iface = 2926 container_of(viface, avro_generic_record_value_iface_t, parent); 2927 AVRO_UNUSED(vself); 2928 return iface->schema; 2929 } 2930 2931 static int 2932 avro_generic_record_get_size(const avro_value_iface_t *viface, 2933 const void *vself, size_t *size) 2934 { 2935 const avro_generic_record_value_iface_t *iface = 2936 container_of(viface, avro_generic_record_value_iface_t, parent); 2937 AVRO_UNUSED(vself); 2938 if (size != NULL) { 2939 *size = iface->field_count; 2940 } 2941 return 0; 2942 } 2943 2944 static int 2945 avro_generic_record_get_by_index(const avro_value_iface_t *viface, 2946 const void *vself, size_t index, 2947 avro_value_t *child, const char **name) 2948 { 2949 const avro_generic_record_value_iface_t *iface = 2950 container_of(viface, avro_generic_record_value_iface_t, parent); 2951 const avro_generic_record_t *self = (const avro_generic_record_t *) vself; 2952 if (index >= iface->field_count) { 2953 avro_set_error("Field index %" PRIsz " out of range", index); 2954 return EINVAL; 2955 } 2956 child->iface = &iface->field_ifaces[index]->parent; 2957 child->self = avro_generic_record_field(iface, self, index); 2958 2959 /* 2960 * Grab the field name from the schema if asked for. 2961 */ 2962 if (name != NULL) { 2963 avro_schema_t schema = iface->schema; 2964 *name = avro_schema_record_field_name(schema, index); 2965 } 2966 2967 return 0; 2968 } 2969 2970 static int 2971 avro_generic_record_get_by_name(const avro_value_iface_t *viface, 2972 const void *vself, const char *name, 2973 avro_value_t *child, size_t *index_out) 2974 { 2975 const avro_generic_record_value_iface_t *iface = 2976 container_of(viface, avro_generic_record_value_iface_t, parent); 2977 const avro_generic_record_t *self = (const avro_generic_record_t *) vself; 2978 2979 avro_schema_t schema = iface->schema; 2980 int index = avro_schema_record_field_get_index(schema, name); 2981 if (index < 0) { 2982 avro_set_error("Unknown record field %s", name); 2983 return EINVAL; 2984 } 2985 2986 child->iface = &iface->field_ifaces[index]->parent; 2987 child->self = avro_generic_record_field(iface, self, index); 2988 if (index_out != NULL) { 2989 *index_out = index; 2990 } 2991 return 0; 2992 } 2993 2994 static size_t 2995 avro_generic_record_instance_size(const avro_value_iface_t *viface) 2996 { 2997 const avro_generic_record_value_iface_t *iface = 2998 container_of(viface, avro_generic_record_value_iface_t, parent); 2999 return iface->instance_size; 3000 } 3001 3002 static int 3003 avro_generic_record_init(const avro_value_iface_t *viface, void *vself) 3004 { 3005 int rval; 3006 const avro_generic_record_value_iface_t *iface = 3007 container_of(viface, avro_generic_record_value_iface_t, parent); 3008 avro_generic_record_t *self = (avro_generic_record_t *) vself; 3009 3010 /* Initialize each field */ 3011 size_t i; 3012 for (i = 0; i < iface->field_count; i++) { 3013 check(rval, avro_value_init 3014 (iface->field_ifaces[i], 3015 avro_generic_record_field(iface, self, i))); 3016 } 3017 3018 return 0; 3019 } 3020 3021 static void 3022 avro_generic_record_done(const avro_value_iface_t *viface, void *vself) 3023 { 3024 const avro_generic_record_value_iface_t *iface = 3025 container_of(viface, avro_generic_record_value_iface_t, parent); 3026 avro_generic_record_t *self = (avro_generic_record_t *) vself; 3027 size_t i; 3028 for (i = 0; i < iface->field_count; i++) { 3029 avro_value_done(iface->field_ifaces[i], 3030 avro_generic_record_field(iface, self, i)); 3031 } 3032 } 3033 3034 static avro_generic_value_iface_t AVRO_GENERIC_RECORD_CLASS = 3035 { 3036 { 3037 /* "class" methods */ 3038 avro_generic_record_incref_iface, 3039 avro_generic_record_decref_iface, 3040 /* general "instance" methods */ 3041 avro_generic_value_incref, 3042 avro_generic_value_decref, 3043 avro_generic_record_reset, 3044 avro_generic_record_get_type, 3045 avro_generic_record_get_schema, 3046 /* primitive getters */ 3047 NULL, /* get_boolean */ 3048 NULL, /* get_bytes */ 3049 NULL, /* grab_bytes */ 3050 NULL, /* get_double */ 3051 NULL, /* get_float */ 3052 NULL, /* get_int */ 3053 NULL, /* get_long */ 3054 NULL, /* get_null */ 3055 NULL, /* get_string */ 3056 NULL, /* grab_string */ 3057 NULL, /* get_enum */ 3058 NULL, /* get_fixed */ 3059 NULL, /* grab_fixed */ 3060 /* primitive setters */ 3061 NULL, /* set_boolean */ 3062 NULL, /* set_bytes */ 3063 NULL, /* give_bytes */ 3064 NULL, /* set_double */ 3065 NULL, /* set_float */ 3066 NULL, /* set_int */ 3067 NULL, /* set_long */ 3068 NULL, /* set_null */ 3069 NULL, /* set_string */ 3070 NULL, /* set_string_length */ 3071 NULL, /* give_string_length */ 3072 NULL, /* set_enum */ 3073 NULL, /* set_fixed */ 3074 NULL, /* give_fixed */ 3075 /* compound getters */ 3076 avro_generic_record_get_size, 3077 avro_generic_record_get_by_index, 3078 avro_generic_record_get_by_name, 3079 NULL, /* get_discriminant */ 3080 NULL, /* get_current_branch */ 3081 /* compound setters */ 3082 NULL, /* append */ 3083 NULL, /* add */ 3084 NULL /* set_branch */ 3085 }, 3086 avro_generic_record_instance_size, 3087 avro_generic_record_init, 3088 avro_generic_record_done 3089 }; 3090 3091 static avro_generic_value_iface_t * 3092 avro_generic_record_class(avro_schema_t schema, memoize_state_t *state) 3093 { 3094 avro_generic_record_value_iface_t *iface = 3095 (avro_generic_record_value_iface_t *) avro_new(avro_generic_record_value_iface_t); 3096 if (iface == NULL) { 3097 return NULL; 3098 } 3099 3100 memset(iface, 0, sizeof(avro_generic_record_value_iface_t)); 3101 iface->parent = AVRO_GENERIC_RECORD_CLASS; 3102 iface->refcount = 1; 3103 iface->schema = avro_schema_incref(schema); 3104 3105 iface->field_count = avro_schema_record_size(schema); 3106 size_t field_offsets_size = 3107 sizeof(size_t) * iface->field_count; 3108 size_t field_ifaces_size = 3109 sizeof(avro_generic_value_iface_t *) * iface->field_count; 3110 3111 if (iface->field_count == 0) { 3112 iface->field_offsets = NULL; 3113 iface->field_ifaces = NULL; 3114 } else { 3115 iface->field_offsets = (size_t *) avro_malloc(field_offsets_size); 3116 if (iface->field_offsets == NULL) { 3117 goto error; 3118 } 3119 3120 iface->field_ifaces = (avro_generic_value_iface_t **) avro_malloc(field_ifaces_size); 3121 if (iface->field_ifaces == NULL) { 3122 goto error; 3123 } 3124 } 3125 3126 size_t next_offset = sizeof(avro_generic_record_t); 3127 #if DEBUG_FIELD_OFFSETS 3128 fprintf(stderr, " Record %s\n Header: Offset 0, size %" PRIsz "\n", 3129 avro_schema_type_name(schema), 3130 sizeof(avro_generic_record_t)); 3131 #endif 3132 size_t i; 3133 for (i = 0; i < iface->field_count; i++) { 3134 #if DEBUG_FIELD_OFFSETS 3135 fprintf(stderr, " Field %" PRIsz ":\n", i); 3136 #endif 3137 avro_schema_t field_schema = 3138 avro_schema_record_field_get_by_index(schema, i); 3139 #if DEBUG_FIELD_OFFSETS 3140 fprintf(stderr, " Schema %s\n", 3141 avro_schema_type_name(field_schema)); 3142 #endif 3143 3144 iface->field_offsets[i] = next_offset; 3145 3146 iface->field_ifaces[i] = 3147 avro_generic_class_from_schema_memoized(field_schema, state); 3148 if (iface->field_ifaces[i] == NULL) { 3149 goto error; 3150 } 3151 3152 ssize_t field_size = 3153 avro_value_instance_size(iface->field_ifaces[i]); 3154 if (field_size < 0) { 3155 avro_set_error("Record field class must provide instance_size"); 3156 goto error; 3157 } 3158 3159 #if DEBUG_FIELD_OFFSETS 3160 fprintf(stderr, " Offset %" PRIsz ", size %" PRIsz "\n", 3161 next_offset, field_size); 3162 #endif 3163 next_offset += field_size; 3164 } 3165 3166 iface->instance_size = next_offset; 3167 #if DEBUG_FIELD_OFFSETS 3168 fprintf(stderr, " TOTAL SIZE: %" PRIsz "\n", next_offset); 3169 #endif 3170 3171 return &iface->parent; 3172 3173 error: 3174 avro_schema_decref(iface->schema); 3175 if (iface->field_offsets != NULL) { 3176 avro_free(iface->field_offsets, field_offsets_size); 3177 } 3178 if (iface->field_ifaces != NULL) { 3179 for (i = 0; i < iface->field_count; i++) { 3180 if (iface->field_ifaces[i] != NULL) { 3181 avro_value_iface_decref(&iface->field_ifaces[i]->parent); 3182 } 3183 } 3184 avro_free(iface->field_ifaces, field_ifaces_size); 3185 } 3186 avro_freet(avro_generic_record_value_iface_t, iface); 3187 return NULL; 3188 } 3189 3190 3191 /*----------------------------------------------------------------------- 3192 * union 3193 */ 3194 3195 #ifndef DEBUG_BRANCHES_OFFSETS 3196 #define DEBUG_BRANCHES_OFFSETS 0 3197 #endif 3198 3199 #if DEBUG_BRANCHES_OFFSETS 3200 #include <stdio.h> 3201 #endif 3202 3203 /* 3204 * For generic unions, we need to store the value implementation for 3205 * each branch, just like for generic records. However, for unions, we 3206 * can only have one branch active at a time, so we can reuse the space 3207 * in the union struct, just like is done with C unions. 3208 */ 3209 3210 typedef struct avro_generic_union_value_iface { 3211 avro_generic_value_iface_t parent; 3212 volatile int refcount; 3213 avro_schema_t schema; 3214 3215 /** The total size of each value struct for this union. */ 3216 size_t instance_size; 3217 3218 /** The number of branches in this union. Yes, we could get 3219 * this from schema, but this is easier. */ 3220 size_t branch_count; 3221 3222 /** The value implementation for each branch. */ 3223 avro_generic_value_iface_t **branch_ifaces; 3224 } avro_generic_union_value_iface_t; 3225 3226 typedef struct avro_generic_union { 3227 /** The currently active branch of the union. -1 if no branch 3228 * is selected. */ 3229 int discriminant; 3230 3231 /* The rest of the struct is taken up by the inline storage 3232 * needed for the active branch. */ 3233 } avro_generic_union_t; 3234 3235 3236 /** Return the child interface for the active branch. */ 3237 #define avro_generic_union_branch_giface(iface, _union) \ 3238 ((iface)->branch_ifaces[(_union)->discriminant]) 3239 #define avro_generic_union_branch_iface(iface, _union) \ 3240 (&(avro_generic_union_branch_giface((iface), (_union)))->parent) 3241 3242 /** Return a pointer to the active branch within a union struct. */ 3243 #define avro_generic_union_branch(_union) \ 3244 (((char *) (_union)) + sizeof(avro_generic_union_t)) 3245 3246 3247 static avro_value_iface_t * 3248 avro_generic_union_incref_iface(avro_value_iface_t *viface) 3249 { 3250 avro_generic_union_value_iface_t *iface = 3251 container_of(viface, avro_generic_union_value_iface_t, parent); 3252 avro_refcount_inc(&iface->refcount); 3253 return viface; 3254 } 3255 3256 static void 3257 avro_generic_union_decref_iface(avro_value_iface_t *viface) 3258 { 3259 avro_generic_union_value_iface_t *iface = 3260 container_of(viface, avro_generic_union_value_iface_t, parent); 3261 3262 if (avro_refcount_dec(&iface->refcount)) { 3263 size_t i; 3264 for (i = 0; i < iface->branch_count; i++) { 3265 avro_value_iface_decref(&iface->branch_ifaces[i]->parent); 3266 } 3267 3268 avro_schema_decref(iface->schema); 3269 avro_free(iface->branch_ifaces, 3270 sizeof(avro_generic_value_iface_t *) * iface->branch_count); 3271 3272 avro_freet(avro_generic_union_value_iface_t, iface); 3273 } 3274 } 3275 3276 3277 static int 3278 avro_generic_union_reset(const avro_value_iface_t *viface, void *vself) 3279 { 3280 const avro_generic_union_value_iface_t *iface = 3281 container_of(viface, avro_generic_union_value_iface_t, parent); 3282 avro_generic_union_t *self = (avro_generic_union_t *) vself; 3283 /* Keep the same branch selected, for the common case that we're 3284 * about to reuse it. */ 3285 if (self->discriminant >= 0) { 3286 #if DEBUG_BRANCHES 3287 fprintf(stderr, "Resetting branch %d\n", 3288 self->discriminant); 3289 #endif 3290 avro_value_t value = { 3291 avro_generic_union_branch_iface(iface, self), 3292 avro_generic_union_branch(self) 3293 }; 3294 return avro_value_reset(&value); 3295 } 3296 return 0; 3297 } 3298 3299 static avro_type_t 3300 avro_generic_union_get_type(const avro_value_iface_t *viface, const void *vself) 3301 { 3302 AVRO_UNUSED(viface); 3303 AVRO_UNUSED(vself); 3304 return AVRO_UNION; 3305 } 3306 3307 static avro_schema_t 3308 avro_generic_union_get_schema(const avro_value_iface_t *viface, const void *vself) 3309 { 3310 const avro_generic_union_value_iface_t *iface = 3311 container_of(viface, avro_generic_union_value_iface_t, parent); 3312 AVRO_UNUSED(vself); 3313 return iface->schema; 3314 } 3315 3316 static int 3317 avro_generic_union_get_discriminant(const avro_value_iface_t *viface, 3318 const void *vself, int *out) 3319 { 3320 AVRO_UNUSED(viface); 3321 const avro_generic_union_t *self = (const avro_generic_union_t *) vself; 3322 *out = self->discriminant; 3323 return 0; 3324 } 3325 3326 static int 3327 avro_generic_union_get_current_branch(const avro_value_iface_t *viface, 3328 const void *vself, avro_value_t *branch) 3329 { 3330 const avro_generic_union_value_iface_t *iface = 3331 container_of(viface, avro_generic_union_value_iface_t, parent); 3332 const avro_generic_union_t *self = (const avro_generic_union_t *) vself; 3333 if (self->discriminant < 0) { 3334 avro_set_error("Union has no selected branch"); 3335 return EINVAL; 3336 } 3337 branch->iface = avro_generic_union_branch_iface(iface, self); 3338 branch->self = avro_generic_union_branch(self); 3339 return 0; 3340 } 3341 3342 static int 3343 avro_generic_union_set_branch(const avro_value_iface_t *viface, 3344 void *vself, int discriminant, 3345 avro_value_t *branch) 3346 { 3347 const avro_generic_union_value_iface_t *iface = 3348 container_of(viface, avro_generic_union_value_iface_t, parent); 3349 int rval; 3350 avro_generic_union_t *self = (avro_generic_union_t *) vself; 3351 3352 #if DEBUG_BRANCHES 3353 fprintf(stderr, "Selecting branch %d (was %d)\n", 3354 discriminant, self->discriminant); 3355 #endif 3356 3357 /* 3358 * If the new desired branch is different than the currently 3359 * active one, then finalize the old branch and initialize the 3360 * new one. 3361 */ 3362 if (self->discriminant != discriminant) { 3363 if (self->discriminant >= 0) { 3364 #if DEBUG_BRANCHES 3365 fprintf(stderr, "Finalizing branch %d\n", 3366 self->discriminant); 3367 #endif 3368 avro_value_done 3369 (avro_generic_union_branch_giface(iface, self), 3370 avro_generic_union_branch(self)); 3371 } 3372 self->discriminant = discriminant; 3373 if (discriminant >= 0) { 3374 #if DEBUG_BRANCHES 3375 fprintf(stderr, "Initializing branch %d\n", 3376 self->discriminant); 3377 #endif 3378 check(rval, avro_value_init 3379 (avro_generic_union_branch_giface(iface, self), 3380 avro_generic_union_branch(self))); 3381 } 3382 } 3383 3384 if (branch != NULL) { 3385 branch->iface = avro_generic_union_branch_iface(iface, self); 3386 branch->self = avro_generic_union_branch(self); 3387 } 3388 3389 return 0; 3390 } 3391 3392 static size_t 3393 avro_generic_union_instance_size(const avro_value_iface_t *viface) 3394 { 3395 const avro_generic_union_value_iface_t *iface = 3396 container_of(viface, avro_generic_union_value_iface_t, parent); 3397 return iface->instance_size; 3398 } 3399 3400 static int 3401 avro_generic_union_init(const avro_value_iface_t *viface, void *vself) 3402 { 3403 AVRO_UNUSED(viface); 3404 avro_generic_union_t *self = (avro_generic_union_t *) vself; 3405 self->discriminant = -1; 3406 return 0; 3407 } 3408 3409 static void 3410 avro_generic_union_done(const avro_value_iface_t *viface, void *vself) 3411 { 3412 const avro_generic_union_value_iface_t *iface = 3413 container_of(viface, avro_generic_union_value_iface_t, parent); 3414 avro_generic_union_t *self = (avro_generic_union_t *) vself; 3415 if (self->discriminant >= 0) { 3416 #if DEBUG_BRANCHES 3417 fprintf(stderr, "Finalizing branch %d\n", 3418 self->discriminant); 3419 #endif 3420 avro_value_done 3421 (avro_generic_union_branch_giface(iface, self), 3422 avro_generic_union_branch(self)); 3423 self->discriminant = -1; 3424 } 3425 } 3426 3427 static avro_generic_value_iface_t AVRO_GENERIC_UNION_CLASS = 3428 { 3429 { 3430 /* "class" methods */ 3431 avro_generic_union_incref_iface, 3432 avro_generic_union_decref_iface, 3433 /* general "instance" methods */ 3434 avro_generic_value_incref, 3435 avro_generic_value_decref, 3436 avro_generic_union_reset, 3437 avro_generic_union_get_type, 3438 avro_generic_union_get_schema, 3439 /* primitive getters */ 3440 NULL, /* get_boolean */ 3441 NULL, /* get_bytes */ 3442 NULL, /* grab_bytes */ 3443 NULL, /* get_double */ 3444 NULL, /* get_float */ 3445 NULL, /* get_int */ 3446 NULL, /* get_long */ 3447 NULL, /* get_null */ 3448 NULL, /* get_string */ 3449 NULL, /* grab_string */ 3450 NULL, /* get_enum */ 3451 NULL, /* get_fixed */ 3452 NULL, /* grab_fixed */ 3453 /* primitive setters */ 3454 NULL, /* set_boolean */ 3455 NULL, /* set_bytes */ 3456 NULL, /* give_bytes */ 3457 NULL, /* set_double */ 3458 NULL, /* set_float */ 3459 NULL, /* set_int */ 3460 NULL, /* set_long */ 3461 NULL, /* set_null */ 3462 NULL, /* set_string */ 3463 NULL, /* set_string_length */ 3464 NULL, /* give_string_length */ 3465 NULL, /* set_enum */ 3466 NULL, /* set_fixed */ 3467 NULL, /* give_fixed */ 3468 /* compound getters */ 3469 NULL, /* get_size */ 3470 NULL, /* get_by_index */ 3471 NULL, /* get_by_name */ 3472 avro_generic_union_get_discriminant, 3473 avro_generic_union_get_current_branch, 3474 /* compound setters */ 3475 NULL, /* append */ 3476 NULL, /* add */ 3477 avro_generic_union_set_branch 3478 }, 3479 avro_generic_union_instance_size, 3480 avro_generic_union_init, 3481 avro_generic_union_done 3482 }; 3483 3484 static avro_generic_value_iface_t * 3485 avro_generic_union_class(avro_schema_t schema, memoize_state_t *state) 3486 { 3487 avro_generic_union_value_iface_t *iface = 3488 (avro_generic_union_value_iface_t *) avro_new(avro_generic_union_value_iface_t); 3489 if (iface == NULL) { 3490 return NULL; 3491 } 3492 3493 memset(iface, 0, sizeof(avro_generic_union_value_iface_t)); 3494 iface->parent = AVRO_GENERIC_UNION_CLASS; 3495 iface->refcount = 1; 3496 iface->schema = avro_schema_incref(schema); 3497 3498 iface->branch_count = avro_schema_union_size(schema); 3499 size_t branch_ifaces_size = 3500 sizeof(avro_generic_value_iface_t *) * iface->branch_count; 3501 3502 iface->branch_ifaces = (avro_generic_value_iface_t **) avro_malloc(branch_ifaces_size); 3503 if (iface->branch_ifaces == NULL) { 3504 goto error; 3505 } 3506 3507 size_t max_branch_size = 0; 3508 size_t i; 3509 for (i = 0; i < iface->branch_count; i++) { 3510 avro_schema_t branch_schema = 3511 avro_schema_union_branch(schema, i); 3512 3513 iface->branch_ifaces[i] = 3514 avro_generic_class_from_schema_memoized(branch_schema, state); 3515 if (iface->branch_ifaces[i] == NULL) { 3516 goto error; 3517 } 3518 3519 ssize_t branch_size = 3520 avro_value_instance_size(iface->branch_ifaces[i]); 3521 if (branch_size < 0) { 3522 avro_set_error("Union branch class must provide instance_size"); 3523 goto error; 3524 } 3525 3526 #if DEBUG_BRANCHES 3527 fprintf(stderr, "Branch %" PRIsz ", size %" PRIsz "\n", 3528 i, branch_size); 3529 #endif 3530 3531 if ((size_t)branch_size > max_branch_size) { 3532 max_branch_size = (size_t)branch_size; 3533 } 3534 } 3535 3536 iface->instance_size = 3537 sizeof(avro_generic_union_t) + max_branch_size; 3538 #if DEBUG_BRANCHES 3539 fprintf(stderr, "MAX BRANCH SIZE: %" PRIsz "\n", max_branch_size); 3540 #endif 3541 3542 return &iface->parent; 3543 3544 error: 3545 avro_schema_decref(iface->schema); 3546 if (iface->branch_ifaces != NULL) { 3547 for (i = 0; i < iface->branch_count; i++) { 3548 if (iface->branch_ifaces[i] != NULL) { 3549 avro_value_iface_decref(&iface->branch_ifaces[i]->parent); 3550 } 3551 } 3552 avro_free(iface->branch_ifaces, branch_ifaces_size); 3553 } 3554 avro_freet(avro_generic_union_value_iface_t, iface); 3555 return NULL; 3556 } 3557 3558 3559 /*----------------------------------------------------------------------- 3560 * Schema type dispatcher 3561 */ 3562 3563 static avro_generic_value_iface_t * 3564 avro_generic_class_from_schema_memoized(avro_schema_t schema, 3565 memoize_state_t *state) 3566 { 3567 /* 3568 * If we've already instantiated a value class for this schema, 3569 * just return it. 3570 */ 3571 3572 avro_generic_value_iface_t *result = NULL; 3573 if (avro_memoize_get(&state->mem, schema, NULL, (void **) &result)) { 3574 avro_value_iface_incref(&result->parent); 3575 return result; 3576 } 3577 3578 /* 3579 * Otherwise instantiate the value class based on the schema 3580 * type. 3581 */ 3582 3583 switch (schema->type) { 3584 case AVRO_BOOLEAN: 3585 result = &AVRO_GENERIC_BOOLEAN_CLASS; 3586 break; 3587 case AVRO_BYTES: 3588 result = &AVRO_GENERIC_BYTES_CLASS; 3589 break; 3590 case AVRO_DOUBLE: 3591 result = &AVRO_GENERIC_DOUBLE_CLASS; 3592 break; 3593 case AVRO_FLOAT: 3594 result = &AVRO_GENERIC_FLOAT_CLASS; 3595 break; 3596 case AVRO_INT32: 3597 result = &AVRO_GENERIC_INT_CLASS; 3598 break; 3599 case AVRO_INT64: 3600 result = &AVRO_GENERIC_LONG_CLASS; 3601 break; 3602 case AVRO_NULL: 3603 result = &AVRO_GENERIC_NULL_CLASS; 3604 break; 3605 case AVRO_STRING: 3606 result = &AVRO_GENERIC_STRING_CLASS; 3607 break; 3608 3609 case AVRO_ARRAY: 3610 result = avro_generic_array_class(schema, state); 3611 break; 3612 case AVRO_ENUM: 3613 result = avro_generic_enum_class(schema); 3614 break; 3615 case AVRO_FIXED: 3616 result = avro_generic_fixed_class(schema); 3617 break; 3618 case AVRO_MAP: 3619 result = avro_generic_map_class(schema, state); 3620 break; 3621 case AVRO_RECORD: 3622 result = avro_generic_record_class(schema, state); 3623 break; 3624 case AVRO_UNION: 3625 result = avro_generic_union_class(schema, state); 3626 break; 3627 3628 case AVRO_LINK: 3629 { 3630 avro_generic_link_value_iface_t *lresult = 3631 avro_generic_link_class(schema); 3632 lresult->next = state->links; 3633 state->links = lresult; 3634 result = &lresult->parent; 3635 break; 3636 } 3637 3638 default: 3639 avro_set_error("Unknown schema type"); 3640 return NULL; 3641 } 3642 3643 /* 3644 * Add the new value implementation to the memoized state before 3645 * we return. 3646 */ 3647 3648 avro_memoize_set(&state->mem, schema, NULL, result); 3649 return result; 3650 } 3651 3652 avro_value_iface_t * 3653 avro_generic_class_from_schema(avro_schema_t schema) 3654 { 3655 /* 3656 * Create a state to keep track of the value implementations 3657 * that we create for each subschema. 3658 */ 3659 3660 memoize_state_t state; 3661 avro_memoize_init(&state.mem); 3662 state.links = NULL; 3663 3664 /* 3665 * Create the value implementations. 3666 */ 3667 3668 avro_generic_value_iface_t *result = 3669 avro_generic_class_from_schema_memoized(schema, &state); 3670 if (result == NULL) { 3671 avro_memoize_done(&state.mem); 3672 return NULL; 3673 } 3674 3675 /* 3676 * Fix up any link schemas so that their value implementations 3677 * point to their target schemas' implementations. 3678 */ 3679 3680 while (state.links != NULL) { 3681 avro_generic_link_value_iface_t *link_iface = state.links; 3682 avro_schema_t target_schema = 3683 avro_schema_link_target(link_iface->schema); 3684 3685 avro_generic_value_iface_t *target_iface = NULL; 3686 if (!avro_memoize_get(&state.mem, target_schema, NULL, 3687 (void **) &target_iface)) { 3688 avro_set_error("Never created a value implementation for %s", 3689 avro_schema_type_name(target_schema)); 3690 return NULL; 3691 } 3692 3693 /* We don't keep a reference to the target 3694 * implementation, since that would give us a reference 3695 * cycle. */ 3696 link_iface->target_giface = target_iface; 3697 state.links = link_iface->next; 3698 link_iface->next = NULL; 3699 } 3700 3701 /* 3702 * And now we can return. 3703 */ 3704 3705 avro_memoize_done(&state.mem); 3706 return &result->parent; 3707 } 3708