]>
Commit | Line | Data |
---|---|---|
2bc8fa02 | 1 | #include "pool.h" |
62e562f9 | 2 | #include "posix.h" |
2bc8fa02 RB |
3 | #ifndef GIT_WIN32 |
4 | #include <unistd.h> | |
5 | #endif | |
6 | ||
7 | struct git_pool_page { | |
8 | git_pool_page *next; | |
9 | uint32_t size; | |
10 | uint32_t avail; | |
1e5e02b4 | 11 | char data[GIT_FLEX_ARRAY]; |
2bc8fa02 RB |
12 | }; |
13 | ||
1e5e02b4 | 14 | static void *pool_alloc_page(git_pool *pool, uint32_t size); |
14bedad9 | 15 | |
1e5e02b4 VM |
16 | uint32_t git_pool__system_page_size(void) |
17 | { | |
18 | static uint32_t size = 0; | |
2bc8fa02 | 19 | |
1e5e02b4 VM |
20 | if (!size) { |
21 | size_t page_size; | |
22 | if (git__page_size(&page_size) < 0) | |
23 | page_size = 4096; | |
410efda8 VM |
24 | /* allow space for malloc overhead */ |
25 | size = page_size - (2 * sizeof(void *)) - sizeof(git_pool_page); | |
1e5e02b4 | 26 | } |
2bc8fa02 | 27 | |
1e5e02b4 VM |
28 | return size; |
29 | } | |
30 | ||
31 | void git_pool_init(git_pool *pool, uint32_t item_size) | |
2bc8fa02 | 32 | { |
1e5e02b4 | 33 | const uint32_t align_size = sizeof(void *) - 1; |
2bc8fa02 RB |
34 | assert(pool); |
35 | ||
1e5e02b4 VM |
36 | if (item_size > 1) |
37 | item_size = (item_size + align_size) & ~align_size; | |
2bc8fa02 RB |
38 | |
39 | memset(pool, 0, sizeof(git_pool)); | |
40 | pool->item_size = item_size; | |
1e5e02b4 | 41 | pool->page_size = git_pool__system_page_size(); |
2bc8fa02 RB |
42 | } |
43 | ||
44 | void git_pool_clear(git_pool *pool) | |
45 | { | |
46 | git_pool_page *scan, *next; | |
47 | ||
1e5e02b4 | 48 | for (scan = pool->pages; scan != NULL; scan = next) { |
2bc8fa02 RB |
49 | next = scan->next; |
50 | git__free(scan); | |
51 | } | |
2bc8fa02 | 52 | |
1e5e02b4 | 53 | pool->pages = NULL; |
2bc8fa02 RB |
54 | } |
55 | ||
19fa2bc1 RB |
56 | void git_pool_swap(git_pool *a, git_pool *b) |
57 | { | |
58 | git_pool temp; | |
59 | ||
60 | if (a == b) | |
61 | return; | |
62 | ||
63 | memcpy(&temp, a, sizeof(temp)); | |
64 | memcpy(a, b, sizeof(temp)); | |
65 | memcpy(b, &temp, sizeof(temp)); | |
66 | } | |
67 | ||
19fa2bc1 | 68 | static void *pool_alloc_page(git_pool *pool, uint32_t size) |
2bc8fa02 RB |
69 | { |
70 | git_pool_page *page; | |
1e5e02b4 | 71 | const uint32_t new_page_size = (size <= pool->page_size) ? pool->page_size : size; |
f1453c59 | 72 | size_t alloc_size; |
2bc8fa02 | 73 | |
f1453c59 | 74 | if (GIT_ADD_SIZET_OVERFLOW(&alloc_size, new_page_size, sizeof(git_pool_page)) || |
d3416dfe | 75 | !(page = git__malloc(alloc_size))) |
19fa2bc1 | 76 | return NULL; |
2bc8fa02 | 77 | |
1e5e02b4 | 78 | page->size = new_page_size; |
f1453c59 | 79 | page->avail = new_page_size - size; |
1e5e02b4 | 80 | page->next = pool->pages; |
2bc8fa02 | 81 | |
1e5e02b4 | 82 | pool->pages = page; |
2bc8fa02 | 83 | |
19fa2bc1 | 84 | return page->data; |
2bc8fa02 RB |
85 | } |
86 | ||
d3416dfe | 87 | static void *pool_alloc(git_pool *pool, uint32_t size) |
2bc8fa02 | 88 | { |
1e5e02b4 VM |
89 | git_pool_page *page = pool->pages; |
90 | void *ptr = NULL; | |
2bc8fa02 | 91 | |
1e5e02b4 | 92 | if (!page || page->avail < size) |
19fa2bc1 RB |
93 | return pool_alloc_page(pool, size); |
94 | ||
1e5e02b4 VM |
95 | ptr = &page->data[page->size - page->avail]; |
96 | page->avail -= size; | |
2bc8fa02 | 97 | |
19fa2bc1 | 98 | return ptr; |
2bc8fa02 RB |
99 | } |
100 | ||
d3416dfe VM |
101 | void *git_pool_malloc(git_pool *pool, uint32_t items) |
102 | { | |
103 | const uint32_t size = items * pool->item_size; | |
104 | return pool_alloc(pool, size); | |
105 | } | |
106 | ||
107 | void *git_pool_mallocz(git_pool *pool, uint32_t items) | |
108 | { | |
109 | const uint32_t size = items * pool->item_size; | |
110 | void *ptr = pool_alloc(pool, size); | |
111 | if (ptr) | |
112 | memset(ptr, 0x0, size); | |
113 | return ptr; | |
114 | } | |
115 | ||
2bc8fa02 RB |
116 | char *git_pool_strndup(git_pool *pool, const char *str, size_t n) |
117 | { | |
ce33645f | 118 | char *ptr = NULL; |
2bc8fa02 RB |
119 | |
120 | assert(pool && str && pool->item_size == sizeof(char)); | |
121 | ||
437f7d69 VM |
122 | if ((uint32_t)(n + 1) < n) |
123 | return NULL; | |
124 | ||
821f6bc7 | 125 | if ((ptr = git_pool_malloc(pool, (uint32_t)(n + 1))) != NULL) { |
2bc8fa02 | 126 | memcpy(ptr, str, n); |
ce33645f | 127 | ptr[n] = '\0'; |
19fa2bc1 | 128 | } |
ce33645f | 129 | |
2bc8fa02 RB |
130 | return ptr; |
131 | } | |
132 | ||
133 | char *git_pool_strdup(git_pool *pool, const char *str) | |
134 | { | |
135 | assert(pool && str && pool->item_size == sizeof(char)); | |
19fa2bc1 RB |
136 | return git_pool_strndup(pool, str, strlen(str)); |
137 | } | |
138 | ||
71d27358 RB |
139 | char *git_pool_strdup_safe(git_pool *pool, const char *str) |
140 | { | |
ce33645f | 141 | return str ? git_pool_strdup(pool, str) : NULL; |
71d27358 RB |
142 | } |
143 | ||
19fa2bc1 RB |
144 | char *git_pool_strcat(git_pool *pool, const char *a, const char *b) |
145 | { | |
146 | void *ptr; | |
147 | size_t len_a, len_b; | |
148 | ||
9ae4ad2d | 149 | assert(pool && pool->item_size == sizeof(char)); |
19fa2bc1 RB |
150 | |
151 | len_a = a ? strlen(a) : 0; | |
152 | len_b = b ? strlen(b) : 0; | |
153 | ||
821f6bc7 | 154 | if ((ptr = git_pool_malloc(pool, (uint32_t)(len_a + len_b + 1))) != NULL) { |
19fa2bc1 RB |
155 | if (len_a) |
156 | memcpy(ptr, a, len_a); | |
157 | if (len_b) | |
158 | memcpy(((char *)ptr) + len_a, b, len_b); | |
159 | *(((char *)ptr) + len_a + len_b) = '\0'; | |
160 | } | |
19fa2bc1 | 161 | return ptr; |
2bc8fa02 RB |
162 | } |
163 | ||
2bc8fa02 RB |
164 | uint32_t git_pool__open_pages(git_pool *pool) |
165 | { | |
166 | uint32_t ct = 0; | |
167 | git_pool_page *scan; | |
1e5e02b4 | 168 | for (scan = pool->pages; scan != NULL; scan = scan->next) ct++; |
2bc8fa02 RB |
169 | return ct; |
170 | } | |
171 | ||
172 | bool git_pool__ptr_in_pool(git_pool *pool, void *ptr) | |
173 | { | |
174 | git_pool_page *scan; | |
1e5e02b4 | 175 | for (scan = pool->pages; scan != NULL; scan = scan->next) |
821f6bc7 RB |
176 | if ((void *)scan->data <= ptr && |
177 | (void *)(((char *)scan->data) + scan->size) > ptr) | |
2bc8fa02 RB |
178 | return true; |
179 | return false; | |
180 | } |