source src/util.c
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 |