1/*2* Licensed under a two-clause BSD-style license.3* See LICENSE for details.4*/56#include "git-compat-util.h"7#include "quote.h"8#include "trp.h"9#include "obj_pool.h"10#include "string_pool.h"1112static struct trp_root tree = { ~0 };1314struct node {15uint32_t offset;16struct trp_node children;17};1819/* Two memory pools: one for struct node, and another for strings */20obj_pool_gen(node, struct node, 4096)21obj_pool_gen(string, char, 4096)2223static char *node_value(struct node *node)24{25return node ? string_pointer(node->offset) : NULL;26}2728static int node_cmp(struct node *a, struct node *b)29{30return strcmp(node_value(a), node_value(b));31}3233/* Build a Treap from the node structure (a trp_node w/ offset) */34trp_gen(static, tree_, struct node, children, node, node_cmp);3536const char *pool_fetch(uint32_t entry)37{38return node_value(node_pointer(entry));39}4041uint32_t pool_intern(const char *key)42{43/* Canonicalize key */44struct node *match = NULL, *node;45uint32_t key_len;46if (key == NULL)47return ~0;48key_len = strlen(key) + 1;49node = node_pointer(node_alloc(1));50node->offset = string_alloc(key_len);51strcpy(node_value(node), key);52match = tree_search(&tree, node);53if (!match) {54tree_insert(&tree, node);55} else {56node_free(1);57string_free(key_len);58node = match;59}60return node_offset(node);61}6263uint32_t pool_tok_r(char *str, const char *delim, char **saveptr)64{65char *token = strtok_r(str, delim, saveptr);66return token ? pool_intern(token) : ~0;67}6869void pool_print_seq(uint32_t len, const uint32_t *seq, char delim, FILE *stream)70{71uint32_t i;72for (i = 0; i < len && ~seq[i]; i++) {73fputs(pool_fetch(seq[i]), stream);74if (i < len - 1 && ~seq[i + 1])75fputc(delim, stream);76}77}7879void pool_print_seq_q(uint32_t len, const uint32_t *seq, char delim, FILE *stream)80{81uint32_t i;82for (i = 0; i < len && ~seq[i]; i++) {83quote_c_style(pool_fetch(seq[i]), NULL, stream, 1);84if (i < len - 1 && ~seq[i + 1])85fputc(delim, stream);86}87}8889uint32_t pool_tok_seq(uint32_t sz, uint32_t *seq, const char *delim, char *str)90{91char *context = NULL;92uint32_t token = ~0;93uint32_t length;9495if (sz == 0)96return ~0;97if (str)98token = pool_tok_r(str, delim, &context);99for (length = 0; length < sz; length++) {100seq[length] = token;101if (token == ~0)102return length;103token = pool_tok_r(NULL, delim, &context);104}105seq[sz - 1] = ~0;106return sz;107}108109void pool_reset(void)110{111node_reset();112string_reset();113}