Coverage Report

Created: 2026-01-09 07:10

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