Coverage Report

Created: 2025-08-18 03:01

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/root/doris/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/compiler_util.h" // IWYU pragma: keep
40
#include "common/status.h"
41
#include "runtime/large_int_value.h"
42
#include "runtime/primitive_type.h"
43
#include "vec/common/int_exp.h"
44
#include "vec/common/string_utils/string_utils.h"
45
#include "vec/core/extended_types.h"
46
#include "vec/data_types/number_traits.h"
47
48
namespace doris {
49
namespace vectorized {
50
template <DecimalNativeTypeConcept T>
51
struct Decimal;
52
} // namespace vectorized
53
54
// they rely on the template parameter `IS_STRICT`. in strict mode, it will set error code and otherwise it will not.
55
#ifndef SET_PARAMS_RET_FALSE_IFN
56
#define SET_PARAMS_RET_FALSE_IFN(stmt, ...)                           \
57
6.31k
    do {                                                              \
58
6.31k
        if (!(stmt)) [[unlikely]] {                                   \
59
282
            if constexpr (IsStrict) {                                 \
60
121
                params.status = Status::InvalidArgument(__VA_ARGS__); \
61
121
            }                                                         \
62
282
            return false;                                             \
63
282
        }                                                             \
64
6.31k
    } while (false)
65
#endif
66
67
#ifndef SET_PARAMS_RET_FALSE_FROM_EXCEPTION
68
#define SET_PARAMS_RET_FALSE_FROM_EXCEPTION(stmt) \
69
155
    do {                                          \
70
155
        try {                                     \
71
155
            { stmt; }                             \
72
155
        } catch (const doris::Exception& e) {     \
73
15
            if constexpr (IsStrict) {             \
74
5
                params.status = e.to_status();    \
75
5
            }                                     \
76
15
            return false;                         \
77
15
        }                                         \
78
155
    } while (false)
79
#endif
80
81
// skip leading and trailing ascii whitespaces,
82
// return the pointer to the first non-whitespace char,
83
// and update the len to the new length, which does not include
84
// leading and trailing whitespaces
85
template <typename T>
86
917k
inline const char* skip_ascii_whitespaces(const char* s, T& len) {
87
1.49M
    while (len > 0 && is_whitespace_ascii(*s)) {
88
573k
        ++s;
89
573k
        --len;
90
573k
    }
91
92
1.48M
    while (len > 0 && is_whitespace_ascii(s[len - 1])) {
93
563k
        --len;
94
563k
    }
95
96
917k
    return s;
97
917k
}
_ZN5doris22skip_ascii_whitespacesImEEPKcS2_RT_
Line
Count
Source
86
887k
inline const char* skip_ascii_whitespaces(const char* s, T& len) {
87
1.38M
    while (len > 0 && is_whitespace_ascii(*s)) {
88
497k
        ++s;
89
497k
        --len;
90
497k
    }
91
92
1.37M
    while (len > 0 && is_whitespace_ascii(s[len - 1])) {
93
488k
        --len;
94
488k
    }
95
96
887k
    return s;
97
887k
}
_ZN5doris22skip_ascii_whitespacesIiEEPKcS2_RT_
Line
Count
Source
86
1.37k
inline const char* skip_ascii_whitespaces(const char* s, T& len) {
87
4.90k
    while (len > 0 && is_whitespace_ascii(*s)) {
88
3.52k
        ++s;
89
3.52k
        --len;
90
3.52k
    }
91
92
4.90k
    while (len > 0 && is_whitespace_ascii(s[len - 1])) {
93
3.52k
        --len;
94
3.52k
    }
95
96
1.37k
    return s;
97
1.37k
}
_ZN5doris22skip_ascii_whitespacesIlEEPKcS2_RT_
Line
Count
Source
86
27.8k
inline const char* skip_ascii_whitespaces(const char* s, T& len) {
87
100k
    while (len > 0 && is_whitespace_ascii(*s)) {
88
72.4k
        ++s;
89
72.4k
        --len;
90
72.4k
    }
91
92
99.8k
    while (len > 0 && is_whitespace_ascii(s[len - 1])) {
93
72.0k
        --len;
94
72.0k
    }
95
96
27.8k
    return s;
97
27.8k
}
98
99
template <bool (*Pred)(char)>
100
778
bool range_suite(const char* s, const char* end) {
101
778
    return std::ranges::all_of(s, end, Pred);
102
778
}
_ZN5doris11range_suiteIXadL_Z16is_numeric_asciicEEEEbPKcS2_
Line
Count
Source
100
702
bool range_suite(const char* s, const char* end) {
101
702
    return std::ranges::all_of(s, end, Pred);
102
702
}
_ZN5doris11range_suiteIXadL_Z19is_whitespace_asciicEEEEbPKcS2_
Line
Count
Source
100
76
bool range_suite(const char* s, const char* end) {
101
76
    return std::ranges::all_of(s, end, Pred);
102
76
}
103
104
inline auto is_digit_range = range_suite<is_numeric_ascii>;
105
inline auto is_space_range = range_suite<is_whitespace_ascii>;
106
107
// combine in_bound and range_suite is ok. won't lead to duplicated calculation.
108
785
inline bool in_bound(const char* s, const char* end, size_t offset) {
109
785
    if (s + offset >= end) [[unlikely]] {
110
42
        return false;
111
42
    }
112
743
    return true;
113
785
}
114
115
// LEN = 0 means any length(include zero). LEN = 1 means only one character. so on. LEN = -x means x or more.
116
// if need result, use StringRef{origin_s, s} outside
117
template <int LEN, bool (*Pred)(char)>
118
2.01k
bool skip_qualified_char(const char*& s, const char* end) {
119
2.01k
    if constexpr (LEN == 0) {
120
        // Consume any length of characters that match the predicate.
121
2.24k
        while (s != end && Pred(*s)) {
122
1.33k
            ++s;
123
1.33k
        }
124
1.06k
    } else if constexpr (LEN > 0) {
125
        // Consume exactly LEN characters that match the predicate.
126
1.96k
        for (int i = 0; i < LEN; ++i, ++s) {
127
1.06k
            if (s == end || !Pred(*s)) [[unlikely]] {
128
157
                return false;
129
157
            }
130
1.06k
        }
131
1.06k
    } else { // LEN < 0
132
        // Consume at least -LEN characters that match the predicate.
133
48
        int count = 0;
134
314
        while (s != end && Pred(*s)) {
135
266
            ++s;
136
266
            ++count;
137
266
        }
138
48
        if (count < -LEN) [[unlikely]] {
139
0
            return false;
140
0
        }
141
48
    }
142
952
    return true;
143
2.01k
}
_ZN5doris19skip_qualified_charILi0EXadL_Z19is_whitespace_asciicEEEEbRPKcS2_
Line
Count
Source
118
360
bool skip_qualified_char(const char*& s, const char* end) {
119
360
    if constexpr (LEN == 0) {
120
        // Consume any length of characters that match the predicate.
121
392
        while (s != end && Pred(*s)) {
122
32
            ++s;
123
32
        }
124
    } else if constexpr (LEN > 0) {
125
        // Consume exactly LEN characters that match the predicate.
126
        for (int i = 0; i < LEN; ++i, ++s) {
127
            if (s == end || !Pred(*s)) [[unlikely]] {
128
                return false;
129
            }
130
        }
131
    } else { // LEN < 0
132
        // Consume at least -LEN characters that match the predicate.
133
        int count = 0;
134
        while (s != end && Pred(*s)) {
135
            ++s;
136
            ++count;
137
        }
138
        if (count < -LEN) [[unlikely]] {
139
            return false;
140
        }
141
    }
142
360
    return true;
143
360
}
_ZN5doris19skip_qualified_charILi0EXadL_Z16is_numeric_asciicEEEEbRPKcS2_
Line
Count
Source
118
547
bool skip_qualified_char(const char*& s, const char* end) {
119
547
    if constexpr (LEN == 0) {
120
        // Consume any length of characters that match the predicate.
121
1.85k
        while (s != end && Pred(*s)) {
122
1.30k
            ++s;
123
1.30k
        }
124
    } else if constexpr (LEN > 0) {
125
        // Consume exactly LEN characters that match the predicate.
126
        for (int i = 0; i < LEN; ++i, ++s) {
127
            if (s == end || !Pred(*s)) [[unlikely]] {
128
                return false;
129
            }
130
        }
131
    } else { // LEN < 0
132
        // Consume at least -LEN characters that match the predicate.
133
        int count = 0;
134
        while (s != end && Pred(*s)) {
135
            ++s;
136
            ++count;
137
        }
138
        if (count < -LEN) [[unlikely]] {
139
            return false;
140
        }
141
    }
142
547
    return true;
143
547
}
_ZN5doris19skip_qualified_charILin1EXadL_Z23is_not_whitespace_asciicEEEEbRPKcS2_
Line
Count
Source
118
48
bool skip_qualified_char(const char*& s, const char* end) {
119
    if constexpr (LEN == 0) {
120
        // Consume any length of characters that match the predicate.
121
        while (s != end && Pred(*s)) {
122
            ++s;
123
        }
124
    } else if constexpr (LEN > 0) {
125
        // Consume exactly LEN characters that match the predicate.
126
        for (int i = 0; i < LEN; ++i, ++s) {
127
            if (s == end || !Pred(*s)) [[unlikely]] {
128
                return false;
129
            }
130
        }
131
48
    } else { // LEN < 0
132
        // Consume at least -LEN characters that match the predicate.
133
48
        int count = 0;
134
314
        while (s != end && Pred(*s)) {
135
266
            ++s;
136
266
            ++count;
137
266
        }
138
48
        if (count < -LEN) [[unlikely]] {
139
0
            return false;
140
0
        }
141
48
    }
142
48
    return true;
143
48
}
Unexecuted instantiation: _ZN5doris19skip_qualified_charILi1EXadL_Z14is_slash_asciicEEEEbRPKcS2_
_ZN5doris19skip_qualified_charILi1EXadL_Z12is_non_alnumcEEEEbRPKcS2_
Line
Count
Source
118
282
bool skip_qualified_char(const char*& s, const char* end) {
119
    if constexpr (LEN == 0) {
120
        // Consume any length of characters that match the predicate.
121
        while (s != end && Pred(*s)) {
122
            ++s;
123
        }
124
282
    } else if constexpr (LEN > 0) {
125
        // Consume exactly LEN characters that match the predicate.
126
540
        for (int i = 0; i < LEN; ++i, ++s) {
127
282
            if (s == end || !Pred(*s)) [[unlikely]] {
128
24
                return false;
129
24
            }
130
282
        }
131
    } else { // LEN < 0
132
        // Consume at least -LEN characters that match the predicate.
133
        int count = 0;
134
        while (s != end && Pred(*s)) {
135
            ++s;
136
            ++count;
137
        }
138
        if (count < -LEN) [[unlikely]] {
139
            return false;
140
        }
141
    }
142
258
    return true;
143
282
}
_ZN5doris19skip_qualified_charILi1EXadL_ZNS_12is_delimiterEcEEEEbRPKcS2_
Line
Count
Source
118
222
bool skip_qualified_char(const char*& s, const char* end) {
119
    if constexpr (LEN == 0) {
120
        // Consume any length of characters that match the predicate.
121
        while (s != end && Pred(*s)) {
122
            ++s;
123
        }
124
222
    } else if constexpr (LEN > 0) {
125
        // Consume exactly LEN characters that match the predicate.
126
406
        for (int i = 0; i < LEN; ++i, ++s) {
127
222
            if (s == end || !Pred(*s)) [[unlikely]] {
128
38
                return false;
129
38
            }
130
222
        }
131
    } else { // LEN < 0
132
        // Consume at least -LEN characters that match the predicate.
133
        int count = 0;
134
        while (s != end && Pred(*s)) {
135
            ++s;
136
            ++count;
137
        }
138
        if (count < -LEN) [[unlikely]] {
139
            return false;
140
        }
141
    }
142
184
    return true;
143
222
}
_ZN5doris19skip_qualified_charILi1EXadL_ZNS_6is_barEcEEEEbRPKcS2_
Line
Count
Source
118
401
bool skip_qualified_char(const char*& s, const char* end) {
119
    if constexpr (LEN == 0) {
120
        // Consume any length of characters that match the predicate.
121
        while (s != end && Pred(*s)) {
122
            ++s;
123
        }
124
401
    } else if constexpr (LEN > 0) {
125
        // Consume exactly LEN characters that match the predicate.
126
731
        for (int i = 0; i < LEN; ++i, ++s) {
127
401
            if (s == end || !Pred(*s)) [[unlikely]] {
128
71
                return false;
129
71
            }
130
401
        }
131
    } else { // LEN < 0
132
        // Consume at least -LEN characters that match the predicate.
133
        int count = 0;
134
        while (s != end && Pred(*s)) {
135
            ++s;
136
            ++count;
137
        }
138
        if (count < -LEN) [[unlikely]] {
139
            return false;
140
        }
141
    }
142
330
    return true;
143
401
}
_ZN5doris19skip_qualified_charILi1EXadL_ZNS_8is_colonEcEEEEbRPKcS2_
Line
Count
Source
118
156
bool skip_qualified_char(const char*& s, const char* end) {
119
    if constexpr (LEN == 0) {
120
        // Consume any length of characters that match the predicate.
121
        while (s != end && Pred(*s)) {
122
            ++s;
123
        }
124
156
    } else if constexpr (LEN > 0) {
125
        // Consume exactly LEN characters that match the predicate.
126
288
        for (int i = 0; i < LEN; ++i, ++s) {
127
156
            if (s == end || !Pred(*s)) [[unlikely]] {
128
24
                return false;
129
24
            }
130
156
        }
131
    } else { // LEN < 0
132
        // Consume at least -LEN characters that match the predicate.
133
        int count = 0;
134
        while (s != end && Pred(*s)) {
135
            ++s;
136
            ++count;
137
        }
138
        if (count < -LEN) [[unlikely]] {
139
            return false;
140
        }
141
    }
142
132
    return true;
143
156
}
144
145
inline auto skip_any_whitespace = skip_qualified_char<0, is_whitespace_ascii>;
146
inline auto skip_any_digit = skip_qualified_char<0, is_numeric_ascii>;
147
inline auto skip_tz_name_part = skip_qualified_char<-1, is_not_whitespace_ascii>;
148
inline auto skip_one_slash = skip_qualified_char<1, is_slash_ascii>;
149
inline auto skip_one_non_alnum = skip_qualified_char<1, is_non_alnum>;
150
151
222
inline bool is_delimiter(char c) {
152
222
    return c == ' ' || c == 'T';
153
222
}
154
inline auto consume_one_delimiter = skip_qualified_char<1, is_delimiter>;
155
156
401
inline bool is_bar(char c) {
157
401
    return c == '-';
158
401
}
159
inline auto consume_one_bar = skip_qualified_char<1, is_bar>;
160
161
156
inline bool is_colon(char c) {
162
156
    return c == ':';
163
156
}
164
inline auto consume_one_colon = skip_qualified_char<1, is_colon>;
165
166
// only consume a string of digit, not include sign.
167
// when has MAX_LEN > 0, do greedy match but at most MAX_LEN.
168
// LEN = 0 means any length, otherwise(must > 0) it means exactly LEN digits.
169
template <typename T, int LEN = 0, int MAX_LEN = -1>
170
15
bool consume_digit(const char*& s, const char* end, T& out) {
171
15
    static_assert(LEN >= 0);
172
    if constexpr (MAX_LEN > 0) {
173
        out = 0;
174
        for (int i = 0; i < MAX_LEN; ++i, ++s) {
175
            if (s == end || !is_numeric_ascii(*s)) {
176
                if (i < LEN) [[unlikely]] {
177
                    return false;
178
                }
179
                break; // stop consuming if we have consumed enough digits.
180
            }
181
            out = out * 10 + (*s - '0');
182
        }
183
    } else if constexpr (LEN == 0) {
184
        // Consume any length of digits.
185
        out = 0;
186
        while (s != end && is_numeric_ascii(*s)) {
187
            out = out * 10 + (*s - '0');
188
            ++s;
189
        }
190
15
    } else if constexpr (LEN > 0) {
191
        // Consume exactly LEN digits.
192
15
        out = 0;
193
60
        for (int i = 0; i < LEN; ++i, ++s) {
194
45
            if (s == end || !is_numeric_ascii(*s)) [[unlikely]] {
195
0
                return false;
196
0
            }
197
45
            out = out * 10 + (*s - '0');
198
45
        }
199
15
    }
200
15
    return true;
201
15
}
_ZN5doris13consume_digitIjLi4ELin1EEEbRPKcS2_RT_
Line
Count
Source
170
10
bool consume_digit(const char*& s, const char* end, T& out) {
171
10
    static_assert(LEN >= 0);
172
    if constexpr (MAX_LEN > 0) {
173
        out = 0;
174
        for (int i = 0; i < MAX_LEN; ++i, ++s) {
175
            if (s == end || !is_numeric_ascii(*s)) {
176
                if (i < LEN) [[unlikely]] {
177
                    return false;
178
                }
179
                break; // stop consuming if we have consumed enough digits.
180
            }
181
            out = out * 10 + (*s - '0');
182
        }
183
    } else if constexpr (LEN == 0) {
184
        // Consume any length of digits.
185
        out = 0;
186
        while (s != end && is_numeric_ascii(*s)) {
187
            out = out * 10 + (*s - '0');
188
            ++s;
189
        }
190
10
    } else if constexpr (LEN > 0) {
191
        // Consume exactly LEN digits.
192
10
        out = 0;
193
50
        for (int i = 0; i < LEN; ++i, ++s) {
194
40
            if (s == end || !is_numeric_ascii(*s)) [[unlikely]] {
195
0
                return false;
196
0
            }
197
40
            out = out * 10 + (*s - '0');
198
40
        }
199
10
    }
200
10
    return true;
201
10
}
_ZN5doris13consume_digitIjLi1ELin1EEEbRPKcS2_RT_
Line
Count
Source
170
5
bool consume_digit(const char*& s, const char* end, T& out) {
171
5
    static_assert(LEN >= 0);
172
    if constexpr (MAX_LEN > 0) {
173
        out = 0;
174
        for (int i = 0; i < MAX_LEN; ++i, ++s) {
175
            if (s == end || !is_numeric_ascii(*s)) {
176
                if (i < LEN) [[unlikely]] {
177
                    return false;
178
                }
179
                break; // stop consuming if we have consumed enough digits.
180
            }
181
            out = out * 10 + (*s - '0');
182
        }
183
    } else if constexpr (LEN == 0) {
184
        // Consume any length of digits.
185
        out = 0;
186
        while (s != end && is_numeric_ascii(*s)) {
187
            out = out * 10 + (*s - '0');
188
            ++s;
189
        }
190
5
    } else if constexpr (LEN > 0) {
191
        // Consume exactly LEN digits.
192
5
        out = 0;
193
10
        for (int i = 0; i < LEN; ++i, ++s) {
194
5
            if (s == end || !is_numeric_ascii(*s)) [[unlikely]] {
195
0
                return false;
196
0
            }
197
5
            out = out * 10 + (*s - '0');
198
5
        }
199
5
    }
200
5
    return true;
201
5
}
202
203
// specialized version for 2 digits, which is used very often in date/time parsing.
204
template <>
205
1.02k
inline bool consume_digit<uint32_t, 2, -1>(const char*& s, const char* end, uint32_t& out) {
206
1.02k
    out = 0;
207
1.02k
    if (s == end || s + 1 == end || !is_numeric_ascii(*s) || !is_numeric_ascii(*(s + 1)))
208
46
            [[unlikely]] {
209
46
        return false;
210
46
    }
211
980
    out = (s[0] - '0') * 10 + (s[1] - '0');
212
980
    s += 2; // consume 2 digits
213
980
    return true;
214
1.02k
}
215
216
// specialized version for 1 or 2 digits, which is used very often in date/time parsing.
217
template <>
218
1.14k
inline bool consume_digit<uint32_t, 1, 2>(const char*& s, const char* end, uint32_t& out) {
219
1.14k
    out = 0;
220
1.14k
    if (s == end || !is_numeric_ascii(*s)) [[unlikely]] {
221
32
        return false;
222
1.11k
    } else if (s + 1 != end && is_numeric_ascii(*(s + 1))) {
223
        // consume 2 digits
224
990
        out = (*s - '0') * 10 + (*(s + 1) - '0');
225
990
        s += 2;
226
990
    } else {
227
        // consume 1 digit
228
121
        out = *s - '0';
229
121
        ++s;
230
121
    }
231
1.11k
    return true;
232
1.14k
}
233
234
template <bool (*Pred)(char)>
235
48
uint32_t count_valid_length(const char* s, const char* end) {
236
48
    DCHECK(s <= end) << "s: " << s << ", end: " << end;
237
48
    uint32_t count = 0;
238
149
    while (s != end && Pred(*s)) {
239
101
        ++count;
240
101
        ++s;
241
101
    }
242
48
    return count;
243
48
}
244
245
inline auto count_digits = count_valid_length<is_numeric_ascii>;
246
247
36
inline PURE std::string combine_tz_offset(char sign, uint32_t hour_offset, uint32_t minute_offset) {
248
36
    std::string result(6, '0');
249
36
    result[0] = sign;
250
36
    result[1] = '0' + (hour_offset / 10);
251
36
    result[2] = '0' + (hour_offset % 10);
252
36
    result[3] = ':';
253
36
    result[4] = '0' + (minute_offset / 10);
254
36
    result[5] = '0' + (minute_offset % 10);
255
36
    DCHECK_EQ(result.size(), 6);
256
36
    return result;
257
36
}
258
259
// Utility functions for doing atoi/atof on non-null terminated strings.  On micro benchmarks,
260
// this is significantly faster than libc (atoi/strtol and atof/strtod).
261
//
262
// Strings with leading and trailing whitespaces are accepted.
263
// Branching is heavily optimized for the non-whitespace successful case.
264
// All the StringTo* functions first parse the input string assuming it has no leading whitespace.
265
// If that first attempt was unsuccessful, these functions retry the parsing after removing
266
// whitespace. Therefore, strings with whitespace take a perf hit on branch mis-prediction.
267
//
268
// For overflows, we are following the mysql behavior, to cap values at the max/min value for that
269
// data type.  This is different from hive, which returns NULL for overflow slots for int types
270
// and inf/-inf for float types.
271
//
272
// Things we tried that did not work:
273
//  - lookup table for converting character to digit
274
// Improvements (TODO):
275
//  - Validate input using _simd_compare_ranges
276
//  - Since we know the length, we can parallelize this: i.e. result = 100*s[0] + 10*s[1] + s[2]
277
class StringParser {
278
public:
279
    enum ParseResult { PARSE_SUCCESS = 0, PARSE_FAILURE, PARSE_OVERFLOW, PARSE_UNDERFLOW };
280
281
    template <typename T>
282
403k
    static T numeric_limits(bool negative) {
283
403k
        if constexpr (std::is_same_v<T, __int128>) {
284
47.4k
            return negative ? MIN_INT128 : MAX_INT128;
285
356k
        } else {
286
356k
            return negative ? std::numeric_limits<T>::min() : std::numeric_limits<T>::max();
287
356k
        }
288
403k
    }
_ZN5doris12StringParser14numeric_limitsInEET_b
Line
Count
Source
282
47.4k
    static T numeric_limits(bool negative) {
283
47.4k
        if constexpr (std::is_same_v<T, __int128>) {
284
47.4k
            return negative ? MIN_INT128 : MAX_INT128;
285
        } else {
286
            return negative ? std::numeric_limits<T>::min() : std::numeric_limits<T>::max();
287
        }
288
47.4k
    }
_ZN5doris12StringParser14numeric_limitsIaEET_b
Line
Count
Source
282
137k
    static T numeric_limits(bool negative) {
283
        if constexpr (std::is_same_v<T, __int128>) {
284
            return negative ? MIN_INT128 : MAX_INT128;
285
137k
        } else {
286
137k
            return negative ? std::numeric_limits<T>::min() : std::numeric_limits<T>::max();
287
137k
        }
288
137k
    }
_ZN5doris12StringParser14numeric_limitsIsEET_b
Line
Count
Source
282
69.9k
    static T numeric_limits(bool negative) {
283
        if constexpr (std::is_same_v<T, __int128>) {
284
            return negative ? MIN_INT128 : MAX_INT128;
285
69.9k
        } else {
286
69.9k
            return negative ? std::numeric_limits<T>::min() : std::numeric_limits<T>::max();
287
69.9k
        }
288
69.9k
    }
_ZN5doris12StringParser14numeric_limitsIiEET_b
Line
Count
Source
282
63.5k
    static T numeric_limits(bool negative) {
283
        if constexpr (std::is_same_v<T, __int128>) {
284
            return negative ? MIN_INT128 : MAX_INT128;
285
63.5k
        } else {
286
63.5k
            return negative ? std::numeric_limits<T>::min() : std::numeric_limits<T>::max();
287
63.5k
        }
288
63.5k
    }
_ZN5doris12StringParser14numeric_limitsIlEET_b
Line
Count
Source
282
84.8k
    static T numeric_limits(bool negative) {
283
        if constexpr (std::is_same_v<T, __int128>) {
284
            return negative ? MIN_INT128 : MAX_INT128;
285
84.8k
        } else {
286
84.8k
            return negative ? std::numeric_limits<T>::min() : std::numeric_limits<T>::max();
287
84.8k
        }
288
84.8k
    }
_ZN5doris12StringParser14numeric_limitsIjEET_b
Line
Count
Source
282
145
    static T numeric_limits(bool negative) {
283
        if constexpr (std::is_same_v<T, __int128>) {
284
            return negative ? MIN_INT128 : MAX_INT128;
285
145
        } else {
286
145
            return negative ? std::numeric_limits<T>::min() : std::numeric_limits<T>::max();
287
145
        }
288
145
    }
_ZN5doris12StringParser14numeric_limitsIN4wide7integerILm256EiEEEET_b
Line
Count
Source
282
4
    static T numeric_limits(bool negative) {
283
        if constexpr (std::is_same_v<T, __int128>) {
284
            return negative ? MIN_INT128 : MAX_INT128;
285
4
        } else {
286
4
            return negative ? std::numeric_limits<T>::min() : std::numeric_limits<T>::max();
287
4
        }
288
4
    }
_ZN5doris12StringParser14numeric_limitsIoEET_b
Line
Count
Source
282
4
    static T numeric_limits(bool negative) {
283
        if constexpr (std::is_same_v<T, __int128>) {
284
            return negative ? MIN_INT128 : MAX_INT128;
285
4
        } else {
286
4
            return negative ? std::numeric_limits<T>::min() : std::numeric_limits<T>::max();
287
4
        }
288
4
    }
_ZN5doris12StringParser14numeric_limitsImEET_b
Line
Count
Source
282
21
    static T numeric_limits(bool negative) {
283
        if constexpr (std::is_same_v<T, __int128>) {
284
            return negative ? MIN_INT128 : MAX_INT128;
285
21
        } else {
286
21
            return negative ? std::numeric_limits<T>::min() : std::numeric_limits<T>::max();
287
21
        }
288
21
    }
289
290
    template <typename T>
291
951k
    static T get_scale_multiplier(int scale) {
292
951k
        static_assert(std::is_same_v<T, int32_t> || std::is_same_v<T, int64_t> ||
293
951k
                              std::is_same_v<T, __int128> || std::is_same_v<T, wide::Int256>,
294
951k
                      "You can only instantiate as int32_t, int64_t, __int128.");
295
951k
        if constexpr (std::is_same_v<T, int32_t>) {
296
134k
            return common::exp10_i32(scale);
297
184k
        } else if constexpr (std::is_same_v<T, int64_t>) {
298
184k
            return common::exp10_i64(scale);
299
240k
        } else if constexpr (std::is_same_v<T, __int128>) {
300
240k
            return common::exp10_i128(scale);
301
391k
        } else if constexpr (std::is_same_v<T, wide::Int256>) {
302
391k
            return common::exp10_i256(scale);
303
391k
        }
304
951k
    }
_ZN5doris12StringParser20get_scale_multiplierIiEET_i
Line
Count
Source
291
134k
    static T get_scale_multiplier(int scale) {
292
134k
        static_assert(std::is_same_v<T, int32_t> || std::is_same_v<T, int64_t> ||
293
134k
                              std::is_same_v<T, __int128> || std::is_same_v<T, wide::Int256>,
294
134k
                      "You can only instantiate as int32_t, int64_t, __int128.");
295
134k
        if constexpr (std::is_same_v<T, int32_t>) {
296
134k
            return common::exp10_i32(scale);
297
        } else if constexpr (std::is_same_v<T, int64_t>) {
298
            return common::exp10_i64(scale);
299
        } else if constexpr (std::is_same_v<T, __int128>) {
300
            return common::exp10_i128(scale);
301
        } else if constexpr (std::is_same_v<T, wide::Int256>) {
302
            return common::exp10_i256(scale);
303
        }
304
134k
    }
_ZN5doris12StringParser20get_scale_multiplierIlEET_i
Line
Count
Source
291
184k
    static T get_scale_multiplier(int scale) {
292
184k
        static_assert(std::is_same_v<T, int32_t> || std::is_same_v<T, int64_t> ||
293
184k
                              std::is_same_v<T, __int128> || std::is_same_v<T, wide::Int256>,
294
184k
                      "You can only instantiate as int32_t, int64_t, __int128.");
295
        if constexpr (std::is_same_v<T, int32_t>) {
296
            return common::exp10_i32(scale);
297
184k
        } else if constexpr (std::is_same_v<T, int64_t>) {
298
184k
            return common::exp10_i64(scale);
299
        } else if constexpr (std::is_same_v<T, __int128>) {
300
            return common::exp10_i128(scale);
301
        } else if constexpr (std::is_same_v<T, wide::Int256>) {
302
            return common::exp10_i256(scale);
303
        }
304
184k
    }
_ZN5doris12StringParser20get_scale_multiplierInEET_i
Line
Count
Source
291
240k
    static T get_scale_multiplier(int scale) {
292
240k
        static_assert(std::is_same_v<T, int32_t> || std::is_same_v<T, int64_t> ||
293
240k
                              std::is_same_v<T, __int128> || std::is_same_v<T, wide::Int256>,
294
240k
                      "You can only instantiate as int32_t, int64_t, __int128.");
295
        if constexpr (std::is_same_v<T, int32_t>) {
296
            return common::exp10_i32(scale);
297
        } else if constexpr (std::is_same_v<T, int64_t>) {
298
            return common::exp10_i64(scale);
299
240k
        } else if constexpr (std::is_same_v<T, __int128>) {
300
240k
            return common::exp10_i128(scale);
301
        } else if constexpr (std::is_same_v<T, wide::Int256>) {
302
            return common::exp10_i256(scale);
303
        }
304
240k
    }
_ZN5doris12StringParser20get_scale_multiplierIN4wide7integerILm256EiEEEET_i
Line
Count
Source
291
391k
    static T get_scale_multiplier(int scale) {
292
391k
        static_assert(std::is_same_v<T, int32_t> || std::is_same_v<T, int64_t> ||
293
391k
                              std::is_same_v<T, __int128> || std::is_same_v<T, wide::Int256>,
294
391k
                      "You can only instantiate as int32_t, int64_t, __int128.");
295
        if constexpr (std::is_same_v<T, int32_t>) {
296
            return common::exp10_i32(scale);
297
        } else if constexpr (std::is_same_v<T, int64_t>) {
298
            return common::exp10_i64(scale);
299
        } else if constexpr (std::is_same_v<T, __int128>) {
300
            return common::exp10_i128(scale);
301
391k
        } else if constexpr (std::is_same_v<T, wide::Int256>) {
302
391k
            return common::exp10_i256(scale);
303
391k
        }
304
391k
    }
305
306
    // This is considerably faster than glibc's implementation (25x).
307
    // Assumes s represents a decimal number.
308
    template <typename T, bool enable_strict_mode = false>
309
363k
    static inline T string_to_int(const char* __restrict s, size_t len, ParseResult* result) {
310
363k
        s = skip_ascii_whitespaces(s, len);
311
363k
        return string_to_int_internal<T, enable_strict_mode>(s, len, result);
312
363k
    }
_ZN5doris12StringParser13string_to_intInLb0EEET_PKcmPNS0_11ParseResultE
Line
Count
Source
309
46.5k
    static inline T string_to_int(const char* __restrict s, size_t len, ParseResult* result) {
310
46.5k
        s = skip_ascii_whitespaces(s, len);
311
46.5k
        return string_to_int_internal<T, enable_strict_mode>(s, len, result);
312
46.5k
    }
_ZN5doris12StringParser13string_to_intIaLb0EEET_PKcmPNS0_11ParseResultE
Line
Count
Source
309
97.4k
    static inline T string_to_int(const char* __restrict s, size_t len, ParseResult* result) {
310
97.4k
        s = skip_ascii_whitespaces(s, len);
311
97.4k
        return string_to_int_internal<T, enable_strict_mode>(s, len, result);
312
97.4k
    }
_ZN5doris12StringParser13string_to_intIsLb0EEET_PKcmPNS0_11ParseResultE
Line
Count
Source
309
68.3k
    static inline T string_to_int(const char* __restrict s, size_t len, ParseResult* result) {
310
68.3k
        s = skip_ascii_whitespaces(s, len);
311
68.3k
        return string_to_int_internal<T, enable_strict_mode>(s, len, result);
312
68.3k
    }
_ZN5doris12StringParser13string_to_intIiLb0EEET_PKcmPNS0_11ParseResultE
Line
Count
Source
309
62.8k
    static inline T string_to_int(const char* __restrict s, size_t len, ParseResult* result) {
310
62.8k
        s = skip_ascii_whitespaces(s, len);
311
62.8k
        return string_to_int_internal<T, enable_strict_mode>(s, len, result);
312
62.8k
    }
_ZN5doris12StringParser13string_to_intIlLb0EEET_PKcmPNS0_11ParseResultE
Line
Count
Source
309
83.3k
    static inline T string_to_int(const char* __restrict s, size_t len, ParseResult* result) {
310
83.3k
        s = skip_ascii_whitespaces(s, len);
311
83.3k
        return string_to_int_internal<T, enable_strict_mode>(s, len, result);
312
83.3k
    }
_ZN5doris12StringParser13string_to_intIN4wide7integerILm256EiEELb0EEET_PKcmPNS0_11ParseResultE
Line
Count
Source
309
4
    static inline T string_to_int(const char* __restrict s, size_t len, ParseResult* result) {
310
4
        s = skip_ascii_whitespaces(s, len);
311
4
        return string_to_int_internal<T, enable_strict_mode>(s, len, result);
312
4
    }
_ZN5doris12StringParser13string_to_intIoLb0EEET_PKcmPNS0_11ParseResultE
Line
Count
Source
309
4
    static inline T string_to_int(const char* __restrict s, size_t len, ParseResult* result) {
310
4
        s = skip_ascii_whitespaces(s, len);
311
4
        return string_to_int_internal<T, enable_strict_mode>(s, len, result);
312
4
    }
_ZN5doris12StringParser13string_to_intImLb0EEET_PKcmPNS0_11ParseResultE
Line
Count
Source
309
20
    static inline T string_to_int(const char* __restrict s, size_t len, ParseResult* result) {
310
20
        s = skip_ascii_whitespaces(s, len);
311
20
        return string_to_int_internal<T, enable_strict_mode>(s, len, result);
312
20
    }
Unexecuted instantiation: _ZN5doris12StringParser13string_to_intIjLb0EEET_PKcmPNS0_11ParseResultE
_ZN5doris12StringParser13string_to_intIaLb1EEET_PKcmPNS0_11ParseResultE
Line
Count
Source
309
1.00k
    static inline T string_to_int(const char* __restrict s, size_t len, ParseResult* result) {
310
1.00k
        s = skip_ascii_whitespaces(s, len);
311
1.00k
        return string_to_int_internal<T, enable_strict_mode>(s, len, result);
312
1.00k
    }
_ZN5doris12StringParser13string_to_intIsLb1EEET_PKcmPNS0_11ParseResultE
Line
Count
Source
309
984
    static inline T string_to_int(const char* __restrict s, size_t len, ParseResult* result) {
310
984
        s = skip_ascii_whitespaces(s, len);
311
984
        return string_to_int_internal<T, enable_strict_mode>(s, len, result);
312
984
    }
_ZN5doris12StringParser13string_to_intIiLb1EEET_PKcmPNS0_11ParseResultE
Line
Count
Source
309
968
    static inline T string_to_int(const char* __restrict s, size_t len, ParseResult* result) {
310
968
        s = skip_ascii_whitespaces(s, len);
311
968
        return string_to_int_internal<T, enable_strict_mode>(s, len, result);
312
968
    }
_ZN5doris12StringParser13string_to_intIlLb1EEET_PKcmPNS0_11ParseResultE
Line
Count
Source
309
954
    static inline T string_to_int(const char* __restrict s, size_t len, ParseResult* result) {
310
954
        s = skip_ascii_whitespaces(s, len);
311
954
        return string_to_int_internal<T, enable_strict_mode>(s, len, result);
312
954
    }
_ZN5doris12StringParser13string_to_intInLb1EEET_PKcmPNS0_11ParseResultE
Line
Count
Source
309
936
    static inline T string_to_int(const char* __restrict s, size_t len, ParseResult* result) {
310
936
        s = skip_ascii_whitespaces(s, len);
311
936
        return string_to_int_internal<T, enable_strict_mode>(s, len, result);
312
936
    }
313
314
    // This is considerably faster than glibc's implementation.
315
    // In the case of overflow, the max/min value for the data type will be returned.
316
    // Assumes s represents a decimal number.
317
    template <typename T>
318
1.37k
    static inline T string_to_unsigned_int(const char* __restrict s, int len, ParseResult* result) {
319
1.37k
        s = skip_ascii_whitespaces(s, len);
320
1.37k
        return string_to_unsigned_int_internal<T>(s, len, result);
321
1.37k
    }
_ZN5doris12StringParser22string_to_unsigned_intIhEET_PKciPNS0_11ParseResultE
Line
Count
Source
318
343
    static inline T string_to_unsigned_int(const char* __restrict s, int len, ParseResult* result) {
319
343
        s = skip_ascii_whitespaces(s, len);
320
343
        return string_to_unsigned_int_internal<T>(s, len, result);
321
343
    }
_ZN5doris12StringParser22string_to_unsigned_intItEET_PKciPNS0_11ParseResultE
Line
Count
Source
318
343
    static inline T string_to_unsigned_int(const char* __restrict s, int len, ParseResult* result) {
319
343
        s = skip_ascii_whitespaces(s, len);
320
343
        return string_to_unsigned_int_internal<T>(s, len, result);
321
343
    }
_ZN5doris12StringParser22string_to_unsigned_intIjEET_PKciPNS0_11ParseResultE
Line
Count
Source
318
343
    static inline T string_to_unsigned_int(const char* __restrict s, int len, ParseResult* result) {
319
343
        s = skip_ascii_whitespaces(s, len);
320
343
        return string_to_unsigned_int_internal<T>(s, len, result);
321
343
    }
_ZN5doris12StringParser22string_to_unsigned_intImEET_PKciPNS0_11ParseResultE
Line
Count
Source
318
343
    static inline T string_to_unsigned_int(const char* __restrict s, int len, ParseResult* result) {
319
343
        s = skip_ascii_whitespaces(s, len);
320
343
        return string_to_unsigned_int_internal<T>(s, len, result);
321
343
    }
322
323
    // Convert a string s representing a number in given base into a decimal number.
324
    template <typename T>
325
    static inline T string_to_int(const char* __restrict s, int64_t len, int base,
326
27.8k
                                  ParseResult* result) {
327
27.8k
        s = skip_ascii_whitespaces(s, len);
328
27.8k
        return string_to_int_internal<T>(s, len, base, result);
329
27.8k
    }
_ZN5doris12StringParser13string_to_intIaEET_PKcliPNS0_11ParseResultE
Line
Count
Source
326
26.4k
                                  ParseResult* result) {
327
26.4k
        s = skip_ascii_whitespaces(s, len);
328
26.4k
        return string_to_int_internal<T>(s, len, base, result);
329
26.4k
    }
_ZN5doris12StringParser13string_to_intIsEET_PKcliPNS0_11ParseResultE
Line
Count
Source
326
490
                                  ParseResult* result) {
327
490
        s = skip_ascii_whitespaces(s, len);
328
490
        return string_to_int_internal<T>(s, len, base, result);
329
490
    }
_ZN5doris12StringParser13string_to_intIiEET_PKcliPNS0_11ParseResultE
Line
Count
Source
326
441
                                  ParseResult* result) {
327
441
        s = skip_ascii_whitespaces(s, len);
328
441
        return string_to_int_internal<T>(s, len, base, result);
329
441
    }
_ZN5doris12StringParser13string_to_intIlEET_PKcliPNS0_11ParseResultE
Line
Count
Source
326
441
                                  ParseResult* result) {
327
441
        s = skip_ascii_whitespaces(s, len);
328
441
        return string_to_int_internal<T>(s, len, base, result);
329
441
    }
_ZN5doris12StringParser13string_to_intImEET_PKcliPNS0_11ParseResultE
Line
Count
Source
326
1
                                  ParseResult* result) {
327
1
        s = skip_ascii_whitespaces(s, len);
328
1
        return string_to_int_internal<T>(s, len, base, result);
329
1
    }
330
331
    template <typename T>
332
156k
    static inline T string_to_float(const char* __restrict s, size_t len, ParseResult* result) {
333
156k
        s = skip_ascii_whitespaces(s, len);
334
156k
        return string_to_float_internal<T>(s, len, result);
335
156k
    }
_ZN5doris12StringParser15string_to_floatIdEET_PKcmPNS0_11ParseResultE
Line
Count
Source
332
89.3k
    static inline T string_to_float(const char* __restrict s, size_t len, ParseResult* result) {
333
89.3k
        s = skip_ascii_whitespaces(s, len);
334
89.3k
        return string_to_float_internal<T>(s, len, result);
335
89.3k
    }
_ZN5doris12StringParser15string_to_floatIfEET_PKcmPNS0_11ParseResultE
Line
Count
Source
332
66.7k
    static inline T string_to_float(const char* __restrict s, size_t len, ParseResult* result) {
333
66.7k
        s = skip_ascii_whitespaces(s, len);
334
66.7k
        return string_to_float_internal<T>(s, len, result);
335
66.7k
    }
336
337
    // Parses a string for 'true' or 'false', case insensitive.
338
11.5k
    static inline bool string_to_bool(const char* __restrict s, size_t len, ParseResult* result) {
339
11.5k
        s = skip_ascii_whitespaces(s, len);
340
11.5k
        return string_to_bool_internal(s, len, result);
341
11.5k
    }
342
343
    template <PrimitiveType P>
344
    static typename PrimitiveTypeTraits<P>::CppType::NativeType string_to_decimal(
345
            const char* __restrict s, size_t len, int type_precision, int type_scale,
346
            ParseResult* result);
347
348
    template <typename T>
349
    static Status split_string_to_map(const std::string& base, const T element_separator,
350
                                      const T key_value_separator,
351
                                      std::map<std::string, std::string>* result) {
352
        int key_pos = 0;
353
        int key_end;
354
        int val_pos;
355
        int val_end;
356
357
        while ((key_end = base.find(key_value_separator, key_pos)) != std::string::npos) {
358
            if ((val_pos = base.find_first_not_of(key_value_separator, key_end)) ==
359
                std::string::npos) {
360
                break;
361
            }
362
            if ((val_end = base.find(element_separator, val_pos)) == std::string::npos) {
363
                val_end = base.size();
364
            }
365
            result->insert(std::make_pair(base.substr(key_pos, key_end - key_pos),
366
                                          base.substr(val_pos, val_end - val_pos)));
367
            key_pos = val_end;
368
            if (key_pos != std::string::npos) {
369
                ++key_pos;
370
            }
371
        }
372
373
        return Status::OK();
374
    }
375
376
    // This is considerably faster than glibc's implementation.
377
    // In the case of overflow, the max/min value for the data type will be returned.
378
    // Assumes s represents a decimal number.
379
    // Return PARSE_FAILURE on leading whitespace. Trailing whitespace is allowed.
380
    template <typename T, bool enable_strict_mode = false>
381
    static inline T string_to_int_internal(const char* __restrict s, int len, ParseResult* result);
382
383
    // This is considerably faster than glibc's implementation.
384
    // In the case of overflow, the max/min value for the data type will be returned.
385
    // Assumes s represents a decimal number.
386
    // Return PARSE_FAILURE on leading whitespace. Trailing whitespace is allowed.
387
    template <typename T>
388
    static inline T string_to_unsigned_int_internal(const char* __restrict s, int len,
389
                                                    ParseResult* result);
390
391
    // Convert a string s representing a number in given base into a decimal number.
392
    // Return PARSE_FAILURE on leading whitespace. Trailing whitespace is allowed.
393
    template <typename T>
394
    static inline T string_to_int_internal(const char* __restrict s, int64_t len, int base,
395
                                           ParseResult* result);
396
397
    // Converts an ascii string to an integer of type T assuming it cannot overflow
398
    // and the number is positive.
399
    // Leading whitespace is not allowed. Trailing whitespace will be skipped.
400
    template <typename T, bool enable_strict_mode = false>
401
    static inline T string_to_int_no_overflow(const char* __restrict s, int len,
402
                                              ParseResult* result);
403
404
    // zero length, or at least one legal digit. at most consume MAX_LEN digits and stop. or stop when next
405
    // char is not a digit.
406
    template <typename T>
407
    static inline T string_to_uint_greedy_no_overflow(const char* __restrict s, int max_len,
408
                                                      ParseResult* result);
409
410
    // This is considerably faster than glibc's implementation (>100x why???)
411
    // No special case handling needs to be done for overflows, the floating point spec
412
    // already does it and will cap the values to -inf/inf
413
    // To avoid inaccurate conversions this function falls back to strtod for
414
    // scientific notation.
415
    // Return PARSE_FAILURE on leading whitespace. Trailing whitespace is allowed.
416
    // TODO: Investigate using intrinsics to speed up the slow strtod path.
417
    template <typename T>
418
    static inline T string_to_float_internal(const char* __restrict s, int len,
419
                                             ParseResult* result);
420
421
    // parses a string for 'true' or 'false', case insensitive
422
    // Return PARSE_FAILURE on leading whitespace. Trailing whitespace is allowed.
423
    static inline bool string_to_bool_internal(const char* __restrict s, int len,
424
                                               ParseResult* result);
425
426
    // Returns true if s only contains whitespace.
427
5.47k
    static inline bool is_all_whitespace(const char* __restrict s, int len) {
428
5.92k
        for (int i = 0; i < len; ++i) {
429
5.92k
            if (!LIKELY(is_whitespace_ascii(s[i]))) {
430
5.47k
                return false;
431
5.47k
            }
432
5.92k
        }
433
0
        return true;
434
5.47k
    }
435
436
    // For strings like "3.0", "3.123", and "3.", can parse them as 3.
437
3.40k
    static inline bool is_float_suffix(const char* __restrict s, int len) {
438
3.40k
        return (s[0] == '.' && is_all_digit(s + 1, len - 1));
439
3.40k
    }
440
441
2.62k
    static inline bool is_all_digit(const char* __restrict s, int len) {
442
5.36k
        for (int i = 0; i < len; ++i) {
443
2.81k
            if (!LIKELY(s[i] >= '0' && s[i] <= '9')) {
444
81
                return false;
445
81
            }
446
2.81k
        }
447
2.54k
        return true;
448
2.62k
    }
449
}; // end of class StringParser
450
451
template <typename T, bool enable_strict_mode>
452
363k
T StringParser::string_to_int_internal(const char* __restrict s, int len, ParseResult* result) {
453
363k
    if (UNLIKELY(len <= 0)) {
454
1.15k
        *result = PARSE_FAILURE;
455
1.15k
        return 0;
456
1.15k
    }
457
458
362k
    using UnsignedT = MakeUnsignedT<T>;
459
362k
    UnsignedT val = 0;
460
362k
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
461
362k
    bool negative = false;
462
362k
    int i = 0;
463
362k
    switch (*s) {
464
95.0k
    case '-':
465
95.0k
        negative = true;
466
95.0k
        max_val += 1;
467
95.0k
        [[fallthrough]];
468
97.8k
    case '+':
469
97.8k
        ++i;
470
        // only one '+'/'-' char, so could return failure directly
471
97.8k
        if (UNLIKELY(len == 1)) {
472
3
            *result = PARSE_FAILURE;
473
3
            return 0;
474
3
        }
475
362k
    }
476
477
    // This is the fast path where the string cannot overflow.
478
362k
    if (LIKELY(len - i < vectorized::NumberTraits::max_ascii_len<T>())) {
479
250k
        val = string_to_int_no_overflow<UnsignedT, enable_strict_mode>(s + i, len - i, result);
480
250k
        return static_cast<T>(negative ? -val : val);
481
250k
    }
482
483
111k
    const T max_div_10 = max_val / 10;
484
111k
    const T max_mod_10 = max_val % 10;
485
486
111k
    int first = i;
487
1.51M
    for (; i < len; ++i) {
488
1.44M
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
489
1.43M
            T digit = s[i] - '0';
490
            // This is a tricky check to see if adding this digit will cause an overflow.
491
1.43M
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
492
31.1k
                *result = PARSE_OVERFLOW;
493
31.1k
                return negative ? -max_val : max_val;
494
31.1k
            }
495
1.40M
            val = val * 10 + digit;
496
1.40M
        } else {
497
3.70k
            if constexpr (enable_strict_mode) {
498
1.10k
                if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
499
                    // Reject the string because the remaining chars are not all whitespace
500
1.10k
                    *result = PARSE_FAILURE;
501
1.10k
                    return 0;
502
1.10k
                }
503
2.59k
            } else {
504
2.59k
                if ((UNLIKELY(i == first || (!is_all_whitespace(s + i, len - i) &&
505
2.59k
                                             !is_float_suffix(s + i, len - i))))) {
506
                    // Reject the string because either the first char was not a digit,
507
                    // or the remaining chars are not all whitespace
508
1.59k
                    *result = PARSE_FAILURE;
509
1.59k
                    return 0;
510
1.59k
                }
511
2.59k
            }
512
            // Returning here is slightly faster than breaking the loop.
513
1.00k
            *result = PARSE_SUCCESS;
514
3.70k
            return static_cast<T>(negative ? -val : val);
515
3.70k
        }
516
1.44M
    }
517
76.9k
    *result = PARSE_SUCCESS;
518
76.9k
    return static_cast<T>(negative ? -val : val);
519
111k
}
_ZN5doris12StringParser22string_to_int_internalInLb0EEET_PKciPNS0_11ParseResultE
Line
Count
Source
452
46.5k
T StringParser::string_to_int_internal(const char* __restrict s, int len, ParseResult* result) {
453
46.5k
    if (UNLIKELY(len <= 0)) {
454
25
        *result = PARSE_FAILURE;
455
25
        return 0;
456
25
    }
457
458
46.5k
    using UnsignedT = MakeUnsignedT<T>;
459
46.5k
    UnsignedT val = 0;
460
46.5k
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
461
46.5k
    bool negative = false;
462
46.5k
    int i = 0;
463
46.5k
    switch (*s) {
464
3.52k
    case '-':
465
3.52k
        negative = true;
466
3.52k
        max_val += 1;
467
3.52k
        [[fallthrough]];
468
3.76k
    case '+':
469
3.76k
        ++i;
470
        // only one '+'/'-' char, so could return failure directly
471
3.76k
        if (UNLIKELY(len == 1)) {
472
0
            *result = PARSE_FAILURE;
473
0
            return 0;
474
0
        }
475
46.5k
    }
476
477
    // This is the fast path where the string cannot overflow.
478
46.5k
    if (LIKELY(len - i < vectorized::NumberTraits::max_ascii_len<T>())) {
479
42.2k
        val = string_to_int_no_overflow<UnsignedT, enable_strict_mode>(s + i, len - i, result);
480
42.2k
        return static_cast<T>(negative ? -val : val);
481
42.2k
    }
482
483
4.25k
    const T max_div_10 = max_val / 10;
484
4.25k
    const T max_mod_10 = max_val % 10;
485
486
4.25k
    int first = i;
487
169k
    for (; i < len; ++i) {
488
165k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
489
165k
            T digit = s[i] - '0';
490
            // This is a tricky check to see if adding this digit will cause an overflow.
491
165k
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
492
340
                *result = PARSE_OVERFLOW;
493
340
                return negative ? -max_val : max_val;
494
340
            }
495
165k
            val = val * 10 + digit;
496
165k
        } else {
497
            if constexpr (enable_strict_mode) {
498
                if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
499
                    // Reject the string because the remaining chars are not all whitespace
500
                    *result = PARSE_FAILURE;
501
                    return 0;
502
                }
503
184
            } else {
504
184
                if ((UNLIKELY(i == first || (!is_all_whitespace(s + i, len - i) &&
505
184
                                             !is_float_suffix(s + i, len - i))))) {
506
                    // Reject the string because either the first char was not a digit,
507
                    // or the remaining chars are not all whitespace
508
56
                    *result = PARSE_FAILURE;
509
56
                    return 0;
510
56
                }
511
184
            }
512
            // Returning here is slightly faster than breaking the loop.
513
128
            *result = PARSE_SUCCESS;
514
184
            return static_cast<T>(negative ? -val : val);
515
184
        }
516
165k
    }
517
3.73k
    *result = PARSE_SUCCESS;
518
3.73k
    return static_cast<T>(negative ? -val : val);
519
4.25k
}
_ZN5doris12StringParser22string_to_int_internalIaLb0EEET_PKciPNS0_11ParseResultE
Line
Count
Source
452
97.4k
T StringParser::string_to_int_internal(const char* __restrict s, int len, ParseResult* result) {
453
97.4k
    if (UNLIKELY(len <= 0)) {
454
209
        *result = PARSE_FAILURE;
455
209
        return 0;
456
209
    }
457
458
97.2k
    using UnsignedT = MakeUnsignedT<T>;
459
97.2k
    UnsignedT val = 0;
460
97.2k
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
461
97.2k
    bool negative = false;
462
97.2k
    int i = 0;
463
97.2k
    switch (*s) {
464
20.1k
    case '-':
465
20.1k
        negative = true;
466
20.1k
        max_val += 1;
467
20.1k
        [[fallthrough]];
468
20.4k
    case '+':
469
20.4k
        ++i;
470
        // only one '+'/'-' char, so could return failure directly
471
20.4k
        if (UNLIKELY(len == 1)) {
472
0
            *result = PARSE_FAILURE;
473
0
            return 0;
474
0
        }
475
97.2k
    }
476
477
    // This is the fast path where the string cannot overflow.
478
97.2k
    if (LIKELY(len - i < vectorized::NumberTraits::max_ascii_len<T>())) {
479
70.1k
        val = string_to_int_no_overflow<UnsignedT, enable_strict_mode>(s + i, len - i, result);
480
70.1k
        return static_cast<T>(negative ? -val : val);
481
70.1k
    }
482
483
27.1k
    const T max_div_10 = max_val / 10;
484
27.1k
    const T max_mod_10 = max_val % 10;
485
486
27.1k
    int first = i;
487
91.5k
    for (; i < len; ++i) {
488
81.8k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
489
80.6k
            T digit = s[i] - '0';
490
            // This is a tricky check to see if adding this digit will cause an overflow.
491
80.6k
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
492
16.2k
                *result = PARSE_OVERFLOW;
493
16.2k
                return negative ? -max_val : max_val;
494
16.2k
            }
495
64.3k
            val = val * 10 + digit;
496
64.3k
        } else {
497
            if constexpr (enable_strict_mode) {
498
                if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
499
                    // Reject the string because the remaining chars are not all whitespace
500
                    *result = PARSE_FAILURE;
501
                    return 0;
502
                }
503
1.29k
            } else {
504
1.29k
                if ((UNLIKELY(i == first || (!is_all_whitespace(s + i, len - i) &&
505
1.29k
                                             !is_float_suffix(s + i, len - i))))) {
506
                    // Reject the string because either the first char was not a digit,
507
                    // or the remaining chars are not all whitespace
508
940
                    *result = PARSE_FAILURE;
509
940
                    return 0;
510
940
                }
511
1.29k
            }
512
            // Returning here is slightly faster than breaking the loop.
513
352
            *result = PARSE_SUCCESS;
514
1.29k
            return static_cast<T>(negative ? -val : val);
515
1.29k
        }
516
81.8k
    }
517
9.61k
    *result = PARSE_SUCCESS;
518
9.61k
    return static_cast<T>(negative ? -val : val);
519
27.1k
}
_ZN5doris12StringParser22string_to_int_internalIsLb0EEET_PKciPNS0_11ParseResultE
Line
Count
Source
452
68.3k
T StringParser::string_to_int_internal(const char* __restrict s, int len, ParseResult* result) {
453
68.3k
    if (UNLIKELY(len <= 0)) {
454
7
        *result = PARSE_FAILURE;
455
7
        return 0;
456
7
    }
457
458
68.3k
    using UnsignedT = MakeUnsignedT<T>;
459
68.3k
    UnsignedT val = 0;
460
68.3k
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
461
68.3k
    bool negative = false;
462
68.3k
    int i = 0;
463
68.3k
    switch (*s) {
464
10.6k
    case '-':
465
10.6k
        negative = true;
466
10.6k
        max_val += 1;
467
10.6k
        [[fallthrough]];
468
10.9k
    case '+':
469
10.9k
        ++i;
470
        // only one '+'/'-' char, so could return failure directly
471
10.9k
        if (UNLIKELY(len == 1)) {
472
0
            *result = PARSE_FAILURE;
473
0
            return 0;
474
0
        }
475
68.3k
    }
476
477
    // This is the fast path where the string cannot overflow.
478
68.3k
    if (LIKELY(len - i < vectorized::NumberTraits::max_ascii_len<T>())) {
479
51.9k
        val = string_to_int_no_overflow<UnsignedT, enable_strict_mode>(s + i, len - i, result);
480
51.9k
        return static_cast<T>(negative ? -val : val);
481
51.9k
    }
482
483
16.4k
    const T max_div_10 = max_val / 10;
484
16.4k
    const T max_mod_10 = max_val % 10;
485
486
16.4k
    int first = i;
487
92.0k
    for (; i < len; ++i) {
488
82.8k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
489
82.4k
            T digit = s[i] - '0';
490
            // This is a tricky check to see if adding this digit will cause an overflow.
491
82.4k
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
492
6.80k
                *result = PARSE_OVERFLOW;
493
6.80k
                return negative ? -max_val : max_val;
494
6.80k
            }
495
75.6k
            val = val * 10 + digit;
496
75.6k
        } else {
497
            if constexpr (enable_strict_mode) {
498
                if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
499
                    // Reject the string because the remaining chars are not all whitespace
500
                    *result = PARSE_FAILURE;
501
                    return 0;
502
                }
503
405
            } else {
504
405
                if ((UNLIKELY(i == first || (!is_all_whitespace(s + i, len - i) &&
505
405
                                             !is_float_suffix(s + i, len - i))))) {
506
                    // Reject the string because either the first char was not a digit,
507
                    // or the remaining chars are not all whitespace
508
133
                    *result = PARSE_FAILURE;
509
133
                    return 0;
510
133
                }
511
405
            }
512
            // Returning here is slightly faster than breaking the loop.
513
272
            *result = PARSE_SUCCESS;
514
405
            return static_cast<T>(negative ? -val : val);
515
405
        }
516
82.8k
    }
517
9.21k
    *result = PARSE_SUCCESS;
518
9.21k
    return static_cast<T>(negative ? -val : val);
519
16.4k
}
_ZN5doris12StringParser22string_to_int_internalIiLb0EEET_PKciPNS0_11ParseResultE
Line
Count
Source
452
62.8k
T StringParser::string_to_int_internal(const char* __restrict s, int len, ParseResult* result) {
453
62.8k
    if (UNLIKELY(len <= 0)) {
454
861
        *result = PARSE_FAILURE;
455
861
        return 0;
456
861
    }
457
458
61.9k
    using UnsignedT = MakeUnsignedT<T>;
459
61.9k
    UnsignedT val = 0;
460
61.9k
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
461
61.9k
    bool negative = false;
462
61.9k
    int i = 0;
463
61.9k
    switch (*s) {
464
8.64k
    case '-':
465
8.64k
        negative = true;
466
8.64k
        max_val += 1;
467
8.64k
        [[fallthrough]];
468
8.99k
    case '+':
469
8.99k
        ++i;
470
        // only one '+'/'-' char, so could return failure directly
471
8.99k
        if (UNLIKELY(len == 1)) {
472
3
            *result = PARSE_FAILURE;
473
3
            return 0;
474
3
        }
475
61.9k
    }
476
477
    // This is the fast path where the string cannot overflow.
478
61.9k
    if (LIKELY(len - i < vectorized::NumberTraits::max_ascii_len<T>())) {
479
52.2k
        val = string_to_int_no_overflow<UnsignedT, enable_strict_mode>(s + i, len - i, result);
480
52.2k
        return static_cast<T>(negative ? -val : val);
481
52.2k
    }
482
483
9.73k
    const T max_div_10 = max_val / 10;
484
9.73k
    const T max_mod_10 = max_val % 10;
485
486
9.73k
    int first = i;
487
101k
    for (; i < len; ++i) {
488
95.1k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
489
94.6k
            T digit = s[i] - '0';
490
            // This is a tricky check to see if adding this digit will cause an overflow.
491
94.6k
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
492
3.11k
                *result = PARSE_OVERFLOW;
493
3.11k
                return negative ? -max_val : max_val;
494
3.11k
            }
495
91.4k
            val = val * 10 + digit;
496
91.4k
        } else {
497
            if constexpr (enable_strict_mode) {
498
                if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
499
                    // Reject the string because the remaining chars are not all whitespace
500
                    *result = PARSE_FAILURE;
501
                    return 0;
502
                }
503
519
            } else {
504
519
                if ((UNLIKELY(i == first || (!is_all_whitespace(s + i, len - i) &&
505
519
                                             !is_float_suffix(s + i, len - i))))) {
506
                    // Reject the string because either the first char was not a digit,
507
                    // or the remaining chars are not all whitespace
508
391
                    *result = PARSE_FAILURE;
509
391
                    return 0;
510
391
                }
511
519
            }
512
            // Returning here is slightly faster than breaking the loop.
513
128
            *result = PARSE_SUCCESS;
514
519
            return static_cast<T>(negative ? -val : val);
515
519
        }
516
95.1k
    }
517
6.10k
    *result = PARSE_SUCCESS;
518
6.10k
    return static_cast<T>(negative ? -val : val);
519
9.73k
}
_ZN5doris12StringParser22string_to_int_internalIlLb0EEET_PKciPNS0_11ParseResultE
Line
Count
Source
452
83.3k
T StringParser::string_to_int_internal(const char* __restrict s, int len, ParseResult* result) {
453
83.3k
    if (UNLIKELY(len <= 0)) {
454
11
        *result = PARSE_FAILURE;
455
11
        return 0;
456
11
    }
457
458
83.2k
    using UnsignedT = MakeUnsignedT<T>;
459
83.2k
    UnsignedT val = 0;
460
83.2k
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
461
83.2k
    bool negative = false;
462
83.2k
    int i = 0;
463
83.2k
    switch (*s) {
464
49.9k
    case '-':
465
49.9k
        negative = true;
466
49.9k
        max_val += 1;
467
49.9k
        [[fallthrough]];
468
50.2k
    case '+':
469
50.2k
        ++i;
470
        // only one '+'/'-' char, so could return failure directly
471
50.2k
        if (UNLIKELY(len == 1)) {
472
0
            *result = PARSE_FAILURE;
473
0
            return 0;
474
0
        }
475
83.2k
    }
476
477
    // This is the fast path where the string cannot overflow.
478
83.2k
    if (LIKELY(len - i < vectorized::NumberTraits::max_ascii_len<T>())) {
479
32.4k
        val = string_to_int_no_overflow<UnsignedT, enable_strict_mode>(s + i, len - i, result);
480
32.4k
        return static_cast<T>(negative ? -val : val);
481
32.4k
    }
482
483
50.8k
    const T max_div_10 = max_val / 10;
484
50.8k
    const T max_mod_10 = max_val % 10;
485
486
50.8k
    int first = i;
487
1.01M
    for (; i < len; ++i) {
488
966k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
489
966k
            T digit = s[i] - '0';
490
            // This is a tricky check to see if adding this digit will cause an overflow.
491
966k
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
492
2.81k
                *result = PARSE_OVERFLOW;
493
2.81k
                return negative ? -max_val : max_val;
494
2.81k
            }
495
963k
            val = val * 10 + digit;
496
963k
        } else {
497
            if constexpr (enable_strict_mode) {
498
                if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
499
                    // Reject the string because the remaining chars are not all whitespace
500
                    *result = PARSE_FAILURE;
501
                    return 0;
502
                }
503
199
            } else {
504
199
                if ((UNLIKELY(i == first || (!is_all_whitespace(s + i, len - i) &&
505
199
                                             !is_float_suffix(s + i, len - i))))) {
506
                    // Reject the string because either the first char was not a digit,
507
                    // or the remaining chars are not all whitespace
508
71
                    *result = PARSE_FAILURE;
509
71
                    return 0;
510
71
                }
511
199
            }
512
            // Returning here is slightly faster than breaking the loop.
513
128
            *result = PARSE_SUCCESS;
514
199
            return static_cast<T>(negative ? -val : val);
515
199
        }
516
966k
    }
517
47.8k
    *result = PARSE_SUCCESS;
518
47.8k
    return static_cast<T>(negative ? -val : val);
519
50.8k
}
_ZN5doris12StringParser22string_to_int_internalIjLb1EEET_PKciPNS0_11ParseResultE
Line
Count
Source
452
147
T StringParser::string_to_int_internal(const char* __restrict s, int len, ParseResult* result) {
453
147
    if (UNLIKELY(len <= 0)) {
454
2
        *result = PARSE_FAILURE;
455
2
        return 0;
456
2
    }
457
458
145
    using UnsignedT = MakeUnsignedT<T>;
459
145
    UnsignedT val = 0;
460
145
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
461
145
    bool negative = false;
462
145
    int i = 0;
463
145
    switch (*s) {
464
0
    case '-':
465
0
        negative = true;
466
0
        max_val += 1;
467
0
        [[fallthrough]];
468
0
    case '+':
469
0
        ++i;
470
        // only one '+'/'-' char, so could return failure directly
471
0
        if (UNLIKELY(len == 1)) {
472
0
            *result = PARSE_FAILURE;
473
0
            return 0;
474
0
        }
475
145
    }
476
477
    // This is the fast path where the string cannot overflow.
478
145
    if (LIKELY(len - i < vectorized::NumberTraits::max_ascii_len<T>())) {
479
145
        val = string_to_int_no_overflow<UnsignedT, enable_strict_mode>(s + i, len - i, result);
480
145
        return static_cast<T>(negative ? -val : val);
481
145
    }
482
483
0
    const T max_div_10 = max_val / 10;
484
0
    const T max_mod_10 = max_val % 10;
485
486
0
    int first = i;
487
0
    for (; i < len; ++i) {
488
0
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
489
0
            T digit = s[i] - '0';
490
            // This is a tricky check to see if adding this digit will cause an overflow.
491
0
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
492
0
                *result = PARSE_OVERFLOW;
493
0
                return negative ? -max_val : max_val;
494
0
            }
495
0
            val = val * 10 + digit;
496
0
        } else {
497
0
            if constexpr (enable_strict_mode) {
498
0
                if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
499
                    // Reject the string because the remaining chars are not all whitespace
500
0
                    *result = PARSE_FAILURE;
501
0
                    return 0;
502
0
                }
503
            } else {
504
                if ((UNLIKELY(i == first || (!is_all_whitespace(s + i, len - i) &&
505
                                             !is_float_suffix(s + i, len - i))))) {
506
                    // Reject the string because either the first char was not a digit,
507
                    // or the remaining chars are not all whitespace
508
                    *result = PARSE_FAILURE;
509
                    return 0;
510
                }
511
            }
512
            // Returning here is slightly faster than breaking the loop.
513
0
            *result = PARSE_SUCCESS;
514
0
            return static_cast<T>(negative ? -val : val);
515
0
        }
516
0
    }
517
0
    *result = PARSE_SUCCESS;
518
0
    return static_cast<T>(negative ? -val : val);
519
0
}
_ZN5doris12StringParser22string_to_int_internalIN4wide7integerILm256EiEELb0EEET_PKciPNS0_11ParseResultE
Line
Count
Source
452
4
T StringParser::string_to_int_internal(const char* __restrict s, int len, ParseResult* result) {
453
4
    if (UNLIKELY(len <= 0)) {
454
0
        *result = PARSE_FAILURE;
455
0
        return 0;
456
0
    }
457
458
4
    using UnsignedT = MakeUnsignedT<T>;
459
4
    UnsignedT val = 0;
460
4
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
461
4
    bool negative = false;
462
4
    int i = 0;
463
4
    switch (*s) {
464
0
    case '-':
465
0
        negative = true;
466
0
        max_val += 1;
467
0
        [[fallthrough]];
468
0
    case '+':
469
0
        ++i;
470
        // only one '+'/'-' char, so could return failure directly
471
0
        if (UNLIKELY(len == 1)) {
472
0
            *result = PARSE_FAILURE;
473
0
            return 0;
474
0
        }
475
4
    }
476
477
    // This is the fast path where the string cannot overflow.
478
4
    if (LIKELY(len - i < vectorized::NumberTraits::max_ascii_len<T>())) {
479
4
        val = string_to_int_no_overflow<UnsignedT, enable_strict_mode>(s + i, len - i, result);
480
4
        return static_cast<T>(negative ? -val : val);
481
4
    }
482
483
0
    const T max_div_10 = max_val / 10;
484
0
    const T max_mod_10 = max_val % 10;
485
486
0
    int first = i;
487
0
    for (; i < len; ++i) {
488
0
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
489
0
            T digit = s[i] - '0';
490
            // This is a tricky check to see if adding this digit will cause an overflow.
491
0
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
492
0
                *result = PARSE_OVERFLOW;
493
0
                return negative ? -max_val : max_val;
494
0
            }
495
0
            val = val * 10 + digit;
496
0
        } else {
497
            if constexpr (enable_strict_mode) {
498
                if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
499
                    // Reject the string because the remaining chars are not all whitespace
500
                    *result = PARSE_FAILURE;
501
                    return 0;
502
                }
503
0
            } else {
504
0
                if ((UNLIKELY(i == first || (!is_all_whitespace(s + i, len - i) &&
505
0
                                             !is_float_suffix(s + i, len - i))))) {
506
                    // Reject the string because either the first char was not a digit,
507
                    // or the remaining chars are not all whitespace
508
0
                    *result = PARSE_FAILURE;
509
0
                    return 0;
510
0
                }
511
0
            }
512
            // Returning here is slightly faster than breaking the loop.
513
0
            *result = PARSE_SUCCESS;
514
0
            return static_cast<T>(negative ? -val : val);
515
0
        }
516
0
    }
517
0
    *result = PARSE_SUCCESS;
518
0
    return static_cast<T>(negative ? -val : val);
519
0
}
_ZN5doris12StringParser22string_to_int_internalIoLb0EEET_PKciPNS0_11ParseResultE
Line
Count
Source
452
4
T StringParser::string_to_int_internal(const char* __restrict s, int len, ParseResult* result) {
453
4
    if (UNLIKELY(len <= 0)) {
454
0
        *result = PARSE_FAILURE;
455
0
        return 0;
456
0
    }
457
458
4
    using UnsignedT = MakeUnsignedT<T>;
459
4
    UnsignedT val = 0;
460
4
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
461
4
    bool negative = false;
462
4
    int i = 0;
463
4
    switch (*s) {
464
0
    case '-':
465
0
        negative = true;
466
0
        max_val += 1;
467
0
        [[fallthrough]];
468
0
    case '+':
469
0
        ++i;
470
        // only one '+'/'-' char, so could return failure directly
471
0
        if (UNLIKELY(len == 1)) {
472
0
            *result = PARSE_FAILURE;
473
0
            return 0;
474
0
        }
475
4
    }
476
477
    // This is the fast path where the string cannot overflow.
478
4
    if (LIKELY(len - i < vectorized::NumberTraits::max_ascii_len<T>())) {
479
0
        val = string_to_int_no_overflow<UnsignedT, enable_strict_mode>(s + i, len - i, result);
480
0
        return static_cast<T>(negative ? -val : val);
481
0
    }
482
483
4
    const T max_div_10 = max_val / 10;
484
4
    const T max_mod_10 = max_val % 10;
485
486
4
    int first = i;
487
84
    for (; i < len; ++i) {
488
80
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
489
80
            T digit = s[i] - '0';
490
            // This is a tricky check to see if adding this digit will cause an overflow.
491
80
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
492
0
                *result = PARSE_OVERFLOW;
493
0
                return negative ? -max_val : max_val;
494
0
            }
495
80
            val = val * 10 + digit;
496
80
        } else {
497
            if constexpr (enable_strict_mode) {
498
                if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
499
                    // Reject the string because the remaining chars are not all whitespace
500
                    *result = PARSE_FAILURE;
501
                    return 0;
502
                }
503
0
            } else {
504
0
                if ((UNLIKELY(i == first || (!is_all_whitespace(s + i, len - i) &&
505
0
                                             !is_float_suffix(s + i, len - i))))) {
506
                    // Reject the string because either the first char was not a digit,
507
                    // or the remaining chars are not all whitespace
508
0
                    *result = PARSE_FAILURE;
509
0
                    return 0;
510
0
                }
511
0
            }
512
            // Returning here is slightly faster than breaking the loop.
513
0
            *result = PARSE_SUCCESS;
514
0
            return static_cast<T>(negative ? -val : val);
515
0
        }
516
80
    }
517
4
    *result = PARSE_SUCCESS;
518
4
    return static_cast<T>(negative ? -val : val);
519
4
}
_ZN5doris12StringParser22string_to_int_internalImLb0EEET_PKciPNS0_11ParseResultE
Line
Count
Source
452
20
T StringParser::string_to_int_internal(const char* __restrict s, int len, ParseResult* result) {
453
20
    if (UNLIKELY(len <= 0)) {
454
0
        *result = PARSE_FAILURE;
455
0
        return 0;
456
0
    }
457
458
20
    using UnsignedT = MakeUnsignedT<T>;
459
20
    UnsignedT val = 0;
460
20
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
461
20
    bool negative = false;
462
20
    int i = 0;
463
20
    switch (*s) {
464
0
    case '-':
465
0
        negative = true;
466
0
        max_val += 1;
467
0
        [[fallthrough]];
468
0
    case '+':
469
0
        ++i;
470
        // only one '+'/'-' char, so could return failure directly
471
0
        if (UNLIKELY(len == 1)) {
472
0
            *result = PARSE_FAILURE;
473
0
            return 0;
474
0
        }
475
20
    }
476
477
    // This is the fast path where the string cannot overflow.
478
20
    if (LIKELY(len - i < vectorized::NumberTraits::max_ascii_len<T>())) {
479
20
        val = string_to_int_no_overflow<UnsignedT, enable_strict_mode>(s + i, len - i, result);
480
20
        return static_cast<T>(negative ? -val : val);
481
20
    }
482
483
0
    const T max_div_10 = max_val / 10;
484
0
    const T max_mod_10 = max_val % 10;
485
486
0
    int first = i;
487
0
    for (; i < len; ++i) {
488
0
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
489
0
            T digit = s[i] - '0';
490
            // This is a tricky check to see if adding this digit will cause an overflow.
491
0
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
492
0
                *result = PARSE_OVERFLOW;
493
0
                return negative ? -max_val : max_val;
494
0
            }
495
0
            val = val * 10 + digit;
496
0
        } else {
497
            if constexpr (enable_strict_mode) {
498
                if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
499
                    // Reject the string because the remaining chars are not all whitespace
500
                    *result = PARSE_FAILURE;
501
                    return 0;
502
                }
503
0
            } else {
504
0
                if ((UNLIKELY(i == first || (!is_all_whitespace(s + i, len - i) &&
505
0
                                             !is_float_suffix(s + i, len - i))))) {
506
                    // Reject the string because either the first char was not a digit,
507
                    // or the remaining chars are not all whitespace
508
0
                    *result = PARSE_FAILURE;
509
0
                    return 0;
510
0
                }
511
0
            }
512
            // Returning here is slightly faster than breaking the loop.
513
0
            *result = PARSE_SUCCESS;
514
0
            return static_cast<T>(negative ? -val : val);
515
0
        }
516
0
    }
517
0
    *result = PARSE_SUCCESS;
518
0
    return static_cast<T>(negative ? -val : val);
519
0
}
Unexecuted instantiation: _ZN5doris12StringParser22string_to_int_internalIjLb0EEET_PKciPNS0_11ParseResultE
_ZN5doris12StringParser22string_to_int_internalIaLb1EEET_PKciPNS0_11ParseResultE
Line
Count
Source
452
1.00k
T StringParser::string_to_int_internal(const char* __restrict s, int len, ParseResult* result) {
453
1.00k
    if (UNLIKELY(len <= 0)) {
454
7
        *result = PARSE_FAILURE;
455
7
        return 0;
456
7
    }
457
458
993
    using UnsignedT = MakeUnsignedT<T>;
459
993
    UnsignedT val = 0;
460
993
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
461
993
    bool negative = false;
462
993
    int i = 0;
463
993
    switch (*s) {
464
446
    case '-':
465
446
        negative = true;
466
446
        max_val += 1;
467
446
        [[fallthrough]];
468
697
    case '+':
469
697
        ++i;
470
        // only one '+'/'-' char, so could return failure directly
471
697
        if (UNLIKELY(len == 1)) {
472
0
            *result = PARSE_FAILURE;
473
0
            return 0;
474
0
        }
475
993
    }
476
477
    // This is the fast path where the string cannot overflow.
478
993
    if (LIKELY(len - i < vectorized::NumberTraits::max_ascii_len<T>())) {
479
51
        val = string_to_int_no_overflow<UnsignedT, enable_strict_mode>(s + i, len - i, result);
480
51
        return static_cast<T>(negative ? -val : val);
481
51
    }
482
483
942
    const T max_div_10 = max_val / 10;
484
942
    const T max_mod_10 = max_val % 10;
485
486
942
    int first = i;
487
4.25k
    for (; i < len; ++i) {
488
4.12k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
489
3.71k
            T digit = s[i] - '0';
490
            // This is a tricky check to see if adding this digit will cause an overflow.
491
3.71k
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
492
400
                *result = PARSE_OVERFLOW;
493
400
                return negative ? -max_val : max_val;
494
400
            }
495
3.31k
            val = val * 10 + digit;
496
3.31k
        } else {
497
406
            if constexpr (enable_strict_mode) {
498
406
                if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
499
                    // Reject the string because the remaining chars are not all whitespace
500
406
                    *result = PARSE_FAILURE;
501
406
                    return 0;
502
406
                }
503
            } else {
504
                if ((UNLIKELY(i == first || (!is_all_whitespace(s + i, len - i) &&
505
                                             !is_float_suffix(s + i, len - i))))) {
506
                    // Reject the string because either the first char was not a digit,
507
                    // or the remaining chars are not all whitespace
508
                    *result = PARSE_FAILURE;
509
                    return 0;
510
                }
511
            }
512
            // Returning here is slightly faster than breaking the loop.
513
0
            *result = PARSE_SUCCESS;
514
406
            return static_cast<T>(negative ? -val : val);
515
406
        }
516
4.12k
    }
517
136
    *result = PARSE_SUCCESS;
518
136
    return static_cast<T>(negative ? -val : val);
519
942
}
_ZN5doris12StringParser22string_to_int_internalIsLb1EEET_PKciPNS0_11ParseResultE
Line
Count
Source
452
984
T StringParser::string_to_int_internal(const char* __restrict s, int len, ParseResult* result) {
453
984
    if (UNLIKELY(len <= 0)) {
454
7
        *result = PARSE_FAILURE;
455
7
        return 0;
456
7
    }
457
458
977
    using UnsignedT = MakeUnsignedT<T>;
459
977
    UnsignedT val = 0;
460
977
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
461
977
    bool negative = false;
462
977
    int i = 0;
463
977
    switch (*s) {
464
438
    case '-':
465
438
        negative = true;
466
438
        max_val += 1;
467
438
        [[fallthrough]];
468
685
    case '+':
469
685
        ++i;
470
        // only one '+'/'-' char, so could return failure directly
471
685
        if (UNLIKELY(len == 1)) {
472
0
            *result = PARSE_FAILURE;
473
0
            return 0;
474
0
        }
475
977
    }
476
477
    // This is the fast path where the string cannot overflow.
478
977
    if (LIKELY(len - i < vectorized::NumberTraits::max_ascii_len<T>())) {
479
203
        val = string_to_int_no_overflow<UnsignedT, enable_strict_mode>(s + i, len - i, result);
480
203
        return static_cast<T>(negative ? -val : val);
481
203
    }
482
483
774
    const T max_div_10 = max_val / 10;
484
774
    const T max_mod_10 = max_val % 10;
485
486
774
    int first = i;
487
4.92k
    for (; i < len; ++i) {
488
4.84k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
489
4.53k
            T digit = s[i] - '0';
490
            // This is a tricky check to see if adding this digit will cause an overflow.
491
4.53k
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
492
384
                *result = PARSE_OVERFLOW;
493
384
                return negative ? -max_val : max_val;
494
384
            }
495
4.14k
            val = val * 10 + digit;
496
4.14k
        } else {
497
310
            if constexpr (enable_strict_mode) {
498
310
                if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
499
                    // Reject the string because the remaining chars are not all whitespace
500
310
                    *result = PARSE_FAILURE;
501
310
                    return 0;
502
310
                }
503
            } else {
504
                if ((UNLIKELY(i == first || (!is_all_whitespace(s + i, len - i) &&
505
                                             !is_float_suffix(s + i, len - i))))) {
506
                    // Reject the string because either the first char was not a digit,
507
                    // or the remaining chars are not all whitespace
508
                    *result = PARSE_FAILURE;
509
                    return 0;
510
                }
511
            }
512
            // Returning here is slightly faster than breaking the loop.
513
0
            *result = PARSE_SUCCESS;
514
310
            return static_cast<T>(negative ? -val : val);
515
310
        }
516
4.84k
    }
517
80
    *result = PARSE_SUCCESS;
518
80
    return static_cast<T>(negative ? -val : val);
519
774
}
_ZN5doris12StringParser22string_to_int_internalIiLb1EEET_PKciPNS0_11ParseResultE
Line
Count
Source
452
968
T StringParser::string_to_int_internal(const char* __restrict s, int len, ParseResult* result) {
453
968
    if (UNLIKELY(len <= 0)) {
454
7
        *result = PARSE_FAILURE;
455
7
        return 0;
456
7
    }
457
458
961
    using UnsignedT = MakeUnsignedT<T>;
459
961
    UnsignedT val = 0;
460
961
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
461
961
    bool negative = false;
462
961
    int i = 0;
463
961
    switch (*s) {
464
430
    case '-':
465
430
        negative = true;
466
430
        max_val += 1;
467
430
        [[fallthrough]];
468
673
    case '+':
469
673
        ++i;
470
        // only one '+'/'-' char, so could return failure directly
471
673
        if (UNLIKELY(len == 1)) {
472
0
            *result = PARSE_FAILURE;
473
0
            return 0;
474
0
        }
475
961
    }
476
477
    // This is the fast path where the string cannot overflow.
478
961
    if (LIKELY(len - i < vectorized::NumberTraits::max_ascii_len<T>())) {
479
399
        val = string_to_int_no_overflow<UnsignedT, enable_strict_mode>(s + i, len - i, result);
480
399
        return static_cast<T>(negative ? -val : val);
481
399
    }
482
483
562
    const T max_div_10 = max_val / 10;
484
562
    const T max_mod_10 = max_val % 10;
485
486
562
    int first = i;
487
6.65k
    for (; i < len; ++i) {
488
6.58k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
489
6.45k
            T digit = s[i] - '0';
490
            // This is a tricky check to see if adding this digit will cause an overflow.
491
6.45k
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
492
368
                *result = PARSE_OVERFLOW;
493
368
                return negative ? -max_val : max_val;
494
368
            }
495
6.08k
            val = val * 10 + digit;
496
6.08k
        } else {
497
130
            if constexpr (enable_strict_mode) {
498
130
                if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
499
                    // Reject the string because the remaining chars are not all whitespace
500
130
                    *result = PARSE_FAILURE;
501
130
                    return 0;
502
130
                }
503
            } else {
504
                if ((UNLIKELY(i == first || (!is_all_whitespace(s + i, len - i) &&
505
                                             !is_float_suffix(s + i, len - i))))) {
506
                    // Reject the string because either the first char was not a digit,
507
                    // or the remaining chars are not all whitespace
508
                    *result = PARSE_FAILURE;
509
                    return 0;
510
                }
511
            }
512
            // Returning here is slightly faster than breaking the loop.
513
0
            *result = PARSE_SUCCESS;
514
130
            return static_cast<T>(negative ? -val : val);
515
130
        }
516
6.58k
    }
517
64
    *result = PARSE_SUCCESS;
518
64
    return static_cast<T>(negative ? -val : val);
519
562
}
_ZN5doris12StringParser22string_to_int_internalIlLb1EEET_PKciPNS0_11ParseResultE
Line
Count
Source
452
954
T StringParser::string_to_int_internal(const char* __restrict s, int len, ParseResult* result) {
453
954
    if (UNLIKELY(len <= 0)) {
454
7
        *result = PARSE_FAILURE;
455
7
        return 0;
456
7
    }
457
458
947
    using UnsignedT = MakeUnsignedT<T>;
459
947
    UnsignedT val = 0;
460
947
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
461
947
    bool negative = false;
462
947
    int i = 0;
463
947
    switch (*s) {
464
422
    case '-':
465
422
        negative = true;
466
422
        max_val += 1;
467
422
        [[fallthrough]];
468
661
    case '+':
469
661
        ++i;
470
        // only one '+'/'-' char, so could return failure directly
471
661
        if (UNLIKELY(len == 1)) {
472
0
            *result = PARSE_FAILURE;
473
0
            return 0;
474
0
        }
475
947
    }
476
477
    // This is the fast path where the string cannot overflow.
478
947
    if (LIKELY(len - i < vectorized::NumberTraits::max_ascii_len<T>())) {
479
402
        val = string_to_int_no_overflow<UnsignedT, enable_strict_mode>(s + i, len - i, result);
480
402
        return static_cast<T>(negative ? -val : val);
481
402
    }
482
483
545
    const T max_div_10 = max_val / 10;
484
545
    const T max_mod_10 = max_val % 10;
485
486
545
    int first = i;
487
11.5k
    for (; i < len; ++i) {
488
11.4k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
489
11.3k
            T digit = s[i] - '0';
490
            // This is a tricky check to see if adding this digit will cause an overflow.
491
11.3k
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
492
352
                *result = PARSE_OVERFLOW;
493
352
                return negative ? -max_val : max_val;
494
352
            }
495
10.9k
            val = val * 10 + digit;
496
10.9k
        } else {
497
129
            if constexpr (enable_strict_mode) {
498
129
                if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
499
                    // Reject the string because the remaining chars are not all whitespace
500
129
                    *result = PARSE_FAILURE;
501
129
                    return 0;
502
129
                }
503
            } else {
504
                if ((UNLIKELY(i == first || (!is_all_whitespace(s + i, len - i) &&
505
                                             !is_float_suffix(s + i, len - i))))) {
506
                    // Reject the string because either the first char was not a digit,
507
                    // or the remaining chars are not all whitespace
508
                    *result = PARSE_FAILURE;
509
                    return 0;
510
                }
511
            }
512
            // Returning here is slightly faster than breaking the loop.
513
0
            *result = PARSE_SUCCESS;
514
129
            return static_cast<T>(negative ? -val : val);
515
129
        }
516
11.4k
    }
517
64
    *result = PARSE_SUCCESS;
518
64
    return static_cast<T>(negative ? -val : val);
519
545
}
_ZN5doris12StringParser22string_to_int_internalInLb1EEET_PKciPNS0_11ParseResultE
Line
Count
Source
452
936
T StringParser::string_to_int_internal(const char* __restrict s, int len, ParseResult* result) {
453
936
    if (UNLIKELY(len <= 0)) {
454
7
        *result = PARSE_FAILURE;
455
7
        return 0;
456
7
    }
457
458
929
    using UnsignedT = MakeUnsignedT<T>;
459
929
    UnsignedT val = 0;
460
929
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
461
929
    bool negative = false;
462
929
    int i = 0;
463
929
    switch (*s) {
464
414
    case '-':
465
414
        negative = true;
466
414
        max_val += 1;
467
414
        [[fallthrough]];
468
649
    case '+':
469
649
        ++i;
470
        // only one '+'/'-' char, so could return failure directly
471
649
        if (UNLIKELY(len == 1)) {
472
0
            *result = PARSE_FAILURE;
473
0
            return 0;
474
0
        }
475
929
    }
476
477
    // This is the fast path where the string cannot overflow.
478
929
    if (LIKELY(len - i < vectorized::NumberTraits::max_ascii_len<T>())) {
479
401
        val = string_to_int_no_overflow<UnsignedT, enable_strict_mode>(s + i, len - i, result);
480
401
        return static_cast<T>(negative ? -val : val);
481
401
    }
482
483
528
    const T max_div_10 = max_val / 10;
484
528
    const T max_mod_10 = max_val % 10;
485
486
528
    int first = i;
487
21.5k
    for (; i < len; ++i) {
488
21.5k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
489
21.3k
            T digit = s[i] - '0';
490
            // This is a tricky check to see if adding this digit will cause an overflow.
491
21.3k
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
492
336
                *result = PARSE_OVERFLOW;
493
336
                return negative ? -max_val : max_val;
494
336
            }
495
21.0k
            val = val * 10 + digit;
496
21.0k
        } else {
497
128
            if constexpr (enable_strict_mode) {
498
128
                if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
499
                    // Reject the string because the remaining chars are not all whitespace
500
128
                    *result = PARSE_FAILURE;
501
128
                    return 0;
502
128
                }
503
            } else {
504
                if ((UNLIKELY(i == first || (!is_all_whitespace(s + i, len - i) &&
505
                                             !is_float_suffix(s + i, len - i))))) {
506
                    // Reject the string because either the first char was not a digit,
507
                    // or the remaining chars are not all whitespace
508
                    *result = PARSE_FAILURE;
509
                    return 0;
510
                }
511
            }
512
            // Returning here is slightly faster than breaking the loop.
513
0
            *result = PARSE_SUCCESS;
514
128
            return static_cast<T>(negative ? -val : val);
515
128
        }
516
21.5k
    }
517
64
    *result = PARSE_SUCCESS;
518
64
    return static_cast<T>(negative ? -val : val);
519
528
}
520
521
template <typename T>
522
T StringParser::string_to_unsigned_int_internal(const char* __restrict s, int len,
523
1.37k
                                                ParseResult* result) {
524
1.37k
    if (UNLIKELY(len <= 0)) {
525
0
        *result = PARSE_FAILURE;
526
0
        return 0;
527
0
    }
528
529
1.37k
    T val = 0;
530
1.37k
    T max_val = std::numeric_limits<T>::max();
531
1.37k
    int i = 0;
532
533
1.37k
    using signedT = MakeSignedT<T>;
534
    // This is the fast path where the string cannot overflow.
535
1.37k
    if (LIKELY(len - i < vectorized::NumberTraits::max_ascii_len<signedT>())) {
536
784
        val = string_to_int_no_overflow<T>(s + i, len - i, result);
537
784
        return val;
538
784
    }
539
540
588
    const T max_div_10 = max_val / 10;
541
588
    const T max_mod_10 = max_val % 10;
542
543
588
    int first = i;
544
4.65k
    for (; i < len; ++i) {
545
4.31k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
546
4.26k
            T digit = s[i] - '0';
547
            // This is a tricky check to see if adding this digit will cause an overflow.
548
4.26k
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
549
196
                *result = PARSE_OVERFLOW;
550
196
                return max_val;
551
196
            }
552
4.06k
            val = val * 10 + digit;
553
4.06k
        } else {
554
49
            if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
555
                // Reject the string because either the first char was not a digit,
556
                // or the remaining chars are not all whitespace
557
49
                *result = PARSE_FAILURE;
558
49
                return 0;
559
49
            }
560
            // Returning here is slightly faster than breaking the loop.
561
0
            *result = PARSE_SUCCESS;
562
0
            return val;
563
49
        }
564
4.31k
    }
565
343
    *result = PARSE_SUCCESS;
566
343
    return val;
567
588
}
_ZN5doris12StringParser31string_to_unsigned_int_internalIhEET_PKciPNS0_11ParseResultE
Line
Count
Source
523
343
                                                ParseResult* result) {
524
343
    if (UNLIKELY(len <= 0)) {
525
0
        *result = PARSE_FAILURE;
526
0
        return 0;
527
0
    }
528
529
343
    T val = 0;
530
343
    T max_val = std::numeric_limits<T>::max();
531
343
    int i = 0;
532
533
343
    using signedT = MakeSignedT<T>;
534
    // This is the fast path where the string cannot overflow.
535
343
    if (LIKELY(len - i < vectorized::NumberTraits::max_ascii_len<signedT>())) {
536
98
        val = string_to_int_no_overflow<T>(s + i, len - i, result);
537
98
        return val;
538
98
    }
539
540
245
    const T max_div_10 = max_val / 10;
541
245
    const T max_mod_10 = max_val % 10;
542
543
245
    int first = i;
544
784
    for (; i < len; ++i) {
545
637
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
546
588
            T digit = s[i] - '0';
547
            // This is a tricky check to see if adding this digit will cause an overflow.
548
588
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
549
49
                *result = PARSE_OVERFLOW;
550
49
                return max_val;
551
49
            }
552
539
            val = val * 10 + digit;
553
539
        } else {
554
49
            if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
555
                // Reject the string because either the first char was not a digit,
556
                // or the remaining chars are not all whitespace
557
49
                *result = PARSE_FAILURE;
558
49
                return 0;
559
49
            }
560
            // Returning here is slightly faster than breaking the loop.
561
0
            *result = PARSE_SUCCESS;
562
0
            return val;
563
49
        }
564
637
    }
565
147
    *result = PARSE_SUCCESS;
566
147
    return val;
567
245
}
_ZN5doris12StringParser31string_to_unsigned_int_internalItEET_PKciPNS0_11ParseResultE
Line
Count
Source
523
343
                                                ParseResult* result) {
524
343
    if (UNLIKELY(len <= 0)) {
525
0
        *result = PARSE_FAILURE;
526
0
        return 0;
527
0
    }
528
529
343
    T val = 0;
530
343
    T max_val = std::numeric_limits<T>::max();
531
343
    int i = 0;
532
533
343
    using signedT = MakeSignedT<T>;
534
    // This is the fast path where the string cannot overflow.
535
343
    if (LIKELY(len - i < vectorized::NumberTraits::max_ascii_len<signedT>())) {
536
196
        val = string_to_int_no_overflow<T>(s + i, len - i, result);
537
196
        return val;
538
196
    }
539
540
147
    const T max_div_10 = max_val / 10;
541
147
    const T max_mod_10 = max_val % 10;
542
543
147
    int first = i;
544
833
    for (; i < len; ++i) {
545
735
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
546
735
            T digit = s[i] - '0';
547
            // This is a tricky check to see if adding this digit will cause an overflow.
548
735
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
549
49
                *result = PARSE_OVERFLOW;
550
49
                return max_val;
551
49
            }
552
686
            val = val * 10 + digit;
553
686
        } else {
554
0
            if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
555
                // Reject the string because either the first char was not a digit,
556
                // or the remaining chars are not all whitespace
557
0
                *result = PARSE_FAILURE;
558
0
                return 0;
559
0
            }
560
            // Returning here is slightly faster than breaking the loop.
561
0
            *result = PARSE_SUCCESS;
562
0
            return val;
563
0
        }
564
735
    }
565
98
    *result = PARSE_SUCCESS;
566
98
    return val;
567
147
}
_ZN5doris12StringParser31string_to_unsigned_int_internalIjEET_PKciPNS0_11ParseResultE
Line
Count
Source
523
343
                                                ParseResult* result) {
524
343
    if (UNLIKELY(len <= 0)) {
525
0
        *result = PARSE_FAILURE;
526
0
        return 0;
527
0
    }
528
529
343
    T val = 0;
530
343
    T max_val = std::numeric_limits<T>::max();
531
343
    int i = 0;
532
533
343
    using signedT = MakeSignedT<T>;
534
    // This is the fast path where the string cannot overflow.
535
343
    if (LIKELY(len - i < vectorized::NumberTraits::max_ascii_len<signedT>())) {
536
245
        val = string_to_int_no_overflow<T>(s + i, len - i, result);
537
245
        return val;
538
245
    }
539
540
98
    const T max_div_10 = max_val / 10;
541
98
    const T max_mod_10 = max_val % 10;
542
543
98
    int first = i;
544
1.02k
    for (; i < len; ++i) {
545
980
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
546
980
            T digit = s[i] - '0';
547
            // This is a tricky check to see if adding this digit will cause an overflow.
548
980
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
549
49
                *result = PARSE_OVERFLOW;
550
49
                return max_val;
551
49
            }
552
931
            val = val * 10 + digit;
553
931
        } else {
554
0
            if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
555
                // Reject the string because either the first char was not a digit,
556
                // or the remaining chars are not all whitespace
557
0
                *result = PARSE_FAILURE;
558
0
                return 0;
559
0
            }
560
            // Returning here is slightly faster than breaking the loop.
561
0
            *result = PARSE_SUCCESS;
562
0
            return val;
563
0
        }
564
980
    }
565
49
    *result = PARSE_SUCCESS;
566
49
    return val;
567
98
}
_ZN5doris12StringParser31string_to_unsigned_int_internalImEET_PKciPNS0_11ParseResultE
Line
Count
Source
523
343
                                                ParseResult* result) {
524
343
    if (UNLIKELY(len <= 0)) {
525
0
        *result = PARSE_FAILURE;
526
0
        return 0;
527
0
    }
528
529
343
    T val = 0;
530
343
    T max_val = std::numeric_limits<T>::max();
531
343
    int i = 0;
532
533
343
    using signedT = MakeSignedT<T>;
534
    // This is the fast path where the string cannot overflow.
535
343
    if (LIKELY(len - i < vectorized::NumberTraits::max_ascii_len<signedT>())) {
536
245
        val = string_to_int_no_overflow<T>(s + i, len - i, result);
537
245
        return val;
538
245
    }
539
540
98
    const T max_div_10 = max_val / 10;
541
98
    const T max_mod_10 = max_val % 10;
542
543
98
    int first = i;
544
2.00k
    for (; i < len; ++i) {
545
1.96k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
546
1.96k
            T digit = s[i] - '0';
547
            // This is a tricky check to see if adding this digit will cause an overflow.
548
1.96k
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
549
49
                *result = PARSE_OVERFLOW;
550
49
                return max_val;
551
49
            }
552
1.91k
            val = val * 10 + digit;
553
1.91k
        } else {
554
0
            if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
555
                // Reject the string because either the first char was not a digit,
556
                // or the remaining chars are not all whitespace
557
0
                *result = PARSE_FAILURE;
558
0
                return 0;
559
0
            }
560
            // Returning here is slightly faster than breaking the loop.
561
0
            *result = PARSE_SUCCESS;
562
0
            return val;
563
0
        }
564
1.96k
    }
565
49
    *result = PARSE_SUCCESS;
566
49
    return val;
567
98
}
568
569
template <typename T>
570
T StringParser::string_to_int_internal(const char* __restrict s, int64_t len, int base,
571
27.8k
                                       ParseResult* result) {
572
27.8k
    using UnsignedT = MakeUnsignedT<T>;
573
27.8k
    UnsignedT val = 0;
574
27.8k
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
575
27.8k
    bool negative = false;
576
27.8k
    if (UNLIKELY(len <= 0)) {
577
0
        *result = PARSE_FAILURE;
578
0
        return 0;
579
0
    }
580
27.8k
    int i = 0;
581
27.8k
    switch (*s) {
582
13.4k
    case '-':
583
13.4k
        negative = true;
584
13.4k
        max_val = StringParser::numeric_limits<T>(false) + 1;
585
13.4k
        [[fallthrough]];
586
13.7k
    case '+':
587
13.7k
        i = 1;
588
27.8k
    }
589
590
27.8k
    const T max_div_base = max_val / base;
591
27.8k
    const T max_mod_base = max_val % base;
592
593
27.8k
    int first = i;
594
90.9k
    for (; i < len; ++i) {
595
76.6k
        T digit;
596
76.6k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
597
75.7k
            digit = s[i] - '0';
598
75.7k
        } else if (s[i] >= 'a' && s[i] <= 'z') {
599
639
            digit = (s[i] - 'a' + 10);
600
639
        } else if (s[i] >= 'A' && s[i] <= 'Z') {
601
98
            digit = (s[i] - 'A' + 10);
602
147
        } else {
603
147
            if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
604
                // Reject the string because either the first char was not an alpha/digit,
605
                // or the remaining chars are not all whitespace
606
147
                *result = PARSE_FAILURE;
607
147
                return 0;
608
147
            }
609
            // skip trailing whitespace.
610
0
            break;
611
147
        }
612
613
        // Bail, if we encounter a digit that is not available in base.
614
76.4k
        if (digit >= base) {
615
392
            break;
616
392
        }
617
618
        // This is a tricky check to see if adding this digit will cause an overflow.
619
76.0k
        if (UNLIKELY(val > (max_div_base - (digit > max_mod_base)))) {
620
12.9k
            *result = PARSE_OVERFLOW;
621
12.9k
            return static_cast<T>(negative ? -max_val : max_val);
622
12.9k
        }
623
63.1k
        val = val * base + digit;
624
63.1k
    }
625
14.7k
    *result = PARSE_SUCCESS;
626
14.7k
    return static_cast<T>(negative ? -val : val);
627
27.8k
}
_ZN5doris12StringParser22string_to_int_internalIaEET_PKcliPNS0_11ParseResultE
Line
Count
Source
571
26.4k
                                       ParseResult* result) {
572
26.4k
    using UnsignedT = MakeUnsignedT<T>;
573
26.4k
    UnsignedT val = 0;
574
26.4k
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
575
26.4k
    bool negative = false;
576
26.4k
    if (UNLIKELY(len <= 0)) {
577
0
        *result = PARSE_FAILURE;
578
0
        return 0;
579
0
    }
580
26.4k
    int i = 0;
581
26.4k
    switch (*s) {
582
12.8k
    case '-':
583
12.8k
        negative = true;
584
12.8k
        max_val = StringParser::numeric_limits<T>(false) + 1;
585
12.8k
        [[fallthrough]];
586
12.9k
    case '+':
587
12.9k
        i = 1;
588
26.4k
    }
589
590
26.4k
    const T max_div_base = max_val / base;
591
26.4k
    const T max_mod_base = max_val % base;
592
593
26.4k
    int first = i;
594
80.7k
    for (; i < len; ++i) {
595
67.4k
        T digit;
596
67.4k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
597
66.6k
            digit = s[i] - '0';
598
66.6k
        } else if (s[i] >= 'a' && s[i] <= 'z') {
599
539
            digit = (s[i] - 'a' + 10);
600
539
        } else if (s[i] >= 'A' && s[i] <= 'Z') {
601
98
            digit = (s[i] - 'A' + 10);
602
147
        } else {
603
147
            if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
604
                // Reject the string because either the first char was not an alpha/digit,
605
                // or the remaining chars are not all whitespace
606
147
                *result = PARSE_FAILURE;
607
147
                return 0;
608
147
            }
609
            // skip trailing whitespace.
610
0
            break;
611
147
        }
612
613
        // Bail, if we encounter a digit that is not available in base.
614
67.3k
        if (digit >= base) {
615
392
            break;
616
392
        }
617
618
        // This is a tricky check to see if adding this digit will cause an overflow.
619
66.9k
        if (UNLIKELY(val > (max_div_base - (digit > max_mod_base)))) {
620
12.6k
            *result = PARSE_OVERFLOW;
621
12.6k
            return static_cast<T>(negative ? -max_val : max_val);
622
12.6k
        }
623
54.2k
        val = val * base + digit;
624
54.2k
    }
625
13.6k
    *result = PARSE_SUCCESS;
626
13.6k
    return static_cast<T>(negative ? -val : val);
627
26.4k
}
_ZN5doris12StringParser22string_to_int_internalIsEET_PKcliPNS0_11ParseResultE
Line
Count
Source
571
490
                                       ParseResult* result) {
572
490
    using UnsignedT = MakeUnsignedT<T>;
573
490
    UnsignedT val = 0;
574
490
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
575
490
    bool negative = false;
576
490
    if (UNLIKELY(len <= 0)) {
577
0
        *result = PARSE_FAILURE;
578
0
        return 0;
579
0
    }
580
490
    int i = 0;
581
490
    switch (*s) {
582
196
    case '-':
583
196
        negative = true;
584
196
        max_val = StringParser::numeric_limits<T>(false) + 1;
585
196
        [[fallthrough]];
586
245
    case '+':
587
245
        i = 1;
588
490
    }
589
590
490
    const T max_div_base = max_val / base;
591
490
    const T max_mod_base = max_val % base;
592
593
490
    int first = i;
594
2.10k
    for (; i < len; ++i) {
595
1.71k
        T digit;
596
1.71k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
597
1.61k
            digit = s[i] - '0';
598
1.61k
        } else if (s[i] >= 'a' && s[i] <= 'z') {
599
98
            digit = (s[i] - 'a' + 10);
600
98
        } else if (s[i] >= 'A' && s[i] <= 'Z') {
601
0
            digit = (s[i] - 'A' + 10);
602
0
        } else {
603
0
            if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
604
                // Reject the string because either the first char was not an alpha/digit,
605
                // or the remaining chars are not all whitespace
606
0
                *result = PARSE_FAILURE;
607
0
                return 0;
608
0
            }
609
            // skip trailing whitespace.
610
0
            break;
611
0
        }
612
613
        // Bail, if we encounter a digit that is not available in base.
614
1.71k
        if (digit >= base) {
615
0
            break;
616
0
        }
617
618
        // This is a tricky check to see if adding this digit will cause an overflow.
619
1.71k
        if (UNLIKELY(val > (max_div_base - (digit > max_mod_base)))) {
620
98
            *result = PARSE_OVERFLOW;
621
98
            return static_cast<T>(negative ? -max_val : max_val);
622
98
        }
623
1.61k
        val = val * base + digit;
624
1.61k
    }
625
392
    *result = PARSE_SUCCESS;
626
392
    return static_cast<T>(negative ? -val : val);
627
490
}
_ZN5doris12StringParser22string_to_int_internalIiEET_PKcliPNS0_11ParseResultE
Line
Count
Source
571
441
                                       ParseResult* result) {
572
441
    using UnsignedT = MakeUnsignedT<T>;
573
441
    UnsignedT val = 0;
574
441
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
575
441
    bool negative = false;
576
441
    if (UNLIKELY(len <= 0)) {
577
0
        *result = PARSE_FAILURE;
578
0
        return 0;
579
0
    }
580
441
    int i = 0;
581
441
    switch (*s) {
582
147
    case '-':
583
147
        negative = true;
584
147
        max_val = StringParser::numeric_limits<T>(false) + 1;
585
147
        [[fallthrough]];
586
245
    case '+':
587
245
        i = 1;
588
441
    }
589
590
441
    const T max_div_base = max_val / base;
591
441
    const T max_mod_base = max_val % base;
592
593
441
    int first = i;
594
3.03k
    for (; i < len; ++i) {
595
2.69k
        T digit;
596
2.69k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
597
2.69k
            digit = s[i] - '0';
598
2.69k
        } else if (s[i] >= 'a' && s[i] <= 'z') {
599
0
            digit = (s[i] - 'a' + 10);
600
0
        } else if (s[i] >= 'A' && s[i] <= 'Z') {
601
0
            digit = (s[i] - 'A' + 10);
602
0
        } else {
603
0
            if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
604
                // Reject the string because either the first char was not an alpha/digit,
605
                // or the remaining chars are not all whitespace
606
0
                *result = PARSE_FAILURE;
607
0
                return 0;
608
0
            }
609
            // skip trailing whitespace.
610
0
            break;
611
0
        }
612
613
        // Bail, if we encounter a digit that is not available in base.
614
2.69k
        if (digit >= base) {
615
0
            break;
616
0
        }
617
618
        // This is a tricky check to see if adding this digit will cause an overflow.
619
2.69k
        if (UNLIKELY(val > (max_div_base - (digit > max_mod_base)))) {
620
98
            *result = PARSE_OVERFLOW;
621
98
            return static_cast<T>(negative ? -max_val : max_val);
622
98
        }
623
2.59k
        val = val * base + digit;
624
2.59k
    }
625
343
    *result = PARSE_SUCCESS;
626
343
    return static_cast<T>(negative ? -val : val);
627
441
}
_ZN5doris12StringParser22string_to_int_internalIlEET_PKcliPNS0_11ParseResultE
Line
Count
Source
571
441
                                       ParseResult* result) {
572
441
    using UnsignedT = MakeUnsignedT<T>;
573
441
    UnsignedT val = 0;
574
441
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
575
441
    bool negative = false;
576
441
    if (UNLIKELY(len <= 0)) {
577
0
        *result = PARSE_FAILURE;
578
0
        return 0;
579
0
    }
580
441
    int i = 0;
581
441
    switch (*s) {
582
196
    case '-':
583
196
        negative = true;
584
196
        max_val = StringParser::numeric_limits<T>(false) + 1;
585
196
        [[fallthrough]];
586
245
    case '+':
587
245
        i = 1;
588
441
    }
589
590
441
    const T max_div_base = max_val / base;
591
441
    const T max_mod_base = max_val % base;
592
593
441
    int first = i;
594
5.09k
    for (; i < len; ++i) {
595
4.75k
        T digit;
596
4.75k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
597
4.75k
            digit = s[i] - '0';
598
4.75k
        } else if (s[i] >= 'a' && s[i] <= 'z') {
599
0
            digit = (s[i] - 'a' + 10);
600
0
        } else if (s[i] >= 'A' && s[i] <= 'Z') {
601
0
            digit = (s[i] - 'A' + 10);
602
0
        } else {
603
0
            if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
604
                // Reject the string because either the first char was not an alpha/digit,
605
                // or the remaining chars are not all whitespace
606
0
                *result = PARSE_FAILURE;
607
0
                return 0;
608
0
            }
609
            // skip trailing whitespace.
610
0
            break;
611
0
        }
612
613
        // Bail, if we encounter a digit that is not available in base.
614
4.75k
        if (digit >= base) {
615
0
            break;
616
0
        }
617
618
        // This is a tricky check to see if adding this digit will cause an overflow.
619
4.75k
        if (UNLIKELY(val > (max_div_base - (digit > max_mod_base)))) {
620
98
            *result = PARSE_OVERFLOW;
621
98
            return static_cast<T>(negative ? -max_val : max_val);
622
98
        }
623
4.65k
        val = val * base + digit;
624
4.65k
    }
625
343
    *result = PARSE_SUCCESS;
626
343
    return static_cast<T>(negative ? -val : val);
627
441
}
_ZN5doris12StringParser22string_to_int_internalImEET_PKcliPNS0_11ParseResultE
Line
Count
Source
571
1
                                       ParseResult* result) {
572
1
    using UnsignedT = MakeUnsignedT<T>;
573
1
    UnsignedT val = 0;
574
1
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
575
1
    bool negative = false;
576
1
    if (UNLIKELY(len <= 0)) {
577
0
        *result = PARSE_FAILURE;
578
0
        return 0;
579
0
    }
580
1
    int i = 0;
581
1
    switch (*s) {
582
0
    case '-':
583
0
        negative = true;
584
0
        max_val = StringParser::numeric_limits<T>(false) + 1;
585
0
        [[fallthrough]];
586
0
    case '+':
587
0
        i = 1;
588
1
    }
589
590
1
    const T max_div_base = max_val / base;
591
1
    const T max_mod_base = max_val % base;
592
593
1
    int first = i;
594
3
    for (; i < len; ++i) {
595
2
        T digit;
596
2
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
597
0
            digit = s[i] - '0';
598
2
        } else if (s[i] >= 'a' && s[i] <= 'z') {
599
2
            digit = (s[i] - 'a' + 10);
600
2
        } else if (s[i] >= 'A' && s[i] <= 'Z') {
601
0
            digit = (s[i] - 'A' + 10);
602
0
        } else {
603
0
            if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
604
                // Reject the string because either the first char was not an alpha/digit,
605
                // or the remaining chars are not all whitespace
606
0
                *result = PARSE_FAILURE;
607
0
                return 0;
608
0
            }
609
            // skip trailing whitespace.
610
0
            break;
611
0
        }
612
613
        // Bail, if we encounter a digit that is not available in base.
614
2
        if (digit >= base) {
615
0
            break;
616
0
        }
617
618
        // This is a tricky check to see if adding this digit will cause an overflow.
619
2
        if (UNLIKELY(val > (max_div_base - (digit > max_mod_base)))) {
620
0
            *result = PARSE_OVERFLOW;
621
0
            return static_cast<T>(negative ? -max_val : max_val);
622
0
        }
623
2
        val = val * base + digit;
624
2
    }
625
1
    *result = PARSE_SUCCESS;
626
1
    return static_cast<T>(negative ? -val : val);
627
1
}
628
629
template <typename T, bool enable_strict_mode>
630
251k
T StringParser::string_to_int_no_overflow(const char* __restrict s, int len, ParseResult* result) {
631
251k
    T val = 0;
632
251k
    if (UNLIKELY(len == 0)) {
633
0
        *result = PARSE_SUCCESS;
634
0
        return val;
635
0
    }
636
    // Factor out the first char for error handling speeds up the loop.
637
251k
    if (LIKELY(s[0] >= '0' && s[0] <= '9')) {
638
249k
        val = s[0] - '0';
639
249k
    } else {
640
2.19k
        *result = PARSE_FAILURE;
641
2.19k
        return 0;
642
2.19k
    }
643
397k
    for (int i = 1; i < len; ++i) {
644
151k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
645
148k
            T digit = s[i] - '0';
646
148k
            val = val * 10 + digit;
647
148k
        } else {
648
2.71k
            if constexpr (enable_strict_mode) {
649
860
                if (UNLIKELY(!is_all_whitespace(s + i, len - i))) {
650
860
                    *result = PARSE_FAILURE;
651
860
                    return 0;
652
860
                }
653
1.85k
            } else {
654
1.85k
                if ((UNLIKELY(!is_all_whitespace(s + i, len - i) &&
655
1.85k
                              !is_float_suffix(s + i, len - i)))) {
656
321
                    *result = PARSE_FAILURE;
657
321
                    return 0;
658
321
                }
659
1.85k
            }
660
1.53k
            *result = PARSE_SUCCESS;
661
2.71k
            return val;
662
2.71k
        }
663
151k
    }
664
246k
    *result = PARSE_SUCCESS;
665
246k
    return val;
666
249k
}
_ZN5doris12StringParser25string_to_int_no_overflowIoLb0EEET_PKciPNS0_11ParseResultE
Line
Count
Source
630
42.2k
T StringParser::string_to_int_no_overflow(const char* __restrict s, int len, ParseResult* result) {
631
42.2k
    T val = 0;
632
42.2k
    if (UNLIKELY(len == 0)) {
633
0
        *result = PARSE_SUCCESS;
634
0
        return val;
635
0
    }
636
    // Factor out the first char for error handling speeds up the loop.
637
42.2k
    if (LIKELY(s[0] >= '0' && s[0] <= '9')) {
638
42.0k
        val = s[0] - '0';
639
42.0k
    } else {
640
185
        *result = PARSE_FAILURE;
641
185
        return 0;
642
185
    }
643
59.1k
    for (int i = 1; i < len; ++i) {
644
17.3k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
645
17.0k
            T digit = s[i] - '0';
646
17.0k
            val = val * 10 + digit;
647
17.0k
        } else {
648
            if constexpr (enable_strict_mode) {
649
                if (UNLIKELY(!is_all_whitespace(s + i, len - i))) {
650
                    *result = PARSE_FAILURE;
651
                    return 0;
652
                }
653
289
            } else {
654
289
                if ((UNLIKELY(!is_all_whitespace(s + i, len - i) &&
655
289
                              !is_float_suffix(s + i, len - i)))) {
656
65
                    *result = PARSE_FAILURE;
657
65
                    return 0;
658
65
                }
659
289
            }
660
224
            *result = PARSE_SUCCESS;
661
289
            return val;
662
289
        }
663
17.3k
    }
664
41.7k
    *result = PARSE_SUCCESS;
665
41.7k
    return val;
666
42.0k
}
_ZN5doris12StringParser25string_to_int_no_overflowIhLb0EEET_PKciPNS0_11ParseResultE
Line
Count
Source
630
70.2k
T StringParser::string_to_int_no_overflow(const char* __restrict s, int len, ParseResult* result) {
631
70.2k
    T val = 0;
632
70.2k
    if (UNLIKELY(len == 0)) {
633
0
        *result = PARSE_SUCCESS;
634
0
        return val;
635
0
    }
636
    // Factor out the first char for error handling speeds up the loop.
637
70.2k
    if (LIKELY(s[0] >= '0' && s[0] <= '9')) {
638
70.0k
        val = s[0] - '0';
639
70.0k
    } else {
640
125
        *result = PARSE_FAILURE;
641
125
        return 0;
642
125
    }
643
103k
    for (int i = 1; i < len; ++i) {
644
33.6k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
645
33.6k
            T digit = s[i] - '0';
646
33.6k
            val = val * 10 + digit;
647
33.6k
        } else {
648
            if constexpr (enable_strict_mode) {
649
                if (UNLIKELY(!is_all_whitespace(s + i, len - i))) {
650
                    *result = PARSE_FAILURE;
651
                    return 0;
652
                }
653
1
            } else {
654
1
                if ((UNLIKELY(!is_all_whitespace(s + i, len - i) &&
655
1
                              !is_float_suffix(s + i, len - i)))) {
656
1
                    *result = PARSE_FAILURE;
657
1
                    return 0;
658
1
                }
659
1
            }
660
0
            *result = PARSE_SUCCESS;
661
1
            return val;
662
1
        }
663
33.6k
    }
664
70.0k
    *result = PARSE_SUCCESS;
665
70.0k
    return val;
666
70.0k
}
_ZN5doris12StringParser25string_to_int_no_overflowItLb0EEET_PKciPNS0_11ParseResultE
Line
Count
Source
630
52.1k
T StringParser::string_to_int_no_overflow(const char* __restrict s, int len, ParseResult* result) {
631
52.1k
    T val = 0;
632
52.1k
    if (UNLIKELY(len == 0)) {
633
0
        *result = PARSE_SUCCESS;
634
0
        return val;
635
0
    }
636
    // Factor out the first char for error handling speeds up the loop.
637
52.1k
    if (LIKELY(s[0] >= '0' && s[0] <= '9')) {
638
51.6k
        val = s[0] - '0';
639
51.6k
    } else {
640
494
        *result = PARSE_FAILURE;
641
494
        return 0;
642
494
    }
643
75.2k
    for (int i = 1; i < len; ++i) {
644
24.5k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
645
23.6k
            T digit = s[i] - '0';
646
23.6k
            val = val * 10 + digit;
647
23.6k
        } else {
648
            if constexpr (enable_strict_mode) {
649
                if (UNLIKELY(!is_all_whitespace(s + i, len - i))) {
650
                    *result = PARSE_FAILURE;
651
                    return 0;
652
                }
653
924
            } else {
654
924
                if ((UNLIKELY(!is_all_whitespace(s + i, len - i) &&
655
924
                              !is_float_suffix(s + i, len - i)))) {
656
63
                    *result = PARSE_FAILURE;
657
63
                    return 0;
658
63
                }
659
924
            }
660
861
            *result = PARSE_SUCCESS;
661
924
            return val;
662
924
        }
663
24.5k
    }
664
50.6k
    *result = PARSE_SUCCESS;
665
50.6k
    return val;
666
51.6k
}
_ZN5doris12StringParser25string_to_int_no_overflowIjLb0EEET_PKciPNS0_11ParseResultE
Line
Count
Source
630
52.4k
T StringParser::string_to_int_no_overflow(const char* __restrict s, int len, ParseResult* result) {
631
52.4k
    T val = 0;
632
52.4k
    if (UNLIKELY(len == 0)) {
633
0
        *result = PARSE_SUCCESS;
634
0
        return val;
635
0
    }
636
    // Factor out the first char for error handling speeds up the loop.
637
52.4k
    if (LIKELY(s[0] >= '0' && s[0] <= '9')) {
638
51.5k
        val = s[0] - '0';
639
51.5k
    } else {
640
896
        *result = PARSE_FAILURE;
641
896
        return 0;
642
896
    }
643
88.0k
    for (int i = 1; i < len; ++i) {
644
36.7k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
645
36.4k
            T digit = s[i] - '0';
646
36.4k
            val = val * 10 + digit;
647
36.4k
        } else {
648
            if constexpr (enable_strict_mode) {
649
                if (UNLIKELY(!is_all_whitespace(s + i, len - i))) {
650
                    *result = PARSE_FAILURE;
651
                    return 0;
652
                }
653
332
            } else {
654
332
                if ((UNLIKELY(!is_all_whitespace(s + i, len - i) &&
655
332
                              !is_float_suffix(s + i, len - i)))) {
656
108
                    *result = PARSE_FAILURE;
657
108
                    return 0;
658
108
                }
659
332
            }
660
224
            *result = PARSE_SUCCESS;
661
332
            return val;
662
332
        }
663
36.7k
    }
664
51.2k
    *result = PARSE_SUCCESS;
665
51.2k
    return val;
666
51.5k
}
_ZN5doris12StringParser25string_to_int_no_overflowImLb0EEET_PKciPNS0_11ParseResultE
Line
Count
Source
630
32.6k
T StringParser::string_to_int_no_overflow(const char* __restrict s, int len, ParseResult* result) {
631
32.6k
    T val = 0;
632
32.6k
    if (UNLIKELY(len == 0)) {
633
0
        *result = PARSE_SUCCESS;
634
0
        return val;
635
0
    }
636
    // Factor out the first char for error handling speeds up the loop.
637
32.6k
    if (LIKELY(s[0] >= '0' && s[0] <= '9')) {
638
32.3k
        val = s[0] - '0';
639
32.3k
    } else {
640
376
        *result = PARSE_FAILURE;
641
376
        return 0;
642
376
    }
643
67.8k
    for (int i = 1; i < len; ++i) {
644
35.8k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
645
35.4k
            T digit = s[i] - '0';
646
35.4k
            val = val * 10 + digit;
647
35.4k
        } else {
648
            if constexpr (enable_strict_mode) {
649
                if (UNLIKELY(!is_all_whitespace(s + i, len - i))) {
650
                    *result = PARSE_FAILURE;
651
                    return 0;
652
                }
653
309
            } else {
654
309
                if ((UNLIKELY(!is_all_whitespace(s + i, len - i) &&
655
309
                              !is_float_suffix(s + i, len - i)))) {
656
84
                    *result = PARSE_FAILURE;
657
84
                    return 0;
658
84
                }
659
309
            }
660
225
            *result = PARSE_SUCCESS;
661
309
            return val;
662
309
        }
663
35.8k
    }
664
31.9k
    *result = PARSE_SUCCESS;
665
31.9k
    return val;
666
32.3k
}
_ZN5doris12StringParser25string_to_int_no_overflowIjLb1EEET_PKciPNS0_11ParseResultE
Line
Count
Source
630
544
T StringParser::string_to_int_no_overflow(const char* __restrict s, int len, ParseResult* result) {
631
544
    T val = 0;
632
544
    if (UNLIKELY(len == 0)) {
633
0
        *result = PARSE_SUCCESS;
634
0
        return val;
635
0
    }
636
    // Factor out the first char for error handling speeds up the loop.
637
544
    if (LIKELY(s[0] >= '0' && s[0] <= '9')) {
638
513
        val = s[0] - '0';
639
513
    } else {
640
31
        *result = PARSE_FAILURE;
641
31
        return 0;
642
31
    }
643
1.46k
    for (int i = 1; i < len; ++i) {
644
1.20k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
645
949
            T digit = s[i] - '0';
646
949
            val = val * 10 + digit;
647
949
        } else {
648
256
            if constexpr (enable_strict_mode) {
649
256
                if (UNLIKELY(!is_all_whitespace(s + i, len - i))) {
650
256
                    *result = PARSE_FAILURE;
651
256
                    return 0;
652
256
                }
653
            } else {
654
                if ((UNLIKELY(!is_all_whitespace(s + i, len - i) &&
655
                              !is_float_suffix(s + i, len - i)))) {
656
                    *result = PARSE_FAILURE;
657
                    return 0;
658
                }
659
            }
660
0
            *result = PARSE_SUCCESS;
661
256
            return val;
662
256
        }
663
1.20k
    }
664
257
    *result = PARSE_SUCCESS;
665
257
    return val;
666
513
}
_ZN5doris12StringParser25string_to_int_no_overflowIN4wide7integerILm256EjEELb0EEET_PKciPNS0_11ParseResultE
Line
Count
Source
630
4
T StringParser::string_to_int_no_overflow(const char* __restrict s, int len, ParseResult* result) {
631
4
    T val = 0;
632
4
    if (UNLIKELY(len == 0)) {
633
0
        *result = PARSE_SUCCESS;
634
0
        return val;
635
0
    }
636
    // Factor out the first char for error handling speeds up the loop.
637
4
    if (LIKELY(s[0] >= '0' && s[0] <= '9')) {
638
4
        val = s[0] - '0';
639
4
    } else {
640
0
        *result = PARSE_FAILURE;
641
0
        return 0;
642
0
    }
643
4
    for (int i = 1; i < len; ++i) {
644
0
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
645
0
            T digit = s[i] - '0';
646
0
            val = val * 10 + digit;
647
0
        } else {
648
            if constexpr (enable_strict_mode) {
649
                if (UNLIKELY(!is_all_whitespace(s + i, len - i))) {
650
                    *result = PARSE_FAILURE;
651
                    return 0;
652
                }
653
0
            } else {
654
0
                if ((UNLIKELY(!is_all_whitespace(s + i, len - i) &&
655
0
                              !is_float_suffix(s + i, len - i)))) {
656
0
                    *result = PARSE_FAILURE;
657
0
                    return 0;
658
0
                }
659
0
            }
660
0
            *result = PARSE_SUCCESS;
661
0
            return val;
662
0
        }
663
0
    }
664
4
    *result = PARSE_SUCCESS;
665
4
    return val;
666
4
}
_ZN5doris12StringParser25string_to_int_no_overflowIhLb1EEET_PKciPNS0_11ParseResultE
Line
Count
Source
630
51
T StringParser::string_to_int_no_overflow(const char* __restrict s, int len, ParseResult* result) {
631
51
    T val = 0;
632
51
    if (UNLIKELY(len == 0)) {
633
0
        *result = PARSE_SUCCESS;
634
0
        return val;
635
0
    }
636
    // Factor out the first char for error handling speeds up the loop.
637
51
    if (LIKELY(s[0] >= '0' && s[0] <= '9')) {
638
41
        val = s[0] - '0';
639
41
    } else {
640
10
        *result = PARSE_FAILURE;
641
10
        return 0;
642
10
    }
643
41
    for (int i = 1; i < len; ++i) {
644
1
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
645
0
            T digit = s[i] - '0';
646
0
            val = val * 10 + digit;
647
1
        } else {
648
1
            if constexpr (enable_strict_mode) {
649
1
                if (UNLIKELY(!is_all_whitespace(s + i, len - i))) {
650
1
                    *result = PARSE_FAILURE;
651
1
                    return 0;
652
1
                }
653
            } else {
654
                if ((UNLIKELY(!is_all_whitespace(s + i, len - i) &&
655
                              !is_float_suffix(s + i, len - i)))) {
656
                    *result = PARSE_FAILURE;
657
                    return 0;
658
                }
659
            }
660
0
            *result = PARSE_SUCCESS;
661
1
            return val;
662
1
        }
663
1
    }
664
40
    *result = PARSE_SUCCESS;
665
40
    return val;
666
41
}
_ZN5doris12StringParser25string_to_int_no_overflowItLb1EEET_PKciPNS0_11ParseResultE
Line
Count
Source
630
203
T StringParser::string_to_int_no_overflow(const char* __restrict s, int len, ParseResult* result) {
631
203
    T val = 0;
632
203
    if (UNLIKELY(len == 0)) {
633
0
        *result = PARSE_SUCCESS;
634
0
        return val;
635
0
    }
636
    // Factor out the first char for error handling speeds up the loop.
637
203
    if (LIKELY(s[0] >= '0' && s[0] <= '9')) {
638
187
        val = s[0] - '0';
639
187
    } else {
640
16
        *result = PARSE_FAILURE;
641
16
        return 0;
642
16
    }
643
339
    for (int i = 1; i < len; ++i) {
644
243
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
645
152
            T digit = s[i] - '0';
646
152
            val = val * 10 + digit;
647
152
        } else {
648
91
            if constexpr (enable_strict_mode) {
649
91
                if (UNLIKELY(!is_all_whitespace(s + i, len - i))) {
650
91
                    *result = PARSE_FAILURE;
651
91
                    return 0;
652
91
                }
653
            } else {
654
                if ((UNLIKELY(!is_all_whitespace(s + i, len - i) &&
655
                              !is_float_suffix(s + i, len - i)))) {
656
                    *result = PARSE_FAILURE;
657
                    return 0;
658
                }
659
            }
660
0
            *result = PARSE_SUCCESS;
661
91
            return val;
662
91
        }
663
243
    }
664
96
    *result = PARSE_SUCCESS;
665
96
    return val;
666
187
}
_ZN5doris12StringParser25string_to_int_no_overflowImLb1EEET_PKciPNS0_11ParseResultE
Line
Count
Source
630
402
T StringParser::string_to_int_no_overflow(const char* __restrict s, int len, ParseResult* result) {
631
402
    T val = 0;
632
402
    if (UNLIKELY(len == 0)) {
633
0
        *result = PARSE_SUCCESS;
634
0
        return val;
635
0
    }
636
    // Factor out the first char for error handling speeds up the loop.
637
402
    if (LIKELY(s[0] >= '0' && s[0] <= '9')) {
638
369
        val = s[0] - '0';
639
369
    } else {
640
33
        *result = PARSE_FAILURE;
641
33
        return 0;
642
33
    }
643
1.10k
    for (int i = 1; i < len; ++i) {
644
990
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
645
734
            T digit = s[i] - '0';
646
734
            val = val * 10 + digit;
647
734
        } else {
648
256
            if constexpr (enable_strict_mode) {
649
256
                if (UNLIKELY(!is_all_whitespace(s + i, len - i))) {
650
256
                    *result = PARSE_FAILURE;
651
256
                    return 0;
652
256
                }
653
            } else {
654
                if ((UNLIKELY(!is_all_whitespace(s + i, len - i) &&
655
                              !is_float_suffix(s + i, len - i)))) {
656
                    *result = PARSE_FAILURE;
657
                    return 0;
658
                }
659
            }
660
0
            *result = PARSE_SUCCESS;
661
256
            return val;
662
256
        }
663
990
    }
664
113
    *result = PARSE_SUCCESS;
665
113
    return val;
666
369
}
_ZN5doris12StringParser25string_to_int_no_overflowIoLb1EEET_PKciPNS0_11ParseResultE
Line
Count
Source
630
401
T StringParser::string_to_int_no_overflow(const char* __restrict s, int len, ParseResult* result) {
631
401
    T val = 0;
632
401
    if (UNLIKELY(len == 0)) {
633
0
        *result = PARSE_SUCCESS;
634
0
        return val;
635
0
    }
636
    // Factor out the first char for error handling speeds up the loop.
637
401
    if (LIKELY(s[0] >= '0' && s[0] <= '9')) {
638
368
        val = s[0] - '0';
639
368
    } else {
640
33
        *result = PARSE_FAILURE;
641
33
        return 0;
642
33
    }
643
1.09k
    for (int i = 1; i < len; ++i) {
644
981
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
645
725
            T digit = s[i] - '0';
646
725
            val = val * 10 + digit;
647
725
        } else {
648
256
            if constexpr (enable_strict_mode) {
649
256
                if (UNLIKELY(!is_all_whitespace(s + i, len - i))) {
650
256
                    *result = PARSE_FAILURE;
651
256
                    return 0;
652
256
                }
653
            } else {
654
                if ((UNLIKELY(!is_all_whitespace(s + i, len - i) &&
655
                              !is_float_suffix(s + i, len - i)))) {
656
                    *result = PARSE_FAILURE;
657
                    return 0;
658
                }
659
            }
660
0
            *result = PARSE_SUCCESS;
661
256
            return val;
662
256
        }
663
981
    }
664
112
    *result = PARSE_SUCCESS;
665
112
    return val;
666
368
}
667
668
// at least the first char(if any) must be a digit.
669
template <typename T>
670
T StringParser::string_to_uint_greedy_no_overflow(const char* __restrict s, int max_len,
671
99
                                                  ParseResult* result) {
672
99
    T val = 0;
673
99
    if (max_len == 0) [[unlikely]] {
674
10
        *result = PARSE_SUCCESS;
675
10
        return val;
676
10
    }
677
    // Factor out the first char for error handling speeds up the loop.
678
89
    if (is_numeric_ascii(s[0])) [[likely]] {
679
89
        val = s[0] - '0';
680
89
    } else {
681
0
        *result = PARSE_FAILURE;
682
0
        return 0;
683
0
    }
684
396
    for (int i = 1; i < max_len; ++i) {
685
307
        if (is_numeric_ascii(s[i])) [[likely]] {
686
307
            T digit = s[i] - '0';
687
307
            val = val * 10 + digit;
688
307
        } else {
689
            // 123abc, return 123
690
0
            *result = PARSE_SUCCESS;
691
0
            return val;
692
0
        }
693
307
    }
694
89
    *result = PARSE_SUCCESS;
695
89
    return val;
696
89
}
697
698
template <typename T>
699
156k
T StringParser::string_to_float_internal(const char* __restrict s, int len, ParseResult* result) {
700
156k
    int i = 0;
701
    // skip leading spaces
702
156k
    for (; i < len; ++i) {
703
156k
        if (!is_whitespace_ascii(s[i])) {
704
156k
            break;
705
156k
        }
706
156k
    }
707
708
    // skip back spaces
709
156k
    int j = len - 1;
710
156k
    for (; j >= i; j--) {
711
156k
        if (!is_whitespace_ascii(s[j])) {
712
156k
            break;
713
156k
        }
714
156k
    }
715
716
    // skip leading '+', from_chars can handle '-'
717
156k
    if (i < len && s[i] == '+') {
718
7.08k
        i++;
719
        // ++ or +- are not valid, but the first + is already skipped,
720
        // if don't check here, from_chars will succeed.
721
        //
722
        // New version of fast_float supports a new flag called 'chars_format::allow_leading_plus'
723
        // which may avoid this extra check here.
724
        // e.g.:
725
        // fast_float::chars_format format =
726
        //         fast_float::chars_format::general | fast_float::chars_format::allow_leading_plus;
727
        // auto res = fast_float::from_chars(s + i, s + j + 1, val, format);
728
7.08k
        if (i < len && (s[i] == '+' || s[i] == '-')) {
729
20
            *result = PARSE_FAILURE;
730
20
            return 0;
731
20
        }
732
7.08k
    }
733
156k
    if (UNLIKELY(i > j)) {
734
32
        *result = PARSE_FAILURE;
735
32
        return 0;
736
32
    }
737
738
    // Use double here to not lose precision while accumulating the result
739
156k
    double val = 0;
740
156k
    auto res = fast_float::from_chars(s + i, s + j + 1, val);
741
742
156k
    if (res.ptr == s + j + 1) {
743
150k
        *result = PARSE_SUCCESS;
744
150k
        return val;
745
150k
    } else {
746
5.09k
        *result = PARSE_FAILURE;
747
5.09k
    }
748
5.09k
    return 0;
749
156k
}
_ZN5doris12StringParser24string_to_float_internalIdEET_PKciPNS0_11ParseResultE
Line
Count
Source
699
89.3k
T StringParser::string_to_float_internal(const char* __restrict s, int len, ParseResult* result) {
700
89.3k
    int i = 0;
701
    // skip leading spaces
702
89.3k
    for (; i < len; ++i) {
703
89.3k
        if (!is_whitespace_ascii(s[i])) {
704
89.3k
            break;
705
89.3k
        }
706
89.3k
    }
707
708
    // skip back spaces
709
89.3k
    int j = len - 1;
710
89.3k
    for (; j >= i; j--) {
711
89.3k
        if (!is_whitespace_ascii(s[j])) {
712
89.3k
            break;
713
89.3k
        }
714
89.3k
    }
715
716
    // skip leading '+', from_chars can handle '-'
717
89.3k
    if (i < len && s[i] == '+') {
718
3.54k
        i++;
719
        // ++ or +- are not valid, but the first + is already skipped,
720
        // if don't check here, from_chars will succeed.
721
        //
722
        // New version of fast_float supports a new flag called 'chars_format::allow_leading_plus'
723
        // which may avoid this extra check here.
724
        // e.g.:
725
        // fast_float::chars_format format =
726
        //         fast_float::chars_format::general | fast_float::chars_format::allow_leading_plus;
727
        // auto res = fast_float::from_chars(s + i, s + j + 1, val, format);
728
3.54k
        if (i < len && (s[i] == '+' || s[i] == '-')) {
729
10
            *result = PARSE_FAILURE;
730
10
            return 0;
731
10
        }
732
3.54k
    }
733
89.3k
    if (UNLIKELY(i > j)) {
734
18
        *result = PARSE_FAILURE;
735
18
        return 0;
736
18
    }
737
738
    // Use double here to not lose precision while accumulating the result
739
89.3k
    double val = 0;
740
89.3k
    auto res = fast_float::from_chars(s + i, s + j + 1, val);
741
742
89.3k
    if (res.ptr == s + j + 1) {
743
86.6k
        *result = PARSE_SUCCESS;
744
86.6k
        return val;
745
86.6k
    } else {
746
2.75k
        *result = PARSE_FAILURE;
747
2.75k
    }
748
2.75k
    return 0;
749
89.3k
}
_ZN5doris12StringParser24string_to_float_internalIfEET_PKciPNS0_11ParseResultE
Line
Count
Source
699
66.7k
T StringParser::string_to_float_internal(const char* __restrict s, int len, ParseResult* result) {
700
66.7k
    int i = 0;
701
    // skip leading spaces
702
66.7k
    for (; i < len; ++i) {
703
66.7k
        if (!is_whitespace_ascii(s[i])) {
704
66.7k
            break;
705
66.7k
        }
706
66.7k
    }
707
708
    // skip back spaces
709
66.7k
    int j = len - 1;
710
66.7k
    for (; j >= i; j--) {
711
66.7k
        if (!is_whitespace_ascii(s[j])) {
712
66.7k
            break;
713
66.7k
        }
714
66.7k
    }
715
716
    // skip leading '+', from_chars can handle '-'
717
66.7k
    if (i < len && s[i] == '+') {
718
3.54k
        i++;
719
        // ++ or +- are not valid, but the first + is already skipped,
720
        // if don't check here, from_chars will succeed.
721
        //
722
        // New version of fast_float supports a new flag called 'chars_format::allow_leading_plus'
723
        // which may avoid this extra check here.
724
        // e.g.:
725
        // fast_float::chars_format format =
726
        //         fast_float::chars_format::general | fast_float::chars_format::allow_leading_plus;
727
        // auto res = fast_float::from_chars(s + i, s + j + 1, val, format);
728
3.54k
        if (i < len && (s[i] == '+' || s[i] == '-')) {
729
10
            *result = PARSE_FAILURE;
730
10
            return 0;
731
10
        }
732
3.54k
    }
733
66.7k
    if (UNLIKELY(i > j)) {
734
14
        *result = PARSE_FAILURE;
735
14
        return 0;
736
14
    }
737
738
    // Use double here to not lose precision while accumulating the result
739
66.6k
    double val = 0;
740
66.6k
    auto res = fast_float::from_chars(s + i, s + j + 1, val);
741
742
66.6k
    if (res.ptr == s + j + 1) {
743
64.3k
        *result = PARSE_SUCCESS;
744
64.3k
        return val;
745
64.3k
    } else {
746
2.34k
        *result = PARSE_FAILURE;
747
2.34k
    }
748
2.34k
    return 0;
749
66.6k
}
750
751
inline bool StringParser::string_to_bool_internal(const char* __restrict s, int len,
752
11.5k
                                                  ParseResult* result) {
753
11.5k
    *result = PARSE_SUCCESS;
754
755
11.5k
    if (len == 1) {
756
2.70k
        if (s[0] == '1' || s[0] == 't' || s[0] == 'T') {
757
338
            return true;
758
338
        }
759
2.36k
        if (s[0] == '0' || s[0] == 'f' || s[0] == 'F') {
760
950
            return false;
761
950
        }
762
1.41k
        *result = PARSE_FAILURE;
763
1.41k
        return false;
764
2.36k
    }
765
766
8.86k
    if (len == 2) {
767
989
        if ((s[0] == 'o' || s[0] == 'O') && (s[1] == 'n' || s[1] == 'N')) {
768
10
            return true;
769
10
        }
770
979
        if ((s[0] == 'n' || s[0] == 'N') && (s[1] == 'o' || s[1] == 'O')) {
771
9
            return false;
772
9
        }
773
979
    }
774
775
8.84k
    if (len == 3) {
776
42
        if ((s[0] == 'y' || s[0] == 'Y') && (s[1] == 'e' || s[1] == 'E') &&
777
42
            (s[2] == 's' || s[2] == 'S')) {
778
10
            return true;
779
10
        }
780
32
        if ((s[0] == 'o' || s[0] == 'O') && (s[1] == 'f' || s[1] == 'F') &&
781
32
            (s[2] == 'f' || s[2] == 'F')) {
782
9
            return false;
783
9
        }
784
32
    }
785
786
8.82k
    if (len == 4 && (s[0] == 't' || s[0] == 'T') && (s[1] == 'r' || s[1] == 'R') &&
787
8.82k
        (s[2] == 'u' || s[2] == 'U') && (s[3] == 'e' || s[3] == 'E')) {
788
3.43k
        return true;
789
3.43k
    }
790
791
5.38k
    if (len == 5 && (s[0] == 'f' || s[0] == 'F') && (s[1] == 'a' || s[1] == 'A') &&
792
5.38k
        (s[2] == 'l' || s[2] == 'L') && (s[3] == 's' || s[3] == 'S') &&
793
5.38k
        (s[4] == 'e' || s[4] == 'E')) {
794
3.48k
        return false;
795
3.48k
    }
796
797
    // No valid boolean value found
798
1.89k
    *result = PARSE_FAILURE;
799
1.89k
    return false;
800
5.38k
}
801
802
} // end namespace doris