Line Flow Count Block(s) Source
1 - /*
2 - * Copyright (C) the libgit2 contributors. All rights reserved.
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 -
8 - #include "util.h"
9 -
10 - #include "common.h"
11 -
12 - #ifdef GIT_WIN32
13 - # include "win32/utf-conv.h"
14 - # include "win32/w32_buffer.h"
15 -
16 - # ifdef HAVE_QSORT_S
17 - # include <search.h>
18 - # endif
19 - #endif
20 -
21 - #ifdef _MSC_VER
22 - # include <Shlwapi.h>
23 - #endif
24 -
25 - 2 suppressed: function cannot be solved git__strntol64 (automatic due to inconsistent arc counts in .gcda files)int git__strntol64(int64_t *result, const char *nptr, size_t nptr_len, const char **endptr, int base)
26 - {
27 - const char *p;
28 - int64_t n, nn;
29 - int c, ovfl, v, neg, ndig;
30 -
31 - 2 suppressed: function cannot be solved git__strntol64 (automatic due to inconsistent arc counts in .gcda files) p = nptr;
32 - 2 suppressed: function cannot be solved git__strntol64 (automatic due to inconsistent arc counts in .gcda files) neg = 0;
33 - 2 suppressed: function cannot be solved git__strntol64 (automatic due to inconsistent arc counts in .gcda files) n = 0;
34 - 2 suppressed: function cannot be solved git__strntol64 (automatic due to inconsistent arc counts in .gcda files) ndig = 0;
35 - 2 suppressed: function cannot be solved git__strntol64 (automatic due to inconsistent arc counts in .gcda files) ovfl = 0;
36 -
37 - /*
38 - * White space
39 - */
40 - 2,4-6 suppressed: function cannot be solved git__strntol64 (automatic due to inconsistent arc counts in .gcda files) while (nptr_len && git__isspace(*p))
41 - 3 suppressed: function cannot be solved git__strntol64 (automatic due to inconsistent arc counts in .gcda files) p++, nptr_len--;
42 -
43 - 7 suppressed: function cannot be solved git__strntol64 (automatic due to inconsistent arc counts in .gcda files) if (!nptr_len)
44 - 8 suppressed: function cannot be solved git__strntol64 (automatic due to inconsistent arc counts in .gcda files) goto Return;
45 -
46 - /*
47 - * Sign
48 - */
49 - 9,10 suppressed: function cannot be solved git__strntol64 (automatic due to inconsistent arc counts in .gcda files) if (*p == '-' || *p == '+') {
50 - 11 suppressed: function cannot be solved git__strntol64 (automatic due to inconsistent arc counts in .gcda files) if (*p == '-')
51 - 12 suppressed: function cannot be solved git__strntol64 (automatic due to inconsistent arc counts in .gcda files) neg = 1;
52 - 13 suppressed: function cannot be solved git__strntol64 (automatic due to inconsistent arc counts in .gcda files) p++;
53 - 13 suppressed: function cannot be solved git__strntol64 (automatic due to inconsistent arc counts in .gcda files) nptr_len--;
54 - }
55 -
56 - 14 suppressed: function cannot be solved git__strntol64 (automatic due to inconsistent arc counts in .gcda files) if (!nptr_len)
57 - 15 suppressed: function cannot be solved git__strntol64 (automatic due to inconsistent arc counts in .gcda files) goto Return;
58 -
59 - /*
60 - * Automatically detect the base if none was given to us.
61 - * Right now, we assume that a number starting with '0x'
62 - * is hexadecimal and a number starting with '0' is
63 - * octal.
64 - */
65 - 16 suppressed: function cannot be solved git__strntol64 (automatic due to inconsistent arc counts in .gcda files) if (base == 0) {
66 - 17 suppressed: function cannot be solved git__strntol64 (automatic due to inconsistent arc counts in .gcda files) if (*p != '0')
67 - 18 suppressed: function cannot be solved git__strntol64 (automatic due to inconsistent arc counts in .gcda files) base = 10;
68 - 19-21 suppressed: function cannot be solved git__strntol64 (automatic due to inconsistent arc counts in .gcda files) else if (nptr_len > 2 && (p[1] == 'x' || p[1] == 'X'))
69 - 22 suppressed: function cannot be solved git__strntol64 (automatic due to inconsistent arc counts in .gcda files) base = 16;
70 - else
71 - 23 suppressed: function cannot be solved git__strntol64 (automatic due to inconsistent arc counts in .gcda files) base = 8;
72 - }
73 -
74 - 24,25 suppressed: function cannot be solved git__strntol64 (automatic due to inconsistent arc counts in .gcda files) if (base < 0 || 36 < base)
75 - goto Return;
76 -
77 - /*
78 - * Skip prefix of '0x'-prefixed hexadecimal numbers. There is no
79 - * need to do the same for '0'-prefixed octal numbers as a
80 - * leading '0' does not have any impact. Also, if we skip a
81 - * leading '0' in such a string, then we may end up with no
82 - * digits left and produce an error later on which isn't one.
83 - */
84 - 26-30 suppressed: function cannot be solved git__strntol64 (automatic due to inconsistent arc counts in .gcda files) if (base == 16 && nptr_len > 2 && p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) {
85 - 31 suppressed: function cannot be solved git__strntol64 (automatic due to inconsistent arc counts in .gcda files) p += 2;
86 - 31 suppressed: function cannot be solved git__strntol64 (automatic due to inconsistent arc counts in .gcda files) nptr_len -= 2;
87 - }
88 -
89 - /*
90 - * Non-empty sequence of digits
91 - */
92 - 32,56,57 suppressed: function cannot be solved git__strntol64 (automatic due to inconsistent arc counts in .gcda files) for (; nptr_len > 0; p++,ndig++,nptr_len--) {
93 - 33 suppressed: function cannot be solved git__strntol64 (automatic due to inconsistent arc counts in .gcda files) c = *p;
94 - 33 suppressed: function cannot be solved git__strntol64 (automatic due to inconsistent arc counts in .gcda files) v = base;
95 - 33,34 suppressed: function cannot be solved git__strntol64 (automatic due to inconsistent arc counts in .gcda files) if ('0'<=c && c<='9')
96 - 35 suppressed: function cannot be solved git__strntol64 (automatic due to inconsistent arc counts in .gcda files) v = c - '0';
97 - 36,37 suppressed: function cannot be solved git__strntol64 (automatic due to inconsistent arc counts in .gcda files) else if ('a'<=c && c<='z')
98 - 38 suppressed: function cannot be solved git__strntol64 (automatic due to inconsistent arc counts in .gcda files) v = c - 'a' + 10;
99 - 39,40 suppressed: function cannot be solved git__strntol64 (automatic due to inconsistent arc counts in .gcda files) else if ('A'<=c && c<='Z')
100 - 41 suppressed: function cannot be solved git__strntol64 (automatic due to inconsistent arc counts in .gcda files) v = c - 'A' + 10;
101 - 42 suppressed: function cannot be solved git__strntol64 (automatic due to inconsistent arc counts in .gcda files) if (v >= base)
102 - 43 suppressed: function cannot be solved git__strntol64 (automatic due to inconsistent arc counts in .gcda files) break;
103 - 44-46 suppressed: function cannot be solved git__strntol64 (automatic due to inconsistent arc counts in .gcda files) v = neg ? -v : v;
104 - 47,48 suppressed: function cannot be solved git__strntol64 (automatic due to inconsistent arc counts in .gcda files) if (n > INT64_MAX / base || n < INT64_MIN / base) {
105 - 49 suppressed: function cannot be solved git__strntol64 (automatic due to inconsistent arc counts in .gcda files) ovfl = 1;
106 - /* Keep on iterating until the end of this number */
107 - 49 suppressed: function cannot be solved git__strntol64 (automatic due to inconsistent arc counts in .gcda files) continue;
108 - }
109 - 50 suppressed: function cannot be solved git__strntol64 (automatic due to inconsistent arc counts in .gcda files) nn = n * base;
110 - 50-52 suppressed: function cannot be solved git__strntol64 (automatic due to inconsistent arc counts in .gcda files) if ((v > 0 && nn > INT64_MAX - v) ||
111 - 53 suppressed: function cannot be solved git__strntol64 (automatic due to inconsistent arc counts in .gcda files) (v < 0 && nn < INT64_MIN - v)) {
112 - 54 suppressed: function cannot be solved git__strntol64 (automatic due to inconsistent arc counts in .gcda files) ovfl = 1;
113 - /* Keep on iterating until the end of this number */
114 - 54 suppressed: function cannot be solved git__strntol64 (automatic due to inconsistent arc counts in .gcda files) continue;
115 - }
116 - 55 suppressed: function cannot be solved git__strntol64 (automatic due to inconsistent arc counts in .gcda files) n = nn + v;
117 - }
118 -
119 - Return:
120 - 58 suppressed: function cannot be solved git__strntol64 (automatic due to inconsistent arc counts in .gcda files) if (ndig == 0) {
121 - 59 suppressed: function cannot be solved git__strntol64 (automatic due to inconsistent arc counts in .gcda files) git_error_set(GIT_ERROR_INVALID, "failed to convert string to long: not a number");
122 - 60 suppressed: function cannot be solved git__strntol64 (automatic due to inconsistent arc counts in .gcda files) return -1;
123 - }
124 -
125 - 61 suppressed: function cannot be solved git__strntol64 (automatic due to inconsistent arc counts in .gcda files) if (endptr)
126 - 62 suppressed: function cannot be solved git__strntol64 (automatic due to inconsistent arc counts in .gcda files) *endptr = p;
127 -
128 - 63 suppressed: function cannot be solved git__strntol64 (automatic due to inconsistent arc counts in .gcda files) if (ovfl) {
129 - 64 suppressed: function cannot be solved git__strntol64 (automatic due to inconsistent arc counts in .gcda files) git_error_set(GIT_ERROR_INVALID, "failed to convert string to long: overflow error");
130 - 65 suppressed: function cannot be solved git__strntol64 (automatic due to inconsistent arc counts in .gcda files) return -1;
131 - }
132 -
133 - 66 suppressed: function cannot be solved git__strntol64 (automatic due to inconsistent arc counts in .gcda files) *result = n;
134 - 66 suppressed: function cannot be solved git__strntol64 (automatic due to inconsistent arc counts in .gcda files) return 0;
135 - }
136 -
137 239728 2 int git__strntol32(int32_t *result, const char *nptr, size_t nptr_len, const char **endptr, int base)
138 - {
139 - const char *tmp_endptr;
140 - int32_t tmp_int;
141 - int64_t tmp_long;
142 - int error;
143 -
144 239734 2,3 if ((error = git__strntol64(&tmp_long, nptr, nptr_len, &tmp_endptr, base)) < 0)
145 18 4 return error;
146 -
147 239716 5 tmp_int = tmp_long & 0xFFFFFFFF;
148 239716 5 if (tmp_int != tmp_long) {
149 3 6 int len = (int)(tmp_endptr - nptr);
150 3 6 git_error_set(GIT_ERROR_INVALID, "failed to convert: '%.*s' is too large", len, nptr);
151 3 7 return -1;
152 - }
153 -
154 239713 8 *result = tmp_int;
155 239713 8 if (endptr)
156 239704 9 *endptr = tmp_endptr;
157 -
158 239713 10 return error;
159 - }
160 -
161 1676 2 int git__strcasecmp(const char *a, const char *b)
162 - {
163 4425 2,4-6 while (*a && *b && git__tolower(*a) == git__tolower(*b))
164 2749 3 ++a, ++b;
165 1676 7 return ((unsigned char)git__tolower(*a) - (unsigned char)git__tolower(*b));
166 - }
167 -
168 9 2 int git__strcasesort_cmp(const char *a, const char *b)
169 - {
170 9 2 int cmp = 0;
171 -
172 24 2,9,10 while (*a && *b) {
173 19 3 if (*a != *b) {
174 11 4 if (git__tolower(*a) != git__tolower(*b))
175 4 5 break;
176 - /* use case in sort order even if not in equivalence */
177 7 6 if (!cmp)
178 3 7 cmp = (int)(*(const uint8_t *)a) - (int)(*(const uint8_t *)b);
179 - }
180 -
181 15 8 ++a, ++b;
182 - }
183 -
184 9 11,12 if (*a || *b)
185 4 13 return (unsigned char)git__tolower(*a) - (unsigned char)git__tolower(*b);
186 -
187 5 14 return cmp;
188 - }
189 -
190 3736 2 int git__strncasecmp(const char *a, const char *b, size_t sz)
191 - {
192 - int al, bl;
193 -
194 - do {
195 3736 2 al = (unsigned char)git__tolower(*a);
196 3736 2 bl = (unsigned char)git__tolower(*b);
197 3736 2 ++a, ++b;
198 3736 2-4 } while (--sz && al && al == bl);
199 -
200 2685 5 return al - bl;
201 - }
202 -
203 200 2 void git__strntolower(char *str, size_t len)
204 - {
205 - size_t i;
206 -
207 997 2-4 for (i = 0; i < len; ++i) {
208 797 3 str[i] = (char)git__tolower(str[i]);
209 - }
210 200 5 }
211 -
212 ##### 2 void git__strtolower(char *str)
213 - {
214 ##### 2 git__strntolower(str, strlen(str));
215 ##### 3 }
216 -
217 167640 2 GIT_INLINE(int) prefixcmp(const char *str, size_t str_n, const char *prefix, bool icase)
218 - {
219 - int s, p;
220 -
221 443655 2,9 while (str_n--) {
222 384964 3 s = (unsigned char)*str++;
223 384964 3 p = (unsigned char)*prefix++;
224 -
225 384964 3 if (icase) {
226 1395 4 s = git__tolower(s);
227 1395 4 p = git__tolower(p);
228 - }
229 -
230 384964 5 if (!p)
231 4365 6 return 0;
232 -
233 380599 7 if (s != p)
234 104584 8 return s - p;
235 - }
236 -
237 58691 10 return (0 - *prefix);
238 - }
239 -
240 13843951 2 int git__prefixcmp(const char *str, const char *prefix)
241 - {
242 - unsigned char s, p;
243 -
244 - while (1) {
245 13843951 2 p = *prefix++;
246 13843951 2 s = *str++;
247 -
248 13843951 2 if (!p)
249 418311 3 return 0;
250 -
251 13425640 4 if (s != p)
252 329032 5 return s - p;
253 13096608 6 }
254 - }
255 -
256 166231 2 int git__prefixncmp(const char *str, size_t str_n, const char *prefix)
257 - {
258 166231 2 return prefixcmp(str, str_n, prefix, false);
259 - }
260 -
261 844 2 int git__prefixcmp_icase(const char *str, const char *prefix)
262 - {
263 844 2 return prefixcmp(str, SIZE_MAX, prefix, true);
264 - }
265 -
266 20 2 int git__prefixncmp_icase(const char *str, size_t str_n, const char *prefix)
267 - {
268 20 2 return prefixcmp(str, str_n, prefix, true);
269 - }
270 -
271 198800 2 int git__suffixcmp(const char *str, const char *suffix)
272 - {
273 198800 2 size_t a = strlen(str);
274 198800 2 size_t b = strlen(suffix);
275 198800 2 if (a < b)
276 73762 3 return -1;
277 125038 4 return strcmp(str + (a - b), suffix);
278 - }
279 -
280 16 2 char *git__strtok(char **end, const char *sep)
281 - {
282 16 2 char *ptr = *end;
283 -
284 16 2,4,5 while (*ptr && strchr(sep, *ptr))
285 ##### 3 ++ptr;
286 -
287 16 6 if (*ptr) {
288 8 7 char *start = ptr;
289 8 7 *end = start + 1;
290 -
291 343 7,9,10 while (**end && !strchr(sep, **end))
292 335 8 ++*end;
293 -
294 8 11 if (**end) {
295 8 12 **end = '\0';
296 8 12 ++*end;
297 - }
298 -
299 8 13 return start;
300 - }
301 -
302 8 14 return NULL;
303 - }
304 -
305 - /* Similar to strtok, but does not collapse repeated tokens. */
306 182 2 char *git__strsep(char **end, const char *sep)
307 - {
308 182 2 char *start = *end, *ptr = *end;
309 -
310 9983 2,4,5 while (*ptr && !strchr(sep, *ptr))
311 9801 3 ++ptr;
312 -
313 182 6 if (*ptr) {
314 165 7 *end = ptr + 1;
315 165 7 *ptr = '\0';
316 -
317 165 7 return start;
318 - }
319 -
320 17 8 return NULL;
321 - }
322 -
323 206123 2 size_t git__linenlen(const char *buffer, size_t buffer_len)
324 - {
325 206123 2 char *nl = memchr(buffer, '\n', buffer_len);
326 206123 2 return nl ? (size_t)(nl - buffer) + 1 : buffer_len;
327 - }
328 -
329 - /*
330 - * Adapted Not So Naive algorithm from http://www-igm.univ-mlv.fr/~lecroq/string/
331 - */
332 22 2 const void * git__memmem(const void *haystack, size_t haystacklen,
333 - const void *needle, size_t needlelen)
334 - {
335 - const char *h, *n;
336 - size_t j, k, l;
337 -
338 22 2-4 if (needlelen > haystacklen || !haystacklen || !needlelen)
339 8 5 return NULL;
340 -
341 14 6 h = (const char *) haystack,
342 14 6 n = (const char *) needle;
343 -
344 14 6 if (needlelen == 1)
345 5 7 return memchr(haystack, *n, haystacklen);
346 -
347 9 8 if (n[0] == n[1]) {
348 4 9 k = 2;
349 4 9 l = 1;
350 - } else {
351 5 10 k = 1;
352 5 10 l = 2;
353 - }
354 -
355 9 11 j = 0;
356 187 11,18 while (j <= haystacklen - needlelen) {
357 184 12 if (n[1] != h[j + 1]) {
358 163 13 j += k;
359 - } else {
360 21 14,15 if (memcmp(n + 2, h + j + 2, needlelen - 2) == 0 &&
361 17 15 n[0] == h[j])
362 6 16 return h + j;
363 15 17 j += l;
364 - }
365 - }
366 -
367 3 19 return NULL;
368 - }
369 -
370 ##### 2 void git__hexdump(const char *buffer, size_t len)
371 - {
372 - static const size_t LINE_WIDTH = 16;
373 -
374 - size_t line_count, last_line, i, j;
375 - const char *line;
376 -
377 ##### 2 line_count = (len / LINE_WIDTH);
378 ##### 2 last_line = (len % LINE_WIDTH);
379 -
380 ##### 2,20,21 for (i = 0; i < line_count; ++i) {
381 ##### 3 printf("%08" PRIxZ " ", (i * LINE_WIDTH));
382 -
383 ##### 4 line = buffer + (i * LINE_WIDTH);
384 ##### 4,8,9 for (j = 0; j < LINE_WIDTH; ++j, ++line) {
385 ##### 5 printf("%02x ", (unsigned char)*line & 0xFF);
386 -
387 ##### 6 if (j == (LINE_WIDTH / 2))
388 ##### 7 printf(" ");
389 - }
390 -
391 ##### 10 printf(" |");
392 -
393 ##### 11 line = buffer + (i * LINE_WIDTH);
394 ##### 11,17,18 for (j = 0; j < LINE_WIDTH; ++j, ++line)
395 ##### 12-16 printf("%c", (*line >= 32 && *line <= 126) ? *line : '.');
396 -
397 ##### 19 printf("|\n");
398 - }
399 -
400 ##### 22 if (last_line > 0) {
401 ##### 23 printf("%08" PRIxZ " ", (line_count * LINE_WIDTH));
402 -
403 ##### 24 line = buffer + (line_count * LINE_WIDTH);
404 ##### 24,28,29 for (j = 0; j < last_line; ++j, ++line) {
405 ##### 25 printf("%02x ", (unsigned char)*line & 0xFF);
406 -
407 ##### 26 if (j == (LINE_WIDTH / 2))
408 ##### 27 printf(" ");
409 - }
410 -
411 ##### 30 if (j < (LINE_WIDTH / 2))
412 ##### 31 printf(" ");
413 ##### 32,34,35 for (j = 0; j < (LINE_WIDTH - last_line); ++j)
414 ##### 33 printf(" ");
415 -
416 ##### 36 printf(" |");
417 -
418 ##### 37 line = buffer + (line_count * LINE_WIDTH);
419 ##### 37,43,44 for (j = 0; j < last_line; ++j, ++line)
420 ##### 38-42 printf("%c", (*line >= 32 && *line <= 126) ? *line : '.');
421 -
422 ##### 45 printf("|\n");
423 - }
424 -
425 ##### 46 printf("\n");
426 ##### 47 }
427 -
428 - #ifdef GIT_LEGACY_HASH
429 - uint32_t git__hash(const void *key, int len, unsigned int seed)
430 - {
431 - const uint32_t m = 0x5bd1e995;
432 - const int r = 24;
433 - uint32_t h = seed ^ len;
434 -
435 - const unsigned char *data = (const unsigned char *)key;
436 -
437 - while(len >= 4) {
438 - uint32_t k = *(uint32_t *)data;
439 -
440 - k *= m;
441 - k ^= k >> r;
442 - k *= m;
443 -
444 - h *= m;
445 - h ^= k;
446 -
447 - data += 4;
448 - len -= 4;
449 - }
450 -
451 - switch(len) {
452 - case 3: h ^= data[2] << 16;
453 - case 2: h ^= data[1] << 8;
454 - case 1: h ^= data[0];
455 - h *= m;
456 - };
457 -
458 - h ^= h >> 13;
459 - h *= m;
460 - h ^= h >> 15;
461 -
462 - return h;
463 - }
464 - #else
465 - /*
466 - Cross-platform version of Murmurhash3
467 - http://code.google.com/p/smhasher/wiki/MurmurHash3
468 - by Austin Appleby (aappleby@gmail.com)
469 -
470 - This code is on the public domain.
471 - */
472 ##### 2 uint32_t git__hash(const void *key, int len, uint32_t seed)
473 - {
474 -
475 - #define MURMUR_BLOCK() {\
476 - k1 *= c1; \
477 - k1 = git__rotl(k1,11);\
478 - k1 *= c2;\
479 - h1 ^= k1;\
480 - h1 = h1*3 + 0x52dce729;\
481 - c1 = c1*5 + 0x7b7d159c;\
482 - c2 = c2*5 + 0x6bce6396;\
483 - }
484 -
485 ##### 2 const uint8_t *data = (const uint8_t*)key;
486 ##### 2 const int nblocks = len / 4;
487 -
488 ##### 2 const uint32_t *blocks = (const uint32_t *)(data + nblocks * 4);
489 ##### 2 const uint8_t *tail = (const uint8_t *)(data + nblocks * 4);
490 -
491 ##### 2 uint32_t h1 = 0x971e137b ^ seed;
492 - uint32_t k1;
493 -
494 ##### 2 uint32_t c1 = 0x95543787;
495 ##### 2 uint32_t c2 = 0x2ad7eb25;
496 -
497 - int i;
498 -
499 ##### 2-4 for (i = -nblocks; i; i++) {
500 ##### 3 k1 = blocks[i];
501 ##### 3 MURMUR_BLOCK();
502 - }
503 -
504 ##### 5 k1 = 0;
505 -
506 ##### 5 switch(len & 3) {
507 ##### 6 case 3: k1 ^= tail[2] << 16;
508 - /* fall through */
509 ##### 7 case 2: k1 ^= tail[1] << 8;
510 - /* fall through */
511 ##### 8 case 1: k1 ^= tail[0];
512 ##### 8 MURMUR_BLOCK();
513 - }
514 -
515 ##### 9 h1 ^= len;
516 ##### 9 h1 ^= h1 >> 16;
517 ##### 9 h1 *= 0x85ebca6b;
518 ##### 9 h1 ^= h1 >> 13;
519 ##### 9 h1 *= 0xc2b2ae35;
520 ##### 9 h1 ^= h1 >> 16;
521 -
522 ##### 9 return h1;
523 - }
524 - #endif
525 -
526 - /**
527 - * A modified `bsearch` from the BSD glibc.
528 - *
529 - * Copyright (c) 1990 Regents of the University of California.
530 - * All rights reserved.
531 - * Redistribution and use in source and binary forms, with or without
532 - * modification, are permitted provided that the following conditions
533 - * are met:
534 - * 1. Redistributions of source code must retain the above copyright
535 - * notice, this list of conditions and the following disclaimer.
536 - * 2. Redistributions in binary form must reproduce the above copyright
537 - * notice, this list of conditions and the following disclaimer in the
538 - * documentation and/or other materials provided with the distribution.
539 - * 3. [rescinded 22 July 1999]
540 - * 4. Neither the name of the University nor the names of its contributors
541 - * may be used to endorse or promote products derived from this software
542 - * without specific prior written permission.
543 - *
544 - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
545 - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
546 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
547 - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
548 - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
549 - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
550 - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
551 - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
552 - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
553 - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
554 - * SUCH DAMAGE.
555 - */
556 254480 2 int git__bsearch(
557 - void **array,
558 - size_t array_len,
559 - const void *key,
560 - int (*compare)(const void *, const void *),
561 - size_t *position)
562 - {
563 - size_t lim;
564 254480 2 int cmp = -1;
565 254480 2 void **part, **base = array;
566 -
567 844676 2,8,9 for (lim = array_len; lim != 0; lim >>= 1) {
568 609758 3 part = base + (lim >> 1);
569 609758 3 cmp = (*compare)(key, *part);
570 609946 4 if (cmp == 0) {
571 19750 5 base = part;
572 19750 5 break;
573 - }
574 590196 6 if (cmp > 0) { /* key > p; take right partition */
575 167997 7 base = part + 1;
576 167997 7 lim--;
577 - } /* else take left partition */
578 - }
579 -
580 254668 10 if (position)
581 248023 11 *position = (base - array);
582 -
583 254668 12 return (cmp == 0) ? 0 : GIT_ENOTFOUND;
584 - }
585 -
586 ##### 2 int git__bsearch_r(
587 - void **array,
588 - size_t array_len,
589 - const void *key,
590 - int (*compare_r)(const void *, const void *, void *),
591 - void *payload,
592 - size_t *position)
593 - {
594 - size_t lim;
595 ##### 2 int cmp = -1;
596 ##### 2 void **part, **base = array;
597 -
598 ##### 2,8,9 for (lim = array_len; lim != 0; lim >>= 1) {
599 ##### 3 part = base + (lim >> 1);
600 ##### 3 cmp = (*compare_r)(key, *part, payload);
601 ##### 4 if (cmp == 0) {
602 ##### 5 base = part;
603 ##### 5 break;
604 - }
605 ##### 6 if (cmp > 0) { /* key > p; take right partition */
606 ##### 7 base = part + 1;
607 ##### 7 lim--;
608 - } /* else take left partition */
609 - }
610 -
611 ##### 10 if (position)
612 ##### 11 *position = (base - array);
613 -
614 ##### 12 return (cmp == 0) ? 0 : GIT_ENOTFOUND;
615 - }
616 -
617 - /**
618 - * A strcmp wrapper
619 - *
620 - * We don't want direct pointers to the CRT on Windows, we may
621 - * get stdcall conflicts.
622 - */
623 11267 2 int git__strcmp_cb(const void *a, const void *b)
624 - {
625 11267 2 return strcmp((const char *)a, (const char *)b);
626 - }
627 -
628 2 2 int git__strcasecmp_cb(const void *a, const void *b)
629 - {
630 2 2 return strcasecmp((const char *)a, (const char *)b);
631 - }
632 -
633 15917 2 int git__parse_bool(int *out, const char *value)
634 - {
635 - /* A missing value means true */
636 15917 2,3 if (value == NULL ||
637 15915 3,4 !strcasecmp(value, "true") ||
638 3393 4,5 !strcasecmp(value, "yes") ||
639 3392 5 !strcasecmp(value, "on")) {
640 12525 6 *out = 1;
641 12525 6 return 0;
642 - }
643 3392 7,8 if (!strcasecmp(value, "false") ||
644 179 8,9 !strcasecmp(value, "no") ||
645 179 9,10 !strcasecmp(value, "off") ||
646 179 10 value[0] == '\0') {
647 3214 11 *out = 0;
648 3214 11 return 0;
649 - }
650 -
651 178 12 return -1;
652 - }
653 -
654 3082 2 size_t git__unescape(char *str)
655 - {
656 3082 2 char *scan, *pos = str;
657 -
658 3082 2 if (!str)
659 ##### 3 return 0;
660 -
661 44494 4,10,11 for (scan = str; *scan; pos++, scan++) {
662 41412 5,6 if (*scan == '\\' && *(scan + 1) != '\0')
663 6 7 scan++; /* skip '\' but include next char */
664 41412 8 if (pos != scan)
665 14 9 *pos = *scan;
666 - }
667 -
668 3082 12 if (pos != scan) {
669 3 13 *pos = '\0';
670 - }
671 -
672 3082 14 return (pos - str);
673 - }
674 -
675 - #if defined(HAVE_QSORT_S) || defined(HAVE_QSORT_R_BSD)
676 - typedef struct {
677 - git__sort_r_cmp cmp;
678 - void *payload;
679 - } git__qsort_r_glue;
680 -
681 - static int GIT_STDLIB_CALL git__qsort_r_glue_cmp(
682 - void *payload, const void *a, const void *b)
683 - {
684 - git__qsort_r_glue *glue = payload;
685 - return glue->cmp(a, b, glue->payload);
686 - }
687 - #endif
688 -
689 -
690 - #if !defined(HAVE_QSORT_R_BSD) && \
691 - !defined(HAVE_QSORT_R_GNU) && \
692 - !defined(HAVE_QSORT_S)
693 - static void swap(uint8_t *a, uint8_t *b, size_t elsize)
694 - {
695 - char tmp[256];
696 -
697 - while (elsize) {
698 - size_t n = elsize < sizeof(tmp) ? elsize : sizeof(tmp);
699 - memcpy(tmp, a + elsize - n, n);
700 - memcpy(a + elsize - n, b + elsize - n, n);
701 - memcpy(b + elsize - n, tmp, n);
702 - elsize -= n;
703 - }
704 - }
705 -
706 - static void insertsort(
707 - void *els, size_t nel, size_t elsize,
708 - git__sort_r_cmp cmp, void *payload)
709 - {
710 - uint8_t *base = els;
711 - uint8_t *end = base + nel * elsize;
712 - uint8_t *i, *j;
713 -
714 - for (i = base + elsize; i < end; i += elsize)
715 - for (j = i; j > base && cmp(j, j - elsize, payload) < 0; j -= elsize)
716 - swap(j, j - elsize, elsize);
717 - }
718 - #endif
719 -
720 2984 2 void git__qsort_r(
721 - void *els, size_t nel, size_t elsize, git__sort_r_cmp cmp, void *payload)
722 - {
723 - #if defined(HAVE_QSORT_R_BSD)
724 - git__qsort_r_glue glue = { cmp, payload };
725 - qsort_r(els, nel, elsize, &glue, git__qsort_r_glue_cmp);
726 - #elif defined(HAVE_QSORT_R_GNU)
727 2984 2 qsort_r(els, nel, elsize, cmp, payload);
728 - #elif defined(HAVE_QSORT_S)
729 - git__qsort_r_glue glue = { cmp, payload };
730 - qsort_s(els, nel, elsize, git__qsort_r_glue_cmp, &glue);
731 - #else
732 - insertsort(els, nel, elsize, cmp, payload);
733 - #endif
734 2984 3 }
735 -
736 - /*
737 - * git__utf8_iterate is taken from the utf8proc project,
738 - * http://www.public-software-group.org/utf8proc
739 - *
740 - * Copyright (c) 2009 Public Software Group e. V., Berlin, Germany
741 - *
742 - * Permission is hereby granted, free of charge, to any person obtaining a
743 - * copy of this software and associated documentation files (the ""Software""),
744 - * to deal in the Software without restriction, including without limitation
745 - * the rights to use, copy, modify, merge, publish, distribute, sublicense,
746 - * and/or sell copies of the Software, and to permit persons to whom the
747 - * Software is furnished to do so, subject to the following conditions:
748 - *
749 - * The above copyright notice and this permission notice shall be included in
750 - * all copies or substantial portions of the Software.
751 - *
752 - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
753 - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
754 - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
755 - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
756 - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
757 - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
758 - * DEALINGS IN THE SOFTWARE.
759 - */
760 -
761 - static const int8_t utf8proc_utf8class[256] = {
762 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
763 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
764 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
765 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
766 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
767 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
768 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
769 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
770 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
771 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
772 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
773 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
774 - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
775 - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
776 - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
777 - 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0
778 - };
779 -
780 21290 2 static int util_utf8_charlen(const uint8_t *str, size_t str_len)
781 - {
782 - size_t length, i;
783 -
784 21290 2 length = utf8proc_utf8class[str[0]];
785 21290 2 if (!length)
786 2 3 return -1;
787 -
788 21288 4,5 if (str_len > 0 && length > str_len)
789 ##### 6 return -1;
790 -
791 21508 7,10,11 for (i = 1; i < length; i++) {
792 224 8 if ((str[i] & 0xC0) != 0x80)
793 4 9 return -1;
794 - }
795 -
796 21284 12 return (int)length;
797 - }
798 -
799 413 2 int git__utf8_iterate(const uint8_t *str, int str_len, int32_t *dst)
800 - {
801 - int length;
802 413 2 int32_t uc = -1;
803 -
804 413 2 *dst = -1;
805 413 2 length = util_utf8_charlen(str, str_len);
806 413 3 if (length < 0)
807 5 4 return -1;
808 -
809 408 5 switch (length) {
810 - case 1:
811 362 6 uc = str[0];
812 362 6 break;
813 - case 2:
814 ##### 7 uc = ((str[0] & 0x1F) << 6) + (str[1] & 0x3F);
815 ##### 7,8 if (uc < 0x80) uc = -1;
816 ##### 9 break;
817 - case 3:
818 46 10,10 uc = ((str[0] & 0x0F) << 12) + ((str[1] & 0x3F) << 6)
819 46 10 + (str[2] & 0x3F);
820 46 10-13 if (uc < 0x800 || (uc >= 0xD800 && uc < 0xE000) ||
821 3 14,15 (uc >= 0xFDD0 && uc < 0xFDF0)) uc = -1;
822 46 16 break;
823 - case 4:
824 ##### 17,17 uc = ((str[0] & 0x07) << 18) + ((str[1] & 0x3F) << 12)
825 ##### 17 + ((str[2] & 0x3F) << 6) + (str[3] & 0x3F);
826 ##### 17-19 if (uc < 0x10000 || uc >= 0x110000) uc = -1;
827 ##### 20 break;
828 - }
829 -
830 408 21,22 if (uc < 0 || ((uc & 0xFFFF) >= 0xFFFE))
831 ##### 23 return -1;
832 -
833 408 24 *dst = uc;
834 408 24 return length;
835 - }
836 -
837 945 2 size_t git__utf8_valid_buf_length(const uint8_t *str, size_t str_len)
838 - {
839 945 2 size_t offset = 0;
840 -
841 21821 2,7 while (offset < str_len) {
842 20877 3 int length = util_utf8_charlen(str + offset, str_len - offset);
843 -
844 20877 4 if (length < 0)
845 1 5 break;
846 -
847 20876 6 offset += length;
848 - }
849 -
850 945 8 return offset;
851 - }
852 -
853 - #ifdef GIT_WIN32
854 - int git__getenv(git_buf *out, const char *name)
855 - {
856 - wchar_t *wide_name = NULL, *wide_value = NULL;
857 - DWORD value_len;
858 - int error = -1;
859 -
860 - git_buf_clear(out);
861 -
862 - if (git__utf8_to_16_alloc(&wide_name, name) < 0)
863 - return -1;
864 -
865 - if ((value_len = GetEnvironmentVariableW(wide_name, NULL, 0)) > 0) {
866 - wide_value = git__malloc(value_len * sizeof(wchar_t));
867 - GIT_ERROR_CHECK_ALLOC(wide_value);
868 -
869 - value_len = GetEnvironmentVariableW(wide_name, wide_value, value_len);
870 - }
871 -
872 - if (value_len)
873 - error = git_buf_put_w(out, wide_value, value_len);
874 - else if (GetLastError() == ERROR_ENVVAR_NOT_FOUND)
875 - error = GIT_ENOTFOUND;
876 - else
877 - git_error_set(GIT_ERROR_OS, "could not read environment variable '%s'", name);
878 -
879 - git__free(wide_name);
880 - git__free(wide_value);
881 - return error;
882 - }
883 - #else
884 2045 2 int git__getenv(git_buf *out, const char *name)
885 - {
886 2045 2 const char *val = getenv(name);
887 -
888 2045 3 git_buf_clear(out);
889 -
890 2045 4 if (!val)
891 1911 5 return GIT_ENOTFOUND;
892 -
893 134 6 return git_buf_puts(out, val);
894 - }
895 - #endif