summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: b2d7778)
raw | patch | inline | side by side (parent: b2d7778)
author | Jonas Fonseca <fonseca@diku.dk> | |
Wed, 18 Feb 2009 10:47:58 +0000 (11:47 +0100) | ||
committer | Jonas Fonseca <fonseca@diku.dk> | |
Wed, 18 Feb 2009 10:47:58 +0000 (11:47 +0100) |
Add a DEFINE_ALLOCATOR macro which can be used to define a custom
allocator which is more type safe than the current realloc_items and
which removed the need for using temporary variables for holding the
newly allocated chunk. The custom allocator also allows the allocation
granularity to be tweaked to the need of the user instead of being
hardcoded to 256 chunks for all.
allocator which is more type safe than the current realloc_items and
which removed the need for using temporary variables for holding the
newly allocated chunk. The custom allocator also allows the allocation
granularity to be tweaked to the need of the user instead of being
hardcoded to 256 chunks for all.
tig.c | patch | blob | history |
index 74be272a673cd1edb1a17643f4acb377231441e6..566f8031d01047e92f9359e42690108f7f9d5486 100644 (file)
--- a/tig.c
+++ b/tig.c
static char *prompt_input(const char *prompt, input_handler handler, void *data);
static bool prompt_yesno(const char *prompt);
+/*
+ * Allocation helpers ... Entering macro hell to never be seen again.
+ */
+
+#define DEFINE_ALLOCATOR(name, type, chunk_size) \
+static type * \
+name(type **mem, size_t *alloc, size_t new_size) \
+{ \
+ size_t num_chunks = *alloc / chunk_size; \
+ size_t num_chunks_new = (new_size + chunk_size - 1) / chunk_size; \
+ type *tmp = *mem; \
+ \
+ if (mem == NULL || num_chunks != num_chunks_new) { \
+ size_t memsize = num_chunks_new * chunk_size; \
+ tmp = realloc(tmp, memsize * sizeof(type)); \
+ if (tmp) \
+ *mem = tmp, *alloc = memsize; \
+ } \
+ \
+ return tmp; \
+}
+
/*
* String helpers
*/
return TRUE;
}
-#define ITEM_CHUNK_SIZE 256
-static void *
-realloc_items(void *mem, size_t *size, size_t new_size, size_t item_size)
-{
- size_t num_chunks = *size / ITEM_CHUNK_SIZE;
- size_t num_chunks_new = (new_size + ITEM_CHUNK_SIZE - 1) / ITEM_CHUNK_SIZE;
-
- if (mem == NULL || num_chunks != num_chunks_new) {
- *size = num_chunks_new * ITEM_CHUNK_SIZE;
- mem = realloc(mem, *size * item_size);
- }
-
- return mem;
-}
-
-static struct line *
-realloc_lines(struct view *view, size_t line_size)
-{
- size_t alloc = view->line_alloc;
- struct line *tmp = realloc_items(view->line, &alloc, line_size,
- sizeof(*view->line));
-
- if (!tmp)
- return NULL;
-
- view->line = tmp;
- view->line_alloc = alloc;
- return view->line;
-}
-
static bool
update_view(struct view *view)
{
return TRUE;
}
+DEFINE_ALLOCATOR(realloc_lines, struct line, 256)
+
static struct line *
add_line_data(struct view *view, void *data, enum line_type type)
{
struct line *line;
- if (!realloc_lines(view, view->lines + 1))
+ if (!realloc_lines(&view->line, &view->line_alloc, view->lines + 1))
return NULL;
line = &view->line[view->lines++];
* View backend utilities
*/
+DEFINE_ALLOCATOR(realloc_authors, const char *, 256)
+
/* Small author cache to reduce memory consumption. It uses binary
* search to lookup or find place to position new entries. No entries
* are ever freed. */
static const char **authors;
static size_t authors_alloc;
static size_t authors_size;
- const char **tmp;
int from = 0, to = authors_size - 1;
while (from <= to) {
from = pos + 1;
}
- tmp = realloc_items(authors, &authors_alloc, authors_size + 1, sizeof(*authors));
- if (!tmp)
+ if (!realloc_authors(&authors, &authors_alloc, authors_size + 1))
return NULL;
name = strdup(name);
if (!name)
return NULL;
- authors = tmp;
memmove(authors + from + 1, authors + from, (authors_size - from) * sizeof(*authors));
authors[from] = name;
authors_size++;
static size_t stage_chunks;
static int *stage_chunk;
+DEFINE_ALLOCATOR(realloc_ints, int, 32)
+
/* This should work even for the "On branch" line. */
static inline bool
status_has_none(struct view *view, struct line *line)
if (!stage_chunks) {
static size_t alloc = 0;
- int *tmp;
for (line = view->line; line < view->line + view->lines; line++) {
if (line->type != LINE_DIFF_CHUNK)
continue;
- tmp = realloc_items(stage_chunk, &alloc,
- stage_chunks, sizeof(*tmp));
- if (!tmp) {
+ if (!realloc_ints(&stage_chunk, &alloc, stage_chunks + 1)) {
report("Allocation failure");
return;
}
- stage_chunk = tmp;
stage_chunk[stage_chunks++] = line - view->line;
}
}
static size_t id_refs_alloc = 0;
static size_t id_refs_size = 0;
+DEFINE_ALLOCATOR(realloc_refs, struct ref, 256)
+DEFINE_ALLOCATOR(realloc_refs_list, struct ref *, 8)
+DEFINE_ALLOCATOR(realloc_refs_lists, struct ref **, 8)
+
static int
compare_refs(const void *ref1_, const void *ref2_)
{
static struct ref **
get_refs(const char *id)
{
- struct ref ***tmp_id_refs;
struct ref **ref_list = NULL;
size_t ref_list_alloc = 0;
size_t ref_list_size = 0;
if (!strcmp(id, id_refs[i][0]->id))
return id_refs[i];
- tmp_id_refs = realloc_items(id_refs, &id_refs_alloc, id_refs_size + 1,
- sizeof(*id_refs));
- if (!tmp_id_refs)
+ if (!realloc_refs_lists(&id_refs, &id_refs_alloc, id_refs_size + 1))
return NULL;
- id_refs = tmp_id_refs;
-
for (i = 0; i < refs_size; i++) {
- struct ref **tmp;
-
if (strcmp(id, refs[i].id))
continue;
- tmp = realloc_items(ref_list, &ref_list_alloc,
- ref_list_size + 1, sizeof(*ref_list));
- if (!tmp) {
- if (ref_list)
- free(ref_list);
- return NULL;
- }
+ if (!realloc_refs_list(&ref_list, &ref_list_alloc, ref_list_size + 1))
+ return ref_list;
- ref_list = tmp;
ref_list[ref_list_size] = &refs[i];
/* XXX: The properties of the commit chains ensures that we can
* safely modify the shared ref. The repo references will
* always be similar for the same id. */
ref_list[ref_list_size]->next = 1;
-
ref_list_size++;
}
return OK;
}
- refs = realloc_items(refs, &refs_alloc, refs_size + 1, sizeof(*refs));
- if (!refs)
+
+ if (!realloc_refs(&refs, &refs_alloc, refs_size + 1))
return ERR;
ref = &refs[refs_size++];