Beispiel #1
0
static int trie_node_add_value(struct trie *trie, struct trie_node *node,
                               const char *key, const char *value,
                               const char *filename, uint16_t file_priority, uint32_t line_number) {
        ssize_t k, v, fn;
        struct trie_value_entry *val;

        k = strbuf_add_string(trie->strings, key, strlen(key));
        if (k < 0)
                return k;
        v = strbuf_add_string(trie->strings, value, strlen(value));
        if (v < 0)
                return v;
        fn = strbuf_add_string(trie->strings, filename, strlen(filename));
        if (fn < 0)
                return fn;

        if (node->values_count) {
                struct trie_value_entry search = {
                        .key_off = k,
                        .value_off = v,
                };

                val = xbsearch_r(&search, node->values, node->values_count, sizeof(struct trie_value_entry), trie_values_cmp, trie);
                if (val) {
                        /* At this point we have 2 identical properties on the same match-string.
                         * Since we process files in order, we just replace the previous value.
                         */
                        val->value_off = v;
                        val->filename_off = fn;
                        val->file_priority = file_priority;
                        val->line_number = line_number;
                        return 0;
                }
        }

        /* extend array, add new entry, sort for bisection */
        val = reallocarray(node->values, node->values_count + 1, sizeof(struct trie_value_entry));
        if (!val)
                return -ENOMEM;
        trie->values_count++;
        node->values = val;
        node->values[node->values_count].key_off = k;
        node->values[node->values_count].value_off = v;
        node->values[node->values_count].filename_off = fn;
        node->values[node->values_count].file_priority = file_priority;
        node->values[node->values_count].line_number = line_number;
        node->values_count++;
        qsort_r(node->values, node->values_count, sizeof(struct trie_value_entry), trie_values_cmp, trie);
        return 0;
}
static int trie_node_add_value(struct trie *trie, struct trie_node *node,
                          const char *key, const char *value) {
        ssize_t k, v;
        struct trie_value_entry *val;

        k = strbuf_add_string(trie->strings, key, strlen(key));
        if (k < 0)
                return k;
        v = strbuf_add_string(trie->strings, value, strlen(value));
        if (v < 0)
                return v;

        if (node->values_count) {
                struct trie_value_entry search = {
                        .key_off = k,
                        .value_off = v,
                };

                val = xbsearch_r(&search, node->values, node->values_count, sizeof(struct trie_value_entry), trie_values_cmp_r, trie);
                if (val) {
                        /* replace existing earlier key with new value */
                        val->value_off = v;
                        return 0;
                }
        }

        /* extend array, add new entry, sort for bisection */
        val = realloc(node->values, (node->values_count + 1) * sizeof(struct trie_value_entry));
        if (!val)
                return -ENOMEM;
        trie->values_count++;
        node->values = val;
        node->values[node->values_count].key_off = k;
        node->values[node->values_count].value_off = v;
        node->values_count++;
	trie_values_cmp_param = trie;
        qsort(node->values, node->values_count, sizeof(struct trie_value_entry), trie_values_cmp);
        return 0;
}
Beispiel #3
0
static int finish_item(
                Hashmap *h,
                struct strbuf *sb,
                sd_id128_t id,
                const char *language,
                const char *payload) {

        ssize_t offset;
        _cleanup_free_ CatalogItem *i = NULL;
        int r;

        assert(h);
        assert(sb);
        assert(payload);

        offset = strbuf_add_string(sb, payload, strlen(payload));
        if (offset < 0)
                return log_oom();

        i = new0(CatalogItem, 1);
        if (!i)
                return log_oom();

        i->id = id;
        if (language) {
                assert(strlen(language) > 1 && strlen(language) < 32);
                strcpy(i->language, language);
        }
        i->offset = htole64((uint64_t) offset);

        r = hashmap_put(h, i, i);
        if (r == -EEXIST) {
                log_warning("Duplicate entry for " SD_ID128_FORMAT_STR ".%s, ignoring.",
                            SD_ID128_FORMAT_VAL(id), language ? language : "C");
                return 0;
        } else if (r < 0)
                return r;

        i = NULL;
        return 0;
}
static int trie_insert(struct trie *trie, struct trie_node *node, const char *search,
                       const char *key, const char *value) {
        size_t i = 0;
        int err = 0;

        for (;;) {
                size_t p;
                uint8_t c;
                struct trie_node *child;

                for (p = 0; (c = trie->strings->buf[node->prefix_off + p]); p++) {
                        _cleanup_free_ char *s = NULL;
                        ssize_t off;
                        _cleanup_free_ struct trie_node *new_child = NULL;

                        if (c == search[i + p])
                                continue;

                        /* split node */
                        new_child = calloc(sizeof(struct trie_node), 1);
                        if (!new_child)
                                return -ENOMEM;

                        /* move values from parent to child */
                        new_child->prefix_off = node->prefix_off + p+1;
                        new_child->children = node->children;
                        new_child->children_count = node->children_count;
                        new_child->values = node->values;
                        new_child->values_count = node->values_count;

                        /* update parent; use strdup() because the source gets realloc()d */
                        s = strndup(trie->strings->buf + node->prefix_off, p);
                        if (!s)
                                return -ENOMEM;

                        off = strbuf_add_string(trie->strings, s, p);
                        if (off < 0)
                                return off;

                        node->prefix_off = off;
                        node->children = NULL;
                        node->children_count = 0;
                        node->values = NULL;
                        node->values_count = 0;
                        err = node_add_child(trie, node, new_child, c);
                        if (err)
                                return err;

                        new_child = NULL; /* avoid cleanup */
                        break;
                }
                i += p;

                c = search[i];
                if (c == '\0')
                        return trie_node_add_value(trie, node, key, value);

                child = node_lookup(node, c);
                if (!child) {
                        ssize_t off;

                        /* new child */
                        child = calloc(sizeof(struct trie_node), 1);
                        if (!child)
                                return -ENOMEM;

                        off = strbuf_add_string(trie->strings, search + i+1, strlen(search + i+1));
                        if (off < 0) {
                                free(child);
                                return off;
                        }

                        child->prefix_off = off;
                        err = node_add_child(trie, node, child, c);
                        if (err) {
                                free(child);
                                return err;
                        }

                        return trie_node_add_value(trie, child, key, value);
                }

                node = child;
                i++;
        }
}
static ssize_t add_string(struct strbuf *sb, const char *s) {
        return strbuf_add_string(sb, s, strlen(s));
}