diff options
Diffstat (limited to 'src/dged/buffers.c')
| -rw-r--r-- | src/dged/buffers.c | 171 |
1 files changed, 132 insertions, 39 deletions
diff --git a/src/dged/buffers.c b/src/dged/buffers.c index f591385..d20be39 100644 --- a/src/dged/buffers.c +++ b/src/dged/buffers.c @@ -5,32 +5,60 @@ #include <stdlib.h> #include <string.h> -struct buffer_entry { - struct buffer buffer; - bool empty; -}; +static struct buffer_chunk *new_chunk(uint32_t sz) { + struct buffer_chunk *chunk = calloc(1, sizeof(struct buffer_chunk)); + chunk->entries = calloc(sz, sizeof(struct buffer_entry)); + return chunk; +} + +static bool chunk_empty(const struct buffer_chunk *chunk, uint32_t sz) { + for (uint32_t i = 0; i < sz; ++i) { + if (chunk->entries[i].occupied) { + return false; + } + } + + return true; +} + +static void free_chunk(struct buffer_chunk *chunk) { + free(chunk->entries); + chunk->entries = NULL; + chunk->next = NULL; + free(chunk); +} void buffers_init(struct buffers *buffers, uint32_t initial_capacity) { - VEC_INIT(&buffers->buffers, initial_capacity); + buffers->chunk_size = initial_capacity; + buffers->head = new_chunk(buffers->chunk_size); VEC_INIT(&buffers->add_hooks, 32); VEC_INIT(&buffers->remove_hooks, 32); } struct buffer *buffers_add(struct buffers *buffers, struct buffer buffer) { struct buffer_entry *slot = NULL; - VEC_FOR_EACH(&buffers->buffers, struct buffer_entry * e) { - if (e->empty) { - slot = e; + struct buffer_chunk *chunk = buffers->head, *prev_chunk = buffers->head; + while (chunk != NULL) { + for (uint32_t i = 0; i < buffers->chunk_size; ++i) { + if (!chunk->entries[i].occupied) { + slot = &chunk->entries[i]; + goto found; + } } - } - if (slot == NULL) { - VEC_APPEND(&buffers->buffers, struct buffer_entry * new); - slot = new; + prev_chunk = chunk; + chunk = chunk->next; } + chunk = new_chunk(buffers->chunk_size); + prev_chunk->next = chunk; + + slot = &chunk->entries[0]; + +found: + slot->buffer = buffer; - slot->empty = false; + slot->occupied = true; VEC_FOR_EACH(&buffers->add_hooks, struct buffers_hook * hook) { hook->callback(&slot->buffer, hook->userdata); @@ -60,10 +88,22 @@ uint32_t buffers_add_remove_hook(struct buffers *buffers, } struct buffer *buffers_find(struct buffers *buffers, const char *name) { - VEC_FOR_EACH(&buffers->buffers, struct buffer_entry * e) { - if (!e->empty && strcmp(name, e->buffer.name) == 0) { - return &e->buffer; + struct buffer_chunk *chunk = buffers->head; + size_t namelen = strlen(name); + while (chunk != NULL) { + for (uint32_t i = 0; i < buffers->chunk_size; ++i) { + if (!chunk->entries[i].occupied) { + continue; + } + + struct buffer *b = &chunk->entries[i].buffer; + size_t bnamelen = b->name != NULL ? strlen(b->name) : 0; + if (namelen == bnamelen && memcmp(name, b->name, bnamelen) == 0) { + return b; + } } + + chunk = chunk->next; } return NULL; @@ -71,65 +111,118 @@ struct buffer *buffers_find(struct buffers *buffers, const char *name) { struct buffer *buffers_find_by_filename(struct buffers *buffers, const char *path) { - VEC_FOR_EACH(&buffers->buffers, struct buffer_entry * e) { - if (!e->empty && e->buffer.filename != NULL && - strcmp(path, e->buffer.filename) == 0) { - return &e->buffer; + struct buffer_chunk *chunk = buffers->head; + size_t pathlen = strlen(path); + while (chunk != NULL) { + for (uint32_t i = 0; i < buffers->chunk_size; ++i) { + if (!chunk->entries[i].occupied) { + continue; + } + + struct buffer *b = &chunk->entries[i].buffer; + if (b->filename == NULL) { + continue; + } + + size_t bnamelen = strlen(b->filename); + if (bnamelen == pathlen && memcmp(path, b->filename, bnamelen) == 0) { + return b; + } } + + chunk = chunk->next; } return NULL; } bool buffers_remove(struct buffers *buffers, const char *name) { + struct buffer_chunk *chunk = buffers->head, *prev_chunk = buffers->head; struct buffer_entry *buf_entry = NULL; - VEC_FOR_EACH(&buffers->buffers, struct buffer_entry * e) { - if (!e->empty && strcmp(name, e->buffer.name) == 0) { - buf_entry = e; + size_t namelen = strlen(name); + while (chunk != NULL) { + for (uint32_t i = 0; i < buffers->chunk_size; ++i) { + struct buffer *b = &chunk->entries[i].buffer; + size_t bnamelen = strlen(b->name); + if (chunk->entries[i].occupied && namelen == bnamelen && + memcmp(name, b->name, bnamelen) == 0) { + buf_entry = &chunk->entries[i]; + goto found; + } } - } - if (buf_entry == NULL) { - return false; + prev_chunk = chunk; + chunk = chunk->next; } + return false; + +found: + VEC_FOR_EACH(&buffers->remove_hooks, struct buffers_hook * hook) { hook->callback(&buf_entry->buffer, hook->userdata); } - buf_entry->empty = true; + buf_entry->occupied = false; buffer_destroy(&buf_entry->buffer); + + if (chunk_empty(chunk, buffers->chunk_size) && chunk != buffers->head) { + prev_chunk->next = chunk->next; + free_chunk(chunk); + } return true; } void buffers_for_each(struct buffers *buffers, buffers_hook_cb callback, void *userdata) { - VEC_FOR_EACH(&buffers->buffers, struct buffer_entry * e) { - if (!e->empty) { - callback(&e->buffer, userdata); + struct buffer_chunk *chunk = buffers->head; + while (chunk != NULL) { + for (uint32_t i = 0; i < buffers->chunk_size; ++i) { + if (chunk->entries[i].occupied) { + callback(&chunk->entries[i].buffer, userdata); + } } + + chunk = chunk->next; } } uint32_t buffers_num_buffers(struct buffers *buffers) { - return VEC_SIZE(&buffers->buffers); + uint32_t total_buffers = 0; + struct buffer_chunk *chunk = buffers->head; + while (chunk != NULL) { + for (uint32_t i = 0; i < buffers->chunk_size; ++i) { + if (chunk->entries[i].occupied) { + ++total_buffers; + } + } + + chunk = chunk->next; + } + + return total_buffers; } struct buffer *buffers_first(struct buffers *buffers) { - return buffers_num_buffers(buffers) > 0 - ? &VEC_ENTRIES(&buffers->buffers)[0].buffer - : NULL; + return buffers_num_buffers(buffers) > 0 ? &buffers->head->entries[0].buffer + : NULL; } void buffers_destroy(struct buffers *buffers) { - VEC_FOR_EACH(&buffers->buffers, struct buffer_entry * e) { - if (!e->empty) { - buffer_destroy(&e->buffer); - e->empty = true; + struct buffer_chunk *chunk = buffers->head; + while (chunk != NULL) { + for (uint32_t i = 0; i < buffers->chunk_size; ++i) { + if (chunk->entries[i].occupied) { + buffer_destroy(&chunk->entries[i].buffer); + chunk->entries[i].occupied = false; + } } + + struct buffer_chunk *old = chunk; + chunk = chunk->next; + free_chunk(old); } - VEC_DESTROY(&buffers->buffers); VEC_DESTROY(&buffers->add_hooks); VEC_DESTROY(&buffers->remove_hooks); } |
