/src/mupdf/thirdparty/extract/src/alloc.c
Line | Count | Source (jump to first uncovered line) |
1 | | #include "extract/alloc.h" |
2 | | |
3 | | #include <assert.h> |
4 | | #include <errno.h> |
5 | | #include <stdlib.h> |
6 | | #include <string.h> |
7 | | |
8 | | |
9 | | struct extract_alloc_t |
10 | | { |
11 | | extract_realloc_fn_t *realloc_fn; |
12 | | extract_caller_context_t *realloc_state; |
13 | | size_t exp_min_alloc_size; |
14 | | extract_alloc_stats_t stats; |
15 | | }; |
16 | | |
17 | | int |
18 | | extract_alloc_create( extract_realloc_fn_t *realloc_fn, |
19 | | void *realloc_state, |
20 | | extract_alloc_t **palloc) |
21 | 0 | { |
22 | 0 | assert(realloc_fn); |
23 | 0 | assert(palloc); |
24 | 0 | *palloc = realloc_fn(realloc_state, NULL /*ptr*/, sizeof(**palloc)); |
25 | 0 | if (!*palloc) { |
26 | 0 | errno = ENOMEM; |
27 | 0 | return -1; |
28 | 0 | } |
29 | 0 | memset(*palloc, 0, sizeof(**palloc)); |
30 | 0 | (*palloc)->realloc_fn = realloc_fn; |
31 | 0 | (*palloc)->realloc_state = realloc_state; |
32 | 0 | (*palloc)->exp_min_alloc_size = 0; |
33 | 0 | return 0; |
34 | 0 | } |
35 | | |
36 | | void extract_alloc_destroy(extract_alloc_t **palloc) |
37 | 0 | { |
38 | 0 | if (!*palloc) return; |
39 | 0 | (*palloc)->realloc_fn((*palloc)->realloc_state, *palloc, 0 /*newsize*/); |
40 | 0 | *palloc = NULL; |
41 | 0 | } |
42 | | |
43 | | extract_alloc_stats_t *extract_alloc_stats(extract_alloc_t *alloc) |
44 | 0 | { |
45 | 0 | return &alloc->stats; |
46 | 0 | } |
47 | | |
48 | | static size_t round_up(extract_alloc_t *alloc, size_t n) |
49 | 0 | { |
50 | 0 | size_t ret; |
51 | |
|
52 | 0 | if (alloc == NULL || alloc->exp_min_alloc_size || n == 0) |
53 | 0 | return n; |
54 | | |
55 | | /* Round up to power of two. */ |
56 | 0 | ret = alloc->exp_min_alloc_size; |
57 | 0 | while (ret < n) { |
58 | 0 | size_t ret_old = ret; |
59 | 0 | ret *= 2; |
60 | 0 | if (ret <= ret_old) |
61 | 0 | ret = n; |
62 | 0 | } |
63 | |
|
64 | 0 | return ret; |
65 | 0 | } |
66 | | |
67 | | int (extract_malloc)(extract_alloc_t *alloc, void **pptr, size_t size) |
68 | 0 | { |
69 | 0 | void *p; |
70 | |
|
71 | 0 | size = round_up(alloc, size); |
72 | 0 | p = (alloc) ? alloc->realloc_fn(alloc->realloc_state, NULL, size) : malloc(size); |
73 | 0 | *pptr = p; |
74 | 0 | if (!p && size) |
75 | 0 | { |
76 | 0 | if (alloc) errno = ENOMEM; |
77 | 0 | return -1; |
78 | 0 | } |
79 | 0 | if (alloc) alloc->stats.num_malloc += 1; |
80 | 0 | return 0; |
81 | 0 | } |
82 | | |
83 | | int (extract_realloc)(extract_alloc_t *alloc, void **pptr, size_t newsize) |
84 | 0 | { |
85 | 0 | void *p = (alloc) ? alloc->realloc_fn(alloc->realloc_state, *pptr, newsize) : realloc(*pptr, newsize); |
86 | 0 | if (!p && newsize) |
87 | 0 | { |
88 | 0 | if (alloc) errno = ENOMEM; |
89 | 0 | return -1; |
90 | 0 | } |
91 | 0 | *pptr = p; |
92 | 0 | if (alloc) alloc->stats.num_realloc += 1; |
93 | 0 | return 0; |
94 | 0 | } |
95 | | |
96 | | int (extract_realloc2)(extract_alloc_t *alloc, void **pptr, size_t oldsize, size_t newsize) |
97 | 0 | { |
98 | | /* We ignore <oldsize> if <ptr> is NULL - allows callers to not worry |
99 | | about edge cases e.g. with strlen+1. */ |
100 | 0 | oldsize = (*pptr) ? round_up(alloc, oldsize) : 0; |
101 | 0 | newsize = round_up(alloc, newsize); |
102 | 0 | if (newsize == oldsize) return 0; |
103 | 0 | return (extract_realloc)(alloc, pptr, newsize); |
104 | 0 | } |
105 | | |
106 | | void (extract_free)(extract_alloc_t *alloc, void **pptr) |
107 | 0 | { |
108 | 0 | if (alloc) |
109 | 0 | (void)alloc->realloc_fn(alloc->realloc_state, *pptr, 0); |
110 | 0 | else |
111 | 0 | free(*pptr); |
112 | 0 | *pptr = NULL; |
113 | 0 | if (alloc) alloc->stats.num_free += 1; |
114 | 0 | } |
115 | | |
116 | | void extract_alloc_exp_min(extract_alloc_t *alloc, size_t size) |
117 | 0 | { |
118 | 0 | alloc->exp_min_alloc_size = size; |
119 | 0 | } |