]> git.proxmox.com Git - libgit2.git/blame - src/util.c
Tabify everything
[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)
29 free(array->strings[i]);
30
31 free(array->strings);
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
c6e65aca
VM
49int git__strtol32(long *result, const char *nptr, const char **endptr, int base)
50{
51 const char *p;
52 long n, nn;
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
26e74c6a 127void git__strntolower(char *str, size_t len)
0da2c700 128{
26e74c6a 129 size_t i;
0da2c700
VM
130
131 for (i = 0; i < len; ++i) {
3a1c4310 132 str[i] = (char) tolower(str[i]);
0da2c700
VM
133 }
134}
135
136void git__strtolower(char *str)
137{
138 git__strntolower(str, strlen(str));
139}
140
9eb79764
SP
141int git__prefixcmp(const char *str, const char *prefix)
142{
143 for (;;) {
144 char p = *(prefix++), s;
145 if (!p)
146 return 0;
147 if ((s = *(str++)) != p)
148 return s - p;
149 }
150}
151
152int git__suffixcmp(const char *str, const char *suffix)
153{
154 size_t a = strlen(str);
155 size_t b = strlen(suffix);
156 if (a < b)
157 return -1;
158 return strcmp(str + (a - b), suffix);
159}
ced645ea 160
0291b5b7 161char *git__strtok(char **end, const char *sep)
f725931b 162{
0291b5b7 163 char *ptr = *end;
ced645ea 164
0291b5b7
VM
165 while (*ptr && strchr(sep, *ptr))
166 ++ptr;
f725931b 167
0291b5b7
VM
168 if (*ptr) {
169 char *start = ptr;
170 *end = start + 1;
ced645ea 171
0291b5b7
VM
172 while (**end && !strchr(sep, **end))
173 ++*end;
f725931b 174
0291b5b7
VM
175 if (**end) {
176 **end = '\0';
177 ++*end;
178 }
179
180 return start;
181 }
182
183 return NULL;
ced645ea
RJ
184}
185
0e465f97
VM
186void git__hexdump(const char *buffer, size_t len)
187{
188 static const size_t LINE_WIDTH = 16;
189
190 size_t line_count, last_line, i, j;
191 const char *line;
192
193 line_count = (len / LINE_WIDTH);
194 last_line = (len % LINE_WIDTH);
195
196 for (i = 0; i < line_count; ++i) {
197 line = buffer + (i * LINE_WIDTH);
198 for (j = 0; j < LINE_WIDTH; ++j, ++line)
199 printf("%02X ", (unsigned char)*line & 0xFF);
200
201 printf("| ");
202
203 line = buffer + (i * LINE_WIDTH);
204 for (j = 0; j < LINE_WIDTH; ++j, ++line)
205 printf("%c", (*line >= 32 && *line <= 126) ? *line : '.');
206
207 printf("\n");
208 }
209
210 if (last_line > 0) {
211
212 line = buffer + (line_count * LINE_WIDTH);
213 for (j = 0; j < last_line; ++j, ++line)
214 printf("%02X ", (unsigned char)*line & 0xFF);
215
216 for (j = 0; j < (LINE_WIDTH - last_line); ++j)
87d9869f 217 printf(" ");
0e465f97
VM
218
219 printf("| ");
220
221 line = buffer + (line_count * LINE_WIDTH);
222 for (j = 0; j < last_line; ++j, ++line)
223 printf("%c", (*line >= 32 && *line <= 126) ? *line : '.');
224
225 printf("\n");
226 }
227
228 printf("\n");
229}
e0646b38
VM
230
231#ifdef GIT_LEGACY_HASH
232uint32_t git__hash(const void *key, int len, unsigned int seed)
233{
234 const uint32_t m = 0x5bd1e995;
235 const int r = 24;
236 uint32_t h = seed ^ len;
237
238 const unsigned char *data = (const unsigned char *)key;
239
240 while(len >= 4) {
241 uint32_t k = *(uint32_t *)data;
242
932d1baf
KS
243 k *= m;
244 k ^= k >> r;
245 k *= m;
246
247 h *= m;
e0646b38
VM
248 h ^= k;
249
250 data += 4;
251 len -= 4;
252 }
932d1baf 253
e0646b38
VM
254 switch(len) {
255 case 3: h ^= data[2] << 16;
256 case 2: h ^= data[1] << 8;
257 case 1: h ^= data[0];
87d9869f 258 h *= m;
e0646b38
VM
259 };
260
261 h ^= h >> 13;
262 h *= m;
263 h ^= h >> 15;
264
265 return h;
932d1baf 266}
e0646b38
VM
267#else
268/*
269 Cross-platform version of Murmurhash3
270 http://code.google.com/p/smhasher/wiki/MurmurHash3
271 by Austin Appleby (aappleby@gmail.com)
272
273 This code is on the public domain.
274*/
275uint32_t git__hash(const void *key, int len, uint32_t seed)
276{
277
278#define MURMUR_BLOCK() {\
87d9869f
VM
279 k1 *= c1; \
280 k1 = git__rotl(k1,11);\
281 k1 *= c2;\
282 h1 ^= k1;\
283 h1 = h1*3 + 0x52dce729;\
284 c1 = c1*5 + 0x7b7d159c;\
285 c2 = c2*5 + 0x6bce6396;\
e0646b38
VM
286}
287
288 const uint8_t *data = (const uint8_t*)key;
289 const int nblocks = len / 4;
290
291 const uint32_t *blocks = (const uint32_t *)(data + nblocks * 4);
292 const uint8_t *tail = (const uint8_t *)(data + nblocks * 4);
293
294 uint32_t h1 = 0x971e137b ^ seed;
295 uint32_t k1;
296
297 uint32_t c1 = 0x95543787;
298 uint32_t c2 = 0x2ad7eb25;
299
300 int i;
301
302 for (i = -nblocks; i; i++) {
303 k1 = blocks[i];
304 MURMUR_BLOCK();
305 }
306
307 k1 = 0;
308
309 switch(len & 3) {
310 case 3: k1 ^= tail[2] << 16;
311 case 2: k1 ^= tail[1] << 8;
312 case 1: k1 ^= tail[0];
313 MURMUR_BLOCK();
314 }
315
316 h1 ^= len;
317 h1 ^= h1 >> 16;
318 h1 *= 0x85ebca6b;
319 h1 ^= h1 >> 13;
320 h1 *= 0xc2b2ae35;
321 h1 ^= h1 >> 16;
322
323 return h1;
932d1baf 324}
e0646b38 325#endif
c20ffa61 326
de18f276
VM
327/**
328 * A modified `bsearch` from the BSD glibc.
329 *
330 * Copyright (c) 1990 Regents of the University of California.
331 * All rights reserved.
c20ffa61 332 */
de18f276 333void **git__bsearch(const void *key, void **base, size_t nmemb, int (*compar)(const void *, const void *))
c20ffa61 334{
87d9869f
VM
335 int lim, cmp;
336 void **p;
337
338 for (lim = nmemb; lim != 0; lim >>= 1) {
339 p = base + (lim >> 1);
340 cmp = (*compar)(key, *p);
341 if (cmp > 0) { /* key > p: move right */
342 base = p + 1;
343 lim--;
344 } else if (cmp == 0) {
345 return (void **)p;
346 } /* else move left */
347 }
348 return NULL;
c20ffa61
KS
349}
350
d1f34693 351/**
352 * A strcmp wrapper
353 *
354 * We don't want direct pointers to the CRT on Windows, we may
355 * get stdcall conflicts.
356 */
357int git__strcmp_cb(const void *a, const void *b)
358{
359 const char *stra = (const char *)a;
360 const char *strb = (const char *)b;
361
362 return strcmp(stra, strb);
84dd3820 363}