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/object.h" 14 #include "qemu-common.h" 15 #include "qapi/qapi-visit-core.h" 16 17 #define MAX_INTERFACES 32 18 19 typedef struct InterfaceImpl InterfaceImpl; 20 typedef struct TypeImpl TypeImpl; 21 22 struct InterfaceImpl 23 { 24 const char *parent; 25 void (*interface_initfn)(ObjectClass *class, void *data); 26 TypeImpl *type; 27 }; 28 29 struct TypeImpl 30 { 31 const char *name; 32 33 size_t class_size; 34 35 size_t instance_size; 36 37 void (*class_init)(ObjectClass *klass, void *data); 38 void (*class_finalize)(ObjectClass *klass, void *data); 39 40 void *class_data; 41 42 void (*instance_init)(Object *obj); 43 void (*instance_finalize)(Object *obj); 44 45 bool abstract; 46 47 const char *parent; 48 TypeImpl *parent_type; 49 50 ObjectClass *class; 51 52 int num_interfaces; 53 InterfaceImpl interfaces[MAX_INTERFACES]; 54 }; 55 56 typedef struct Interface 57 { 58 Object parent; 59 Object *obj; 60 } Interface; 61 62 #define INTERFACE(obj) OBJECT_CHECK(Interface, obj, TYPE_INTERFACE) 63 64 static Type type_interface; 65 66 static GHashTable *type_table_get(void) 67 { 68 static GHashTable *type_table; 69 70 if (type_table == NULL) { 71 type_table = g_hash_table_new(g_str_hash, g_str_equal); 72 } 73 74 return type_table; 75 } 76 77 static void type_table_add(TypeImpl *ti) 78 { 79 g_hash_table_insert(type_table_get(), (void *)ti->name, ti); 80 } 81 82 static TypeImpl *type_table_lookup(const char *name) 83 { 84 return g_hash_table_lookup(type_table_get(), name); 85 } 86 87 TypeImpl *type_register(const TypeInfo *info) 88 { 89 TypeImpl *ti = g_malloc0(sizeof(*ti)); 90 91 g_assert(info->name != NULL); 92 93 if (type_table_lookup(info->name) != NULL) { 94 fprintf(stderr, "Registering `%s' which already exists\n", info->name); 95 abort(); 96 } 97 98 ti->name = g_strdup(info->name); 99 ti->parent = g_strdup(info->parent); 100 101 ti->class_size = info->class_size; 102 ti->instance_size = info->instance_size; 103 104 ti->class_init = info->class_init; 105 ti->class_finalize = info->class_finalize; 106 ti->class_data = info->class_data; 107 108 ti->instance_init = info->instance_init; 109 ti->instance_finalize = info->instance_finalize; 110 111 ti->abstract = info->abstract; 112 113 if (info->interfaces) { 114 int i; 115 116 for (i = 0; info->interfaces[i].type; i++) { 117 ti->interfaces[i].parent = info->interfaces[i].type; 118 ti->interfaces[i].interface_initfn = info->interfaces[i].interface_initfn; 119 ti->num_interfaces++; 120 } 121 } 122 123 type_table_add(ti); 124 125 return ti; 126 } 127 128 TypeImpl *type_register_static(const TypeInfo *info) 129 { 130 return type_register(info); 131 } 132 133 static TypeImpl *type_get_by_name(const char *name) 134 { 135 if (name == NULL) { 136 return NULL; 137 } 138 139 return type_table_lookup(name); 140 } 141 142 static TypeImpl *type_get_parent(TypeImpl *type) 143 { 144 if (!type->parent_type && type->parent) { 145 type->parent_type = type_get_by_name(type->parent); 146 g_assert(type->parent_type != NULL); 147 } 148 149 return type->parent_type; 150 } 151 152 static bool type_has_parent(TypeImpl *type) 153 { 154 return (type->parent != NULL); 155 } 156 157 static size_t type_class_get_size(TypeImpl *ti) 158 { 159 if (ti->class_size) { 160 return ti->class_size; 161 } 162 163 if (type_has_parent(ti)) { 164 return type_class_get_size(type_get_parent(ti)); 165 } 166 167 return sizeof(ObjectClass); 168 } 169 170 static void type_class_interface_init(TypeImpl *ti, InterfaceImpl *iface) 171 { 172 TypeInfo info = { 173 .instance_size = sizeof(Interface), 174 .parent = iface->parent, 175 .class_size = sizeof(InterfaceClass), 176 .class_init = iface->interface_initfn, 177 .abstract = true, 178 }; 179 char *name = g_strdup_printf("<%s::%s>", ti->name, iface->parent); 180 181 info.name = name; 182 iface->type = type_register(&info); 183 g_free(name); 184 } 185 186 static void type_class_init(TypeImpl *ti) 187 { 188 size_t class_size = sizeof(ObjectClass); 189 int i; 190 191 if (ti->class) { 192 return; 193 } 194 195 ti->class_size = type_class_get_size(ti); 196 197 ti->class = g_malloc0(ti->class_size); 198 ti->class->type = ti; 199 200 if (type_has_parent(ti)) { 201 TypeImpl *parent = type_get_parent(ti); 202 203 type_class_init(parent); 204 205 class_size = parent->class_size; 206 g_assert(parent->class_size <= ti->class_size); 207 208 memcpy((void *)ti->class + sizeof(ObjectClass), 209 (void *)parent->class + sizeof(ObjectClass), 210 parent->class_size - sizeof(ObjectClass)); 211 } 212 213 memset((void *)ti->class + class_size, 0, ti->class_size - class_size); 214 215 for (i = 0; i < ti->num_interfaces; i++) { 216 type_class_interface_init(ti, &ti->interfaces[i]); 217 } 218 219 if (ti->class_init) { 220 ti->class_init(ti->class, ti->class_data); 221 } 222 } 223 224 static void object_interface_init(Object *obj, InterfaceImpl *iface) 225 { 226 TypeImpl *ti = iface->type; 227 Interface *iface_obj; 228 229 iface_obj = INTERFACE(object_new(ti->name)); 230 iface_obj->obj = obj; 231 232 obj->interfaces = g_slist_prepend(obj->interfaces, iface_obj); 233 } 234 235 static void object_init_with_type(Object *obj, TypeImpl *ti) 236 { 237 int i; 238 239 if (type_has_parent(ti)) { 240 object_init_with_type(obj, type_get_parent(ti)); 241 } 242 243 for (i = 0; i < ti->num_interfaces; i++) { 244 object_interface_init(obj, &ti->interfaces[i]); 245 } 246 247 if (ti->instance_init) { 248 ti->instance_init(obj); 249 } 250 } 251 252 void object_initialize_with_type(void *data, TypeImpl *type) 253 { 254 Object *obj = data; 255 256 g_assert(type != NULL); 257 g_assert(type->instance_size >= sizeof(ObjectClass)); 258 259 type_class_init(type); 260 g_assert(type->abstract == false); 261 262 memset(obj, 0, type->instance_size); 263 obj->class = type->class; 264 QTAILQ_INIT(&obj->properties); 265 object_init_with_type(obj, type); 266 } 267 268 void object_initialize(void *data, const char *typename) 269 { 270 TypeImpl *type = type_get_by_name(typename); 271 272 object_initialize_with_type(data, type); 273 } 274 275 static void object_property_del_all(Object *obj) 276 { 277 while (!QTAILQ_EMPTY(&obj->properties)) { 278 ObjectProperty *prop = QTAILQ_FIRST(&obj->properties); 279 280 QTAILQ_REMOVE(&obj->properties, prop, node); 281 282 if (prop->release) { 283 prop->release(obj, prop->name, prop->opaque); 284 } 285 286 g_free(prop->name); 287 g_free(prop->type); 288 g_free(prop); 289 } 290 } 291 292 static void object_property_del_child(Object *obj, Object *child, Error **errp) 293 { 294 ObjectProperty *prop; 295 296 QTAILQ_FOREACH(prop, &obj->properties, node) { 297 if (!strstart(prop->type, "child<", NULL)) { 298 continue; 299 } 300 301 if (prop->opaque == child) { 302 object_property_del(obj, prop->name, errp); 303 } 304 } 305 } 306 307 void object_unparent(Object *obj) 308 { 309 if (obj->parent) { 310 object_property_del_child(obj->parent, obj, NULL); 311 } 312 } 313 314 static void object_deinit(Object *obj, TypeImpl *type) 315 { 316 if (type->instance_finalize) { 317 type->instance_finalize(obj); 318 } 319 320 while (obj->interfaces) { 321 Interface *iface_obj = obj->interfaces->data; 322 obj->interfaces = g_slist_delete_link(obj->interfaces, obj->interfaces); 323 object_delete(OBJECT(iface_obj)); 324 } 325 326 if (type_has_parent(type)) { 327 object_deinit(obj, type_get_parent(type)); 328 } 329 330 object_unparent(obj); 331 } 332 333 void object_finalize(void *data) 334 { 335 Object *obj = data; 336 TypeImpl *ti = obj->class->type; 337 338 object_deinit(obj, ti); 339 object_property_del_all(obj); 340 341 g_assert(obj->ref == 0); 342 } 343 344 Object *object_new_with_type(Type type) 345 { 346 Object *obj; 347 348 g_assert(type != NULL); 349 350 obj = g_malloc(type->instance_size); 351 object_initialize_with_type(obj, type); 352 object_ref(obj); 353 354 return obj; 355 } 356 357 Object *object_new(const char *typename) 358 { 359 TypeImpl *ti = type_get_by_name(typename); 360 361 return object_new_with_type(ti); 362 } 363 364 void object_delete(Object *obj) 365 { 366 object_unref(obj); 367 g_assert(obj->ref == 0); 368 g_free(obj); 369 } 370 371 static bool type_is_ancestor(TypeImpl *type, TypeImpl *target_type) 372 { 373 assert(target_type); 374 375 /* Check if typename is a direct ancestor of type */ 376 while (type) { 377 if (type == target_type) { 378 return true; 379 } 380 381 type = type_get_parent(type); 382 } 383 384 return false; 385 } 386 387 static bool object_is_type(Object *obj, TypeImpl *target_type) 388 { 389 return !target_type || type_is_ancestor(obj->class->type, target_type); 390 } 391 392 Object *object_dynamic_cast(Object *obj, const char *typename) 393 { 394 TypeImpl *target_type = type_get_by_name(typename); 395 GSList *i; 396 397 /* Check if typename is a direct ancestor. Special-case TYPE_OBJECT, 398 * we want to go back from interfaces to the parent. 399 */ 400 if (target_type && object_is_type(obj, target_type)) { 401 return obj; 402 } 403 404 /* Check if obj is an interface and its containing object is a direct 405 * ancestor of typename. In principle we could do this test at the very 406 * beginning of object_dynamic_cast, avoiding a second call to 407 * object_is_type. However, casting between interfaces is relatively 408 * rare, and object_is_type(obj, type_interface) would fail almost always. 409 * 410 * Perhaps we could add a magic value to the object header for increased 411 * (run-time) type safety and to speed up tests like this one. If we ever 412 * do that we can revisit the order here. 413 */ 414 if (object_is_type(obj, type_interface)) { 415 assert(!obj->interfaces); 416 obj = INTERFACE(obj)->obj; 417 if (object_is_type(obj, target_type)) { 418 return obj; 419 } 420 } 421 422 if (!target_type) { 423 return obj; 424 } 425 426 /* Check if obj has an interface of typename */ 427 for (i = obj->interfaces; i; i = i->next) { 428 Interface *iface = i->data; 429 430 if (object_is_type(OBJECT(iface), target_type)) { 431 return OBJECT(iface); 432 } 433 } 434 435 return NULL; 436 } 437 438 439 static void register_interface(void) 440 { 441 static TypeInfo interface_info = { 442 .name = TYPE_INTERFACE, 443 .instance_size = sizeof(Interface), 444 .abstract = true, 445 }; 446 447 type_interface = type_register_static(&interface_info); 448 } 449 450 device_init(register_interface); 451 452 Object *object_dynamic_cast_assert(Object *obj, const char *typename) 453 { 454 Object *inst; 455 456 inst = object_dynamic_cast(obj, typename); 457 458 if (!inst) { 459 fprintf(stderr, "Object %p is not an instance of type %s\n", 460 obj, typename); 461 abort(); 462 } 463 464 return inst; 465 } 466 467 ObjectClass *object_class_dynamic_cast(ObjectClass *class, 468 const char *typename) 469 { 470 TypeImpl *target_type = type_get_by_name(typename); 471 TypeImpl *type = class->type; 472 473 while (type) { 474 if (type == target_type) { 475 return class; 476 } 477 478 type = type_get_parent(type); 479 } 480 481 return NULL; 482 } 483 484 ObjectClass *object_class_dynamic_cast_assert(ObjectClass *class, 485 const char *typename) 486 { 487 ObjectClass *ret = object_class_dynamic_cast(class, typename); 488 489 if (!ret) { 490 fprintf(stderr, "Object %p is not an instance of type %s\n", 491 class, typename); 492 abort(); 493 } 494 495 return ret; 496 } 497 498 const char *object_get_typename(Object *obj) 499 { 500 return obj->class->type->name; 501 } 502 503 ObjectClass *object_get_class(Object *obj) 504 { 505 return obj->class; 506 } 507 508 const char *object_class_get_name(ObjectClass *klass) 509 { 510 return klass->type->name; 511 } 512 513 ObjectClass *object_class_by_name(const char *typename) 514 { 515 TypeImpl *type = type_get_by_name(typename); 516 517 if (!type) { 518 return NULL; 519 } 520 521 type_class_init(type); 522 523 return type->class; 524 } 525 526 typedef struct OCFData 527 { 528 void (*fn)(ObjectClass *klass, void *opaque); 529 const char *implements_type; 530 bool include_abstract; 531 void *opaque; 532 } OCFData; 533 534 static void object_class_foreach_tramp(gpointer key, gpointer value, 535 gpointer opaque) 536 { 537 OCFData *data = opaque; 538 TypeImpl *type = value; 539 ObjectClass *k; 540 541 type_class_init(type); 542 k = type->class; 543 544 if (!data->include_abstract && type->abstract) { 545 return; 546 } 547 548 if (data->implements_type && 549 !object_class_dynamic_cast(k, data->implements_type)) { 550 return; 551 } 552 553 data->fn(k, data->opaque); 554 } 555 556 void object_class_foreach(void (*fn)(ObjectClass *klass, void *opaque), 557 const char *implements_type, bool include_abstract, 558 void *opaque) 559 { 560 OCFData data = { fn, implements_type, include_abstract, opaque }; 561 562 g_hash_table_foreach(type_table_get(), object_class_foreach_tramp, &data); 563 } 564 565 void object_ref(Object *obj) 566 { 567 obj->ref++; 568 } 569 570 void object_unref(Object *obj) 571 { 572 g_assert(obj->ref > 0); 573 obj->ref--; 574 575 /* parent always holds a reference to its children */ 576 if (obj->ref == 0) { 577 object_finalize(obj); 578 } 579 } 580 581 void object_property_add(Object *obj, const char *name, const char *type, 582 ObjectPropertyAccessor *get, 583 ObjectPropertyAccessor *set, 584 ObjectPropertyRelease *release, 585 void *opaque, Error **errp) 586 { 587 ObjectProperty *prop = g_malloc0(sizeof(*prop)); 588 589 prop->name = g_strdup(name); 590 prop->type = g_strdup(type); 591 592 prop->get = get; 593 prop->set = set; 594 prop->release = release; 595 prop->opaque = opaque; 596 597 QTAILQ_INSERT_TAIL(&obj->properties, prop, node); 598 } 599 600 static ObjectProperty *object_property_find(Object *obj, const char *name) 601 { 602 ObjectProperty *prop; 603 604 QTAILQ_FOREACH(prop, &obj->properties, node) { 605 if (strcmp(prop->name, name) == 0) { 606 return prop; 607 } 608 } 609 610 return NULL; 611 } 612 613 void object_property_del(Object *obj, const char *name, Error **errp) 614 { 615 ObjectProperty *prop = object_property_find(obj, name); 616 617 QTAILQ_REMOVE(&obj->properties, prop, node); 618 619 prop->release(obj, prop->name, prop->opaque); 620 621 g_free(prop->name); 622 g_free(prop->type); 623 g_free(prop); 624 } 625 626 void object_property_get(Object *obj, Visitor *v, const char *name, 627 Error **errp) 628 { 629 ObjectProperty *prop = object_property_find(obj, name); 630 631 if (prop == NULL) { 632 error_set(errp, QERR_PROPERTY_NOT_FOUND, "", name); 633 return; 634 } 635 636 if (!prop->get) { 637 error_set(errp, QERR_PERMISSION_DENIED); 638 } else { 639 prop->get(obj, v, prop->opaque, name, errp); 640 } 641 } 642 643 void object_property_set(Object *obj, Visitor *v, const char *name, 644 Error **errp) 645 { 646 ObjectProperty *prop = object_property_find(obj, name); 647 648 if (prop == NULL) { 649 error_set(errp, QERR_PROPERTY_NOT_FOUND, "", name); 650 return; 651 } 652 653 if (!prop->set) { 654 error_set(errp, QERR_PERMISSION_DENIED); 655 } else { 656 prop->set(obj, v, prop->opaque, name, errp); 657 } 658 } 659 660 const char *object_property_get_type(Object *obj, const char *name, Error **errp) 661 { 662 ObjectProperty *prop = object_property_find(obj, name); 663 664 if (prop == NULL) { 665 error_set(errp, QERR_PROPERTY_NOT_FOUND, "", name); 666 return NULL; 667 } 668 669 return prop->type; 670 } 671 672 Object *object_get_root(void) 673 { 674 static Object *root; 675 676 if (!root) { 677 root = object_new("container"); 678 } 679 680 return root; 681 } 682 683 static void object_get_child_property(Object *obj, Visitor *v, void *opaque, 684 const char *name, Error **errp) 685 { 686 Object *child = opaque; 687 gchar *path; 688 689 path = object_get_canonical_path(child); 690 visit_type_str(v, &path, name, errp); 691 g_free(path); 692 } 693 694 static void object_finalize_child_property(Object *obj, const char *name, 695 void *opaque) 696 { 697 Object *child = opaque; 698 699 object_unref(child); 700 } 701 702 void object_property_add_child(Object *obj, const char *name, 703 Object *child, Error **errp) 704 { 705 gchar *type; 706 707 type = g_strdup_printf("child<%s>", object_get_typename(OBJECT(child))); 708 709 object_property_add(obj, name, type, object_get_child_property, 710 NULL, object_finalize_child_property, child, errp); 711 712 object_ref(child); 713 g_assert(child->parent == NULL); 714 child->parent = obj; 715 716 g_free(type); 717 } 718 719 static void object_get_link_property(Object *obj, Visitor *v, void *opaque, 720 const char *name, Error **errp) 721 { 722 Object **child = opaque; 723 gchar *path; 724 725 if (*child) { 726 path = object_get_canonical_path(*child); 727 visit_type_str(v, &path, name, errp); 728 g_free(path); 729 } else { 730 path = (gchar *)""; 731 visit_type_str(v, &path, name, errp); 732 } 733 } 734 735 static void object_set_link_property(Object *obj, Visitor *v, void *opaque, 736 const char *name, Error **errp) 737 { 738 Object **child = opaque; 739 bool ambiguous = false; 740 const char *type; 741 char *path; 742 743 type = object_property_get_type(obj, name, NULL); 744 745 visit_type_str(v, &path, name, errp); 746 747 if (*child) { 748 object_unref(*child); 749 } 750 751 if (strcmp(path, "") != 0) { 752 Object *target; 753 754 target = object_resolve_path(path, &ambiguous); 755 if (target) { 756 gchar *target_type; 757 758 target_type = g_strdup(&type[5]); 759 target_type[strlen(target_type) - 2] = 0; 760 761 if (object_dynamic_cast(target, target_type)) { 762 object_ref(target); 763 *child = target; 764 } else { 765 error_set(errp, QERR_INVALID_PARAMETER_TYPE, name, type); 766 } 767 768 g_free(target_type); 769 } else { 770 error_set(errp, QERR_DEVICE_NOT_FOUND, path); 771 } 772 } else { 773 *child = NULL; 774 } 775 776 g_free(path); 777 } 778 779 void object_property_add_link(Object *obj, const char *name, 780 const char *type, Object **child, 781 Error **errp) 782 { 783 gchar *full_type; 784 785 full_type = g_strdup_printf("link<%s>", type); 786 787 object_property_add(obj, name, full_type, 788 object_get_link_property, 789 object_set_link_property, 790 NULL, child, errp); 791 792 g_free(full_type); 793 } 794 795 gchar *object_get_canonical_path(Object *obj) 796 { 797 Object *root = object_get_root(); 798 char *newpath = NULL, *path = NULL; 799 800 while (obj != root) { 801 ObjectProperty *prop = NULL; 802 803 g_assert(obj->parent != NULL); 804 805 QTAILQ_FOREACH(prop, &obj->parent->properties, node) { 806 if (!strstart(prop->type, "child<", NULL)) { 807 continue; 808 } 809 810 if (prop->opaque == obj) { 811 if (path) { 812 newpath = g_strdup_printf("%s/%s", prop->name, path); 813 g_free(path); 814 path = newpath; 815 } else { 816 path = g_strdup(prop->name); 817 } 818 break; 819 } 820 } 821 822 g_assert(prop != NULL); 823 824 obj = obj->parent; 825 } 826 827 newpath = g_strdup_printf("/%s", path); 828 g_free(path); 829 830 return newpath; 831 } 832 833 static Object *object_resolve_abs_path(Object *parent, 834 gchar **parts, 835 int index) 836 { 837 ObjectProperty *prop; 838 Object *child; 839 840 if (parts[index] == NULL) { 841 return parent; 842 } 843 844 if (strcmp(parts[index], "") == 0) { 845 return object_resolve_abs_path(parent, parts, index + 1); 846 } 847 848 prop = object_property_find(parent, parts[index]); 849 if (prop == NULL) { 850 return NULL; 851 } 852 853 child = NULL; 854 if (strstart(prop->type, "link<", NULL)) { 855 Object **pchild = prop->opaque; 856 if (*pchild) { 857 child = *pchild; 858 } 859 } else if (strstart(prop->type, "child<", NULL)) { 860 child = prop->opaque; 861 } 862 863 if (!child) { 864 return NULL; 865 } 866 867 return object_resolve_abs_path(child, parts, index + 1); 868 } 869 870 static Object *object_resolve_partial_path(Object *parent, 871 gchar **parts, 872 bool *ambiguous) 873 { 874 Object *obj; 875 ObjectProperty *prop; 876 877 obj = object_resolve_abs_path(parent, parts, 0); 878 879 QTAILQ_FOREACH(prop, &parent->properties, node) { 880 Object *found; 881 882 if (!strstart(prop->type, "child<", NULL)) { 883 continue; 884 } 885 886 found = object_resolve_partial_path(prop->opaque, parts, ambiguous); 887 if (found) { 888 if (obj) { 889 if (ambiguous) { 890 *ambiguous = true; 891 } 892 return NULL; 893 } 894 obj = found; 895 } 896 897 if (ambiguous && *ambiguous) { 898 return NULL; 899 } 900 } 901 902 return obj; 903 } 904 905 Object *object_resolve_path(const char *path, bool *ambiguous) 906 { 907 bool partial_path = true; 908 Object *obj; 909 gchar **parts; 910 911 parts = g_strsplit(path, "/", 0); 912 if (parts == NULL || parts[0] == NULL) { 913 g_strfreev(parts); 914 return object_get_root(); 915 } 916 917 if (strcmp(parts[0], "") == 0) { 918 partial_path = false; 919 } 920 921 if (partial_path) { 922 if (ambiguous) { 923 *ambiguous = false; 924 } 925 obj = object_resolve_partial_path(object_get_root(), parts, ambiguous); 926 } else { 927 obj = object_resolve_abs_path(object_get_root(), parts, 1); 928 } 929 930 g_strfreev(parts); 931 932 return obj; 933 } 934 935 typedef struct StringProperty 936 { 937 char *(*get)(Object *, Error **); 938 void (*set)(Object *, const char *, Error **); 939 } StringProperty; 940 941 static void object_property_get_str(Object *obj, Visitor *v, void *opaque, 942 const char *name, Error **errp) 943 { 944 StringProperty *prop = opaque; 945 char *value; 946 947 value = prop->get(obj, errp); 948 if (value) { 949 visit_type_str(v, &value, name, errp); 950 g_free(value); 951 } 952 } 953 954 static void object_property_set_str(Object *obj, Visitor *v, void *opaque, 955 const char *name, Error **errp) 956 { 957 StringProperty *prop = opaque; 958 char *value; 959 Error *local_err = NULL; 960 961 visit_type_str(v, &value, name, &local_err); 962 if (local_err) { 963 error_propagate(errp, local_err); 964 return; 965 } 966 967 prop->set(obj, value, errp); 968 g_free(value); 969 } 970 971 static void object_property_release_str(Object *obj, const char *name, 972 void *opaque) 973 { 974 StringProperty *prop = opaque; 975 g_free(prop); 976 } 977 978 void object_property_add_str(Object *obj, const char *name, 979 char *(*get)(Object *, Error **), 980 void (*set)(Object *, const char *, Error **), 981 Error **errp) 982 { 983 StringProperty *prop = g_malloc0(sizeof(*prop)); 984 985 prop->get = get; 986 prop->set = set; 987 988 object_property_add(obj, name, "string", 989 get ? object_property_get_str : NULL, 990 set ? object_property_set_str : NULL, 991 object_property_release_str, 992 prop, errp); 993 } 994