Annotation of qemu/qom/object.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.