]> git.proxmox.com Git - libgit2.git/blame - src/util.c
Fixed up memory leaks
[libgit2.git] / src / util.c
CommitLineData
bb742ede
VM
1/*
2 * Copyright (C) 2009-2011 the libgit2 contributors
3 *
4 * This file is part of libgit2, distributed under the GNU GPL v2 with
5 * a Linking Exception. For full terms see the included COPYING file.
6 */
536955f9 7#include <git2.h>
64a47c01 8#include "common.h"
2c4b7707
SP
9#include <stdarg.h>
10#include <stdio.h>
c6e65aca 11#include <ctype.h>
e9c6571d 12#include "posix.h"
64a47c01 13
ae2e4c6a 14#ifdef _MSC_VER
63f91e1c 15# include <Shlwapi.h>
63f91e1c
CMN
16#endif
17
536955f9
VM
18void git_libgit2_version(int *major, int *minor, int *rev)
19{
20 *major = LIBGIT2_VER_MAJOR;
21 *minor = LIBGIT2_VER_MINOR;
22 *rev = LIBGIT2_VER_REVISION;
23}
24
955f9ae9
VM
25void git_strarray_free(git_strarray *array)
26{
27 size_t i;
28 for (i = 0; i < array->count; ++i)
3286c408 29 git__free(array->strings[i]);
955f9ae9 30
3286c408 31 git__free(array->strings);
955f9ae9
VM
32}
33
63f91e1c
CMN
34int git__fnmatch(const char *pattern, const char *name, int flags)
35{
36 int ret;
37
e9c6571d 38 ret = p_fnmatch(pattern, name, flags);
63f91e1c
CMN
39 switch (ret) {
40 case 0:
41 return GIT_SUCCESS;
42 case FNM_NOMATCH:
43 return GIT_ENOMATCH;
44 default:
45 return git__throw(GIT_EOSERR, "Error trying to match path");
46 }
47}
48
fafd4710 49int git__strtol64(int64_t *result, const char *nptr, const char **endptr, int base)
c6e65aca
VM
50{
51 const char *p;
fafd4710 52 int64_t n, nn;
c6e65aca
VM
53 int c, ovfl, v, neg, ndig;
54
55 p = nptr;
56 neg = 0;
57 n = 0;
58 ndig = 0;
59 ovfl = 0;
60
61 /*
62 * White space
63 */
64 while (isspace(*p))
65 p++;
66
67 /*
68 * Sign
69 */
70 if (*p == '-' || *p == '+')
71 if (*p++ == '-')
72 neg = 1;
73
74 /*
75 * Base
76 */
77 if (base == 0) {
78 if (*p != '0')
79 base = 10;
80 else {
81 base = 8;
82 if (p[1] == 'x' || p[1] == 'X') {
83 p += 2;
84 base = 16;
85 }
86 }
87 } else if (base == 16 && *p == '0') {
88 if (p[1] == 'x' || p[1] == 'X')
89 p += 2;
90 } else if (base < 0 || 36 < base)
91 goto Return;
92
93 /*
94 * Non-empty sequence of digits
95 */
96 for (;; p++,ndig++) {
97 c = *p;
98 v = base;
99 if ('0'<=c && c<='9')
100 v = c - '0';
101 else if ('a'<=c && c<='z')
102 v = c - 'a' + 10;
103 else if ('A'<=c && c<='Z')
104 v = c - 'A' + 10;
105 if (v >= base)
106 break;
107 nn = n*base + v;
108 if (nn < n)
109 ovfl = 1;
110 n = nn;
111 }
112
113Return:
114 if (ndig == 0)
33b1d19e 115 return git__throw(GIT_ENOTNUM, "Failed to convert string to long. Not a number");
c6e65aca
VM
116
117 if (endptr)
118 *endptr = p;
119
120 if (ovfl)
33b1d19e 121 return git__throw(GIT_EOVERFLOW, "Failed to convert string to long. Overflow error");
c6e65aca
VM
122
123 *result = neg ? -n : n;
124 return GIT_SUCCESS;
125}
126
fafd4710 127int git__strtol32(int32_t *result, const char *nptr, const char **endptr, int base)
ad196c6a 128{
fafd4710
VM
129 int error = GIT_SUCCESS;
130 int32_t tmp_int;
131 int64_t tmp_long;
ad196c6a 132
133 if ((error = git__strtol64(&tmp_long, nptr, endptr, base)) < GIT_SUCCESS)
134 return error;
135
136 tmp_int = tmp_long & 0xFFFFFFFF;
137 if (tmp_int != tmp_long)
138 return git__throw(GIT_EOVERFLOW, "Failed to convert. '%s' is too large", nptr);
139
140 *result = tmp_int;
141
142 return error;
143}
144
26e74c6a 145void git__strntolower(char *str, size_t len)
0da2c700 146{
26e74c6a 147 size_t i;
0da2c700
VM
148
149 for (i = 0; i < len; ++i) {
3a1c4310 150 str[i] = (char) tolower(str[i]);
0da2c700
VM
151 }
152}
153
154void git__strtolower(char *str)
155{
156 git__strntolower(str, strlen(str));
157}
158
9eb79764
SP
159int git__prefixcmp(const char *str, const char *prefix)
160{
161 for (;;) {
162 char p = *(prefix++), s;
163 if (!p)
164 return 0;
165 if ((s = *(str++)) != p)
166 return s - p;
167 }
168}
169
170int git__suffixcmp(const char *str, const char *suffix)
171{
172 size_t a = strlen(str);
173 size_t b = strlen(suffix);
174 if (a < b)
175 return -1;
176 return strcmp(str + (a - b), suffix);
177}
ced645ea 178
0291b5b7 179char *git__strtok(char **end, const char *sep)
f725931b 180{
0291b5b7 181 char *ptr = *end;
ced645ea 182
0291b5b7
VM
183 while (*ptr && strchr(sep, *ptr))
184 ++ptr;
f725931b 185
0291b5b7
VM
186 if (*ptr) {
187 char *start = ptr;
188 *end = start + 1;
ced645ea 189
0291b5b7
VM
190 while (**end && !strchr(sep, **end))
191 ++*end;
f725931b 192
0291b5b7
VM
193 if (**end) {
194 **end = '\0';
195 ++*end;
196 }
197
198 return start;
199 }
200
201 return NULL;
ced645ea
RJ
202}
203
0e465f97
VM
204void git__hexdump(const char *buffer, size_t len)
205{
206 static const size_t LINE_WIDTH = 16;
207
208 size_t line_count, last_line, i, j;
209 const char *line;
210
211 line_count = (len / LINE_WIDTH);
212 last_line = (len % LINE_WIDTH);
213
214 for (i = 0; i < line_count; ++i) {
215 line = buffer + (i * LINE_WIDTH);
216 for (j = 0; j < LINE_WIDTH; ++j, ++line)
217 printf("%02X ", (unsigned char)*line & 0xFF);
218
219 printf("| ");
220
221 line = buffer + (i * LINE_WIDTH);
222 for (j = 0; j < LINE_WIDTH; ++j, ++line)
223 printf("%c", (*line >= 32 && *line <= 126) ? *line : '.');
224
225 printf("\n");
226 }
227
228 if (last_line > 0) {
229
230 line = buffer + (line_count * LINE_WIDTH);
231 for (j = 0; j < last_line; ++j, ++line)
232 printf("%02X ", (unsigned char)*line & 0xFF);
233
234 for (j = 0; j < (LINE_WIDTH - last_line); ++j)
87d9869f 235 printf(" ");
0e465f97
VM
236
237 printf("| ");
238
239 line = buffer + (line_count * LINE_WIDTH);
240 for (j = 0; j < last_line; ++j, ++line)
241 printf("%c", (*line >= 32 && *line <= 126) ? *line : '.');
242
243 printf("\n");
244 }
245
246 printf("\n");
247}
e0646b38
VM
248
249#ifdef GIT_LEGACY_HASH
250uint32_t git__hash(const void *key, int len, unsigned int seed)
251{
252 const uint32_t m = 0x5bd1e995;
253 const int r = 24;
254 uint32_t h = seed ^ len;
255
256 const unsigned char *data = (const unsigned char *)key;
257
258 while(len >= 4) {
259 uint32_t k = *(uint32_t *)data;
260
932d1baf
KS
261 k *= m;
262 k ^= k >> r;
263 k *= m;
264
265 h *= m;
e0646b38
VM
266 h ^= k;
267
268 data += 4;
269 len -= 4;
270 }
932d1baf 271
e0646b38
VM
272 switch(len) {
273 case 3: h ^= data[2] << 16;
274 case 2: h ^= data[1] << 8;
275 case 1: h ^= data[0];
87d9869f 276 h *= m;
e0646b38
VM
277 };
278
279 h ^= h >> 13;
280 h *= m;
281 h ^= h >> 15;
282
283 return h;
932d1baf 284}
e0646b38
VM
285#else
286/*
287 Cross-platform version of Murmurhash3
288 http://code.google.com/p/smhasher/wiki/MurmurHash3
289 by Austin Appleby (aappleby@gmail.com)
290
291 This code is on the public domain.
292*/
293uint32_t git__hash(const void *key, int len, uint32_t seed)
294{
295
296#define MURMUR_BLOCK() {\
87d9869f
VM
297 k1 *= c1; \
298 k1 = git__rotl(k1,11);\
299 k1 *= c2;\
300 h1 ^= k1;\
301 h1 = h1*3 + 0x52dce729;\
302 c1 = c1*5 + 0x7b7d159c;\
303 c2 = c2*5 + 0x6bce6396;\
e0646b38
VM
304}
305
306 const uint8_t *data = (const uint8_t*)key;
307 const int nblocks = len / 4;
308
309 const uint32_t *blocks = (const uint32_t *)(data + nblocks * 4);
310 const uint8_t *tail = (const uint8_t *)(data + nblocks * 4);
311
312 uint32_t h1 = 0x971e137b ^ seed;
313 uint32_t k1;
314
315 uint32_t c1 = 0x95543787;
316 uint32_t c2 = 0x2ad7eb25;
317
318 int i;
319
320 for (i = -nblocks; i; i++) {
321 k1 = blocks[i];
322 MURMUR_BLOCK();
323 }
324
325 k1 = 0;
326
327 switch(len & 3) {
328 case 3: k1 ^= tail[2] << 16;
329 case 2: k1 ^= tail[1] << 8;
330 case 1: k1 ^= tail[0];
331 MURMUR_BLOCK();
332 }
333
334 h1 ^= len;
335 h1 ^= h1 >> 16;
336 h1 *= 0x85ebca6b;
337 h1 ^= h1 >> 13;
338 h1 *= 0xc2b2ae35;
339 h1 ^= h1 >> 16;
340
341 return h1;
932d1baf 342}
e0646b38 343#endif
c20ffa61 344
de18f276
VM
345/**
346 * A modified `bsearch` from the BSD glibc.
347 *
348 * Copyright (c) 1990 Regents of the University of California.
349 * All rights reserved.
c20ffa61 350 */
de18f276 351void **git__bsearch(const void *key, void **base, size_t nmemb, int (*compar)(const void *, const void *))
c20ffa61 352{
87d9869f
VM
353 int lim, cmp;
354 void **p;
355
356 for (lim = nmemb; lim != 0; lim >>= 1) {
357 p = base + (lim >> 1);
358 cmp = (*compar)(key, *p);
359 if (cmp > 0) { /* key > p: move right */
360 base = p + 1;
361 lim--;
362 } else if (cmp == 0) {
363 return (void **)p;
364 } /* else move left */
365 }
366 return NULL;
c20ffa61
KS
367}
368
d1f34693 369/**
370 * A strcmp wrapper
371 *
372 * We don't want direct pointers to the CRT on Windows, we may
373 * get stdcall conflicts.
374 */
375int git__strcmp_cb(const void *a, const void *b)
376{
377 const char *stra = (const char *)a;
378 const char *strb = (const char *)b;
379
380 return strcmp(stra, strb);
84dd3820 381}