]>
git.proxmox.com Git - libgit2.git/blob - src/util.c
2 * Copyright (C) 2009-2012 the libgit2 contributors
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.
18 void git_libgit2_version(int *major
, int *minor
, int *rev
)
20 *major
= LIBGIT2_VER_MAJOR
;
21 *minor
= LIBGIT2_VER_MINOR
;
22 *rev
= LIBGIT2_VER_REVISION
;
25 int git_libgit2_capabilities()
31 #if defined(GIT_SSL) || defined(GIT_WINHTTP)
37 void git_strarray_free(git_strarray
*array
)
40 for (i
= 0; i
< array
->count
; ++i
)
41 git__free(array
->strings
[i
]);
43 git__free(array
->strings
);
46 int git_strarray_copy(git_strarray
*tgt
, const git_strarray
*src
)
52 memset(tgt
, 0, sizeof(*tgt
));
57 tgt
->strings
= git__calloc(src
->count
, sizeof(char *));
58 GITERR_CHECK_ALLOC(tgt
->strings
);
60 for (i
= 0; i
< src
->count
; ++i
) {
61 tgt
->strings
[tgt
->count
] = git__strdup(src
->strings
[i
]);
63 if (!tgt
->strings
[tgt
->count
]) {
64 git_strarray_free(tgt
);
65 memset(tgt
, 0, sizeof(*tgt
));
75 int git__strtol64(int64_t *result
, const char *nptr
, const char **endptr
, int base
)
79 int c
, ovfl
, v
, neg
, ndig
;
90 while (git__isspace(*p
))
96 if (*p
== '-' || *p
== '+')
108 if (p
[1] == 'x' || p
[1] == 'X') {
113 } else if (base
== 16 && *p
== '0') {
114 if (p
[1] == 'x' || p
[1] == 'X')
116 } else if (base
< 0 || 36 < base
)
120 * Non-empty sequence of digits
122 for (;; p
++,ndig
++) {
125 if ('0'<=c
&& c
<='9')
127 else if ('a'<=c
&& c
<='z')
129 else if ('A'<=c
&& c
<='Z')
141 giterr_set(GITERR_INVALID
, "Failed to convert string to long. Not a number");
149 giterr_set(GITERR_INVALID
, "Failed to convert string to long. Overflow error");
153 *result
= neg
? -n
: n
;
157 int git__strtol32(int32_t *result
, const char *nptr
, const char **endptr
, int base
)
163 if ((error
= git__strtol64(&tmp_long
, nptr
, endptr
, base
)) < 0)
166 tmp_int
= tmp_long
& 0xFFFFFFFF;
167 if (tmp_int
!= tmp_long
) {
168 giterr_set(GITERR_INVALID
, "Failed to convert. '%s' is too large", nptr
);
177 int git__strcmp(const char *a
, const char *b
)
179 while (*a
&& *b
&& *a
== *b
)
181 return (int)(*(const unsigned char *)a
) - (int)(*(const unsigned char *)b
);
184 int git__strcasecmp(const char *a
, const char *b
)
186 while (*a
&& *b
&& tolower(*a
) == tolower(*b
))
188 return (tolower(*a
) - tolower(*b
));
191 int git__strncmp(const char *a
, const char *b
, size_t sz
)
193 while (sz
&& *a
&& *b
&& *a
== *b
)
197 return (int)(*(const unsigned char *)a
) - (int)(*(const unsigned char *)b
);
200 int git__strncasecmp(const char *a
, const char *b
, size_t sz
)
205 al
= (unsigned char)tolower(*a
);
206 bl
= (unsigned char)tolower(*b
);
208 } while (--sz
&& al
&& al
== bl
);
213 void git__strntolower(char *str
, size_t len
)
217 for (i
= 0; i
< len
; ++i
) {
218 str
[i
] = (char) tolower(str
[i
]);
222 void git__strtolower(char *str
)
224 git__strntolower(str
, strlen(str
));
227 int git__prefixcmp(const char *str
, const char *prefix
)
230 unsigned char p
= *(prefix
++), s
;
233 if ((s
= *(str
++)) != p
)
238 int git__prefixcmp_icase(const char *str
, const char *prefix
)
240 return strncasecmp(str
, prefix
, strlen(prefix
));
243 int git__suffixcmp(const char *str
, const char *suffix
)
245 size_t a
= strlen(str
);
246 size_t b
= strlen(suffix
);
249 return strcmp(str
+ (a
- b
), suffix
);
252 char *git__strtok(char **end
, const char *sep
)
256 while (*ptr
&& strchr(sep
, *ptr
))
263 while (**end
&& !strchr(sep
, **end
))
277 /* Similar to strtok, but does not collapse repeated tokens. */
278 char *git__strsep(char **end
, const char *sep
)
280 char *start
= *end
, *ptr
= *end
;
282 while (*ptr
&& !strchr(sep
, *ptr
))
295 void git__hexdump(const char *buffer
, size_t len
)
297 static const size_t LINE_WIDTH
= 16;
299 size_t line_count
, last_line
, i
, j
;
302 line_count
= (len
/ LINE_WIDTH
);
303 last_line
= (len
% LINE_WIDTH
);
305 for (i
= 0; i
< line_count
; ++i
) {
306 line
= buffer
+ (i
* LINE_WIDTH
);
307 for (j
= 0; j
< LINE_WIDTH
; ++j
, ++line
)
308 printf("%02X ", (unsigned char)*line
& 0xFF);
312 line
= buffer
+ (i
* LINE_WIDTH
);
313 for (j
= 0; j
< LINE_WIDTH
; ++j
, ++line
)
314 printf("%c", (*line
>= 32 && *line
<= 126) ? *line
: '.');
321 line
= buffer
+ (line_count
* LINE_WIDTH
);
322 for (j
= 0; j
< last_line
; ++j
, ++line
)
323 printf("%02X ", (unsigned char)*line
& 0xFF);
325 for (j
= 0; j
< (LINE_WIDTH
- last_line
); ++j
)
330 line
= buffer
+ (line_count
* LINE_WIDTH
);
331 for (j
= 0; j
< last_line
; ++j
, ++line
)
332 printf("%c", (*line
>= 32 && *line
<= 126) ? *line
: '.');
340 #ifdef GIT_LEGACY_HASH
341 uint32_t git__hash(const void *key
, int len
, unsigned int seed
)
343 const uint32_t m
= 0x5bd1e995;
345 uint32_t h
= seed
^ len
;
347 const unsigned char *data
= (const unsigned char *)key
;
350 uint32_t k
= *(uint32_t *)data
;
364 case 3: h
^= data
[2] << 16;
365 case 2: h
^= data
[1] << 8;
366 case 1: h
^= data
[0];
378 Cross-platform version of Murmurhash3
379 http://code.google.com/p/smhasher/wiki/MurmurHash3
380 by Austin Appleby (aappleby@gmail.com)
382 This code is on the public domain.
384 uint32_t git__hash(const void *key
, int len
, uint32_t seed
)
387 #define MURMUR_BLOCK() {\
389 k1 = git__rotl(k1,11);\
392 h1 = h1*3 + 0x52dce729;\
393 c1 = c1*5 + 0x7b7d159c;\
394 c2 = c2*5 + 0x6bce6396;\
397 const uint8_t *data
= (const uint8_t*)key
;
398 const int nblocks
= len
/ 4;
400 const uint32_t *blocks
= (const uint32_t *)(data
+ nblocks
* 4);
401 const uint8_t *tail
= (const uint8_t *)(data
+ nblocks
* 4);
403 uint32_t h1
= 0x971e137b ^ seed
;
406 uint32_t c1
= 0x95543787;
407 uint32_t c2
= 0x2ad7eb25;
411 for (i
= -nblocks
; i
; i
++) {
419 case 3: k1
^= tail
[2] << 16;
420 case 2: k1
^= tail
[1] << 8;
421 case 1: k1
^= tail
[0];
437 * A modified `bsearch` from the BSD glibc.
439 * Copyright (c) 1990 Regents of the University of California.
440 * All rights reserved.
441 * Redistribution and use in source and binary forms, with or without
442 * modification, are permitted provided that the following conditions
444 * 1. Redistributions of source code must retain the above copyright
445 * notice, this list of conditions and the following disclaimer.
446 * 2. Redistributions in binary form must reproduce the above copyright
447 * notice, this list of conditions and the following disclaimer in the
448 * documentation and/or other materials provided with the distribution.
449 * 3. [rescinded 22 July 1999]
450 * 4. Neither the name of the University nor the names of its contributors
451 * may be used to endorse or promote products derived from this software
452 * without specific prior written permission.
454 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
455 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
456 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
457 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
458 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
459 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
460 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
461 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
462 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
463 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
470 int (*compare
)(const void *, const void *),
475 void **part
, **base
= array
;
477 for (lim
= (unsigned int)array_len
; lim
!= 0; lim
>>= 1) {
478 part
= base
+ (lim
>> 1);
479 cmp
= (*compare
)(key
, *part
);
484 if (cmp
> 0) { /* key > p; take right partition */
487 } /* else take left partition */
491 *position
= (base
- array
);
493 return (cmp
== 0) ? 0 : -1;
499 * We don't want direct pointers to the CRT on Windows, we may
500 * get stdcall conflicts.
502 int git__strcmp_cb(const void *a
, const void *b
)
504 const char *stra
= (const char *)a
;
505 const char *strb
= (const char *)b
;
507 return strcmp(stra
, strb
);
510 int git__parse_bool(int *out
, const char *value
)
512 /* A missing value means true */
514 !strcasecmp(value
, "true") ||
515 !strcasecmp(value
, "yes") ||
516 !strcasecmp(value
, "on")) {
520 if (!strcasecmp(value
, "false") ||
521 !strcasecmp(value
, "no") ||
522 !strcasecmp(value
, "off") ||
531 size_t git__unescape(char *str
)
533 char *scan
, *pos
= str
;
535 for (scan
= str
; *scan
; pos
++, scan
++) {
536 if (*scan
== '\\' && *(scan
+ 1) != '\0')
537 scan
++; /* skip '\' but include next char */