Skip to content

Commit 851e778

Browse files
authored
Merge pull request libgit2#5735 from lhchavez/faster-strntol64
Make git__strntol64() ~70%* faster
2 parents 86a1cdd + e99e833 commit 851e778

File tree

2 files changed

+34
-11
lines changed

2 files changed

+34
-11
lines changed

src/integer.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,11 @@ GIT_INLINE(int) git__is_int(long long p)
7777
# define git__sub_int_overflow(out, one, two) \
7878
__builtin_ssub_overflow(one, two, out)
7979

80+
# define git__add_int64_overflow(out, one, two) \
81+
__builtin_add_overflow(one, two, out)
82+
# define git__multiply_int64_overflow(out, one, two) \
83+
__builtin_mul_overflow(one, two, out)
84+
8085
/* Use Microsoft's safe integer handling functions where available */
8186
#elif defined(_MSC_VER)
8287

@@ -87,11 +92,17 @@ GIT_INLINE(int) git__is_int(long long p)
8792
(SizeTAdd(one, two, out) != S_OK)
8893
# define git__multiply_sizet_overflow(out, one, two) \
8994
(SizeTMult(one, two, out) != S_OK)
95+
9096
#define git__add_int_overflow(out, one, two) \
9197
(IntAdd(one, two, out) != S_OK)
9298
#define git__sub_int_overflow(out, one, two) \
9399
(IntSub(one, two, out) != S_OK)
94100

101+
#define git__add_int64_overflow(out, one, two) \
102+
(LongLongAdd(one, two, out) != S_OK)
103+
#define git__multiply_int64_overflow(out, one, two) \
104+
(LongLongMult(one, two, out) != S_OK)
105+
95106
#else
96107

97108
/**
@@ -136,6 +147,26 @@ GIT_INLINE(bool) git__sub_int_overflow(int *out, int one, int two)
136147
return false;
137148
}
138149

150+
GIT_INLINE(bool) git__add_int64_overflow(int64_t *out, int64_t one, int64_t two)
151+
{
152+
if ((two > 0 && one > (INT64_MAX - two)) ||
153+
(two < 0 && one < (INT64_MIN - two)))
154+
return true;
155+
*out = one + two;
156+
return false;
157+
}
158+
159+
GIT_INLINE(bool) git__multiply_int64_overflow(int64_t *out, int64_t one, int64_t two)
160+
{
161+
if ((one == -1 && two == INT_MIN) ||
162+
(two == -1 && one == INT_MIN) ||
163+
(one && INT64_MAX / one < two) ||
164+
(one && INT64_MIN / one > two))
165+
return true;
166+
*out = one * two;
167+
return false;
168+
}
169+
139170
#endif
140171

141172
#endif

src/util.c

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@
3434
int git__strntol64(int64_t *result, const char *nptr, size_t nptr_len, const char **endptr, int base)
3535
{
3636
const char *p;
37-
int64_t n, nn;
38-
int c, ovfl, v, neg, ndig;
37+
int64_t n, nn, v;
38+
int c, ovfl, neg, ndig;
3939

4040
p = nptr;
4141
neg = 0;
@@ -110,19 +110,11 @@ int git__strntol64(int64_t *result, const char *nptr, size_t nptr_len, const cha
110110
if (v >= base)
111111
break;
112112
v = neg ? -v : v;
113-
if (n > INT64_MAX / base || n < INT64_MIN / base) {
113+
if (git__multiply_int64_overflow(&nn, n, base) || git__add_int64_overflow(&n, nn, v)) {
114114
ovfl = 1;
115115
/* Keep on iterating until the end of this number */
116116
continue;
117117
}
118-
nn = n * base;
119-
if ((v > 0 && nn > INT64_MAX - v) ||
120-
(v < 0 && nn < INT64_MIN - v)) {
121-
ovfl = 1;
122-
/* Keep on iterating until the end of this number */
123-
continue;
124-
}
125-
n = nn + v;
126118
}
127119

128120
Return:

0 commit comments

Comments
 (0)