]>
Commit | Line | Data |
---|---|---|
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 |
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 | ||
955f9ae9 VM |
25 | void 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 |
34 | int 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 | 49 | int 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 | ||
113 | Return: | |
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 | 127 | int 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 | 145 | void 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 | ||
154 | void git__strtolower(char *str) | |
155 | { | |
156 | git__strntolower(str, strlen(str)); | |
157 | } | |
158 | ||
9eb79764 SP |
159 | int 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 | ||
170 | int 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 | 179 | char *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 |
204 | void 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 | |
250 | uint32_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 | */ | |
293 | uint32_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 | 351 | void **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 | */ | |
375 | int 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 | } |