|
| 1 | +/* |
| 2 | + * Licensed under a two-clause BSD-style license. |
| 3 | + * See LICENSE for details. |
| 4 | + */ |
| 5 | + |
| 6 | +#include "git-compat-util.h" |
| 7 | +#include "trp.h" |
| 8 | +#include "obj_pool.h" |
| 9 | +#include "string_pool.h" |
| 10 | + |
| 11 | +static struct trp_root tree = { ~0 }; |
| 12 | + |
| 13 | +struct node { |
| 14 | + uint32_t offset; |
| 15 | + struct trp_node children; |
| 16 | +}; |
| 17 | + |
| 18 | +/* Two memory pools: one for struct node, and another for strings */ |
| 19 | +obj_pool_gen(node, struct node, 4096) |
| 20 | +obj_pool_gen(string, char, 4096) |
| 21 | + |
| 22 | +static char *node_value(struct node *node) |
| 23 | +{ |
| 24 | + return node ? string_pointer(node->offset) : NULL; |
| 25 | +} |
| 26 | + |
| 27 | +static int node_cmp(struct node *a, struct node *b) |
| 28 | +{ |
| 29 | + return strcmp(node_value(a), node_value(b)); |
| 30 | +} |
| 31 | + |
| 32 | +/* Build a Treap from the node structure (a trp_node w/ offset) */ |
| 33 | +trp_gen(static, tree_, struct node, children, node, node_cmp); |
| 34 | + |
| 35 | +const char *pool_fetch(uint32_t entry) |
| 36 | +{ |
| 37 | + return node_value(node_pointer(entry)); |
| 38 | +} |
| 39 | + |
| 40 | +uint32_t pool_intern(const char *key) |
| 41 | +{ |
| 42 | + /* Canonicalize key */ |
| 43 | + struct node *match = NULL, *node; |
| 44 | + uint32_t key_len; |
| 45 | + if (key == NULL) |
| 46 | + return ~0; |
| 47 | + key_len = strlen(key) + 1; |
| 48 | + node = node_pointer(node_alloc(1)); |
| 49 | + node->offset = string_alloc(key_len); |
| 50 | + strcpy(node_value(node), key); |
| 51 | + match = tree_search(&tree, node); |
| 52 | + if (!match) { |
| 53 | + tree_insert(&tree, node); |
| 54 | + } else { |
| 55 | + node_free(1); |
| 56 | + string_free(key_len); |
| 57 | + node = match; |
| 58 | + } |
| 59 | + return node_offset(node); |
| 60 | +} |
| 61 | + |
| 62 | +uint32_t pool_tok_r(char *str, const char *delim, char **saveptr) |
| 63 | +{ |
| 64 | + char *token = strtok_r(str, delim, saveptr); |
| 65 | + return token ? pool_intern(token) : ~0; |
| 66 | +} |
| 67 | + |
| 68 | +void pool_print_seq(uint32_t len, uint32_t *seq, char delim, FILE *stream) |
| 69 | +{ |
| 70 | + uint32_t i; |
| 71 | + for (i = 0; i < len && ~seq[i]; i++) { |
| 72 | + fputs(pool_fetch(seq[i]), stream); |
| 73 | + if (i < len - 1 && ~seq[i + 1]) |
| 74 | + fputc(delim, stream); |
| 75 | + } |
| 76 | +} |
| 77 | + |
| 78 | +uint32_t pool_tok_seq(uint32_t sz, uint32_t *seq, const char *delim, char *str) |
| 79 | +{ |
| 80 | + char *context = NULL; |
| 81 | + uint32_t token = ~0; |
| 82 | + uint32_t length; |
| 83 | + |
| 84 | + if (sz == 0) |
| 85 | + return ~0; |
| 86 | + if (str) |
| 87 | + token = pool_tok_r(str, delim, &context); |
| 88 | + for (length = 0; length < sz; length++) { |
| 89 | + seq[length] = token; |
| 90 | + if (token == ~0) |
| 91 | + return length; |
| 92 | + token = pool_tok_r(NULL, delim, &context); |
| 93 | + } |
| 94 | + seq[sz - 1] = ~0; |
| 95 | + return sz; |
| 96 | +} |
| 97 | + |
| 98 | +void pool_reset(void) |
| 99 | +{ |
| 100 | + node_reset(); |
| 101 | + string_reset(); |
| 102 | +} |
0 commit comments