Esempio n. 1
0
static bool bus_match_node_maybe_free(struct bus_match_node *node) {
        assert(node);

        if (node->child)
                return false;

        if (BUS_MATCH_IS_COMPARE(node->type) && !hashmap_isempty(node->compare.children))
                return true;

        bus_match_node_free(node);
        return true;
}
Esempio n. 2
0
static void bus_match_node_free(struct bus_match_node *node) {
        assert(node);
        assert(node->parent);
        assert(!node->child);
        assert(node->type != BUS_MATCH_ROOT);
        assert(node->type < _BUS_MATCH_NODE_TYPE_MAX);

        if (node->parent->child) {
                /* We are apparently linked into the parent's child
                 * list. Let's remove us from there. */
                if (node->prev) {
                        assert(node->prev->next == node);
                        node->prev->next = node->next;
                } else {
                        assert(node->parent->child == node);
                        node->parent->child = node->next;
                }

                if (node->next)
                        node->next->prev = node->prev;
        }

        if (node->type == BUS_MATCH_VALUE) {
                /* We might be in the parent's hash table, so clean
                 * this up */

                if (node->parent->type == BUS_MATCH_MESSAGE_TYPE)
                        hashmap_remove(node->parent->compare.children, UINT_TO_PTR(node->value.u8));
                else if (BUS_MATCH_CAN_HASH(node->parent->type) && node->value.str)
                        hashmap_remove(node->parent->compare.children, node->value.str);

                free(node->value.str);
        }

        if (BUS_MATCH_IS_COMPARE(node->type)) {
                assert(hashmap_isempty(node->compare.children));
                hashmap_free(node->compare.children);
        }

        free(node);
}
Esempio n. 3
0
static int bus_match_find_compare_value(
                struct bus_match_node *where,
                enum bus_match_node_type t,
                uint8_t value_u8,
                const char *value_str,
                struct bus_match_node **ret) {

        struct bus_match_node *c, *n;

        assert(where);
        assert(where->type == BUS_MATCH_ROOT || where->type == BUS_MATCH_VALUE);
        assert(BUS_MATCH_IS_COMPARE(t));
        assert(ret);

        for (c = where->child; c && c->type != t; c = c->next)
                ;

        if (!c)
                return 0;

        if (t == BUS_MATCH_MESSAGE_TYPE)
                n = hashmap_get(c->compare.children, UINT_TO_PTR(value_u8));
        else if (BUS_MATCH_CAN_HASH(t))
                n = hashmap_get(c->compare.children, value_str);
        else {
                for (n = c->child; !value_node_same(n, t, value_u8, value_str); n = n->next)
                        ;
        }

        if (n) {
                *ret = n;
                return 1;
        }

        return 0;
}
Esempio n. 4
0
static int bus_match_add_compare_value(
                struct bus_match_node *where,
                enum bus_match_node_type t,
                uint8_t value_u8,
                const char *value_str,
                struct bus_match_node **ret) {

        struct bus_match_node *c = NULL, *n = NULL;
        int r;

        assert(where);
        assert(where->type == BUS_MATCH_ROOT || where->type == BUS_MATCH_VALUE);
        assert(BUS_MATCH_IS_COMPARE(t));
        assert(ret);

        for (c = where->child; c && c->type != t; c = c->next)
                ;

        if (c) {
                /* Comparison node already exists? Then let's see if
                 * the value node exists too. */

                if (t == BUS_MATCH_MESSAGE_TYPE)
                        n = hashmap_get(c->compare.children, UINT_TO_PTR(value_u8));
                else if (BUS_MATCH_CAN_HASH(t))
                        n = hashmap_get(c->compare.children, value_str);
                else {
                        for (n = c->child; n && !value_node_same(n, t, value_u8, value_str); n = n->next)
                                ;
                }

                if (n) {
                        *ret = n;
                        return 0;
                }
        } else {
                /* Comparison node, doesn't exist yet? Then let's
                 * create it. */

                c = new0(struct bus_match_node, 1);
                if (!c) {
                        r = -ENOMEM;
                        goto fail;
                }

                c->type = t;
                c->parent = where;
                c->next = where->child;
                if (c->next)
                        c->next->prev = c;
                where->child = c;

                if (t == BUS_MATCH_MESSAGE_TYPE) {
                        c->compare.children = hashmap_new(trivial_hash_func, trivial_compare_func);
                        if (!c->compare.children) {
                                r = -ENOMEM;
                                goto fail;
                        }
                } else if (BUS_MATCH_CAN_HASH(t)) {
                        c->compare.children = hashmap_new(string_hash_func, string_compare_func);
                        if (!c->compare.children) {
                                r = -ENOMEM;
                                goto fail;
                        }
                }
        }

        n = new0(struct bus_match_node, 1);
        if (!n) {
                r = -ENOMEM;
                goto fail;
        }

        n->type = BUS_MATCH_VALUE;
        n->value.u8 = value_u8;
        if (value_str) {
                n->value.str = strdup(value_str);
                if (!n->value.str) {
                        r = -ENOMEM;
                        goto fail;
                }
        }

        n->parent = c;
        if (c->compare.children) {

                if (t == BUS_MATCH_MESSAGE_TYPE)
                        r = hashmap_put(c->compare.children, UINT_TO_PTR(value_u8), n);
                else
                        r = hashmap_put(c->compare.children, n->value.str, n);

                if (r < 0)
                        goto fail;
        } else {
                n->next = c->child;
                if (n->next)
                        n->next->prev = n;
                c->child = n;
        }

        *ret = n;
        return 1;

fail:
        if (c)
                bus_match_node_maybe_free(c);

        if (n) {
                free(n->value.str);
                free(n);
        }

        return r;
}