]>
git.proxmox.com Git - libgit2.git/blob - src/util.c
1 #define GIT__NO_HIDE_MALLOC
15 void git_libgit2_version(int *major
, int *minor
, int *rev
)
17 *major
= LIBGIT2_VER_MAJOR
;
18 *minor
= LIBGIT2_VER_MINOR
;
19 *rev
= LIBGIT2_VER_REVISION
;
22 void git_strarray_free(git_strarray
*array
)
25 for (i
= 0; i
< array
->count
; ++i
)
26 free(array
->strings
[i
]);
31 int git__fnmatch(const char *pattern
, const char *name
, int flags
)
35 ret
= fnmatch(pattern
, name
, flags
);
42 return git__throw(GIT_EOSERR
, "Error trying to match path");
46 int git__strtol32(long *result
, const char *nptr
, const char **endptr
, int base
)
50 int c
, ovfl
, v
, neg
, ndig
;
67 if (*p
== '-' || *p
== '+')
79 if (p
[1] == 'x' || p
[1] == 'X') {
84 } else if (base
== 16 && *p
== '0') {
85 if (p
[1] == 'x' || p
[1] == 'X')
87 } else if (base
< 0 || 36 < base
)
91 * Non-empty sequence of digits
98 else if ('a'<=c
&& c
<='z')
100 else if ('A'<=c
&& c
<='Z')
112 return git__throw(GIT_ENOTNUM
, "Failed to convert string to long. Not a number");
118 return git__throw(GIT_EOVERFLOW
, "Failed to convert string to long. Overflow error");
120 *result
= neg
? -n
: n
;
124 int git__fmt(char *buf
, size_t buf_sz
, const char *fmt
, ...)
130 r
= vsnprintf(buf
, buf_sz
, fmt
, va
);
132 if (r
< 0 || ((size_t) r
) >= buf_sz
)
133 return git__throw(GIT_ERROR
, "Failed to format string");
137 void git__strntolower(char *str
, int len
)
141 for (i
= 0; i
< len
; ++i
) {
142 str
[i
] = (char) tolower(str
[i
]);
146 void git__strtolower(char *str
)
148 git__strntolower(str
, strlen(str
));
151 int git__prefixcmp(const char *str
, const char *prefix
)
154 char p
= *(prefix
++), s
;
157 if ((s
= *(str
++)) != p
)
162 int git__suffixcmp(const char *str
, const char *suffix
)
164 size_t a
= strlen(str
);
165 size_t b
= strlen(suffix
);
168 return strcmp(str
+ (a
- b
), suffix
);
172 * Based on the Android implementation, BSD licensed.
173 * Check http://android.git.kernel.org/
175 int git__basename_r(char *buffer
, size_t bufflen
, const char *path
)
177 const char *endp
, *startp
;
180 /* Empty or NULL string gets treated as "." */
181 if (path
== NULL
|| *path
== '\0') {
187 /* Strip trailing slashes */
188 endp
= path
+ strlen(path
) - 1;
189 while (endp
> path
&& *endp
== '/')
192 /* All slashes becomes "/" */
193 if (endp
== path
&& *endp
== '/') {
199 /* Find the start of the base */
201 while (startp
> path
&& *(startp
- 1) != '/')
204 len
= endp
- startp
+1;
208 if (buffer
== NULL
) {
211 if (len
> (int)bufflen
-1) {
212 len
= (int)bufflen
-1;
217 memmove(buffer
, startp
, len
);
224 * Based on the Android implementation, BSD licensed.
225 * Check http://android.git.kernel.org/
227 int git__dirname_r(char *buffer
, size_t bufflen
, const char *path
)
232 /* Empty or NULL string gets treated as "." */
233 if (path
== NULL
|| *path
== '\0') {
239 /* Strip trailing slashes */
240 endp
= path
+ strlen(path
) - 1;
241 while (endp
> path
&& *endp
== '/')
244 /* Find the start of the dir */
245 while (endp
> path
&& *endp
!= '/')
248 /* Either the dir is "/" or there are no slashes */
250 path
= (*endp
== '/') ? "/" : ".";
257 } while (endp
> path
&& *endp
== '/');
259 len
= endp
- path
+1;
263 if (len
+1 > GIT_PATH_MAX
) {
269 if (len
> (int)bufflen
-1) {
270 len
= (int)bufflen
-1;
275 memmove(buffer
, path
, len
);
282 char *git__dirname(const char *path
)
287 len
= (path
? strlen(path
) : 0) + 2;
288 dname
= (char *)git__malloc(len
);
292 if (git__dirname_r(dname
, len
, path
) < GIT_SUCCESS
) {
300 char *git__basename(const char *path
)
305 len
= (path
? strlen(path
) : 0) + 2;
306 bname
= (char *)git__malloc(len
);
310 if (git__basename_r(bname
, len
, path
) < GIT_SUCCESS
) {
319 const char *git__topdir(const char *path
)
327 if (!len
|| path
[len
- 1] != '/')
330 for (i
= len
- 2; i
>= 0; --i
)
337 void git__joinpath_n(char *buffer_out
, int count
, ...)
341 char *buffer_start
= buffer_out
;
344 for (i
= 0; i
< count
; ++i
) {
348 path
= va_arg(ap
, const char *);
350 assert((i
== 0) || path
!= buffer_start
);
352 if (i
> 0 && *path
== '/' && buffer_out
> buffer_start
&& buffer_out
[-1] == '/')
359 memmove(buffer_out
, path
, len
);
360 buffer_out
= buffer_out
+ len
;
362 if (i
< count
- 1 && buffer_out
[-1] != '/')
370 char *git__strtok(char **end
, const char *sep
)
374 while (*ptr
&& strchr(sep
, *ptr
))
381 while (**end
&& !strchr(sep
, **end
))
395 void git__hexdump(const char *buffer
, size_t len
)
397 static const size_t LINE_WIDTH
= 16;
399 size_t line_count
, last_line
, i
, j
;
402 line_count
= (len
/ LINE_WIDTH
);
403 last_line
= (len
% LINE_WIDTH
);
405 for (i
= 0; i
< line_count
; ++i
) {
406 line
= buffer
+ (i
* LINE_WIDTH
);
407 for (j
= 0; j
< LINE_WIDTH
; ++j
, ++line
)
408 printf("%02X ", (unsigned char)*line
& 0xFF);
412 line
= buffer
+ (i
* LINE_WIDTH
);
413 for (j
= 0; j
< LINE_WIDTH
; ++j
, ++line
)
414 printf("%c", (*line
>= 32 && *line
<= 126) ? *line
: '.');
421 line
= buffer
+ (line_count
* LINE_WIDTH
);
422 for (j
= 0; j
< last_line
; ++j
, ++line
)
423 printf("%02X ", (unsigned char)*line
& 0xFF);
425 for (j
= 0; j
< (LINE_WIDTH
- last_line
); ++j
)
430 line
= buffer
+ (line_count
* LINE_WIDTH
);
431 for (j
= 0; j
< last_line
; ++j
, ++line
)
432 printf("%c", (*line
>= 32 && *line
<= 126) ? *line
: '.');
440 #ifdef GIT_LEGACY_HASH
441 uint32_t git__hash(const void *key
, int len
, unsigned int seed
)
443 const uint32_t m
= 0x5bd1e995;
445 uint32_t h
= seed
^ len
;
447 const unsigned char *data
= (const unsigned char *)key
;
450 uint32_t k
= *(uint32_t *)data
;
464 case 3: h
^= data
[2] << 16;
465 case 2: h
^= data
[1] << 8;
466 case 1: h
^= data
[0];
478 Cross-platform version of Murmurhash3
479 http://code.google.com/p/smhasher/wiki/MurmurHash3
480 by Austin Appleby (aappleby@gmail.com)
482 This code is on the public domain.
484 uint32_t git__hash(const void *key
, int len
, uint32_t seed
)
487 #define MURMUR_BLOCK() {\
489 k1 = git__rotl(k1,11);\
492 h1 = h1*3 + 0x52dce729;\
493 c1 = c1*5 + 0x7b7d159c;\
494 c2 = c2*5 + 0x6bce6396;\
497 const uint8_t *data
= (const uint8_t*)key
;
498 const int nblocks
= len
/ 4;
500 const uint32_t *blocks
= (const uint32_t *)(data
+ nblocks
* 4);
501 const uint8_t *tail
= (const uint8_t *)(data
+ nblocks
* 4);
503 uint32_t h1
= 0x971e137b ^ seed
;
506 uint32_t c1
= 0x95543787;
507 uint32_t c2
= 0x2ad7eb25;
511 for (i
= -nblocks
; i
; i
++) {
519 case 3: k1
^= tail
[2] << 16;
520 case 2: k1
^= tail
[1] << 8;
521 case 1: k1
^= tail
[0];