1 /* 2 * QEMU Object Model 3 * 4 * Copyright IBM, Corp. 2011 5 * 6 * Authors: 7 * Anthony Liguori <aliguori@us.ibm.com> 8 * 9 * This work is licensed under the terms of the GNU GPL, version 2 or later. 10 * See the COPYING file in the top-level directory. 11 */ 12 13 #include "qemu/osdep.h" 14 #include "hw/qdev-core.h" 15 #include "qapi/error.h" 16 #include "qom/object.h" 17 #include "qom/object_interfaces.h" 18 #include "qemu/cutils.h" 19 #include "qapi/visitor.h" 20 #include "qapi/string-input-visitor.h" 21 #include "qapi/string-output-visitor.h" 22 #include "qapi/qapi-builtin-visit.h" 23 #include "qapi/qmp/qerror.h" 24 #include "trace.h" 25 26 /* TODO: replace QObject with a simpler visitor to avoid a dependency 27 * of the QOM core on QObject? */ 28 #include "qom/qom-qobject.h" 29 #include "qapi/qmp/qbool.h" 30 #include "qapi/qmp/qnum.h" 31 #include "qapi/qmp/qstring.h" 32 #include "qemu/error-report.h" 33 34 #define MAX_INTERFACES 32 35 36 typedef struct InterfaceImpl InterfaceImpl; 37 typedef struct TypeImpl TypeImpl; 38 39 struct InterfaceImpl 40 { 41 const char *typename; 42 }; 43 44 struct TypeImpl 45 { 46 const char *name; 47 48 size_t class_size; 49 50 size_t instance_size; 51 52 void (*class_init)(ObjectClass *klass, void *data); 53 void (*class_base_init)(ObjectClass *klass, void *data); 54 55 void *class_data; 56 57 void (*instance_init)(Object *obj); 58 void (*instance_post_init)(Object *obj); 59 void (*instance_finalize)(Object *obj); 60 61 bool abstract; 62 63 const char *parent; 64 TypeImpl *parent_type; 65 66 ObjectClass *class; 67 68 int num_interfaces; 69 InterfaceImpl interfaces[MAX_INTERFACES]; 70 }; 71 72 static Type type_interface; 73 74 static GHashTable *type_table_get(void) 75 { 76 static GHashTable *type_table; 77 78 if (type_table == NULL) { 79 type_table = g_hash_table_new(g_str_hash, g_str_equal); 80 } 81 82 return type_table; 83 } 84 85 static bool enumerating_types; 86 87 static void type_table_add(TypeImpl *ti) 88 { 89 assert(!enumerating_types); 90 g_hash_table_insert(type_table_get(), (void *)ti->name, ti); 91 } 92 93 static TypeImpl *type_table_lookup(const char *name) 94 { 95 return g_hash_table_lookup(type_table_get(), name); 96 } 97 98 static TypeImpl *type_new(const TypeInfo *info) 99 { 100 TypeImpl *ti = g_malloc0(sizeof(*ti)); 101 int i; 102 103 g_assert(info->name != NULL); 104 105 if (type_table_lookup(info->name) != NULL) { 106 fprintf(stderr, "Registering `%s' which already exists\n", info->name); 107 abort(); 108 } 109 110 ti->name = g_strdup(info->name); 111 ti->parent = g_strdup(info->parent); 112 113 ti->class_size = info->class_size; 114 ti->instance_size = info->instance_size; 115 116 ti->class_init = info->class_init; 117 ti->class_base_init = info->class_base_init; 118 ti->class_data = info->class_data; 119 120 ti->instance_init = info->instance_init; 121 ti->instance_post_init = info->instance_post_init; 122 ti->instance_finalize = info->instance_finalize; 123 124 ti->abstract = info->abstract; 125 126 for (i = 0; info->interfaces && info->interfaces[i].type; i++) { 127 ti->interfaces[i].typename = g_strdup(info->interfaces[i].type); 128 } 129 ti->num_interfaces = i; 130 131 return ti; 132 } 133 134 static TypeImpl *type_register_internal(const TypeInfo *info) 135 { 136 TypeImpl *ti; 137 ti = type_new(info); 138 139 type_table_add(ti); 140 return ti; 141 } 142 143 TypeImpl *type_register(const TypeInfo *info) 144 { 145 assert(info->parent); 146 return type_register_internal(info); 147 } 148 149 TypeImpl *type_register_static(const TypeInfo *info) 150 { 151 return type_register(info); 152 } 153 154 void type_register_static_array(const TypeInfo *infos, int nr_infos) 155 { 156 int i; 157 158 for (i = 0; i < nr_infos; i++) { 159 type_register_static(&infos[i]); 160 } 161 } 162 163 static TypeImpl *type_get_by_name(const char *name) 164 { 165 if (name == NULL) { 166 return NULL; 167 } 168 169 return type_table_lookup(name); 170 } 171 172 static TypeImpl *type_get_parent(TypeImpl *type) 173 { 174 if (!type->parent_type && type->parent) { 175 type->parent_type = type_get_by_name(type->parent); 176 if (!type->parent_type) { 177 fprintf(stderr, "Type '%s' is missing its parent '%s'\n", 178 type->name, type->parent); 179 abort(); 180 } 181 } 182 183 return type->parent_type; 184 } 185 186 static bool type_has_parent(TypeImpl *type) 187 { 188 return (type->parent != NULL); 189 } 190 191 static size_t type_class_get_size(TypeImpl *ti) 192 { 193 if (ti->class_size) { 194 return ti->class_size; 195 } 196 197 if (type_has_parent(ti)) { 198 return type_class_get_size(type_get_parent(ti)); 199 } 200 201 return sizeof(ObjectClass); 202 } 203 204 static size_t type_object_get_size(TypeImpl *ti) 205 { 206 if (ti->instance_size) { 207 return ti->instance_size; 208 } 209 210 if (type_has_parent(ti)) { 211 return type_object_get_size(type_get_parent(ti)); 212 } 213 214 return 0; 215 } 216 217 size_t object_type_get_instance_size(const char *typename) 218 { 219 TypeImpl *type = type_get_by_name(typename); 220 221 g_assert(type != NULL); 222 return type_object_get_size(type); 223 } 224 225 static bool type_is_ancestor(TypeImpl *type, TypeImpl *target_type) 226 { 227 assert(target_type); 228 229 /* Check if target_type is a direct ancestor of type */ 230 while (type) { 231 if (type == target_type) { 232 return true; 233 } 234 235 type = type_get_parent(type); 236 } 237 238 return false; 239 } 240 241 static void type_initialize(TypeImpl *ti); 242 243 static void type_initialize_interface(TypeImpl *ti, TypeImpl *interface_type, 244 TypeImpl *parent_type) 245 { 246 InterfaceClass *new_iface; 247 TypeInfo info = { }; 248 TypeImpl *iface_impl; 249 250 info.parent = parent_type->name; 251 info.name = g_strdup_printf("%s::%s", ti->name, interface_type->name); 252 info.abstract = true; 253 254 iface_impl = type_new(&info); 255 iface_impl->parent_type = parent_type; 256 type_initialize(iface_impl); 257 g_free((char *)info.name); 258 259 new_iface = (InterfaceClass *)iface_impl->class; 260 new_iface->concrete_class = ti->class; 261 new_iface->interface_type = interface_type; 262 263 ti->class->interfaces = g_slist_append(ti->class->interfaces, 264 iface_impl->class); 265 } 266 267 static void object_property_free(gpointer data) 268 { 269 ObjectProperty *prop = data; 270 271 g_free(prop->name); 272 g_free(prop->type); 273 g_free(prop->description); 274 g_free(prop); 275 } 276 277 static void type_initialize(TypeImpl *ti) 278 { 279 TypeImpl *parent; 280 281 if (ti->class) { 282 return; 283 } 284 285 ti->class_size = type_class_get_size(ti); 286 ti->instance_size = type_object_get_size(ti); 287 /* Any type with zero instance_size is implicitly abstract. 288 * This means interface types are all abstract. 289 */ 290 if (ti->instance_size == 0) { 291 ti->abstract = true; 292 } 293 if (type_is_ancestor(ti, type_interface)) { 294 assert(ti->instance_size == 0); 295 assert(ti->abstract); 296 assert(!ti->instance_init); 297 assert(!ti->instance_post_init); 298 assert(!ti->instance_finalize); 299 assert(!ti->num_interfaces); 300 } 301 ti->class = g_malloc0(ti->class_size); 302 303 parent = type_get_parent(ti); 304 if (parent) { 305 type_initialize(parent); 306 GSList *e; 307 int i; 308 309 g_assert(parent->class_size <= ti->class_size); 310 memcpy(ti->class, parent->class, parent->class_size); 311 ti->class->interfaces = NULL; 312 ti->class->properties = g_hash_table_new_full( 313 g_str_hash, g_str_equal, g_free, object_property_free); 314 315 for (e = parent->class->interfaces; e; e = e->next) { 316 InterfaceClass *iface = e->data; 317 ObjectClass *klass = OBJECT_CLASS(iface); 318 319 type_initialize_interface(ti, iface->interface_type, klass->type); 320 } 321 322 for (i = 0; i < ti->num_interfaces; i++) { 323 TypeImpl *t = type_get_by_name(ti->interfaces[i].typename); 324 if (!t) { 325 error_report("missing interface '%s' for object '%s'", 326 ti->interfaces[i].typename, parent->name); 327 abort(); 328 } 329 for (e = ti->class->interfaces; e; e = e->next) { 330 TypeImpl *target_type = OBJECT_CLASS(e->data)->type; 331 332 if (type_is_ancestor(target_type, t)) { 333 break; 334 } 335 } 336 337 if (e) { 338 continue; 339 } 340 341 type_initialize_interface(ti, t, t); 342 } 343 } else { 344 ti->class->properties = g_hash_table_new_full( 345 g_str_hash, g_str_equal, g_free, object_property_free); 346 } 347 348 ti->class->type = ti; 349 350 while (parent) { 351 if (parent->class_base_init) { 352 parent->class_base_init(ti->class, ti->class_data); 353 } 354 parent = type_get_parent(parent); 355 } 356 357 if (ti->class_init) { 358 ti->class_init(ti->class, ti->class_data); 359 } 360 } 361 362 static void object_init_with_type(Object *obj, TypeImpl *ti) 363 { 364 if (type_has_parent(ti)) { 365 object_init_with_type(obj, type_get_parent(ti)); 366 } 367 368 if (ti->instance_init) { 369 ti->instance_init(obj); 370 } 371 } 372 373 static void object_post_init_with_type(Object *obj, TypeImpl *ti) 374 { 375 if (ti->instance_post_init) { 376 ti->instance_post_init(obj); 377 } 378 379 if (type_has_parent(ti)) { 380 object_post_init_with_type(obj, type_get_parent(ti)); 381 } 382 } 383 384 void object_apply_global_props(Object *obj, const GPtrArray *props, Error **errp) 385 { 386 int i; 387 388 if (!props) { 389 return; 390 } 391 392 for (i = 0; i < props->len; i++) { 393 GlobalProperty *p = g_ptr_array_index(props, i); 394 Error *err = NULL; 395 396 if (object_dynamic_cast(obj, p->driver) == NULL) { 397 continue; 398 } 399 if (p->optional && !object_property_find(obj, p->property, NULL)) { 400 continue; 401 } 402 p->used = true; 403 object_property_parse(obj, p->value, p->property, &err); 404 if (err != NULL) { 405 error_prepend(&err, "can't apply global %s.%s=%s: ", 406 p->driver, p->property, p->value); 407 /* 408 * If errp != NULL, propagate error and return. 409 * If errp == NULL, report a warning, but keep going 410 * with the remaining globals. 411 */ 412 if (errp) { 413 error_propagate(errp, err); 414 return; 415 } else { 416 warn_report_err(err); 417 } 418 } 419 } 420 } 421 422 /* 423 * Global property defaults 424 * Slot 0: accelerator's global property defaults 425 * Slot 1: machine's global property defaults 426 * Slot 2: global properties from legacy command line option 427 * Each is a GPtrArray of of GlobalProperty. 428 * Applied in order, later entries override earlier ones. 429 */ 430 static GPtrArray *object_compat_props[3]; 431 432 /* 433 * Retrieve @GPtrArray for global property defined with options 434 * other than "-global". These are generally used for syntactic 435 * sugar and legacy command line options. 436 */ 437 void object_register_sugar_prop(const char *driver, const char *prop, const char *value) 438 { 439 GlobalProperty *g; 440 if (!object_compat_props[2]) { 441 object_compat_props[2] = g_ptr_array_new(); 442 } 443 g = g_new0(GlobalProperty, 1); 444 g->driver = g_strdup(driver); 445 g->property = g_strdup(prop); 446 g->value = g_strdup(value); 447 g_ptr_array_add(object_compat_props[2], g); 448 } 449 450 /* 451 * Set machine's global property defaults to @compat_props. 452 * May be called at most once. 453 */ 454 void object_set_machine_compat_props(GPtrArray *compat_props) 455 { 456 assert(!object_compat_props[1]); 457 object_compat_props[1] = compat_props; 458 } 459 460 /* 461 * Set accelerator's global property defaults to @compat_props. 462 * May be called at most once. 463 */ 464 void object_set_accelerator_compat_props(GPtrArray *compat_props) 465 { 466 assert(!object_compat_props[0]); 467 object_compat_props[0] = compat_props; 468 } 469 470 void object_apply_compat_props(Object *obj) 471 { 472 int i; 473 474 for (i = 0; i < ARRAY_SIZE(object_compat_props); i++) { 475 object_apply_global_props(obj, object_compat_props[i], 476 i == 2 ? &error_fatal : &error_abort); 477 } 478 } 479 480 static void object_initialize_with_type(void *data, size_t size, TypeImpl *type) 481 { 482 Object *obj = data; 483 484 type_initialize(type); 485 486 g_assert(type->instance_size >= sizeof(Object)); 487 g_assert(type->abstract == false); 488 g_assert(size >= type->instance_size); 489 490 memset(obj, 0, type->instance_size); 491 obj->class = type->class; 492 object_ref(obj); 493 obj->properties = g_hash_table_new_full(g_str_hash, g_str_equal, 494 NULL, object_property_free); 495 object_init_with_type(obj, type); 496 object_post_init_with_type(obj, type); 497 } 498 499 void object_initialize(void *data, size_t size, const char *typename) 500 { 501 TypeImpl *type = type_get_by_name(typename); 502 503 if (!type) { 504 error_report("missing object type '%s'", typename); 505 abort(); 506 } 507 508 object_initialize_with_type(data, size, type); 509 } 510 511 void object_initialize_child(Object *parentobj, const char *propname, 512 void *childobj, size_t size, const char *type, 513 Error **errp, ...) 514 { 515 va_list vargs; 516 517 va_start(vargs, errp); 518 object_initialize_childv(parentobj, propname, childobj, size, type, errp, 519 vargs); 520 va_end(vargs); 521 } 522 523 void object_initialize_childv(Object *parentobj, const char *propname, 524 void *childobj, size_t size, const char *type, 525 Error **errp, va_list vargs) 526 { 527 Error *local_err = NULL; 528 Object *obj; 529 UserCreatable *uc; 530 531 object_initialize(childobj, size, type); 532 obj = OBJECT(childobj); 533 534 object_set_propv(obj, &local_err, vargs); 535 if (local_err) { 536 goto out; 537 } 538 539 object_property_add_child(parentobj, propname, obj, &local_err); 540 if (local_err) { 541 goto out; 542 } 543 544 uc = (UserCreatable *)object_dynamic_cast(obj, TYPE_USER_CREATABLE); 545 if (uc) { 546 user_creatable_complete(uc, &local_err); 547 if (local_err) { 548 object_unparent(obj); 549 goto out; 550 } 551 } 552 553 /* 554 * Since object_property_add_child added a reference to the child object, 555 * we can drop the reference added by object_initialize(), so the child 556 * property will own the only reference to the object. 557 */ 558 object_unref(obj); 559 560 out: 561 if (local_err) { 562 error_propagate(errp, local_err); 563 object_unref(obj); 564 } 565 } 566 567 static inline bool object_property_is_child(ObjectProperty *prop) 568 { 569 return strstart(prop->type, "child<", NULL); 570 } 571 572 static void object_property_del_all(Object *obj) 573 { 574 ObjectProperty *prop; 575 GHashTableIter iter; 576 gpointer key, value; 577 bool released; 578 579 do { 580 released = false; 581 g_hash_table_iter_init(&iter, obj->properties); 582 while (g_hash_table_iter_next(&iter, &key, &value)) { 583 prop = value; 584 if (prop->release) { 585 prop->release(obj, prop->name, prop->opaque); 586 prop->release = NULL; 587 released = true; 588 break; 589 } 590 g_hash_table_iter_remove(&iter); 591 } 592 } while (released); 593 594 g_hash_table_unref(obj->properties); 595 } 596 597 static void object_property_del_child(Object *obj, Object *child, Error **errp) 598 { 599 ObjectProperty *prop; 600 GHashTableIter iter; 601 gpointer key, value; 602 603 g_hash_table_iter_init(&iter, obj->properties); 604 while (g_hash_table_iter_next(&iter, &key, &value)) { 605 prop = value; 606 if (object_property_is_child(prop) && prop->opaque == child) { 607 if (prop->release) { 608 prop->release(obj, prop->name, prop->opaque); 609 prop->release = NULL; 610 } 611 break; 612 } 613 } 614 g_hash_table_iter_init(&iter, obj->properties); 615 while (g_hash_table_iter_next(&iter, &key, &value)) { 616 prop = value; 617 if (object_property_is_child(prop) && prop->opaque == child) { 618 g_hash_table_iter_remove(&iter); 619 break; 620 } 621 } 622 } 623 624 void object_unparent(Object *obj) 625 { 626 if (obj->parent) { 627 object_property_del_child(obj->parent, obj, NULL); 628 } 629 } 630 631 static void object_deinit(Object *obj, TypeImpl *type) 632 { 633 if (type->instance_finalize) { 634 type->instance_finalize(obj); 635 } 636 637 if (type_has_parent(type)) { 638 object_deinit(obj, type_get_parent(type)); 639 } 640 } 641 642 static void object_finalize(void *data) 643 { 644 Object *obj = data; 645 TypeImpl *ti = obj->class->type; 646 647 object_property_del_all(obj); 648 object_deinit(obj, ti); 649 650 g_assert(obj->ref == 0); 651 if (obj->free) { 652 obj->free(obj); 653 } 654 } 655 656 static Object *object_new_with_type(Type type) 657 { 658 Object *obj; 659 660 g_assert(type != NULL); 661 type_initialize(type); 662 663 obj = g_malloc(type->instance_size); 664 object_initialize_with_type(obj, type->instance_size, type); 665 obj->free = g_free; 666 667 return obj; 668 } 669 670 Object *object_new_with_class(ObjectClass *klass) 671 { 672 return object_new_with_type(klass->type); 673 } 674 675 Object *object_new(const char *typename) 676 { 677 TypeImpl *ti = type_get_by_name(typename); 678 679 return object_new_with_type(ti); 680 } 681 682 683 Object *object_new_with_props(const char *typename, 684 Object *parent, 685 const char *id, 686 Error **errp, 687 ...) 688 { 689 va_list vargs; 690 Object *obj; 691 692 va_start(vargs, errp); 693 obj = object_new_with_propv(typename, parent, id, errp, vargs); 694 va_end(vargs); 695 696 return obj; 697 } 698 699 700 Object *object_new_with_propv(const char *typename, 701 Object *parent, 702 const char *id, 703 Error **errp, 704 va_list vargs) 705 { 706 Object *obj; 707 ObjectClass *klass; 708 Error *local_err = NULL; 709 UserCreatable *uc; 710 711 klass = object_class_by_name(typename); 712 if (!klass) { 713 error_setg(errp, "invalid object type: %s", typename); 714 return NULL; 715 } 716 717 if (object_class_is_abstract(klass)) { 718 error_setg(errp, "object type '%s' is abstract", typename); 719 return NULL; 720 } 721 obj = object_new_with_type(klass->type); 722 723 if (object_set_propv(obj, &local_err, vargs) < 0) { 724 goto error; 725 } 726 727 if (id != NULL) { 728 object_property_add_child(parent, id, obj, &local_err); 729 if (local_err) { 730 goto error; 731 } 732 } 733 734 uc = (UserCreatable *)object_dynamic_cast(obj, TYPE_USER_CREATABLE); 735 if (uc) { 736 user_creatable_complete(uc, &local_err); 737 if (local_err) { 738 if (id != NULL) { 739 object_unparent(obj); 740 } 741 goto error; 742 } 743 } 744 745 object_unref(OBJECT(obj)); 746 return obj; 747 748 error: 749 error_propagate(errp, local_err); 750 object_unref(obj); 751 return NULL; 752 } 753 754 755 int object_set_props(Object *obj, 756 Error **errp, 757 ...) 758 { 759 va_list vargs; 760 int ret; 761 762 va_start(vargs, errp); 763 ret = object_set_propv(obj, errp, vargs); 764 va_end(vargs); 765 766 return ret; 767 } 768 769 770 int object_set_propv(Object *obj, 771 Error **errp, 772 va_list vargs) 773 { 774 const char *propname; 775 Error *local_err = NULL; 776 777 propname = va_arg(vargs, char *); 778 while (propname != NULL) { 779 const char *value = va_arg(vargs, char *); 780 781 g_assert(value != NULL); 782 object_property_parse(obj, value, propname, &local_err); 783 if (local_err) { 784 error_propagate(errp, local_err); 785 return -1; 786 } 787 propname = va_arg(vargs, char *); 788 } 789 790 return 0; 791 } 792 793 794 Object *object_dynamic_cast(Object *obj, const char *typename) 795 { 796 if (obj && object_class_dynamic_cast(object_get_class(obj), typename)) { 797 return obj; 798 } 799 800 return NULL; 801 } 802 803 Object *object_dynamic_cast_assert(Object *obj, const char *typename, 804 const char *file, int line, const char *func) 805 { 806 trace_object_dynamic_cast_assert(obj ? obj->class->type->name : "(null)", 807 typename, file, line, func); 808 809 #ifdef CONFIG_QOM_CAST_DEBUG 810 int i; 811 Object *inst; 812 813 for (i = 0; obj && i < OBJECT_CLASS_CAST_CACHE; i++) { 814 if (atomic_read(&obj->class->object_cast_cache[i]) == typename) { 815 goto out; 816 } 817 } 818 819 inst = object_dynamic_cast(obj, typename); 820 821 if (!inst && obj) { 822 fprintf(stderr, "%s:%d:%s: Object %p is not an instance of type %s\n", 823 file, line, func, obj, typename); 824 abort(); 825 } 826 827 assert(obj == inst); 828 829 if (obj && obj == inst) { 830 for (i = 1; i < OBJECT_CLASS_CAST_CACHE; i++) { 831 atomic_set(&obj->class->object_cast_cache[i - 1], 832 atomic_read(&obj->class->object_cast_cache[i])); 833 } 834 atomic_set(&obj->class->object_cast_cache[i - 1], typename); 835 } 836 837 out: 838 #endif 839 return obj; 840 } 841 842 ObjectClass *object_class_dynamic_cast(ObjectClass *class, 843 const char *typename) 844 { 845 ObjectClass *ret = NULL; 846 TypeImpl *target_type; 847 TypeImpl *type; 848 849 if (!class) { 850 return NULL; 851 } 852 853 /* A simple fast path that can trigger a lot for leaf classes. */ 854 type = class->type; 855 if (type->name == typename) { 856 return class; 857 } 858 859 target_type = type_get_by_name(typename); 860 if (!target_type) { 861 /* target class type unknown, so fail the cast */ 862 return NULL; 863 } 864 865 if (type->class->interfaces && 866 type_is_ancestor(target_type, type_interface)) { 867 int found = 0; 868 GSList *i; 869 870 for (i = class->interfaces; i; i = i->next) { 871 ObjectClass *target_class = i->data; 872 873 if (type_is_ancestor(target_class->type, target_type)) { 874 ret = target_class; 875 found++; 876 } 877 } 878 879 /* The match was ambiguous, don't allow a cast */ 880 if (found > 1) { 881 ret = NULL; 882 } 883 } else if (type_is_ancestor(type, target_type)) { 884 ret = class; 885 } 886 887 return ret; 888 } 889 890 ObjectClass *object_class_dynamic_cast_assert(ObjectClass *class, 891 const char *typename, 892 const char *file, int line, 893 const char *func) 894 { 895 ObjectClass *ret; 896 897 trace_object_class_dynamic_cast_assert(class ? class->type->name : "(null)", 898 typename, file, line, func); 899 900 #ifdef CONFIG_QOM_CAST_DEBUG 901 int i; 902 903 for (i = 0; class && i < OBJECT_CLASS_CAST_CACHE; i++) { 904 if (atomic_read(&class->class_cast_cache[i]) == typename) { 905 ret = class; 906 goto out; 907 } 908 } 909 #else 910 if (!class || !class->interfaces) { 911 return class; 912 } 913 #endif 914 915 ret = object_class_dynamic_cast(class, typename); 916 if (!ret && class) { 917 fprintf(stderr, "%s:%d:%s: Object %p is not an instance of type %s\n", 918 file, line, func, class, typename); 919 abort(); 920 } 921 922 #ifdef CONFIG_QOM_CAST_DEBUG 923 if (class && ret == class) { 924 for (i = 1; i < OBJECT_CLASS_CAST_CACHE; i++) { 925 atomic_set(&class->class_cast_cache[i - 1], 926 atomic_read(&class->class_cast_cache[i])); 927 } 928 atomic_set(&class->class_cast_cache[i - 1], typename); 929 } 930 out: 931 #endif 932 return ret; 933 } 934 935 const char *object_get_typename(const Object *obj) 936 { 937 return obj->class->type->name; 938 } 939 940 ObjectClass *object_get_class(Object *obj) 941 { 942 return obj->class; 943 } 944 945 bool object_class_is_abstract(ObjectClass *klass) 946 { 947 return klass->type->abstract; 948 } 949 950 const char *object_class_get_name(ObjectClass *klass) 951 { 952 return klass->type->name; 953 } 954 955 ObjectClass *object_class_by_name(const char *typename) 956 { 957 TypeImpl *type = type_get_by_name(typename); 958 959 if (!type) { 960 return NULL; 961 } 962 963 type_initialize(type); 964 965 return type->class; 966 } 967 968 ObjectClass *object_class_get_parent(ObjectClass *class) 969 { 970 TypeImpl *type = type_get_parent(class->type); 971 972 if (!type) { 973 return NULL; 974 } 975 976 type_initialize(type); 977 978 return type->class; 979 } 980 981 typedef struct OCFData 982 { 983 void (*fn)(ObjectClass *klass, void *opaque); 984 const char *implements_type; 985 bool include_abstract; 986 void *opaque; 987 } OCFData; 988 989 static void object_class_foreach_tramp(gpointer key, gpointer value, 990 gpointer opaque) 991 { 992 OCFData *data = opaque; 993 TypeImpl *type = value; 994 ObjectClass *k; 995 996 type_initialize(type); 997 k = type->class; 998 999 if (!data->include_abstract && type->abstract) { 1000 return; 1001 } 1002 1003 if (data->implements_type && 1004 !object_class_dynamic_cast(k, data->implements_type)) { 1005 return; 1006 } 1007 1008 data->fn(k, data->opaque); 1009 } 1010 1011 void object_class_foreach(void (*fn)(ObjectClass *klass, void *opaque), 1012 const char *implements_type, bool include_abstract, 1013 void *opaque) 1014 { 1015 OCFData data = { fn, implements_type, include_abstract, opaque }; 1016 1017 enumerating_types = true; 1018 g_hash_table_foreach(type_table_get(), object_class_foreach_tramp, &data); 1019 enumerating_types = false; 1020 } 1021 1022 static int do_object_child_foreach(Object *obj, 1023 int (*fn)(Object *child, void *opaque), 1024 void *opaque, bool recurse) 1025 { 1026 GHashTableIter iter; 1027 ObjectProperty *prop; 1028 int ret = 0; 1029 1030 g_hash_table_iter_init(&iter, obj->properties); 1031 while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&prop)) { 1032 if (object_property_is_child(prop)) { 1033 Object *child = prop->opaque; 1034 1035 ret = fn(child, opaque); 1036 if (ret != 0) { 1037 break; 1038 } 1039 if (recurse) { 1040 do_object_child_foreach(child, fn, opaque, true); 1041 } 1042 } 1043 } 1044 return ret; 1045 } 1046 1047 int object_child_foreach(Object *obj, int (*fn)(Object *child, void *opaque), 1048 void *opaque) 1049 { 1050 return do_object_child_foreach(obj, fn, opaque, false); 1051 } 1052 1053 int object_child_foreach_recursive(Object *obj, 1054 int (*fn)(Object *child, void *opaque), 1055 void *opaque) 1056 { 1057 return do_object_child_foreach(obj, fn, opaque, true); 1058 } 1059 1060 static void object_class_get_list_tramp(ObjectClass *klass, void *opaque) 1061 { 1062 GSList **list = opaque; 1063 1064 *list = g_slist_prepend(*list, klass); 1065 } 1066 1067 GSList *object_class_get_list(const char *implements_type, 1068 bool include_abstract) 1069 { 1070 GSList *list = NULL; 1071 1072 object_class_foreach(object_class_get_list_tramp, 1073 implements_type, include_abstract, &list); 1074 return list; 1075 } 1076 1077 static gint object_class_cmp(gconstpointer a, gconstpointer b) 1078 { 1079 return strcasecmp(object_class_get_name((ObjectClass *)a), 1080 object_class_get_name((ObjectClass *)b)); 1081 } 1082 1083 GSList *object_class_get_list_sorted(const char *implements_type, 1084 bool include_abstract) 1085 { 1086 return g_slist_sort(object_class_get_list(implements_type, include_abstract), 1087 object_class_cmp); 1088 } 1089 1090 void object_ref(Object *obj) 1091 { 1092 if (!obj) { 1093 return; 1094 } 1095 atomic_inc(&obj->ref); 1096 } 1097 1098 void object_unref(Object *obj) 1099 { 1100 if (!obj) { 1101 return; 1102 } 1103 g_assert(obj->ref > 0); 1104 1105 /* parent always holds a reference to its children */ 1106 if (atomic_fetch_dec(&obj->ref) == 1) { 1107 object_finalize(obj); 1108 } 1109 } 1110 1111 ObjectProperty * 1112 object_property_add(Object *obj, const char *name, const char *type, 1113 ObjectPropertyAccessor *get, 1114 ObjectPropertyAccessor *set, 1115 ObjectPropertyRelease *release, 1116 void *opaque, Error **errp) 1117 { 1118 ObjectProperty *prop; 1119 size_t name_len = strlen(name); 1120 1121 if (name_len >= 3 && !memcmp(name + name_len - 3, "[*]", 4)) { 1122 int i; 1123 ObjectProperty *ret; 1124 char *name_no_array = g_strdup(name); 1125 1126 name_no_array[name_len - 3] = '\0'; 1127 for (i = 0; ; ++i) { 1128 char *full_name = g_strdup_printf("%s[%d]", name_no_array, i); 1129 1130 ret = object_property_add(obj, full_name, type, get, set, 1131 release, opaque, NULL); 1132 g_free(full_name); 1133 if (ret) { 1134 break; 1135 } 1136 } 1137 g_free(name_no_array); 1138 return ret; 1139 } 1140 1141 if (object_property_find(obj, name, NULL) != NULL) { 1142 error_setg(errp, "attempt to add duplicate property '%s' to object (type '%s')", 1143 name, object_get_typename(obj)); 1144 return NULL; 1145 } 1146 1147 prop = g_malloc0(sizeof(*prop)); 1148 1149 prop->name = g_strdup(name); 1150 prop->type = g_strdup(type); 1151 1152 prop->get = get; 1153 prop->set = set; 1154 prop->release = release; 1155 prop->opaque = opaque; 1156 1157 g_hash_table_insert(obj->properties, prop->name, prop); 1158 return prop; 1159 } 1160 1161 ObjectProperty * 1162 object_class_property_add(ObjectClass *klass, 1163 const char *name, 1164 const char *type, 1165 ObjectPropertyAccessor *get, 1166 ObjectPropertyAccessor *set, 1167 ObjectPropertyRelease *release, 1168 void *opaque, 1169 Error **errp) 1170 { 1171 ObjectProperty *prop; 1172 1173 if (object_class_property_find(klass, name, NULL) != NULL) { 1174 error_setg(errp, "attempt to add duplicate property '%s' to class (type '%s')", 1175 name, object_class_get_name(klass)); 1176 return NULL; 1177 } 1178 1179 prop = g_malloc0(sizeof(*prop)); 1180 1181 prop->name = g_strdup(name); 1182 prop->type = g_strdup(type); 1183 1184 prop->get = get; 1185 prop->set = set; 1186 prop->release = release; 1187 prop->opaque = opaque; 1188 1189 g_hash_table_insert(klass->properties, g_strdup(name), prop); 1190 1191 return prop; 1192 } 1193 1194 ObjectProperty *object_property_find(Object *obj, const char *name, 1195 Error **errp) 1196 { 1197 ObjectProperty *prop; 1198 ObjectClass *klass = object_get_class(obj); 1199 1200 prop = object_class_property_find(klass, name, NULL); 1201 if (prop) { 1202 return prop; 1203 } 1204 1205 prop = g_hash_table_lookup(obj->properties, name); 1206 if (prop) { 1207 return prop; 1208 } 1209 1210 error_setg(errp, "Property '.%s' not found", name); 1211 return NULL; 1212 } 1213 1214 void object_property_iter_init(ObjectPropertyIterator *iter, 1215 Object *obj) 1216 { 1217 g_hash_table_iter_init(&iter->iter, obj->properties); 1218 iter->nextclass = object_get_class(obj); 1219 } 1220 1221 ObjectProperty *object_property_iter_next(ObjectPropertyIterator *iter) 1222 { 1223 gpointer key, val; 1224 while (!g_hash_table_iter_next(&iter->iter, &key, &val)) { 1225 if (!iter->nextclass) { 1226 return NULL; 1227 } 1228 g_hash_table_iter_init(&iter->iter, iter->nextclass->properties); 1229 iter->nextclass = object_class_get_parent(iter->nextclass); 1230 } 1231 return val; 1232 } 1233 1234 void object_class_property_iter_init(ObjectPropertyIterator *iter, 1235 ObjectClass *klass) 1236 { 1237 g_hash_table_iter_init(&iter->iter, klass->properties); 1238 iter->nextclass = object_class_get_parent(klass); 1239 } 1240 1241 ObjectProperty *object_class_property_find(ObjectClass *klass, const char *name, 1242 Error **errp) 1243 { 1244 ObjectProperty *prop; 1245 ObjectClass *parent_klass; 1246 1247 parent_klass = object_class_get_parent(klass); 1248 if (parent_klass) { 1249 prop = object_class_property_find(parent_klass, name, NULL); 1250 if (prop) { 1251 return prop; 1252 } 1253 } 1254 1255 prop = g_hash_table_lookup(klass->properties, name); 1256 if (!prop) { 1257 error_setg(errp, "Property '.%s' not found", name); 1258 } 1259 return prop; 1260 } 1261 1262 void object_property_del(Object *obj, const char *name, Error **errp) 1263 { 1264 ObjectProperty *prop = g_hash_table_lookup(obj->properties, name); 1265 1266 if (!prop) { 1267 error_setg(errp, "Property '.%s' not found", name); 1268 return; 1269 } 1270 1271 if (prop->release) { 1272 prop->release(obj, name, prop->opaque); 1273 } 1274 g_hash_table_remove(obj->properties, name); 1275 } 1276 1277 void object_property_get(Object *obj, Visitor *v, const char *name, 1278 Error **errp) 1279 { 1280 ObjectProperty *prop = object_property_find(obj, name, errp); 1281 if (prop == NULL) { 1282 return; 1283 } 1284 1285 if (!prop->get) { 1286 error_setg(errp, QERR_PERMISSION_DENIED); 1287 } else { 1288 prop->get(obj, v, name, prop->opaque, errp); 1289 } 1290 } 1291 1292 void object_property_set(Object *obj, Visitor *v, const char *name, 1293 Error **errp) 1294 { 1295 ObjectProperty *prop = object_property_find(obj, name, errp); 1296 if (prop == NULL) { 1297 return; 1298 } 1299 1300 if (!prop->set) { 1301 error_setg(errp, QERR_PERMISSION_DENIED); 1302 } else { 1303 prop->set(obj, v, name, prop->opaque, errp); 1304 } 1305 } 1306 1307 void object_property_set_str(Object *obj, const char *value, 1308 const char *name, Error **errp) 1309 { 1310 QString *qstr = qstring_from_str(value); 1311 object_property_set_qobject(obj, QOBJECT(qstr), name, errp); 1312 1313 qobject_unref(qstr); 1314 } 1315 1316 char *object_property_get_str(Object *obj, const char *name, 1317 Error **errp) 1318 { 1319 QObject *ret = object_property_get_qobject(obj, name, errp); 1320 char *retval; 1321 1322 if (!ret) { 1323 return NULL; 1324 } 1325 1326 retval = g_strdup(qobject_get_try_str(ret)); 1327 if (!retval) { 1328 error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name, "string"); 1329 } 1330 1331 qobject_unref(ret); 1332 return retval; 1333 } 1334 1335 void object_property_set_link(Object *obj, Object *value, 1336 const char *name, Error **errp) 1337 { 1338 if (value) { 1339 gchar *path = object_get_canonical_path(value); 1340 object_property_set_str(obj, path, name, errp); 1341 g_free(path); 1342 } else { 1343 object_property_set_str(obj, "", name, errp); 1344 } 1345 } 1346 1347 Object *object_property_get_link(Object *obj, const char *name, 1348 Error **errp) 1349 { 1350 char *str = object_property_get_str(obj, name, errp); 1351 Object *target = NULL; 1352 1353 if (str && *str) { 1354 target = object_resolve_path(str, NULL); 1355 if (!target) { 1356 error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND, 1357 "Device '%s' not found", str); 1358 } 1359 } 1360 1361 g_free(str); 1362 return target; 1363 } 1364 1365 void object_property_set_bool(Object *obj, bool value, 1366 const char *name, Error **errp) 1367 { 1368 QBool *qbool = qbool_from_bool(value); 1369 object_property_set_qobject(obj, QOBJECT(qbool), name, errp); 1370 1371 qobject_unref(qbool); 1372 } 1373 1374 bool object_property_get_bool(Object *obj, const char *name, 1375 Error **errp) 1376 { 1377 QObject *ret = object_property_get_qobject(obj, name, errp); 1378 QBool *qbool; 1379 bool retval; 1380 1381 if (!ret) { 1382 return false; 1383 } 1384 qbool = qobject_to(QBool, ret); 1385 if (!qbool) { 1386 error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name, "boolean"); 1387 retval = false; 1388 } else { 1389 retval = qbool_get_bool(qbool); 1390 } 1391 1392 qobject_unref(ret); 1393 return retval; 1394 } 1395 1396 void object_property_set_int(Object *obj, int64_t value, 1397 const char *name, Error **errp) 1398 { 1399 QNum *qnum = qnum_from_int(value); 1400 object_property_set_qobject(obj, QOBJECT(qnum), name, errp); 1401 1402 qobject_unref(qnum); 1403 } 1404 1405 int64_t object_property_get_int(Object *obj, const char *name, 1406 Error **errp) 1407 { 1408 QObject *ret = object_property_get_qobject(obj, name, errp); 1409 QNum *qnum; 1410 int64_t retval; 1411 1412 if (!ret) { 1413 return -1; 1414 } 1415 1416 qnum = qobject_to(QNum, ret); 1417 if (!qnum || !qnum_get_try_int(qnum, &retval)) { 1418 error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name, "int"); 1419 retval = -1; 1420 } 1421 1422 qobject_unref(ret); 1423 return retval; 1424 } 1425 1426 void object_property_set_uint(Object *obj, uint64_t value, 1427 const char *name, Error **errp) 1428 { 1429 QNum *qnum = qnum_from_uint(value); 1430 1431 object_property_set_qobject(obj, QOBJECT(qnum), name, errp); 1432 qobject_unref(qnum); 1433 } 1434 1435 uint64_t object_property_get_uint(Object *obj, const char *name, 1436 Error **errp) 1437 { 1438 QObject *ret = object_property_get_qobject(obj, name, errp); 1439 QNum *qnum; 1440 uint64_t retval; 1441 1442 if (!ret) { 1443 return 0; 1444 } 1445 qnum = qobject_to(QNum, ret); 1446 if (!qnum || !qnum_get_try_uint(qnum, &retval)) { 1447 error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name, "uint"); 1448 retval = 0; 1449 } 1450 1451 qobject_unref(ret); 1452 return retval; 1453 } 1454 1455 typedef struct EnumProperty { 1456 const QEnumLookup *lookup; 1457 int (*get)(Object *, Error **); 1458 void (*set)(Object *, int, Error **); 1459 } EnumProperty; 1460 1461 int object_property_get_enum(Object *obj, const char *name, 1462 const char *typename, Error **errp) 1463 { 1464 Error *err = NULL; 1465 Visitor *v; 1466 char *str; 1467 int ret; 1468 ObjectProperty *prop = object_property_find(obj, name, errp); 1469 EnumProperty *enumprop; 1470 1471 if (prop == NULL) { 1472 return 0; 1473 } 1474 1475 if (!g_str_equal(prop->type, typename)) { 1476 error_setg(errp, "Property %s on %s is not '%s' enum type", 1477 name, object_class_get_name( 1478 object_get_class(obj)), typename); 1479 return 0; 1480 } 1481 1482 enumprop = prop->opaque; 1483 1484 v = string_output_visitor_new(false, &str); 1485 object_property_get(obj, v, name, &err); 1486 if (err) { 1487 error_propagate(errp, err); 1488 visit_free(v); 1489 return 0; 1490 } 1491 visit_complete(v, &str); 1492 visit_free(v); 1493 v = string_input_visitor_new(str); 1494 visit_type_enum(v, name, &ret, enumprop->lookup, errp); 1495 1496 g_free(str); 1497 visit_free(v); 1498 1499 return ret; 1500 } 1501 1502 void object_property_get_uint16List(Object *obj, const char *name, 1503 uint16List **list, Error **errp) 1504 { 1505 Error *err = NULL; 1506 Visitor *v; 1507 char *str; 1508 1509 v = string_output_visitor_new(false, &str); 1510 object_property_get(obj, v, name, &err); 1511 if (err) { 1512 error_propagate(errp, err); 1513 goto out; 1514 } 1515 visit_complete(v, &str); 1516 visit_free(v); 1517 v = string_input_visitor_new(str); 1518 visit_type_uint16List(v, NULL, list, errp); 1519 1520 g_free(str); 1521 out: 1522 visit_free(v); 1523 } 1524 1525 void object_property_parse(Object *obj, const char *string, 1526 const char *name, Error **errp) 1527 { 1528 Visitor *v = string_input_visitor_new(string); 1529 object_property_set(obj, v, name, errp); 1530 visit_free(v); 1531 } 1532 1533 char *object_property_print(Object *obj, const char *name, bool human, 1534 Error **errp) 1535 { 1536 Visitor *v; 1537 char *string = NULL; 1538 Error *local_err = NULL; 1539 1540 v = string_output_visitor_new(human, &string); 1541 object_property_get(obj, v, name, &local_err); 1542 if (local_err) { 1543 error_propagate(errp, local_err); 1544 goto out; 1545 } 1546 1547 visit_complete(v, &string); 1548 1549 out: 1550 visit_free(v); 1551 return string; 1552 } 1553 1554 const char *object_property_get_type(Object *obj, const char *name, Error **errp) 1555 { 1556 ObjectProperty *prop = object_property_find(obj, name, errp); 1557 if (prop == NULL) { 1558 return NULL; 1559 } 1560 1561 return prop->type; 1562 } 1563 1564 Object *object_get_root(void) 1565 { 1566 static Object *root; 1567 1568 if (!root) { 1569 root = object_new("container"); 1570 } 1571 1572 return root; 1573 } 1574 1575 Object *object_get_objects_root(void) 1576 { 1577 return container_get(object_get_root(), "/objects"); 1578 } 1579 1580 Object *object_get_internal_root(void) 1581 { 1582 static Object *internal_root; 1583 1584 if (!internal_root) { 1585 internal_root = object_new("container"); 1586 } 1587 1588 return internal_root; 1589 } 1590 1591 static void object_get_child_property(Object *obj, Visitor *v, 1592 const char *name, void *opaque, 1593 Error **errp) 1594 { 1595 Object *child = opaque; 1596 gchar *path; 1597 1598 path = object_get_canonical_path(child); 1599 visit_type_str(v, name, &path, errp); 1600 g_free(path); 1601 } 1602 1603 static Object *object_resolve_child_property(Object *parent, void *opaque, const gchar *part) 1604 { 1605 return opaque; 1606 } 1607 1608 static void object_finalize_child_property(Object *obj, const char *name, 1609 void *opaque) 1610 { 1611 Object *child = opaque; 1612 1613 if (child->class->unparent) { 1614 (child->class->unparent)(child); 1615 } 1616 child->parent = NULL; 1617 object_unref(child); 1618 } 1619 1620 void object_property_add_child(Object *obj, const char *name, 1621 Object *child, Error **errp) 1622 { 1623 Error *local_err = NULL; 1624 gchar *type; 1625 ObjectProperty *op; 1626 1627 if (child->parent != NULL) { 1628 error_setg(errp, "child object is already parented"); 1629 return; 1630 } 1631 1632 type = g_strdup_printf("child<%s>", object_get_typename(OBJECT(child))); 1633 1634 op = object_property_add(obj, name, type, object_get_child_property, NULL, 1635 object_finalize_child_property, child, &local_err); 1636 if (local_err) { 1637 error_propagate(errp, local_err); 1638 goto out; 1639 } 1640 1641 op->resolve = object_resolve_child_property; 1642 object_ref(child); 1643 child->parent = obj; 1644 1645 out: 1646 g_free(type); 1647 } 1648 1649 void object_property_allow_set_link(const Object *obj, const char *name, 1650 Object *val, Error **errp) 1651 { 1652 /* Allow the link to be set, always */ 1653 } 1654 1655 typedef struct { 1656 Object **child; 1657 void (*check)(const Object *, const char *, Object *, Error **); 1658 ObjectPropertyLinkFlags flags; 1659 } LinkProperty; 1660 1661 static void object_get_link_property(Object *obj, Visitor *v, 1662 const char *name, void *opaque, 1663 Error **errp) 1664 { 1665 LinkProperty *lprop = opaque; 1666 Object **child = lprop->child; 1667 gchar *path; 1668 1669 if (*child) { 1670 path = object_get_canonical_path(*child); 1671 visit_type_str(v, name, &path, errp); 1672 g_free(path); 1673 } else { 1674 path = (gchar *)""; 1675 visit_type_str(v, name, &path, errp); 1676 } 1677 } 1678 1679 /* 1680 * object_resolve_link: 1681 * 1682 * Lookup an object and ensure its type matches the link property type. This 1683 * is similar to object_resolve_path() except type verification against the 1684 * link property is performed. 1685 * 1686 * Returns: The matched object or NULL on path lookup failures. 1687 */ 1688 static Object *object_resolve_link(Object *obj, const char *name, 1689 const char *path, Error **errp) 1690 { 1691 const char *type; 1692 gchar *target_type; 1693 bool ambiguous = false; 1694 Object *target; 1695 1696 /* Go from link<FOO> to FOO. */ 1697 type = object_property_get_type(obj, name, NULL); 1698 target_type = g_strndup(&type[5], strlen(type) - 6); 1699 target = object_resolve_path_type(path, target_type, &ambiguous); 1700 1701 if (ambiguous) { 1702 error_setg(errp, "Path '%s' does not uniquely identify an object", 1703 path); 1704 } else if (!target) { 1705 target = object_resolve_path(path, &ambiguous); 1706 if (target || ambiguous) { 1707 error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name, target_type); 1708 } else { 1709 error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND, 1710 "Device '%s' not found", path); 1711 } 1712 target = NULL; 1713 } 1714 g_free(target_type); 1715 1716 return target; 1717 } 1718 1719 static void object_set_link_property(Object *obj, Visitor *v, 1720 const char *name, void *opaque, 1721 Error **errp) 1722 { 1723 Error *local_err = NULL; 1724 LinkProperty *prop = opaque; 1725 Object **child = prop->child; 1726 Object *old_target = *child; 1727 Object *new_target = NULL; 1728 char *path = NULL; 1729 1730 visit_type_str(v, name, &path, &local_err); 1731 1732 if (!local_err && strcmp(path, "") != 0) { 1733 new_target = object_resolve_link(obj, name, path, &local_err); 1734 } 1735 1736 g_free(path); 1737 if (local_err) { 1738 error_propagate(errp, local_err); 1739 return; 1740 } 1741 1742 prop->check(obj, name, new_target, &local_err); 1743 if (local_err) { 1744 error_propagate(errp, local_err); 1745 return; 1746 } 1747 1748 *child = new_target; 1749 if (prop->flags == OBJ_PROP_LINK_STRONG) { 1750 object_ref(new_target); 1751 object_unref(old_target); 1752 } 1753 } 1754 1755 static Object *object_resolve_link_property(Object *parent, void *opaque, const gchar *part) 1756 { 1757 LinkProperty *lprop = opaque; 1758 1759 return *lprop->child; 1760 } 1761 1762 static void object_release_link_property(Object *obj, const char *name, 1763 void *opaque) 1764 { 1765 LinkProperty *prop = opaque; 1766 1767 if ((prop->flags & OBJ_PROP_LINK_STRONG) && *prop->child) { 1768 object_unref(*prop->child); 1769 } 1770 g_free(prop); 1771 } 1772 1773 void object_property_add_link(Object *obj, const char *name, 1774 const char *type, Object **child, 1775 void (*check)(const Object *, const char *, 1776 Object *, Error **), 1777 ObjectPropertyLinkFlags flags, 1778 Error **errp) 1779 { 1780 Error *local_err = NULL; 1781 LinkProperty *prop = g_malloc(sizeof(*prop)); 1782 gchar *full_type; 1783 ObjectProperty *op; 1784 1785 prop->child = child; 1786 prop->check = check; 1787 prop->flags = flags; 1788 1789 full_type = g_strdup_printf("link<%s>", type); 1790 1791 op = object_property_add(obj, name, full_type, 1792 object_get_link_property, 1793 check ? object_set_link_property : NULL, 1794 object_release_link_property, 1795 prop, 1796 &local_err); 1797 if (local_err) { 1798 error_propagate(errp, local_err); 1799 g_free(prop); 1800 goto out; 1801 } 1802 1803 op->resolve = object_resolve_link_property; 1804 1805 out: 1806 g_free(full_type); 1807 } 1808 1809 void object_property_add_const_link(Object *obj, const char *name, 1810 Object *target, Error **errp) 1811 { 1812 char *link_type; 1813 ObjectProperty *op; 1814 1815 link_type = g_strdup_printf("link<%s>", object_get_typename(target)); 1816 op = object_property_add(obj, name, link_type, 1817 object_get_child_property, NULL, 1818 NULL, target, errp); 1819 if (op != NULL) { 1820 op->resolve = object_resolve_child_property; 1821 } 1822 g_free(link_type); 1823 } 1824 1825 gchar *object_get_canonical_path_component(Object *obj) 1826 { 1827 ObjectProperty *prop = NULL; 1828 GHashTableIter iter; 1829 1830 if (obj->parent == NULL) { 1831 return NULL; 1832 } 1833 1834 g_hash_table_iter_init(&iter, obj->parent->properties); 1835 while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&prop)) { 1836 if (!object_property_is_child(prop)) { 1837 continue; 1838 } 1839 1840 if (prop->opaque == obj) { 1841 return g_strdup(prop->name); 1842 } 1843 } 1844 1845 /* obj had a parent but was not a child, should never happen */ 1846 g_assert_not_reached(); 1847 return NULL; 1848 } 1849 1850 gchar *object_get_canonical_path(Object *obj) 1851 { 1852 Object *root = object_get_root(); 1853 char *newpath, *path = NULL; 1854 1855 if (obj == root) { 1856 return g_strdup("/"); 1857 } 1858 1859 do { 1860 char *component = object_get_canonical_path_component(obj); 1861 1862 if (!component) { 1863 /* A canonical path must be complete, so discard what was 1864 * collected so far. 1865 */ 1866 g_free(path); 1867 return NULL; 1868 } 1869 1870 newpath = g_strdup_printf("/%s%s", component, path ? path : ""); 1871 g_free(path); 1872 g_free(component); 1873 path = newpath; 1874 obj = obj->parent; 1875 } while (obj != root); 1876 1877 return path; 1878 } 1879 1880 Object *object_resolve_path_component(Object *parent, const gchar *part) 1881 { 1882 ObjectProperty *prop = object_property_find(parent, part, NULL); 1883 if (prop == NULL) { 1884 return NULL; 1885 } 1886 1887 if (prop->resolve) { 1888 return prop->resolve(parent, prop->opaque, part); 1889 } else { 1890 return NULL; 1891 } 1892 } 1893 1894 static Object *object_resolve_abs_path(Object *parent, 1895 gchar **parts, 1896 const char *typename, 1897 int index) 1898 { 1899 Object *child; 1900 1901 if (parts[index] == NULL) { 1902 return object_dynamic_cast(parent, typename); 1903 } 1904 1905 if (strcmp(parts[index], "") == 0) { 1906 return object_resolve_abs_path(parent, parts, typename, index + 1); 1907 } 1908 1909 child = object_resolve_path_component(parent, parts[index]); 1910 if (!child) { 1911 return NULL; 1912 } 1913 1914 return object_resolve_abs_path(child, parts, typename, index + 1); 1915 } 1916 1917 static Object *object_resolve_partial_path(Object *parent, 1918 gchar **parts, 1919 const char *typename, 1920 bool *ambiguous) 1921 { 1922 Object *obj; 1923 GHashTableIter iter; 1924 ObjectProperty *prop; 1925 1926 obj = object_resolve_abs_path(parent, parts, typename, 0); 1927 1928 g_hash_table_iter_init(&iter, parent->properties); 1929 while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&prop)) { 1930 Object *found; 1931 1932 if (!object_property_is_child(prop)) { 1933 continue; 1934 } 1935 1936 found = object_resolve_partial_path(prop->opaque, parts, 1937 typename, ambiguous); 1938 if (found) { 1939 if (obj) { 1940 *ambiguous = true; 1941 return NULL; 1942 } 1943 obj = found; 1944 } 1945 1946 if (*ambiguous) { 1947 return NULL; 1948 } 1949 } 1950 1951 return obj; 1952 } 1953 1954 Object *object_resolve_path_type(const char *path, const char *typename, 1955 bool *ambiguousp) 1956 { 1957 Object *obj; 1958 gchar **parts; 1959 1960 parts = g_strsplit(path, "/", 0); 1961 assert(parts); 1962 1963 if (parts[0] == NULL || strcmp(parts[0], "") != 0) { 1964 bool ambiguous = false; 1965 obj = object_resolve_partial_path(object_get_root(), parts, 1966 typename, &ambiguous); 1967 if (ambiguousp) { 1968 *ambiguousp = ambiguous; 1969 } 1970 } else { 1971 obj = object_resolve_abs_path(object_get_root(), parts, typename, 1); 1972 } 1973 1974 g_strfreev(parts); 1975 1976 return obj; 1977 } 1978 1979 Object *object_resolve_path(const char *path, bool *ambiguous) 1980 { 1981 return object_resolve_path_type(path, TYPE_OBJECT, ambiguous); 1982 } 1983 1984 typedef struct StringProperty 1985 { 1986 char *(*get)(Object *, Error **); 1987 void (*set)(Object *, const char *, Error **); 1988 } StringProperty; 1989 1990 static void property_get_str(Object *obj, Visitor *v, const char *name, 1991 void *opaque, Error **errp) 1992 { 1993 StringProperty *prop = opaque; 1994 char *value; 1995 Error *err = NULL; 1996 1997 value = prop->get(obj, &err); 1998 if (err) { 1999 error_propagate(errp, err); 2000 return; 2001 } 2002 2003 visit_type_str(v, name, &value, errp); 2004 g_free(value); 2005 } 2006 2007 static void property_set_str(Object *obj, Visitor *v, const char *name, 2008 void *opaque, Error **errp) 2009 { 2010 StringProperty *prop = opaque; 2011 char *value; 2012 Error *local_err = NULL; 2013 2014 visit_type_str(v, name, &value, &local_err); 2015 if (local_err) { 2016 error_propagate(errp, local_err); 2017 return; 2018 } 2019 2020 prop->set(obj, value, errp); 2021 g_free(value); 2022 } 2023 2024 static void property_release_str(Object *obj, const char *name, 2025 void *opaque) 2026 { 2027 StringProperty *prop = opaque; 2028 g_free(prop); 2029 } 2030 2031 void object_property_add_str(Object *obj, const char *name, 2032 char *(*get)(Object *, Error **), 2033 void (*set)(Object *, const char *, Error **), 2034 Error **errp) 2035 { 2036 Error *local_err = NULL; 2037 StringProperty *prop = g_malloc0(sizeof(*prop)); 2038 2039 prop->get = get; 2040 prop->set = set; 2041 2042 object_property_add(obj, name, "string", 2043 get ? property_get_str : NULL, 2044 set ? property_set_str : NULL, 2045 property_release_str, 2046 prop, &local_err); 2047 if (local_err) { 2048 error_propagate(errp, local_err); 2049 g_free(prop); 2050 } 2051 } 2052 2053 void object_class_property_add_str(ObjectClass *klass, const char *name, 2054 char *(*get)(Object *, Error **), 2055 void (*set)(Object *, const char *, 2056 Error **), 2057 Error **errp) 2058 { 2059 Error *local_err = NULL; 2060 StringProperty *prop = g_malloc0(sizeof(*prop)); 2061 2062 prop->get = get; 2063 prop->set = set; 2064 2065 object_class_property_add(klass, name, "string", 2066 get ? property_get_str : NULL, 2067 set ? property_set_str : NULL, 2068 property_release_str, 2069 prop, &local_err); 2070 if (local_err) { 2071 error_propagate(errp, local_err); 2072 g_free(prop); 2073 } 2074 } 2075 2076 typedef struct BoolProperty 2077 { 2078 bool (*get)(Object *, Error **); 2079 void (*set)(Object *, bool, Error **); 2080 } BoolProperty; 2081 2082 static void property_get_bool(Object *obj, Visitor *v, const char *name, 2083 void *opaque, Error **errp) 2084 { 2085 BoolProperty *prop = opaque; 2086 bool value; 2087 Error *err = NULL; 2088 2089 value = prop->get(obj, &err); 2090 if (err) { 2091 error_propagate(errp, err); 2092 return; 2093 } 2094 2095 visit_type_bool(v, name, &value, errp); 2096 } 2097 2098 static void property_set_bool(Object *obj, Visitor *v, const char *name, 2099 void *opaque, Error **errp) 2100 { 2101 BoolProperty *prop = opaque; 2102 bool value; 2103 Error *local_err = NULL; 2104 2105 visit_type_bool(v, name, &value, &local_err); 2106 if (local_err) { 2107 error_propagate(errp, local_err); 2108 return; 2109 } 2110 2111 prop->set(obj, value, errp); 2112 } 2113 2114 static void property_release_bool(Object *obj, const char *name, 2115 void *opaque) 2116 { 2117 BoolProperty *prop = opaque; 2118 g_free(prop); 2119 } 2120 2121 void object_property_add_bool(Object *obj, const char *name, 2122 bool (*get)(Object *, Error **), 2123 void (*set)(Object *, bool, Error **), 2124 Error **errp) 2125 { 2126 Error *local_err = NULL; 2127 BoolProperty *prop = g_malloc0(sizeof(*prop)); 2128 2129 prop->get = get; 2130 prop->set = set; 2131 2132 object_property_add(obj, name, "bool", 2133 get ? property_get_bool : NULL, 2134 set ? property_set_bool : NULL, 2135 property_release_bool, 2136 prop, &local_err); 2137 if (local_err) { 2138 error_propagate(errp, local_err); 2139 g_free(prop); 2140 } 2141 } 2142 2143 void object_class_property_add_bool(ObjectClass *klass, const char *name, 2144 bool (*get)(Object *, Error **), 2145 void (*set)(Object *, bool, Error **), 2146 Error **errp) 2147 { 2148 Error *local_err = NULL; 2149 BoolProperty *prop = g_malloc0(sizeof(*prop)); 2150 2151 prop->get = get; 2152 prop->set = set; 2153 2154 object_class_property_add(klass, name, "bool", 2155 get ? property_get_bool : NULL, 2156 set ? property_set_bool : NULL, 2157 property_release_bool, 2158 prop, &local_err); 2159 if (local_err) { 2160 error_propagate(errp, local_err); 2161 g_free(prop); 2162 } 2163 } 2164 2165 static void property_get_enum(Object *obj, Visitor *v, const char *name, 2166 void *opaque, Error **errp) 2167 { 2168 EnumProperty *prop = opaque; 2169 int value; 2170 Error *err = NULL; 2171 2172 value = prop->get(obj, &err); 2173 if (err) { 2174 error_propagate(errp, err); 2175 return; 2176 } 2177 2178 visit_type_enum(v, name, &value, prop->lookup, errp); 2179 } 2180 2181 static void property_set_enum(Object *obj, Visitor *v, const char *name, 2182 void *opaque, Error **errp) 2183 { 2184 EnumProperty *prop = opaque; 2185 int value; 2186 Error *err = NULL; 2187 2188 visit_type_enum(v, name, &value, prop->lookup, &err); 2189 if (err) { 2190 error_propagate(errp, err); 2191 return; 2192 } 2193 prop->set(obj, value, errp); 2194 } 2195 2196 static void property_release_enum(Object *obj, const char *name, 2197 void *opaque) 2198 { 2199 EnumProperty *prop = opaque; 2200 g_free(prop); 2201 } 2202 2203 void object_property_add_enum(Object *obj, const char *name, 2204 const char *typename, 2205 const QEnumLookup *lookup, 2206 int (*get)(Object *, Error **), 2207 void (*set)(Object *, int, Error **), 2208 Error **errp) 2209 { 2210 Error *local_err = NULL; 2211 EnumProperty *prop = g_malloc(sizeof(*prop)); 2212 2213 prop->lookup = lookup; 2214 prop->get = get; 2215 prop->set = set; 2216 2217 object_property_add(obj, name, typename, 2218 get ? property_get_enum : NULL, 2219 set ? property_set_enum : NULL, 2220 property_release_enum, 2221 prop, &local_err); 2222 if (local_err) { 2223 error_propagate(errp, local_err); 2224 g_free(prop); 2225 } 2226 } 2227 2228 void object_class_property_add_enum(ObjectClass *klass, const char *name, 2229 const char *typename, 2230 const QEnumLookup *lookup, 2231 int (*get)(Object *, Error **), 2232 void (*set)(Object *, int, Error **), 2233 Error **errp) 2234 { 2235 Error *local_err = NULL; 2236 EnumProperty *prop = g_malloc(sizeof(*prop)); 2237 2238 prop->lookup = lookup; 2239 prop->get = get; 2240 prop->set = set; 2241 2242 object_class_property_add(klass, name, typename, 2243 get ? property_get_enum : NULL, 2244 set ? property_set_enum : NULL, 2245 property_release_enum, 2246 prop, &local_err); 2247 if (local_err) { 2248 error_propagate(errp, local_err); 2249 g_free(prop); 2250 } 2251 } 2252 2253 typedef struct TMProperty { 2254 void (*get)(Object *, struct tm *, Error **); 2255 } TMProperty; 2256 2257 static void property_get_tm(Object *obj, Visitor *v, const char *name, 2258 void *opaque, Error **errp) 2259 { 2260 TMProperty *prop = opaque; 2261 Error *err = NULL; 2262 struct tm value; 2263 2264 prop->get(obj, &value, &err); 2265 if (err) { 2266 goto out; 2267 } 2268 2269 visit_start_struct(v, name, NULL, 0, &err); 2270 if (err) { 2271 goto out; 2272 } 2273 visit_type_int32(v, "tm_year", &value.tm_year, &err); 2274 if (err) { 2275 goto out_end; 2276 } 2277 visit_type_int32(v, "tm_mon", &value.tm_mon, &err); 2278 if (err) { 2279 goto out_end; 2280 } 2281 visit_type_int32(v, "tm_mday", &value.tm_mday, &err); 2282 if (err) { 2283 goto out_end; 2284 } 2285 visit_type_int32(v, "tm_hour", &value.tm_hour, &err); 2286 if (err) { 2287 goto out_end; 2288 } 2289 visit_type_int32(v, "tm_min", &value.tm_min, &err); 2290 if (err) { 2291 goto out_end; 2292 } 2293 visit_type_int32(v, "tm_sec", &value.tm_sec, &err); 2294 if (err) { 2295 goto out_end; 2296 } 2297 visit_check_struct(v, &err); 2298 out_end: 2299 visit_end_struct(v, NULL); 2300 out: 2301 error_propagate(errp, err); 2302 2303 } 2304 2305 static void property_release_tm(Object *obj, const char *name, 2306 void *opaque) 2307 { 2308 TMProperty *prop = opaque; 2309 g_free(prop); 2310 } 2311 2312 void object_property_add_tm(Object *obj, const char *name, 2313 void (*get)(Object *, struct tm *, Error **), 2314 Error **errp) 2315 { 2316 Error *local_err = NULL; 2317 TMProperty *prop = g_malloc0(sizeof(*prop)); 2318 2319 prop->get = get; 2320 2321 object_property_add(obj, name, "struct tm", 2322 get ? property_get_tm : NULL, NULL, 2323 property_release_tm, 2324 prop, &local_err); 2325 if (local_err) { 2326 error_propagate(errp, local_err); 2327 g_free(prop); 2328 } 2329 } 2330 2331 void object_class_property_add_tm(ObjectClass *klass, const char *name, 2332 void (*get)(Object *, struct tm *, Error **), 2333 Error **errp) 2334 { 2335 Error *local_err = NULL; 2336 TMProperty *prop = g_malloc0(sizeof(*prop)); 2337 2338 prop->get = get; 2339 2340 object_class_property_add(klass, name, "struct tm", 2341 get ? property_get_tm : NULL, NULL, 2342 property_release_tm, 2343 prop, &local_err); 2344 if (local_err) { 2345 error_propagate(errp, local_err); 2346 g_free(prop); 2347 } 2348 } 2349 2350 static char *qdev_get_type(Object *obj, Error **errp) 2351 { 2352 return g_strdup(object_get_typename(obj)); 2353 } 2354 2355 static void property_get_uint8_ptr(Object *obj, Visitor *v, const char *name, 2356 void *opaque, Error **errp) 2357 { 2358 uint8_t value = *(uint8_t *)opaque; 2359 visit_type_uint8(v, name, &value, errp); 2360 } 2361 2362 static void property_get_uint16_ptr(Object *obj, Visitor *v, const char *name, 2363 void *opaque, Error **errp) 2364 { 2365 uint16_t value = *(uint16_t *)opaque; 2366 visit_type_uint16(v, name, &value, errp); 2367 } 2368 2369 static void property_get_uint32_ptr(Object *obj, Visitor *v, const char *name, 2370 void *opaque, Error **errp) 2371 { 2372 uint32_t value = *(uint32_t *)opaque; 2373 visit_type_uint32(v, name, &value, errp); 2374 } 2375 2376 static void property_get_uint64_ptr(Object *obj, Visitor *v, const char *name, 2377 void *opaque, Error **errp) 2378 { 2379 uint64_t value = *(uint64_t *)opaque; 2380 visit_type_uint64(v, name, &value, errp); 2381 } 2382 2383 void object_property_add_uint8_ptr(Object *obj, const char *name, 2384 const uint8_t *v, Error **errp) 2385 { 2386 object_property_add(obj, name, "uint8", property_get_uint8_ptr, 2387 NULL, NULL, (void *)v, errp); 2388 } 2389 2390 void object_class_property_add_uint8_ptr(ObjectClass *klass, const char *name, 2391 const uint8_t *v, Error **errp) 2392 { 2393 object_class_property_add(klass, name, "uint8", property_get_uint8_ptr, 2394 NULL, NULL, (void *)v, errp); 2395 } 2396 2397 void object_property_add_uint16_ptr(Object *obj, const char *name, 2398 const uint16_t *v, Error **errp) 2399 { 2400 object_property_add(obj, name, "uint16", property_get_uint16_ptr, 2401 NULL, NULL, (void *)v, errp); 2402 } 2403 2404 void object_class_property_add_uint16_ptr(ObjectClass *klass, const char *name, 2405 const uint16_t *v, Error **errp) 2406 { 2407 object_class_property_add(klass, name, "uint16", property_get_uint16_ptr, 2408 NULL, NULL, (void *)v, errp); 2409 } 2410 2411 void object_property_add_uint32_ptr(Object *obj, const char *name, 2412 const uint32_t *v, Error **errp) 2413 { 2414 object_property_add(obj, name, "uint32", property_get_uint32_ptr, 2415 NULL, NULL, (void *)v, errp); 2416 } 2417 2418 void object_class_property_add_uint32_ptr(ObjectClass *klass, const char *name, 2419 const uint32_t *v, Error **errp) 2420 { 2421 object_class_property_add(klass, name, "uint32", property_get_uint32_ptr, 2422 NULL, NULL, (void *)v, errp); 2423 } 2424 2425 void object_property_add_uint64_ptr(Object *obj, const char *name, 2426 const uint64_t *v, Error **errp) 2427 { 2428 object_property_add(obj, name, "uint64", property_get_uint64_ptr, 2429 NULL, NULL, (void *)v, errp); 2430 } 2431 2432 void object_class_property_add_uint64_ptr(ObjectClass *klass, const char *name, 2433 const uint64_t *v, Error **errp) 2434 { 2435 object_class_property_add(klass, name, "uint64", property_get_uint64_ptr, 2436 NULL, NULL, (void *)v, errp); 2437 } 2438 2439 typedef struct { 2440 Object *target_obj; 2441 char *target_name; 2442 } AliasProperty; 2443 2444 static void property_get_alias(Object *obj, Visitor *v, const char *name, 2445 void *opaque, Error **errp) 2446 { 2447 AliasProperty *prop = opaque; 2448 2449 object_property_get(prop->target_obj, v, prop->target_name, errp); 2450 } 2451 2452 static void property_set_alias(Object *obj, Visitor *v, const char *name, 2453 void *opaque, Error **errp) 2454 { 2455 AliasProperty *prop = opaque; 2456 2457 object_property_set(prop->target_obj, v, prop->target_name, errp); 2458 } 2459 2460 static Object *property_resolve_alias(Object *obj, void *opaque, 2461 const gchar *part) 2462 { 2463 AliasProperty *prop = opaque; 2464 2465 return object_resolve_path_component(prop->target_obj, prop->target_name); 2466 } 2467 2468 static void property_release_alias(Object *obj, const char *name, void *opaque) 2469 { 2470 AliasProperty *prop = opaque; 2471 2472 g_free(prop->target_name); 2473 g_free(prop); 2474 } 2475 2476 void object_property_add_alias(Object *obj, const char *name, 2477 Object *target_obj, const char *target_name, 2478 Error **errp) 2479 { 2480 AliasProperty *prop; 2481 ObjectProperty *op; 2482 ObjectProperty *target_prop; 2483 gchar *prop_type; 2484 Error *local_err = NULL; 2485 2486 target_prop = object_property_find(target_obj, target_name, errp); 2487 if (!target_prop) { 2488 return; 2489 } 2490 2491 if (object_property_is_child(target_prop)) { 2492 prop_type = g_strdup_printf("link%s", 2493 target_prop->type + strlen("child")); 2494 } else { 2495 prop_type = g_strdup(target_prop->type); 2496 } 2497 2498 prop = g_malloc(sizeof(*prop)); 2499 prop->target_obj = target_obj; 2500 prop->target_name = g_strdup(target_name); 2501 2502 op = object_property_add(obj, name, prop_type, 2503 property_get_alias, 2504 property_set_alias, 2505 property_release_alias, 2506 prop, &local_err); 2507 if (local_err) { 2508 error_propagate(errp, local_err); 2509 g_free(prop); 2510 goto out; 2511 } 2512 op->resolve = property_resolve_alias; 2513 2514 object_property_set_description(obj, op->name, 2515 target_prop->description, 2516 &error_abort); 2517 2518 out: 2519 g_free(prop_type); 2520 } 2521 2522 void object_property_set_description(Object *obj, const char *name, 2523 const char *description, Error **errp) 2524 { 2525 ObjectProperty *op; 2526 2527 op = object_property_find(obj, name, errp); 2528 if (!op) { 2529 return; 2530 } 2531 2532 g_free(op->description); 2533 op->description = g_strdup(description); 2534 } 2535 2536 void object_class_property_set_description(ObjectClass *klass, 2537 const char *name, 2538 const char *description, 2539 Error **errp) 2540 { 2541 ObjectProperty *op; 2542 2543 op = g_hash_table_lookup(klass->properties, name); 2544 if (!op) { 2545 error_setg(errp, "Property '.%s' not found", name); 2546 return; 2547 } 2548 2549 g_free(op->description); 2550 op->description = g_strdup(description); 2551 } 2552 2553 static void object_class_init(ObjectClass *klass, void *data) 2554 { 2555 object_class_property_add_str(klass, "type", qdev_get_type, 2556 NULL, &error_abort); 2557 } 2558 2559 static void register_types(void) 2560 { 2561 static TypeInfo interface_info = { 2562 .name = TYPE_INTERFACE, 2563 .class_size = sizeof(InterfaceClass), 2564 .abstract = true, 2565 }; 2566 2567 static TypeInfo object_info = { 2568 .name = TYPE_OBJECT, 2569 .instance_size = sizeof(Object), 2570 .class_init = object_class_init, 2571 .abstract = true, 2572 }; 2573 2574 type_interface = type_register_internal(&interface_info); 2575 type_register_internal(&object_info); 2576 } 2577 2578 type_init(register_types) 2579