#include #define SET_CAST(p) OBJECT_C_CAST(struct set, s_base, &set_type, p) struct set { struct object s_base; struct queue s_list; char s_name[OBJECT_NAME_MAX]; }; static struct object_type set_type; static kern_status_t set_query_name(struct object *obj, char out[OBJECT_NAME_MAX]) { struct set *set = SET_CAST(obj); strncpy(out, set->s_name, OBJECT_NAME_MAX - 1); out[OBJECT_NAME_MAX - 1] = 0; return KERN_OK; } static kern_status_t set_get_child_at(struct object *obj, size_t at, struct object **out) { struct set *set = SET_CAST(obj); size_t i = 0; queue_foreach(struct object, child, &set->s_list, ob_list) { if (i == at) { *out = object_ref(child); return KERN_OK; } i++; } return KERN_NO_ENTRY; } static kern_status_t set_get_child_named(struct object *obj, const char *name, struct object **out) { struct set *set = SET_CAST(obj); char child_name[OBJECT_NAME_MAX]; queue_foreach(struct object, child, &set->s_list, ob_list) { kern_status_t status = object_query_name(child, child_name); if (status != KERN_OK) { continue; } if (!strcmp(child_name, name)) { *out = object_ref(child); return KERN_OK; } } return KERN_NO_ENTRY; } static struct object_type set_type = { .ob_name = "set", .ob_size = sizeof(struct set), .ob_header_offset = offsetof(struct set, s_base), .ob_ops = { .query_name = set_query_name, .get_named = set_get_child_named, .get_at = set_get_child_at, }, }; void init_set_objects(void) { object_type_register(&set_type); } struct object *set_create(const char *name) { struct object *set_obj = object_create(&set_type); if (!set_obj) { return NULL; } struct set *set = SET_CAST(set_obj); set->s_list = QUEUE_INIT; strncpy(set->s_name, name, sizeof set->s_name - 1); set->s_name[sizeof set->s_name - 1] = 0; return set_obj; } kern_status_t set_add_object(struct object *set_obj, struct object *obj) { if (!object_is_set(set_obj)) { return KERN_INVALID_ARGUMENT; } struct set *set = SET_CAST(set_obj); char child_name[OBJECT_NAME_MAX]; char obj_name[OBJECT_NAME_MAX]; kern_status_t status = object_query_name(obj, obj_name); if (status != KERN_OK) { return status; } queue_foreach (struct object, child, &set->s_list, ob_list) { object_query_name(child, child_name); if (!strcmp(child_name, obj_name)) { return KERN_NAME_EXISTS; } } object_ref(obj); queue_push_back(&set->s_list, &obj->ob_list); return KERN_OK; } kern_status_t set_remove_object(struct object *set_obj, struct object *obj) { if (!object_is_set(set_obj)) { return KERN_INVALID_ARGUMENT; } struct set *set = SET_CAST(set_obj); queue_delete(&set->s_list, &obj->ob_list); object_deref(obj); return KERN_OK; } bool object_is_set(struct object *obj) { return obj->ob_type == &set_type; }