The seventh batch
[git.git] / reftable / basics.c
blob3b5ea27bbdc56ed9cc3d475a649a26d9f294e636
1 /*
2 Copyright 2020 Google LLC
4 Use of this source code is governed by a BSD-style
5 license that can be found in the LICENSE file or at
6 https://developers.google.com/open-source/licenses/bsd
7 */
9 #define REFTABLE_ALLOW_BANNED_ALLOCATORS
10 #include "basics.h"
11 #include "reftable-basics.h"
12 #include "reftable-error.h"
14 static void *(*reftable_malloc_ptr)(size_t sz);
15 static void *(*reftable_realloc_ptr)(void *, size_t);
16 static void (*reftable_free_ptr)(void *);
18 void *reftable_malloc(size_t sz)
20 if (!sz)
21 return NULL;
22 if (reftable_malloc_ptr)
23 return (*reftable_malloc_ptr)(sz);
24 return malloc(sz);
27 void *reftable_realloc(void *p, size_t sz)
29 if (!sz) {
30 reftable_free(p);
31 return NULL;
34 if (reftable_realloc_ptr)
35 return (*reftable_realloc_ptr)(p, sz);
36 return realloc(p, sz);
39 void reftable_free(void *p)
41 if (reftable_free_ptr)
42 reftable_free_ptr(p);
43 else
44 free(p);
47 void *reftable_calloc(size_t nelem, size_t elsize)
49 void *p;
51 if (nelem && elsize > SIZE_MAX / nelem)
52 return NULL;
54 p = reftable_malloc(nelem * elsize);
55 if (!p)
56 return NULL;
58 memset(p, 0, nelem * elsize);
59 return p;
62 char *reftable_strdup(const char *str)
64 size_t len = strlen(str);
65 char *result = reftable_malloc(len + 1);
66 if (!result)
67 return NULL;
68 memcpy(result, str, len + 1);
69 return result;
72 void reftable_set_alloc(void *(*malloc)(size_t),
73 void *(*realloc)(void *, size_t), void (*free)(void *))
75 reftable_malloc_ptr = malloc;
76 reftable_realloc_ptr = realloc;
77 reftable_free_ptr = free;
80 void reftable_buf_init(struct reftable_buf *buf)
82 struct reftable_buf empty = REFTABLE_BUF_INIT;
83 *buf = empty;
86 void reftable_buf_release(struct reftable_buf *buf)
88 reftable_free(buf->buf);
89 reftable_buf_init(buf);
92 void reftable_buf_reset(struct reftable_buf *buf)
94 if (buf->alloc) {
95 buf->len = 0;
96 buf->buf[0] = '\0';
100 int reftable_buf_setlen(struct reftable_buf *buf, size_t len)
102 if (len > buf->len)
103 return -1;
104 if (len == buf->len)
105 return 0;
106 buf->buf[len] = '\0';
107 buf->len = len;
108 return 0;
111 int reftable_buf_cmp(const struct reftable_buf *a, const struct reftable_buf *b)
113 size_t len = a->len < b->len ? a->len : b->len;
114 if (len) {
115 int cmp = memcmp(a->buf, b->buf, len);
116 if (cmp)
117 return cmp;
119 return a->len < b->len ? -1 : a->len != b->len;
122 int reftable_buf_add(struct reftable_buf *buf, const void *data, size_t len)
124 size_t newlen = buf->len + len;
126 if (newlen + 1 > buf->alloc) {
127 if (REFTABLE_ALLOC_GROW(buf->buf, newlen + 1, buf->alloc))
128 return REFTABLE_OUT_OF_MEMORY_ERROR;
131 memcpy(buf->buf + buf->len, data, len);
132 buf->buf[newlen] = '\0';
133 buf->len = newlen;
135 return 0;
138 int reftable_buf_addstr(struct reftable_buf *buf, const char *s)
140 return reftable_buf_add(buf, s, strlen(s));
143 char *reftable_buf_detach(struct reftable_buf *buf)
145 char *result = buf->buf;
146 reftable_buf_init(buf);
147 return result;
150 void put_be24(uint8_t *out, uint32_t i)
152 out[0] = (uint8_t)((i >> 16) & 0xff);
153 out[1] = (uint8_t)((i >> 8) & 0xff);
154 out[2] = (uint8_t)(i & 0xff);
157 uint32_t get_be24(uint8_t *in)
159 return (uint32_t)(in[0]) << 16 | (uint32_t)(in[1]) << 8 |
160 (uint32_t)(in[2]);
163 void put_be16(uint8_t *out, uint16_t i)
165 out[0] = (uint8_t)((i >> 8) & 0xff);
166 out[1] = (uint8_t)(i & 0xff);
169 size_t binsearch(size_t sz, int (*f)(size_t k, void *args), void *args)
171 size_t lo = 0;
172 size_t hi = sz;
174 /* Invariants:
176 * (hi == sz) || f(hi) == true
177 * (lo == 0 && f(0) == true) || fi(lo) == false
179 while (hi - lo > 1) {
180 size_t mid = lo + (hi - lo) / 2;
181 int ret = f(mid, args);
182 if (ret < 0)
183 return sz;
185 if (ret > 0)
186 hi = mid;
187 else
188 lo = mid;
191 if (lo)
192 return hi;
194 return f(0, args) ? 0 : 1;
197 void free_names(char **a)
199 char **p;
200 if (!a) {
201 return;
203 for (p = a; *p; p++) {
204 reftable_free(*p);
206 reftable_free(a);
209 size_t names_length(const char **names)
211 const char **p = names;
212 while (*p)
213 p++;
214 return p - names;
217 char **parse_names(char *buf, int size)
219 char **names = NULL;
220 size_t names_cap = 0;
221 size_t names_len = 0;
222 char *p = buf;
223 char *end = buf + size;
225 while (p < end) {
226 char *next = strchr(p, '\n');
227 if (next && next < end) {
228 *next = 0;
229 } else {
230 next = end;
232 if (p < next) {
233 if (REFTABLE_ALLOC_GROW(names, names_len + 1,
234 names_cap))
235 goto err;
237 names[names_len] = reftable_strdup(p);
238 if (!names[names_len++])
239 goto err;
241 p = next + 1;
244 if (REFTABLE_ALLOC_GROW(names, names_len + 1, names_cap))
245 goto err;
246 names[names_len] = NULL;
248 return names;
250 err:
251 for (size_t i = 0; i < names_len; i++)
252 reftable_free(names[i]);
253 reftable_free(names);
254 return NULL;
257 int names_equal(const char **a, const char **b)
259 size_t i = 0;
260 for (; a[i] && b[i]; i++)
261 if (strcmp(a[i], b[i]))
262 return 0;
263 return a[i] == b[i];
266 size_t common_prefix_size(struct reftable_buf *a, struct reftable_buf *b)
268 size_t p = 0;
269 for (; p < a->len && p < b->len; p++)
270 if (a->buf[p] != b->buf[p])
271 break;
272 return p;
275 uint32_t hash_size(enum reftable_hash id)
277 if (!id)
278 return REFTABLE_HASH_SIZE_SHA1;
279 switch (id) {
280 case REFTABLE_HASH_SHA1:
281 return REFTABLE_HASH_SIZE_SHA1;
282 case REFTABLE_HASH_SHA256:
283 return REFTABLE_HASH_SIZE_SHA256;
285 abort();