]> git.proxmox.com Git - libgit2.git/blame - src/util.c
config: rename get_config_entry -> config_entry
[libgit2.git] / src / util.c
CommitLineData
bb742ede 1/*
5e0de328 2 * Copyright (C) 2009-2012 the libgit2 contributors
bb742ede
VM
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
e564e496
SC
25int git_libgit2_capabilities()
26{
27 return 0
28#ifdef GIT_THREADS
29 | GIT_CAP_THREADS
30#endif
3ce22c74 31#if defined(GIT_SSL) || defined(GIT_WINHTTP)
e564e496
SC
32 | GIT_CAP_HTTPS
33#endif
34 ;
35}
36
955f9ae9
VM
37void git_strarray_free(git_strarray *array)
38{
39 size_t i;
40 for (i = 0; i < array->count; ++i)
3286c408 41 git__free(array->strings[i]);
955f9ae9 42
3286c408 43 git__free(array->strings);
955f9ae9
VM
44}
45
14a513e0
RB
46int git_strarray_copy(git_strarray *tgt, const git_strarray *src)
47{
48 size_t i;
49
50 assert(tgt && src);
51
52 memset(tgt, 0, sizeof(*tgt));
53
54 if (!src->count)
55 return 0;
56
57 tgt->strings = git__calloc(src->count, sizeof(char *));
58 GITERR_CHECK_ALLOC(tgt->strings);
59
60 for (i = 0; i < src->count; ++i) {
61 tgt->strings[tgt->count] = git__strdup(src->strings[i]);
62
63 if (!tgt->strings[tgt->count]) {
64 git_strarray_free(tgt);
65 memset(tgt, 0, sizeof(*tgt));
66 return -1;
67 }
68
69 tgt->count++;
70 }
71
72 return 0;
73}
74
fafd4710 75int git__strtol64(int64_t *result, const char *nptr, const char **endptr, int base)
c6e65aca
VM
76{
77 const char *p;
fafd4710 78 int64_t n, nn;
c6e65aca
VM
79 int c, ovfl, v, neg, ndig;
80
81 p = nptr;
82 neg = 0;
83 n = 0;
84 ndig = 0;
85 ovfl = 0;
86
87 /*
88 * White space
89 */
0f49200c 90 while (git__isspace(*p))
c6e65aca
VM
91 p++;
92
93 /*
94 * Sign
95 */
96 if (*p == '-' || *p == '+')
97 if (*p++ == '-')
98 neg = 1;
99
100 /*
101 * Base
102 */
103 if (base == 0) {
104 if (*p != '0')
105 base = 10;
106 else {
107 base = 8;
108 if (p[1] == 'x' || p[1] == 'X') {
109 p += 2;
110 base = 16;
111 }
112 }
113 } else if (base == 16 && *p == '0') {
114 if (p[1] == 'x' || p[1] == 'X')
115 p += 2;
116 } else if (base < 0 || 36 < base)
117 goto Return;
118
119 /*
120 * Non-empty sequence of digits
121 */
122 for (;; p++,ndig++) {
123 c = *p;
124 v = base;
125 if ('0'<=c && c<='9')
126 v = c - '0';
127 else if ('a'<=c && c<='z')
128 v = c - 'a' + 10;
129 else if ('A'<=c && c<='Z')
130 v = c - 'A' + 10;
131 if (v >= base)
132 break;
133 nn = n*base + v;
134 if (nn < n)
135 ovfl = 1;
136 n = nn;
137 }
138
139Return:
7c7ff7d1
RB
140 if (ndig == 0) {
141 giterr_set(GITERR_INVALID, "Failed to convert string to long. Not a number");
142 return -1;
143 }
c6e65aca
VM
144
145 if (endptr)
146 *endptr = p;
147
7c7ff7d1
RB
148 if (ovfl) {
149 giterr_set(GITERR_INVALID, "Failed to convert string to long. Overflow error");
150 return -1;
151 }
c6e65aca
VM
152
153 *result = neg ? -n : n;
7c7ff7d1 154 return 0;
c6e65aca
VM
155}
156
fafd4710 157int git__strtol32(int32_t *result, const char *nptr, const char **endptr, int base)
ad196c6a 158{
7c7ff7d1 159 int error;
fafd4710
VM
160 int32_t tmp_int;
161 int64_t tmp_long;
ad196c6a 162
7c7ff7d1 163 if ((error = git__strtol64(&tmp_long, nptr, endptr, base)) < 0)
ad196c6a 164 return error;
165
166 tmp_int = tmp_long & 0xFFFFFFFF;
7c7ff7d1
RB
167 if (tmp_int != tmp_long) {
168 giterr_set(GITERR_INVALID, "Failed to convert. '%s' is too large", nptr);
169 return -1;
170 }
ad196c6a 171
172 *result = tmp_int;
7c7ff7d1 173
ad196c6a 174 return error;
175}
176
26e74c6a 177void git__strntolower(char *str, size_t len)
0da2c700 178{
26e74c6a 179 size_t i;
0da2c700
VM
180
181 for (i = 0; i < len; ++i) {
3a1c4310 182 str[i] = (char) tolower(str[i]);
0da2c700
VM
183 }
184}
185
186void git__strtolower(char *str)
187{
188 git__strntolower(str, strlen(str));
189}
190
9eb79764
SP
191int git__prefixcmp(const char *str, const char *prefix)
192{
193 for (;;) {
8e60c712 194 unsigned char p = *(prefix++), s;
9eb79764
SP
195 if (!p)
196 return 0;
197 if ((s = *(str++)) != p)
198 return s - p;
199 }
200}
201
ec40b7f9
PK
202int git__prefixcmp_icase(const char *str, const char *prefix)
203{
204 return strncasecmp(str, prefix, strlen(prefix));
205}
206
9eb79764
SP
207int git__suffixcmp(const char *str, const char *suffix)
208{
209 size_t a = strlen(str);
210 size_t b = strlen(suffix);
211 if (a < b)
212 return -1;
213 return strcmp(str + (a - b), suffix);
214}
ced645ea 215
0291b5b7 216char *git__strtok(char **end, const char *sep)
f725931b 217{
0291b5b7 218 char *ptr = *end;
ced645ea 219
0291b5b7
VM
220 while (*ptr && strchr(sep, *ptr))
221 ++ptr;
f725931b 222
0291b5b7
VM
223 if (*ptr) {
224 char *start = ptr;
225 *end = start + 1;
ced645ea 226
0291b5b7
VM
227 while (**end && !strchr(sep, **end))
228 ++*end;
f725931b 229
0291b5b7
VM
230 if (**end) {
231 **end = '\0';
232 ++*end;
233 }
234
235 return start;
236 }
237
238 return NULL;
ced645ea
RJ
239}
240
0e465f97
VM
241void git__hexdump(const char *buffer, size_t len)
242{
243 static const size_t LINE_WIDTH = 16;
244
245 size_t line_count, last_line, i, j;
246 const char *line;
247
248 line_count = (len / LINE_WIDTH);
249 last_line = (len % LINE_WIDTH);
250
251 for (i = 0; i < line_count; ++i) {
252 line = buffer + (i * LINE_WIDTH);
253 for (j = 0; j < LINE_WIDTH; ++j, ++line)
254 printf("%02X ", (unsigned char)*line & 0xFF);
255
256 printf("| ");
257
258 line = buffer + (i * LINE_WIDTH);
259 for (j = 0; j < LINE_WIDTH; ++j, ++line)
260 printf("%c", (*line >= 32 && *line <= 126) ? *line : '.');
261
262 printf("\n");
263 }
264
265 if (last_line > 0) {
266
267 line = buffer + (line_count * LINE_WIDTH);
268 for (j = 0; j < last_line; ++j, ++line)
269 printf("%02X ", (unsigned char)*line & 0xFF);
270
271 for (j = 0; j < (LINE_WIDTH - last_line); ++j)
87d9869f 272 printf(" ");
0e465f97
VM
273
274 printf("| ");
275
276 line = buffer + (line_count * LINE_WIDTH);
277 for (j = 0; j < last_line; ++j, ++line)
278 printf("%c", (*line >= 32 && *line <= 126) ? *line : '.');
279
280 printf("\n");
281 }
282
283 printf("\n");
284}
e0646b38
VM
285
286#ifdef GIT_LEGACY_HASH
287uint32_t git__hash(const void *key, int len, unsigned int seed)
288{
289 const uint32_t m = 0x5bd1e995;
290 const int r = 24;
291 uint32_t h = seed ^ len;
292
293 const unsigned char *data = (const unsigned char *)key;
294
295 while(len >= 4) {
296 uint32_t k = *(uint32_t *)data;
297
932d1baf
KS
298 k *= m;
299 k ^= k >> r;
300 k *= m;
301
302 h *= m;
e0646b38
VM
303 h ^= k;
304
305 data += 4;
306 len -= 4;
307 }
932d1baf 308
e0646b38
VM
309 switch(len) {
310 case 3: h ^= data[2] << 16;
311 case 2: h ^= data[1] << 8;
312 case 1: h ^= data[0];
87d9869f 313 h *= m;
e0646b38
VM
314 };
315
316 h ^= h >> 13;
317 h *= m;
318 h ^= h >> 15;
319
320 return h;
932d1baf 321}
e0646b38
VM
322#else
323/*
324 Cross-platform version of Murmurhash3
325 http://code.google.com/p/smhasher/wiki/MurmurHash3
326 by Austin Appleby (aappleby@gmail.com)
327
328 This code is on the public domain.
329*/
330uint32_t git__hash(const void *key, int len, uint32_t seed)
331{
332
333#define MURMUR_BLOCK() {\
87d9869f
VM
334 k1 *= c1; \
335 k1 = git__rotl(k1,11);\
336 k1 *= c2;\
337 h1 ^= k1;\
338 h1 = h1*3 + 0x52dce729;\
339 c1 = c1*5 + 0x7b7d159c;\
340 c2 = c2*5 + 0x6bce6396;\
e0646b38
VM
341}
342
343 const uint8_t *data = (const uint8_t*)key;
344 const int nblocks = len / 4;
345
346 const uint32_t *blocks = (const uint32_t *)(data + nblocks * 4);
347 const uint8_t *tail = (const uint8_t *)(data + nblocks * 4);
348
349 uint32_t h1 = 0x971e137b ^ seed;
350 uint32_t k1;
351
352 uint32_t c1 = 0x95543787;
353 uint32_t c2 = 0x2ad7eb25;
354
355 int i;
356
357 for (i = -nblocks; i; i++) {
358 k1 = blocks[i];
359 MURMUR_BLOCK();
360 }
361
362 k1 = 0;
363
364 switch(len & 3) {
365 case 3: k1 ^= tail[2] << 16;
366 case 2: k1 ^= tail[1] << 8;
367 case 1: k1 ^= tail[0];
368 MURMUR_BLOCK();
369 }
370
371 h1 ^= len;
372 h1 ^= h1 >> 16;
373 h1 *= 0x85ebca6b;
374 h1 ^= h1 >> 13;
375 h1 *= 0xc2b2ae35;
376 h1 ^= h1 >> 16;
377
378 return h1;
932d1baf 379}
e0646b38 380#endif
c20ffa61 381
de18f276
VM
382/**
383 * A modified `bsearch` from the BSD glibc.
384 *
385 * Copyright (c) 1990 Regents of the University of California.
386 * All rights reserved.
c20ffa61 387 */
bd370b14
RB
388int git__bsearch(
389 void **array,
390 size_t array_len,
391 const void *key,
392 int (*compare)(const void *, const void *),
393 size_t *position)
c20ffa61 394{
44ef8b1b
RB
395 unsigned int lim;
396 int cmp = -1;
bd370b14
RB
397 void **part, **base = array;
398
44ef8b1b 399 for (lim = (unsigned int)array_len; lim != 0; lim >>= 1) {
bd370b14
RB
400 part = base + (lim >> 1);
401 cmp = (*compare)(key, *part);
402 if (cmp == 0) {
ae9e29fd
RB
403 base = part;
404 break;
405 }
406 if (cmp > 0) { /* key > p; take right partition */
bd370b14
RB
407 base = part + 1;
408 lim--;
409 } /* else take left partition */
410 }
411
ae9e29fd
RB
412 if (position)
413 *position = (base - array);
414
415 return (cmp == 0) ? 0 : -1;
c20ffa61
KS
416}
417
d1f34693 418/**
419 * A strcmp wrapper
420 *
421 * We don't want direct pointers to the CRT on Windows, we may
422 * get stdcall conflicts.
423 */
424int git__strcmp_cb(const void *a, const void *b)
425{
426 const char *stra = (const char *)a;
427 const char *strb = (const char *)b;
428
429 return strcmp(stra, strb);
84dd3820 430}
29e948de
VM
431
432int git__parse_bool(int *out, const char *value)
433{
434 /* A missing value means true */
435 if (value == NULL) {
436 *out = 1;
437 return 0;
438 }
439
440 if (!strcasecmp(value, "true") ||
441 !strcasecmp(value, "yes") ||
442 !strcasecmp(value, "on")) {
443 *out = 1;
444 return 0;
445 }
446 if (!strcasecmp(value, "false") ||
447 !strcasecmp(value, "no") ||
448 !strcasecmp(value, "off")) {
449 *out = 0;
450 return 0;
451 }
452
453 return -1;
454}
02a0d651 455
456size_t git__unescape(char *str)
457{
458 char *scan, *pos = str;
459
460 for (scan = str; *scan; pos++, scan++) {
461 if (*scan == '\\' && *(scan + 1) != '\0')
462 scan++; /* skip '\' but include next char */
463 if (pos != scan)
464 *pos = *scan;
465 }
466
467 if (pos != scan) {
468 *pos = '\0';
469 }
470
471 return (pos - str);
472}