]> git.proxmox.com Git - libgit2.git/blob - src/util.c
Tabify everything
[libgit2.git] / src / util.c
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 */
7 #include <git2.h>
8 #include "common.h"
9 #include <stdarg.h>
10 #include <stdio.h>
11 #include <ctype.h>
12 #include "posix.h"
13
14 #ifdef _MSC_VER
15 # include <Shlwapi.h>
16 #endif
17
18 void 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
25 void 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
34 int git__fnmatch(const char *pattern, const char *name, int flags)
35 {
36 int ret;
37
38 ret = p_fnmatch(pattern, name, flags);
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
49 int 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
113 Return:
114 if (ndig == 0)
115 return git__throw(GIT_ENOTNUM, "Failed to convert string to long. Not a number");
116
117 if (endptr)
118 *endptr = p;
119
120 if (ovfl)
121 return git__throw(GIT_EOVERFLOW, "Failed to convert string to long. Overflow error");
122
123 *result = neg ? -n : n;
124 return GIT_SUCCESS;
125 }
126
127 void git__strntolower(char *str, size_t len)
128 {
129 size_t i;
130
131 for (i = 0; i < len; ++i) {
132 str[i] = (char) tolower(str[i]);
133 }
134 }
135
136 void git__strtolower(char *str)
137 {
138 git__strntolower(str, strlen(str));
139 }
140
141 int 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
152 int 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 }
160
161 char *git__strtok(char **end, const char *sep)
162 {
163 char *ptr = *end;
164
165 while (*ptr && strchr(sep, *ptr))
166 ++ptr;
167
168 if (*ptr) {
169 char *start = ptr;
170 *end = start + 1;
171
172 while (**end && !strchr(sep, **end))
173 ++*end;
174
175 if (**end) {
176 **end = '\0';
177 ++*end;
178 }
179
180 return start;
181 }
182
183 return NULL;
184 }
185
186 void 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)
217 printf(" ");
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 }
230
231 #ifdef GIT_LEGACY_HASH
232 uint32_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
243 k *= m;
244 k ^= k >> r;
245 k *= m;
246
247 h *= m;
248 h ^= k;
249
250 data += 4;
251 len -= 4;
252 }
253
254 switch(len) {
255 case 3: h ^= data[2] << 16;
256 case 2: h ^= data[1] << 8;
257 case 1: h ^= data[0];
258 h *= m;
259 };
260
261 h ^= h >> 13;
262 h *= m;
263 h ^= h >> 15;
264
265 return h;
266 }
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 */
275 uint32_t git__hash(const void *key, int len, uint32_t seed)
276 {
277
278 #define MURMUR_BLOCK() {\
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;\
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;
324 }
325 #endif
326
327 /**
328 * A modified `bsearch` from the BSD glibc.
329 *
330 * Copyright (c) 1990 Regents of the University of California.
331 * All rights reserved.
332 */
333 void **git__bsearch(const void *key, void **base, size_t nmemb, int (*compar)(const void *, const void *))
334 {
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;
349 }
350
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 */
357 int 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);
363 }