Coverage Report

Created: 2026-09-20 22:27

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
be/src/util/string_parser.hpp
Line
Count
Source
1
// Licensed to the Apache Software Foundation (ASF) under one
2
// or more contributor license agreements.  See the NOTICE file
3
// distributed with this work for additional information
4
// regarding copyright ownership.  The ASF licenses this file
5
// to you under the Apache License, Version 2.0 (the
6
// "License"); you may not use this file except in compliance
7
// with the License.  You may obtain a copy of the License at
8
//
9
//   http://www.apache.org/licenses/LICENSE-2.0
10
//
11
// Unless required by applicable law or agreed to in writing,
12
// software distributed under the License is distributed on an
13
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
// KIND, either express or implied.  See the License for the
15
// specific language governing permissions and limitations
16
// under the License.
17
// This file is copied from
18
// https://github.com/apache/impala/blob/branch-2.9.0/be/src/util/string-parser.hpp
19
// and modified by Doris
20
21
#pragma once
22
23
#include <fast_float/fast_float.h>
24
#include <fast_float/parse_number.h>
25
#include <glog/logging.h>
26
#include <sys/types.h>
27
28
#include <algorithm>
29
#include <cstdlib>
30
// IWYU pragma: no_include <bits/std_abs.h>
31
#include <cmath> // IWYU pragma: keep
32
#include <cstdint>
33
#include <limits>
34
#include <map>
35
#include <string>
36
#include <type_traits>
37
#include <utility>
38
39
#include "common/status.h"
40
#include "core/data_type/number_traits.h"
41
#include "core/data_type/primitive_type.h"
42
#include "core/extended_types.h"
43
#include "core/value/large_int_value.h"
44
#include "exec/common/int_exp.h"
45
#include "exec/common/string_utils/string_utils.h"
46
47
namespace doris {
48
#include "common/compile_check_avoid_begin.h"
49
template <DecimalNativeTypeConcept T>
50
struct Decimal;
51
52
// they rely on the template parameter `IS_STRICT`. in strict mode, it will set error code and otherwise it will not.
53
#ifndef SET_PARAMS_RET_FALSE_IFN
54
#define SET_PARAMS_RET_FALSE_IFN(stmt, ...)                           \
55
1.93M
    do {                                                              \
56
1.93M
        if (!(stmt)) [[unlikely]] {                                   \
57
62.9k
            if constexpr (IsStrict) {                                 \
58
308
                params.status = Status::InvalidArgument(__VA_ARGS__); \
59
308
            }                                                         \
60
62.9k
            return false;                                             \
61
62.9k
        }                                                             \
62
1.93M
    } while (false)
63
#endif
64
65
#ifndef SET_PARAMS_RET_FALSE_FROM_EXCEPTION
66
#define SET_PARAMS_RET_FALSE_FROM_EXCEPTION(stmt) \
67
334
    do {                                          \
68
334
        try {                                     \
69
334
            { stmt; }                             \
70
334
        } catch (const doris::Exception& e) {     \
71
30
            if constexpr (IsStrict) {             \
72
4
                params.status = e.to_status();    \
73
4
            }                                     \
74
30
            return false;                         \
75
30
        }                                         \
76
334
    } while (false)
77
#endif
78
79
// skip leading and trailing ascii whitespaces,
80
// return the pointer to the first non-whitespace char,
81
// and update the len to the new length, which does not include
82
// leading and trailing whitespaces
83
template <typename T>
84
1.11M
inline const char* skip_ascii_whitespaces(const char* s, T& len) {
85
2.05M
    while (len > 0 && is_whitespace_ascii(*s)) {
86
939k
        ++s;
87
939k
        --len;
88
939k
    }
89
90
2.04M
    while (len > 0 && is_whitespace_ascii(s[len - 1])) {
91
931k
        --len;
92
931k
    }
93
94
1.11M
    return s;
95
1.11M
}
_ZN5doris22skip_ascii_whitespacesImEEPKcS2_RT_
Line
Count
Source
84
1.05M
inline const char* skip_ascii_whitespaces(const char* s, T& len) {
85
1.84M
    while (len > 0 && is_whitespace_ascii(*s)) {
86
787k
        ++s;
87
787k
        --len;
88
787k
    }
89
90
1.83M
    while (len > 0 && is_whitespace_ascii(s[len - 1])) {
91
780k
        --len;
92
780k
    }
93
94
1.05M
    return s;
95
1.05M
}
_ZN5doris22skip_ascii_whitespacesIiEEPKcS2_RT_
Line
Count
Source
84
2.74k
inline const char* skip_ascii_whitespaces(const char* s, T& len) {
85
9.80k
    while (len > 0 && is_whitespace_ascii(*s)) {
86
7.05k
        ++s;
87
7.05k
        --len;
88
7.05k
    }
89
90
9.80k
    while (len > 0 && is_whitespace_ascii(s[len - 1])) {
91
7.05k
        --len;
92
7.05k
    }
93
94
2.74k
    return s;
95
2.74k
}
_ZN5doris22skip_ascii_whitespacesIlEEPKcS2_RT_
Line
Count
Source
84
55.6k
inline const char* skip_ascii_whitespaces(const char* s, T& len) {
85
200k
    while (len > 0 && is_whitespace_ascii(*s)) {
86
144k
        ++s;
87
144k
        --len;
88
144k
    }
89
90
199k
    while (len > 0 && is_whitespace_ascii(s[len - 1])) {
91
144k
        --len;
92
144k
    }
93
94
55.6k
    return s;
95
55.6k
}
96
97
template <typename T>
98
108k
inline const char* skip_leading_whitespace(const char* __restrict s, T& len) {
99
316k
    while (len > 0 && is_whitespace_ascii(*s)) {
100
207k
        ++s;
101
207k
        --len;
102
207k
    }
103
104
108k
    return s;
105
108k
}
106
107
// skip trailing ascii whitespaces,
108
// return the pointer to the first char,
109
// and update the len to the new length, which does not include
110
// trailing whitespaces
111
template <typename T>
112
88.6k
inline const char* skip_trailing_whitespaces(const char* s, T& len) {
113
320k
    while (len > 0 && is_whitespace_ascii(s[len - 1])) {
114
231k
        --len;
115
231k
    }
116
117
88.6k
    return s;
118
88.6k
}
119
120
template <bool (*Pred)(char)>
121
122k
bool range_suite(const char* s, const char* end) {
122
122k
    return std::ranges::all_of(s, end, Pred);
123
122k
}
_ZN5doris11range_suiteIXadL_Z16is_numeric_asciicEEEEbPKcS2_
Line
Count
Source
121
117k
bool range_suite(const char* s, const char* end) {
122
117k
    return std::ranges::all_of(s, end, Pred);
123
117k
}
_ZN5doris11range_suiteIXadL_Z19is_whitespace_asciicEEEEbPKcS2_
Line
Count
Source
121
4.63k
bool range_suite(const char* s, const char* end) {
122
4.63k
    return std::ranges::all_of(s, end, Pred);
123
4.63k
}
124
125
inline auto is_digit_range = range_suite<is_numeric_ascii>;
126
inline auto is_space_range = range_suite<is_whitespace_ascii>;
127
128
// combine in_bound and range_suite is ok. won't lead to duplicated calculation.
129
115k
inline bool in_bound(const char* s, const char* end, size_t offset) {
130
115k
    if (s + offset >= end) [[unlikely]] {
131
6.25k
        return false;
132
6.25k
    }
133
109k
    return true;
134
115k
}
135
136
// LEN = 0 means any length(include zero). LEN = 1 means only one character. so on. LEN = -x means x or more.
137
// if need result, use StringRef{origin_s, s} outside
138
template <int LEN, bool (*Pred)(char)>
139
1.01M
bool skip_qualified_char(const char*& s, const char* end) {
140
1.01M
    if constexpr (LEN == 0) {
141
        // Consume any length of characters that match the predicate.
142
2.28M
        while (s != end && Pred(*s)) {
143
1.41M
            ++s;
144
1.41M
        }
145
871k
    } else if constexpr (LEN > 0) {
146
        // Consume exactly LEN characters that match the predicate.
147
267k
        for (int i = 0; i < LEN; ++i, ++s) {
148
144k
            if (s == end || !Pred(*s)) [[unlikely]] {
149
21.8k
                return false;
150
21.8k
            }
151
144k
        }
152
144k
    } else { // LEN < 0
153
        // Consume at least -LEN characters that match the predicate.
154
125
        int count = 0;
155
810
        while (s != end && Pred(*s)) {
156
685
            ++s;
157
685
            ++count;
158
685
        }
159
125
        if (count < -LEN) [[unlikely]] {
160
0
            return false;
161
0
        }
162
125
    }
163
123k
    return true;
164
1.01M
}
_ZN5doris19skip_qualified_charILi0EXadL_Z19is_whitespace_asciicEEEEbRPKcS2_
Line
Count
Source
139
324k
bool skip_qualified_char(const char*& s, const char* end) {
140
324k
    if constexpr (LEN == 0) {
141
        // Consume any length of characters that match the predicate.
142
331k
        while (s != end && Pred(*s)) {
143
6.79k
            ++s;
144
6.79k
        }
145
    } else if constexpr (LEN > 0) {
146
        // Consume exactly LEN characters that match the predicate.
147
        for (int i = 0; i < LEN; ++i, ++s) {
148
            if (s == end || !Pred(*s)) [[unlikely]] {
149
                return false;
150
            }
151
        }
152
    } else { // LEN < 0
153
        // Consume at least -LEN characters that match the predicate.
154
        int count = 0;
155
        while (s != end && Pred(*s)) {
156
            ++s;
157
            ++count;
158
        }
159
        if (count < -LEN) [[unlikely]] {
160
            return false;
161
        }
162
    }
163
324k
    return true;
164
324k
}
_ZN5doris19skip_qualified_charILi0EXadL_Z16is_numeric_asciicEEEEbRPKcS2_
Line
Count
Source
139
546k
bool skip_qualified_char(const char*& s, const char* end) {
140
546k
    if constexpr (LEN == 0) {
141
        // Consume any length of characters that match the predicate.
142
1.95M
        while (s != end && Pred(*s)) {
143
1.40M
            ++s;
144
1.40M
        }
145
    } else if constexpr (LEN > 0) {
146
        // Consume exactly LEN characters that match the predicate.
147
        for (int i = 0; i < LEN; ++i, ++s) {
148
            if (s == end || !Pred(*s)) [[unlikely]] {
149
                return false;
150
            }
151
        }
152
    } else { // LEN < 0
153
        // Consume at least -LEN characters that match the predicate.
154
        int count = 0;
155
        while (s != end && Pred(*s)) {
156
            ++s;
157
            ++count;
158
        }
159
        if (count < -LEN) [[unlikely]] {
160
            return false;
161
        }
162
    }
163
546k
    return true;
164
546k
}
_ZN5doris19skip_qualified_charILin1EXadL_Z23is_not_whitespace_asciicEEEEbRPKcS2_
Line
Count
Source
139
125
bool skip_qualified_char(const char*& s, const char* end) {
140
    if constexpr (LEN == 0) {
141
        // Consume any length of characters that match the predicate.
142
        while (s != end && Pred(*s)) {
143
            ++s;
144
        }
145
    } else if constexpr (LEN > 0) {
146
        // Consume exactly LEN characters that match the predicate.
147
        for (int i = 0; i < LEN; ++i, ++s) {
148
            if (s == end || !Pred(*s)) [[unlikely]] {
149
                return false;
150
            }
151
        }
152
125
    } else { // LEN < 0
153
        // Consume at least -LEN characters that match the predicate.
154
125
        int count = 0;
155
810
        while (s != end && Pred(*s)) {
156
685
            ++s;
157
685
            ++count;
158
685
        }
159
125
        if (count < -LEN) [[unlikely]] {
160
0
            return false;
161
0
        }
162
125
    }
163
125
    return true;
164
125
}
Unexecuted instantiation: _ZN5doris19skip_qualified_charILi1EXadL_Z14is_slash_asciicEEEEbRPKcS2_
_ZN5doris19skip_qualified_charILi1EXadL_Z12is_non_alnumcEEEEbRPKcS2_
Line
Count
Source
139
71.4k
bool skip_qualified_char(const char*& s, const char* end) {
140
    if constexpr (LEN == 0) {
141
        // Consume any length of characters that match the predicate.
142
        while (s != end && Pred(*s)) {
143
            ++s;
144
        }
145
71.4k
    } else if constexpr (LEN > 0) {
146
        // Consume exactly LEN characters that match the predicate.
147
121k
        for (int i = 0; i < LEN; ++i, ++s) {
148
71.4k
            if (s == end || !Pred(*s)) [[unlikely]] {
149
21.5k
                return false;
150
21.5k
            }
151
71.4k
        }
152
    } else { // LEN < 0
153
        // Consume at least -LEN characters that match the predicate.
154
        int count = 0;
155
        while (s != end && Pred(*s)) {
156
            ++s;
157
            ++count;
158
        }
159
        if (count < -LEN) [[unlikely]] {
160
            return false;
161
        }
162
    }
163
49.8k
    return true;
164
71.4k
}
_ZN5doris19skip_qualified_charILi1EXadL_ZNS_12is_delimiterEcEEEEbRPKcS2_
Line
Count
Source
139
4.97k
bool skip_qualified_char(const char*& s, const char* end) {
140
    if constexpr (LEN == 0) {
141
        // Consume any length of characters that match the predicate.
142
        while (s != end && Pred(*s)) {
143
            ++s;
144
        }
145
4.97k
    } else if constexpr (LEN > 0) {
146
        // Consume exactly LEN characters that match the predicate.
147
9.86k
        for (int i = 0; i < LEN; ++i, ++s) {
148
4.97k
            if (s == end || !Pred(*s)) [[unlikely]] {
149
95
                return false;
150
95
            }
151
4.97k
        }
152
    } else { // LEN < 0
153
        // Consume at least -LEN characters that match the predicate.
154
        int count = 0;
155
        while (s != end && Pred(*s)) {
156
            ++s;
157
            ++count;
158
        }
159
        if (count < -LEN) [[unlikely]] {
160
            return false;
161
        }
162
    }
163
4.88k
    return true;
164
4.97k
}
_ZN5doris19skip_qualified_charILi1EXadL_ZNS_11is_date_sepEcEEEEbRPKcS2_
Line
Count
Source
139
68.0k
bool skip_qualified_char(const char*& s, const char* end) {
140
    if constexpr (LEN == 0) {
141
        // Consume any length of characters that match the predicate.
142
        while (s != end && Pred(*s)) {
143
            ++s;
144
        }
145
68.0k
    } else if constexpr (LEN > 0) {
146
        // Consume exactly LEN characters that match the predicate.
147
136k
        for (int i = 0; i < LEN; ++i, ++s) {
148
68.0k
            if (s == end || !Pred(*s)) [[unlikely]] {
149
88
                return false;
150
88
            }
151
68.0k
        }
152
    } else { // LEN < 0
153
        // Consume at least -LEN characters that match the predicate.
154
        int count = 0;
155
        while (s != end && Pred(*s)) {
156
            ++s;
157
            ++count;
158
        }
159
        if (count < -LEN) [[unlikely]] {
160
            return false;
161
        }
162
    }
163
67.9k
    return true;
164
68.0k
}
_ZN5doris19skip_qualified_charILi1EXadL_ZNS_8is_colonEcEEEEbRPKcS2_
Line
Count
Source
139
294
bool skip_qualified_char(const char*& s, const char* end) {
140
    if constexpr (LEN == 0) {
141
        // Consume any length of characters that match the predicate.
142
        while (s != end && Pred(*s)) {
143
            ++s;
144
        }
145
294
    } else if constexpr (LEN > 0) {
146
        // Consume exactly LEN characters that match the predicate.
147
540
        for (int i = 0; i < LEN; ++i, ++s) {
148
294
            if (s == end || !Pred(*s)) [[unlikely]] {
149
48
                return false;
150
48
            }
151
294
        }
152
    } else { // LEN < 0
153
        // Consume at least -LEN characters that match the predicate.
154
        int count = 0;
155
        while (s != end && Pred(*s)) {
156
            ++s;
157
            ++count;
158
        }
159
        if (count < -LEN) [[unlikely]] {
160
            return false;
161
        }
162
    }
163
246
    return true;
164
294
}
165
166
inline auto skip_any_whitespace = skip_qualified_char<0, is_whitespace_ascii>;
167
inline auto skip_any_digit = skip_qualified_char<0, is_numeric_ascii>;
168
inline auto skip_tz_name_part = skip_qualified_char<-1, is_not_whitespace_ascii>;
169
inline auto skip_one_slash = skip_qualified_char<1, is_slash_ascii>;
170
inline auto skip_one_non_alnum = skip_qualified_char<1, is_non_alnum>;
171
172
4.97k
inline bool is_delimiter(char c) {
173
4.97k
    return c == ' ' || c == 'T' || c == ':';
174
4.97k
}
175
inline auto consume_one_delimiter = skip_qualified_char<1, is_delimiter>;
176
177
112k
inline bool is_date_sep(char c) {
178
112k
    return c == '-' || c == '/';
179
112k
}
180
inline auto consume_one_date_sep = skip_qualified_char<1, is_date_sep>;
181
182
294
inline bool is_colon(char c) {
183
294
    return c == ':';
184
294
}
185
inline auto consume_one_colon = skip_qualified_char<1, is_colon>;
186
187
// only consume a string of digit, not include sign.
188
// when has MAX_LEN > 0, do greedy match but at most MAX_LEN.
189
// LEN = 0 means any length, otherwise(must > 0) it means exactly LEN digits.
190
template <typename T, int LEN = 0, int MAX_LEN = -1>
191
44
bool consume_digit(const char*& s, const char* end, T& out) {
192
44
    static_assert(LEN >= 0);
193
    if constexpr (MAX_LEN > 0) {
194
        out = 0;
195
        for (int i = 0; i < MAX_LEN; ++i, ++s) {
196
            if (s == end || !is_numeric_ascii(*s)) {
197
                if (i < LEN) [[unlikely]] {
198
                    return false;
199
                }
200
                break; // stop consuming if we have consumed enough digits.
201
            }
202
            out = out * 10 + (*s - '0');
203
        }
204
    } else if constexpr (LEN == 0) {
205
        // Consume any length of digits.
206
        out = 0;
207
        while (s != end && is_numeric_ascii(*s)) {
208
            out = out * 10 + (*s - '0');
209
            ++s;
210
        }
211
44
    } else if constexpr (LEN > 0) {
212
        // Consume exactly LEN digits.
213
44
        out = 0;
214
184
        for (int i = 0; i < LEN; ++i, ++s) {
215
140
            if (s == end || !is_numeric_ascii(*s)) [[unlikely]] {
216
0
                return false;
217
0
            }
218
140
            out = out * 10 + (*s - '0');
219
140
        }
220
44
    }
221
44
    return true;
222
44
}
_ZN5doris13consume_digitIjLi4ELin1EEEbRPKcS2_RT_
Line
Count
Source
191
32
bool consume_digit(const char*& s, const char* end, T& out) {
192
32
    static_assert(LEN >= 0);
193
    if constexpr (MAX_LEN > 0) {
194
        out = 0;
195
        for (int i = 0; i < MAX_LEN; ++i, ++s) {
196
            if (s == end || !is_numeric_ascii(*s)) {
197
                if (i < LEN) [[unlikely]] {
198
                    return false;
199
                }
200
                break; // stop consuming if we have consumed enough digits.
201
            }
202
            out = out * 10 + (*s - '0');
203
        }
204
    } else if constexpr (LEN == 0) {
205
        // Consume any length of digits.
206
        out = 0;
207
        while (s != end && is_numeric_ascii(*s)) {
208
            out = out * 10 + (*s - '0');
209
            ++s;
210
        }
211
32
    } else if constexpr (LEN > 0) {
212
        // Consume exactly LEN digits.
213
32
        out = 0;
214
160
        for (int i = 0; i < LEN; ++i, ++s) {
215
128
            if (s == end || !is_numeric_ascii(*s)) [[unlikely]] {
216
0
                return false;
217
0
            }
218
128
            out = out * 10 + (*s - '0');
219
128
        }
220
32
    }
221
32
    return true;
222
32
}
_ZN5doris13consume_digitIjLi1ELin1EEEbRPKcS2_RT_
Line
Count
Source
191
12
bool consume_digit(const char*& s, const char* end, T& out) {
192
12
    static_assert(LEN >= 0);
193
    if constexpr (MAX_LEN > 0) {
194
        out = 0;
195
        for (int i = 0; i < MAX_LEN; ++i, ++s) {
196
            if (s == end || !is_numeric_ascii(*s)) {
197
                if (i < LEN) [[unlikely]] {
198
                    return false;
199
                }
200
                break; // stop consuming if we have consumed enough digits.
201
            }
202
            out = out * 10 + (*s - '0');
203
        }
204
    } else if constexpr (LEN == 0) {
205
        // Consume any length of digits.
206
        out = 0;
207
        while (s != end && is_numeric_ascii(*s)) {
208
            out = out * 10 + (*s - '0');
209
            ++s;
210
        }
211
12
    } else if constexpr (LEN > 0) {
212
        // Consume exactly LEN digits.
213
12
        out = 0;
214
24
        for (int i = 0; i < LEN; ++i, ++s) {
215
12
            if (s == end || !is_numeric_ascii(*s)) [[unlikely]] {
216
0
                return false;
217
0
            }
218
12
            out = out * 10 + (*s - '0');
219
12
        }
220
12
    }
221
12
    return true;
222
12
}
223
224
// specialized version for 2 digits, which is used very often in date/time parsing.
225
template <>
226
230k
inline bool consume_digit<uint32_t, 2, -1>(const char*& s, const char* end, uint32_t& out) {
227
230k
    out = 0;
228
230k
    if (s == end || s + 1 == end || !is_numeric_ascii(*s) || !is_numeric_ascii(*(s + 1)))
229
36.7k
            [[unlikely]] {
230
36.7k
        return false;
231
36.7k
    }
232
193k
    out = (s[0] - '0') * 10 + (s[1] - '0');
233
193k
    s += 2; // consume 2 digits
234
193k
    return true;
235
230k
}
236
237
// specialized version for 1 or 2 digits, which is used very often in date/time parsing.
238
template <>
239
123k
inline bool consume_digit<uint32_t, 1, 2>(const char*& s, const char* end, uint32_t& out) {
240
123k
    out = 0;
241
123k
    if (s == end || !is_numeric_ascii(*s)) [[unlikely]] {
242
958
        return false;
243
122k
    } else if (s + 1 != end && is_numeric_ascii(*(s + 1))) {
244
        // consume 2 digits
245
88.6k
        out = (*s - '0') * 10 + (*(s + 1) - '0');
246
88.6k
        s += 2;
247
88.6k
    } else {
248
        // consume 1 digit
249
33.8k
        out = *s - '0';
250
33.8k
        ++s;
251
33.8k
    }
252
122k
    return true;
253
123k
}
254
255
template <bool (*Pred)(char)>
256
1.13k
uint32_t count_valid_length(const char* s, const char* end) {
257
1.13k
    DCHECK(s <= end) << "s: " << s << ", end: " << end;
258
1.13k
    uint32_t count = 0;
259
3.40k
    while (s != end && Pred(*s)) {
260
2.27k
        ++count;
261
2.27k
        ++s;
262
2.27k
    }
263
1.13k
    return count;
264
1.13k
}
265
266
inline auto count_digits = count_valid_length<is_numeric_ascii>;
267
268
1.10k
inline std::string combine_tz_offset(char sign, uint32_t hour_offset, uint32_t minute_offset) {
269
1.10k
    std::string result(6, '0');
270
1.10k
    result[0] = sign;
271
1.10k
    result[1] = '0' + (hour_offset / 10);
272
1.10k
    result[2] = '0' + (hour_offset % 10);
273
1.10k
    result[3] = ':';
274
1.10k
    result[4] = '0' + (minute_offset / 10);
275
1.10k
    result[5] = '0' + (minute_offset % 10);
276
1.10k
    DCHECK_EQ(result.size(), 6);
277
1.10k
    return result;
278
1.10k
}
279
280
// Utility functions for doing atoi/atof on non-null terminated strings.  On micro benchmarks,
281
// this is significantly faster than libc (atoi/strtol and atof/strtod).
282
//
283
// Strings with leading and trailing whitespaces are accepted.
284
// Branching is heavily optimized for the non-whitespace successful case.
285
// All the StringTo* functions first parse the input string assuming it has no leading whitespace.
286
// If that first attempt was unsuccessful, these functions retry the parsing after removing
287
// whitespace. Therefore, strings with whitespace take a perf hit on branch mis-prediction.
288
//
289
// For overflows, we are following the mysql behavior, to cap values at the max/min value for that
290
// data type.  This is different from hive, which returns NULL for overflow slots for int types
291
// and inf/-inf for float types.
292
//
293
// Things we tried that did not work:
294
//  - lookup table for converting character to digit
295
// Improvements (TODO):
296
//  - Validate input using _simd_compare_ranges
297
//  - Since we know the length, we can parallelize this: i.e. result = 100*s[0] + 10*s[1] + s[2]
298
class StringParser {
299
public:
300
    enum ParseResult { PARSE_SUCCESS = 0, PARSE_FAILURE, PARSE_OVERFLOW, PARSE_UNDERFLOW };
301
302
    template <typename T>
303
986k
    static T numeric_limits(bool negative) {
304
986k
        if constexpr (std::is_same_v<T, __int128>) {
305
98.6k
            return negative ? MIN_INT128 : MAX_INT128;
306
887k
        } else {
307
887k
            return negative ? std::numeric_limits<T>::min() : std::numeric_limits<T>::max();
308
887k
        }
309
986k
    }
_ZN5doris12StringParser14numeric_limitsInEET_b
Line
Count
Source
303
98.6k
    static T numeric_limits(bool negative) {
304
98.6k
        if constexpr (std::is_same_v<T, __int128>) {
305
98.6k
            return negative ? MIN_INT128 : MAX_INT128;
306
        } else {
307
            return negative ? std::numeric_limits<T>::min() : std::numeric_limits<T>::max();
308
        }
309
98.6k
    }
_ZN5doris12StringParser14numeric_limitsIaEET_b
Line
Count
Source
303
334k
    static T numeric_limits(bool negative) {
304
        if constexpr (std::is_same_v<T, __int128>) {
305
            return negative ? MIN_INT128 : MAX_INT128;
306
334k
        } else {
307
334k
            return negative ? std::numeric_limits<T>::min() : std::numeric_limits<T>::max();
308
334k
        }
309
334k
    }
_ZN5doris12StringParser14numeric_limitsIsEET_b
Line
Count
Source
303
156k
    static T numeric_limits(bool negative) {
304
        if constexpr (std::is_same_v<T, __int128>) {
305
            return negative ? MIN_INT128 : MAX_INT128;
306
156k
        } else {
307
156k
            return negative ? std::numeric_limits<T>::min() : std::numeric_limits<T>::max();
308
156k
        }
309
156k
    }
_ZN5doris12StringParser14numeric_limitsIiEET_b
Line
Count
Source
303
216k
    static T numeric_limits(bool negative) {
304
        if constexpr (std::is_same_v<T, __int128>) {
305
            return negative ? MIN_INT128 : MAX_INT128;
306
216k
        } else {
307
216k
            return negative ? std::numeric_limits<T>::min() : std::numeric_limits<T>::max();
308
216k
        }
309
216k
    }
_ZN5doris12StringParser14numeric_limitsIlEET_b
Line
Count
Source
303
179k
    static T numeric_limits(bool negative) {
304
        if constexpr (std::is_same_v<T, __int128>) {
305
            return negative ? MIN_INT128 : MAX_INT128;
306
179k
        } else {
307
179k
            return negative ? std::numeric_limits<T>::min() : std::numeric_limits<T>::max();
308
179k
        }
309
179k
    }
_ZN5doris12StringParser14numeric_limitsIjEET_b
Line
Count
Source
303
310
    static T numeric_limits(bool negative) {
304
        if constexpr (std::is_same_v<T, __int128>) {
305
            return negative ? MIN_INT128 : MAX_INT128;
306
310
        } else {
307
310
            return negative ? std::numeric_limits<T>::min() : std::numeric_limits<T>::max();
308
310
        }
309
310
    }
_ZN5doris12StringParser14numeric_limitsImEET_b
Line
Count
Source
303
432
    static T numeric_limits(bool negative) {
304
        if constexpr (std::is_same_v<T, __int128>) {
305
            return negative ? MIN_INT128 : MAX_INT128;
306
432
        } else {
307
432
            return negative ? std::numeric_limits<T>::min() : std::numeric_limits<T>::max();
308
432
        }
309
432
    }
_ZN5doris12StringParser14numeric_limitsIN4wide7integerILm256EiEEEET_b
Line
Count
Source
303
8
    static T numeric_limits(bool negative) {
304
        if constexpr (std::is_same_v<T, __int128>) {
305
            return negative ? MIN_INT128 : MAX_INT128;
306
8
        } else {
307
8
            return negative ? std::numeric_limits<T>::min() : std::numeric_limits<T>::max();
308
8
        }
309
8
    }
_ZN5doris12StringParser14numeric_limitsIoEET_b
Line
Count
Source
303
8
    static T numeric_limits(bool negative) {
304
        if constexpr (std::is_same_v<T, __int128>) {
305
            return negative ? MIN_INT128 : MAX_INT128;
306
8
        } else {
307
8
            return negative ? std::numeric_limits<T>::min() : std::numeric_limits<T>::max();
308
8
        }
309
8
    }
310
311
    template <typename T>
312
1.90M
    static T get_scale_multiplier(int scale) {
313
1.90M
        static_assert(std::is_same_v<T, int32_t> || std::is_same_v<T, int64_t> ||
314
1.90M
                              std::is_same_v<T, __int128> || std::is_same_v<T, wide::Int256>,
315
1.90M
                      "You can only instantiate as int32_t, int64_t, __int128.");
316
1.90M
        if constexpr (std::is_same_v<T, int32_t>) {
317
273k
            return common::exp10_i32(scale);
318
372k
        } else if constexpr (std::is_same_v<T, int64_t>) {
319
372k
            return common::exp10_i64(scale);
320
484k
        } else if constexpr (std::is_same_v<T, __int128>) {
321
484k
            return common::exp10_i128(scale);
322
778k
        } else if constexpr (std::is_same_v<T, wide::Int256>) {
323
778k
            return common::exp10_i256(scale);
324
778k
        }
325
1.90M
    }
_ZN5doris12StringParser20get_scale_multiplierIiEET_i
Line
Count
Source
312
273k
    static T get_scale_multiplier(int scale) {
313
273k
        static_assert(std::is_same_v<T, int32_t> || std::is_same_v<T, int64_t> ||
314
273k
                              std::is_same_v<T, __int128> || std::is_same_v<T, wide::Int256>,
315
273k
                      "You can only instantiate as int32_t, int64_t, __int128.");
316
273k
        if constexpr (std::is_same_v<T, int32_t>) {
317
273k
            return common::exp10_i32(scale);
318
        } else if constexpr (std::is_same_v<T, int64_t>) {
319
            return common::exp10_i64(scale);
320
        } else if constexpr (std::is_same_v<T, __int128>) {
321
            return common::exp10_i128(scale);
322
        } else if constexpr (std::is_same_v<T, wide::Int256>) {
323
            return common::exp10_i256(scale);
324
        }
325
273k
    }
_ZN5doris12StringParser20get_scale_multiplierIlEET_i
Line
Count
Source
312
372k
    static T get_scale_multiplier(int scale) {
313
372k
        static_assert(std::is_same_v<T, int32_t> || std::is_same_v<T, int64_t> ||
314
372k
                              std::is_same_v<T, __int128> || std::is_same_v<T, wide::Int256>,
315
372k
                      "You can only instantiate as int32_t, int64_t, __int128.");
316
        if constexpr (std::is_same_v<T, int32_t>) {
317
            return common::exp10_i32(scale);
318
372k
        } else if constexpr (std::is_same_v<T, int64_t>) {
319
372k
            return common::exp10_i64(scale);
320
        } else if constexpr (std::is_same_v<T, __int128>) {
321
            return common::exp10_i128(scale);
322
        } else if constexpr (std::is_same_v<T, wide::Int256>) {
323
            return common::exp10_i256(scale);
324
        }
325
372k
    }
_ZN5doris12StringParser20get_scale_multiplierInEET_i
Line
Count
Source
312
484k
    static T get_scale_multiplier(int scale) {
313
484k
        static_assert(std::is_same_v<T, int32_t> || std::is_same_v<T, int64_t> ||
314
484k
                              std::is_same_v<T, __int128> || std::is_same_v<T, wide::Int256>,
315
484k
                      "You can only instantiate as int32_t, int64_t, __int128.");
316
        if constexpr (std::is_same_v<T, int32_t>) {
317
            return common::exp10_i32(scale);
318
        } else if constexpr (std::is_same_v<T, int64_t>) {
319
            return common::exp10_i64(scale);
320
484k
        } else if constexpr (std::is_same_v<T, __int128>) {
321
484k
            return common::exp10_i128(scale);
322
        } else if constexpr (std::is_same_v<T, wide::Int256>) {
323
            return common::exp10_i256(scale);
324
        }
325
484k
    }
_ZN5doris12StringParser20get_scale_multiplierIN4wide7integerILm256EiEEEET_i
Line
Count
Source
312
778k
    static T get_scale_multiplier(int scale) {
313
778k
        static_assert(std::is_same_v<T, int32_t> || std::is_same_v<T, int64_t> ||
314
778k
                              std::is_same_v<T, __int128> || std::is_same_v<T, wide::Int256>,
315
778k
                      "You can only instantiate as int32_t, int64_t, __int128.");
316
        if constexpr (std::is_same_v<T, int32_t>) {
317
            return common::exp10_i32(scale);
318
        } else if constexpr (std::is_same_v<T, int64_t>) {
319
            return common::exp10_i64(scale);
320
        } else if constexpr (std::is_same_v<T, __int128>) {
321
            return common::exp10_i128(scale);
322
778k
        } else if constexpr (std::is_same_v<T, wide::Int256>) {
323
778k
            return common::exp10_i256(scale);
324
778k
        }
325
778k
    }
326
327
    // This is considerably faster than glibc's implementation (25x).
328
    // Assumes s represents a decimal number.
329
    template <typename T, bool enable_strict_mode = false>
330
800k
    static inline T string_to_int(const char* __restrict s, size_t len, ParseResult* result) {
331
800k
        T ans = string_to_int_internal<T, enable_strict_mode>(s, len, result);
332
800k
        if (LIKELY(*result == PARSE_SUCCESS)) {
333
691k
            return ans;
334
691k
        }
335
108k
        s = skip_leading_whitespace(s, len);
336
108k
        return string_to_int_internal<T, enable_strict_mode>(s, len, result);
337
800k
    }
_ZN5doris12StringParser13string_to_intInLb0EEET_PKcmPNS0_11ParseResultE
Line
Count
Source
330
92.0k
    static inline T string_to_int(const char* __restrict s, size_t len, ParseResult* result) {
331
92.0k
        T ans = string_to_int_internal<T, enable_strict_mode>(s, len, result);
332
92.0k
        if (LIKELY(*result == PARSE_SUCCESS)) {
333
89.3k
            return ans;
334
89.3k
        }
335
2.67k
        s = skip_leading_whitespace(s, len);
336
2.67k
        return string_to_int_internal<T, enable_strict_mode>(s, len, result);
337
92.0k
    }
_ZN5doris12StringParser13string_to_intIaLb0EEET_PKcmPNS0_11ParseResultE
Line
Count
Source
330
193k
    static inline T string_to_int(const char* __restrict s, size_t len, ParseResult* result) {
331
193k
        T ans = string_to_int_internal<T, enable_strict_mode>(s, len, result);
332
193k
        if (LIKELY(*result == PARSE_SUCCESS)) {
333
134k
            return ans;
334
134k
        }
335
58.5k
        s = skip_leading_whitespace(s, len);
336
58.5k
        return string_to_int_internal<T, enable_strict_mode>(s, len, result);
337
193k
    }
_ZN5doris12StringParser13string_to_intIaLb1EEET_PKcmPNS0_11ParseResultE
Line
Count
Source
330
2.51k
    static inline T string_to_int(const char* __restrict s, size_t len, ParseResult* result) {
331
2.51k
        T ans = string_to_int_internal<T, enable_strict_mode>(s, len, result);
332
2.51k
        if (LIKELY(*result == PARSE_SUCCESS)) {
333
692
            return ans;
334
692
        }
335
1.82k
        s = skip_leading_whitespace(s, len);
336
1.82k
        return string_to_int_internal<T, enable_strict_mode>(s, len, result);
337
2.51k
    }
_ZN5doris12StringParser13string_to_intIsLb0EEET_PKcmPNS0_11ParseResultE
Line
Count
Source
330
134k
    static inline T string_to_int(const char* __restrict s, size_t len, ParseResult* result) {
331
134k
        T ans = string_to_int_internal<T, enable_strict_mode>(s, len, result);
332
134k
        if (LIKELY(*result == PARSE_SUCCESS)) {
333
118k
            return ans;
334
118k
        }
335
16.4k
        s = skip_leading_whitespace(s, len);
336
16.4k
        return string_to_int_internal<T, enable_strict_mode>(s, len, result);
337
134k
    }
_ZN5doris12StringParser13string_to_intIsLb1EEET_PKcmPNS0_11ParseResultE
Line
Count
Source
330
2.46k
    static inline T string_to_int(const char* __restrict s, size_t len, ParseResult* result) {
331
2.46k
        T ans = string_to_int_internal<T, enable_strict_mode>(s, len, result);
332
2.46k
        if (LIKELY(*result == PARSE_SUCCESS)) {
333
676
            return ans;
334
676
        }
335
1.79k
        s = skip_leading_whitespace(s, len);
336
1.79k
        return string_to_int_internal<T, enable_strict_mode>(s, len, result);
337
2.46k
    }
_ZN5doris12StringParser13string_to_intIiLb0EEET_PKcmPNS0_11ParseResultE
Line
Count
Source
330
202k
    static inline T string_to_int(const char* __restrict s, size_t len, ParseResult* result) {
331
202k
        T ans = string_to_int_internal<T, enable_strict_mode>(s, len, result);
332
202k
        if (LIKELY(*result == PARSE_SUCCESS)) {
333
189k
            return ans;
334
189k
        }
335
12.7k
        s = skip_leading_whitespace(s, len);
336
12.7k
        return string_to_int_internal<T, enable_strict_mode>(s, len, result);
337
202k
    }
_ZN5doris12StringParser13string_to_intIiLb1EEET_PKcmPNS0_11ParseResultE
Line
Count
Source
330
2.66k
    static inline T string_to_int(const char* __restrict s, size_t len, ParseResult* result) {
331
2.66k
        T ans = string_to_int_internal<T, enable_strict_mode>(s, len, result);
332
2.66k
        if (LIKELY(*result == PARSE_SUCCESS)) {
333
902
            return ans;
334
902
        }
335
1.76k
        s = skip_leading_whitespace(s, len);
336
1.76k
        return string_to_int_internal<T, enable_strict_mode>(s, len, result);
337
2.66k
    }
_ZN5doris12StringParser13string_to_intIlLb0EEET_PKcmPNS0_11ParseResultE
Line
Count
Source
330
164k
    static inline T string_to_int(const char* __restrict s, size_t len, ParseResult* result) {
331
164k
        T ans = string_to_int_internal<T, enable_strict_mode>(s, len, result);
332
164k
        if (LIKELY(*result == PARSE_SUCCESS)) {
333
155k
            return ans;
334
155k
        }
335
9.07k
        s = skip_leading_whitespace(s, len);
336
9.07k
        return string_to_int_internal<T, enable_strict_mode>(s, len, result);
337
164k
    }
_ZN5doris12StringParser13string_to_intIlLb1EEET_PKcmPNS0_11ParseResultE
Line
Count
Source
330
2.43k
    static inline T string_to_int(const char* __restrict s, size_t len, ParseResult* result) {
331
2.43k
        T ans = string_to_int_internal<T, enable_strict_mode>(s, len, result);
332
2.43k
        if (LIKELY(*result == PARSE_SUCCESS)) {
333
694
            return ans;
334
694
        }
335
1.73k
        s = skip_leading_whitespace(s, len);
336
1.73k
        return string_to_int_internal<T, enable_strict_mode>(s, len, result);
337
2.43k
    }
_ZN5doris12StringParser13string_to_intInLb1EEET_PKcmPNS0_11ParseResultE
Line
Count
Source
330
2.37k
    static inline T string_to_int(const char* __restrict s, size_t len, ParseResult* result) {
331
2.37k
        T ans = string_to_int_internal<T, enable_strict_mode>(s, len, result);
332
2.37k
        if (LIKELY(*result == PARSE_SUCCESS)) {
333
676
            return ans;
334
676
        }
335
1.69k
        s = skip_leading_whitespace(s, len);
336
1.69k
        return string_to_int_internal<T, enable_strict_mode>(s, len, result);
337
2.37k
    }
_ZN5doris12StringParser13string_to_intIjLb0EEET_PKcmPNS0_11ParseResultE
Line
Count
Source
330
2
    static inline T string_to_int(const char* __restrict s, size_t len, ParseResult* result) {
331
2
        T ans = string_to_int_internal<T, enable_strict_mode>(s, len, result);
332
2
        if (LIKELY(*result == PARSE_SUCCESS)) {
333
2
            return ans;
334
2
        }
335
0
        s = skip_leading_whitespace(s, len);
336
0
        return string_to_int_internal<T, enable_strict_mode>(s, len, result);
337
2
    }
_ZN5doris12StringParser13string_to_intImLb0EEET_PKcmPNS0_11ParseResultE
Line
Count
Source
330
430
    static inline T string_to_int(const char* __restrict s, size_t len, ParseResult* result) {
331
430
        T ans = string_to_int_internal<T, enable_strict_mode>(s, len, result);
332
430
        if (LIKELY(*result == PARSE_SUCCESS)) {
333
430
            return ans;
334
430
        }
335
0
        s = skip_leading_whitespace(s, len);
336
0
        return string_to_int_internal<T, enable_strict_mode>(s, len, result);
337
430
    }
_ZN5doris12StringParser13string_to_intIN4wide7integerILm256EiEELb0EEET_PKcmPNS0_11ParseResultE
Line
Count
Source
330
8
    static inline T string_to_int(const char* __restrict s, size_t len, ParseResult* result) {
331
8
        T ans = string_to_int_internal<T, enable_strict_mode>(s, len, result);
332
8
        if (LIKELY(*result == PARSE_SUCCESS)) {
333
8
            return ans;
334
8
        }
335
0
        s = skip_leading_whitespace(s, len);
336
0
        return string_to_int_internal<T, enable_strict_mode>(s, len, result);
337
8
    }
_ZN5doris12StringParser13string_to_intIoLb0EEET_PKcmPNS0_11ParseResultE
Line
Count
Source
330
8
    static inline T string_to_int(const char* __restrict s, size_t len, ParseResult* result) {
331
8
        T ans = string_to_int_internal<T, enable_strict_mode>(s, len, result);
332
8
        if (LIKELY(*result == PARSE_SUCCESS)) {
333
8
            return ans;
334
8
        }
335
0
        s = skip_leading_whitespace(s, len);
336
0
        return string_to_int_internal<T, enable_strict_mode>(s, len, result);
337
8
    }
338
339
    // This is considerably faster than glibc's implementation.
340
    // In the case of overflow, the max/min value for the data type will be returned.
341
    // Assumes s represents a decimal number.
342
    template <typename T>
343
2.74k
    static inline T string_to_unsigned_int(const char* __restrict s, int len, ParseResult* result) {
344
2.74k
        s = skip_ascii_whitespaces(s, len);
345
2.74k
        return string_to_unsigned_int_internal<T>(s, len, result);
346
2.74k
    }
_ZN5doris12StringParser22string_to_unsigned_intIhEET_PKciPNS0_11ParseResultE
Line
Count
Source
343
686
    static inline T string_to_unsigned_int(const char* __restrict s, int len, ParseResult* result) {
344
686
        s = skip_ascii_whitespaces(s, len);
345
686
        return string_to_unsigned_int_internal<T>(s, len, result);
346
686
    }
_ZN5doris12StringParser22string_to_unsigned_intItEET_PKciPNS0_11ParseResultE
Line
Count
Source
343
686
    static inline T string_to_unsigned_int(const char* __restrict s, int len, ParseResult* result) {
344
686
        s = skip_ascii_whitespaces(s, len);
345
686
        return string_to_unsigned_int_internal<T>(s, len, result);
346
686
    }
_ZN5doris12StringParser22string_to_unsigned_intIjEET_PKciPNS0_11ParseResultE
Line
Count
Source
343
686
    static inline T string_to_unsigned_int(const char* __restrict s, int len, ParseResult* result) {
344
686
        s = skip_ascii_whitespaces(s, len);
345
686
        return string_to_unsigned_int_internal<T>(s, len, result);
346
686
    }
_ZN5doris12StringParser22string_to_unsigned_intImEET_PKciPNS0_11ParseResultE
Line
Count
Source
343
686
    static inline T string_to_unsigned_int(const char* __restrict s, int len, ParseResult* result) {
344
686
        s = skip_ascii_whitespaces(s, len);
345
686
        return string_to_unsigned_int_internal<T>(s, len, result);
346
686
    }
347
348
    // Convert a string s representing a number in given base into a decimal number.
349
    template <typename T>
350
    static inline T string_to_int(const char* __restrict s, int64_t len, int base,
351
55.6k
                                  ParseResult* result) {
352
55.6k
        s = skip_ascii_whitespaces(s, len);
353
55.6k
        return string_to_int_internal<T>(s, len, base, result);
354
55.6k
    }
_ZN5doris12StringParser13string_to_intIaEET_PKcliPNS0_11ParseResultE
Line
Count
Source
351
52.9k
                                  ParseResult* result) {
352
52.9k
        s = skip_ascii_whitespaces(s, len);
353
52.9k
        return string_to_int_internal<T>(s, len, base, result);
354
52.9k
    }
_ZN5doris12StringParser13string_to_intIsEET_PKcliPNS0_11ParseResultE
Line
Count
Source
351
980
                                  ParseResult* result) {
352
980
        s = skip_ascii_whitespaces(s, len);
353
980
        return string_to_int_internal<T>(s, len, base, result);
354
980
    }
_ZN5doris12StringParser13string_to_intIiEET_PKcliPNS0_11ParseResultE
Line
Count
Source
351
882
                                  ParseResult* result) {
352
882
        s = skip_ascii_whitespaces(s, len);
353
882
        return string_to_int_internal<T>(s, len, base, result);
354
882
    }
_ZN5doris12StringParser13string_to_intIlEET_PKcliPNS0_11ParseResultE
Line
Count
Source
351
882
                                  ParseResult* result) {
352
882
        s = skip_ascii_whitespaces(s, len);
353
882
        return string_to_int_internal<T>(s, len, base, result);
354
882
    }
_ZN5doris12StringParser13string_to_intImEET_PKcliPNS0_11ParseResultE
Line
Count
Source
351
2
                                  ParseResult* result) {
352
2
        s = skip_ascii_whitespaces(s, len);
353
2
        return string_to_int_internal<T>(s, len, base, result);
354
2
    }
355
356
    template <typename T>
357
311k
    static inline T string_to_float(const char* __restrict s, size_t len, ParseResult* result) {
358
311k
        s = skip_ascii_whitespaces(s, len);
359
311k
        return string_to_float_internal<T>(s, len, result);
360
311k
    }
_ZN5doris12StringParser15string_to_floatIdEET_PKcmPNS0_11ParseResultE
Line
Count
Source
357
178k
    static inline T string_to_float(const char* __restrict s, size_t len, ParseResult* result) {
358
178k
        s = skip_ascii_whitespaces(s, len);
359
178k
        return string_to_float_internal<T>(s, len, result);
360
178k
    }
_ZN5doris12StringParser15string_to_floatIfEET_PKcmPNS0_11ParseResultE
Line
Count
Source
357
132k
    static inline T string_to_float(const char* __restrict s, size_t len, ParseResult* result) {
358
132k
        s = skip_ascii_whitespaces(s, len);
359
132k
        return string_to_float_internal<T>(s, len, result);
360
132k
    }
361
362
    // Parses a string for 'true' or 'false', case insensitive.
363
23.4k
    static inline bool string_to_bool(const char* __restrict s, size_t len, ParseResult* result) {
364
23.4k
        s = skip_ascii_whitespaces(s, len);
365
23.4k
        return string_to_bool_internal(s, len, result);
366
23.4k
    }
367
368
    template <PrimitiveType P>
369
    static typename PrimitiveTypeTraits<P>::CppType::NativeType string_to_decimal(
370
            const char* __restrict s, size_t len, int type_precision, int type_scale,
371
            ParseResult* result);
372
373
    template <typename T>
374
    static Status split_string_to_map(const std::string& base, const T element_separator,
375
                                      const T key_value_separator,
376
                                      std::map<std::string, std::string>* result) {
377
        int key_pos = 0;
378
        int key_end;
379
        int val_pos;
380
        int val_end;
381
382
        while ((key_end = base.find(key_value_separator, key_pos)) != std::string::npos) {
383
            if ((val_pos = base.find_first_not_of(key_value_separator, key_end)) ==
384
                std::string::npos) {
385
                break;
386
            }
387
            if ((val_end = base.find(element_separator, val_pos)) == std::string::npos) {
388
                val_end = base.size();
389
            }
390
            result->insert(std::make_pair(base.substr(key_pos, key_end - key_pos),
391
                                          base.substr(val_pos, val_end - val_pos)));
392
            key_pos = val_end;
393
            if (key_pos != std::string::npos) {
394
                ++key_pos;
395
            }
396
        }
397
398
        return Status::OK();
399
    }
400
401
    // This is considerably faster than glibc's implementation.
402
    // In the case of overflow, the max/min value for the data type will be returned.
403
    // Assumes s represents a decimal number.
404
    // Return PARSE_FAILURE on leading whitespace. Trailing whitespace is allowed.
405
    template <typename T, bool enable_strict_mode = false>
406
    static inline T string_to_int_internal(const char* __restrict s, int len, ParseResult* result);
407
408
    // This is considerably faster than glibc's implementation.
409
    // In the case of overflow, the max/min value for the data type will be returned.
410
    // Assumes s represents a decimal number.
411
    // Return PARSE_FAILURE on leading whitespace. Trailing whitespace is allowed.
412
    template <typename T>
413
    static inline T string_to_unsigned_int_internal(const char* __restrict s, int len,
414
                                                    ParseResult* result);
415
416
    // Convert a string s representing a number in given base into a decimal number.
417
    // Return PARSE_FAILURE on leading whitespace. Trailing whitespace is allowed.
418
    template <typename T>
419
    static inline T string_to_int_internal(const char* __restrict s, int64_t len, int base,
420
                                           ParseResult* result);
421
422
    // Converts an ascii string to an integer of type T assuming it cannot overflow
423
    // and the number is positive.
424
    // Leading whitespace is not allowed. Trailing whitespace will be skipped.
425
    template <typename T, bool enable_strict_mode = false>
426
    static inline T string_to_int_no_overflow(const char* __restrict s, int len,
427
                                              ParseResult* result);
428
429
    // zero length, or at least one legal digit. at most consume MAX_LEN digits and stop. or stop when next
430
    // char is not a digit.
431
    template <typename T>
432
    static inline T string_to_uint_greedy_no_overflow(const char* __restrict s, int max_len,
433
                                                      ParseResult* result);
434
435
    // This is considerably faster than glibc's implementation (>100x why???)
436
    // No special case handling needs to be done for overflows, the floating point spec
437
    // already does it and will cap the values to -inf/inf
438
    // To avoid inaccurate conversions this function falls back to strtod for
439
    // scientific notation.
440
    // Return PARSE_FAILURE on leading whitespace. Trailing whitespace is allowed.
441
    // TODO: Investigate using intrinsics to speed up the slow strtod path.
442
    template <typename T>
443
    static inline T string_to_float_internal(const char* __restrict s, int len,
444
                                             ParseResult* result);
445
446
    // parses a string for 'true' or 'false', case insensitive
447
    // Return PARSE_FAILURE on leading whitespace. Trailing whitespace is allowed.
448
    static inline bool string_to_bool_internal(const char* __restrict s, int len,
449
                                               ParseResult* result);
450
451
    // Returns true if s only contains whitespace.
452
7.09k
    static inline bool is_all_whitespace(const char* __restrict s, int len) {
453
12.8k
        for (int i = 0; i < len; ++i) {
454
12.0k
            if (!LIKELY(is_whitespace_ascii(s[i]))) {
455
6.21k
                return false;
456
6.21k
            }
457
12.0k
        }
458
880
        return true;
459
7.09k
    }
460
461
    // For strings like "3.0", "3.123", and "3.", can parse them as 3.
462
7.35k
    static inline bool is_float_suffix(const char* __restrict s, int len) {
463
7.35k
        return (s[0] == '.' && is_all_digit(s + 1, len - 1));
464
7.35k
    }
465
466
5.36k
    static inline bool is_all_digit(const char* __restrict s, int len) {
467
11.1k
        for (int i = 0; i < len; ++i) {
468
6.13k
            if (!LIKELY(s[i] >= '0' && s[i] <= '9')) {
469
306
                return false;
470
306
            }
471
6.13k
        }
472
5.06k
        return true;
473
5.36k
    }
474
}; // end of class StringParser
475
476
template <typename T, bool enable_strict_mode>
477
908k
T StringParser::string_to_int_internal(const char* __restrict s, int len, ParseResult* result) {
478
908k
    if (UNLIKELY(len <= 0)) {
479
4.72k
        *result = PARSE_FAILURE;
480
4.72k
        return 0;
481
4.72k
    }
482
483
904k
    using UnsignedT = MakeUnsignedT<T>;
484
904k
    UnsignedT val = 0;
485
904k
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
486
904k
    bool negative = false;
487
904k
    int i = 0;
488
904k
    switch (*s) {
489
208k
    case '-':
490
208k
        negative = true;
491
208k
        max_val += 1;
492
208k
        [[fallthrough]];
493
215k
    case '+':
494
215k
        ++i;
495
        // only one '+'/'-' char, so could return failure directly
496
215k
        if (UNLIKELY(len == 1)) {
497
6
            *result = PARSE_FAILURE;
498
6
            return 0;
499
6
        }
500
904k
    }
501
502
    // This is the fast path where the string cannot overflow.
503
904k
    if (LIKELY(len - i < NumberTraits::max_ascii_len<T>())) {
504
569k
        val = string_to_int_no_overflow<UnsignedT, enable_strict_mode>(s + i, len - i, result);
505
569k
        return static_cast<T>(negative ? -val : val);
506
569k
    }
507
508
335k
    const T max_div_10 = max_val / 10;
509
335k
    const T max_mod_10 = max_val % 10;
510
511
335k
    int first = i;
512
3.41M
    for (; i < len; ++i) {
513
3.27M
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
514
3.18M
            T digit = s[i] - '0';
515
            // This is a tricky check to see if adding this digit will cause an overflow.
516
3.18M
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
517
97.6k
                *result = PARSE_OVERFLOW;
518
97.6k
                return negative ? -max_val : max_val;
519
97.6k
            }
520
3.08M
            val = val * 10 + digit;
521
3.08M
        } else {
522
91.7k
            if constexpr (enable_strict_mode) {
523
8.16k
                if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
524
                    // Reject the string because the remaining chars are not all whitespace
525
7.56k
                    *result = PARSE_FAILURE;
526
7.56k
                    return 0;
527
7.56k
                }
528
83.6k
            } else {
529
                // Save original position where non-digit was found
530
83.6k
                int remaining_len = len - i;
531
83.6k
                const char* remaining_s = s + i;
532
                // Skip trailing whitespaces from the remaining portion
533
83.6k
                remaining_s = skip_trailing_whitespaces(remaining_s, remaining_len);
534
83.6k
                if ((UNLIKELY(i == first || (remaining_len != 0 &&
535
83.6k
                                             !is_float_suffix(remaining_s, remaining_len))))) {
536
                    // Reject the string because either the first char was not a digit,
537
                    // or the remaining chars are not all whitespace
538
57.8k
                    *result = PARSE_FAILURE;
539
57.8k
                    return 0;
540
57.8k
                }
541
83.6k
            }
542
            // Returning here is slightly faster than breaking the loop.
543
26.3k
            *result = PARSE_SUCCESS;
544
91.7k
            return static_cast<T>(negative ? -val : val);
545
91.7k
        }
546
3.27M
    }
547
145k
    *result = PARSE_SUCCESS;
548
145k
    return static_cast<T>(negative ? -val : val);
549
335k
}
_ZN5doris12StringParser22string_to_int_internalInLb0EEET_PKciPNS0_11ParseResultE
Line
Count
Source
477
94.7k
T StringParser::string_to_int_internal(const char* __restrict s, int len, ParseResult* result) {
478
94.7k
    if (UNLIKELY(len <= 0)) {
479
88
        *result = PARSE_FAILURE;
480
88
        return 0;
481
88
    }
482
483
94.6k
    using UnsignedT = MakeUnsignedT<T>;
484
94.6k
    UnsignedT val = 0;
485
94.6k
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
486
94.6k
    bool negative = false;
487
94.6k
    int i = 0;
488
94.6k
    switch (*s) {
489
7.22k
    case '-':
490
7.22k
        negative = true;
491
7.22k
        max_val += 1;
492
7.22k
        [[fallthrough]];
493
7.79k
    case '+':
494
7.79k
        ++i;
495
        // only one '+'/'-' char, so could return failure directly
496
7.79k
        if (UNLIKELY(len == 1)) {
497
0
            *result = PARSE_FAILURE;
498
0
            return 0;
499
0
        }
500
94.6k
    }
501
502
    // This is the fast path where the string cannot overflow.
503
94.6k
    if (LIKELY(len - i < NumberTraits::max_ascii_len<T>())) {
504
85.2k
        val = string_to_int_no_overflow<UnsignedT, enable_strict_mode>(s + i, len - i, result);
505
85.2k
        return static_cast<T>(negative ? -val : val);
506
85.2k
    }
507
508
9.40k
    const T max_div_10 = max_val / 10;
509
9.40k
    const T max_mod_10 = max_val % 10;
510
511
9.40k
    int first = i;
512
349k
    for (; i < len; ++i) {
513
342k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
514
341k
            T digit = s[i] - '0';
515
            // This is a tricky check to see if adding this digit will cause an overflow.
516
341k
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
517
1.02k
                *result = PARSE_OVERFLOW;
518
1.02k
                return negative ? -max_val : max_val;
519
1.02k
            }
520
340k
            val = val * 10 + digit;
521
340k
        } else {
522
            if constexpr (enable_strict_mode) {
523
                if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
524
                    // Reject the string because the remaining chars are not all whitespace
525
                    *result = PARSE_FAILURE;
526
                    return 0;
527
                }
528
1.07k
            } else {
529
                // Save original position where non-digit was found
530
1.07k
                int remaining_len = len - i;
531
1.07k
                const char* remaining_s = s + i;
532
                // Skip trailing whitespaces from the remaining portion
533
1.07k
                remaining_s = skip_trailing_whitespaces(remaining_s, remaining_len);
534
1.07k
                if ((UNLIKELY(i == first || (remaining_len != 0 &&
535
1.07k
                                             !is_float_suffix(remaining_s, remaining_len))))) {
536
                    // Reject the string because either the first char was not a digit,
537
                    // or the remaining chars are not all whitespace
538
752
                    *result = PARSE_FAILURE;
539
752
                    return 0;
540
752
                }
541
1.07k
            }
542
            // Returning here is slightly faster than breaking the loop.
543
320
            *result = PARSE_SUCCESS;
544
1.07k
            return static_cast<T>(negative ? -val : val);
545
1.07k
        }
546
342k
    }
547
7.30k
    *result = PARSE_SUCCESS;
548
7.30k
    return static_cast<T>(negative ? -val : val);
549
9.40k
}
_ZN5doris12StringParser22string_to_int_internalIaLb0EEET_PKciPNS0_11ParseResultE
Line
Count
Source
477
251k
T StringParser::string_to_int_internal(const char* __restrict s, int len, ParseResult* result) {
478
251k
    if (UNLIKELY(len <= 0)) {
479
436
        *result = PARSE_FAILURE;
480
436
        return 0;
481
436
    }
482
483
251k
    using UnsignedT = MakeUnsignedT<T>;
484
251k
    UnsignedT val = 0;
485
251k
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
486
251k
    bool negative = false;
487
251k
    int i = 0;
488
251k
    switch (*s) {
489
45.2k
    case '-':
490
45.2k
        negative = true;
491
45.2k
        max_val += 1;
492
45.2k
        [[fallthrough]];
493
46.0k
    case '+':
494
46.0k
        ++i;
495
        // only one '+'/'-' char, so could return failure directly
496
46.0k
        if (UNLIKELY(len == 1)) {
497
0
            *result = PARSE_FAILURE;
498
0
            return 0;
499
0
        }
500
251k
    }
501
502
    // This is the fast path where the string cannot overflow.
503
251k
    if (LIKELY(len - i < NumberTraits::max_ascii_len<T>())) {
504
122k
        val = string_to_int_no_overflow<UnsignedT, enable_strict_mode>(s + i, len - i, result);
505
122k
        return static_cast<T>(negative ? -val : val);
506
122k
    }
507
508
128k
    const T max_div_10 = max_val / 10;
509
128k
    const T max_mod_10 = max_val % 10;
510
511
128k
    int first = i;
512
309k
    for (; i < len; ++i) {
513
296k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
514
224k
            T digit = s[i] - '0';
515
            // This is a tricky check to see if adding this digit will cause an overflow.
516
224k
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
517
42.6k
                *result = PARSE_OVERFLOW;
518
42.6k
                return negative ? -max_val : max_val;
519
42.6k
            }
520
181k
            val = val * 10 + digit;
521
181k
        } else {
522
            if constexpr (enable_strict_mode) {
523
                if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
524
                    // Reject the string because the remaining chars are not all whitespace
525
                    *result = PARSE_FAILURE;
526
                    return 0;
527
                }
528
71.9k
            } else {
529
                // Save original position where non-digit was found
530
71.9k
                int remaining_len = len - i;
531
71.9k
                const char* remaining_s = s + i;
532
                // Skip trailing whitespaces from the remaining portion
533
71.9k
                remaining_s = skip_trailing_whitespaces(remaining_s, remaining_len);
534
71.9k
                if ((UNLIKELY(i == first || (remaining_len != 0 &&
535
71.9k
                                             !is_float_suffix(remaining_s, remaining_len))))) {
536
                    // Reject the string because either the first char was not a digit,
537
                    // or the remaining chars are not all whitespace
538
49.0k
                    *result = PARSE_FAILURE;
539
49.0k
                    return 0;
540
49.0k
                }
541
71.9k
            }
542
            // Returning here is slightly faster than breaking the loop.
543
22.9k
            *result = PARSE_SUCCESS;
544
71.9k
            return static_cast<T>(negative ? -val : val);
545
71.9k
        }
546
296k
    }
547
13.7k
    *result = PARSE_SUCCESS;
548
13.7k
    return static_cast<T>(negative ? -val : val);
549
128k
}
_ZN5doris12StringParser22string_to_int_internalIaLb1EEET_PKciPNS0_11ParseResultE
Line
Count
Source
477
4.34k
T StringParser::string_to_int_internal(const char* __restrict s, int len, ParseResult* result) {
478
4.34k
    if (UNLIKELY(len <= 0)) {
479
16
        *result = PARSE_FAILURE;
480
16
        return 0;
481
16
    }
482
483
4.32k
    using UnsignedT = MakeUnsignedT<T>;
484
4.32k
    UnsignedT val = 0;
485
4.32k
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
486
4.32k
    bool negative = false;
487
4.32k
    int i = 0;
488
4.32k
    switch (*s) {
489
1.55k
    case '-':
490
1.55k
        negative = true;
491
1.55k
        max_val += 1;
492
1.55k
        [[fallthrough]];
493
2.26k
    case '+':
494
2.26k
        ++i;
495
        // only one '+'/'-' char, so could return failure directly
496
2.26k
        if (UNLIKELY(len == 1)) {
497
0
            *result = PARSE_FAILURE;
498
0
            return 0;
499
0
        }
500
4.32k
    }
501
502
    // This is the fast path where the string cannot overflow.
503
4.32k
    if (LIKELY(len - i < NumberTraits::max_ascii_len<T>())) {
504
532
        val = string_to_int_no_overflow<UnsignedT, enable_strict_mode>(s + i, len - i, result);
505
532
        return static_cast<T>(negative ? -val : val);
506
532
    }
507
508
3.79k
    const T max_div_10 = max_val / 10;
509
3.79k
    const T max_mod_10 = max_val % 10;
510
511
3.79k
    int first = i;
512
13.4k
    for (; i < len; ++i) {
513
13.2k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
514
10.8k
            T digit = s[i] - '0';
515
            // This is a tricky check to see if adding this digit will cause an overflow.
516
10.8k
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
517
1.20k
                *result = PARSE_OVERFLOW;
518
1.20k
                return negative ? -max_val : max_val;
519
1.20k
            }
520
9.69k
            val = val * 10 + digit;
521
9.69k
        } else {
522
2.37k
            if constexpr (enable_strict_mode) {
523
2.37k
                if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
524
                    // Reject the string because the remaining chars are not all whitespace
525
2.20k
                    *result = PARSE_FAILURE;
526
2.20k
                    return 0;
527
2.20k
                }
528
            } else {
529
                // Save original position where non-digit was found
530
                int remaining_len = len - i;
531
                const char* remaining_s = s + i;
532
                // Skip trailing whitespaces from the remaining portion
533
                remaining_s = skip_trailing_whitespaces(remaining_s, remaining_len);
534
                if ((UNLIKELY(i == first || (remaining_len != 0 &&
535
                                             !is_float_suffix(remaining_s, remaining_len))))) {
536
                    // Reject the string because either the first char was not a digit,
537
                    // or the remaining chars are not all whitespace
538
                    *result = PARSE_FAILURE;
539
                    return 0;
540
                }
541
            }
542
            // Returning here is slightly faster than breaking the loop.
543
176
            *result = PARSE_SUCCESS;
544
2.37k
            return static_cast<T>(negative ? -val : val);
545
2.37k
        }
546
13.2k
    }
547
216
    *result = PARSE_SUCCESS;
548
216
    return static_cast<T>(negative ? -val : val);
549
3.79k
}
_ZN5doris12StringParser22string_to_int_internalIsLb0EEET_PKciPNS0_11ParseResultE
Line
Count
Source
477
151k
T StringParser::string_to_int_internal(const char* __restrict s, int len, ParseResult* result) {
478
151k
    if (UNLIKELY(len <= 0)) {
479
16
        *result = PARSE_FAILURE;
480
16
        return 0;
481
16
    }
482
483
151k
    using UnsignedT = MakeUnsignedT<T>;
484
151k
    UnsignedT val = 0;
485
151k
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
486
151k
    bool negative = false;
487
151k
    int i = 0;
488
151k
    switch (*s) {
489
26.0k
    case '-':
490
26.0k
        negative = true;
491
26.0k
        max_val += 1;
492
26.0k
        [[fallthrough]];
493
26.7k
    case '+':
494
26.7k
        ++i;
495
        // only one '+'/'-' char, so could return failure directly
496
26.7k
        if (UNLIKELY(len == 1)) {
497
0
            *result = PARSE_FAILURE;
498
0
            return 0;
499
0
        }
500
151k
    }
501
502
    // This is the fast path where the string cannot overflow.
503
151k
    if (LIKELY(len - i < NumberTraits::max_ascii_len<T>())) {
504
103k
        val = string_to_int_no_overflow<UnsignedT, enable_strict_mode>(s + i, len - i, result);
505
103k
        return static_cast<T>(negative ? -val : val);
506
103k
    }
507
508
47.8k
    const T max_div_10 = max_val / 10;
509
47.8k
    const T max_mod_10 = max_val % 10;
510
511
47.8k
    int first = i;
512
249k
    for (; i < len; ++i) {
513
231k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
514
227k
            T digit = s[i] - '0';
515
            // This is a tricky check to see if adding this digit will cause an overflow.
516
227k
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
517
26.1k
                *result = PARSE_OVERFLOW;
518
26.1k
                return negative ? -max_val : max_val;
519
26.1k
            }
520
201k
            val = val * 10 + digit;
521
201k
        } else {
522
            if constexpr (enable_strict_mode) {
523
                if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
524
                    // Reject the string because the remaining chars are not all whitespace
525
                    *result = PARSE_FAILURE;
526
                    return 0;
527
                }
528
3.81k
            } else {
529
                // Save original position where non-digit was found
530
3.81k
                int remaining_len = len - i;
531
3.81k
                const char* remaining_s = s + i;
532
                // Skip trailing whitespaces from the remaining portion
533
3.81k
                remaining_s = skip_trailing_whitespaces(remaining_s, remaining_len);
534
3.81k
                if ((UNLIKELY(i == first || (remaining_len != 0 &&
535
3.81k
                                             !is_float_suffix(remaining_s, remaining_len))))) {
536
                    // Reject the string because either the first char was not a digit,
537
                    // or the remaining chars are not all whitespace
538
2.59k
                    *result = PARSE_FAILURE;
539
2.59k
                    return 0;
540
2.59k
                }
541
3.81k
            }
542
            // Returning here is slightly faster than breaking the loop.
543
1.22k
            *result = PARSE_SUCCESS;
544
3.81k
            return static_cast<T>(negative ? -val : val);
545
3.81k
        }
546
231k
    }
547
17.8k
    *result = PARSE_SUCCESS;
548
17.8k
    return static_cast<T>(negative ? -val : val);
549
47.8k
}
_ZN5doris12StringParser22string_to_int_internalIsLb1EEET_PKciPNS0_11ParseResultE
Line
Count
Source
477
4.26k
T StringParser::string_to_int_internal(const char* __restrict s, int len, ParseResult* result) {
478
4.26k
    if (UNLIKELY(len <= 0)) {
479
16
        *result = PARSE_FAILURE;
480
16
        return 0;
481
16
    }
482
483
4.24k
    using UnsignedT = MakeUnsignedT<T>;
484
4.24k
    UnsignedT val = 0;
485
4.24k
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
486
4.24k
    bool negative = false;
487
4.24k
    int i = 0;
488
4.24k
    switch (*s) {
489
1.25k
    case '-':
490
1.25k
        negative = true;
491
1.25k
        max_val += 1;
492
1.25k
        [[fallthrough]];
493
1.95k
    case '+':
494
1.95k
        ++i;
495
        // only one '+'/'-' char, so could return failure directly
496
1.95k
        if (UNLIKELY(len == 1)) {
497
0
            *result = PARSE_FAILURE;
498
0
            return 0;
499
0
        }
500
4.24k
    }
501
502
    // This is the fast path where the string cannot overflow.
503
4.24k
    if (LIKELY(len - i < NumberTraits::max_ascii_len<T>())) {
504
816
        val = string_to_int_no_overflow<UnsignedT, enable_strict_mode>(s + i, len - i, result);
505
816
        return static_cast<T>(negative ? -val : val);
506
816
    }
507
508
3.42k
    const T max_div_10 = max_val / 10;
509
3.42k
    const T max_mod_10 = max_val % 10;
510
511
3.42k
    int first = i;
512
15.8k
    for (; i < len; ++i) {
513
15.7k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
514
13.5k
            T digit = s[i] - '0';
515
            // This is a tricky check to see if adding this digit will cause an overflow.
516
13.5k
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
517
1.15k
                *result = PARSE_OVERFLOW;
518
1.15k
                return negative ? -max_val : max_val;
519
1.15k
            }
520
12.4k
            val = val * 10 + digit;
521
12.4k
        } else {
522
2.17k
            if constexpr (enable_strict_mode) {
523
2.17k
                if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
524
                    // Reject the string because the remaining chars are not all whitespace
525
2.00k
                    *result = PARSE_FAILURE;
526
2.00k
                    return 0;
527
2.00k
                }
528
            } else {
529
                // Save original position where non-digit was found
530
                int remaining_len = len - i;
531
                const char* remaining_s = s + i;
532
                // Skip trailing whitespaces from the remaining portion
533
                remaining_s = skip_trailing_whitespaces(remaining_s, remaining_len);
534
                if ((UNLIKELY(i == first || (remaining_len != 0 &&
535
                                             !is_float_suffix(remaining_s, remaining_len))))) {
536
                    // Reject the string because either the first char was not a digit,
537
                    // or the remaining chars are not all whitespace
538
                    *result = PARSE_FAILURE;
539
                    return 0;
540
                }
541
            }
542
            // Returning here is slightly faster than breaking the loop.
543
176
            *result = PARSE_SUCCESS;
544
2.17k
            return static_cast<T>(negative ? -val : val);
545
2.17k
        }
546
15.7k
    }
547
100
    *result = PARSE_SUCCESS;
548
100
    return static_cast<T>(negative ? -val : val);
549
3.42k
}
_ZN5doris12StringParser22string_to_int_internalIiLb0EEET_PKciPNS0_11ParseResultE
Line
Count
Source
477
215k
T StringParser::string_to_int_internal(const char* __restrict s, int len, ParseResult* result) {
478
215k
    if (UNLIKELY(len <= 0)) {
479
4.07k
        *result = PARSE_FAILURE;
480
4.07k
        return 0;
481
4.07k
    }
482
483
211k
    using UnsignedT = MakeUnsignedT<T>;
484
211k
    UnsignedT val = 0;
485
211k
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
486
211k
    bool negative = false;
487
211k
    int i = 0;
488
211k
    switch (*s) {
489
21.8k
    case '-':
490
21.8k
        negative = true;
491
21.8k
        max_val += 1;
492
21.8k
        [[fallthrough]];
493
22.6k
    case '+':
494
22.6k
        ++i;
495
        // only one '+'/'-' char, so could return failure directly
496
22.6k
        if (UNLIKELY(len == 1)) {
497
2
            *result = PARSE_FAILURE;
498
2
            return 0;
499
2
        }
500
211k
    }
501
502
    // This is the fast path where the string cannot overflow.
503
211k
    if (LIKELY(len - i < NumberTraits::max_ascii_len<T>())) {
504
183k
        val = string_to_int_no_overflow<UnsignedT, enable_strict_mode>(s + i, len - i, result);
505
183k
        return static_cast<T>(negative ? -val : val);
506
183k
    }
507
508
27.3k
    const T max_div_10 = max_val / 10;
509
27.3k
    const T max_mod_10 = max_val % 10;
510
511
27.3k
    int first = i;
512
260k
    for (; i < len; ++i) {
513
248k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
514
244k
            T digit = s[i] - '0';
515
            // This is a tricky check to see if adding this digit will cause an overflow.
516
244k
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
517
11.7k
                *result = PARSE_OVERFLOW;
518
11.7k
                return negative ? -max_val : max_val;
519
11.7k
            }
520
233k
            val = val * 10 + digit;
521
233k
        } else {
522
            if constexpr (enable_strict_mode) {
523
                if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
524
                    // Reject the string because the remaining chars are not all whitespace
525
                    *result = PARSE_FAILURE;
526
                    return 0;
527
                }
528
3.76k
            } else {
529
                // Save original position where non-digit was found
530
3.76k
                int remaining_len = len - i;
531
3.76k
                const char* remaining_s = s + i;
532
                // Skip trailing whitespaces from the remaining portion
533
3.76k
                remaining_s = skip_trailing_whitespaces(remaining_s, remaining_len);
534
3.76k
                if ((UNLIKELY(i == first || (remaining_len != 0 &&
535
3.76k
                                             !is_float_suffix(remaining_s, remaining_len))))) {
536
                    // Reject the string because either the first char was not a digit,
537
                    // or the remaining chars are not all whitespace
538
2.99k
                    *result = PARSE_FAILURE;
539
2.99k
                    return 0;
540
2.99k
                }
541
3.76k
            }
542
            // Returning here is slightly faster than breaking the loop.
543
772
            *result = PARSE_SUCCESS;
544
3.76k
            return static_cast<T>(negative ? -val : val);
545
3.76k
        }
546
248k
    }
547
11.8k
    *result = PARSE_SUCCESS;
548
11.8k
    return static_cast<T>(negative ? -val : val);
549
27.3k
}
_ZN5doris12StringParser22string_to_int_internalIiLb1EEET_PKciPNS0_11ParseResultE
Line
Count
Source
477
4.43k
T StringParser::string_to_int_internal(const char* __restrict s, int len, ParseResult* result) {
478
4.43k
    if (UNLIKELY(len <= 0)) {
479
16
        *result = PARSE_FAILURE;
480
16
        return 0;
481
16
    }
482
483
4.41k
    using UnsignedT = MakeUnsignedT<T>;
484
4.41k
    UnsignedT val = 0;
485
4.41k
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
486
4.41k
    bool negative = false;
487
4.41k
    int i = 0;
488
4.41k
    switch (*s) {
489
1.22k
    case '-':
490
1.22k
        negative = true;
491
1.22k
        max_val += 1;
492
1.22k
        [[fallthrough]];
493
1.91k
    case '+':
494
1.91k
        ++i;
495
        // only one '+'/'-' char, so could return failure directly
496
1.91k
        if (UNLIKELY(len == 1)) {
497
0
            *result = PARSE_FAILURE;
498
0
            return 0;
499
0
        }
500
4.41k
    }
501
502
    // This is the fast path where the string cannot overflow.
503
4.41k
    if (LIKELY(len - i < NumberTraits::max_ascii_len<T>())) {
504
1.63k
        val = string_to_int_no_overflow<UnsignedT, enable_strict_mode>(s + i, len - i, result);
505
1.63k
        return static_cast<T>(negative ? -val : val);
506
1.63k
    }
507
508
2.78k
    const T max_div_10 = max_val / 10;
509
2.78k
    const T max_mod_10 = max_val % 10;
510
511
2.78k
    int first = i;
512
21.7k
    for (; i < len; ++i) {
513
21.6k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
514
20.0k
            T digit = s[i] - '0';
515
            // This is a tricky check to see if adding this digit will cause an overflow.
516
20.0k
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
517
1.10k
                *result = PARSE_OVERFLOW;
518
1.10k
                return negative ? -max_val : max_val;
519
1.10k
            }
520
18.9k
            val = val * 10 + digit;
521
18.9k
        } else {
522
1.59k
            if constexpr (enable_strict_mode) {
523
1.59k
                if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
524
                    // Reject the string because the remaining chars are not all whitespace
525
1.47k
                    *result = PARSE_FAILURE;
526
1.47k
                    return 0;
527
1.47k
                }
528
            } else {
529
                // Save original position where non-digit was found
530
                int remaining_len = len - i;
531
                const char* remaining_s = s + i;
532
                // Skip trailing whitespaces from the remaining portion
533
                remaining_s = skip_trailing_whitespaces(remaining_s, remaining_len);
534
                if ((UNLIKELY(i == first || (remaining_len != 0 &&
535
                                             !is_float_suffix(remaining_s, remaining_len))))) {
536
                    // Reject the string because either the first char was not a digit,
537
                    // or the remaining chars are not all whitespace
538
                    *result = PARSE_FAILURE;
539
                    return 0;
540
                }
541
            }
542
            // Returning here is slightly faster than breaking the loop.
543
120
            *result = PARSE_SUCCESS;
544
1.59k
            return static_cast<T>(negative ? -val : val);
545
1.59k
        }
546
21.6k
    }
547
90
    *result = PARSE_SUCCESS;
548
90
    return static_cast<T>(negative ? -val : val);
549
2.78k
}
_ZN5doris12StringParser22string_to_int_internalIlLb0EEET_PKciPNS0_11ParseResultE
Line
Count
Source
477
174k
T StringParser::string_to_int_internal(const char* __restrict s, int len, ParseResult* result) {
478
174k
    if (UNLIKELY(len <= 0)) {
479
28
        *result = PARSE_FAILURE;
480
28
        return 0;
481
28
    }
482
483
174k
    using UnsignedT = MakeUnsignedT<T>;
484
174k
    UnsignedT val = 0;
485
174k
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
486
174k
    bool negative = false;
487
174k
    int i = 0;
488
174k
    switch (*s) {
489
101k
    case '-':
490
101k
        negative = true;
491
101k
        max_val += 1;
492
101k
        [[fallthrough]];
493
102k
    case '+':
494
102k
        ++i;
495
        // only one '+'/'-' char, so could return failure directly
496
102k
        if (UNLIKELY(len == 1)) {
497
0
            *result = PARSE_FAILURE;
498
0
            return 0;
499
0
        }
500
174k
    }
501
502
    // This is the fast path where the string cannot overflow.
503
174k
    if (LIKELY(len - i < NumberTraits::max_ascii_len<T>())) {
504
66.2k
        val = string_to_int_no_overflow<UnsignedT, enable_strict_mode>(s + i, len - i, result);
505
66.2k
        return static_cast<T>(negative ? -val : val);
506
66.2k
    }
507
508
107k
    const T max_div_10 = max_val / 10;
509
107k
    const T max_mod_10 = max_val % 10;
510
511
107k
    int first = i;
512
2.10M
    for (; i < len; ++i) {
513
2.00M
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
514
2.00M
            T digit = s[i] - '0';
515
            // This is a tricky check to see if adding this digit will cause an overflow.
516
2.00M
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
517
10.5k
                *result = PARSE_OVERFLOW;
518
10.5k
                return negative ? -max_val : max_val;
519
10.5k
            }
520
1.99M
            val = val * 10 + digit;
521
1.99M
        } else {
522
            if constexpr (enable_strict_mode) {
523
                if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
524
                    // Reject the string because the remaining chars are not all whitespace
525
                    *result = PARSE_FAILURE;
526
                    return 0;
527
                }
528
2.98k
            } else {
529
                // Save original position where non-digit was found
530
2.98k
                int remaining_len = len - i;
531
2.98k
                const char* remaining_s = s + i;
532
                // Skip trailing whitespaces from the remaining portion
533
2.98k
                remaining_s = skip_trailing_whitespaces(remaining_s, remaining_len);
534
2.98k
                if ((UNLIKELY(i == first || (remaining_len != 0 &&
535
2.98k
                                             !is_float_suffix(remaining_s, remaining_len))))) {
536
                    // Reject the string because either the first char was not a digit,
537
                    // or the remaining chars are not all whitespace
538
2.49k
                    *result = PARSE_FAILURE;
539
2.49k
                    return 0;
540
2.49k
                }
541
2.98k
            }
542
            // Returning here is slightly faster than breaking the loop.
543
488
            *result = PARSE_SUCCESS;
544
2.98k
            return static_cast<T>(negative ? -val : val);
545
2.98k
        }
546
2.00M
    }
547
94.2k
    *result = PARSE_SUCCESS;
548
94.2k
    return static_cast<T>(negative ? -val : val);
549
107k
}
_ZN5doris12StringParser22string_to_int_internalIlLb1EEET_PKciPNS0_11ParseResultE
Line
Count
Source
477
4.16k
T StringParser::string_to_int_internal(const char* __restrict s, int len, ParseResult* result) {
478
4.16k
    if (UNLIKELY(len <= 0)) {
479
20
        *result = PARSE_FAILURE;
480
20
        return 0;
481
20
    }
482
483
4.14k
    using UnsignedT = MakeUnsignedT<T>;
484
4.14k
    UnsignedT val = 0;
485
4.14k
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
486
4.14k
    bool negative = false;
487
4.14k
    int i = 0;
488
4.14k
    switch (*s) {
489
1.20k
    case '-':
490
1.20k
        negative = true;
491
1.20k
        max_val += 1;
492
1.20k
        [[fallthrough]];
493
1.88k
    case '+':
494
1.88k
        ++i;
495
        // only one '+'/'-' char, so could return failure directly
496
1.88k
        if (UNLIKELY(len == 1)) {
497
4
            *result = PARSE_FAILURE;
498
4
            return 0;
499
4
        }
500
4.14k
    }
501
502
    // This is the fast path where the string cannot overflow.
503
4.14k
    if (LIKELY(len - i < NumberTraits::max_ascii_len<T>())) {
504
1.95k
        val = string_to_int_no_overflow<UnsignedT, enable_strict_mode>(s + i, len - i, result);
505
1.95k
        return static_cast<T>(negative ? -val : val);
506
1.95k
    }
507
508
2.18k
    const T max_div_10 = max_val / 10;
509
2.18k
    const T max_mod_10 = max_val % 10;
510
511
2.18k
    int first = i;
512
34.2k
    for (; i < len; ++i) {
513
34.1k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
514
33.1k
            T digit = s[i] - '0';
515
            // This is a tricky check to see if adding this digit will cause an overflow.
516
33.1k
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
517
1.05k
                *result = PARSE_OVERFLOW;
518
1.05k
                return negative ? -max_val : max_val;
519
1.05k
            }
520
32.0k
            val = val * 10 + digit;
521
32.0k
        } else {
522
1.04k
            if constexpr (enable_strict_mode) {
523
1.04k
                if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
524
                    // Reject the string because the remaining chars are not all whitespace
525
982
                    *result = PARSE_FAILURE;
526
982
                    return 0;
527
982
                }
528
            } else {
529
                // Save original position where non-digit was found
530
                int remaining_len = len - i;
531
                const char* remaining_s = s + i;
532
                // Skip trailing whitespaces from the remaining portion
533
                remaining_s = skip_trailing_whitespaces(remaining_s, remaining_len);
534
                if ((UNLIKELY(i == first || (remaining_len != 0 &&
535
                                             !is_float_suffix(remaining_s, remaining_len))))) {
536
                    // Reject the string because either the first char was not a digit,
537
                    // or the remaining chars are not all whitespace
538
                    *result = PARSE_FAILURE;
539
                    return 0;
540
                }
541
            }
542
            // Returning here is slightly faster than breaking the loop.
543
64
            *result = PARSE_SUCCESS;
544
1.04k
            return static_cast<T>(negative ? -val : val);
545
1.04k
        }
546
34.1k
    }
547
84
    *result = PARSE_SUCCESS;
548
84
    return static_cast<T>(negative ? -val : val);
549
2.18k
}
_ZN5doris12StringParser22string_to_int_internalInLb1EEET_PKciPNS0_11ParseResultE
Line
Count
Source
477
4.06k
T StringParser::string_to_int_internal(const char* __restrict s, int len, ParseResult* result) {
478
4.06k
    if (UNLIKELY(len <= 0)) {
479
16
        *result = PARSE_FAILURE;
480
16
        return 0;
481
16
    }
482
483
4.05k
    using UnsignedT = MakeUnsignedT<T>;
484
4.05k
    UnsignedT val = 0;
485
4.05k
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
486
4.05k
    bool negative = false;
487
4.05k
    int i = 0;
488
4.05k
    switch (*s) {
489
1.17k
    case '-':
490
1.17k
        negative = true;
491
1.17k
        max_val += 1;
492
1.17k
        [[fallthrough]];
493
1.84k
    case '+':
494
1.84k
        ++i;
495
        // only one '+'/'-' char, so could return failure directly
496
1.84k
        if (UNLIKELY(len == 1)) {
497
0
            *result = PARSE_FAILURE;
498
0
            return 0;
499
0
        }
500
4.05k
    }
501
502
    // This is the fast path where the string cannot overflow.
503
4.05k
    if (LIKELY(len - i < NumberTraits::max_ascii_len<T>())) {
504
1.98k
        val = string_to_int_no_overflow<UnsignedT, enable_strict_mode>(s + i, len - i, result);
505
1.98k
        return static_cast<T>(negative ? -val : val);
506
1.98k
    }
507
508
2.06k
    const T max_div_10 = max_val / 10;
509
2.06k
    const T max_mod_10 = max_val % 10;
510
511
2.06k
    int first = i;
512
63.4k
    for (; i < len; ++i) {
513
63.3k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
514
62.3k
            T digit = s[i] - '0';
515
            // This is a tricky check to see if adding this digit will cause an overflow.
516
62.3k
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
517
1.00k
                *result = PARSE_OVERFLOW;
518
1.00k
                return negative ? -max_val : max_val;
519
1.00k
            }
520
61.3k
            val = val * 10 + digit;
521
61.3k
        } else {
522
976
            if constexpr (enable_strict_mode) {
523
976
                if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
524
                    // Reject the string because the remaining chars are not all whitespace
525
912
                    *result = PARSE_FAILURE;
526
912
                    return 0;
527
912
                }
528
            } else {
529
                // Save original position where non-digit was found
530
                int remaining_len = len - i;
531
                const char* remaining_s = s + i;
532
                // Skip trailing whitespaces from the remaining portion
533
                remaining_s = skip_trailing_whitespaces(remaining_s, remaining_len);
534
                if ((UNLIKELY(i == first || (remaining_len != 0 &&
535
                                             !is_float_suffix(remaining_s, remaining_len))))) {
536
                    // Reject the string because either the first char was not a digit,
537
                    // or the remaining chars are not all whitespace
538
                    *result = PARSE_FAILURE;
539
                    return 0;
540
                }
541
            }
542
            // Returning here is slightly faster than breaking the loop.
543
64
            *result = PARSE_SUCCESS;
544
976
            return static_cast<T>(negative ? -val : val);
545
976
        }
546
63.3k
    }
547
84
    *result = PARSE_SUCCESS;
548
84
    return static_cast<T>(negative ? -val : val);
549
2.06k
}
_ZN5doris12StringParser22string_to_int_internalIjLb1EEET_PKciPNS0_11ParseResultE
Line
Count
Source
477
312
T StringParser::string_to_int_internal(const char* __restrict s, int len, ParseResult* result) {
478
312
    if (UNLIKELY(len <= 0)) {
479
4
        *result = PARSE_FAILURE;
480
4
        return 0;
481
4
    }
482
483
308
    using UnsignedT = MakeUnsignedT<T>;
484
308
    UnsignedT val = 0;
485
308
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
486
308
    bool negative = false;
487
308
    int i = 0;
488
308
    switch (*s) {
489
0
    case '-':
490
0
        negative = true;
491
0
        max_val += 1;
492
0
        [[fallthrough]];
493
0
    case '+':
494
0
        ++i;
495
        // only one '+'/'-' char, so could return failure directly
496
0
        if (UNLIKELY(len == 1)) {
497
0
            *result = PARSE_FAILURE;
498
0
            return 0;
499
0
        }
500
308
    }
501
502
    // This is the fast path where the string cannot overflow.
503
308
    if (LIKELY(len - i < NumberTraits::max_ascii_len<T>())) {
504
308
        val = string_to_int_no_overflow<UnsignedT, enable_strict_mode>(s + i, len - i, result);
505
308
        return static_cast<T>(negative ? -val : val);
506
308
    }
507
508
0
    const T max_div_10 = max_val / 10;
509
0
    const T max_mod_10 = max_val % 10;
510
511
0
    int first = i;
512
0
    for (; i < len; ++i) {
513
0
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
514
0
            T digit = s[i] - '0';
515
            // This is a tricky check to see if adding this digit will cause an overflow.
516
0
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
517
0
                *result = PARSE_OVERFLOW;
518
0
                return negative ? -max_val : max_val;
519
0
            }
520
0
            val = val * 10 + digit;
521
0
        } else {
522
0
            if constexpr (enable_strict_mode) {
523
0
                if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
524
                    // Reject the string because the remaining chars are not all whitespace
525
0
                    *result = PARSE_FAILURE;
526
0
                    return 0;
527
0
                }
528
            } else {
529
                // Save original position where non-digit was found
530
                int remaining_len = len - i;
531
                const char* remaining_s = s + i;
532
                // Skip trailing whitespaces from the remaining portion
533
                remaining_s = skip_trailing_whitespaces(remaining_s, remaining_len);
534
                if ((UNLIKELY(i == first || (remaining_len != 0 &&
535
                                             !is_float_suffix(remaining_s, remaining_len))))) {
536
                    // Reject the string because either the first char was not a digit,
537
                    // or the remaining chars are not all whitespace
538
                    *result = PARSE_FAILURE;
539
                    return 0;
540
                }
541
            }
542
            // Returning here is slightly faster than breaking the loop.
543
0
            *result = PARSE_SUCCESS;
544
0
            return static_cast<T>(negative ? -val : val);
545
0
        }
546
0
    }
547
0
    *result = PARSE_SUCCESS;
548
0
    return static_cast<T>(negative ? -val : val);
549
0
}
_ZN5doris12StringParser22string_to_int_internalIjLb0EEET_PKciPNS0_11ParseResultE
Line
Count
Source
477
2
T StringParser::string_to_int_internal(const char* __restrict s, int len, ParseResult* result) {
478
2
    if (UNLIKELY(len <= 0)) {
479
0
        *result = PARSE_FAILURE;
480
0
        return 0;
481
0
    }
482
483
2
    using UnsignedT = MakeUnsignedT<T>;
484
2
    UnsignedT val = 0;
485
2
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
486
2
    bool negative = false;
487
2
    int i = 0;
488
2
    switch (*s) {
489
0
    case '-':
490
0
        negative = true;
491
0
        max_val += 1;
492
0
        [[fallthrough]];
493
0
    case '+':
494
0
        ++i;
495
        // only one '+'/'-' char, so could return failure directly
496
0
        if (UNLIKELY(len == 1)) {
497
0
            *result = PARSE_FAILURE;
498
0
            return 0;
499
0
        }
500
2
    }
501
502
    // This is the fast path where the string cannot overflow.
503
2
    if (LIKELY(len - i < NumberTraits::max_ascii_len<T>())) {
504
2
        val = string_to_int_no_overflow<UnsignedT, enable_strict_mode>(s + i, len - i, result);
505
2
        return static_cast<T>(negative ? -val : val);
506
2
    }
507
508
0
    const T max_div_10 = max_val / 10;
509
0
    const T max_mod_10 = max_val % 10;
510
511
0
    int first = i;
512
0
    for (; i < len; ++i) {
513
0
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
514
0
            T digit = s[i] - '0';
515
            // This is a tricky check to see if adding this digit will cause an overflow.
516
0
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
517
0
                *result = PARSE_OVERFLOW;
518
0
                return negative ? -max_val : max_val;
519
0
            }
520
0
            val = val * 10 + digit;
521
0
        } else {
522
            if constexpr (enable_strict_mode) {
523
                if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
524
                    // Reject the string because the remaining chars are not all whitespace
525
                    *result = PARSE_FAILURE;
526
                    return 0;
527
                }
528
0
            } else {
529
                // Save original position where non-digit was found
530
0
                int remaining_len = len - i;
531
0
                const char* remaining_s = s + i;
532
                // Skip trailing whitespaces from the remaining portion
533
0
                remaining_s = skip_trailing_whitespaces(remaining_s, remaining_len);
534
0
                if ((UNLIKELY(i == first || (remaining_len != 0 &&
535
0
                                             !is_float_suffix(remaining_s, remaining_len))))) {
536
                    // Reject the string because either the first char was not a digit,
537
                    // or the remaining chars are not all whitespace
538
0
                    *result = PARSE_FAILURE;
539
0
                    return 0;
540
0
                }
541
0
            }
542
            // Returning here is slightly faster than breaking the loop.
543
0
            *result = PARSE_SUCCESS;
544
0
            return static_cast<T>(negative ? -val : val);
545
0
        }
546
0
    }
547
0
    *result = PARSE_SUCCESS;
548
0
    return static_cast<T>(negative ? -val : val);
549
0
}
_ZN5doris12StringParser22string_to_int_internalImLb0EEET_PKciPNS0_11ParseResultE
Line
Count
Source
477
430
T StringParser::string_to_int_internal(const char* __restrict s, int len, ParseResult* result) {
478
430
    if (UNLIKELY(len <= 0)) {
479
0
        *result = PARSE_FAILURE;
480
0
        return 0;
481
0
    }
482
483
430
    using UnsignedT = MakeUnsignedT<T>;
484
430
    UnsignedT val = 0;
485
430
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
486
430
    bool negative = false;
487
430
    int i = 0;
488
430
    switch (*s) {
489
0
    case '-':
490
0
        negative = true;
491
0
        max_val += 1;
492
0
        [[fallthrough]];
493
0
    case '+':
494
0
        ++i;
495
        // only one '+'/'-' char, so could return failure directly
496
0
        if (UNLIKELY(len == 1)) {
497
0
            *result = PARSE_FAILURE;
498
0
            return 0;
499
0
        }
500
430
    }
501
502
    // This is the fast path where the string cannot overflow.
503
430
    if (LIKELY(len - i < NumberTraits::max_ascii_len<T>())) {
504
430
        val = string_to_int_no_overflow<UnsignedT, enable_strict_mode>(s + i, len - i, result);
505
430
        return static_cast<T>(negative ? -val : val);
506
430
    }
507
508
0
    const T max_div_10 = max_val / 10;
509
0
    const T max_mod_10 = max_val % 10;
510
511
0
    int first = i;
512
0
    for (; i < len; ++i) {
513
0
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
514
0
            T digit = s[i] - '0';
515
            // This is a tricky check to see if adding this digit will cause an overflow.
516
0
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
517
0
                *result = PARSE_OVERFLOW;
518
0
                return negative ? -max_val : max_val;
519
0
            }
520
0
            val = val * 10 + digit;
521
0
        } else {
522
            if constexpr (enable_strict_mode) {
523
                if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
524
                    // Reject the string because the remaining chars are not all whitespace
525
                    *result = PARSE_FAILURE;
526
                    return 0;
527
                }
528
0
            } else {
529
                // Save original position where non-digit was found
530
0
                int remaining_len = len - i;
531
0
                const char* remaining_s = s + i;
532
                // Skip trailing whitespaces from the remaining portion
533
0
                remaining_s = skip_trailing_whitespaces(remaining_s, remaining_len);
534
0
                if ((UNLIKELY(i == first || (remaining_len != 0 &&
535
0
                                             !is_float_suffix(remaining_s, remaining_len))))) {
536
                    // Reject the string because either the first char was not a digit,
537
                    // or the remaining chars are not all whitespace
538
0
                    *result = PARSE_FAILURE;
539
0
                    return 0;
540
0
                }
541
0
            }
542
            // Returning here is slightly faster than breaking the loop.
543
0
            *result = PARSE_SUCCESS;
544
0
            return static_cast<T>(negative ? -val : val);
545
0
        }
546
0
    }
547
0
    *result = PARSE_SUCCESS;
548
0
    return static_cast<T>(negative ? -val : val);
549
0
}
_ZN5doris12StringParser22string_to_int_internalIN4wide7integerILm256EiEELb0EEET_PKciPNS0_11ParseResultE
Line
Count
Source
477
8
T StringParser::string_to_int_internal(const char* __restrict s, int len, ParseResult* result) {
478
8
    if (UNLIKELY(len <= 0)) {
479
0
        *result = PARSE_FAILURE;
480
0
        return 0;
481
0
    }
482
483
8
    using UnsignedT = MakeUnsignedT<T>;
484
8
    UnsignedT val = 0;
485
8
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
486
8
    bool negative = false;
487
8
    int i = 0;
488
8
    switch (*s) {
489
0
    case '-':
490
0
        negative = true;
491
0
        max_val += 1;
492
0
        [[fallthrough]];
493
0
    case '+':
494
0
        ++i;
495
        // only one '+'/'-' char, so could return failure directly
496
0
        if (UNLIKELY(len == 1)) {
497
0
            *result = PARSE_FAILURE;
498
0
            return 0;
499
0
        }
500
8
    }
501
502
    // This is the fast path where the string cannot overflow.
503
8
    if (LIKELY(len - i < NumberTraits::max_ascii_len<T>())) {
504
8
        val = string_to_int_no_overflow<UnsignedT, enable_strict_mode>(s + i, len - i, result);
505
8
        return static_cast<T>(negative ? -val : val);
506
8
    }
507
508
0
    const T max_div_10 = max_val / 10;
509
0
    const T max_mod_10 = max_val % 10;
510
511
0
    int first = i;
512
0
    for (; i < len; ++i) {
513
0
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
514
0
            T digit = s[i] - '0';
515
            // This is a tricky check to see if adding this digit will cause an overflow.
516
0
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
517
0
                *result = PARSE_OVERFLOW;
518
0
                return negative ? -max_val : max_val;
519
0
            }
520
0
            val = val * 10 + digit;
521
0
        } else {
522
            if constexpr (enable_strict_mode) {
523
                if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
524
                    // Reject the string because the remaining chars are not all whitespace
525
                    *result = PARSE_FAILURE;
526
                    return 0;
527
                }
528
0
            } else {
529
                // Save original position where non-digit was found
530
0
                int remaining_len = len - i;
531
0
                const char* remaining_s = s + i;
532
                // Skip trailing whitespaces from the remaining portion
533
0
                remaining_s = skip_trailing_whitespaces(remaining_s, remaining_len);
534
0
                if ((UNLIKELY(i == first || (remaining_len != 0 &&
535
0
                                             !is_float_suffix(remaining_s, remaining_len))))) {
536
                    // Reject the string because either the first char was not a digit,
537
                    // or the remaining chars are not all whitespace
538
0
                    *result = PARSE_FAILURE;
539
0
                    return 0;
540
0
                }
541
0
            }
542
            // Returning here is slightly faster than breaking the loop.
543
0
            *result = PARSE_SUCCESS;
544
0
            return static_cast<T>(negative ? -val : val);
545
0
        }
546
0
    }
547
0
    *result = PARSE_SUCCESS;
548
0
    return static_cast<T>(negative ? -val : val);
549
0
}
_ZN5doris12StringParser22string_to_int_internalIoLb0EEET_PKciPNS0_11ParseResultE
Line
Count
Source
477
8
T StringParser::string_to_int_internal(const char* __restrict s, int len, ParseResult* result) {
478
8
    if (UNLIKELY(len <= 0)) {
479
0
        *result = PARSE_FAILURE;
480
0
        return 0;
481
0
    }
482
483
8
    using UnsignedT = MakeUnsignedT<T>;
484
8
    UnsignedT val = 0;
485
8
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
486
8
    bool negative = false;
487
8
    int i = 0;
488
8
    switch (*s) {
489
0
    case '-':
490
0
        negative = true;
491
0
        max_val += 1;
492
0
        [[fallthrough]];
493
0
    case '+':
494
0
        ++i;
495
        // only one '+'/'-' char, so could return failure directly
496
0
        if (UNLIKELY(len == 1)) {
497
0
            *result = PARSE_FAILURE;
498
0
            return 0;
499
0
        }
500
8
    }
501
502
    // This is the fast path where the string cannot overflow.
503
8
    if (LIKELY(len - i < NumberTraits::max_ascii_len<T>())) {
504
0
        val = string_to_int_no_overflow<UnsignedT, enable_strict_mode>(s + i, len - i, result);
505
0
        return static_cast<T>(negative ? -val : val);
506
0
    }
507
508
8
    const T max_div_10 = max_val / 10;
509
8
    const T max_mod_10 = max_val % 10;
510
511
8
    int first = i;
512
168
    for (; i < len; ++i) {
513
160
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
514
160
            T digit = s[i] - '0';
515
            // This is a tricky check to see if adding this digit will cause an overflow.
516
160
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
517
0
                *result = PARSE_OVERFLOW;
518
0
                return negative ? -max_val : max_val;
519
0
            }
520
160
            val = val * 10 + digit;
521
160
        } else {
522
            if constexpr (enable_strict_mode) {
523
                if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
524
                    // Reject the string because the remaining chars are not all whitespace
525
                    *result = PARSE_FAILURE;
526
                    return 0;
527
                }
528
0
            } else {
529
                // Save original position where non-digit was found
530
0
                int remaining_len = len - i;
531
0
                const char* remaining_s = s + i;
532
                // Skip trailing whitespaces from the remaining portion
533
0
                remaining_s = skip_trailing_whitespaces(remaining_s, remaining_len);
534
0
                if ((UNLIKELY(i == first || (remaining_len != 0 &&
535
0
                                             !is_float_suffix(remaining_s, remaining_len))))) {
536
                    // Reject the string because either the first char was not a digit,
537
                    // or the remaining chars are not all whitespace
538
0
                    *result = PARSE_FAILURE;
539
0
                    return 0;
540
0
                }
541
0
            }
542
            // Returning here is slightly faster than breaking the loop.
543
0
            *result = PARSE_SUCCESS;
544
0
            return static_cast<T>(negative ? -val : val);
545
0
        }
546
160
    }
547
8
    *result = PARSE_SUCCESS;
548
8
    return static_cast<T>(negative ? -val : val);
549
8
}
550
551
template <typename T>
552
T StringParser::string_to_unsigned_int_internal(const char* __restrict s, int len,
553
2.74k
                                                ParseResult* result) {
554
2.74k
    if (UNLIKELY(len <= 0)) {
555
0
        *result = PARSE_FAILURE;
556
0
        return 0;
557
0
    }
558
559
2.74k
    T val = 0;
560
2.74k
    T max_val = std::numeric_limits<T>::max();
561
2.74k
    int i = 0;
562
563
2.74k
    using signedT = MakeSignedT<T>;
564
    // This is the fast path where the string cannot overflow.
565
2.74k
    if (LIKELY(len - i < NumberTraits::max_ascii_len<signedT>())) {
566
1.56k
        val = string_to_int_no_overflow<T>(s + i, len - i, result);
567
1.56k
        return val;
568
1.56k
    }
569
570
1.17k
    const T max_div_10 = max_val / 10;
571
1.17k
    const T max_mod_10 = max_val % 10;
572
573
1.17k
    int first = i;
574
9.31k
    for (; i < len; ++i) {
575
8.62k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
576
8.52k
            T digit = s[i] - '0';
577
            // This is a tricky check to see if adding this digit will cause an overflow.
578
8.52k
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
579
392
                *result = PARSE_OVERFLOW;
580
392
                return max_val;
581
392
            }
582
8.13k
            val = val * 10 + digit;
583
8.13k
        } else {
584
98
            if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
585
                // Reject the string because either the first char was not a digit,
586
                // or the remaining chars are not all whitespace
587
98
                *result = PARSE_FAILURE;
588
98
                return 0;
589
98
            }
590
            // Returning here is slightly faster than breaking the loop.
591
0
            *result = PARSE_SUCCESS;
592
0
            return val;
593
98
        }
594
8.62k
    }
595
686
    *result = PARSE_SUCCESS;
596
686
    return val;
597
1.17k
}
_ZN5doris12StringParser31string_to_unsigned_int_internalIhEET_PKciPNS0_11ParseResultE
Line
Count
Source
553
686
                                                ParseResult* result) {
554
686
    if (UNLIKELY(len <= 0)) {
555
0
        *result = PARSE_FAILURE;
556
0
        return 0;
557
0
    }
558
559
686
    T val = 0;
560
686
    T max_val = std::numeric_limits<T>::max();
561
686
    int i = 0;
562
563
686
    using signedT = MakeSignedT<T>;
564
    // This is the fast path where the string cannot overflow.
565
686
    if (LIKELY(len - i < NumberTraits::max_ascii_len<signedT>())) {
566
196
        val = string_to_int_no_overflow<T>(s + i, len - i, result);
567
196
        return val;
568
196
    }
569
570
490
    const T max_div_10 = max_val / 10;
571
490
    const T max_mod_10 = max_val % 10;
572
573
490
    int first = i;
574
1.56k
    for (; i < len; ++i) {
575
1.27k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
576
1.17k
            T digit = s[i] - '0';
577
            // This is a tricky check to see if adding this digit will cause an overflow.
578
1.17k
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
579
98
                *result = PARSE_OVERFLOW;
580
98
                return max_val;
581
98
            }
582
1.07k
            val = val * 10 + digit;
583
1.07k
        } else {
584
98
            if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
585
                // Reject the string because either the first char was not a digit,
586
                // or the remaining chars are not all whitespace
587
98
                *result = PARSE_FAILURE;
588
98
                return 0;
589
98
            }
590
            // Returning here is slightly faster than breaking the loop.
591
0
            *result = PARSE_SUCCESS;
592
0
            return val;
593
98
        }
594
1.27k
    }
595
294
    *result = PARSE_SUCCESS;
596
294
    return val;
597
490
}
_ZN5doris12StringParser31string_to_unsigned_int_internalItEET_PKciPNS0_11ParseResultE
Line
Count
Source
553
686
                                                ParseResult* result) {
554
686
    if (UNLIKELY(len <= 0)) {
555
0
        *result = PARSE_FAILURE;
556
0
        return 0;
557
0
    }
558
559
686
    T val = 0;
560
686
    T max_val = std::numeric_limits<T>::max();
561
686
    int i = 0;
562
563
686
    using signedT = MakeSignedT<T>;
564
    // This is the fast path where the string cannot overflow.
565
686
    if (LIKELY(len - i < NumberTraits::max_ascii_len<signedT>())) {
566
392
        val = string_to_int_no_overflow<T>(s + i, len - i, result);
567
392
        return val;
568
392
    }
569
570
294
    const T max_div_10 = max_val / 10;
571
294
    const T max_mod_10 = max_val % 10;
572
573
294
    int first = i;
574
1.66k
    for (; i < len; ++i) {
575
1.47k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
576
1.47k
            T digit = s[i] - '0';
577
            // This is a tricky check to see if adding this digit will cause an overflow.
578
1.47k
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
579
98
                *result = PARSE_OVERFLOW;
580
98
                return max_val;
581
98
            }
582
1.37k
            val = val * 10 + digit;
583
1.37k
        } else {
584
0
            if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
585
                // Reject the string because either the first char was not a digit,
586
                // or the remaining chars are not all whitespace
587
0
                *result = PARSE_FAILURE;
588
0
                return 0;
589
0
            }
590
            // Returning here is slightly faster than breaking the loop.
591
0
            *result = PARSE_SUCCESS;
592
0
            return val;
593
0
        }
594
1.47k
    }
595
196
    *result = PARSE_SUCCESS;
596
196
    return val;
597
294
}
_ZN5doris12StringParser31string_to_unsigned_int_internalIjEET_PKciPNS0_11ParseResultE
Line
Count
Source
553
686
                                                ParseResult* result) {
554
686
    if (UNLIKELY(len <= 0)) {
555
0
        *result = PARSE_FAILURE;
556
0
        return 0;
557
0
    }
558
559
686
    T val = 0;
560
686
    T max_val = std::numeric_limits<T>::max();
561
686
    int i = 0;
562
563
686
    using signedT = MakeSignedT<T>;
564
    // This is the fast path where the string cannot overflow.
565
686
    if (LIKELY(len - i < NumberTraits::max_ascii_len<signedT>())) {
566
490
        val = string_to_int_no_overflow<T>(s + i, len - i, result);
567
490
        return val;
568
490
    }
569
570
196
    const T max_div_10 = max_val / 10;
571
196
    const T max_mod_10 = max_val % 10;
572
573
196
    int first = i;
574
2.05k
    for (; i < len; ++i) {
575
1.96k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
576
1.96k
            T digit = s[i] - '0';
577
            // This is a tricky check to see if adding this digit will cause an overflow.
578
1.96k
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
579
98
                *result = PARSE_OVERFLOW;
580
98
                return max_val;
581
98
            }
582
1.86k
            val = val * 10 + digit;
583
1.86k
        } else {
584
0
            if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
585
                // Reject the string because either the first char was not a digit,
586
                // or the remaining chars are not all whitespace
587
0
                *result = PARSE_FAILURE;
588
0
                return 0;
589
0
            }
590
            // Returning here is slightly faster than breaking the loop.
591
0
            *result = PARSE_SUCCESS;
592
0
            return val;
593
0
        }
594
1.96k
    }
595
98
    *result = PARSE_SUCCESS;
596
98
    return val;
597
196
}
_ZN5doris12StringParser31string_to_unsigned_int_internalImEET_PKciPNS0_11ParseResultE
Line
Count
Source
553
686
                                                ParseResult* result) {
554
686
    if (UNLIKELY(len <= 0)) {
555
0
        *result = PARSE_FAILURE;
556
0
        return 0;
557
0
    }
558
559
686
    T val = 0;
560
686
    T max_val = std::numeric_limits<T>::max();
561
686
    int i = 0;
562
563
686
    using signedT = MakeSignedT<T>;
564
    // This is the fast path where the string cannot overflow.
565
686
    if (LIKELY(len - i < NumberTraits::max_ascii_len<signedT>())) {
566
490
        val = string_to_int_no_overflow<T>(s + i, len - i, result);
567
490
        return val;
568
490
    }
569
570
196
    const T max_div_10 = max_val / 10;
571
196
    const T max_mod_10 = max_val % 10;
572
573
196
    int first = i;
574
4.01k
    for (; i < len; ++i) {
575
3.92k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
576
3.92k
            T digit = s[i] - '0';
577
            // This is a tricky check to see if adding this digit will cause an overflow.
578
3.92k
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
579
98
                *result = PARSE_OVERFLOW;
580
98
                return max_val;
581
98
            }
582
3.82k
            val = val * 10 + digit;
583
3.82k
        } else {
584
0
            if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
585
                // Reject the string because either the first char was not a digit,
586
                // or the remaining chars are not all whitespace
587
0
                *result = PARSE_FAILURE;
588
0
                return 0;
589
0
            }
590
            // Returning here is slightly faster than breaking the loop.
591
0
            *result = PARSE_SUCCESS;
592
0
            return val;
593
0
        }
594
3.92k
    }
595
98
    *result = PARSE_SUCCESS;
596
98
    return val;
597
196
}
598
599
template <typename T>
600
T StringParser::string_to_int_internal(const char* __restrict s, int64_t len, int base,
601
55.6k
                                       ParseResult* result) {
602
55.6k
    using UnsignedT = MakeUnsignedT<T>;
603
55.6k
    UnsignedT val = 0;
604
55.6k
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
605
55.6k
    bool negative = false;
606
55.6k
    if (UNLIKELY(len <= 0)) {
607
0
        *result = PARSE_FAILURE;
608
0
        return 0;
609
0
    }
610
55.6k
    int i = 0;
611
55.6k
    switch (*s) {
612
26.8k
    case '-':
613
26.8k
        negative = true;
614
26.8k
        max_val = StringParser::numeric_limits<T>(false) + 1;
615
26.8k
        [[fallthrough]];
616
27.4k
    case '+':
617
27.4k
        i = 1;
618
55.6k
    }
619
620
55.6k
    const T max_div_base = max_val / base;
621
55.6k
    const T max_mod_base = max_val % base;
622
623
55.6k
    int first = i;
624
181k
    for (; i < len; ++i) {
625
153k
        T digit;
626
153k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
627
151k
            digit = s[i] - '0';
628
151k
        } else if (s[i] >= 'a' && s[i] <= 'z') {
629
1.27k
            digit = (s[i] - 'a' + 10);
630
1.27k
        } else if (s[i] >= 'A' && s[i] <= 'Z') {
631
196
            digit = (s[i] - 'A' + 10);
632
294
        } else {
633
294
            if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
634
                // Reject the string because either the first char was not an alpha/digit,
635
                // or the remaining chars are not all whitespace
636
294
                *result = PARSE_FAILURE;
637
294
                return 0;
638
294
            }
639
            // skip trailing whitespace.
640
0
            break;
641
294
        }
642
643
        // Bail, if we encounter a digit that is not available in base.
644
152k
        if (digit >= base) {
645
784
            break;
646
784
        }
647
648
        // This is a tricky check to see if adding this digit will cause an overflow.
649
152k
        if (UNLIKELY(val > (max_div_base - (digit > max_mod_base)))) {
650
25.9k
            *result = PARSE_OVERFLOW;
651
25.9k
            return static_cast<T>(negative ? -max_val : max_val);
652
25.9k
        }
653
126k
        val = val * base + digit;
654
126k
    }
655
29.4k
    *result = PARSE_SUCCESS;
656
29.4k
    return static_cast<T>(negative ? -val : val);
657
55.6k
}
_ZN5doris12StringParser22string_to_int_internalIaEET_PKcliPNS0_11ParseResultE
Line
Count
Source
601
52.9k
                                       ParseResult* result) {
602
52.9k
    using UnsignedT = MakeUnsignedT<T>;
603
52.9k
    UnsignedT val = 0;
604
52.9k
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
605
52.9k
    bool negative = false;
606
52.9k
    if (UNLIKELY(len <= 0)) {
607
0
        *result = PARSE_FAILURE;
608
0
        return 0;
609
0
    }
610
52.9k
    int i = 0;
611
52.9k
    switch (*s) {
612
25.7k
    case '-':
613
25.7k
        negative = true;
614
25.7k
        max_val = StringParser::numeric_limits<T>(false) + 1;
615
25.7k
        [[fallthrough]];
616
25.9k
    case '+':
617
25.9k
        i = 1;
618
52.9k
    }
619
620
52.9k
    const T max_div_base = max_val / base;
621
52.9k
    const T max_mod_base = max_val % base;
622
623
52.9k
    int first = i;
624
161k
    for (; i < len; ++i) {
625
134k
        T digit;
626
134k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
627
133k
            digit = s[i] - '0';
628
133k
        } else if (s[i] >= 'a' && s[i] <= 'z') {
629
1.07k
            digit = (s[i] - 'a' + 10);
630
1.07k
        } else if (s[i] >= 'A' && s[i] <= 'Z') {
631
196
            digit = (s[i] - 'A' + 10);
632
294
        } else {
633
294
            if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
634
                // Reject the string because either the first char was not an alpha/digit,
635
                // or the remaining chars are not all whitespace
636
294
                *result = PARSE_FAILURE;
637
294
                return 0;
638
294
            }
639
            // skip trailing whitespace.
640
0
            break;
641
294
        }
642
643
        // Bail, if we encounter a digit that is not available in base.
644
134k
        if (digit >= base) {
645
784
            break;
646
784
        }
647
648
        // This is a tricky check to see if adding this digit will cause an overflow.
649
133k
        if (UNLIKELY(val > (max_div_base - (digit > max_mod_base)))) {
650
25.3k
            *result = PARSE_OVERFLOW;
651
25.3k
            return static_cast<T>(negative ? -max_val : max_val);
652
25.3k
        }
653
108k
        val = val * base + digit;
654
108k
    }
655
27.2k
    *result = PARSE_SUCCESS;
656
27.2k
    return static_cast<T>(negative ? -val : val);
657
52.9k
}
_ZN5doris12StringParser22string_to_int_internalIsEET_PKcliPNS0_11ParseResultE
Line
Count
Source
601
980
                                       ParseResult* result) {
602
980
    using UnsignedT = MakeUnsignedT<T>;
603
980
    UnsignedT val = 0;
604
980
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
605
980
    bool negative = false;
606
980
    if (UNLIKELY(len <= 0)) {
607
0
        *result = PARSE_FAILURE;
608
0
        return 0;
609
0
    }
610
980
    int i = 0;
611
980
    switch (*s) {
612
392
    case '-':
613
392
        negative = true;
614
392
        max_val = StringParser::numeric_limits<T>(false) + 1;
615
392
        [[fallthrough]];
616
490
    case '+':
617
490
        i = 1;
618
980
    }
619
620
980
    const T max_div_base = max_val / base;
621
980
    const T max_mod_base = max_val % base;
622
623
980
    int first = i;
624
4.21k
    for (; i < len; ++i) {
625
3.43k
        T digit;
626
3.43k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
627
3.23k
            digit = s[i] - '0';
628
3.23k
        } else if (s[i] >= 'a' && s[i] <= 'z') {
629
196
            digit = (s[i] - 'a' + 10);
630
196
        } else if (s[i] >= 'A' && s[i] <= 'Z') {
631
0
            digit = (s[i] - 'A' + 10);
632
0
        } else {
633
0
            if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
634
                // Reject the string because either the first char was not an alpha/digit,
635
                // or the remaining chars are not all whitespace
636
0
                *result = PARSE_FAILURE;
637
0
                return 0;
638
0
            }
639
            // skip trailing whitespace.
640
0
            break;
641
0
        }
642
643
        // Bail, if we encounter a digit that is not available in base.
644
3.43k
        if (digit >= base) {
645
0
            break;
646
0
        }
647
648
        // This is a tricky check to see if adding this digit will cause an overflow.
649
3.43k
        if (UNLIKELY(val > (max_div_base - (digit > max_mod_base)))) {
650
196
            *result = PARSE_OVERFLOW;
651
196
            return static_cast<T>(negative ? -max_val : max_val);
652
196
        }
653
3.23k
        val = val * base + digit;
654
3.23k
    }
655
784
    *result = PARSE_SUCCESS;
656
784
    return static_cast<T>(negative ? -val : val);
657
980
}
_ZN5doris12StringParser22string_to_int_internalIiEET_PKcliPNS0_11ParseResultE
Line
Count
Source
601
882
                                       ParseResult* result) {
602
882
    using UnsignedT = MakeUnsignedT<T>;
603
882
    UnsignedT val = 0;
604
882
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
605
882
    bool negative = false;
606
882
    if (UNLIKELY(len <= 0)) {
607
0
        *result = PARSE_FAILURE;
608
0
        return 0;
609
0
    }
610
882
    int i = 0;
611
882
    switch (*s) {
612
294
    case '-':
613
294
        negative = true;
614
294
        max_val = StringParser::numeric_limits<T>(false) + 1;
615
294
        [[fallthrough]];
616
490
    case '+':
617
490
        i = 1;
618
882
    }
619
620
882
    const T max_div_base = max_val / base;
621
882
    const T max_mod_base = max_val % base;
622
623
882
    int first = i;
624
6.07k
    for (; i < len; ++i) {
625
5.39k
        T digit;
626
5.39k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
627
5.39k
            digit = s[i] - '0';
628
5.39k
        } else if (s[i] >= 'a' && s[i] <= 'z') {
629
0
            digit = (s[i] - 'a' + 10);
630
0
        } else if (s[i] >= 'A' && s[i] <= 'Z') {
631
0
            digit = (s[i] - 'A' + 10);
632
0
        } else {
633
0
            if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
634
                // Reject the string because either the first char was not an alpha/digit,
635
                // or the remaining chars are not all whitespace
636
0
                *result = PARSE_FAILURE;
637
0
                return 0;
638
0
            }
639
            // skip trailing whitespace.
640
0
            break;
641
0
        }
642
643
        // Bail, if we encounter a digit that is not available in base.
644
5.39k
        if (digit >= base) {
645
0
            break;
646
0
        }
647
648
        // This is a tricky check to see if adding this digit will cause an overflow.
649
5.39k
        if (UNLIKELY(val > (max_div_base - (digit > max_mod_base)))) {
650
196
            *result = PARSE_OVERFLOW;
651
196
            return static_cast<T>(negative ? -max_val : max_val);
652
196
        }
653
5.19k
        val = val * base + digit;
654
5.19k
    }
655
686
    *result = PARSE_SUCCESS;
656
686
    return static_cast<T>(negative ? -val : val);
657
882
}
_ZN5doris12StringParser22string_to_int_internalIlEET_PKcliPNS0_11ParseResultE
Line
Count
Source
601
882
                                       ParseResult* result) {
602
882
    using UnsignedT = MakeUnsignedT<T>;
603
882
    UnsignedT val = 0;
604
882
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
605
882
    bool negative = false;
606
882
    if (UNLIKELY(len <= 0)) {
607
0
        *result = PARSE_FAILURE;
608
0
        return 0;
609
0
    }
610
882
    int i = 0;
611
882
    switch (*s) {
612
392
    case '-':
613
392
        negative = true;
614
392
        max_val = StringParser::numeric_limits<T>(false) + 1;
615
392
        [[fallthrough]];
616
490
    case '+':
617
490
        i = 1;
618
882
    }
619
620
882
    const T max_div_base = max_val / base;
621
882
    const T max_mod_base = max_val % base;
622
623
882
    int first = i;
624
10.1k
    for (; i < len; ++i) {
625
9.50k
        T digit;
626
9.50k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
627
9.50k
            digit = s[i] - '0';
628
9.50k
        } else if (s[i] >= 'a' && s[i] <= 'z') {
629
0
            digit = (s[i] - 'a' + 10);
630
0
        } else if (s[i] >= 'A' && s[i] <= 'Z') {
631
0
            digit = (s[i] - 'A' + 10);
632
0
        } else {
633
0
            if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
634
                // Reject the string because either the first char was not an alpha/digit,
635
                // or the remaining chars are not all whitespace
636
0
                *result = PARSE_FAILURE;
637
0
                return 0;
638
0
            }
639
            // skip trailing whitespace.
640
0
            break;
641
0
        }
642
643
        // Bail, if we encounter a digit that is not available in base.
644
9.50k
        if (digit >= base) {
645
0
            break;
646
0
        }
647
648
        // This is a tricky check to see if adding this digit will cause an overflow.
649
9.50k
        if (UNLIKELY(val > (max_div_base - (digit > max_mod_base)))) {
650
196
            *result = PARSE_OVERFLOW;
651
196
            return static_cast<T>(negative ? -max_val : max_val);
652
196
        }
653
9.31k
        val = val * base + digit;
654
9.31k
    }
655
686
    *result = PARSE_SUCCESS;
656
686
    return static_cast<T>(negative ? -val : val);
657
882
}
_ZN5doris12StringParser22string_to_int_internalImEET_PKcliPNS0_11ParseResultE
Line
Count
Source
601
2
                                       ParseResult* result) {
602
2
    using UnsignedT = MakeUnsignedT<T>;
603
2
    UnsignedT val = 0;
604
2
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
605
2
    bool negative = false;
606
2
    if (UNLIKELY(len <= 0)) {
607
0
        *result = PARSE_FAILURE;
608
0
        return 0;
609
0
    }
610
2
    int i = 0;
611
2
    switch (*s) {
612
0
    case '-':
613
0
        negative = true;
614
0
        max_val = StringParser::numeric_limits<T>(false) + 1;
615
0
        [[fallthrough]];
616
0
    case '+':
617
0
        i = 1;
618
2
    }
619
620
2
    const T max_div_base = max_val / base;
621
2
    const T max_mod_base = max_val % base;
622
623
2
    int first = i;
624
6
    for (; i < len; ++i) {
625
4
        T digit;
626
4
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
627
0
            digit = s[i] - '0';
628
4
        } else if (s[i] >= 'a' && s[i] <= 'z') {
629
4
            digit = (s[i] - 'a' + 10);
630
4
        } else if (s[i] >= 'A' && s[i] <= 'Z') {
631
0
            digit = (s[i] - 'A' + 10);
632
0
        } else {
633
0
            if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
634
                // Reject the string because either the first char was not an alpha/digit,
635
                // or the remaining chars are not all whitespace
636
0
                *result = PARSE_FAILURE;
637
0
                return 0;
638
0
            }
639
            // skip trailing whitespace.
640
0
            break;
641
0
        }
642
643
        // Bail, if we encounter a digit that is not available in base.
644
4
        if (digit >= base) {
645
0
            break;
646
0
        }
647
648
        // This is a tricky check to see if adding this digit will cause an overflow.
649
4
        if (UNLIKELY(val > (max_div_base - (digit > max_mod_base)))) {
650
0
            *result = PARSE_OVERFLOW;
651
0
            return static_cast<T>(negative ? -max_val : max_val);
652
0
        }
653
4
        val = val * base + digit;
654
4
    }
655
2
    *result = PARSE_SUCCESS;
656
2
    return static_cast<T>(negative ? -val : val);
657
2
}
658
659
template <typename T, bool enable_strict_mode>
660
570k
T StringParser::string_to_int_no_overflow(const char* __restrict s, int len, ParseResult* result) {
661
570k
    T val = 0;
662
570k
    if (UNLIKELY(len == 0)) {
663
0
        *result = PARSE_SUCCESS;
664
0
        return val;
665
0
    }
666
    // Factor out the first char for error handling speeds up the loop.
667
570k
    if (LIKELY(s[0] >= '0' && s[0] <= '9')) {
668
557k
        val = s[0] - '0';
669
557k
    } else {
670
12.6k
        *result = PARSE_FAILURE;
671
12.6k
        return 0;
672
12.6k
    }
673
1.12M
    for (int i = 1; i < len; ++i) {
674
570k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
675
563k
            T digit = s[i] - '0';
676
563k
            val = val * 10 + digit;
677
563k
        } else {
678
7.64k
            if constexpr (enable_strict_mode) {
679
2.63k
                if (UNLIKELY(!is_all_whitespace(s + i, len - i))) {
680
2.35k
                    *result = PARSE_FAILURE;
681
2.35k
                    return 0;
682
2.35k
                }
683
5.01k
            } else {
684
                // Save original position where non-digit was found
685
5.01k
                int remaining_len = len - i;
686
5.01k
                const char* remaining_s = s + i;
687
                // Skip trailing whitespaces from the remaining portion
688
5.01k
                remaining_s = skip_trailing_whitespaces(remaining_s, remaining_len);
689
5.01k
                if ((UNLIKELY(remaining_len != 0 &&
690
5.01k
                              !is_float_suffix(remaining_s, remaining_len)))) {
691
988
                    *result = PARSE_FAILURE;
692
988
                    return 0;
693
988
                }
694
5.01k
            }
695
4.30k
            *result = PARSE_SUCCESS;
696
7.64k
            return val;
697
7.64k
        }
698
570k
    }
699
550k
    *result = PARSE_SUCCESS;
700
550k
    return val;
701
557k
}
_ZN5doris12StringParser25string_to_int_no_overflowIoLb0EEET_PKciPNS0_11ParseResultE
Line
Count
Source
660
85.2k
T StringParser::string_to_int_no_overflow(const char* __restrict s, int len, ParseResult* result) {
661
85.2k
    T val = 0;
662
85.2k
    if (UNLIKELY(len == 0)) {
663
0
        *result = PARSE_SUCCESS;
664
0
        return val;
665
0
    }
666
    // Factor out the first char for error handling speeds up the loop.
667
85.2k
    if (LIKELY(s[0] >= '0' && s[0] <= '9')) {
668
83.3k
        val = s[0] - '0';
669
83.3k
    } else {
670
1.83k
        *result = PARSE_FAILURE;
671
1.83k
        return 0;
672
1.83k
    }
673
119k
    for (int i = 1; i < len; ++i) {
674
36.8k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
675
36.0k
            T digit = s[i] - '0';
676
36.0k
            val = val * 10 + digit;
677
36.0k
        } else {
678
            if constexpr (enable_strict_mode) {
679
                if (UNLIKELY(!is_all_whitespace(s + i, len - i))) {
680
                    *result = PARSE_FAILURE;
681
                    return 0;
682
                }
683
756
            } else {
684
                // Save original position where non-digit was found
685
756
                int remaining_len = len - i;
686
756
                const char* remaining_s = s + i;
687
                // Skip trailing whitespaces from the remaining portion
688
756
                remaining_s = skip_trailing_whitespaces(remaining_s, remaining_len);
689
756
                if ((UNLIKELY(remaining_len != 0 &&
690
756
                              !is_float_suffix(remaining_s, remaining_len)))) {
691
196
                    *result = PARSE_FAILURE;
692
196
                    return 0;
693
196
                }
694
756
            }
695
560
            *result = PARSE_SUCCESS;
696
756
            return val;
697
756
        }
698
36.8k
    }
699
82.6k
    *result = PARSE_SUCCESS;
700
82.6k
    return val;
701
83.3k
}
_ZN5doris12StringParser25string_to_int_no_overflowIhLb0EEET_PKciPNS0_11ParseResultE
Line
Count
Source
660
123k
T StringParser::string_to_int_no_overflow(const char* __restrict s, int len, ParseResult* result) {
661
123k
    T val = 0;
662
123k
    if (UNLIKELY(len == 0)) {
663
0
        *result = PARSE_SUCCESS;
664
0
        return val;
665
0
    }
666
    // Factor out the first char for error handling speeds up the loop.
667
123k
    if (LIKELY(s[0] >= '0' && s[0] <= '9')) {
668
121k
        val = s[0] - '0';
669
121k
    } else {
670
1.16k
        *result = PARSE_FAILURE;
671
1.16k
        return 0;
672
1.16k
    }
673
173k
    for (int i = 1; i < len; ++i) {
674
51.4k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
675
51.4k
            T digit = s[i] - '0';
676
51.4k
            val = val * 10 + digit;
677
51.4k
        } else {
678
            if constexpr (enable_strict_mode) {
679
                if (UNLIKELY(!is_all_whitespace(s + i, len - i))) {
680
                    *result = PARSE_FAILURE;
681
                    return 0;
682
                }
683
4
            } else {
684
                // Save original position where non-digit was found
685
4
                int remaining_len = len - i;
686
4
                const char* remaining_s = s + i;
687
                // Skip trailing whitespaces from the remaining portion
688
4
                remaining_s = skip_trailing_whitespaces(remaining_s, remaining_len);
689
4
                if ((UNLIKELY(remaining_len != 0 &&
690
4
                              !is_float_suffix(remaining_s, remaining_len)))) {
691
4
                    *result = PARSE_FAILURE;
692
4
                    return 0;
693
4
                }
694
4
            }
695
0
            *result = PARSE_SUCCESS;
696
4
            return val;
697
4
        }
698
51.4k
    }
699
121k
    *result = PARSE_SUCCESS;
700
121k
    return val;
701
121k
}
_ZN5doris12StringParser25string_to_int_no_overflowIhLb1EEET_PKciPNS0_11ParseResultE
Line
Count
Source
660
532
T StringParser::string_to_int_no_overflow(const char* __restrict s, int len, ParseResult* result) {
661
532
    T val = 0;
662
532
    if (UNLIKELY(len == 0)) {
663
0
        *result = PARSE_SUCCESS;
664
0
        return val;
665
0
    }
666
    // Factor out the first char for error handling speeds up the loop.
667
532
    if (LIKELY(s[0] >= '0' && s[0] <= '9')) {
668
480
        val = s[0] - '0';
669
480
    } else {
670
52
        *result = PARSE_FAILURE;
671
52
        return 0;
672
52
    }
673
826
    for (int i = 1; i < len; ++i) {
674
350
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
675
346
            T digit = s[i] - '0';
676
346
            val = val * 10 + digit;
677
346
        } else {
678
4
            if constexpr (enable_strict_mode) {
679
4
                if (UNLIKELY(!is_all_whitespace(s + i, len - i))) {
680
4
                    *result = PARSE_FAILURE;
681
4
                    return 0;
682
4
                }
683
            } else {
684
                // Save original position where non-digit was found
685
                int remaining_len = len - i;
686
                const char* remaining_s = s + i;
687
                // Skip trailing whitespaces from the remaining portion
688
                remaining_s = skip_trailing_whitespaces(remaining_s, remaining_len);
689
                if ((UNLIKELY(remaining_len != 0 &&
690
                              !is_float_suffix(remaining_s, remaining_len)))) {
691
                    *result = PARSE_FAILURE;
692
                    return 0;
693
                }
694
            }
695
0
            *result = PARSE_SUCCESS;
696
4
            return val;
697
4
        }
698
350
    }
699
476
    *result = PARSE_SUCCESS;
700
476
    return val;
701
480
}
_ZN5doris12StringParser25string_to_int_no_overflowItLb0EEET_PKciPNS0_11ParseResultE
Line
Count
Source
660
103k
T StringParser::string_to_int_no_overflow(const char* __restrict s, int len, ParseResult* result) {
661
103k
    T val = 0;
662
103k
    if (UNLIKELY(len == 0)) {
663
0
        *result = PARSE_SUCCESS;
664
0
        return val;
665
0
    }
666
    // Factor out the first char for error handling speeds up the loop.
667
103k
    if (LIKELY(s[0] >= '0' && s[0] <= '9')) {
668
101k
        val = s[0] - '0';
669
101k
    } else {
670
1.83k
        *result = PARSE_FAILURE;
671
1.83k
        return 0;
672
1.83k
    }
673
148k
    for (int i = 1; i < len; ++i) {
674
48.4k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
675
46.5k
            T digit = s[i] - '0';
676
46.5k
            val = val * 10 + digit;
677
46.5k
        } else {
678
            if constexpr (enable_strict_mode) {
679
                if (UNLIKELY(!is_all_whitespace(s + i, len - i))) {
680
                    *result = PARSE_FAILURE;
681
                    return 0;
682
                }
683
1.93k
            } else {
684
                // Save original position where non-digit was found
685
1.93k
                int remaining_len = len - i;
686
1.93k
                const char* remaining_s = s + i;
687
                // Skip trailing whitespaces from the remaining portion
688
1.93k
                remaining_s = skip_trailing_whitespaces(remaining_s, remaining_len);
689
1.93k
                if ((UNLIKELY(remaining_len != 0 &&
690
1.93k
                              !is_float_suffix(remaining_s, remaining_len)))) {
691
148
                    *result = PARSE_FAILURE;
692
148
                    return 0;
693
148
                }
694
1.93k
            }
695
1.78k
            *result = PARSE_SUCCESS;
696
1.93k
            return val;
697
1.93k
        }
698
48.4k
    }
699
99.8k
    *result = PARSE_SUCCESS;
700
99.8k
    return val;
701
101k
}
_ZN5doris12StringParser25string_to_int_no_overflowItLb1EEET_PKciPNS0_11ParseResultE
Line
Count
Source
660
816
T StringParser::string_to_int_no_overflow(const char* __restrict s, int len, ParseResult* result) {
661
816
    T val = 0;
662
816
    if (UNLIKELY(len == 0)) {
663
0
        *result = PARSE_SUCCESS;
664
0
        return val;
665
0
    }
666
    // Factor out the first char for error handling speeds up the loop.
667
816
    if (LIKELY(s[0] >= '0' && s[0] <= '9')) {
668
740
        val = s[0] - '0';
669
740
    } else {
670
76
        *result = PARSE_FAILURE;
671
76
        return 0;
672
76
    }
673
1.85k
    for (int i = 1; i < len; ++i) {
674
1.27k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
675
1.11k
            T digit = s[i] - '0';
676
1.11k
            val = val * 10 + digit;
677
1.11k
        } else {
678
164
            if constexpr (enable_strict_mode) {
679
164
                if (UNLIKELY(!is_all_whitespace(s + i, len - i))) {
680
164
                    *result = PARSE_FAILURE;
681
164
                    return 0;
682
164
                }
683
            } else {
684
                // Save original position where non-digit was found
685
                int remaining_len = len - i;
686
                const char* remaining_s = s + i;
687
                // Skip trailing whitespaces from the remaining portion
688
                remaining_s = skip_trailing_whitespaces(remaining_s, remaining_len);
689
                if ((UNLIKELY(remaining_len != 0 &&
690
                              !is_float_suffix(remaining_s, remaining_len)))) {
691
                    *result = PARSE_FAILURE;
692
                    return 0;
693
                }
694
            }
695
0
            *result = PARSE_SUCCESS;
696
164
            return val;
697
164
        }
698
1.27k
    }
699
576
    *result = PARSE_SUCCESS;
700
576
    return val;
701
740
}
_ZN5doris12StringParser25string_to_int_no_overflowIjLb0EEET_PKciPNS0_11ParseResultE
Line
Count
Source
660
184k
T StringParser::string_to_int_no_overflow(const char* __restrict s, int len, ParseResult* result) {
661
184k
    T val = 0;
662
184k
    if (UNLIKELY(len == 0)) {
663
0
        *result = PARSE_SUCCESS;
664
0
        return val;
665
0
    }
666
    // Factor out the first char for error handling speeds up the loop.
667
184k
    if (LIKELY(s[0] >= '0' && s[0] <= '9')) {
668
179k
        val = s[0] - '0';
669
179k
    } else {
670
4.40k
        *result = PARSE_FAILURE;
671
4.40k
        return 0;
672
4.40k
    }
673
522k
    for (int i = 1; i < len; ++i) {
674
344k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
675
342k
            T digit = s[i] - '0';
676
342k
            val = val * 10 + digit;
677
342k
        } else {
678
            if constexpr (enable_strict_mode) {
679
                if (UNLIKELY(!is_all_whitespace(s + i, len - i))) {
680
                    *result = PARSE_FAILURE;
681
                    return 0;
682
                }
683
1.08k
            } else {
684
                // Save original position where non-digit was found
685
1.08k
                int remaining_len = len - i;
686
1.08k
                const char* remaining_s = s + i;
687
                // Skip trailing whitespaces from the remaining portion
688
1.08k
                remaining_s = skip_trailing_whitespaces(remaining_s, remaining_len);
689
1.08k
                if ((UNLIKELY(remaining_len != 0 &&
690
1.08k
                              !is_float_suffix(remaining_s, remaining_len)))) {
691
392
                    *result = PARSE_FAILURE;
692
392
                    return 0;
693
392
                }
694
1.08k
            }
695
697
            *result = PARSE_SUCCESS;
696
1.08k
            return val;
697
1.08k
        }
698
344k
    }
699
178k
    *result = PARSE_SUCCESS;
700
178k
    return val;
701
179k
}
_ZN5doris12StringParser25string_to_int_no_overflowIjLb1EEET_PKciPNS0_11ParseResultE
Line
Count
Source
660
1.93k
T StringParser::string_to_int_no_overflow(const char* __restrict s, int len, ParseResult* result) {
661
1.93k
    T val = 0;
662
1.93k
    if (UNLIKELY(len == 0)) {
663
0
        *result = PARSE_SUCCESS;
664
0
        return val;
665
0
    }
666
    // Factor out the first char for error handling speeds up the loop.
667
1.93k
    if (LIKELY(s[0] >= '0' && s[0] <= '9')) {
668
1.76k
        val = s[0] - '0';
669
1.76k
    } else {
670
178
        *result = PARSE_FAILURE;
671
178
        return 0;
672
178
    }
673
5.22k
    for (int i = 1; i < len; ++i) {
674
4.10k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
675
3.46k
            T digit = s[i] - '0';
676
3.46k
            val = val * 10 + digit;
677
3.46k
        } else {
678
640
            if constexpr (enable_strict_mode) {
679
640
                if (UNLIKELY(!is_all_whitespace(s + i, len - i))) {
680
584
                    *result = PARSE_FAILURE;
681
584
                    return 0;
682
584
                }
683
            } else {
684
                // Save original position where non-digit was found
685
                int remaining_len = len - i;
686
                const char* remaining_s = s + i;
687
                // Skip trailing whitespaces from the remaining portion
688
                remaining_s = skip_trailing_whitespaces(remaining_s, remaining_len);
689
                if ((UNLIKELY(remaining_len != 0 &&
690
                              !is_float_suffix(remaining_s, remaining_len)))) {
691
                    *result = PARSE_FAILURE;
692
                    return 0;
693
                }
694
            }
695
56
            *result = PARSE_SUCCESS;
696
640
            return val;
697
640
        }
698
4.10k
    }
699
1.12k
    *result = PARSE_SUCCESS;
700
1.12k
    return val;
701
1.76k
}
_ZN5doris12StringParser25string_to_int_no_overflowImLb0EEET_PKciPNS0_11ParseResultE
Line
Count
Source
660
67.1k
T StringParser::string_to_int_no_overflow(const char* __restrict s, int len, ParseResult* result) {
661
67.1k
    T val = 0;
662
67.1k
    if (UNLIKELY(len == 0)) {
663
0
        *result = PARSE_SUCCESS;
664
0
        return val;
665
0
    }
666
    // Factor out the first char for error handling speeds up the loop.
667
67.1k
    if (LIKELY(s[0] >= '0' && s[0] <= '9')) {
668
64.9k
        val = s[0] - '0';
669
64.9k
    } else {
670
2.15k
        *result = PARSE_FAILURE;
671
2.15k
        return 0;
672
2.15k
    }
673
137k
    for (int i = 1; i < len; ++i) {
674
74.1k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
675
72.8k
            T digit = s[i] - '0';
676
72.8k
            val = val * 10 + digit;
677
72.8k
        } else {
678
            if constexpr (enable_strict_mode) {
679
                if (UNLIKELY(!is_all_whitespace(s + i, len - i))) {
680
                    *result = PARSE_FAILURE;
681
                    return 0;
682
                }
683
1.23k
            } else {
684
                // Save original position where non-digit was found
685
1.23k
                int remaining_len = len - i;
686
1.23k
                const char* remaining_s = s + i;
687
                // Skip trailing whitespaces from the remaining portion
688
1.23k
                remaining_s = skip_trailing_whitespaces(remaining_s, remaining_len);
689
1.23k
                if ((UNLIKELY(remaining_len != 0 &&
690
1.23k
                              !is_float_suffix(remaining_s, remaining_len)))) {
691
248
                    *result = PARSE_FAILURE;
692
248
                    return 0;
693
248
                }
694
1.23k
            }
695
982
            *result = PARSE_SUCCESS;
696
1.23k
            return val;
697
1.23k
        }
698
74.1k
    }
699
63.7k
    *result = PARSE_SUCCESS;
700
63.7k
    return val;
701
64.9k
}
_ZN5doris12StringParser25string_to_int_no_overflowImLb1EEET_PKciPNS0_11ParseResultE
Line
Count
Source
660
1.95k
T StringParser::string_to_int_no_overflow(const char* __restrict s, int len, ParseResult* result) {
661
1.95k
    T val = 0;
662
1.95k
    if (UNLIKELY(len == 0)) {
663
0
        *result = PARSE_SUCCESS;
664
0
        return val;
665
0
    }
666
    // Factor out the first char for error handling speeds up the loop.
667
1.95k
    if (LIKELY(s[0] >= '0' && s[0] <= '9')) {
668
1.52k
        val = s[0] - '0';
669
1.52k
    } else {
670
434
        *result = PARSE_FAILURE;
671
434
        return 0;
672
434
    }
673
5.45k
    for (int i = 1; i < len; ++i) {
674
4.84k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
675
3.93k
            T digit = s[i] - '0';
676
3.93k
            val = val * 10 + digit;
677
3.93k
        } else {
678
912
            if constexpr (enable_strict_mode) {
679
912
                if (UNLIKELY(!is_all_whitespace(s + i, len - i))) {
680
800
                    *result = PARSE_FAILURE;
681
800
                    return 0;
682
800
                }
683
            } else {
684
                // Save original position where non-digit was found
685
                int remaining_len = len - i;
686
                const char* remaining_s = s + i;
687
                // Skip trailing whitespaces from the remaining portion
688
                remaining_s = skip_trailing_whitespaces(remaining_s, remaining_len);
689
                if ((UNLIKELY(remaining_len != 0 &&
690
                              !is_float_suffix(remaining_s, remaining_len)))) {
691
                    *result = PARSE_FAILURE;
692
                    return 0;
693
                }
694
            }
695
112
            *result = PARSE_SUCCESS;
696
912
            return val;
697
912
        }
698
4.84k
    }
699
610
    *result = PARSE_SUCCESS;
700
610
    return val;
701
1.52k
}
_ZN5doris12StringParser25string_to_int_no_overflowIoLb1EEET_PKciPNS0_11ParseResultE
Line
Count
Source
660
1.98k
T StringParser::string_to_int_no_overflow(const char* __restrict s, int len, ParseResult* result) {
661
1.98k
    T val = 0;
662
1.98k
    if (UNLIKELY(len == 0)) {
663
0
        *result = PARSE_SUCCESS;
664
0
        return val;
665
0
    }
666
    // Factor out the first char for error handling speeds up the loop.
667
1.98k
    if (LIKELY(s[0] >= '0' && s[0] <= '9')) {
668
1.50k
        val = s[0] - '0';
669
1.50k
    } else {
670
480
        *result = PARSE_FAILURE;
671
480
        return 0;
672
480
    }
673
5.87k
    for (int i = 1; i < len; ++i) {
674
5.28k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
675
4.37k
            T digit = s[i] - '0';
676
4.37k
            val = val * 10 + digit;
677
4.37k
        } else {
678
912
            if constexpr (enable_strict_mode) {
679
912
                if (UNLIKELY(!is_all_whitespace(s + i, len - i))) {
680
800
                    *result = PARSE_FAILURE;
681
800
                    return 0;
682
800
                }
683
            } else {
684
                // Save original position where non-digit was found
685
                int remaining_len = len - i;
686
                const char* remaining_s = s + i;
687
                // Skip trailing whitespaces from the remaining portion
688
                remaining_s = skip_trailing_whitespaces(remaining_s, remaining_len);
689
                if ((UNLIKELY(remaining_len != 0 &&
690
                              !is_float_suffix(remaining_s, remaining_len)))) {
691
                    *result = PARSE_FAILURE;
692
                    return 0;
693
                }
694
            }
695
112
            *result = PARSE_SUCCESS;
696
912
            return val;
697
912
        }
698
5.28k
    }
699
592
    *result = PARSE_SUCCESS;
700
592
    return val;
701
1.50k
}
_ZN5doris12StringParser25string_to_int_no_overflowIN4wide7integerILm256EjEELb0EEET_PKciPNS0_11ParseResultE
Line
Count
Source
660
8
T StringParser::string_to_int_no_overflow(const char* __restrict s, int len, ParseResult* result) {
661
8
    T val = 0;
662
8
    if (UNLIKELY(len == 0)) {
663
0
        *result = PARSE_SUCCESS;
664
0
        return val;
665
0
    }
666
    // Factor out the first char for error handling speeds up the loop.
667
8
    if (LIKELY(s[0] >= '0' && s[0] <= '9')) {
668
8
        val = s[0] - '0';
669
8
    } else {
670
0
        *result = PARSE_FAILURE;
671
0
        return 0;
672
0
    }
673
8
    for (int i = 1; i < len; ++i) {
674
0
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
675
0
            T digit = s[i] - '0';
676
0
            val = val * 10 + digit;
677
0
        } else {
678
            if constexpr (enable_strict_mode) {
679
                if (UNLIKELY(!is_all_whitespace(s + i, len - i))) {
680
                    *result = PARSE_FAILURE;
681
                    return 0;
682
                }
683
0
            } else {
684
                // Save original position where non-digit was found
685
0
                int remaining_len = len - i;
686
0
                const char* remaining_s = s + i;
687
                // Skip trailing whitespaces from the remaining portion
688
0
                remaining_s = skip_trailing_whitespaces(remaining_s, remaining_len);
689
0
                if ((UNLIKELY(remaining_len != 0 &&
690
0
                              !is_float_suffix(remaining_s, remaining_len)))) {
691
0
                    *result = PARSE_FAILURE;
692
0
                    return 0;
693
0
                }
694
0
            }
695
0
            *result = PARSE_SUCCESS;
696
0
            return val;
697
0
        }
698
0
    }
699
8
    *result = PARSE_SUCCESS;
700
8
    return val;
701
8
}
702
703
// at least the first char(if any) must be a digit.
704
template <typename T>
705
T StringParser::string_to_uint_greedy_no_overflow(const char* __restrict s, int max_len,
706
277k
                                                  ParseResult* result) {
707
277k
    T val = 0;
708
277k
    if (max_len == 0) [[unlikely]] {
709
274k
        *result = PARSE_SUCCESS;
710
274k
        return val;
711
274k
    }
712
    // Factor out the first char for error handling speeds up the loop.
713
3.21k
    if (is_numeric_ascii(s[0])) [[likely]] {
714
3.21k
        val = s[0] - '0';
715
3.21k
    } else {
716
0
        *result = PARSE_FAILURE;
717
0
        return 0;
718
0
    }
719
16.5k
    for (int i = 1; i < max_len; ++i) {
720
13.3k
        if (is_numeric_ascii(s[i])) [[likely]] {
721
13.3k
            T digit = s[i] - '0';
722
13.3k
            val = val * 10 + digit;
723
13.3k
        } else {
724
            // 123abc, return 123
725
0
            *result = PARSE_SUCCESS;
726
0
            return val;
727
0
        }
728
13.3k
    }
729
3.21k
    *result = PARSE_SUCCESS;
730
3.21k
    return val;
731
3.21k
}
732
733
template <typename T>
734
311k
T StringParser::string_to_float_internal(const char* __restrict s, int len, ParseResult* result) {
735
311k
    int i = 0;
736
    // skip leading spaces
737
311k
    for (; i < len; ++i) {
738
311k
        if (!is_whitespace_ascii(s[i])) {
739
311k
            break;
740
311k
        }
741
311k
    }
742
743
    // skip back spaces
744
311k
    int j = len - 1;
745
311k
    for (; j >= i; j--) {
746
311k
        if (!is_whitespace_ascii(s[j])) {
747
311k
            break;
748
311k
        }
749
311k
    }
750
751
    // skip leading '+', from_chars can handle '-'
752
311k
    if (i < len && s[i] == '+') {
753
14.1k
        i++;
754
        // ++ or +- are not valid, but the first + is already skipped,
755
        // if don't check here, from_chars will succeed.
756
        //
757
        // New version of fast_float supports a new flag called 'chars_format::allow_leading_plus'
758
        // which may avoid this extra check here.
759
        // e.g.:
760
        // fast_float::chars_format format =
761
        //         fast_float::chars_format::general | fast_float::chars_format::allow_leading_plus;
762
        // auto res = fast_float::from_chars(s + i, s + j + 1, val, format);
763
14.1k
        if (i < len && (s[i] == '+' || s[i] == '-')) {
764
40
            *result = PARSE_FAILURE;
765
40
            return 0;
766
40
        }
767
14.1k
    }
768
311k
    if (UNLIKELY(i > j)) {
769
64
        *result = PARSE_FAILURE;
770
64
        return 0;
771
64
    }
772
773
    // Use double here to not lose precision while accumulating the result
774
311k
    double val = 0;
775
311k
    auto res = fast_float::from_chars(s + i, s + j + 1, val);
776
777
311k
    if (res.ptr == s + j + 1) {
778
302k
        *result = PARSE_SUCCESS;
779
302k
        return val;
780
302k
    } else {
781
9.23k
        *result = PARSE_FAILURE;
782
9.23k
    }
783
9.23k
    return 0;
784
311k
}
_ZN5doris12StringParser24string_to_float_internalIdEET_PKciPNS0_11ParseResultE
Line
Count
Source
734
178k
T StringParser::string_to_float_internal(const char* __restrict s, int len, ParseResult* result) {
735
178k
    int i = 0;
736
    // skip leading spaces
737
178k
    for (; i < len; ++i) {
738
178k
        if (!is_whitespace_ascii(s[i])) {
739
178k
            break;
740
178k
        }
741
178k
    }
742
743
    // skip back spaces
744
178k
    int j = len - 1;
745
178k
    for (; j >= i; j--) {
746
178k
        if (!is_whitespace_ascii(s[j])) {
747
178k
            break;
748
178k
        }
749
178k
    }
750
751
    // skip leading '+', from_chars can handle '-'
752
178k
    if (i < len && s[i] == '+') {
753
7.08k
        i++;
754
        // ++ or +- are not valid, but the first + is already skipped,
755
        // if don't check here, from_chars will succeed.
756
        //
757
        // New version of fast_float supports a new flag called 'chars_format::allow_leading_plus'
758
        // which may avoid this extra check here.
759
        // e.g.:
760
        // fast_float::chars_format format =
761
        //         fast_float::chars_format::general | fast_float::chars_format::allow_leading_plus;
762
        // auto res = fast_float::from_chars(s + i, s + j + 1, val, format);
763
7.08k
        if (i < len && (s[i] == '+' || s[i] == '-')) {
764
20
            *result = PARSE_FAILURE;
765
20
            return 0;
766
20
        }
767
7.08k
    }
768
178k
    if (UNLIKELY(i > j)) {
769
36
        *result = PARSE_FAILURE;
770
36
        return 0;
771
36
    }
772
773
    // Use double here to not lose precision while accumulating the result
774
178k
    double val = 0;
775
178k
    auto res = fast_float::from_chars(s + i, s + j + 1, val);
776
777
178k
    if (res.ptr == s + j + 1) {
778
173k
        *result = PARSE_SUCCESS;
779
173k
        return val;
780
173k
    } else {
781
4.65k
        *result = PARSE_FAILURE;
782
4.65k
    }
783
4.65k
    return 0;
784
178k
}
_ZN5doris12StringParser24string_to_float_internalIfEET_PKciPNS0_11ParseResultE
Line
Count
Source
734
132k
T StringParser::string_to_float_internal(const char* __restrict s, int len, ParseResult* result) {
735
132k
    int i = 0;
736
    // skip leading spaces
737
132k
    for (; i < len; ++i) {
738
132k
        if (!is_whitespace_ascii(s[i])) {
739
132k
            break;
740
132k
        }
741
132k
    }
742
743
    // skip back spaces
744
132k
    int j = len - 1;
745
132k
    for (; j >= i; j--) {
746
132k
        if (!is_whitespace_ascii(s[j])) {
747
132k
            break;
748
132k
        }
749
132k
    }
750
751
    // skip leading '+', from_chars can handle '-'
752
132k
    if (i < len && s[i] == '+') {
753
7.08k
        i++;
754
        // ++ or +- are not valid, but the first + is already skipped,
755
        // if don't check here, from_chars will succeed.
756
        //
757
        // New version of fast_float supports a new flag called 'chars_format::allow_leading_plus'
758
        // which may avoid this extra check here.
759
        // e.g.:
760
        // fast_float::chars_format format =
761
        //         fast_float::chars_format::general | fast_float::chars_format::allow_leading_plus;
762
        // auto res = fast_float::from_chars(s + i, s + j + 1, val, format);
763
7.08k
        if (i < len && (s[i] == '+' || s[i] == '-')) {
764
20
            *result = PARSE_FAILURE;
765
20
            return 0;
766
20
        }
767
7.08k
    }
768
132k
    if (UNLIKELY(i > j)) {
769
28
        *result = PARSE_FAILURE;
770
28
        return 0;
771
28
    }
772
773
    // Use double here to not lose precision while accumulating the result
774
132k
    double val = 0;
775
132k
    auto res = fast_float::from_chars(s + i, s + j + 1, val);
776
777
132k
    if (res.ptr == s + j + 1) {
778
128k
        *result = PARSE_SUCCESS;
779
128k
        return val;
780
128k
    } else {
781
4.57k
        *result = PARSE_FAILURE;
782
4.57k
    }
783
4.57k
    return 0;
784
132k
}
785
786
inline bool StringParser::string_to_bool_internal(const char* __restrict s, int len,
787
23.4k
                                                  ParseResult* result) {
788
23.4k
    *result = PARSE_SUCCESS;
789
790
23.4k
    if (len == 1) {
791
6.02k
        if (s[0] == '1' || s[0] == 't' || s[0] == 'T') {
792
1.08k
            return true;
793
1.08k
        }
794
4.93k
        if (s[0] == '0' || s[0] == 'f' || s[0] == 'F') {
795
2.15k
            return false;
796
2.15k
        }
797
2.78k
        *result = PARSE_FAILURE;
798
2.78k
        return false;
799
4.93k
    }
800
801
17.4k
    if (len == 2) {
802
1.95k
        if ((s[0] == 'o' || s[0] == 'O') && (s[1] == 'n' || s[1] == 'N')) {
803
20
            return true;
804
20
        }
805
1.93k
        if ((s[0] == 'n' || s[0] == 'N') && (s[1] == 'o' || s[1] == 'O')) {
806
18
            return false;
807
18
        }
808
1.93k
    }
809
810
17.3k
    if (len == 3) {
811
84
        if ((s[0] == 'y' || s[0] == 'Y') && (s[1] == 'e' || s[1] == 'E') &&
812
84
            (s[2] == 's' || s[2] == 'S')) {
813
20
            return true;
814
20
        }
815
64
        if ((s[0] == 'o' || s[0] == 'O') && (s[1] == 'f' || s[1] == 'F') &&
816
64
            (s[2] == 'f' || s[2] == 'F')) {
817
18
            return false;
818
18
        }
819
64
    }
820
821
17.3k
    if (len == 4 && (s[0] == 't' || s[0] == 'T') && (s[1] == 'r' || s[1] == 'R') &&
822
17.3k
        (s[2] == 'u' || s[2] == 'U') && (s[3] == 'e' || s[3] == 'E')) {
823
6.76k
        return true;
824
6.76k
    }
825
826
10.5k
    if (len == 5 && (s[0] == 'f' || s[0] == 'F') && (s[1] == 'a' || s[1] == 'A') &&
827
10.5k
        (s[2] == 'l' || s[2] == 'L') && (s[3] == 's' || s[3] == 'S') &&
828
10.5k
        (s[4] == 'e' || s[4] == 'E')) {
829
6.85k
        return false;
830
6.85k
    }
831
832
    // No valid boolean value found
833
3.74k
    *result = PARSE_FAILURE;
834
3.74k
    return false;
835
10.5k
}
836
#include "common/compile_check_avoid_end.h"
837
} // end namespace doris