File Coverage

deps/libgit2/src/util/util.h
Criterion Covered Total %
statement 0 8 0.0
branch 0 4 0.0
condition n/a
subroutine n/a
pod n/a
total 0 12 0.0


line stmt bran cond sub pod time code
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             #ifndef INCLUDE_util_h__
8             #define INCLUDE_util_h__
9              
10             #ifndef GIT_WIN32
11             # include
12             #endif
13              
14             #include "str.h"
15             #include "git2_util.h"
16             #include "strnlen.h"
17             #include "thread.h"
18              
19             #define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
20             #define bitsizeof(x) (CHAR_BIT * sizeof(x))
21             #define MSB(x, bits) ((x) & (~UINT64_C(0) << (bitsizeof(x) - (bits))))
22             #ifndef min
23             # define min(a,b) ((a) < (b) ? (a) : (b))
24             #endif
25             #ifndef max
26             # define max(a,b) ((a) > (b) ? (a) : (b))
27             #endif
28              
29             #if defined(__GNUC__)
30             # define GIT_CONTAINER_OF(ptr, type, member) \
31             __builtin_choose_expr( \
32             __builtin_offsetof(type, member) == 0 && \
33             __builtin_types_compatible_p(__typeof__(&((type *) 0)->member), __typeof__(ptr)), \
34             ((type *) (ptr)), \
35             (void)0)
36             #else
37             # define GIT_CONTAINER_OF(ptr, type, member) (type *)(ptr)
38             #endif
39              
40             /**
41             * Return the length of a constant string.
42             * We are aware that `strlen` performs the same task and is usually
43             * optimized away by the compiler, whilst being safer because it returns
44             * valid values when passed a pointer instead of a constant string; however
45             * this macro will transparently work with wide-char and single-char strings.
46             */
47             #define CONST_STRLEN(x) ((sizeof(x)/sizeof(x[0])) - 1)
48              
49             #define STRCMP_CASESELECT(IGNORE_CASE, STR1, STR2) \
50             ((IGNORE_CASE) ? strcasecmp((STR1), (STR2)) : strcmp((STR1), (STR2)))
51              
52             #define CASESELECT(IGNORE_CASE, ICASE, CASE) \
53             ((IGNORE_CASE) ? (ICASE) : (CASE))
54              
55             extern int git__prefixcmp(const char *str, const char *prefix);
56             extern int git__prefixcmp_icase(const char *str, const char *prefix);
57             extern int git__prefixncmp(const char *str, size_t str_n, const char *prefix);
58             extern int git__prefixncmp_icase(const char *str, size_t str_n, const char *prefix);
59             extern int git__suffixcmp(const char *str, const char *suffix);
60              
61             GIT_INLINE(int) git__signum(int val)
62             {
63             return ((val > 0) - (val < 0));
64             }
65              
66             extern int git__strntol32(int32_t *n, const char *buff, size_t buff_len, const char **end_buf, int base);
67             extern int git__strntol64(int64_t *n, const char *buff, size_t buff_len, const char **end_buf, int base);
68              
69              
70             extern void git__hexdump(const char *buffer, size_t n);
71             extern uint32_t git__hash(const void *key, int len, uint32_t seed);
72              
73             /* 32-bit cross-platform rotl */
74             #ifdef _MSC_VER /* use built-in method in MSVC */
75             # define git__rotl(v, s) (uint32_t)_rotl(v, s)
76             #else /* use bitops in GCC; with o2 this gets optimized to a rotl instruction */
77             # define git__rotl(v, s) (uint32_t)(((uint32_t)(v) << (s)) | ((uint32_t)(v) >> (32 - (s))))
78             #endif
79              
80             extern char *git__strtok(char **end, const char *sep);
81             extern char *git__strsep(char **end, const char *sep);
82              
83             extern void git__strntolower(char *str, size_t len);
84             extern void git__strtolower(char *str);
85              
86             #ifdef GIT_WIN32
87             GIT_INLINE(int) git__tolower(int c)
88             {
89             return (c >= 'A' && c <= 'Z') ? (c + 32) : c;
90             }
91             #else
92             # define git__tolower(a) tolower(a)
93             #endif
94              
95             extern size_t git__linenlen(const char *buffer, size_t buffer_len);
96              
97             GIT_INLINE(const char *) git__next_line(const char *s)
98             {
99             while (*s && *s != '\n') s++;
100             while (*s == '\n' || *s == '\r') s++;
101             return s;
102             }
103              
104             GIT_INLINE(const void *) git__memrchr(const void *s, int c, size_t n)
105             {
106             const unsigned char *cp;
107              
108             if (n != 0) {
109             cp = (unsigned char *)s + n;
110             do {
111             if (*(--cp) == (unsigned char)c)
112             return cp;
113             } while (--n != 0);
114             }
115              
116             return NULL;
117             }
118              
119             extern const void * git__memmem(const void *haystack, size_t haystacklen,
120             const void *needle, size_t needlelen);
121              
122             typedef int (*git__tsort_cmp)(const void *a, const void *b);
123              
124             extern void git__tsort(void **dst, size_t size, git__tsort_cmp cmp);
125              
126             typedef int (*git__sort_r_cmp)(const void *a, const void *b, void *payload);
127              
128             extern void git__tsort_r(
129             void **dst, size_t size, git__sort_r_cmp cmp, void *payload);
130              
131             extern void git__qsort_r(
132             void *els, size_t nel, size_t elsize, git__sort_r_cmp cmp, void *payload);
133              
134             /**
135             * @param position If non-NULL, this will be set to the position where the
136             * element is or would be inserted if not found.
137             * @return 0 if found; GIT_ENOTFOUND if not found
138             */
139             extern int git__bsearch(
140             void **array,
141             size_t array_len,
142             const void *key,
143             int (*compare)(const void *key, const void *element),
144             size_t *position);
145              
146             extern int git__bsearch_r(
147             void **array,
148             size_t array_len,
149             const void *key,
150             int (*compare_r)(const void *key, const void *element, void *payload),
151             void *payload,
152             size_t *position);
153              
154             #define git__strcmp strcmp
155             #define git__strncmp strncmp
156              
157             extern int git__strcmp_cb(const void *a, const void *b);
158             extern int git__strcasecmp_cb(const void *a, const void *b);
159              
160             extern int git__strcasecmp(const char *a, const char *b);
161             extern int git__strncasecmp(const char *a, const char *b, size_t sz);
162              
163             extern int git__strcasesort_cmp(const char *a, const char *b);
164              
165             /*
166             * Compare some NUL-terminated `a` to a possibly non-NUL terminated
167             * `b` of length `b_len`; like `strncmp` but ensuring that
168             * `strlen(a) == b_len` as well.
169             */
170 0           GIT_INLINE(int) git__strlcmp(const char *a, const char *b, size_t b_len)
171             {
172 0           int cmp = strncmp(a, b, b_len);
173 0 0         return cmp ? cmp : (int)a[b_len];
174             }
175              
176             typedef struct {
177             git_atomic32 refcount;
178             void *owner;
179             } git_refcount;
180              
181             typedef void (*git_refcount_freeptr)(void *r);
182              
183             #define GIT_REFCOUNT_INC(r) { \
184             git_atomic32_inc(&(r)->rc.refcount); \
185             }
186              
187             #define GIT_REFCOUNT_DEC(_r, do_free) { \
188             git_refcount *r = &(_r)->rc; \
189             int val = git_atomic32_dec(&r->refcount); \
190             if (val <= 0 && r->owner == NULL) { do_free(_r); } \
191             }
192              
193             #define GIT_REFCOUNT_OWN(r, o) { \
194             (void)git_atomic_swap((r)->rc.owner, o); \
195             }
196              
197             #define GIT_REFCOUNT_OWNER(r) git_atomic_load((r)->rc.owner)
198              
199             #define GIT_REFCOUNT_VAL(r) git_atomic32_get((r)->rc.refcount)
200              
201              
202             static signed char from_hex[] = {
203             -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 00 */
204             -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 10 */
205             -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 20 */
206             0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, /* 30 */
207             -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 40 */
208             -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 50 */
209             -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 60 */
210             -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 70 */
211             -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 80 */
212             -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 90 */
213             -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* a0 */
214             -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* b0 */
215             -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* c0 */
216             -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* d0 */
217             -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* e0 */
218             -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* f0 */
219             };
220              
221             GIT_INLINE(int) git__fromhex(char h)
222             {
223             return from_hex[(unsigned char) h];
224             }
225              
226             GIT_INLINE(int) git__ishex(const char *str)
227             {
228             unsigned i;
229             for (i=0; str[i] != '\0'; i++)
230             if (git__fromhex(str[i]) < 0)
231             return 0;
232             return 1;
233             }
234              
235             GIT_INLINE(size_t) git__size_t_bitmask(size_t v)
236             {
237             v--;
238             v |= v >> 1;
239             v |= v >> 2;
240             v |= v >> 4;
241             v |= v >> 8;
242             v |= v >> 16;
243              
244             return v;
245             }
246              
247             GIT_INLINE(size_t) git__size_t_powerof2(size_t v)
248             {
249             return git__size_t_bitmask(v) + 1;
250             }
251              
252             GIT_INLINE(bool) git__isupper(int c)
253             {
254             return (c >= 'A' && c <= 'Z');
255             }
256              
257             GIT_INLINE(bool) git__isalpha(int c)
258             {
259             return ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'));
260             }
261              
262             GIT_INLINE(bool) git__isdigit(int c)
263             {
264             return (c >= '0' && c <= '9');
265             }
266              
267             GIT_INLINE(bool) git__isspace(int c)
268             {
269             return (c == ' ' || c == '\t' || c == '\n' || c == '\f' || c == '\r' || c == '\v');
270             }
271              
272             GIT_INLINE(bool) git__isspace_nonlf(int c)
273             {
274             return (c == ' ' || c == '\t' || c == '\f' || c == '\r' || c == '\v');
275             }
276              
277             GIT_INLINE(bool) git__iswildcard(int c)
278             {
279             return (c == '*' || c == '?' || c == '[');
280             }
281              
282             GIT_INLINE(bool) git__isxdigit(int c)
283             {
284             return ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'));
285             }
286              
287             /*
288             * Parse a string value as a boolean, just like Core Git does.
289             *
290             * Valid values for true are: 'true', 'yes', 'on'
291             * Valid values for false are: 'false', 'no', 'off'
292             */
293             extern int git__parse_bool(int *out, const char *value);
294              
295             /*
296             * Unescapes a string in-place.
297             *
298             * Edge cases behavior:
299             * - "jackie\" -> "jacky\"
300             * - "chan\\" -> "chan\"
301             */
302             extern size_t git__unescape(char *str);
303              
304             /*
305             * Safely zero-out memory, making sure that the compiler
306             * doesn't optimize away the operation.
307             */
308 0           GIT_INLINE(void) git__memzero(void *data, size_t size)
309             {
310             #ifdef _MSC_VER
311             SecureZeroMemory((PVOID)data, size);
312             #else
313 0           volatile uint8_t *scan = (volatile uint8_t *)data;
314              
315 0 0         while (size--)
316 0           *scan++ = 0x0;
317             #endif
318 0           }
319              
320             #ifdef GIT_WIN32
321              
322             GIT_INLINE(double) git__timer(void)
323             {
324             /* GetTickCount64 returns the number of milliseconds that have
325             * elapsed since the system was started. */
326             return (double) GetTickCount64() / (double) 1000;
327             }
328              
329             #elif __APPLE__
330              
331             #include
332              
333             GIT_INLINE(double) git__timer(void)
334             {
335             uint64_t time = mach_absolute_time();
336             static double scaling_factor = 0;
337              
338             if (scaling_factor == 0) {
339             mach_timebase_info_data_t info;
340             (void)mach_timebase_info(&info);
341             scaling_factor = (double)info.numer / (double)info.denom;
342             }
343              
344             return (double)time * scaling_factor / 1.0E9;
345             }
346              
347             #elif defined(__amigaos4__)
348              
349             #include
350              
351             GIT_INLINE(double) git__timer(void)
352             {
353             struct TimeVal tv;
354             ITimer->GetUpTime(&tv);
355             return (double)tv.Seconds + (double)tv.Microseconds / 1.0E6;
356             }
357              
358             #else
359              
360             #include
361              
362             GIT_INLINE(double) git__timer(void)
363             {
364             struct timeval tv;
365              
366             #ifdef CLOCK_MONOTONIC
367             struct timespec tp;
368             if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0)
369             return (double) tp.tv_sec + (double) tp.tv_nsec / 1.0E9;
370             #endif
371              
372             /* Fall back to using gettimeofday */
373             gettimeofday(&tv, NULL);
374             return (double)tv.tv_sec + (double)tv.tv_usec / 1.0E6;
375             }
376              
377             #endif
378              
379             extern int git__getenv(git_str *out, const char *name);
380              
381             extern int git__online_cpus(void);
382              
383             GIT_INLINE(int) git__noop(void) { return 0; }
384              
385             #include "alloc.h"
386              
387             #endif