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