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