git/vcs-svn/string_pool.c
Jonathan Nieder 9ecfa8ae4c Merge branch 'db/vcs-svn-incremental' into svn-fe
This teaches svn-fe to incrementally import into an existing
repository (at last!) at the expense of less convenient UI.  Think of
it as growing pains.  This opens the door to many excellent things,
and it would be a bad idea to discourage people from building on it
for much longer.

* db/vcs-svn-incremental:
  vcs-svn: avoid using ls command twice
  vcs-svn: use mark from previous import for parent commit
  vcs-svn: handle filenames with dq correctly
  vcs-svn: quote paths correctly for ls command
  vcs-svn: eliminate repo_tree structure
  vcs-svn: add a comment before each commit
  vcs-svn: save marks for imported commits
  vcs-svn: use higher mark numbers for blobs
  vcs-svn: set up channel to read fast-import cat-blob response

Conflicts:
	t/t9010-svn-fe.sh
	vcs-svn/fast_export.c
	vcs-svn/fast_export.h
	vcs-svn/repo_tree.c
	vcs-svn/svndump.c
2011-05-26 02:02:44 -05:00

114 lines
2.4 KiB
C

/*
* Licensed under a two-clause BSD-style license.
* See LICENSE for details.
*/
#include "git-compat-util.h"
#include "quote.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, const 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);
}
}
void pool_print_seq_q(uint32_t len, const uint32_t *seq, char delim, FILE *stream)
{
uint32_t i;
for (i = 0; i < len && ~seq[i]; i++) {
quote_c_style(pool_fetch(seq[i]), NULL, stream, 1);
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();
}