Git fork
at reftables-rust 278 lines 5.1 kB view raw
1/* 2 * Copyright 2020 Google LLC 3 * 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 */ 8 9#define REFTABLE_ALLOW_BANNED_ALLOCATORS 10#include "basics.h" 11#include "reftable-basics.h" 12#include "reftable-error.h" 13 14static void *(*reftable_malloc_ptr)(size_t sz); 15static void *(*reftable_realloc_ptr)(void *, size_t); 16static void (*reftable_free_ptr)(void *); 17 18void *reftable_malloc(size_t sz) 19{ 20 if (!sz) 21 return NULL; 22 if (reftable_malloc_ptr) 23 return (*reftable_malloc_ptr)(sz); 24 return malloc(sz); 25} 26 27void *reftable_realloc(void *p, size_t sz) 28{ 29 if (!sz) { 30 reftable_free(p); 31 return NULL; 32 } 33 34 if (reftable_realloc_ptr) 35 return (*reftable_realloc_ptr)(p, sz); 36 return realloc(p, sz); 37} 38 39void reftable_free(void *p) 40{ 41 if (reftable_free_ptr) 42 reftable_free_ptr(p); 43 else 44 free(p); 45} 46 47void *reftable_calloc(size_t nelem, size_t elsize) 48{ 49 void *p; 50 51 if (nelem && elsize > SIZE_MAX / nelem) 52 return NULL; 53 54 p = reftable_malloc(nelem * elsize); 55 if (!p) 56 return NULL; 57 58 memset(p, 0, nelem * elsize); 59 return p; 60} 61 62char *reftable_strdup(const char *str) 63{ 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; 70} 71 72void reftable_set_alloc(void *(*malloc)(size_t), 73 void *(*realloc)(void *, size_t), void (*free)(void *)) 74{ 75 reftable_malloc_ptr = malloc; 76 reftable_realloc_ptr = realloc; 77 reftable_free_ptr = free; 78} 79 80void reftable_buf_init(struct reftable_buf *buf) 81{ 82 struct reftable_buf empty = REFTABLE_BUF_INIT; 83 *buf = empty; 84} 85 86void reftable_buf_release(struct reftable_buf *buf) 87{ 88 reftable_free(buf->buf); 89 reftable_buf_init(buf); 90} 91 92void reftable_buf_reset(struct reftable_buf *buf) 93{ 94 if (buf->alloc) { 95 buf->len = 0; 96 buf->buf[0] = '\0'; 97 } 98} 99 100int reftable_buf_setlen(struct reftable_buf *buf, size_t len) 101{ 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; 109} 110 111int reftable_buf_cmp(const struct reftable_buf *a, const struct reftable_buf *b) 112{ 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; 118 } 119 return a->len < b->len ? -1 : a->len != b->len; 120} 121 122int reftable_buf_add(struct reftable_buf *buf, const void *data, size_t len) 123{ 124 size_t newlen = buf->len + len; 125 126 if (newlen + 1 > buf->alloc) { 127 if (REFTABLE_ALLOC_GROW(buf->buf, newlen + 1, buf->alloc)) 128 return REFTABLE_OUT_OF_MEMORY_ERROR; 129 } 130 131 memcpy(buf->buf + buf->len, data, len); 132 buf->buf[newlen] = '\0'; 133 buf->len = newlen; 134 135 return 0; 136} 137 138int reftable_buf_addstr(struct reftable_buf *buf, const char *s) 139{ 140 return reftable_buf_add(buf, s, strlen(s)); 141} 142 143char *reftable_buf_detach(struct reftable_buf *buf) 144{ 145 char *result = buf->buf; 146 reftable_buf_init(buf); 147 return result; 148} 149 150size_t binsearch(size_t sz, int (*f)(size_t k, void *args), void *args) 151{ 152 size_t lo = 0; 153 size_t hi = sz; 154 155 /* Invariants: 156 * 157 * (hi == sz) || f(hi) == true 158 * (lo == 0 && f(0) == true) || fi(lo) == false 159 */ 160 while (hi - lo > 1) { 161 size_t mid = lo + (hi - lo) / 2; 162 int ret = f(mid, args); 163 if (ret < 0) 164 return sz; 165 166 if (ret > 0) 167 hi = mid; 168 else 169 lo = mid; 170 } 171 172 if (lo) 173 return hi; 174 175 return f(0, args) ? 0 : 1; 176} 177 178void free_names(char **a) 179{ 180 char **p; 181 if (!a) { 182 return; 183 } 184 for (p = a; *p; p++) { 185 reftable_free(*p); 186 } 187 reftable_free(a); 188} 189 190size_t names_length(const char **names) 191{ 192 const char **p = names; 193 while (*p) 194 p++; 195 return p - names; 196} 197 198int parse_names(char *buf, int size, char ***out) 199{ 200 char **names = NULL; 201 size_t names_cap = 0; 202 size_t names_len = 0; 203 char *p = buf; 204 char *end = buf + size; 205 int err = 0; 206 207 while (p < end) { 208 char *next = strchr(p, '\n'); 209 if (!next) { 210 err = REFTABLE_FORMAT_ERROR; 211 goto done; 212 } else if (next < end) { 213 *next = '\0'; 214 } else { 215 next = end; 216 } 217 218 if (p < next) { 219 if (REFTABLE_ALLOC_GROW(names, names_len + 1, 220 names_cap)) { 221 err = REFTABLE_OUT_OF_MEMORY_ERROR; 222 goto done; 223 } 224 225 names[names_len] = reftable_strdup(p); 226 if (!names[names_len++]) { 227 err = REFTABLE_OUT_OF_MEMORY_ERROR; 228 goto done; 229 } 230 } 231 p = next + 1; 232 } 233 234 if (REFTABLE_ALLOC_GROW(names, names_len + 1, names_cap)) { 235 err = REFTABLE_OUT_OF_MEMORY_ERROR; 236 goto done; 237 } 238 names[names_len] = NULL; 239 240 *out = names; 241 return 0; 242done: 243 for (size_t i = 0; i < names_len; i++) 244 reftable_free(names[i]); 245 reftable_free(names); 246 return err; 247} 248 249int names_equal(const char **a, const char **b) 250{ 251 size_t i = 0; 252 for (; a[i] && b[i]; i++) 253 if (strcmp(a[i], b[i])) 254 return 0; 255 return a[i] == b[i]; 256} 257 258size_t common_prefix_size(struct reftable_buf *a, struct reftable_buf *b) 259{ 260 size_t p = 0; 261 for (; p < a->len && p < b->len; p++) 262 if (a->buf[p] != b->buf[p]) 263 break; 264 return p; 265} 266 267uint32_t hash_size(enum reftable_hash id) 268{ 269 if (!id) 270 return REFTABLE_HASH_SIZE_SHA1; 271 switch (id) { 272 case REFTABLE_HASH_SHA1: 273 return REFTABLE_HASH_SIZE_SHA1; 274 case REFTABLE_HASH_SHA256: 275 return REFTABLE_HASH_SIZE_SHA256; 276 } 277 abort(); 278}