| /* |
| * Licensed under a two-clause BSD-style license. |
| * See LICENSE for details. |
| */ |
| |
| #include "git-compat-util.h" |
| #include "trp.h" |
| #include "obj_pool.h" |
| #include "string_pool.h" |
| |
| static struct trp_root tree = { ~0 }; |
| |
| struct node { |
| uint32_t offset; |
| struct trp_node children; |
| }; |
| |
| /* Two memory pools: one for struct node, and another for strings */ |
| obj_pool_gen(node, struct node, 4096) |
| obj_pool_gen(string, char, 4096) |
| |
| static char *node_value(struct node *node) |
| { |
| return node ? string_pointer(node->offset) : NULL; |
| } |
| |
| static int node_cmp(struct node *a, struct node *b) |
| { |
| return strcmp(node_value(a), node_value(b)); |
| } |
| |
| /* Build a Treap from the node structure (a trp_node w/ offset) */ |
| trp_gen(static, tree_, struct node, children, node, node_cmp) |
| |
| const char *pool_fetch(uint32_t entry) |
| { |
| return node_value(node_pointer(entry)); |
| } |
| |
| uint32_t pool_intern(const char *key) |
| { |
| /* Canonicalize key */ |
| struct node *match = NULL, *node; |
| uint32_t key_len; |
| if (key == NULL) |
| return ~0; |
| key_len = strlen(key) + 1; |
| node = node_pointer(node_alloc(1)); |
| node->offset = string_alloc(key_len); |
| strcpy(node_value(node), key); |
| match = tree_search(&tree, node); |
| if (!match) { |
| tree_insert(&tree, node); |
| } else { |
| node_free(1); |
| string_free(key_len); |
| node = match; |
| } |
| return node_offset(node); |
| } |
| |
| uint32_t pool_tok_r(char *str, const char *delim, char **saveptr) |
| { |
| char *token = strtok_r(str, delim, saveptr); |
| return token ? pool_intern(token) : ~0; |
| } |
| |
| void pool_print_seq(uint32_t len, uint32_t *seq, char delim, FILE *stream) |
| { |
| uint32_t i; |
| for (i = 0; i < len && ~seq[i]; i++) { |
| fputs(pool_fetch(seq[i]), stream); |
| if (i < len - 1 && ~seq[i + 1]) |
| fputc(delim, stream); |
| } |
| } |
| |
| uint32_t pool_tok_seq(uint32_t sz, uint32_t *seq, const char *delim, char *str) |
| { |
| char *context = NULL; |
| uint32_t token = ~0; |
| uint32_t length; |
| |
| if (sz == 0) |
| return ~0; |
| if (str) |
| token = pool_tok_r(str, delim, &context); |
| for (length = 0; length < sz; length++) { |
| seq[length] = token; |
| if (token == ~0) |
| return length; |
| token = pool_tok_r(NULL, delim, &context); |
| } |
| seq[sz - 1] = ~0; |
| return sz; |
| } |
| |
| void pool_reset(void) |
| { |
| node_reset(); |
| string_reset(); |
| } |