]> git.proxmox.com Git - libgit2.git/blame - src/pool.c
pool: Handle 32 bit systems
[libgit2.git] / src / pool.c
CommitLineData
2bc8fa02 1#include "pool.h"
62e562f9 2#include "posix.h"
2bc8fa02
RB
3#ifndef GIT_WIN32
4#include <unistd.h>
5#endif
6
7struct 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 14static void *pool_alloc_page(git_pool *pool, uint32_t size);
14bedad9 15
1e5e02b4
VM
16uint32_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
31void 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
44void 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;
19fa2bc1 54 pool->items = 0;
2bc8fa02
RB
55}
56
19fa2bc1
RB
57void git_pool_swap(git_pool *a, git_pool *b)
58{
59 git_pool temp;
60
61 if (a == b)
62 return;
63
64 memcpy(&temp, a, sizeof(temp));
65 memcpy(a, b, sizeof(temp));
66 memcpy(b, &temp, sizeof(temp));
67}
68
19fa2bc1 69static void *pool_alloc_page(git_pool *pool, uint32_t size)
2bc8fa02
RB
70{
71 git_pool_page *page;
1e5e02b4 72 const uint32_t new_page_size = (size <= pool->page_size) ? pool->page_size : size;
f1453c59 73 size_t alloc_size;
2bc8fa02 74
f1453c59
ET
75 if (GIT_ADD_SIZET_OVERFLOW(&alloc_size, new_page_size, sizeof(git_pool_page)) ||
76 !(page = git__calloc(1, alloc_size)))
19fa2bc1 77 return NULL;
2bc8fa02 78
1e5e02b4 79 page->size = new_page_size;
f1453c59 80 page->avail = new_page_size - size;
1e5e02b4 81 page->next = pool->pages;
2bc8fa02 82
1e5e02b4 83 pool->pages = page;
19fa2bc1 84 pool->items++;
2bc8fa02 85
19fa2bc1 86 return page->data;
2bc8fa02
RB
87}
88
19fa2bc1 89void *git_pool_malloc(git_pool *pool, uint32_t items)
2bc8fa02 90{
1e5e02b4 91 const uint32_t size = items * pool->item_size;
2bc8fa02 92
1e5e02b4
VM
93 git_pool_page *page = pool->pages;
94 void *ptr = NULL;
2bc8fa02 95
1e5e02b4 96 if (!page || page->avail < size)
19fa2bc1
RB
97 return pool_alloc_page(pool, size);
98
1e5e02b4
VM
99 ptr = &page->data[page->size - page->avail];
100 page->avail -= size;
19fa2bc1 101 pool->items++;
2bc8fa02 102
19fa2bc1 103 return ptr;
2bc8fa02
RB
104}
105
106char *git_pool_strndup(git_pool *pool, const char *str, size_t n)
107{
ce33645f 108 char *ptr = NULL;
2bc8fa02
RB
109
110 assert(pool && str && pool->item_size == sizeof(char));
111
437f7d69
VM
112 if ((uint32_t)(n + 1) < n)
113 return NULL;
114
821f6bc7 115 if ((ptr = git_pool_malloc(pool, (uint32_t)(n + 1))) != NULL) {
2bc8fa02 116 memcpy(ptr, str, n);
ce33645f 117 ptr[n] = '\0';
19fa2bc1 118 }
ce33645f 119
2bc8fa02
RB
120 return ptr;
121}
122
123char *git_pool_strdup(git_pool *pool, const char *str)
124{
125 assert(pool && str && pool->item_size == sizeof(char));
19fa2bc1
RB
126 return git_pool_strndup(pool, str, strlen(str));
127}
128
71d27358
RB
129char *git_pool_strdup_safe(git_pool *pool, const char *str)
130{
ce33645f 131 return str ? git_pool_strdup(pool, str) : NULL;
71d27358
RB
132}
133
19fa2bc1
RB
134char *git_pool_strcat(git_pool *pool, const char *a, const char *b)
135{
136 void *ptr;
137 size_t len_a, len_b;
138
9ae4ad2d 139 assert(pool && pool->item_size == sizeof(char));
19fa2bc1
RB
140
141 len_a = a ? strlen(a) : 0;
142 len_b = b ? strlen(b) : 0;
143
821f6bc7 144 if ((ptr = git_pool_malloc(pool, (uint32_t)(len_a + len_b + 1))) != NULL) {
19fa2bc1
RB
145 if (len_a)
146 memcpy(ptr, a, len_a);
147 if (len_b)
148 memcpy(((char *)ptr) + len_a, b, len_b);
149 *(((char *)ptr) + len_a + len_b) = '\0';
150 }
19fa2bc1 151 return ptr;
2bc8fa02
RB
152}
153
2bc8fa02
RB
154uint32_t git_pool__open_pages(git_pool *pool)
155{
156 uint32_t ct = 0;
157 git_pool_page *scan;
1e5e02b4 158 for (scan = pool->pages; scan != NULL; scan = scan->next) ct++;
2bc8fa02
RB
159 return ct;
160}
161
162bool git_pool__ptr_in_pool(git_pool *pool, void *ptr)
163{
164 git_pool_page *scan;
1e5e02b4 165 for (scan = pool->pages; scan != NULL; scan = scan->next)
821f6bc7
RB
166 if ((void *)scan->data <= ptr &&
167 (void *)(((char *)scan->data) + scan->size) > ptr)
2bc8fa02
RB
168 return true;
169 return false;
170}