| 1 | #include "mupdf/fitz.h" |
| 2 | |
| 3 | #include <string.h> |
| 4 | #include <stdio.h> |
| 5 | |
| 6 | typedef struct fz_pool_node_s fz_pool_node; |
| 7 | |
| 8 | #define POOL_SIZE (4<<10) /* default size of pool blocks */ |
| 9 | #define POOL_SELF (1<<10) /* size where allocs are put into their own blocks */ |
| 10 | |
| 11 | struct fz_pool_s |
| 12 | { |
| 13 | fz_pool_node *head, *tail; |
| 14 | char *pos, *end; |
| 15 | }; |
| 16 | |
| 17 | struct fz_pool_node_s |
| 18 | { |
| 19 | fz_pool_node *next; |
| 20 | char mem[1]; |
| 21 | }; |
| 22 | |
| 23 | fz_pool *fz_new_pool(fz_context *ctx) |
| 24 | { |
| 25 | fz_pool *pool; |
| 26 | fz_pool_node *node = NULL; |
| 27 | |
| 28 | pool = fz_malloc_struct(ctx, fz_pool); |
| 29 | fz_try(ctx) |
| 30 | { |
| 31 | node = fz_calloc(ctx, offsetof(fz_pool_node, mem) + POOL_SIZE, 1); |
| 32 | pool->head = pool->tail = node; |
| 33 | pool->pos = node->mem; |
| 34 | pool->end = node->mem + POOL_SIZE; |
| 35 | } |
| 36 | fz_catch(ctx) |
| 37 | { |
| 38 | fz_free(ctx, pool); |
| 39 | fz_rethrow(ctx); |
| 40 | } |
| 41 | |
| 42 | return pool; |
| 43 | } |
| 44 | |
| 45 | static void *fz_pool_alloc_oversize(fz_context *ctx, fz_pool *pool, size_t size) |
| 46 | { |
| 47 | fz_pool_node *node; |
| 48 | |
| 49 | /* link in memory at the head of the list */ |
| 50 | node = fz_calloc(ctx, offsetof(fz_pool_node, mem) + size, 1); |
| 51 | node->next = pool->head; |
| 52 | pool->head = node; |
| 53 | |
| 54 | return node->mem; |
| 55 | } |
| 56 | |
| 57 | void *fz_pool_alloc(fz_context *ctx, fz_pool *pool, size_t size) |
| 58 | { |
| 59 | char *ptr; |
| 60 | |
| 61 | if (size >= POOL_SELF) |
| 62 | return fz_pool_alloc_oversize(ctx, pool, size); |
| 63 | |
| 64 | /* round size to pointer alignment (we don't expect to use doubles) */ |
| 65 | size = ((size + sizeof(void*) - 1) / sizeof(void*)) * sizeof(void*); |
| 66 | |
| 67 | if (pool->pos + size > pool->end) |
| 68 | { |
| 69 | fz_pool_node *node = fz_calloc(ctx, offsetof(fz_pool_node, mem) + POOL_SIZE, 1); |
| 70 | pool->tail = pool->tail->next = node; |
| 71 | pool->pos = node->mem; |
| 72 | pool->end = node->mem + POOL_SIZE; |
| 73 | } |
| 74 | ptr = pool->pos; |
| 75 | pool->pos += size; |
| 76 | return ptr; |
| 77 | } |
| 78 | |
| 79 | char *fz_pool_strdup(fz_context *ctx, fz_pool *pool, const char *s) |
| 80 | { |
| 81 | size_t n = strlen(s) + 1; |
| 82 | char *p = fz_pool_alloc(ctx, pool, n); |
| 83 | memcpy(p, s, n); |
| 84 | return p; |
| 85 | } |
| 86 | |
| 87 | void fz_drop_pool(fz_context *ctx, fz_pool *pool) |
| 88 | { |
| 89 | fz_pool_node *node; |
| 90 | |
| 91 | if (!pool) |
| 92 | return; |
| 93 | |
| 94 | node = pool->head; |
| 95 | while (node) |
| 96 | { |
| 97 | fz_pool_node *next = node->next; |
| 98 | fz_free(ctx, node); |
| 99 | node = next; |
| 100 | } |
| 101 | fz_free(ctx, pool); |
| 102 | } |
| 103 | |