Coverage Report

Created: 2026-10-14 22:10

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
be/src/util/string_parser.hpp
Line
Count
Source
1
// Licensed to the Apache Software Foundation (ASF) under one
2
// or more contributor license agreements.  See the NOTICE file
3
// distributed with this work for additional information
4
// regarding copyright ownership.  The ASF licenses this file
5
// to you under the Apache License, Version 2.0 (the
6
// "License"); you may not use this file except in compliance
7
// with the License.  You may obtain a copy of the License at
8
//
9
//   http://www.apache.org/licenses/LICENSE-2.0
10
//
11
// Unless required by applicable law or agreed to in writing,
12
// software distributed under the License is distributed on an
13
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
// KIND, either express or implied.  See the License for the
15
// specific language governing permissions and limitations
16
// under the License.
17
// This file is copied from
18
// https://github.com/apache/impala/blob/branch-2.9.0/be/src/util/string-parser.hpp
19
// and modified by Doris
20
21
#pragma once
22
23
#include <fast_float/fast_float.h>
24
#include <fast_float/parse_number.h>
25
#include <glog/logging.h>
26
#include <sys/types.h>
27
28
#include <algorithm>
29
#include <cstdlib>
30
// IWYU pragma: no_include <bits/std_abs.h>
31
#include <cmath> // IWYU pragma: keep
32
#include <cstdint>
33
#include <limits>
34
#include <map>
35
#include <string>
36
#include <type_traits>
37
#include <utility>
38
39
#include "common/status.h"
40
#include "core/data_type/number_traits.h"
41
#include "core/data_type/primitive_type.h"
42
#include "core/extended_types.h"
43
#include "core/value/large_int_value.h"
44
#include "exec/common/int_exp.h"
45
#include "exec/common/string_utils/string_utils.h"
46
47
namespace doris {
48
#include "common/compile_check_avoid_begin.h"
49
template <DecimalNativeTypeConcept T>
50
struct Decimal;
51
52
// they rely on the template parameter `IS_STRICT`. in strict mode, it will set error code and otherwise it will not.
53
#ifndef SET_PARAMS_RET_FALSE_IFN
54
#define SET_PARAMS_RET_FALSE_IFN(stmt, ...)                           \
55
1.09M
    do {                                                              \
56
1.09M
        if (!(stmt)) [[unlikely]] {                                   \
57
36.6k
            if constexpr (IsStrict) {                                 \
58
212
                params.status = Status::InvalidArgument(__VA_ARGS__); \
59
212
            }                                                         \
60
36.6k
            return false;                                             \
61
36.6k
        }                                                             \
62
1.09M
    } while (false)
63
#endif
64
65
#ifndef SET_PARAMS_RET_FALSE_FROM_EXCEPTION
66
#define SET_PARAMS_RET_FALSE_FROM_EXCEPTION(stmt) \
67
186
    do {                                          \
68
186
        try {                                     \
69
186
            { stmt; }                             \
70
186
        } catch (const doris::Exception& e) {     \
71
15
            if constexpr (IsStrict) {             \
72
2
                params.status = e.to_status();    \
73
2
            }                                     \
74
15
            return false;                         \
75
15
        }                                         \
76
186
    } while (false)
77
#endif
78
79
// skip leading and trailing ascii whitespaces,
80
// return the pointer to the first non-whitespace char,
81
// and update the len to the new length, which does not include
82
// leading and trailing whitespaces
83
template <typename T>
84
563k
inline const char* skip_ascii_whitespaces(const char* s, T& len) {
85
1.03M
    while (len > 0 && is_whitespace_ascii(*s)) {
86
471k
        ++s;
87
471k
        --len;
88
471k
    }
89
90
1.03M
    while (len > 0 && is_whitespace_ascii(s[len - 1])) {
91
467k
        --len;
92
467k
    }
93
94
563k
    return s;
95
563k
}
_ZN5doris22skip_ascii_whitespacesImEEPKcS2_RT_
Line
Count
Source
84
531k
inline const char* skip_ascii_whitespaces(const char* s, T& len) {
85
925k
    while (len > 0 && is_whitespace_ascii(*s)) {
86
393k
        ++s;
87
393k
        --len;
88
393k
    }
89
90
921k
    while (len > 0 && is_whitespace_ascii(s[len - 1])) {
91
390k
        --len;
92
390k
    }
93
94
531k
    return s;
95
531k
}
_ZN5doris22skip_ascii_whitespacesIiEEPKcS2_RT_
Line
Count
Source
84
1.37k
inline const char* skip_ascii_whitespaces(const char* s, T& len) {
85
4.90k
    while (len > 0 && is_whitespace_ascii(*s)) {
86
3.52k
        ++s;
87
3.52k
        --len;
88
3.52k
    }
89
90
4.90k
    while (len > 0 && is_whitespace_ascii(s[len - 1])) {
91
3.52k
        --len;
92
3.52k
    }
93
94
1.37k
    return s;
95
1.37k
}
_ZN5doris22skip_ascii_whitespacesIlEEPKcS2_RT_
Line
Count
Source
84
31.1k
inline const char* skip_ascii_whitespaces(const char* s, T& len) {
85
105k
    while (len > 0 && is_whitespace_ascii(*s)) {
86
74.3k
        ++s;
87
74.3k
        --len;
88
74.3k
    }
89
90
105k
    while (len > 0 && is_whitespace_ascii(s[len - 1])) {
91
73.9k
        --len;
92
73.9k
    }
93
94
31.1k
    return s;
95
31.1k
}
96
97
template <typename T>
98
58.6k
inline const char* skip_leading_whitespace(const char* __restrict s, T& len) {
99
174k
    while (len > 0 && is_whitespace_ascii(*s)) {
100
116k
        ++s;
101
116k
        --len;
102
116k
    }
103
104
58.6k
    return s;
105
58.6k
}
106
107
// skip trailing ascii whitespaces,
108
// return the pointer to the first char,
109
// and update the len to the new length, which does not include
110
// trailing whitespaces
111
template <typename T>
112
47.3k
inline const char* skip_trailing_whitespaces(const char* s, T& len) {
113
171k
    while (len > 0 && is_whitespace_ascii(s[len - 1])) {
114
123k
        --len;
115
123k
    }
116
117
47.3k
    return s;
118
47.3k
}
119
120
template <bool (*Pred)(char)>
121
61.2k
bool range_suite(const char* s, const char* end) {
122
61.2k
    return std::ranges::all_of(s, end, Pred);
123
61.2k
}
_ZN5doris11range_suiteIXadL_Z16is_numeric_asciicEEEEbPKcS2_
Line
Count
Source
121
58.9k
bool range_suite(const char* s, const char* end) {
122
58.9k
    return std::ranges::all_of(s, end, Pred);
123
58.9k
}
_ZN5doris11range_suiteIXadL_Z19is_whitespace_asciicEEEEbPKcS2_
Line
Count
Source
121
2.34k
bool range_suite(const char* s, const char* end) {
122
2.34k
    return std::ranges::all_of(s, end, Pred);
123
2.34k
}
124
125
inline auto is_digit_range = range_suite<is_numeric_ascii>;
126
inline auto is_space_range = range_suite<is_whitespace_ascii>;
127
128
// combine in_bound and range_suite is ok. won't lead to duplicated calculation.
129
57.7k
inline bool in_bound(const char* s, const char* end, size_t offset) {
130
57.7k
    if (s + offset >= end) [[unlikely]] {
131
3.12k
        return false;
132
3.12k
    }
133
54.6k
    return true;
134
57.7k
}
135
136
// LEN = 0 means any length(include zero). LEN = 1 means only one character. so on. LEN = -x means x or more.
137
// if need result, use StringRef{origin_s, s} outside
138
template <int LEN, bool (*Pred)(char)>
139
513k
bool skip_qualified_char(const char*& s, const char* end) {
140
513k
    if constexpr (LEN == 0) {
141
        // Consume any length of characters that match the predicate.
142
1.15M
        while (s != end && Pred(*s)) {
143
714k
            ++s;
144
714k
        }
145
440k
    } else if constexpr (LEN > 0) {
146
        // Consume exactly LEN characters that match the predicate.
147
134k
        for (int i = 0; i < LEN; ++i, ++s) {
148
72.5k
            if (s == end || !Pred(*s)) [[unlikely]] {
149
10.9k
                return false;
150
10.9k
            }
151
72.5k
        }
152
72.5k
    } else { // LEN < 0
153
        // Consume at least -LEN characters that match the predicate.
154
70
        int count = 0;
155
448
        while (s != end && Pred(*s)) {
156
378
            ++s;
157
378
            ++count;
158
378
        }
159
70
        if (count < -LEN) [[unlikely]] {
160
0
            return false;
161
0
        }
162
70
    }
163
61.6k
    return true;
164
513k
}
_ZN5doris19skip_qualified_charILi0EXadL_Z19is_whitespace_asciicEEEEbRPKcS2_
Line
Count
Source
139
164k
bool skip_qualified_char(const char*& s, const char* end) {
140
164k
    if constexpr (LEN == 0) {
141
        // Consume any length of characters that match the predicate.
142
168k
        while (s != end && Pred(*s)) {
143
4.06k
            ++s;
144
4.06k
        }
145
    } else if constexpr (LEN > 0) {
146
        // Consume exactly LEN characters that match the predicate.
147
        for (int i = 0; i < LEN; ++i, ++s) {
148
            if (s == end || !Pred(*s)) [[unlikely]] {
149
                return false;
150
            }
151
        }
152
    } else { // LEN < 0
153
        // Consume at least -LEN characters that match the predicate.
154
        int count = 0;
155
        while (s != end && Pred(*s)) {
156
            ++s;
157
            ++count;
158
        }
159
        if (count < -LEN) [[unlikely]] {
160
            return false;
161
        }
162
    }
163
164k
    return true;
164
164k
}
_ZN5doris19skip_qualified_charILi0EXadL_Z16is_numeric_asciicEEEEbRPKcS2_
Line
Count
Source
139
275k
bool skip_qualified_char(const char*& s, const char* end) {
140
275k
    if constexpr (LEN == 0) {
141
        // Consume any length of characters that match the predicate.
142
986k
        while (s != end && Pred(*s)) {
143
710k
            ++s;
144
710k
        }
145
    } else if constexpr (LEN > 0) {
146
        // Consume exactly LEN characters that match the predicate.
147
        for (int i = 0; i < LEN; ++i, ++s) {
148
            if (s == end || !Pred(*s)) [[unlikely]] {
149
                return false;
150
            }
151
        }
152
    } else { // LEN < 0
153
        // Consume at least -LEN characters that match the predicate.
154
        int count = 0;
155
        while (s != end && Pred(*s)) {
156
            ++s;
157
            ++count;
158
        }
159
        if (count < -LEN) [[unlikely]] {
160
            return false;
161
        }
162
    }
163
275k
    return true;
164
275k
}
_ZN5doris19skip_qualified_charILin1EXadL_Z23is_not_whitespace_asciicEEEEbRPKcS2_
Line
Count
Source
139
70
bool skip_qualified_char(const char*& s, const char* end) {
140
    if constexpr (LEN == 0) {
141
        // Consume any length of characters that match the predicate.
142
        while (s != end && Pred(*s)) {
143
            ++s;
144
        }
145
    } else if constexpr (LEN > 0) {
146
        // Consume exactly LEN characters that match the predicate.
147
        for (int i = 0; i < LEN; ++i, ++s) {
148
            if (s == end || !Pred(*s)) [[unlikely]] {
149
                return false;
150
            }
151
        }
152
70
    } else { // LEN < 0
153
        // Consume at least -LEN characters that match the predicate.
154
70
        int count = 0;
155
448
        while (s != end && Pred(*s)) {
156
378
            ++s;
157
378
            ++count;
158
378
        }
159
70
        if (count < -LEN) [[unlikely]] {
160
0
            return false;
161
0
        }
162
70
    }
163
70
    return true;
164
70
}
Unexecuted instantiation: _ZN5doris19skip_qualified_charILi1EXadL_Z14is_slash_asciicEEEEbRPKcS2_
_ZN5doris19skip_qualified_charILi1EXadL_Z12is_non_alnumcEEEEbRPKcS2_
Line
Count
Source
139
35.7k
bool skip_qualified_char(const char*& s, const char* end) {
140
    if constexpr (LEN == 0) {
141
        // Consume any length of characters that match the predicate.
142
        while (s != end && Pred(*s)) {
143
            ++s;
144
        }
145
35.7k
    } else if constexpr (LEN > 0) {
146
        // Consume exactly LEN characters that match the predicate.
147
60.8k
        for (int i = 0; i < LEN; ++i, ++s) {
148
35.7k
            if (s == end || !Pred(*s)) [[unlikely]] {
149
10.7k
                return false;
150
10.7k
            }
151
35.7k
        }
152
    } else { // LEN < 0
153
        // Consume at least -LEN characters that match the predicate.
154
        int count = 0;
155
        while (s != end && Pred(*s)) {
156
            ++s;
157
            ++count;
158
        }
159
        if (count < -LEN) [[unlikely]] {
160
            return false;
161
        }
162
    }
163
25.0k
    return true;
164
35.7k
}
_ZN5doris19skip_qualified_charILi1EXadL_ZNS_12is_delimiterEcEEEEbRPKcS2_
Line
Count
Source
139
2.51k
bool skip_qualified_char(const char*& s, const char* end) {
140
    if constexpr (LEN == 0) {
141
        // Consume any length of characters that match the predicate.
142
        while (s != end && Pred(*s)) {
143
            ++s;
144
        }
145
2.51k
    } else if constexpr (LEN > 0) {
146
        // Consume exactly LEN characters that match the predicate.
147
4.98k
        for (int i = 0; i < LEN; ++i, ++s) {
148
2.51k
            if (s == end || !Pred(*s)) [[unlikely]] {
149
48
                return false;
150
48
            }
151
2.51k
        }
152
    } else { // LEN < 0
153
        // Consume at least -LEN characters that match the predicate.
154
        int count = 0;
155
        while (s != end && Pred(*s)) {
156
            ++s;
157
            ++count;
158
        }
159
        if (count < -LEN) [[unlikely]] {
160
            return false;
161
        }
162
    }
163
2.46k
    return true;
164
2.51k
}
_ZN5doris19skip_qualified_charILi1EXadL_ZNS_11is_date_sepEcEEEEbRPKcS2_
Line
Count
Source
139
34.0k
bool skip_qualified_char(const char*& s, const char* end) {
140
    if constexpr (LEN == 0) {
141
        // Consume any length of characters that match the predicate.
142
        while (s != end && Pred(*s)) {
143
            ++s;
144
        }
145
34.0k
    } else if constexpr (LEN > 0) {
146
        // Consume exactly LEN characters that match the predicate.
147
68.0k
        for (int i = 0; i < LEN; ++i, ++s) {
148
34.0k
            if (s == end || !Pred(*s)) [[unlikely]] {
149
46
                return false;
150
46
            }
151
34.0k
        }
152
    } else { // LEN < 0
153
        // Consume at least -LEN characters that match the predicate.
154
        int count = 0;
155
        while (s != end && Pred(*s)) {
156
            ++s;
157
            ++count;
158
        }
159
        if (count < -LEN) [[unlikely]] {
160
            return false;
161
        }
162
    }
163
33.9k
    return true;
164
34.0k
}
_ZN5doris19skip_qualified_charILi1EXadL_ZNS_8is_colonEcEEEEbRPKcS2_
Line
Count
Source
139
152
bool skip_qualified_char(const char*& s, const char* end) {
140
    if constexpr (LEN == 0) {
141
        // Consume any length of characters that match the predicate.
142
        while (s != end && Pred(*s)) {
143
            ++s;
144
        }
145
152
    } else if constexpr (LEN > 0) {
146
        // Consume exactly LEN characters that match the predicate.
147
280
        for (int i = 0; i < LEN; ++i, ++s) {
148
152
            if (s == end || !Pred(*s)) [[unlikely]] {
149
24
                return false;
150
24
            }
151
152
        }
152
    } else { // LEN < 0
153
        // Consume at least -LEN characters that match the predicate.
154
        int count = 0;
155
        while (s != end && Pred(*s)) {
156
            ++s;
157
            ++count;
158
        }
159
        if (count < -LEN) [[unlikely]] {
160
            return false;
161
        }
162
    }
163
128
    return true;
164
152
}
165
166
inline auto skip_any_whitespace = skip_qualified_char<0, is_whitespace_ascii>;
167
inline auto skip_any_digit = skip_qualified_char<0, is_numeric_ascii>;
168
inline auto skip_tz_name_part = skip_qualified_char<-1, is_not_whitespace_ascii>;
169
inline auto skip_one_slash = skip_qualified_char<1, is_slash_ascii>;
170
inline auto skip_one_non_alnum = skip_qualified_char<1, is_non_alnum>;
171
172
2.51k
inline bool is_delimiter(char c) {
173
2.51k
    return c == ' ' || c == 'T' || c == ':';
174
2.51k
}
175
inline auto consume_one_delimiter = skip_qualified_char<1, is_delimiter>;
176
177
56.2k
inline bool is_date_sep(char c) {
178
56.2k
    return c == '-' || c == '/';
179
56.2k
}
180
inline auto consume_one_date_sep = skip_qualified_char<1, is_date_sep>;
181
182
152
inline bool is_colon(char c) {
183
152
    return c == ':';
184
152
}
185
inline auto consume_one_colon = skip_qualified_char<1, is_colon>;
186
187
// only consume a string of digit, not include sign.
188
// when has MAX_LEN > 0, do greedy match but at most MAX_LEN.
189
// LEN = 0 means any length, otherwise(must > 0) it means exactly LEN digits.
190
template <typename T, int LEN = 0, int MAX_LEN = -1>
191
23
bool consume_digit(const char*& s, const char* end, T& out) {
192
23
    static_assert(LEN >= 0);
193
    if constexpr (MAX_LEN > 0) {
194
        out = 0;
195
        for (int i = 0; i < MAX_LEN; ++i, ++s) {
196
            if (s == end || !is_numeric_ascii(*s)) {
197
                if (i < LEN) [[unlikely]] {
198
                    return false;
199
                }
200
                break; // stop consuming if we have consumed enough digits.
201
            }
202
            out = out * 10 + (*s - '0');
203
        }
204
    } else if constexpr (LEN == 0) {
205
        // Consume any length of digits.
206
        out = 0;
207
        while (s != end && is_numeric_ascii(*s)) {
208
            out = out * 10 + (*s - '0');
209
            ++s;
210
        }
211
23
    } else if constexpr (LEN > 0) {
212
        // Consume exactly LEN digits.
213
23
        out = 0;
214
94
        for (int i = 0; i < LEN; ++i, ++s) {
215
71
            if (s == end || !is_numeric_ascii(*s)) [[unlikely]] {
216
0
                return false;
217
0
            }
218
71
            out = out * 10 + (*s - '0');
219
71
        }
220
23
    }
221
23
    return true;
222
23
}
_ZN5doris13consume_digitIjLi4ELin1EEEbRPKcS2_RT_
Line
Count
Source
191
16
bool consume_digit(const char*& s, const char* end, T& out) {
192
16
    static_assert(LEN >= 0);
193
    if constexpr (MAX_LEN > 0) {
194
        out = 0;
195
        for (int i = 0; i < MAX_LEN; ++i, ++s) {
196
            if (s == end || !is_numeric_ascii(*s)) {
197
                if (i < LEN) [[unlikely]] {
198
                    return false;
199
                }
200
                break; // stop consuming if we have consumed enough digits.
201
            }
202
            out = out * 10 + (*s - '0');
203
        }
204
    } else if constexpr (LEN == 0) {
205
        // Consume any length of digits.
206
        out = 0;
207
        while (s != end && is_numeric_ascii(*s)) {
208
            out = out * 10 + (*s - '0');
209
            ++s;
210
        }
211
16
    } else if constexpr (LEN > 0) {
212
        // Consume exactly LEN digits.
213
16
        out = 0;
214
80
        for (int i = 0; i < LEN; ++i, ++s) {
215
64
            if (s == end || !is_numeric_ascii(*s)) [[unlikely]] {
216
0
                return false;
217
0
            }
218
64
            out = out * 10 + (*s - '0');
219
64
        }
220
16
    }
221
16
    return true;
222
16
}
_ZN5doris13consume_digitIjLi1ELin1EEEbRPKcS2_RT_
Line
Count
Source
191
7
bool consume_digit(const char*& s, const char* end, T& out) {
192
7
    static_assert(LEN >= 0);
193
    if constexpr (MAX_LEN > 0) {
194
        out = 0;
195
        for (int i = 0; i < MAX_LEN; ++i, ++s) {
196
            if (s == end || !is_numeric_ascii(*s)) {
197
                if (i < LEN) [[unlikely]] {
198
                    return false;
199
                }
200
                break; // stop consuming if we have consumed enough digits.
201
            }
202
            out = out * 10 + (*s - '0');
203
        }
204
    } else if constexpr (LEN == 0) {
205
        // Consume any length of digits.
206
        out = 0;
207
        while (s != end && is_numeric_ascii(*s)) {
208
            out = out * 10 + (*s - '0');
209
            ++s;
210
        }
211
7
    } else if constexpr (LEN > 0) {
212
        // Consume exactly LEN digits.
213
7
        out = 0;
214
14
        for (int i = 0; i < LEN; ++i, ++s) {
215
7
            if (s == end || !is_numeric_ascii(*s)) [[unlikely]] {
216
0
                return false;
217
0
            }
218
7
            out = out * 10 + (*s - '0');
219
7
        }
220
7
    }
221
7
    return true;
222
7
}
223
224
// specialized version for 2 digits, which is used very often in date/time parsing.
225
template <>
226
116k
inline bool consume_digit<uint32_t, 2, -1>(const char*& s, const char* end, uint32_t& out) {
227
116k
    out = 0;
228
116k
    if (s == end || s + 1 == end || !is_numeric_ascii(*s) || !is_numeric_ascii(*(s + 1)))
229
18.4k
            [[unlikely]] {
230
18.4k
        return false;
231
18.4k
    }
232
98.5k
    out = (s[0] - '0') * 10 + (s[1] - '0');
233
98.5k
    s += 2; // consume 2 digits
234
98.5k
    return true;
235
116k
}
236
237
// specialized version for 1 or 2 digits, which is used very often in date/time parsing.
238
template <>
239
61.8k
inline bool consume_digit<uint32_t, 1, 2>(const char*& s, const char* end, uint32_t& out) {
240
61.8k
    out = 0;
241
61.8k
    if (s == end || !is_numeric_ascii(*s)) [[unlikely]] {
242
479
        return false;
243
61.4k
    } else if (s + 1 != end && is_numeric_ascii(*(s + 1))) {
244
        // consume 2 digits
245
44.4k
        out = (*s - '0') * 10 + (*(s + 1) - '0');
246
44.4k
        s += 2;
247
44.4k
    } else {
248
        // consume 1 digit
249
16.9k
        out = *s - '0';
250
16.9k
        ++s;
251
16.9k
    }
252
61.4k
    return true;
253
61.8k
}
254
255
template <bool (*Pred)(char)>
256
1.34k
uint32_t count_valid_length(const char* s, const char* end) {
257
1.34k
    DCHECK(s <= end) << "s: " << s << ", end: " << end;
258
1.34k
    uint32_t count = 0;
259
4.04k
    while (s != end && Pred(*s)) {
260
2.70k
        ++count;
261
2.70k
        ++s;
262
2.70k
    }
263
1.34k
    return count;
264
1.34k
}
265
266
inline auto count_digits = count_valid_length<is_numeric_ascii>;
267
268
47
inline std::string combine_tz_offset(char sign, uint32_t hour_offset, uint32_t minute_offset) {
269
47
    std::string result(6, '0');
270
47
    result[0] = sign;
271
47
    result[1] = '0' + (hour_offset / 10);
272
47
    result[2] = '0' + (hour_offset % 10);
273
47
    result[3] = ':';
274
47
    result[4] = '0' + (minute_offset / 10);
275
47
    result[5] = '0' + (minute_offset % 10);
276
47
    DCHECK_EQ(result.size(), 6);
277
47
    return result;
278
47
}
279
280
// Utility functions for doing atoi/atof on non-null terminated strings.  On micro benchmarks,
281
// this is significantly faster than libc (atoi/strtol and atof/strtod).
282
//
283
// Strings with leading and trailing whitespaces are accepted.
284
// Branching is heavily optimized for the non-whitespace successful case.
285
// All the StringTo* functions first parse the input string assuming it has no leading whitespace.
286
// If that first attempt was unsuccessful, these functions retry the parsing after removing
287
// whitespace. Therefore, strings with whitespace take a perf hit on branch mis-prediction.
288
//
289
// For overflows, we are following the mysql behavior, to cap values at the max/min value for that
290
// data type.  This is different from hive, which returns NULL for overflow slots for int types
291
// and inf/-inf for float types.
292
//
293
// Things we tried that did not work:
294
//  - lookup table for converting character to digit
295
// Improvements (TODO):
296
//  - Validate input using _simd_compare_ranges
297
//  - Since we know the length, we can parallelize this: i.e. result = 100*s[0] + 10*s[1] + s[2]
298
class StringParser {
299
public:
300
    enum ParseResult { PARSE_SUCCESS = 0, PARSE_FAILURE, PARSE_OVERFLOW, PARSE_UNDERFLOW };
301
302
    template <typename T>
303
502k
    static T numeric_limits(bool negative) {
304
502k
        if constexpr (std::is_same_v<T, __int128>) {
305
49.7k
            return negative ? MIN_INT128 : MAX_INT128;
306
452k
        } else {
307
452k
            return negative ? std::numeric_limits<T>::min() : std::numeric_limits<T>::max();
308
452k
        }
309
502k
    }
_ZN5doris12StringParser14numeric_limitsInEET_b
Line
Count
Source
303
49.7k
    static T numeric_limits(bool negative) {
304
49.7k
        if constexpr (std::is_same_v<T, __int128>) {
305
49.7k
            return negative ? MIN_INT128 : MAX_INT128;
306
        } else {
307
            return negative ? std::numeric_limits<T>::min() : std::numeric_limits<T>::max();
308
        }
309
49.7k
    }
_ZN5doris12StringParser14numeric_limitsIaEET_b
Line
Count
Source
303
154k
    static T numeric_limits(bool negative) {
304
        if constexpr (std::is_same_v<T, __int128>) {
305
            return negative ? MIN_INT128 : MAX_INT128;
306
154k
        } else {
307
154k
            return negative ? std::numeric_limits<T>::min() : std::numeric_limits<T>::max();
308
154k
        }
309
154k
    }
_ZN5doris12StringParser14numeric_limitsIsEET_b
Line
Count
Source
303
78.4k
    static T numeric_limits(bool negative) {
304
        if constexpr (std::is_same_v<T, __int128>) {
305
            return negative ? MIN_INT128 : MAX_INT128;
306
78.4k
        } else {
307
78.4k
            return negative ? std::numeric_limits<T>::min() : std::numeric_limits<T>::max();
308
78.4k
        }
309
78.4k
    }
_ZN5doris12StringParser14numeric_limitsIiEET_b
Line
Count
Source
303
116k
    static T numeric_limits(bool negative) {
304
        if constexpr (std::is_same_v<T, __int128>) {
305
            return negative ? MIN_INT128 : MAX_INT128;
306
116k
        } else {
307
116k
            return negative ? std::numeric_limits<T>::min() : std::numeric_limits<T>::max();
308
116k
        }
309
116k
    }
_ZN5doris12StringParser14numeric_limitsIlEET_b
Line
Count
Source
303
90.0k
    static T numeric_limits(bool negative) {
304
        if constexpr (std::is_same_v<T, __int128>) {
305
            return negative ? MIN_INT128 : MAX_INT128;
306
90.0k
        } else {
307
90.0k
            return negative ? std::numeric_limits<T>::min() : std::numeric_limits<T>::max();
308
90.0k
        }
309
90.0k
    }
_ZN5doris12StringParser14numeric_limitsIjEET_b
Line
Count
Source
303
1.85k
    static T numeric_limits(bool negative) {
304
        if constexpr (std::is_same_v<T, __int128>) {
305
            return negative ? MIN_INT128 : MAX_INT128;
306
1.85k
        } else {
307
1.85k
            return negative ? std::numeric_limits<T>::min() : std::numeric_limits<T>::max();
308
1.85k
        }
309
1.85k
    }
_ZN5doris12StringParser14numeric_limitsIhEET_b
Line
Count
Source
303
1.83k
    static T numeric_limits(bool negative) {
304
        if constexpr (std::is_same_v<T, __int128>) {
305
            return negative ? MIN_INT128 : MAX_INT128;
306
1.83k
        } else {
307
1.83k
            return negative ? std::numeric_limits<T>::min() : std::numeric_limits<T>::max();
308
1.83k
        }
309
1.83k
    }
_ZN5doris12StringParser14numeric_limitsItEET_b
Line
Count
Source
303
1.68k
    static T numeric_limits(bool negative) {
304
        if constexpr (std::is_same_v<T, __int128>) {
305
            return negative ? MIN_INT128 : MAX_INT128;
306
1.68k
        } else {
307
1.68k
            return negative ? std::numeric_limits<T>::min() : std::numeric_limits<T>::max();
308
1.68k
        }
309
1.68k
    }
_ZN5doris12StringParser14numeric_limitsImEET_b
Line
Count
Source
303
5.21k
    static T numeric_limits(bool negative) {
304
        if constexpr (std::is_same_v<T, __int128>) {
305
            return negative ? MIN_INT128 : MAX_INT128;
306
5.21k
        } else {
307
5.21k
            return negative ? std::numeric_limits<T>::min() : std::numeric_limits<T>::max();
308
5.21k
        }
309
5.21k
    }
_ZN5doris12StringParser14numeric_limitsIoEET_b
Line
Count
Source
303
1.69k
    static T numeric_limits(bool negative) {
304
        if constexpr (std::is_same_v<T, __int128>) {
305
            return negative ? MIN_INT128 : MAX_INT128;
306
1.69k
        } else {
307
1.69k
            return negative ? std::numeric_limits<T>::min() : std::numeric_limits<T>::max();
308
1.69k
        }
309
1.69k
    }
_ZN5doris12StringParser14numeric_limitsIN4wide7integerILm256EiEEEET_b
Line
Count
Source
303
4
    static T numeric_limits(bool negative) {
304
        if constexpr (std::is_same_v<T, __int128>) {
305
            return negative ? MIN_INT128 : MAX_INT128;
306
4
        } else {
307
4
            return negative ? std::numeric_limits<T>::min() : std::numeric_limits<T>::max();
308
4
        }
309
4
    }
310
311
    template <typename T>
312
965k
    static T get_scale_multiplier(int scale) {
313
965k
        static_assert(std::is_same_v<T, int32_t> || std::is_same_v<T, int64_t> ||
314
965k
                              std::is_same_v<T, __int128> || std::is_same_v<T, wide::Int256>,
315
965k
                      "You can only instantiate as int32_t, int64_t, __int128.");
316
965k
        if constexpr (std::is_same_v<T, int32_t>) {
317
139k
            return common::exp10_i32(scale);
318
188k
        } else if constexpr (std::is_same_v<T, int64_t>) {
319
188k
            return common::exp10_i64(scale);
320
245k
        } else if constexpr (std::is_same_v<T, __int128>) {
321
245k
            return common::exp10_i128(scale);
322
392k
        } else if constexpr (std::is_same_v<T, wide::Int256>) {
323
392k
            return common::exp10_i256(scale);
324
392k
        }
325
965k
    }
_ZN5doris12StringParser20get_scale_multiplierIiEET_i
Line
Count
Source
312
139k
    static T get_scale_multiplier(int scale) {
313
139k
        static_assert(std::is_same_v<T, int32_t> || std::is_same_v<T, int64_t> ||
314
139k
                              std::is_same_v<T, __int128> || std::is_same_v<T, wide::Int256>,
315
139k
                      "You can only instantiate as int32_t, int64_t, __int128.");
316
139k
        if constexpr (std::is_same_v<T, int32_t>) {
317
139k
            return common::exp10_i32(scale);
318
        } else if constexpr (std::is_same_v<T, int64_t>) {
319
            return common::exp10_i64(scale);
320
        } else if constexpr (std::is_same_v<T, __int128>) {
321
            return common::exp10_i128(scale);
322
        } else if constexpr (std::is_same_v<T, wide::Int256>) {
323
            return common::exp10_i256(scale);
324
        }
325
139k
    }
_ZN5doris12StringParser20get_scale_multiplierIlEET_i
Line
Count
Source
312
188k
    static T get_scale_multiplier(int scale) {
313
188k
        static_assert(std::is_same_v<T, int32_t> || std::is_same_v<T, int64_t> ||
314
188k
                              std::is_same_v<T, __int128> || std::is_same_v<T, wide::Int256>,
315
188k
                      "You can only instantiate as int32_t, int64_t, __int128.");
316
        if constexpr (std::is_same_v<T, int32_t>) {
317
            return common::exp10_i32(scale);
318
188k
        } else if constexpr (std::is_same_v<T, int64_t>) {
319
188k
            return common::exp10_i64(scale);
320
        } else if constexpr (std::is_same_v<T, __int128>) {
321
            return common::exp10_i128(scale);
322
        } else if constexpr (std::is_same_v<T, wide::Int256>) {
323
            return common::exp10_i256(scale);
324
        }
325
188k
    }
_ZN5doris12StringParser20get_scale_multiplierInEET_i
Line
Count
Source
312
245k
    static T get_scale_multiplier(int scale) {
313
245k
        static_assert(std::is_same_v<T, int32_t> || std::is_same_v<T, int64_t> ||
314
245k
                              std::is_same_v<T, __int128> || std::is_same_v<T, wide::Int256>,
315
245k
                      "You can only instantiate as int32_t, int64_t, __int128.");
316
        if constexpr (std::is_same_v<T, int32_t>) {
317
            return common::exp10_i32(scale);
318
        } else if constexpr (std::is_same_v<T, int64_t>) {
319
            return common::exp10_i64(scale);
320
245k
        } else if constexpr (std::is_same_v<T, __int128>) {
321
245k
            return common::exp10_i128(scale);
322
        } else if constexpr (std::is_same_v<T, wide::Int256>) {
323
            return common::exp10_i256(scale);
324
        }
325
245k
    }
_ZN5doris12StringParser20get_scale_multiplierIN4wide7integerILm256EiEEEET_i
Line
Count
Source
312
392k
    static T get_scale_multiplier(int scale) {
313
392k
        static_assert(std::is_same_v<T, int32_t> || std::is_same_v<T, int64_t> ||
314
392k
                              std::is_same_v<T, __int128> || std::is_same_v<T, wide::Int256>,
315
392k
                      "You can only instantiate as int32_t, int64_t, __int128.");
316
        if constexpr (std::is_same_v<T, int32_t>) {
317
            return common::exp10_i32(scale);
318
        } else if constexpr (std::is_same_v<T, int64_t>) {
319
            return common::exp10_i64(scale);
320
        } else if constexpr (std::is_same_v<T, __int128>) {
321
            return common::exp10_i128(scale);
322
392k
        } else if constexpr (std::is_same_v<T, wide::Int256>) {
323
392k
            return common::exp10_i256(scale);
324
392k
        }
325
392k
    }
326
327
    // This is considerably faster than glibc's implementation (25x).
328
    // Assumes s represents a decimal number.
329
    template <typename T, bool enable_strict_mode = false>
330
414k
    static inline T string_to_int(const char* __restrict s, size_t len, ParseResult* result) {
331
414k
        T ans = string_to_int_internal<T, enable_strict_mode>(s, len, result);
332
414k
        if (LIKELY(*result == PARSE_SUCCESS)) {
333
355k
            return ans;
334
355k
        }
335
58.6k
        s = skip_leading_whitespace(s, len);
336
58.6k
        return string_to_int_internal<T, enable_strict_mode>(s, len, result);
337
414k
    }
_ZN5doris12StringParser13string_to_intInLb0EEET_PKcmPNS0_11ParseResultE
Line
Count
Source
330
46.1k
    static inline T string_to_int(const char* __restrict s, size_t len, ParseResult* result) {
331
46.1k
        T ans = string_to_int_internal<T, enable_strict_mode>(s, len, result);
332
46.1k
        if (LIKELY(*result == PARSE_SUCCESS)) {
333
44.7k
            return ans;
334
44.7k
        }
335
1.34k
        s = skip_leading_whitespace(s, len);
336
1.34k
        return string_to_int_internal<T, enable_strict_mode>(s, len, result);
337
46.1k
    }
_ZN5doris12StringParser13string_to_intIaLb0EEET_PKcmPNS0_11ParseResultE
Line
Count
Source
330
96.7k
    static inline T string_to_int(const char* __restrict s, size_t len, ParseResult* result) {
331
96.7k
        T ans = string_to_int_internal<T, enable_strict_mode>(s, len, result);
332
96.7k
        if (LIKELY(*result == PARSE_SUCCESS)) {
333
67.4k
            return ans;
334
67.4k
        }
335
29.2k
        s = skip_leading_whitespace(s, len);
336
29.2k
        return string_to_int_internal<T, enable_strict_mode>(s, len, result);
337
96.7k
    }
_ZN5doris12StringParser13string_to_intIaLb1EEET_PKcmPNS0_11ParseResultE
Line
Count
Source
330
1.65k
    static inline T string_to_int(const char* __restrict s, size_t len, ParseResult* result) {
331
1.65k
        T ans = string_to_int_internal<T, enable_strict_mode>(s, len, result);
332
1.65k
        if (LIKELY(*result == PARSE_SUCCESS)) {
333
612
            return ans;
334
612
        }
335
1.04k
        s = skip_leading_whitespace(s, len);
336
1.04k
        return string_to_int_internal<T, enable_strict_mode>(s, len, result);
337
1.65k
    }
_ZN5doris12StringParser13string_to_intIsLb0EEET_PKcmPNS0_11ParseResultE
Line
Count
Source
330
67.4k
    static inline T string_to_int(const char* __restrict s, size_t len, ParseResult* result) {
331
67.4k
        T ans = string_to_int_internal<T, enable_strict_mode>(s, len, result);
332
67.4k
        if (LIKELY(*result == PARSE_SUCCESS)) {
333
59.1k
            return ans;
334
59.1k
        }
335
8.21k
        s = skip_leading_whitespace(s, len);
336
8.21k
        return string_to_int_internal<T, enable_strict_mode>(s, len, result);
337
67.4k
    }
_ZN5doris12StringParser13string_to_intIsLb1EEET_PKcmPNS0_11ParseResultE
Line
Count
Source
330
1.48k
    static inline T string_to_int(const char* __restrict s, size_t len, ParseResult* result) {
331
1.48k
        T ans = string_to_int_internal<T, enable_strict_mode>(s, len, result);
332
1.48k
        if (LIKELY(*result == PARSE_SUCCESS)) {
333
588
            return ans;
334
588
        }
335
896
        s = skip_leading_whitespace(s, len);
336
896
        return string_to_int_internal<T, enable_strict_mode>(s, len, result);
337
1.48k
    }
_ZN5doris12StringParser13string_to_intIiLb0EEET_PKcmPNS0_11ParseResultE
Line
Count
Source
330
109k
    static inline T string_to_int(const char* __restrict s, size_t len, ParseResult* result) {
331
109k
        T ans = string_to_int_internal<T, enable_strict_mode>(s, len, result);
332
109k
        if (LIKELY(*result == PARSE_SUCCESS)) {
333
102k
            return ans;
334
102k
        }
335
6.51k
        s = skip_leading_whitespace(s, len);
336
6.51k
        return string_to_int_internal<T, enable_strict_mode>(s, len, result);
337
109k
    }
_ZN5doris12StringParser13string_to_intIiLb1EEET_PKcmPNS0_11ParseResultE
Line
Count
Source
330
1.65k
    static inline T string_to_int(const char* __restrict s, size_t len, ParseResult* result) {
331
1.65k
        T ans = string_to_int_internal<T, enable_strict_mode>(s, len, result);
332
1.65k
        if (LIKELY(*result == PARSE_SUCCESS)) {
333
776
            return ans;
334
776
        }
335
882
        s = skip_leading_whitespace(s, len);
336
882
        return string_to_int_internal<T, enable_strict_mode>(s, len, result);
337
1.65k
    }
_ZN5doris12StringParser13string_to_intIlLb0EEET_PKcmPNS0_11ParseResultE
Line
Count
Source
330
82.5k
    static inline T string_to_int(const char* __restrict s, size_t len, ParseResult* result) {
331
82.5k
        T ans = string_to_int_internal<T, enable_strict_mode>(s, len, result);
332
82.5k
        if (LIKELY(*result == PARSE_SUCCESS)) {
333
77.9k
            return ans;
334
77.9k
        }
335
4.53k
        s = skip_leading_whitespace(s, len);
336
4.53k
        return string_to_int_internal<T, enable_strict_mode>(s, len, result);
337
82.5k
    }
_ZN5doris12StringParser13string_to_intIlLb1EEET_PKcmPNS0_11ParseResultE
Line
Count
Source
330
1.61k
    static inline T string_to_int(const char* __restrict s, size_t len, ParseResult* result) {
331
1.61k
        T ans = string_to_int_internal<T, enable_strict_mode>(s, len, result);
332
1.61k
        if (LIKELY(*result == PARSE_SUCCESS)) {
333
611
            return ans;
334
611
        }
335
1.00k
        s = skip_leading_whitespace(s, len);
336
1.00k
        return string_to_int_internal<T, enable_strict_mode>(s, len, result);
337
1.61k
    }
_ZN5doris12StringParser13string_to_intInLb1EEET_PKcmPNS0_11ParseResultE
Line
Count
Source
330
1.48k
    static inline T string_to_int(const char* __restrict s, size_t len, ParseResult* result) {
331
1.48k
        T ans = string_to_int_internal<T, enable_strict_mode>(s, len, result);
332
1.48k
        if (LIKELY(*result == PARSE_SUCCESS)) {
333
595
            return ans;
334
595
        }
335
890
        s = skip_leading_whitespace(s, len);
336
890
        return string_to_int_internal<T, enable_strict_mode>(s, len, result);
337
1.48k
    }
_ZN5doris12StringParser13string_to_intIhLb0EEET_PKcmPNS0_11ParseResultE
Line
Count
Source
330
441
    static inline T string_to_int(const char* __restrict s, size_t len, ParseResult* result) {
331
441
        T ans = string_to_int_internal<T, enable_strict_mode>(s, len, result);
332
441
        if (LIKELY(*result == PARSE_SUCCESS)) {
333
42
            return ans;
334
42
        }
335
399
        s = skip_leading_whitespace(s, len);
336
399
        return string_to_int_internal<T, enable_strict_mode>(s, len, result);
337
441
    }
_ZN5doris12StringParser13string_to_intItLb0EEET_PKcmPNS0_11ParseResultE
Line
Count
Source
330
441
    static inline T string_to_int(const char* __restrict s, size_t len, ParseResult* result) {
331
441
        T ans = string_to_int_internal<T, enable_strict_mode>(s, len, result);
332
441
        if (LIKELY(*result == PARSE_SUCCESS)) {
333
42
            return ans;
334
42
        }
335
399
        s = skip_leading_whitespace(s, len);
336
399
        return string_to_int_internal<T, enable_strict_mode>(s, len, result);
337
441
    }
_ZN5doris12StringParser13string_to_intIjLb0EEET_PKcmPNS0_11ParseResultE
Line
Count
Source
330
442
    static inline T string_to_int(const char* __restrict s, size_t len, ParseResult* result) {
331
442
        T ans = string_to_int_internal<T, enable_strict_mode>(s, len, result);
332
442
        if (LIKELY(*result == PARSE_SUCCESS)) {
333
43
            return ans;
334
43
        }
335
399
        s = skip_leading_whitespace(s, len);
336
399
        return string_to_int_internal<T, enable_strict_mode>(s, len, result);
337
442
    }
_ZN5doris12StringParser13string_to_intImLb0EEET_PKcmPNS0_11ParseResultE
Line
Count
Source
330
841
    static inline T string_to_int(const char* __restrict s, size_t len, ParseResult* result) {
331
841
        T ans = string_to_int_internal<T, enable_strict_mode>(s, len, result);
332
841
        if (LIKELY(*result == PARSE_SUCCESS)) {
333
442
            return ans;
334
442
        }
335
399
        s = skip_leading_whitespace(s, len);
336
399
        return string_to_int_internal<T, enable_strict_mode>(s, len, result);
337
841
    }
_ZN5doris12StringParser13string_to_intIoLb0EEET_PKcmPNS0_11ParseResultE
Line
Count
Source
330
445
    static inline T string_to_int(const char* __restrict s, size_t len, ParseResult* result) {
331
445
        T ans = string_to_int_internal<T, enable_strict_mode>(s, len, result);
332
445
        if (LIKELY(*result == PARSE_SUCCESS)) {
333
46
            return ans;
334
46
        }
335
399
        s = skip_leading_whitespace(s, len);
336
399
        return string_to_int_internal<T, enable_strict_mode>(s, len, result);
337
445
    }
_ZN5doris12StringParser13string_to_intIhLb1EEET_PKcmPNS0_11ParseResultE
Line
Count
Source
330
441
    static inline T string_to_int(const char* __restrict s, size_t len, ParseResult* result) {
331
441
        T ans = string_to_int_internal<T, enable_strict_mode>(s, len, result);
332
441
        if (LIKELY(*result == PARSE_SUCCESS)) {
333
35
            return ans;
334
35
        }
335
406
        s = skip_leading_whitespace(s, len);
336
406
        return string_to_int_internal<T, enable_strict_mode>(s, len, result);
337
441
    }
_ZN5doris12StringParser13string_to_intItLb1EEET_PKcmPNS0_11ParseResultE
Line
Count
Source
330
441
    static inline T string_to_int(const char* __restrict s, size_t len, ParseResult* result) {
331
441
        T ans = string_to_int_internal<T, enable_strict_mode>(s, len, result);
332
441
        if (LIKELY(*result == PARSE_SUCCESS)) {
333
35
            return ans;
334
35
        }
335
406
        s = skip_leading_whitespace(s, len);
336
406
        return string_to_int_internal<T, enable_strict_mode>(s, len, result);
337
441
    }
_ZN5doris12StringParser13string_to_intIjLb1EEET_PKcmPNS0_11ParseResultE
Line
Count
Source
330
441
    static inline T string_to_int(const char* __restrict s, size_t len, ParseResult* result) {
331
441
        T ans = string_to_int_internal<T, enable_strict_mode>(s, len, result);
332
441
        if (LIKELY(*result == PARSE_SUCCESS)) {
333
35
            return ans;
334
35
        }
335
406
        s = skip_leading_whitespace(s, len);
336
406
        return string_to_int_internal<T, enable_strict_mode>(s, len, result);
337
441
    }
_ZN5doris12StringParser13string_to_intImLb1EEET_PKcmPNS0_11ParseResultE
Line
Count
Source
330
441
    static inline T string_to_int(const char* __restrict s, size_t len, ParseResult* result) {
331
441
        T ans = string_to_int_internal<T, enable_strict_mode>(s, len, result);
332
441
        if (LIKELY(*result == PARSE_SUCCESS)) {
333
35
            return ans;
334
35
        }
335
406
        s = skip_leading_whitespace(s, len);
336
406
        return string_to_int_internal<T, enable_strict_mode>(s, len, result);
337
441
    }
_ZN5doris12StringParser13string_to_intIoLb1EEET_PKcmPNS0_11ParseResultE
Line
Count
Source
330
441
    static inline T string_to_int(const char* __restrict s, size_t len, ParseResult* result) {
331
441
        T ans = string_to_int_internal<T, enable_strict_mode>(s, len, result);
332
441
        if (LIKELY(*result == PARSE_SUCCESS)) {
333
35
            return ans;
334
35
        }
335
406
        s = skip_leading_whitespace(s, len);
336
406
        return string_to_int_internal<T, enable_strict_mode>(s, len, result);
337
441
    }
_ZN5doris12StringParser13string_to_intIN4wide7integerILm256EiEELb0EEET_PKcmPNS0_11ParseResultE
Line
Count
Source
330
4
    static inline T string_to_int(const char* __restrict s, size_t len, ParseResult* result) {
331
4
        T ans = string_to_int_internal<T, enable_strict_mode>(s, len, result);
332
4
        if (LIKELY(*result == PARSE_SUCCESS)) {
333
4
            return ans;
334
4
        }
335
0
        s = skip_leading_whitespace(s, len);
336
0
        return string_to_int_internal<T, enable_strict_mode>(s, len, result);
337
4
    }
338
339
    // This is considerably faster than glibc's implementation.
340
    // In the case of overflow, the max/min value for the data type will be returned.
341
    // Assumes s represents a decimal number.
342
    template <typename T>
343
1.37k
    static inline T string_to_unsigned_int(const char* __restrict s, int len, ParseResult* result) {
344
1.37k
        s = skip_ascii_whitespaces(s, len);
345
1.37k
        return string_to_unsigned_int_internal<T>(s, len, result);
346
1.37k
    }
_ZN5doris12StringParser22string_to_unsigned_intIhEET_PKciPNS0_11ParseResultE
Line
Count
Source
343
343
    static inline T string_to_unsigned_int(const char* __restrict s, int len, ParseResult* result) {
344
343
        s = skip_ascii_whitespaces(s, len);
345
343
        return string_to_unsigned_int_internal<T>(s, len, result);
346
343
    }
_ZN5doris12StringParser22string_to_unsigned_intItEET_PKciPNS0_11ParseResultE
Line
Count
Source
343
343
    static inline T string_to_unsigned_int(const char* __restrict s, int len, ParseResult* result) {
344
343
        s = skip_ascii_whitespaces(s, len);
345
343
        return string_to_unsigned_int_internal<T>(s, len, result);
346
343
    }
_ZN5doris12StringParser22string_to_unsigned_intIjEET_PKciPNS0_11ParseResultE
Line
Count
Source
343
343
    static inline T string_to_unsigned_int(const char* __restrict s, int len, ParseResult* result) {
344
343
        s = skip_ascii_whitespaces(s, len);
345
343
        return string_to_unsigned_int_internal<T>(s, len, result);
346
343
    }
_ZN5doris12StringParser22string_to_unsigned_intImEET_PKciPNS0_11ParseResultE
Line
Count
Source
343
343
    static inline T string_to_unsigned_int(const char* __restrict s, int len, ParseResult* result) {
344
343
        s = skip_ascii_whitespaces(s, len);
345
343
        return string_to_unsigned_int_internal<T>(s, len, result);
346
343
    }
347
348
    // Convert a string s representing a number in given base into a decimal number.
349
    template <typename T>
350
    static inline T string_to_int(const char* __restrict s, int64_t len, int base,
351
31.1k
                                  ParseResult* result) {
352
31.1k
        s = skip_ascii_whitespaces(s, len);
353
31.1k
        return string_to_int_internal<T>(s, len, base, result);
354
31.1k
    }
_ZN5doris12StringParser13string_to_intIaEET_PKcliPNS0_11ParseResultE
Line
Count
Source
351
26.4k
                                  ParseResult* result) {
352
26.4k
        s = skip_ascii_whitespaces(s, len);
353
26.4k
        return string_to_int_internal<T>(s, len, base, result);
354
26.4k
    }
_ZN5doris12StringParser13string_to_intIsEET_PKcliPNS0_11ParseResultE
Line
Count
Source
351
490
                                  ParseResult* result) {
352
490
        s = skip_ascii_whitespaces(s, len);
353
490
        return string_to_int_internal<T>(s, len, base, result);
354
490
    }
_ZN5doris12StringParser13string_to_intIiEET_PKcliPNS0_11ParseResultE
Line
Count
Source
351
441
                                  ParseResult* result) {
352
441
        s = skip_ascii_whitespaces(s, len);
353
441
        return string_to_int_internal<T>(s, len, base, result);
354
441
    }
_ZN5doris12StringParser13string_to_intIlEET_PKcliPNS0_11ParseResultE
Line
Count
Source
351
441
                                  ParseResult* result) {
352
441
        s = skip_ascii_whitespaces(s, len);
353
441
        return string_to_int_internal<T>(s, len, base, result);
354
441
    }
_ZN5doris12StringParser13string_to_intIhEET_PKcliPNS0_11ParseResultE
Line
Count
Source
351
147
                                  ParseResult* result) {
352
147
        s = skip_ascii_whitespaces(s, len);
353
147
        return string_to_int_internal<T>(s, len, base, result);
354
147
    }
_ZN5doris12StringParser13string_to_intImEET_PKcliPNS0_11ParseResultE
Line
Count
Source
351
3.12k
                                  ParseResult* result) {
352
3.12k
        s = skip_ascii_whitespaces(s, len);
353
3.12k
        return string_to_int_internal<T>(s, len, base, result);
354
3.12k
    }
355
356
    template <typename T>
357
155k
    static inline T string_to_float(const char* __restrict s, size_t len, ParseResult* result) {
358
155k
        s = skip_ascii_whitespaces(s, len);
359
155k
        return string_to_float_internal<T>(s, len, result);
360
155k
    }
_ZN5doris12StringParser15string_to_floatIdEET_PKcmPNS0_11ParseResultE
Line
Count
Source
357
89.4k
    static inline T string_to_float(const char* __restrict s, size_t len, ParseResult* result) {
358
89.4k
        s = skip_ascii_whitespaces(s, len);
359
89.4k
        return string_to_float_internal<T>(s, len, result);
360
89.4k
    }
_ZN5doris12StringParser15string_to_floatIfEET_PKcmPNS0_11ParseResultE
Line
Count
Source
357
66.4k
    static inline T string_to_float(const char* __restrict s, size_t len, ParseResult* result) {
358
66.4k
        s = skip_ascii_whitespaces(s, len);
359
66.4k
        return string_to_float_internal<T>(s, len, result);
360
66.4k
    }
361
362
    // Parses a string for 'true' or 'false', case insensitive.
363
12.0k
    static inline bool string_to_bool(const char* __restrict s, size_t len, ParseResult* result) {
364
12.0k
        s = skip_ascii_whitespaces(s, len);
365
12.0k
        return string_to_bool_internal(s, len, result);
366
12.0k
    }
367
368
    template <PrimitiveType P>
369
    static typename PrimitiveTypeTraits<P>::CppType::NativeType string_to_decimal(
370
            const char* __restrict s, size_t len, int type_precision, int type_scale,
371
            ParseResult* result);
372
373
    template <typename T>
374
    static Status split_string_to_map(const std::string& base, const T element_separator,
375
                                      const T key_value_separator,
376
                                      std::map<std::string, std::string>* result) {
377
        int key_pos = 0;
378
        int key_end;
379
        int val_pos;
380
        int val_end;
381
382
        while ((key_end = base.find(key_value_separator, key_pos)) != std::string::npos) {
383
            if ((val_pos = base.find_first_not_of(key_value_separator, key_end)) ==
384
                std::string::npos) {
385
                break;
386
            }
387
            if ((val_end = base.find(element_separator, val_pos)) == std::string::npos) {
388
                val_end = base.size();
389
            }
390
            result->insert(std::make_pair(base.substr(key_pos, key_end - key_pos),
391
                                          base.substr(val_pos, val_end - val_pos)));
392
            key_pos = val_end;
393
            if (key_pos != std::string::npos) {
394
                ++key_pos;
395
            }
396
        }
397
398
        return Status::OK();
399
    }
400
401
    // This is considerably faster than glibc's implementation.
402
    // In the case of overflow, the max/min value for the data type will be returned.
403
    // Assumes s represents a decimal number.
404
    // Return PARSE_FAILURE on leading whitespace. Trailing whitespace is allowed.
405
    template <typename T, bool enable_strict_mode = false>
406
    static inline T string_to_int_internal(const char* __restrict s, int len, ParseResult* result);
407
408
    // This is considerably faster than glibc's implementation.
409
    // In the case of overflow, the max/min value for the data type will be returned.
410
    // Assumes s represents a decimal number.
411
    // Return PARSE_FAILURE on leading whitespace. Trailing whitespace is allowed.
412
    template <typename T>
413
    static inline T string_to_unsigned_int_internal(const char* __restrict s, int len,
414
                                                    ParseResult* result);
415
416
    // Convert a string s representing a number in given base into a decimal number.
417
    // Return PARSE_FAILURE on leading whitespace. Trailing whitespace is allowed.
418
    template <typename T>
419
    static inline T string_to_int_internal(const char* __restrict s, int64_t len, int base,
420
                                           ParseResult* result);
421
422
    // Converts an ascii string to an integer of type T assuming it cannot overflow
423
    // and the number is positive.
424
    // Leading whitespace is not allowed. Trailing whitespace will be skipped.
425
    template <typename T, bool enable_strict_mode = false>
426
    static inline T string_to_int_no_overflow(const char* __restrict s, int len,
427
                                              ParseResult* result);
428
429
    // zero length, or at least one legal digit. at most consume MAX_LEN digits and stop. or stop when next
430
    // char is not a digit.
431
    template <typename T>
432
    static inline T string_to_uint_greedy_no_overflow(const char* __restrict s, int max_len,
433
                                                      ParseResult* result);
434
435
    // This is considerably faster than glibc's implementation (>100x why???)
436
    // No special case handling needs to be done for overflows, the floating point spec
437
    // already does it and will cap the values to -inf/inf
438
    // To avoid inaccurate conversions this function falls back to strtod for
439
    // scientific notation.
440
    // Return PARSE_FAILURE on leading whitespace. Trailing whitespace is allowed.
441
    // TODO: Investigate using intrinsics to speed up the slow strtod path.
442
    template <typename T>
443
    static inline T string_to_float_internal(const char* __restrict s, int len,
444
                                             ParseResult* result);
445
446
    // parses a string for 'true' or 'false', case insensitive
447
    // Return PARSE_FAILURE on leading whitespace. Trailing whitespace is allowed.
448
    static inline bool string_to_bool_internal(const char* __restrict s, int len,
449
                                               ParseResult* result);
450
451
    // Returns true if s only contains whitespace.
452
5.08k
    static inline bool is_all_whitespace(const char* __restrict s, int len) {
453
11.7k
        for (int i = 0; i < len; ++i) {
454
10.0k
            if (!LIKELY(is_whitespace_ascii(s[i]))) {
455
3.38k
                return false;
456
3.38k
            }
457
10.0k
        }
458
1.70k
        return true;
459
5.08k
    }
460
461
    // For strings like "3.0", "3.123", and "3.", can parse them as 3.
462
3.93k
    static inline bool is_float_suffix(const char* __restrict s, int len) {
463
3.93k
        return (s[0] == '.' && is_all_digit(s + 1, len - 1));
464
3.93k
    }
465
466
2.92k
    static inline bool is_all_digit(const char* __restrict s, int len) {
467
6.08k
        for (int i = 0; i < len; ++i) {
468
3.30k
            if (!LIKELY(s[i] >= '0' && s[i] <= '9')) {
469
151
                return false;
470
151
            }
471
3.30k
        }
472
2.77k
        return true;
473
2.92k
    }
474
}; // end of class StringParser
475
476
template <typename T, bool enable_strict_mode>
477
473k
T StringParser::string_to_int_internal(const char* __restrict s, int len, ParseResult* result) {
478
473k
    if (UNLIKELY(len <= 0)) {
479
2.37k
        *result = PARSE_FAILURE;
480
2.37k
        return 0;
481
2.37k
    }
482
483
470k
    using UnsignedT = MakeUnsignedT<T>;
484
470k
    UnsignedT val = 0;
485
470k
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
486
470k
    bool negative = false;
487
470k
    int i = 0;
488
470k
    switch (*s) {
489
108k
    case '-':
490
108k
        negative = true;
491
        // Only signed types have an extra value in their negative range.
492
108k
        max_val += std::numeric_limits<T>::is_signed;
493
108k
        [[fallthrough]];
494
112k
    case '+':
495
112k
        ++i;
496
        // only one '+'/'-' char, so could return failure directly
497
112k
        if (UNLIKELY(len == 1)) {
498
4
            *result = PARSE_FAILURE;
499
4
            return 0;
500
4
        }
501
470k
    }
502
503
    // This is the fast path where the string cannot overflow.
504
470k
    if (LIKELY(len - i < NumberTraits::max_ascii_len<T>())) {
505
295k
        val = string_to_int_no_overflow<UnsignedT, enable_strict_mode>(s + i, len - i, result);
506
295k
        return static_cast<T>(negative ? -val : val);
507
295k
    }
508
509
175k
    const T max_div_10 = max_val / 10;
510
175k
    const T max_mod_10 = max_val % 10;
511
512
175k
    int first = i;
513
1.77M
    for (; i < len; ++i) {
514
1.70M
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
515
1.64M
            T digit = s[i] - '0';
516
            // This is a tricky check to see if adding this digit will cause an overflow.
517
1.64M
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
518
50.6k
                *result = PARSE_OVERFLOW;
519
50.6k
                return negative ? -max_val : max_val;
520
50.6k
            }
521
1.59M
            val = val * 10 + digit;
522
1.59M
        } else {
523
51.7k
            if constexpr (enable_strict_mode) {
524
7.26k
                if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
525
                    // Reject the string because the remaining chars are not all whitespace
526
5.91k
                    *result = PARSE_FAILURE;
527
5.91k
                    return 0;
528
5.91k
                }
529
44.4k
            } else {
530
                // Save original position where non-digit was found
531
44.4k
                int remaining_len = len - i;
532
44.4k
                const char* remaining_s = s + i;
533
                // Skip trailing whitespaces from the remaining portion
534
44.4k
                remaining_s = skip_trailing_whitespaces(remaining_s, remaining_len);
535
44.4k
                if ((UNLIKELY(i == first || (remaining_len != 0 &&
536
44.4k
                                             !is_float_suffix(remaining_s, remaining_len))))) {
537
                    // Reject the string because either the first char was not a digit,
538
                    // or the remaining chars are not all whitespace
539
30.6k
                    *result = PARSE_FAILURE;
540
30.6k
                    return 0;
541
30.6k
                }
542
44.4k
            }
543
            // Returning here is slightly faster than breaking the loop.
544
15.2k
            *result = PARSE_SUCCESS;
545
51.7k
            return static_cast<T>(negative ? -val : val);
546
51.7k
        }
547
1.70M
    }
548
73.1k
    *result = PARSE_SUCCESS;
549
73.1k
    return static_cast<T>(negative ? -val : val);
550
175k
}
_ZN5doris12StringParser22string_to_int_internalInLb0EEET_PKciPNS0_11ParseResultE
Line
Count
Source
477
47.4k
T StringParser::string_to_int_internal(const char* __restrict s, int len, ParseResult* result) {
478
47.4k
    if (UNLIKELY(len <= 0)) {
479
44
        *result = PARSE_FAILURE;
480
44
        return 0;
481
44
    }
482
483
47.4k
    using UnsignedT = MakeUnsignedT<T>;
484
47.4k
    UnsignedT val = 0;
485
47.4k
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
486
47.4k
    bool negative = false;
487
47.4k
    int i = 0;
488
47.4k
    switch (*s) {
489
3.64k
    case '-':
490
3.64k
        negative = true;
491
        // Only signed types have an extra value in their negative range.
492
3.64k
        max_val += std::numeric_limits<T>::is_signed;
493
3.64k
        [[fallthrough]];
494
3.93k
    case '+':
495
3.93k
        ++i;
496
        // only one '+'/'-' char, so could return failure directly
497
3.93k
        if (UNLIKELY(len == 1)) {
498
0
            *result = PARSE_FAILURE;
499
0
            return 0;
500
0
        }
501
47.4k
    }
502
503
    // This is the fast path where the string cannot overflow.
504
47.4k
    if (LIKELY(len - i < NumberTraits::max_ascii_len<T>())) {
505
42.7k
        val = string_to_int_no_overflow<UnsignedT, enable_strict_mode>(s + i, len - i, result);
506
42.7k
        return static_cast<T>(negative ? -val : val);
507
42.7k
    }
508
509
4.70k
    const T max_div_10 = max_val / 10;
510
4.70k
    const T max_mod_10 = max_val % 10;
511
512
4.70k
    int first = i;
513
175k
    for (; i < len; ++i) {
514
171k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
515
170k
            T digit = s[i] - '0';
516
            // This is a tricky check to see if adding this digit will cause an overflow.
517
170k
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
518
514
                *result = PARSE_OVERFLOW;
519
514
                return negative ? -max_val : max_val;
520
514
            }
521
170k
            val = val * 10 + digit;
522
170k
        } else {
523
            if constexpr (enable_strict_mode) {
524
                if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
525
                    // Reject the string because the remaining chars are not all whitespace
526
                    *result = PARSE_FAILURE;
527
                    return 0;
528
                }
529
536
            } else {
530
                // Save original position where non-digit was found
531
536
                int remaining_len = len - i;
532
536
                const char* remaining_s = s + i;
533
                // Skip trailing whitespaces from the remaining portion
534
536
                remaining_s = skip_trailing_whitespaces(remaining_s, remaining_len);
535
536
                if ((UNLIKELY(i == first || (remaining_len != 0 &&
536
536
                                             !is_float_suffix(remaining_s, remaining_len))))) {
537
                    // Reject the string because either the first char was not a digit,
538
                    // or the remaining chars are not all whitespace
539
376
                    *result = PARSE_FAILURE;
540
376
                    return 0;
541
376
                }
542
536
            }
543
            // Returning here is slightly faster than breaking the loop.
544
160
            *result = PARSE_SUCCESS;
545
536
            return static_cast<T>(negative ? -val : val);
546
536
        }
547
171k
    }
548
3.65k
    *result = PARSE_SUCCESS;
549
3.65k
    return static_cast<T>(negative ? -val : val);
550
4.70k
}
_ZN5doris12StringParser22string_to_int_internalIaLb0EEET_PKciPNS0_11ParseResultE
Line
Count
Source
477
126k
T StringParser::string_to_int_internal(const char* __restrict s, int len, ParseResult* result) {
478
126k
    if (UNLIKELY(len <= 0)) {
479
218
        *result = PARSE_FAILURE;
480
218
        return 0;
481
218
    }
482
483
125k
    using UnsignedT = MakeUnsignedT<T>;
484
125k
    UnsignedT val = 0;
485
125k
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
486
125k
    bool negative = false;
487
125k
    int i = 0;
488
125k
    switch (*s) {
489
22.6k
    case '-':
490
22.6k
        negative = true;
491
        // Only signed types have an extra value in their negative range.
492
22.6k
        max_val += std::numeric_limits<T>::is_signed;
493
22.6k
        [[fallthrough]];
494
23.0k
    case '+':
495
23.0k
        ++i;
496
        // only one '+'/'-' char, so could return failure directly
497
23.0k
        if (UNLIKELY(len == 1)) {
498
0
            *result = PARSE_FAILURE;
499
0
            return 0;
500
0
        }
501
125k
    }
502
503
    // This is the fast path where the string cannot overflow.
504
125k
    if (LIKELY(len - i < NumberTraits::max_ascii_len<T>())) {
505
61.6k
        val = string_to_int_no_overflow<UnsignedT, enable_strict_mode>(s + i, len - i, result);
506
61.6k
        return static_cast<T>(negative ? -val : val);
507
61.6k
    }
508
509
64.2k
    const T max_div_10 = max_val / 10;
510
64.2k
    const T max_mod_10 = max_val % 10;
511
512
64.2k
    int first = i;
513
154k
    for (; i < len; ++i) {
514
148k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
515
112k
            T digit = s[i] - '0';
516
            // This is a tricky check to see if adding this digit will cause an overflow.
517
112k
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
518
21.3k
                *result = PARSE_OVERFLOW;
519
21.3k
                return negative ? -max_val : max_val;
520
21.3k
            }
521
90.7k
            val = val * 10 + digit;
522
90.7k
        } else {
523
            if constexpr (enable_strict_mode) {
524
                if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
525
                    // Reject the string because the remaining chars are not all whitespace
526
                    *result = PARSE_FAILURE;
527
                    return 0;
528
                }
529
35.9k
            } else {
530
                // Save original position where non-digit was found
531
35.9k
                int remaining_len = len - i;
532
35.9k
                const char* remaining_s = s + i;
533
                // Skip trailing whitespaces from the remaining portion
534
35.9k
                remaining_s = skip_trailing_whitespaces(remaining_s, remaining_len);
535
35.9k
                if ((UNLIKELY(i == first || (remaining_len != 0 &&
536
35.9k
                                             !is_float_suffix(remaining_s, remaining_len))))) {
537
                    // Reject the string because either the first char was not a digit,
538
                    // or the remaining chars are not all whitespace
539
24.5k
                    *result = PARSE_FAILURE;
540
24.5k
                    return 0;
541
24.5k
                }
542
35.9k
            }
543
            // Returning here is slightly faster than breaking the loop.
544
11.4k
            *result = PARSE_SUCCESS;
545
35.9k
            return static_cast<T>(negative ? -val : val);
546
35.9k
        }
547
148k
    }
548
6.89k
    *result = PARSE_SUCCESS;
549
6.89k
    return static_cast<T>(negative ? -val : val);
550
64.2k
}
_ZN5doris12StringParser22string_to_int_internalIaLb1EEET_PKciPNS0_11ParseResultE
Line
Count
Source
477
2.70k
T StringParser::string_to_int_internal(const char* __restrict s, int len, ParseResult* result) {
478
2.70k
    if (UNLIKELY(len <= 0)) {
479
8
        *result = PARSE_FAILURE;
480
8
        return 0;
481
8
    }
482
483
2.69k
    using UnsignedT = MakeUnsignedT<T>;
484
2.69k
    UnsignedT val = 0;
485
2.69k
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
486
2.69k
    bool negative = false;
487
2.69k
    int i = 0;
488
2.69k
    switch (*s) {
489
1.02k
    case '-':
490
1.02k
        negative = true;
491
        // Only signed types have an extra value in their negative range.
492
1.02k
        max_val += std::numeric_limits<T>::is_signed;
493
1.02k
        [[fallthrough]];
494
1.38k
    case '+':
495
1.38k
        ++i;
496
        // only one '+'/'-' char, so could return failure directly
497
1.38k
        if (UNLIKELY(len == 1)) {
498
0
            *result = PARSE_FAILURE;
499
0
            return 0;
500
0
        }
501
2.69k
    }
502
503
    // This is the fast path where the string cannot overflow.
504
2.69k
    if (LIKELY(len - i < NumberTraits::max_ascii_len<T>())) {
505
478
        val = string_to_int_no_overflow<UnsignedT, enable_strict_mode>(s + i, len - i, result);
506
478
        return static_cast<T>(negative ? -val : val);
507
478
    }
508
509
2.21k
    const T max_div_10 = max_val / 10;
510
2.21k
    const T max_mod_10 = max_val % 10;
511
512
2.21k
    int first = i;
513
7.59k
    for (; i < len; ++i) {
514
7.43k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
515
6.03k
            T digit = s[i] - '0';
516
            // This is a tricky check to see if adding this digit will cause an overflow.
517
6.03k
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
518
656
                *result = PARSE_OVERFLOW;
519
656
                return negative ? -max_val : max_val;
520
656
            }
521
5.37k
            val = val * 10 + digit;
522
5.37k
        } else {
523
1.40k
            if constexpr (enable_strict_mode) {
524
1.40k
                if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
525
                    // Reject the string because the remaining chars are not all whitespace
526
1.22k
                    *result = PARSE_FAILURE;
527
1.22k
                    return 0;
528
1.22k
                }
529
            } else {
530
                // Save original position where non-digit was found
531
                int remaining_len = len - i;
532
                const char* remaining_s = s + i;
533
                // Skip trailing whitespaces from the remaining portion
534
                remaining_s = skip_trailing_whitespaces(remaining_s, remaining_len);
535
                if ((UNLIKELY(i == first || (remaining_len != 0 &&
536
                                             !is_float_suffix(remaining_s, remaining_len))))) {
537
                    // Reject the string because either the first char was not a digit,
538
                    // or the remaining chars are not all whitespace
539
                    *result = PARSE_FAILURE;
540
                    return 0;
541
                }
542
            }
543
            // Returning here is slightly faster than breaking the loop.
544
172
            *result = PARSE_SUCCESS;
545
1.40k
            return static_cast<T>(negative ? -val : val);
546
1.40k
        }
547
7.43k
    }
548
162
    *result = PARSE_SUCCESS;
549
162
    return static_cast<T>(negative ? -val : val);
550
2.21k
}
_ZN5doris12StringParser22string_to_int_internalIsLb0EEET_PKciPNS0_11ParseResultE
Line
Count
Source
477
75.6k
T StringParser::string_to_int_internal(const char* __restrict s, int len, ParseResult* result) {
478
75.6k
    if (UNLIKELY(len <= 0)) {
479
8
        *result = PARSE_FAILURE;
480
8
        return 0;
481
8
    }
482
483
75.6k
    using UnsignedT = MakeUnsignedT<T>;
484
75.6k
    UnsignedT val = 0;
485
75.6k
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
486
75.6k
    bool negative = false;
487
75.6k
    int i = 0;
488
75.6k
    switch (*s) {
489
13.0k
    case '-':
490
13.0k
        negative = true;
491
        // Only signed types have an extra value in their negative range.
492
13.0k
        max_val += std::numeric_limits<T>::is_signed;
493
13.0k
        [[fallthrough]];
494
13.3k
    case '+':
495
13.3k
        ++i;
496
        // only one '+'/'-' char, so could return failure directly
497
13.3k
        if (UNLIKELY(len == 1)) {
498
0
            *result = PARSE_FAILURE;
499
0
            return 0;
500
0
        }
501
75.6k
    }
502
503
    // This is the fast path where the string cannot overflow.
504
75.6k
    if (LIKELY(len - i < NumberTraits::max_ascii_len<T>())) {
505
51.6k
        val = string_to_int_no_overflow<UnsignedT, enable_strict_mode>(s + i, len - i, result);
506
51.6k
        return static_cast<T>(negative ? -val : val);
507
51.6k
    }
508
509
23.9k
    const T max_div_10 = max_val / 10;
510
23.9k
    const T max_mod_10 = max_val % 10;
511
512
23.9k
    int first = i;
513
124k
    for (; i < len; ++i) {
514
115k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
515
113k
            T digit = s[i] - '0';
516
            // This is a tricky check to see if adding this digit will cause an overflow.
517
113k
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
518
13.0k
                *result = PARSE_OVERFLOW;
519
13.0k
                return negative ? -max_val : max_val;
520
13.0k
            }
521
100k
            val = val * 10 + digit;
522
100k
        } else {
523
            if constexpr (enable_strict_mode) {
524
                if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
525
                    // Reject the string because the remaining chars are not all whitespace
526
                    *result = PARSE_FAILURE;
527
                    return 0;
528
                }
529
1.90k
            } else {
530
                // Save original position where non-digit was found
531
1.90k
                int remaining_len = len - i;
532
1.90k
                const char* remaining_s = s + i;
533
                // Skip trailing whitespaces from the remaining portion
534
1.90k
                remaining_s = skip_trailing_whitespaces(remaining_s, remaining_len);
535
1.90k
                if ((UNLIKELY(i == first || (remaining_len != 0 &&
536
1.90k
                                             !is_float_suffix(remaining_s, remaining_len))))) {
537
                    // Reject the string because either the first char was not a digit,
538
                    // or the remaining chars are not all whitespace
539
1.29k
                    *result = PARSE_FAILURE;
540
1.29k
                    return 0;
541
1.29k
                }
542
1.90k
            }
543
            // Returning here is slightly faster than breaking the loop.
544
610
            *result = PARSE_SUCCESS;
545
1.90k
            return static_cast<T>(negative ? -val : val);
546
1.90k
        }
547
115k
    }
548
8.93k
    *result = PARSE_SUCCESS;
549
8.93k
    return static_cast<T>(negative ? -val : val);
550
23.9k
}
_ZN5doris12StringParser22string_to_int_internalIsLb1EEET_PKciPNS0_11ParseResultE
Line
Count
Source
477
2.38k
T StringParser::string_to_int_internal(const char* __restrict s, int len, ParseResult* result) {
478
2.38k
    if (UNLIKELY(len <= 0)) {
479
8
        *result = PARSE_FAILURE;
480
8
        return 0;
481
8
    }
482
483
2.37k
    using UnsignedT = MakeUnsignedT<T>;
484
2.37k
    UnsignedT val = 0;
485
2.37k
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
486
2.37k
    bool negative = false;
487
2.37k
    int i = 0;
488
2.37k
    switch (*s) {
489
630
    case '-':
490
630
        negative = true;
491
        // Only signed types have an extra value in their negative range.
492
630
        max_val += std::numeric_limits<T>::is_signed;
493
630
        [[fallthrough]];
494
980
    case '+':
495
980
        ++i;
496
        // only one '+'/'-' char, so could return failure directly
497
980
        if (UNLIKELY(len == 1)) {
498
0
            *result = PARSE_FAILURE;
499
0
            return 0;
500
0
        }
501
2.37k
    }
502
503
    // This is the fast path where the string cannot overflow.
504
2.37k
    if (LIKELY(len - i < NumberTraits::max_ascii_len<T>())) {
505
648
        val = string_to_int_no_overflow<UnsignedT, enable_strict_mode>(s + i, len - i, result);
506
648
        return static_cast<T>(negative ? -val : val);
507
648
    }
508
509
1.72k
    const T max_div_10 = max_val / 10;
510
1.72k
    const T max_mod_10 = max_val % 10;
511
512
1.72k
    int first = i;
513
7.99k
    for (; i < len; ++i) {
514
7.93k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
515
6.84k
            T digit = s[i] - '0';
516
            // This is a tricky check to see if adding this digit will cause an overflow.
517
6.84k
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
518
576
                *result = PARSE_OVERFLOW;
519
576
                return negative ? -max_val : max_val;
520
576
            }
521
6.27k
            val = val * 10 + digit;
522
6.27k
        } else {
523
1.08k
            if constexpr (enable_strict_mode) {
524
1.08k
                if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
525
                    // Reject the string because the remaining chars are not all whitespace
526
1.00k
                    *result = PARSE_FAILURE;
527
1.00k
                    return 0;
528
1.00k
                }
529
            } else {
530
                // Save original position where non-digit was found
531
                int remaining_len = len - i;
532
                const char* remaining_s = s + i;
533
                // Skip trailing whitespaces from the remaining portion
534
                remaining_s = skip_trailing_whitespaces(remaining_s, remaining_len);
535
                if ((UNLIKELY(i == first || (remaining_len != 0 &&
536
                                             !is_float_suffix(remaining_s, remaining_len))))) {
537
                    // Reject the string because either the first char was not a digit,
538
                    // or the remaining chars are not all whitespace
539
                    *result = PARSE_FAILURE;
540
                    return 0;
541
                }
542
            }
543
            // Returning here is slightly faster than breaking the loop.
544
88
            *result = PARSE_SUCCESS;
545
1.08k
            return static_cast<T>(negative ? -val : val);
546
1.08k
        }
547
7.93k
    }
548
60
    *result = PARSE_SUCCESS;
549
60
    return static_cast<T>(negative ? -val : val);
550
1.72k
}
_ZN5doris12StringParser22string_to_int_internalIiLb0EEET_PKciPNS0_11ParseResultE
Line
Count
Source
477
115k
T StringParser::string_to_int_internal(const char* __restrict s, int len, ParseResult* result) {
478
115k
    if (UNLIKELY(len <= 0)) {
479
2.04k
        *result = PARSE_FAILURE;
480
2.04k
        return 0;
481
2.04k
    }
482
483
113k
    using UnsignedT = MakeUnsignedT<T>;
484
113k
    UnsignedT val = 0;
485
113k
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
486
113k
    bool negative = false;
487
113k
    int i = 0;
488
113k
    switch (*s) {
489
10.9k
    case '-':
490
10.9k
        negative = true;
491
        // Only signed types have an extra value in their negative range.
492
10.9k
        max_val += std::numeric_limits<T>::is_signed;
493
10.9k
        [[fallthrough]];
494
11.3k
    case '+':
495
11.3k
        ++i;
496
        // only one '+'/'-' char, so could return failure directly
497
11.3k
        if (UNLIKELY(len == 1)) {
498
2
            *result = PARSE_FAILURE;
499
2
            return 0;
500
2
        }
501
113k
    }
502
503
    // This is the fast path where the string cannot overflow.
504
113k
    if (LIKELY(len - i < NumberTraits::max_ascii_len<T>())) {
505
99.7k
        val = string_to_int_no_overflow<UnsignedT, enable_strict_mode>(s + i, len - i, result);
506
99.7k
        return static_cast<T>(negative ? -val : val);
507
99.7k
    }
508
509
13.6k
    const T max_div_10 = max_val / 10;
510
13.6k
    const T max_mod_10 = max_val % 10;
511
512
13.6k
    int first = i;
513
130k
    for (; i < len; ++i) {
514
124k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
515
122k
            T digit = s[i] - '0';
516
            // This is a tricky check to see if adding this digit will cause an overflow.
517
122k
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
518
5.87k
                *result = PARSE_OVERFLOW;
519
5.87k
                return negative ? -max_val : max_val;
520
5.87k
            }
521
116k
            val = val * 10 + digit;
522
116k
        } else {
523
            if constexpr (enable_strict_mode) {
524
                if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
525
                    // Reject the string because the remaining chars are not all whitespace
526
                    *result = PARSE_FAILURE;
527
                    return 0;
528
                }
529
1.90k
            } else {
530
                // Save original position where non-digit was found
531
1.90k
                int remaining_len = len - i;
532
1.90k
                const char* remaining_s = s + i;
533
                // Skip trailing whitespaces from the remaining portion
534
1.90k
                remaining_s = skip_trailing_whitespaces(remaining_s, remaining_len);
535
1.90k
                if ((UNLIKELY(i == first || (remaining_len != 0 &&
536
1.90k
                                             !is_float_suffix(remaining_s, remaining_len))))) {
537
                    // Reject the string because either the first char was not a digit,
538
                    // or the remaining chars are not all whitespace
539
1.51k
                    *result = PARSE_FAILURE;
540
1.51k
                    return 0;
541
1.51k
                }
542
1.90k
            }
543
            // Returning here is slightly faster than breaking the loop.
544
386
            *result = PARSE_SUCCESS;
545
1.90k
            return static_cast<T>(negative ? -val : val);
546
1.90k
        }
547
124k
    }
548
5.91k
    *result = PARSE_SUCCESS;
549
5.91k
    return static_cast<T>(negative ? -val : val);
550
13.6k
}
_ZN5doris12StringParser22string_to_int_internalIiLb1EEET_PKciPNS0_11ParseResultE
Line
Count
Source
477
2.54k
T StringParser::string_to_int_internal(const char* __restrict s, int len, ParseResult* result) {
478
2.54k
    if (UNLIKELY(len <= 0)) {
479
8
        *result = PARSE_FAILURE;
480
8
        return 0;
481
8
    }
482
483
2.53k
    using UnsignedT = MakeUnsignedT<T>;
484
2.53k
    UnsignedT val = 0;
485
2.53k
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
486
2.53k
    bool negative = false;
487
2.53k
    int i = 0;
488
2.53k
    switch (*s) {
489
621
    case '-':
490
621
        negative = true;
491
        // Only signed types have an extra value in their negative range.
492
621
        max_val += std::numeric_limits<T>::is_signed;
493
621
        [[fallthrough]];
494
965
    case '+':
495
965
        ++i;
496
        // only one '+'/'-' char, so could return failure directly
497
965
        if (UNLIKELY(len == 1)) {
498
0
            *result = PARSE_FAILURE;
499
0
            return 0;
500
0
        }
501
2.53k
    }
502
503
    // This is the fast path where the string cannot overflow.
504
2.53k
    if (LIKELY(len - i < NumberTraits::max_ascii_len<T>())) {
505
1.12k
        val = string_to_int_no_overflow<UnsignedT, enable_strict_mode>(s + i, len - i, result);
506
1.12k
        return static_cast<T>(negative ? -val : val);
507
1.12k
    }
508
509
1.40k
    const T max_div_10 = max_val / 10;
510
1.40k
    const T max_mod_10 = max_val % 10;
511
512
1.40k
    int first = i;
513
11.0k
    for (; i < len; ++i) {
514
10.9k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
515
10.1k
            T digit = s[i] - '0';
516
            // This is a tricky check to see if adding this digit will cause an overflow.
517
10.1k
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
518
552
                *result = PARSE_OVERFLOW;
519
552
                return negative ? -max_val : max_val;
520
552
            }
521
9.60k
            val = val * 10 + digit;
522
9.60k
        } else {
523
795
            if constexpr (enable_strict_mode) {
524
795
                if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
525
                    // Reject the string because the remaining chars are not all whitespace
526
735
                    *result = PARSE_FAILURE;
527
735
                    return 0;
528
735
                }
529
            } else {
530
                // Save original position where non-digit was found
531
                int remaining_len = len - i;
532
                const char* remaining_s = s + i;
533
                // Skip trailing whitespaces from the remaining portion
534
                remaining_s = skip_trailing_whitespaces(remaining_s, remaining_len);
535
                if ((UNLIKELY(i == first || (remaining_len != 0 &&
536
                                             !is_float_suffix(remaining_s, remaining_len))))) {
537
                    // Reject the string because either the first char was not a digit,
538
                    // or the remaining chars are not all whitespace
539
                    *result = PARSE_FAILURE;
540
                    return 0;
541
                }
542
            }
543
            // Returning here is slightly faster than breaking the loop.
544
60
            *result = PARSE_SUCCESS;
545
795
            return static_cast<T>(negative ? -val : val);
546
795
        }
547
10.9k
    }
548
58
    *result = PARSE_SUCCESS;
549
58
    return static_cast<T>(negative ? -val : val);
550
1.40k
}
_ZN5doris12StringParser22string_to_int_internalIlLb0EEET_PKciPNS0_11ParseResultE
Line
Count
Source
477
87.0k
T StringParser::string_to_int_internal(const char* __restrict s, int len, ParseResult* result) {
478
87.0k
    if (UNLIKELY(len <= 0)) {
479
14
        *result = PARSE_FAILURE;
480
14
        return 0;
481
14
    }
482
483
87.0k
    using UnsignedT = MakeUnsignedT<T>;
484
87.0k
    UnsignedT val = 0;
485
87.0k
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
486
87.0k
    bool negative = false;
487
87.0k
    int i = 0;
488
87.0k
    switch (*s) {
489
50.9k
    case '-':
490
50.9k
        negative = true;
491
        // Only signed types have an extra value in their negative range.
492
50.9k
        max_val += std::numeric_limits<T>::is_signed;
493
50.9k
        [[fallthrough]];
494
51.3k
    case '+':
495
51.3k
        ++i;
496
        // only one '+'/'-' char, so could return failure directly
497
51.3k
        if (UNLIKELY(len == 1)) {
498
0
            *result = PARSE_FAILURE;
499
0
            return 0;
500
0
        }
501
87.0k
    }
502
503
    // This is the fast path where the string cannot overflow.
504
87.0k
    if (LIKELY(len - i < NumberTraits::max_ascii_len<T>())) {
505
33.1k
        val = string_to_int_no_overflow<UnsignedT, enable_strict_mode>(s + i, len - i, result);
506
33.1k
        return static_cast<T>(negative ? -val : val);
507
33.1k
    }
508
509
53.8k
    const T max_div_10 = max_val / 10;
510
53.8k
    const T max_mod_10 = max_val % 10;
511
512
53.8k
    int first = i;
513
1.05M
    for (; i < len; ++i) {
514
1.00M
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
515
1.00M
            T digit = s[i] - '0';
516
            // This is a tricky check to see if adding this digit will cause an overflow.
517
1.00M
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
518
5.28k
                *result = PARSE_OVERFLOW;
519
5.28k
                return negative ? -max_val : max_val;
520
5.28k
            }
521
996k
            val = val * 10 + digit;
522
996k
        } else {
523
            if constexpr (enable_strict_mode) {
524
                if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
525
                    // Reject the string because the remaining chars are not all whitespace
526
                    *result = PARSE_FAILURE;
527
                    return 0;
528
                }
529
1.49k
            } else {
530
                // Save original position where non-digit was found
531
1.49k
                int remaining_len = len - i;
532
1.49k
                const char* remaining_s = s + i;
533
                // Skip trailing whitespaces from the remaining portion
534
1.49k
                remaining_s = skip_trailing_whitespaces(remaining_s, remaining_len);
535
1.49k
                if ((UNLIKELY(i == first || (remaining_len != 0 &&
536
1.49k
                                             !is_float_suffix(remaining_s, remaining_len))))) {
537
                    // Reject the string because either the first char was not a digit,
538
                    // or the remaining chars are not all whitespace
539
1.24k
                    *result = PARSE_FAILURE;
540
1.24k
                    return 0;
541
1.24k
                }
542
1.49k
            }
543
            // Returning here is slightly faster than breaking the loop.
544
244
            *result = PARSE_SUCCESS;
545
1.49k
            return static_cast<T>(negative ? -val : val);
546
1.49k
        }
547
1.00M
    }
548
47.1k
    *result = PARSE_SUCCESS;
549
47.1k
    return static_cast<T>(negative ? -val : val);
550
53.8k
}
_ZN5doris12StringParser22string_to_int_internalIlLb1EEET_PKciPNS0_11ParseResultE
Line
Count
Source
477
2.61k
T StringParser::string_to_int_internal(const char* __restrict s, int len, ParseResult* result) {
478
2.61k
    if (UNLIKELY(len <= 0)) {
479
10
        *result = PARSE_FAILURE;
480
10
        return 0;
481
10
    }
482
483
2.60k
    using UnsignedT = MakeUnsignedT<T>;
484
2.60k
    UnsignedT val = 0;
485
2.60k
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
486
2.60k
    bool negative = false;
487
2.60k
    int i = 0;
488
2.60k
    switch (*s) {
489
713
    case '-':
490
713
        negative = true;
491
        // Only signed types have an extra value in their negative range.
492
713
        max_val += std::numeric_limits<T>::is_signed;
493
713
        [[fallthrough]];
494
1.05k
    case '+':
495
1.05k
        ++i;
496
        // only one '+'/'-' char, so could return failure directly
497
1.05k
        if (UNLIKELY(len == 1)) {
498
2
            *result = PARSE_FAILURE;
499
2
            return 0;
500
2
        }
501
2.60k
    }
502
503
    // This is the fast path where the string cannot overflow.
504
2.60k
    if (LIKELY(len - i < NumberTraits::max_ascii_len<T>())) {
505
1.21k
        val = string_to_int_no_overflow<UnsignedT, enable_strict_mode>(s + i, len - i, result);
506
1.21k
        return static_cast<T>(negative ? -val : val);
507
1.21k
    }
508
509
1.38k
    const T max_div_10 = max_val / 10;
510
1.38k
    const T max_mod_10 = max_val % 10;
511
512
1.38k
    int first = i;
513
20.4k
    for (; i < len; ++i) {
514
20.3k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
515
19.6k
            T digit = s[i] - '0';
516
            // This is a tricky check to see if adding this digit will cause an overflow.
517
19.6k
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
518
584
                *result = PARSE_OVERFLOW;
519
584
                return negative ? -max_val : max_val;
520
584
            }
521
19.0k
            val = val * 10 + digit;
522
19.0k
        } else {
523
733
            if constexpr (enable_strict_mode) {
524
733
                if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
525
                    // Reject the string because the remaining chars are not all whitespace
526
617
                    *result = PARSE_FAILURE;
527
617
                    return 0;
528
617
                }
529
            } else {
530
                // Save original position where non-digit was found
531
                int remaining_len = len - i;
532
                const char* remaining_s = s + i;
533
                // Skip trailing whitespaces from the remaining portion
534
                remaining_s = skip_trailing_whitespaces(remaining_s, remaining_len);
535
                if ((UNLIKELY(i == first || (remaining_len != 0 &&
536
                                             !is_float_suffix(remaining_s, remaining_len))))) {
537
                    // Reject the string because either the first char was not a digit,
538
                    // or the remaining chars are not all whitespace
539
                    *result = PARSE_FAILURE;
540
                    return 0;
541
                }
542
            }
543
            // Returning here is slightly faster than breaking the loop.
544
116
            *result = PARSE_SUCCESS;
545
733
            return static_cast<T>(negative ? -val : val);
546
733
        }
547
20.3k
    }
548
66
    *result = PARSE_SUCCESS;
549
66
    return static_cast<T>(negative ? -val : val);
550
1.38k
}
_ZN5doris12StringParser22string_to_int_internalInLb1EEET_PKciPNS0_11ParseResultE
Line
Count
Source
477
2.37k
T StringParser::string_to_int_internal(const char* __restrict s, int len, ParseResult* result) {
478
2.37k
    if (UNLIKELY(len <= 0)) {
479
8
        *result = PARSE_FAILURE;
480
8
        return 0;
481
8
    }
482
483
2.36k
    using UnsignedT = MakeUnsignedT<T>;
484
2.36k
    UnsignedT val = 0;
485
2.36k
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
486
2.36k
    bool negative = false;
487
2.36k
    int i = 0;
488
2.36k
    switch (*s) {
489
643
    case '-':
490
643
        negative = true;
491
        // Only signed types have an extra value in their negative range.
492
643
        max_val += std::numeric_limits<T>::is_signed;
493
643
        [[fallthrough]];
494
975
    case '+':
495
975
        ++i;
496
        // only one '+'/'-' char, so could return failure directly
497
975
        if (UNLIKELY(len == 1)) {
498
0
            *result = PARSE_FAILURE;
499
0
            return 0;
500
0
        }
501
2.36k
    }
502
503
    // This is the fast path where the string cannot overflow.
504
2.36k
    if (LIKELY(len - i < NumberTraits::max_ascii_len<T>())) {
505
1.23k
        val = string_to_int_no_overflow<UnsignedT, enable_strict_mode>(s + i, len - i, result);
506
1.23k
        return static_cast<T>(negative ? -val : val);
507
1.23k
    }
508
509
1.13k
    const T max_div_10 = max_val / 10;
510
1.13k
    const T max_mod_10 = max_val % 10;
511
512
1.13k
    int first = i;
513
34.1k
    for (; i < len; ++i) {
514
34.0k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
515
33.4k
            T digit = s[i] - '0';
516
            // This is a tricky check to see if adding this digit will cause an overflow.
517
33.4k
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
518
504
                *result = PARSE_OVERFLOW;
519
504
                return negative ? -max_val : max_val;
520
504
            }
521
32.9k
            val = val * 10 + digit;
522
32.9k
        } else {
523
572
            if constexpr (enable_strict_mode) {
524
572
                if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
525
                    // Reject the string because the remaining chars are not all whitespace
526
498
                    *result = PARSE_FAILURE;
527
498
                    return 0;
528
498
                }
529
            } else {
530
                // Save original position where non-digit was found
531
                int remaining_len = len - i;
532
                const char* remaining_s = s + i;
533
                // Skip trailing whitespaces from the remaining portion
534
                remaining_s = skip_trailing_whitespaces(remaining_s, remaining_len);
535
                if ((UNLIKELY(i == first || (remaining_len != 0 &&
536
                                             !is_float_suffix(remaining_s, remaining_len))))) {
537
                    // Reject the string because either the first char was not a digit,
538
                    // or the remaining chars are not all whitespace
539
                    *result = PARSE_FAILURE;
540
                    return 0;
541
                }
542
            }
543
            // Returning here is slightly faster than breaking the loop.
544
74
            *result = PARSE_SUCCESS;
545
572
            return static_cast<T>(negative ? -val : val);
546
572
        }
547
34.0k
    }
548
59
    *result = PARSE_SUCCESS;
549
59
    return static_cast<T>(negative ? -val : val);
550
1.13k
}
_ZN5doris12StringParser22string_to_int_internalIjLb1EEET_PKciPNS0_11ParseResultE
Line
Count
Source
477
1.02k
T StringParser::string_to_int_internal(const char* __restrict s, int len, ParseResult* result) {
478
1.02k
    if (UNLIKELY(len <= 0)) {
479
2
        *result = PARSE_FAILURE;
480
2
        return 0;
481
2
    }
482
483
1.01k
    using UnsignedT = MakeUnsignedT<T>;
484
1.01k
    UnsignedT val = 0;
485
1.01k
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
486
1.01k
    bool negative = false;
487
1.01k
    int i = 0;
488
1.01k
    switch (*s) {
489
364
    case '-':
490
364
        negative = true;
491
        // Only signed types have an extra value in their negative range.
492
364
        max_val += std::numeric_limits<T>::is_signed;
493
364
        [[fallthrough]];
494
364
    case '+':
495
364
        ++i;
496
        // only one '+'/'-' char, so could return failure directly
497
364
        if (UNLIKELY(len == 1)) {
498
0
            *result = PARSE_FAILURE;
499
0
            return 0;
500
0
        }
501
1.01k
    }
502
503
    // This is the fast path where the string cannot overflow.
504
1.01k
    if (LIKELY(len - i < NumberTraits::max_ascii_len<T>())) {
505
415
        val = string_to_int_no_overflow<UnsignedT, enable_strict_mode>(s + i, len - i, result);
506
415
        return static_cast<T>(negative ? -val : val);
507
415
    }
508
509
603
    const T max_div_10 = max_val / 10;
510
603
    const T max_mod_10 = max_val % 10;
511
512
603
    int first = i;
513
4.07k
    for (; i < len; ++i) {
514
4.05k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
515
3.64k
            T digit = s[i] - '0';
516
            // This is a tricky check to see if adding this digit will cause an overflow.
517
3.64k
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
518
168
                *result = PARSE_OVERFLOW;
519
168
                return negative ? -max_val : max_val;
520
168
            }
521
3.47k
            val = val * 10 + digit;
522
3.47k
        } else {
523
414
            if constexpr (enable_strict_mode) {
524
414
                if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
525
                    // Reject the string because the remaining chars are not all whitespace
526
288
                    *result = PARSE_FAILURE;
527
288
                    return 0;
528
288
                }
529
            } else {
530
                // Save original position where non-digit was found
531
                int remaining_len = len - i;
532
                const char* remaining_s = s + i;
533
                // Skip trailing whitespaces from the remaining portion
534
                remaining_s = skip_trailing_whitespaces(remaining_s, remaining_len);
535
                if ((UNLIKELY(i == first || (remaining_len != 0 &&
536
                                             !is_float_suffix(remaining_s, remaining_len))))) {
537
                    // Reject the string because either the first char was not a digit,
538
                    // or the remaining chars are not all whitespace
539
                    *result = PARSE_FAILURE;
540
                    return 0;
541
                }
542
            }
543
            // Returning here is slightly faster than breaking the loop.
544
126
            *result = PARSE_SUCCESS;
545
414
            return static_cast<T>(negative ? -val : val);
546
414
        }
547
4.05k
    }
548
21
    *result = PARSE_SUCCESS;
549
21
    return static_cast<T>(negative ? -val : val);
550
603
}
_ZN5doris12StringParser22string_to_int_internalIhLb0EEET_PKciPNS0_11ParseResultE
Line
Count
Source
477
840
T StringParser::string_to_int_internal(const char* __restrict s, int len, ParseResult* result) {
478
840
    if (UNLIKELY(len <= 0)) {
479
0
        *result = PARSE_FAILURE;
480
0
        return 0;
481
0
    }
482
483
840
    using UnsignedT = MakeUnsignedT<T>;
484
840
    UnsignedT val = 0;
485
840
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
486
840
    bool negative = false;
487
840
    int i = 0;
488
840
    switch (*s) {
489
357
    case '-':
490
357
        negative = true;
491
        // Only signed types have an extra value in their negative range.
492
357
        max_val += std::numeric_limits<T>::is_signed;
493
357
        [[fallthrough]];
494
357
    case '+':
495
357
        ++i;
496
        // only one '+'/'-' char, so could return failure directly
497
357
        if (UNLIKELY(len == 1)) {
498
0
            *result = PARSE_FAILURE;
499
0
            return 0;
500
0
        }
501
840
    }
502
503
    // This is the fast path where the string cannot overflow.
504
840
    if (LIKELY(len - i < NumberTraits::max_ascii_len<T>())) {
505
0
        val = string_to_int_no_overflow<UnsignedT, enable_strict_mode>(s + i, len - i, result);
506
0
        return static_cast<T>(negative ? -val : val);
507
0
    }
508
509
840
    const T max_div_10 = max_val / 10;
510
840
    const T max_mod_10 = max_val % 10;
511
512
840
    int first = i;
513
2.69k
    for (; i < len; ++i) {
514
2.66k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
515
2.02k
            T digit = s[i] - '0';
516
            // This is a tricky check to see if adding this digit will cause an overflow.
517
2.02k
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
518
168
                *result = PARSE_OVERFLOW;
519
168
                return negative ? -max_val : max_val;
520
168
            }
521
1.85k
            val = val * 10 + digit;
522
1.85k
        } else {
523
            if constexpr (enable_strict_mode) {
524
                if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
525
                    // Reject the string because the remaining chars are not all whitespace
526
                    *result = PARSE_FAILURE;
527
                    return 0;
528
                }
529
637
            } else {
530
                // Save original position where non-digit was found
531
637
                int remaining_len = len - i;
532
637
                const char* remaining_s = s + i;
533
                // Skip trailing whitespaces from the remaining portion
534
637
                remaining_s = skip_trailing_whitespaces(remaining_s, remaining_len);
535
637
                if ((UNLIKELY(i == first || (remaining_len != 0 &&
536
637
                                             !is_float_suffix(remaining_s, remaining_len))))) {
537
                    // Reject the string because either the first char was not a digit,
538
                    // or the remaining chars are not all whitespace
539
378
                    *result = PARSE_FAILURE;
540
378
                    return 0;
541
378
                }
542
637
            }
543
            // Returning here is slightly faster than breaking the loop.
544
259
            *result = PARSE_SUCCESS;
545
637
            return static_cast<T>(negative ? -val : val);
546
637
        }
547
2.66k
    }
548
35
    *result = PARSE_SUCCESS;
549
35
    return static_cast<T>(negative ? -val : val);
550
840
}
_ZN5doris12StringParser22string_to_int_internalItLb0EEET_PKciPNS0_11ParseResultE
Line
Count
Source
477
840
T StringParser::string_to_int_internal(const char* __restrict s, int len, ParseResult* result) {
478
840
    if (UNLIKELY(len <= 0)) {
479
0
        *result = PARSE_FAILURE;
480
0
        return 0;
481
0
    }
482
483
840
    using UnsignedT = MakeUnsignedT<T>;
484
840
    UnsignedT val = 0;
485
840
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
486
840
    bool negative = false;
487
840
    int i = 0;
488
840
    switch (*s) {
489
357
    case '-':
490
357
        negative = true;
491
        // Only signed types have an extra value in their negative range.
492
357
        max_val += std::numeric_limits<T>::is_signed;
493
357
        [[fallthrough]];
494
357
    case '+':
495
357
        ++i;
496
        // only one '+'/'-' char, so could return failure directly
497
357
        if (UNLIKELY(len == 1)) {
498
0
            *result = PARSE_FAILURE;
499
0
            return 0;
500
0
        }
501
840
    }
502
503
    // This is the fast path where the string cannot overflow.
504
840
    if (LIKELY(len - i < NumberTraits::max_ascii_len<T>())) {
505
63
        val = string_to_int_no_overflow<UnsignedT, enable_strict_mode>(s + i, len - i, result);
506
63
        return static_cast<T>(negative ? -val : val);
507
63
    }
508
509
777
    const T max_div_10 = max_val / 10;
510
777
    const T max_mod_10 = max_val % 10;
511
512
777
    int first = i;
513
3.08k
    for (; i < len; ++i) {
514
3.06k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
515
2.47k
            T digit = s[i] - '0';
516
            // This is a tricky check to see if adding this digit will cause an overflow.
517
2.47k
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
518
168
                *result = PARSE_OVERFLOW;
519
168
                return negative ? -max_val : max_val;
520
168
            }
521
2.31k
            val = val * 10 + digit;
522
2.31k
        } else {
523
            if constexpr (enable_strict_mode) {
524
                if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
525
                    // Reject the string because the remaining chars are not all whitespace
526
                    *result = PARSE_FAILURE;
527
                    return 0;
528
                }
529
588
            } else {
530
                // Save original position where non-digit was found
531
588
                int remaining_len = len - i;
532
588
                const char* remaining_s = s + i;
533
                // Skip trailing whitespaces from the remaining portion
534
588
                remaining_s = skip_trailing_whitespaces(remaining_s, remaining_len);
535
588
                if ((UNLIKELY(i == first || (remaining_len != 0 &&
536
588
                                             !is_float_suffix(remaining_s, remaining_len))))) {
537
                    // Reject the string because either the first char was not a digit,
538
                    // or the remaining chars are not all whitespace
539
378
                    *result = PARSE_FAILURE;
540
378
                    return 0;
541
378
                }
542
588
            }
543
            // Returning here is slightly faster than breaking the loop.
544
210
            *result = PARSE_SUCCESS;
545
588
            return static_cast<T>(negative ? -val : val);
546
588
        }
547
3.06k
    }
548
21
    *result = PARSE_SUCCESS;
549
21
    return static_cast<T>(negative ? -val : val);
550
777
}
_ZN5doris12StringParser22string_to_int_internalIjLb0EEET_PKciPNS0_11ParseResultE
Line
Count
Source
477
841
T StringParser::string_to_int_internal(const char* __restrict s, int len, ParseResult* result) {
478
841
    if (UNLIKELY(len <= 0)) {
479
0
        *result = PARSE_FAILURE;
480
0
        return 0;
481
0
    }
482
483
841
    using UnsignedT = MakeUnsignedT<T>;
484
841
    UnsignedT val = 0;
485
841
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
486
841
    bool negative = false;
487
841
    int i = 0;
488
841
    switch (*s) {
489
357
    case '-':
490
357
        negative = true;
491
        // Only signed types have an extra value in their negative range.
492
357
        max_val += std::numeric_limits<T>::is_signed;
493
357
        [[fallthrough]];
494
357
    case '+':
495
357
        ++i;
496
        // only one '+'/'-' char, so could return failure directly
497
357
        if (UNLIKELY(len == 1)) {
498
0
            *result = PARSE_FAILURE;
499
0
            return 0;
500
0
        }
501
841
    }
502
503
    // This is the fast path where the string cannot overflow.
504
841
    if (LIKELY(len - i < NumberTraits::max_ascii_len<T>())) {
505
238
        val = string_to_int_no_overflow<UnsignedT, enable_strict_mode>(s + i, len - i, result);
506
238
        return static_cast<T>(negative ? -val : val);
507
238
    }
508
509
603
    const T max_div_10 = max_val / 10;
510
603
    const T max_mod_10 = max_val % 10;
511
512
603
    int first = i;
513
4.07k
    for (; i < len; ++i) {
514
4.05k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
515
3.64k
            T digit = s[i] - '0';
516
            // This is a tricky check to see if adding this digit will cause an overflow.
517
3.64k
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
518
168
                *result = PARSE_OVERFLOW;
519
168
                return negative ? -max_val : max_val;
520
168
            }
521
3.47k
            val = val * 10 + digit;
522
3.47k
        } else {
523
            if constexpr (enable_strict_mode) {
524
                if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
525
                    // Reject the string because the remaining chars are not all whitespace
526
                    *result = PARSE_FAILURE;
527
                    return 0;
528
                }
529
414
            } else {
530
                // Save original position where non-digit was found
531
414
                int remaining_len = len - i;
532
414
                const char* remaining_s = s + i;
533
                // Skip trailing whitespaces from the remaining portion
534
414
                remaining_s = skip_trailing_whitespaces(remaining_s, remaining_len);
535
414
                if ((UNLIKELY(i == first || (remaining_len != 0 &&
536
414
                                             !is_float_suffix(remaining_s, remaining_len))))) {
537
                    // Reject the string because either the first char was not a digit,
538
                    // or the remaining chars are not all whitespace
539
288
                    *result = PARSE_FAILURE;
540
288
                    return 0;
541
288
                }
542
414
            }
543
            // Returning here is slightly faster than breaking the loop.
544
126
            *result = PARSE_SUCCESS;
545
414
            return static_cast<T>(negative ? -val : val);
546
414
        }
547
4.05k
    }
548
21
    *result = PARSE_SUCCESS;
549
21
    return static_cast<T>(negative ? -val : val);
550
603
}
_ZN5doris12StringParser22string_to_int_internalImLb0EEET_PKciPNS0_11ParseResultE
Line
Count
Source
477
1.24k
T StringParser::string_to_int_internal(const char* __restrict s, int len, ParseResult* result) {
478
1.24k
    if (UNLIKELY(len <= 0)) {
479
0
        *result = PARSE_FAILURE;
480
0
        return 0;
481
0
    }
482
483
1.24k
    using UnsignedT = MakeUnsignedT<T>;
484
1.24k
    UnsignedT val = 0;
485
1.24k
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
486
1.24k
    bool negative = false;
487
1.24k
    int i = 0;
488
1.24k
    switch (*s) {
489
357
    case '-':
490
357
        negative = true;
491
        // Only signed types have an extra value in their negative range.
492
357
        max_val += std::numeric_limits<T>::is_signed;
493
357
        [[fallthrough]];
494
357
    case '+':
495
357
        ++i;
496
        // only one '+'/'-' char, so could return failure directly
497
357
        if (UNLIKELY(len == 1)) {
498
0
            *result = PARSE_FAILURE;
499
0
            return 0;
500
0
        }
501
1.24k
    }
502
503
    // This is the fast path where the string cannot overflow.
504
1.24k
    if (LIKELY(len - i < NumberTraits::max_ascii_len<T>())) {
505
673
        val = string_to_int_no_overflow<UnsignedT, enable_strict_mode>(s + i, len - i, result);
506
673
        return static_cast<T>(negative ? -val : val);
507
673
    }
508
509
567
    const T max_div_10 = max_val / 10;
510
567
    const T max_mod_10 = max_val % 10;
511
512
567
    int first = i;
513
6.69k
    for (; i < len; ++i) {
514
6.67k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
515
6.30k
            T digit = s[i] - '0';
516
            // This is a tricky check to see if adding this digit will cause an overflow.
517
6.30k
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
518
168
                *result = PARSE_OVERFLOW;
519
168
                return negative ? -max_val : max_val;
520
168
            }
521
6.13k
            val = val * 10 + digit;
522
6.13k
        } else {
523
            if constexpr (enable_strict_mode) {
524
                if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
525
                    // Reject the string because the remaining chars are not all whitespace
526
                    *result = PARSE_FAILURE;
527
                    return 0;
528
                }
529
378
            } else {
530
                // Save original position where non-digit was found
531
378
                int remaining_len = len - i;
532
378
                const char* remaining_s = s + i;
533
                // Skip trailing whitespaces from the remaining portion
534
378
                remaining_s = skip_trailing_whitespaces(remaining_s, remaining_len);
535
378
                if ((UNLIKELY(i == first || (remaining_len != 0 &&
536
378
                                             !is_float_suffix(remaining_s, remaining_len))))) {
537
                    // Reject the string because either the first char was not a digit,
538
                    // or the remaining chars are not all whitespace
539
252
                    *result = PARSE_FAILURE;
540
252
                    return 0;
541
252
                }
542
378
            }
543
            // Returning here is slightly faster than breaking the loop.
544
126
            *result = PARSE_SUCCESS;
545
378
            return static_cast<T>(negative ? -val : val);
546
378
        }
547
6.67k
    }
548
21
    *result = PARSE_SUCCESS;
549
21
    return static_cast<T>(negative ? -val : val);
550
567
}
_ZN5doris12StringParser22string_to_int_internalIoLb0EEET_PKciPNS0_11ParseResultE
Line
Count
Source
477
844
T StringParser::string_to_int_internal(const char* __restrict s, int len, ParseResult* result) {
478
844
    if (UNLIKELY(len <= 0)) {
479
0
        *result = PARSE_FAILURE;
480
0
        return 0;
481
0
    }
482
483
844
    using UnsignedT = MakeUnsignedT<T>;
484
844
    UnsignedT val = 0;
485
844
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
486
844
    bool negative = false;
487
844
    int i = 0;
488
844
    switch (*s) {
489
357
    case '-':
490
357
        negative = true;
491
        // Only signed types have an extra value in their negative range.
492
357
        max_val += std::numeric_limits<T>::is_signed;
493
357
        [[fallthrough]];
494
357
    case '+':
495
357
        ++i;
496
        // only one '+'/'-' char, so could return failure directly
497
357
        if (UNLIKELY(len == 1)) {
498
0
            *result = PARSE_FAILURE;
499
0
            return 0;
500
0
        }
501
844
    }
502
503
    // This is the fast path where the string cannot overflow.
504
844
    if (LIKELY(len - i < NumberTraits::max_ascii_len<T>())) {
505
0
        val = string_to_int_no_overflow<UnsignedT, enable_strict_mode>(s + i, len - i, result);
506
0
        return static_cast<T>(negative ? -val : val);
507
0
    }
508
509
844
    const T max_div_10 = max_val / 10;
510
844
    const T max_mod_10 = max_val % 10;
511
512
844
    int first = i;
513
12.3k
    for (; i < len; ++i) {
514
12.3k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
515
11.6k
            T digit = s[i] - '0';
516
            // This is a tricky check to see if adding this digit will cause an overflow.
517
11.6k
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
518
168
                *result = PARSE_OVERFLOW;
519
168
                return negative ? -max_val : max_val;
520
168
            }
521
11.5k
            val = val * 10 + digit;
522
11.5k
        } else {
523
            if constexpr (enable_strict_mode) {
524
                if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
525
                    // Reject the string because the remaining chars are not all whitespace
526
                    *result = PARSE_FAILURE;
527
                    return 0;
528
                }
529
637
            } else {
530
                // Save original position where non-digit was found
531
637
                int remaining_len = len - i;
532
637
                const char* remaining_s = s + i;
533
                // Skip trailing whitespaces from the remaining portion
534
637
                remaining_s = skip_trailing_whitespaces(remaining_s, remaining_len);
535
637
                if ((UNLIKELY(i == first || (remaining_len != 0 &&
536
637
                                             !is_float_suffix(remaining_s, remaining_len))))) {
537
                    // Reject the string because either the first char was not a digit,
538
                    // or the remaining chars are not all whitespace
539
378
                    *result = PARSE_FAILURE;
540
378
                    return 0;
541
378
                }
542
637
            }
543
            // Returning here is slightly faster than breaking the loop.
544
259
            *result = PARSE_SUCCESS;
545
637
            return static_cast<T>(negative ? -val : val);
546
637
        }
547
12.3k
    }
548
39
    *result = PARSE_SUCCESS;
549
39
    return static_cast<T>(negative ? -val : val);
550
844
}
_ZN5doris12StringParser22string_to_int_internalIhLb1EEET_PKciPNS0_11ParseResultE
Line
Count
Source
477
847
T StringParser::string_to_int_internal(const char* __restrict s, int len, ParseResult* result) {
478
847
    if (UNLIKELY(len <= 0)) {
479
0
        *result = PARSE_FAILURE;
480
0
        return 0;
481
0
    }
482
483
847
    using UnsignedT = MakeUnsignedT<T>;
484
847
    UnsignedT val = 0;
485
847
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
486
847
    bool negative = false;
487
847
    int i = 0;
488
847
    switch (*s) {
489
364
    case '-':
490
364
        negative = true;
491
        // Only signed types have an extra value in their negative range.
492
364
        max_val += std::numeric_limits<T>::is_signed;
493
364
        [[fallthrough]];
494
364
    case '+':
495
364
        ++i;
496
        // only one '+'/'-' char, so could return failure directly
497
364
        if (UNLIKELY(len == 1)) {
498
0
            *result = PARSE_FAILURE;
499
0
            return 0;
500
0
        }
501
847
    }
502
503
    // This is the fast path where the string cannot overflow.
504
847
    if (LIKELY(len - i < NumberTraits::max_ascii_len<T>())) {
505
0
        val = string_to_int_no_overflow<UnsignedT, enable_strict_mode>(s + i, len - i, result);
506
0
        return static_cast<T>(negative ? -val : val);
507
0
    }
508
509
847
    const T max_div_10 = max_val / 10;
510
847
    const T max_mod_10 = max_val % 10;
511
512
847
    int first = i;
513
2.71k
    for (; i < len; ++i) {
514
2.68k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
515
2.03k
            T digit = s[i] - '0';
516
            // This is a tricky check to see if adding this digit will cause an overflow.
517
2.03k
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
518
168
                *result = PARSE_OVERFLOW;
519
168
                return negative ? -max_val : max_val;
520
168
            }
521
1.86k
            val = val * 10 + digit;
522
1.86k
        } else {
523
644
            if constexpr (enable_strict_mode) {
524
644
                if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
525
                    // Reject the string because the remaining chars are not all whitespace
526
434
                    *result = PARSE_FAILURE;
527
434
                    return 0;
528
434
                }
529
            } else {
530
                // Save original position where non-digit was found
531
                int remaining_len = len - i;
532
                const char* remaining_s = s + i;
533
                // Skip trailing whitespaces from the remaining portion
534
                remaining_s = skip_trailing_whitespaces(remaining_s, remaining_len);
535
                if ((UNLIKELY(i == first || (remaining_len != 0 &&
536
                                             !is_float_suffix(remaining_s, remaining_len))))) {
537
                    // Reject the string because either the first char was not a digit,
538
                    // or the remaining chars are not all whitespace
539
                    *result = PARSE_FAILURE;
540
                    return 0;
541
                }
542
            }
543
            // Returning here is slightly faster than breaking the loop.
544
210
            *result = PARSE_SUCCESS;
545
644
            return static_cast<T>(negative ? -val : val);
546
644
        }
547
2.68k
    }
548
35
    *result = PARSE_SUCCESS;
549
35
    return static_cast<T>(negative ? -val : val);
550
847
}
_ZN5doris12StringParser22string_to_int_internalItLb1EEET_PKciPNS0_11ParseResultE
Line
Count
Source
477
847
T StringParser::string_to_int_internal(const char* __restrict s, int len, ParseResult* result) {
478
847
    if (UNLIKELY(len <= 0)) {
479
0
        *result = PARSE_FAILURE;
480
0
        return 0;
481
0
    }
482
483
847
    using UnsignedT = MakeUnsignedT<T>;
484
847
    UnsignedT val = 0;
485
847
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
486
847
    bool negative = false;
487
847
    int i = 0;
488
847
    switch (*s) {
489
364
    case '-':
490
364
        negative = true;
491
        // Only signed types have an extra value in their negative range.
492
364
        max_val += std::numeric_limits<T>::is_signed;
493
364
        [[fallthrough]];
494
364
    case '+':
495
364
        ++i;
496
        // only one '+'/'-' char, so could return failure directly
497
364
        if (UNLIKELY(len == 1)) {
498
0
            *result = PARSE_FAILURE;
499
0
            return 0;
500
0
        }
501
847
    }
502
503
    // This is the fast path where the string cannot overflow.
504
847
    if (LIKELY(len - i < NumberTraits::max_ascii_len<T>())) {
505
64
        val = string_to_int_no_overflow<UnsignedT, enable_strict_mode>(s + i, len - i, result);
506
64
        return static_cast<T>(negative ? -val : val);
507
64
    }
508
509
783
    const T max_div_10 = max_val / 10;
510
783
    const T max_mod_10 = max_val % 10;
511
512
783
    int first = i;
513
3.10k
    for (; i < len; ++i) {
514
3.08k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
515
2.49k
            T digit = s[i] - '0';
516
            // This is a tricky check to see if adding this digit will cause an overflow.
517
2.49k
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
518
168
                *result = PARSE_OVERFLOW;
519
168
                return negative ? -max_val : max_val;
520
168
            }
521
2.32k
            val = val * 10 + digit;
522
2.32k
        } else {
523
594
            if constexpr (enable_strict_mode) {
524
594
                if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
525
                    // Reject the string because the remaining chars are not all whitespace
526
426
                    *result = PARSE_FAILURE;
527
426
                    return 0;
528
426
                }
529
            } else {
530
                // Save original position where non-digit was found
531
                int remaining_len = len - i;
532
                const char* remaining_s = s + i;
533
                // Skip trailing whitespaces from the remaining portion
534
                remaining_s = skip_trailing_whitespaces(remaining_s, remaining_len);
535
                if ((UNLIKELY(i == first || (remaining_len != 0 &&
536
                                             !is_float_suffix(remaining_s, remaining_len))))) {
537
                    // Reject the string because either the first char was not a digit,
538
                    // or the remaining chars are not all whitespace
539
                    *result = PARSE_FAILURE;
540
                    return 0;
541
                }
542
            }
543
            // Returning here is slightly faster than breaking the loop.
544
168
            *result = PARSE_SUCCESS;
545
594
            return static_cast<T>(negative ? -val : val);
546
594
        }
547
3.08k
    }
548
21
    *result = PARSE_SUCCESS;
549
21
    return static_cast<T>(negative ? -val : val);
550
783
}
_ZN5doris12StringParser22string_to_int_internalImLb1EEET_PKciPNS0_11ParseResultE
Line
Count
Source
477
847
T StringParser::string_to_int_internal(const char* __restrict s, int len, ParseResult* result) {
478
847
    if (UNLIKELY(len <= 0)) {
479
0
        *result = PARSE_FAILURE;
480
0
        return 0;
481
0
    }
482
483
847
    using UnsignedT = MakeUnsignedT<T>;
484
847
    UnsignedT val = 0;
485
847
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
486
847
    bool negative = false;
487
847
    int i = 0;
488
847
    switch (*s) {
489
364
    case '-':
490
364
        negative = true;
491
        // Only signed types have an extra value in their negative range.
492
364
        max_val += std::numeric_limits<T>::is_signed;
493
364
        [[fallthrough]];
494
364
    case '+':
495
364
        ++i;
496
        // only one '+'/'-' char, so could return failure directly
497
364
        if (UNLIKELY(len == 1)) {
498
0
            *result = PARSE_FAILURE;
499
0
            return 0;
500
0
        }
501
847
    }
502
503
    // This is the fast path where the string cannot overflow.
504
847
    if (LIKELY(len - i < NumberTraits::max_ascii_len<T>())) {
505
280
        val = string_to_int_no_overflow<UnsignedT, enable_strict_mode>(s + i, len - i, result);
506
280
        return static_cast<T>(negative ? -val : val);
507
280
    }
508
509
567
    const T max_div_10 = max_val / 10;
510
567
    const T max_mod_10 = max_val % 10;
511
512
567
    int first = i;
513
6.69k
    for (; i < len; ++i) {
514
6.67k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
515
6.30k
            T digit = s[i] - '0';
516
            // This is a tricky check to see if adding this digit will cause an overflow.
517
6.30k
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
518
168
                *result = PARSE_OVERFLOW;
519
168
                return negative ? -max_val : max_val;
520
168
            }
521
6.13k
            val = val * 10 + digit;
522
6.13k
        } else {
523
378
            if constexpr (enable_strict_mode) {
524
378
                if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
525
                    // Reject the string because the remaining chars are not all whitespace
526
252
                    *result = PARSE_FAILURE;
527
252
                    return 0;
528
252
                }
529
            } else {
530
                // Save original position where non-digit was found
531
                int remaining_len = len - i;
532
                const char* remaining_s = s + i;
533
                // Skip trailing whitespaces from the remaining portion
534
                remaining_s = skip_trailing_whitespaces(remaining_s, remaining_len);
535
                if ((UNLIKELY(i == first || (remaining_len != 0 &&
536
                                             !is_float_suffix(remaining_s, remaining_len))))) {
537
                    // Reject the string because either the first char was not a digit,
538
                    // or the remaining chars are not all whitespace
539
                    *result = PARSE_FAILURE;
540
                    return 0;
541
                }
542
            }
543
            // Returning here is slightly faster than breaking the loop.
544
126
            *result = PARSE_SUCCESS;
545
378
            return static_cast<T>(negative ? -val : val);
546
378
        }
547
6.67k
    }
548
21
    *result = PARSE_SUCCESS;
549
21
    return static_cast<T>(negative ? -val : val);
550
567
}
_ZN5doris12StringParser22string_to_int_internalIoLb1EEET_PKciPNS0_11ParseResultE
Line
Count
Source
477
847
T StringParser::string_to_int_internal(const char* __restrict s, int len, ParseResult* result) {
478
847
    if (UNLIKELY(len <= 0)) {
479
0
        *result = PARSE_FAILURE;
480
0
        return 0;
481
0
    }
482
483
847
    using UnsignedT = MakeUnsignedT<T>;
484
847
    UnsignedT val = 0;
485
847
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
486
847
    bool negative = false;
487
847
    int i = 0;
488
847
    switch (*s) {
489
364
    case '-':
490
364
        negative = true;
491
        // Only signed types have an extra value in their negative range.
492
364
        max_val += std::numeric_limits<T>::is_signed;
493
364
        [[fallthrough]];
494
364
    case '+':
495
364
        ++i;
496
        // only one '+'/'-' char, so could return failure directly
497
364
        if (UNLIKELY(len == 1)) {
498
0
            *result = PARSE_FAILURE;
499
0
            return 0;
500
0
        }
501
847
    }
502
503
    // This is the fast path where the string cannot overflow.
504
847
    if (LIKELY(len - i < NumberTraits::max_ascii_len<T>())) {
505
0
        val = string_to_int_no_overflow<UnsignedT, enable_strict_mode>(s + i, len - i, result);
506
0
        return static_cast<T>(negative ? -val : val);
507
0
    }
508
509
847
    const T max_div_10 = max_val / 10;
510
847
    const T max_mod_10 = max_val % 10;
511
512
847
    int first = i;
513
12.2k
    for (; i < len; ++i) {
514
12.2k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
515
11.6k
            T digit = s[i] - '0';
516
            // This is a tricky check to see if adding this digit will cause an overflow.
517
11.6k
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
518
168
                *result = PARSE_OVERFLOW;
519
168
                return negative ? -max_val : max_val;
520
168
            }
521
11.4k
            val = val * 10 + digit;
522
11.4k
        } else {
523
644
            if constexpr (enable_strict_mode) {
524
644
                if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
525
                    // Reject the string because the remaining chars are not all whitespace
526
434
                    *result = PARSE_FAILURE;
527
434
                    return 0;
528
434
                }
529
            } else {
530
                // Save original position where non-digit was found
531
                int remaining_len = len - i;
532
                const char* remaining_s = s + i;
533
                // Skip trailing whitespaces from the remaining portion
534
                remaining_s = skip_trailing_whitespaces(remaining_s, remaining_len);
535
                if ((UNLIKELY(i == first || (remaining_len != 0 &&
536
                                             !is_float_suffix(remaining_s, remaining_len))))) {
537
                    // Reject the string because either the first char was not a digit,
538
                    // or the remaining chars are not all whitespace
539
                    *result = PARSE_FAILURE;
540
                    return 0;
541
                }
542
            }
543
            // Returning here is slightly faster than breaking the loop.
544
210
            *result = PARSE_SUCCESS;
545
644
            return static_cast<T>(negative ? -val : val);
546
644
        }
547
12.2k
    }
548
35
    *result = PARSE_SUCCESS;
549
35
    return static_cast<T>(negative ? -val : val);
550
847
}
_ZN5doris12StringParser22string_to_int_internalIN4wide7integerILm256EiEELb0EEET_PKciPNS0_11ParseResultE
Line
Count
Source
477
4
T StringParser::string_to_int_internal(const char* __restrict s, int len, ParseResult* result) {
478
4
    if (UNLIKELY(len <= 0)) {
479
0
        *result = PARSE_FAILURE;
480
0
        return 0;
481
0
    }
482
483
4
    using UnsignedT = MakeUnsignedT<T>;
484
4
    UnsignedT val = 0;
485
4
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
486
4
    bool negative = false;
487
4
    int i = 0;
488
4
    switch (*s) {
489
0
    case '-':
490
0
        negative = true;
491
        // Only signed types have an extra value in their negative range.
492
0
        max_val += std::numeric_limits<T>::is_signed;
493
0
        [[fallthrough]];
494
0
    case '+':
495
0
        ++i;
496
        // only one '+'/'-' char, so could return failure directly
497
0
        if (UNLIKELY(len == 1)) {
498
0
            *result = PARSE_FAILURE;
499
0
            return 0;
500
0
        }
501
4
    }
502
503
    // This is the fast path where the string cannot overflow.
504
4
    if (LIKELY(len - i < NumberTraits::max_ascii_len<T>())) {
505
4
        val = string_to_int_no_overflow<UnsignedT, enable_strict_mode>(s + i, len - i, result);
506
4
        return static_cast<T>(negative ? -val : val);
507
4
    }
508
509
0
    const T max_div_10 = max_val / 10;
510
0
    const T max_mod_10 = max_val % 10;
511
512
0
    int first = i;
513
0
    for (; i < len; ++i) {
514
0
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
515
0
            T digit = s[i] - '0';
516
            // This is a tricky check to see if adding this digit will cause an overflow.
517
0
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
518
0
                *result = PARSE_OVERFLOW;
519
0
                return negative ? -max_val : max_val;
520
0
            }
521
0
            val = val * 10 + digit;
522
0
        } else {
523
            if constexpr (enable_strict_mode) {
524
                if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
525
                    // Reject the string because the remaining chars are not all whitespace
526
                    *result = PARSE_FAILURE;
527
                    return 0;
528
                }
529
0
            } else {
530
                // Save original position where non-digit was found
531
0
                int remaining_len = len - i;
532
0
                const char* remaining_s = s + i;
533
                // Skip trailing whitespaces from the remaining portion
534
0
                remaining_s = skip_trailing_whitespaces(remaining_s, remaining_len);
535
0
                if ((UNLIKELY(i == first || (remaining_len != 0 &&
536
0
                                             !is_float_suffix(remaining_s, remaining_len))))) {
537
                    // Reject the string because either the first char was not a digit,
538
                    // or the remaining chars are not all whitespace
539
0
                    *result = PARSE_FAILURE;
540
0
                    return 0;
541
0
                }
542
0
            }
543
            // Returning here is slightly faster than breaking the loop.
544
0
            *result = PARSE_SUCCESS;
545
0
            return static_cast<T>(negative ? -val : val);
546
0
        }
547
0
    }
548
0
    *result = PARSE_SUCCESS;
549
0
    return static_cast<T>(negative ? -val : val);
550
0
}
551
552
template <typename T>
553
T StringParser::string_to_unsigned_int_internal(const char* __restrict s, int len,
554
1.37k
                                                ParseResult* result) {
555
1.37k
    if (UNLIKELY(len <= 0)) {
556
0
        *result = PARSE_FAILURE;
557
0
        return 0;
558
0
    }
559
560
1.37k
    T val = 0;
561
1.37k
    T max_val = std::numeric_limits<T>::max();
562
1.37k
    int i = 0;
563
564
1.37k
    using signedT = MakeSignedT<T>;
565
    // This is the fast path where the string cannot overflow.
566
1.37k
    if (LIKELY(len - i < NumberTraits::max_ascii_len<signedT>())) {
567
784
        val = string_to_int_no_overflow<T>(s + i, len - i, result);
568
784
        return val;
569
784
    }
570
571
588
    const T max_div_10 = max_val / 10;
572
588
    const T max_mod_10 = max_val % 10;
573
574
588
    int first = i;
575
4.65k
    for (; i < len; ++i) {
576
4.31k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
577
4.26k
            T digit = s[i] - '0';
578
            // This is a tricky check to see if adding this digit will cause an overflow.
579
4.26k
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
580
196
                *result = PARSE_OVERFLOW;
581
196
                return max_val;
582
196
            }
583
4.06k
            val = val * 10 + digit;
584
4.06k
        } else {
585
49
            if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
586
                // Reject the string because either the first char was not a digit,
587
                // or the remaining chars are not all whitespace
588
49
                *result = PARSE_FAILURE;
589
49
                return 0;
590
49
            }
591
            // Returning here is slightly faster than breaking the loop.
592
0
            *result = PARSE_SUCCESS;
593
0
            return val;
594
49
        }
595
4.31k
    }
596
343
    *result = PARSE_SUCCESS;
597
343
    return val;
598
588
}
_ZN5doris12StringParser31string_to_unsigned_int_internalIhEET_PKciPNS0_11ParseResultE
Line
Count
Source
554
343
                                                ParseResult* result) {
555
343
    if (UNLIKELY(len <= 0)) {
556
0
        *result = PARSE_FAILURE;
557
0
        return 0;
558
0
    }
559
560
343
    T val = 0;
561
343
    T max_val = std::numeric_limits<T>::max();
562
343
    int i = 0;
563
564
343
    using signedT = MakeSignedT<T>;
565
    // This is the fast path where the string cannot overflow.
566
343
    if (LIKELY(len - i < NumberTraits::max_ascii_len<signedT>())) {
567
98
        val = string_to_int_no_overflow<T>(s + i, len - i, result);
568
98
        return val;
569
98
    }
570
571
245
    const T max_div_10 = max_val / 10;
572
245
    const T max_mod_10 = max_val % 10;
573
574
245
    int first = i;
575
784
    for (; i < len; ++i) {
576
637
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
577
588
            T digit = s[i] - '0';
578
            // This is a tricky check to see if adding this digit will cause an overflow.
579
588
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
580
49
                *result = PARSE_OVERFLOW;
581
49
                return max_val;
582
49
            }
583
539
            val = val * 10 + digit;
584
539
        } else {
585
49
            if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
586
                // Reject the string because either the first char was not a digit,
587
                // or the remaining chars are not all whitespace
588
49
                *result = PARSE_FAILURE;
589
49
                return 0;
590
49
            }
591
            // Returning here is slightly faster than breaking the loop.
592
0
            *result = PARSE_SUCCESS;
593
0
            return val;
594
49
        }
595
637
    }
596
147
    *result = PARSE_SUCCESS;
597
147
    return val;
598
245
}
_ZN5doris12StringParser31string_to_unsigned_int_internalItEET_PKciPNS0_11ParseResultE
Line
Count
Source
554
343
                                                ParseResult* result) {
555
343
    if (UNLIKELY(len <= 0)) {
556
0
        *result = PARSE_FAILURE;
557
0
        return 0;
558
0
    }
559
560
343
    T val = 0;
561
343
    T max_val = std::numeric_limits<T>::max();
562
343
    int i = 0;
563
564
343
    using signedT = MakeSignedT<T>;
565
    // This is the fast path where the string cannot overflow.
566
343
    if (LIKELY(len - i < NumberTraits::max_ascii_len<signedT>())) {
567
196
        val = string_to_int_no_overflow<T>(s + i, len - i, result);
568
196
        return val;
569
196
    }
570
571
147
    const T max_div_10 = max_val / 10;
572
147
    const T max_mod_10 = max_val % 10;
573
574
147
    int first = i;
575
833
    for (; i < len; ++i) {
576
735
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
577
735
            T digit = s[i] - '0';
578
            // This is a tricky check to see if adding this digit will cause an overflow.
579
735
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
580
49
                *result = PARSE_OVERFLOW;
581
49
                return max_val;
582
49
            }
583
686
            val = val * 10 + digit;
584
686
        } else {
585
0
            if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
586
                // Reject the string because either the first char was not a digit,
587
                // or the remaining chars are not all whitespace
588
0
                *result = PARSE_FAILURE;
589
0
                return 0;
590
0
            }
591
            // Returning here is slightly faster than breaking the loop.
592
0
            *result = PARSE_SUCCESS;
593
0
            return val;
594
0
        }
595
735
    }
596
98
    *result = PARSE_SUCCESS;
597
98
    return val;
598
147
}
_ZN5doris12StringParser31string_to_unsigned_int_internalIjEET_PKciPNS0_11ParseResultE
Line
Count
Source
554
343
                                                ParseResult* result) {
555
343
    if (UNLIKELY(len <= 0)) {
556
0
        *result = PARSE_FAILURE;
557
0
        return 0;
558
0
    }
559
560
343
    T val = 0;
561
343
    T max_val = std::numeric_limits<T>::max();
562
343
    int i = 0;
563
564
343
    using signedT = MakeSignedT<T>;
565
    // This is the fast path where the string cannot overflow.
566
343
    if (LIKELY(len - i < NumberTraits::max_ascii_len<signedT>())) {
567
245
        val = string_to_int_no_overflow<T>(s + i, len - i, result);
568
245
        return val;
569
245
    }
570
571
98
    const T max_div_10 = max_val / 10;
572
98
    const T max_mod_10 = max_val % 10;
573
574
98
    int first = i;
575
1.02k
    for (; i < len; ++i) {
576
980
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
577
980
            T digit = s[i] - '0';
578
            // This is a tricky check to see if adding this digit will cause an overflow.
579
980
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
580
49
                *result = PARSE_OVERFLOW;
581
49
                return max_val;
582
49
            }
583
931
            val = val * 10 + digit;
584
931
        } else {
585
0
            if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
586
                // Reject the string because either the first char was not a digit,
587
                // or the remaining chars are not all whitespace
588
0
                *result = PARSE_FAILURE;
589
0
                return 0;
590
0
            }
591
            // Returning here is slightly faster than breaking the loop.
592
0
            *result = PARSE_SUCCESS;
593
0
            return val;
594
0
        }
595
980
    }
596
49
    *result = PARSE_SUCCESS;
597
49
    return val;
598
98
}
_ZN5doris12StringParser31string_to_unsigned_int_internalImEET_PKciPNS0_11ParseResultE
Line
Count
Source
554
343
                                                ParseResult* result) {
555
343
    if (UNLIKELY(len <= 0)) {
556
0
        *result = PARSE_FAILURE;
557
0
        return 0;
558
0
    }
559
560
343
    T val = 0;
561
343
    T max_val = std::numeric_limits<T>::max();
562
343
    int i = 0;
563
564
343
    using signedT = MakeSignedT<T>;
565
    // This is the fast path where the string cannot overflow.
566
343
    if (LIKELY(len - i < NumberTraits::max_ascii_len<signedT>())) {
567
245
        val = string_to_int_no_overflow<T>(s + i, len - i, result);
568
245
        return val;
569
245
    }
570
571
98
    const T max_div_10 = max_val / 10;
572
98
    const T max_mod_10 = max_val % 10;
573
574
98
    int first = i;
575
2.00k
    for (; i < len; ++i) {
576
1.96k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
577
1.96k
            T digit = s[i] - '0';
578
            // This is a tricky check to see if adding this digit will cause an overflow.
579
1.96k
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
580
49
                *result = PARSE_OVERFLOW;
581
49
                return max_val;
582
49
            }
583
1.91k
            val = val * 10 + digit;
584
1.91k
        } else {
585
0
            if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
586
                // Reject the string because either the first char was not a digit,
587
                // or the remaining chars are not all whitespace
588
0
                *result = PARSE_FAILURE;
589
0
                return 0;
590
0
            }
591
            // Returning here is slightly faster than breaking the loop.
592
0
            *result = PARSE_SUCCESS;
593
0
            return val;
594
0
        }
595
1.96k
    }
596
49
    *result = PARSE_SUCCESS;
597
49
    return val;
598
98
}
599
600
template <typename T>
601
T StringParser::string_to_int_internal(const char* __restrict s, int64_t len, int base,
602
31.1k
                                       ParseResult* result) {
603
31.1k
    using UnsignedT = MakeUnsignedT<T>;
604
31.1k
    UnsignedT val = 0;
605
31.1k
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
606
31.1k
    bool negative = false;
607
31.1k
    if (UNLIKELY(len <= 0)) {
608
10
        *result = PARSE_FAILURE;
609
10
        return 0;
610
10
    }
611
31.0k
    int i = 0;
612
31.0k
    switch (*s) {
613
14.9k
    case '-':
614
14.9k
        negative = true;
615
        // Only signed types have an extra value in their negative range.
616
        // Keep the unsigned magnitude limit unchanged to avoid wrapping it to zero.
617
14.9k
        max_val += std::numeric_limits<T>::is_signed;
618
14.9k
        [[fallthrough]];
619
15.2k
    case '+':
620
15.2k
        i = 1;
621
31.0k
    }
622
623
31.0k
    const T max_div_base = max_val / base;
624
31.0k
    const T max_mod_base = max_val % base;
625
626
31.0k
    int first = i;
627
105k
    for (; i < len; ++i) {
628
88.4k
        T digit;
629
88.4k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
630
87.3k
            digit = s[i] - '0';
631
87.3k
        } else if (s[i] >= 'a' && s[i] <= 'z') {
632
850
            digit = (s[i] - 'a' + 10);
633
850
        } else if (s[i] >= 'A' && s[i] <= 'Z') {
634
106
            digit = (s[i] - 'A' + 10);
635
155
        } else {
636
155
            if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
637
                // Reject the string because either the first char was not an alpha/digit,
638
                // or the remaining chars are not all whitespace
639
155
                *result = PARSE_FAILURE;
640
155
                return 0;
641
155
            }
642
            // skip trailing whitespace.
643
0
            break;
644
155
        }
645
646
        // Bail, if we encounter a digit that is not available in base.
647
88.3k
        if (digit >= base) {
648
546
            break;
649
546
        }
650
651
        // This is a tricky check to see if adding this digit will cause an overflow.
652
87.7k
        if (UNLIKELY(val > (max_div_base - (digit > max_mod_base)))) {
653
13.1k
            *result = PARSE_OVERFLOW;
654
13.1k
            return static_cast<T>(negative ? -max_val : max_val);
655
13.1k
        }
656
74.6k
        val = val * base + digit;
657
74.6k
    }
658
17.8k
    *result = PARSE_SUCCESS;
659
17.8k
    return static_cast<T>(negative ? -val : val);
660
31.0k
}
_ZN5doris12StringParser22string_to_int_internalIaEET_PKcliPNS0_11ParseResultE
Line
Count
Source
602
26.4k
                                       ParseResult* result) {
603
26.4k
    using UnsignedT = MakeUnsignedT<T>;
604
26.4k
    UnsignedT val = 0;
605
26.4k
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
606
26.4k
    bool negative = false;
607
26.4k
    if (UNLIKELY(len <= 0)) {
608
0
        *result = PARSE_FAILURE;
609
0
        return 0;
610
0
    }
611
26.4k
    int i = 0;
612
26.4k
    switch (*s) {
613
12.8k
    case '-':
614
12.8k
        negative = true;
615
        // Only signed types have an extra value in their negative range.
616
        // Keep the unsigned magnitude limit unchanged to avoid wrapping it to zero.
617
12.8k
        max_val += std::numeric_limits<T>::is_signed;
618
12.8k
        [[fallthrough]];
619
12.9k
    case '+':
620
12.9k
        i = 1;
621
26.4k
    }
622
623
26.4k
    const T max_div_base = max_val / base;
624
26.4k
    const T max_mod_base = max_val % base;
625
626
26.4k
    int first = i;
627
80.7k
    for (; i < len; ++i) {
628
67.4k
        T digit;
629
67.4k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
630
66.6k
            digit = s[i] - '0';
631
66.6k
        } else if (s[i] >= 'a' && s[i] <= 'z') {
632
539
            digit = (s[i] - 'a' + 10);
633
539
        } else if (s[i] >= 'A' && s[i] <= 'Z') {
634
98
            digit = (s[i] - 'A' + 10);
635
147
        } else {
636
147
            if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
637
                // Reject the string because either the first char was not an alpha/digit,
638
                // or the remaining chars are not all whitespace
639
147
                *result = PARSE_FAILURE;
640
147
                return 0;
641
147
            }
642
            // skip trailing whitespace.
643
0
            break;
644
147
        }
645
646
        // Bail, if we encounter a digit that is not available in base.
647
67.3k
        if (digit >= base) {
648
392
            break;
649
392
        }
650
651
        // This is a tricky check to see if adding this digit will cause an overflow.
652
66.9k
        if (UNLIKELY(val > (max_div_base - (digit > max_mod_base)))) {
653
12.6k
            *result = PARSE_OVERFLOW;
654
12.6k
            return static_cast<T>(negative ? -max_val : max_val);
655
12.6k
        }
656
54.2k
        val = val * base + digit;
657
54.2k
    }
658
13.6k
    *result = PARSE_SUCCESS;
659
13.6k
    return static_cast<T>(negative ? -val : val);
660
26.4k
}
_ZN5doris12StringParser22string_to_int_internalIsEET_PKcliPNS0_11ParseResultE
Line
Count
Source
602
490
                                       ParseResult* result) {
603
490
    using UnsignedT = MakeUnsignedT<T>;
604
490
    UnsignedT val = 0;
605
490
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
606
490
    bool negative = false;
607
490
    if (UNLIKELY(len <= 0)) {
608
0
        *result = PARSE_FAILURE;
609
0
        return 0;
610
0
    }
611
490
    int i = 0;
612
490
    switch (*s) {
613
196
    case '-':
614
196
        negative = true;
615
        // Only signed types have an extra value in their negative range.
616
        // Keep the unsigned magnitude limit unchanged to avoid wrapping it to zero.
617
196
        max_val += std::numeric_limits<T>::is_signed;
618
196
        [[fallthrough]];
619
245
    case '+':
620
245
        i = 1;
621
490
    }
622
623
490
    const T max_div_base = max_val / base;
624
490
    const T max_mod_base = max_val % base;
625
626
490
    int first = i;
627
2.10k
    for (; i < len; ++i) {
628
1.71k
        T digit;
629
1.71k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
630
1.61k
            digit = s[i] - '0';
631
1.61k
        } else if (s[i] >= 'a' && s[i] <= 'z') {
632
98
            digit = (s[i] - 'a' + 10);
633
98
        } else if (s[i] >= 'A' && s[i] <= 'Z') {
634
0
            digit = (s[i] - 'A' + 10);
635
0
        } else {
636
0
            if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
637
                // Reject the string because either the first char was not an alpha/digit,
638
                // or the remaining chars are not all whitespace
639
0
                *result = PARSE_FAILURE;
640
0
                return 0;
641
0
            }
642
            // skip trailing whitespace.
643
0
            break;
644
0
        }
645
646
        // Bail, if we encounter a digit that is not available in base.
647
1.71k
        if (digit >= base) {
648
0
            break;
649
0
        }
650
651
        // This is a tricky check to see if adding this digit will cause an overflow.
652
1.71k
        if (UNLIKELY(val > (max_div_base - (digit > max_mod_base)))) {
653
98
            *result = PARSE_OVERFLOW;
654
98
            return static_cast<T>(negative ? -max_val : max_val);
655
98
        }
656
1.61k
        val = val * base + digit;
657
1.61k
    }
658
392
    *result = PARSE_SUCCESS;
659
392
    return static_cast<T>(negative ? -val : val);
660
490
}
_ZN5doris12StringParser22string_to_int_internalIiEET_PKcliPNS0_11ParseResultE
Line
Count
Source
602
441
                                       ParseResult* result) {
603
441
    using UnsignedT = MakeUnsignedT<T>;
604
441
    UnsignedT val = 0;
605
441
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
606
441
    bool negative = false;
607
441
    if (UNLIKELY(len <= 0)) {
608
0
        *result = PARSE_FAILURE;
609
0
        return 0;
610
0
    }
611
441
    int i = 0;
612
441
    switch (*s) {
613
147
    case '-':
614
147
        negative = true;
615
        // Only signed types have an extra value in their negative range.
616
        // Keep the unsigned magnitude limit unchanged to avoid wrapping it to zero.
617
147
        max_val += std::numeric_limits<T>::is_signed;
618
147
        [[fallthrough]];
619
245
    case '+':
620
245
        i = 1;
621
441
    }
622
623
441
    const T max_div_base = max_val / base;
624
441
    const T max_mod_base = max_val % base;
625
626
441
    int first = i;
627
3.03k
    for (; i < len; ++i) {
628
2.69k
        T digit;
629
2.69k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
630
2.69k
            digit = s[i] - '0';
631
2.69k
        } else if (s[i] >= 'a' && s[i] <= 'z') {
632
0
            digit = (s[i] - 'a' + 10);
633
0
        } else if (s[i] >= 'A' && s[i] <= 'Z') {
634
0
            digit = (s[i] - 'A' + 10);
635
0
        } else {
636
0
            if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
637
                // Reject the string because either the first char was not an alpha/digit,
638
                // or the remaining chars are not all whitespace
639
0
                *result = PARSE_FAILURE;
640
0
                return 0;
641
0
            }
642
            // skip trailing whitespace.
643
0
            break;
644
0
        }
645
646
        // Bail, if we encounter a digit that is not available in base.
647
2.69k
        if (digit >= base) {
648
0
            break;
649
0
        }
650
651
        // This is a tricky check to see if adding this digit will cause an overflow.
652
2.69k
        if (UNLIKELY(val > (max_div_base - (digit > max_mod_base)))) {
653
98
            *result = PARSE_OVERFLOW;
654
98
            return static_cast<T>(negative ? -max_val : max_val);
655
98
        }
656
2.59k
        val = val * base + digit;
657
2.59k
    }
658
343
    *result = PARSE_SUCCESS;
659
343
    return static_cast<T>(negative ? -val : val);
660
441
}
_ZN5doris12StringParser22string_to_int_internalIlEET_PKcliPNS0_11ParseResultE
Line
Count
Source
602
441
                                       ParseResult* result) {
603
441
    using UnsignedT = MakeUnsignedT<T>;
604
441
    UnsignedT val = 0;
605
441
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
606
441
    bool negative = false;
607
441
    if (UNLIKELY(len <= 0)) {
608
0
        *result = PARSE_FAILURE;
609
0
        return 0;
610
0
    }
611
441
    int i = 0;
612
441
    switch (*s) {
613
196
    case '-':
614
196
        negative = true;
615
        // Only signed types have an extra value in their negative range.
616
        // Keep the unsigned magnitude limit unchanged to avoid wrapping it to zero.
617
196
        max_val += std::numeric_limits<T>::is_signed;
618
196
        [[fallthrough]];
619
245
    case '+':
620
245
        i = 1;
621
441
    }
622
623
441
    const T max_div_base = max_val / base;
624
441
    const T max_mod_base = max_val % base;
625
626
441
    int first = i;
627
5.09k
    for (; i < len; ++i) {
628
4.75k
        T digit;
629
4.75k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
630
4.75k
            digit = s[i] - '0';
631
4.75k
        } else if (s[i] >= 'a' && s[i] <= 'z') {
632
0
            digit = (s[i] - 'a' + 10);
633
0
        } else if (s[i] >= 'A' && s[i] <= 'Z') {
634
0
            digit = (s[i] - 'A' + 10);
635
0
        } else {
636
0
            if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
637
                // Reject the string because either the first char was not an alpha/digit,
638
                // or the remaining chars are not all whitespace
639
0
                *result = PARSE_FAILURE;
640
0
                return 0;
641
0
            }
642
            // skip trailing whitespace.
643
0
            break;
644
0
        }
645
646
        // Bail, if we encounter a digit that is not available in base.
647
4.75k
        if (digit >= base) {
648
0
            break;
649
0
        }
650
651
        // This is a tricky check to see if adding this digit will cause an overflow.
652
4.75k
        if (UNLIKELY(val > (max_div_base - (digit > max_mod_base)))) {
653
98
            *result = PARSE_OVERFLOW;
654
98
            return static_cast<T>(negative ? -max_val : max_val);
655
98
        }
656
4.65k
        val = val * base + digit;
657
4.65k
    }
658
343
    *result = PARSE_SUCCESS;
659
343
    return static_cast<T>(negative ? -val : val);
660
441
}
_ZN5doris12StringParser22string_to_int_internalIhEET_PKcliPNS0_11ParseResultE
Line
Count
Source
602
147
                                       ParseResult* result) {
603
147
    using UnsignedT = MakeUnsignedT<T>;
604
147
    UnsignedT val = 0;
605
147
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
606
147
    bool negative = false;
607
147
    if (UNLIKELY(len <= 0)) {
608
0
        *result = PARSE_FAILURE;
609
0
        return 0;
610
0
    }
611
147
    int i = 0;
612
147
    switch (*s) {
613
147
    case '-':
614
147
        negative = true;
615
        // Only signed types have an extra value in their negative range.
616
        // Keep the unsigned magnitude limit unchanged to avoid wrapping it to zero.
617
147
        max_val += std::numeric_limits<T>::is_signed;
618
147
        [[fallthrough]];
619
147
    case '+':
620
147
        i = 1;
621
147
    }
622
623
147
    const T max_div_base = max_val / base;
624
147
    const T max_mod_base = max_val % base;
625
626
147
    int first = i;
627
490
    for (; i < len; ++i) {
628
392
        T digit;
629
392
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
630
392
            digit = s[i] - '0';
631
392
        } else if (s[i] >= 'a' && s[i] <= 'z') {
632
0
            digit = (s[i] - 'a' + 10);
633
0
        } else if (s[i] >= 'A' && s[i] <= 'Z') {
634
0
            digit = (s[i] - 'A' + 10);
635
0
        } else {
636
0
            if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
637
                // Reject the string because either the first char was not an alpha/digit,
638
                // or the remaining chars are not all whitespace
639
0
                *result = PARSE_FAILURE;
640
0
                return 0;
641
0
            }
642
            // skip trailing whitespace.
643
0
            break;
644
0
        }
645
646
        // Bail, if we encounter a digit that is not available in base.
647
392
        if (digit >= base) {
648
0
            break;
649
0
        }
650
651
        // This is a tricky check to see if adding this digit will cause an overflow.
652
392
        if (UNLIKELY(val > (max_div_base - (digit > max_mod_base)))) {
653
49
            *result = PARSE_OVERFLOW;
654
49
            return static_cast<T>(negative ? -max_val : max_val);
655
49
        }
656
343
        val = val * base + digit;
657
343
    }
658
98
    *result = PARSE_SUCCESS;
659
98
    return static_cast<T>(negative ? -val : val);
660
147
}
_ZN5doris12StringParser22string_to_int_internalImEET_PKcliPNS0_11ParseResultE
Line
Count
Source
602
3.12k
                                       ParseResult* result) {
603
3.12k
    using UnsignedT = MakeUnsignedT<T>;
604
3.12k
    UnsignedT val = 0;
605
3.12k
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
606
3.12k
    bool negative = false;
607
3.12k
    if (UNLIKELY(len <= 0)) {
608
10
        *result = PARSE_FAILURE;
609
10
        return 0;
610
10
    }
611
3.11k
    int i = 0;
612
3.11k
    switch (*s) {
613
1.34k
    case '-':
614
1.34k
        negative = true;
615
        // Only signed types have an extra value in their negative range.
616
        // Keep the unsigned magnitude limit unchanged to avoid wrapping it to zero.
617
1.34k
        max_val += std::numeric_limits<T>::is_signed;
618
1.34k
        [[fallthrough]];
619
1.34k
    case '+':
620
1.34k
        i = 1;
621
3.11k
    }
622
623
3.11k
    const T max_div_base = max_val / base;
624
3.11k
    const T max_mod_base = max_val % base;
625
626
3.11k
    int first = i;
627
14.2k
    for (; i < len; ++i) {
628
11.4k
        T digit;
629
11.4k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
630
11.2k
            digit = s[i] - '0';
631
11.2k
        } else if (s[i] >= 'a' && s[i] <= 'z') {
632
213
            digit = (s[i] - 'a' + 10);
633
213
        } else if (s[i] >= 'A' && s[i] <= 'Z') {
634
8
            digit = (s[i] - 'A' + 10);
635
8
        } else {
636
8
            if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
637
                // Reject the string because either the first char was not an alpha/digit,
638
                // or the remaining chars are not all whitespace
639
8
                *result = PARSE_FAILURE;
640
8
                return 0;
641
8
            }
642
            // skip trailing whitespace.
643
0
            break;
644
8
        }
645
646
        // Bail, if we encounter a digit that is not available in base.
647
11.4k
        if (digit >= base) {
648
154
            break;
649
154
        }
650
651
        // This is a tricky check to see if adding this digit will cause an overflow.
652
11.2k
        if (UNLIKELY(val > (max_div_base - (digit > max_mod_base)))) {
653
89
            *result = PARSE_OVERFLOW;
654
89
            return static_cast<T>(negative ? -max_val : max_val);
655
89
        }
656
11.1k
        val = val * base + digit;
657
11.1k
    }
658
3.02k
    *result = PARSE_SUCCESS;
659
3.02k
    return static_cast<T>(negative ? -val : val);
660
3.11k
}
661
662
template <typename T, bool enable_strict_mode>
663
296k
T StringParser::string_to_int_no_overflow(const char* __restrict s, int len, ParseResult* result) {
664
296k
    T val = 0;
665
296k
    if (UNLIKELY(len == 0)) {
666
0
        *result = PARSE_SUCCESS;
667
0
        return val;
668
0
    }
669
    // Factor out the first char for error handling speeds up the loop.
670
296k
    if (LIKELY(s[0] >= '0' && s[0] <= '9')) {
671
289k
        val = s[0] - '0';
672
289k
    } else {
673
6.93k
        *result = PARSE_FAILURE;
674
6.93k
        return 0;
675
6.93k
    }
676
583k
    for (int i = 1; i < len; ++i) {
677
298k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
678
294k
            T digit = s[i] - '0';
679
294k
            val = val * 10 + digit;
680
294k
        } else {
681
4.47k
            if constexpr (enable_strict_mode) {
682
1.64k
                if (UNLIKELY(!is_all_whitespace(s + i, len - i))) {
683
1.29k
                    *result = PARSE_FAILURE;
684
1.29k
                    return 0;
685
1.29k
                }
686
2.82k
            } else {
687
                // Save original position where non-digit was found
688
2.82k
                int remaining_len = len - i;
689
2.82k
                const char* remaining_s = s + i;
690
                // Skip trailing whitespaces from the remaining portion
691
2.82k
                remaining_s = skip_trailing_whitespaces(remaining_s, remaining_len);
692
2.82k
                if ((UNLIKELY(remaining_len != 0 &&
693
2.82k
                              !is_float_suffix(remaining_s, remaining_len)))) {
694
496
                    *result = PARSE_FAILURE;
695
496
                    return 0;
696
496
                }
697
2.82k
            }
698
2.67k
            *result = PARSE_SUCCESS;
699
4.47k
            return val;
700
4.47k
        }
701
298k
    }
702
284k
    *result = PARSE_SUCCESS;
703
284k
    return val;
704
289k
}
_ZN5doris12StringParser25string_to_int_no_overflowIoLb0EEET_PKciPNS0_11ParseResultE
Line
Count
Source
663
42.7k
T StringParser::string_to_int_no_overflow(const char* __restrict s, int len, ParseResult* result) {
664
42.7k
    T val = 0;
665
42.7k
    if (UNLIKELY(len == 0)) {
666
0
        *result = PARSE_SUCCESS;
667
0
        return val;
668
0
    }
669
    // Factor out the first char for error handling speeds up the loop.
670
42.7k
    if (LIKELY(s[0] >= '0' && s[0] <= '9')) {
671
41.8k
        val = s[0] - '0';
672
41.8k
    } else {
673
916
        *result = PARSE_FAILURE;
674
916
        return 0;
675
916
    }
676
61.0k
    for (int i = 1; i < len; ++i) {
677
19.5k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
678
19.2k
            T digit = s[i] - '0';
679
19.2k
            val = val * 10 + digit;
680
19.2k
        } else {
681
            if constexpr (enable_strict_mode) {
682
                if (UNLIKELY(!is_all_whitespace(s + i, len - i))) {
683
                    *result = PARSE_FAILURE;
684
                    return 0;
685
                }
686
378
            } else {
687
                // Save original position where non-digit was found
688
378
                int remaining_len = len - i;
689
378
                const char* remaining_s = s + i;
690
                // Skip trailing whitespaces from the remaining portion
691
378
                remaining_s = skip_trailing_whitespaces(remaining_s, remaining_len);
692
378
                if ((UNLIKELY(remaining_len != 0 &&
693
378
                              !is_float_suffix(remaining_s, remaining_len)))) {
694
98
                    *result = PARSE_FAILURE;
695
98
                    return 0;
696
98
                }
697
378
            }
698
280
            *result = PARSE_SUCCESS;
699
378
            return val;
700
378
        }
701
19.5k
    }
702
41.4k
    *result = PARSE_SUCCESS;
703
41.4k
    return val;
704
41.8k
}
_ZN5doris12StringParser25string_to_int_no_overflowIhLb0EEET_PKciPNS0_11ParseResultE
Line
Count
Source
663
61.7k
T StringParser::string_to_int_no_overflow(const char* __restrict s, int len, ParseResult* result) {
664
61.7k
    T val = 0;
665
61.7k
    if (UNLIKELY(len == 0)) {
666
0
        *result = PARSE_SUCCESS;
667
0
        return val;
668
0
    }
669
    // Factor out the first char for error handling speeds up the loop.
670
61.7k
    if (LIKELY(s[0] >= '0' && s[0] <= '9')) {
671
61.1k
        val = s[0] - '0';
672
61.1k
    } else {
673
582
        *result = PARSE_FAILURE;
674
582
        return 0;
675
582
    }
676
86.8k
    for (int i = 1; i < len; ++i) {
677
25.7k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
678
25.7k
            T digit = s[i] - '0';
679
25.7k
            val = val * 10 + digit;
680
25.7k
        } else {
681
            if constexpr (enable_strict_mode) {
682
                if (UNLIKELY(!is_all_whitespace(s + i, len - i))) {
683
                    *result = PARSE_FAILURE;
684
                    return 0;
685
                }
686
2
            } else {
687
                // Save original position where non-digit was found
688
2
                int remaining_len = len - i;
689
2
                const char* remaining_s = s + i;
690
                // Skip trailing whitespaces from the remaining portion
691
2
                remaining_s = skip_trailing_whitespaces(remaining_s, remaining_len);
692
2
                if ((UNLIKELY(remaining_len != 0 &&
693
2
                              !is_float_suffix(remaining_s, remaining_len)))) {
694
2
                    *result = PARSE_FAILURE;
695
2
                    return 0;
696
2
                }
697
2
            }
698
0
            *result = PARSE_SUCCESS;
699
2
            return val;
700
2
        }
701
25.7k
    }
702
61.1k
    *result = PARSE_SUCCESS;
703
61.1k
    return val;
704
61.1k
}
_ZN5doris12StringParser25string_to_int_no_overflowIhLb1EEET_PKciPNS0_11ParseResultE
Line
Count
Source
663
478
T StringParser::string_to_int_no_overflow(const char* __restrict s, int len, ParseResult* result) {
664
478
    T val = 0;
665
478
    if (UNLIKELY(len == 0)) {
666
0
        *result = PARSE_SUCCESS;
667
0
        return val;
668
0
    }
669
    // Factor out the first char for error handling speeds up the loop.
670
478
    if (LIKELY(s[0] >= '0' && s[0] <= '9')) {
671
452
        val = s[0] - '0';
672
452
    } else {
673
26
        *result = PARSE_FAILURE;
674
26
        return 0;
675
26
    }
676
790
    for (int i = 1; i < len; ++i) {
677
340
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
678
338
            T digit = s[i] - '0';
679
338
            val = val * 10 + digit;
680
338
        } else {
681
2
            if constexpr (enable_strict_mode) {
682
2
                if (UNLIKELY(!is_all_whitespace(s + i, len - i))) {
683
2
                    *result = PARSE_FAILURE;
684
2
                    return 0;
685
2
                }
686
            } else {
687
                // Save original position where non-digit was found
688
                int remaining_len = len - i;
689
                const char* remaining_s = s + i;
690
                // Skip trailing whitespaces from the remaining portion
691
                remaining_s = skip_trailing_whitespaces(remaining_s, remaining_len);
692
                if ((UNLIKELY(remaining_len != 0 &&
693
                              !is_float_suffix(remaining_s, remaining_len)))) {
694
                    *result = PARSE_FAILURE;
695
                    return 0;
696
                }
697
            }
698
0
            *result = PARSE_SUCCESS;
699
2
            return val;
700
2
        }
701
340
    }
702
450
    *result = PARSE_SUCCESS;
703
450
    return val;
704
452
}
_ZN5doris12StringParser25string_to_int_no_overflowItLb0EEET_PKciPNS0_11ParseResultE
Line
Count
Source
663
51.9k
T StringParser::string_to_int_no_overflow(const char* __restrict s, int len, ParseResult* result) {
664
51.9k
    T val = 0;
665
51.9k
    if (UNLIKELY(len == 0)) {
666
0
        *result = PARSE_SUCCESS;
667
0
        return val;
668
0
    }
669
    // Factor out the first char for error handling speeds up the loop.
670
51.9k
    if (LIKELY(s[0] >= '0' && s[0] <= '9')) {
671
51.0k
        val = s[0] - '0';
672
51.0k
    } else {
673
918
        *result = PARSE_FAILURE;
674
918
        return 0;
675
918
    }
676
74.4k
    for (int i = 1; i < len; ++i) {
677
24.4k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
678
23.3k
            T digit = s[i] - '0';
679
23.3k
            val = val * 10 + digit;
680
23.3k
        } else {
681
            if constexpr (enable_strict_mode) {
682
                if (UNLIKELY(!is_all_whitespace(s + i, len - i))) {
683
                    *result = PARSE_FAILURE;
684
                    return 0;
685
                }
686
1.01k
            } else {
687
                // Save original position where non-digit was found
688
1.01k
                int remaining_len = len - i;
689
1.01k
                const char* remaining_s = s + i;
690
                // Skip trailing whitespaces from the remaining portion
691
1.01k
                remaining_s = skip_trailing_whitespaces(remaining_s, remaining_len);
692
1.01k
                if ((UNLIKELY(remaining_len != 0 &&
693
1.01k
                              !is_float_suffix(remaining_s, remaining_len)))) {
694
74
                    *result = PARSE_FAILURE;
695
74
                    return 0;
696
74
                }
697
1.01k
            }
698
943
            *result = PARSE_SUCCESS;
699
1.01k
            return val;
700
1.01k
        }
701
24.4k
    }
702
50.0k
    *result = PARSE_SUCCESS;
703
50.0k
    return val;
704
51.0k
}
_ZN5doris12StringParser25string_to_int_no_overflowItLb1EEET_PKciPNS0_11ParseResultE
Line
Count
Source
663
712
T StringParser::string_to_int_no_overflow(const char* __restrict s, int len, ParseResult* result) {
664
712
    T val = 0;
665
712
    if (UNLIKELY(len == 0)) {
666
0
        *result = PARSE_SUCCESS;
667
0
        return val;
668
0
    }
669
    // Factor out the first char for error handling speeds up the loop.
670
712
    if (LIKELY(s[0] >= '0' && s[0] <= '9')) {
671
674
        val = s[0] - '0';
672
674
    } else {
673
38
        *result = PARSE_FAILURE;
674
38
        return 0;
675
38
    }
676
1.72k
    for (int i = 1; i < len; ++i) {
677
1.18k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
678
1.05k
            T digit = s[i] - '0';
679
1.05k
            val = val * 10 + digit;
680
1.05k
        } else {
681
132
            if constexpr (enable_strict_mode) {
682
132
                if (UNLIKELY(!is_all_whitespace(s + i, len - i))) {
683
90
                    *result = PARSE_FAILURE;
684
90
                    return 0;
685
90
                }
686
            } else {
687
                // Save original position where non-digit was found
688
                int remaining_len = len - i;
689
                const char* remaining_s = s + i;
690
                // Skip trailing whitespaces from the remaining portion
691
                remaining_s = skip_trailing_whitespaces(remaining_s, remaining_len);
692
                if ((UNLIKELY(remaining_len != 0 &&
693
                              !is_float_suffix(remaining_s, remaining_len)))) {
694
                    *result = PARSE_FAILURE;
695
                    return 0;
696
                }
697
            }
698
42
            *result = PARSE_SUCCESS;
699
132
            return val;
700
132
        }
701
1.18k
    }
702
542
    *result = PARSE_SUCCESS;
703
542
    return val;
704
674
}
_ZN5doris12StringParser25string_to_int_no_overflowIjLb0EEET_PKciPNS0_11ParseResultE
Line
Count
Source
663
100k
T StringParser::string_to_int_no_overflow(const char* __restrict s, int len, ParseResult* result) {
664
100k
    T val = 0;
665
100k
    if (UNLIKELY(len == 0)) {
666
0
        *result = PARSE_SUCCESS;
667
0
        return val;
668
0
    }
669
    // Factor out the first char for error handling speeds up the loop.
670
100k
    if (LIKELY(s[0] >= '0' && s[0] <= '9')) {
671
97.7k
        val = s[0] - '0';
672
97.7k
    } else {
673
2.49k
        *result = PARSE_FAILURE;
674
2.49k
        return 0;
675
2.49k
    }
676
276k
    for (int i = 1; i < len; ++i) {
677
179k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
678
178k
            T digit = s[i] - '0';
679
178k
            val = val * 10 + digit;
680
178k
        } else {
681
            if constexpr (enable_strict_mode) {
682
                if (UNLIKELY(!is_all_whitespace(s + i, len - i))) {
683
                    *result = PARSE_FAILURE;
684
                    return 0;
685
                }
686
679
            } else {
687
                // Save original position where non-digit was found
688
679
                int remaining_len = len - i;
689
679
                const char* remaining_s = s + i;
690
                // Skip trailing whitespaces from the remaining portion
691
679
                remaining_s = skip_trailing_whitespaces(remaining_s, remaining_len);
692
679
                if ((UNLIKELY(remaining_len != 0 &&
693
679
                              !is_float_suffix(remaining_s, remaining_len)))) {
694
198
                    *result = PARSE_FAILURE;
695
198
                    return 0;
696
198
                }
697
679
            }
698
481
            *result = PARSE_SUCCESS;
699
679
            return val;
700
679
        }
701
179k
    }
702
97.1k
    *result = PARSE_SUCCESS;
703
97.1k
    return val;
704
97.7k
}
_ZN5doris12StringParser25string_to_int_no_overflowIjLb1EEET_PKciPNS0_11ParseResultE
Line
Count
Source
663
1.54k
T StringParser::string_to_int_no_overflow(const char* __restrict s, int len, ParseResult* result) {
664
1.54k
    T val = 0;
665
1.54k
    if (UNLIKELY(len == 0)) {
666
0
        *result = PARSE_SUCCESS;
667
0
        return val;
668
0
    }
669
    // Factor out the first char for error handling speeds up the loop.
670
1.54k
    if (LIKELY(s[0] >= '0' && s[0] <= '9')) {
671
1.36k
        val = s[0] - '0';
672
1.36k
    } else {
673
179
        *result = PARSE_FAILURE;
674
179
        return 0;
675
179
    }
676
4.16k
    for (int i = 1; i < len; ++i) {
677
3.25k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
678
2.79k
            T digit = s[i] - '0';
679
2.79k
            val = val * 10 + digit;
680
2.79k
        } else {
681
460
            if constexpr (enable_strict_mode) {
682
460
                if (UNLIKELY(!is_all_whitespace(s + i, len - i))) {
683
348
                    *result = PARSE_FAILURE;
684
348
                    return 0;
685
348
                }
686
            } else {
687
                // Save original position where non-digit was found
688
                int remaining_len = len - i;
689
                const char* remaining_s = s + i;
690
                // Skip trailing whitespaces from the remaining portion
691
                remaining_s = skip_trailing_whitespaces(remaining_s, remaining_len);
692
                if ((UNLIKELY(remaining_len != 0 &&
693
                              !is_float_suffix(remaining_s, remaining_len)))) {
694
                    *result = PARSE_FAILURE;
695
                    return 0;
696
                }
697
            }
698
112
            *result = PARSE_SUCCESS;
699
460
            return val;
700
460
        }
701
3.25k
    }
702
903
    *result = PARSE_SUCCESS;
703
903
    return val;
704
1.36k
}
_ZN5doris12StringParser25string_to_int_no_overflowImLb0EEET_PKciPNS0_11ParseResultE
Line
Count
Source
663
34.0k
T StringParser::string_to_int_no_overflow(const char* __restrict s, int len, ParseResult* result) {
664
34.0k
    T val = 0;
665
34.0k
    if (UNLIKELY(len == 0)) {
666
0
        *result = PARSE_SUCCESS;
667
0
        return val;
668
0
    }
669
    // Factor out the first char for error handling speeds up the loop.
670
34.0k
    if (LIKELY(s[0] >= '0' && s[0] <= '9')) {
671
32.8k
        val = s[0] - '0';
672
32.8k
    } else {
673
1.20k
        *result = PARSE_FAILURE;
674
1.20k
        return 0;
675
1.20k
    }
676
69.1k
    for (int i = 1; i < len; ++i) {
677
37.0k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
678
36.3k
            T digit = s[i] - '0';
679
36.3k
            val = val * 10 + digit;
680
36.3k
        } else {
681
            if constexpr (enable_strict_mode) {
682
                if (UNLIKELY(!is_all_whitespace(s + i, len - i))) {
683
                    *result = PARSE_FAILURE;
684
                    return 0;
685
                }
686
748
            } else {
687
                // Save original position where non-digit was found
688
748
                int remaining_len = len - i;
689
748
                const char* remaining_s = s + i;
690
                // Skip trailing whitespaces from the remaining portion
691
748
                remaining_s = skip_trailing_whitespaces(remaining_s, remaining_len);
692
748
                if ((UNLIKELY(remaining_len != 0 &&
693
748
                              !is_float_suffix(remaining_s, remaining_len)))) {
694
124
                    *result = PARSE_FAILURE;
695
124
                    return 0;
696
124
                }
697
748
            }
698
624
            *result = PARSE_SUCCESS;
699
748
            return val;
700
748
        }
701
37.0k
    }
702
32.1k
    *result = PARSE_SUCCESS;
703
32.1k
    return val;
704
32.8k
}
_ZN5doris12StringParser25string_to_int_no_overflowImLb1EEET_PKciPNS0_11ParseResultE
Line
Count
Source
663
1.49k
T StringParser::string_to_int_no_overflow(const char* __restrict s, int len, ParseResult* result) {
664
1.49k
    T val = 0;
665
1.49k
    if (UNLIKELY(len == 0)) {
666
0
        *result = PARSE_SUCCESS;
667
0
        return val;
668
0
    }
669
    // Factor out the first char for error handling speeds up the loop.
670
1.49k
    if (LIKELY(s[0] >= '0' && s[0] <= '9')) {
671
1.15k
        val = s[0] - '0';
672
1.15k
    } else {
673
343
        *result = PARSE_FAILURE;
674
343
        return 0;
675
343
    }
676
4.18k
    for (int i = 1; i < len; ++i) {
677
3.62k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
678
3.03k
            T digit = s[i] - '0';
679
3.03k
            val = val * 10 + digit;
680
3.03k
        } else {
681
596
            if constexpr (enable_strict_mode) {
682
596
                if (UNLIKELY(!is_all_whitespace(s + i, len - i))) {
683
456
                    *result = PARSE_FAILURE;
684
456
                    return 0;
685
456
                }
686
            } else {
687
                // Save original position where non-digit was found
688
                int remaining_len = len - i;
689
                const char* remaining_s = s + i;
690
                // Skip trailing whitespaces from the remaining portion
691
                remaining_s = skip_trailing_whitespaces(remaining_s, remaining_len);
692
                if ((UNLIKELY(remaining_len != 0 &&
693
                              !is_float_suffix(remaining_s, remaining_len)))) {
694
                    *result = PARSE_FAILURE;
695
                    return 0;
696
                }
697
            }
698
140
            *result = PARSE_SUCCESS;
699
596
            return val;
700
596
        }
701
3.62k
    }
702
559
    *result = PARSE_SUCCESS;
703
559
    return val;
704
1.15k
}
_ZN5doris12StringParser25string_to_int_no_overflowIoLb1EEET_PKciPNS0_11ParseResultE
Line
Count
Source
663
1.23k
T StringParser::string_to_int_no_overflow(const char* __restrict s, int len, ParseResult* result) {
664
1.23k
    T val = 0;
665
1.23k
    if (UNLIKELY(len == 0)) {
666
0
        *result = PARSE_SUCCESS;
667
0
        return val;
668
0
    }
669
    // Factor out the first char for error handling speeds up the loop.
670
1.23k
    if (LIKELY(s[0] >= '0' && s[0] <= '9')) {
671
992
        val = s[0] - '0';
672
992
    } else {
673
240
        *result = PARSE_FAILURE;
674
240
        return 0;
675
240
    }
676
4.37k
    for (int i = 1; i < len; ++i) {
677
3.84k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
678
3.38k
            T digit = s[i] - '0';
679
3.38k
            val = val * 10 + digit;
680
3.38k
        } else {
681
456
            if constexpr (enable_strict_mode) {
682
456
                if (UNLIKELY(!is_all_whitespace(s + i, len - i))) {
683
400
                    *result = PARSE_FAILURE;
684
400
                    return 0;
685
400
                }
686
            } else {
687
                // Save original position where non-digit was found
688
                int remaining_len = len - i;
689
                const char* remaining_s = s + i;
690
                // Skip trailing whitespaces from the remaining portion
691
                remaining_s = skip_trailing_whitespaces(remaining_s, remaining_len);
692
                if ((UNLIKELY(remaining_len != 0 &&
693
                              !is_float_suffix(remaining_s, remaining_len)))) {
694
                    *result = PARSE_FAILURE;
695
                    return 0;
696
                }
697
            }
698
56
            *result = PARSE_SUCCESS;
699
456
            return val;
700
456
        }
701
3.84k
    }
702
536
    *result = PARSE_SUCCESS;
703
536
    return val;
704
992
}
_ZN5doris12StringParser25string_to_int_no_overflowIN4wide7integerILm256EjEELb0EEET_PKciPNS0_11ParseResultE
Line
Count
Source
663
4
T StringParser::string_to_int_no_overflow(const char* __restrict s, int len, ParseResult* result) {
664
4
    T val = 0;
665
4
    if (UNLIKELY(len == 0)) {
666
0
        *result = PARSE_SUCCESS;
667
0
        return val;
668
0
    }
669
    // Factor out the first char for error handling speeds up the loop.
670
4
    if (LIKELY(s[0] >= '0' && s[0] <= '9')) {
671
4
        val = s[0] - '0';
672
4
    } else {
673
0
        *result = PARSE_FAILURE;
674
0
        return 0;
675
0
    }
676
4
    for (int i = 1; i < len; ++i) {
677
0
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
678
0
            T digit = s[i] - '0';
679
0
            val = val * 10 + digit;
680
0
        } else {
681
            if constexpr (enable_strict_mode) {
682
                if (UNLIKELY(!is_all_whitespace(s + i, len - i))) {
683
                    *result = PARSE_FAILURE;
684
                    return 0;
685
                }
686
0
            } else {
687
                // Save original position where non-digit was found
688
0
                int remaining_len = len - i;
689
0
                const char* remaining_s = s + i;
690
                // Skip trailing whitespaces from the remaining portion
691
0
                remaining_s = skip_trailing_whitespaces(remaining_s, remaining_len);
692
0
                if ((UNLIKELY(remaining_len != 0 &&
693
0
                              !is_float_suffix(remaining_s, remaining_len)))) {
694
0
                    *result = PARSE_FAILURE;
695
0
                    return 0;
696
0
                }
697
0
            }
698
0
            *result = PARSE_SUCCESS;
699
0
            return val;
700
0
        }
701
0
    }
702
4
    *result = PARSE_SUCCESS;
703
4
    return val;
704
4
}
705
706
// at least the first char(if any) must be a digit.
707
template <typename T>
708
T StringParser::string_to_uint_greedy_no_overflow(const char* __restrict s, int max_len,
709
139k
                                                  ParseResult* result) {
710
139k
    T val = 0;
711
139k
    if (max_len == 0) [[unlikely]] {
712
137k
        *result = PARSE_SUCCESS;
713
137k
        return val;
714
137k
    }
715
    // Factor out the first char for error handling speeds up the loop.
716
2.69k
    if (is_numeric_ascii(s[0])) [[likely]] {
717
2.69k
        val = s[0] - '0';
718
2.69k
    } else {
719
0
        *result = PARSE_FAILURE;
720
0
        return 0;
721
0
    }
722
15.2k
    for (int i = 1; i < max_len; ++i) {
723
12.5k
        if (is_numeric_ascii(s[i])) [[likely]] {
724
12.5k
            T digit = s[i] - '0';
725
12.5k
            val = val * 10 + digit;
726
12.5k
        } else {
727
            // 123abc, return 123
728
0
            *result = PARSE_SUCCESS;
729
0
            return val;
730
0
        }
731
12.5k
    }
732
2.69k
    *result = PARSE_SUCCESS;
733
2.69k
    return val;
734
2.69k
}
735
736
template <typename T>
737
155k
T StringParser::string_to_float_internal(const char* __restrict s, int len, ParseResult* result) {
738
155k
    int i = 0;
739
    // skip leading spaces
740
155k
    for (; i < len; ++i) {
741
155k
        if (!is_whitespace_ascii(s[i])) {
742
155k
            break;
743
155k
        }
744
155k
    }
745
746
    // skip back spaces
747
155k
    int j = len - 1;
748
155k
    for (; j >= i; j--) {
749
155k
        if (!is_whitespace_ascii(s[j])) {
750
155k
            break;
751
155k
        }
752
155k
    }
753
754
    // skip leading '+', from_chars can handle '-'
755
155k
    if (i < len && s[i] == '+') {
756
7.08k
        i++;
757
        // ++ or +- are not valid, but the first + is already skipped,
758
        // if don't check here, from_chars will succeed.
759
        //
760
        // New version of fast_float supports a new flag called 'chars_format::allow_leading_plus'
761
        // which may avoid this extra check here.
762
        // e.g.:
763
        // fast_float::chars_format format =
764
        //         fast_float::chars_format::general | fast_float::chars_format::allow_leading_plus;
765
        // auto res = fast_float::from_chars(s + i, s + j + 1, val, format);
766
7.08k
        if (i < len && (s[i] == '+' || s[i] == '-')) {
767
20
            *result = PARSE_FAILURE;
768
20
            return 0;
769
20
        }
770
7.08k
    }
771
155k
    if (UNLIKELY(i > j)) {
772
32
        *result = PARSE_FAILURE;
773
32
        return 0;
774
32
    }
775
776
    // Use double here to not lose precision while accumulating the result
777
155k
    double val = 0;
778
155k
    auto res = fast_float::from_chars(s + i, s + j + 1, val);
779
780
155k
    if (res.ptr == s + j + 1) {
781
151k
        *result = PARSE_SUCCESS;
782
151k
        return val;
783
151k
    } else {
784
4.60k
        *result = PARSE_FAILURE;
785
4.60k
    }
786
4.60k
    return 0;
787
155k
}
_ZN5doris12StringParser24string_to_float_internalIdEET_PKciPNS0_11ParseResultE
Line
Count
Source
737
89.4k
T StringParser::string_to_float_internal(const char* __restrict s, int len, ParseResult* result) {
738
89.4k
    int i = 0;
739
    // skip leading spaces
740
89.4k
    for (; i < len; ++i) {
741
89.4k
        if (!is_whitespace_ascii(s[i])) {
742
89.4k
            break;
743
89.4k
        }
744
89.4k
    }
745
746
    // skip back spaces
747
89.4k
    int j = len - 1;
748
89.4k
    for (; j >= i; j--) {
749
89.4k
        if (!is_whitespace_ascii(s[j])) {
750
89.4k
            break;
751
89.4k
        }
752
89.4k
    }
753
754
    // skip leading '+', from_chars can handle '-'
755
89.4k
    if (i < len && s[i] == '+') {
756
3.54k
        i++;
757
        // ++ or +- are not valid, but the first + is already skipped,
758
        // if don't check here, from_chars will succeed.
759
        //
760
        // New version of fast_float supports a new flag called 'chars_format::allow_leading_plus'
761
        // which may avoid this extra check here.
762
        // e.g.:
763
        // fast_float::chars_format format =
764
        //         fast_float::chars_format::general | fast_float::chars_format::allow_leading_plus;
765
        // auto res = fast_float::from_chars(s + i, s + j + 1, val, format);
766
3.54k
        if (i < len && (s[i] == '+' || s[i] == '-')) {
767
10
            *result = PARSE_FAILURE;
768
10
            return 0;
769
10
        }
770
3.54k
    }
771
89.4k
    if (UNLIKELY(i > j)) {
772
18
        *result = PARSE_FAILURE;
773
18
        return 0;
774
18
    }
775
776
    // Use double here to not lose precision while accumulating the result
777
89.4k
    double val = 0;
778
89.4k
    auto res = fast_float::from_chars(s + i, s + j + 1, val);
779
780
89.4k
    if (res.ptr == s + j + 1) {
781
87.1k
        *result = PARSE_SUCCESS;
782
87.1k
        return val;
783
87.1k
    } else {
784
2.32k
        *result = PARSE_FAILURE;
785
2.32k
    }
786
2.32k
    return 0;
787
89.4k
}
_ZN5doris12StringParser24string_to_float_internalIfEET_PKciPNS0_11ParseResultE
Line
Count
Source
737
66.4k
T StringParser::string_to_float_internal(const char* __restrict s, int len, ParseResult* result) {
738
66.4k
    int i = 0;
739
    // skip leading spaces
740
66.4k
    for (; i < len; ++i) {
741
66.4k
        if (!is_whitespace_ascii(s[i])) {
742
66.4k
            break;
743
66.4k
        }
744
66.4k
    }
745
746
    // skip back spaces
747
66.4k
    int j = len - 1;
748
66.4k
    for (; j >= i; j--) {
749
66.4k
        if (!is_whitespace_ascii(s[j])) {
750
66.4k
            break;
751
66.4k
        }
752
66.4k
    }
753
754
    // skip leading '+', from_chars can handle '-'
755
66.4k
    if (i < len && s[i] == '+') {
756
3.54k
        i++;
757
        // ++ or +- are not valid, but the first + is already skipped,
758
        // if don't check here, from_chars will succeed.
759
        //
760
        // New version of fast_float supports a new flag called 'chars_format::allow_leading_plus'
761
        // which may avoid this extra check here.
762
        // e.g.:
763
        // fast_float::chars_format format =
764
        //         fast_float::chars_format::general | fast_float::chars_format::allow_leading_plus;
765
        // auto res = fast_float::from_chars(s + i, s + j + 1, val, format);
766
3.54k
        if (i < len && (s[i] == '+' || s[i] == '-')) {
767
10
            *result = PARSE_FAILURE;
768
10
            return 0;
769
10
        }
770
3.54k
    }
771
66.4k
    if (UNLIKELY(i > j)) {
772
14
        *result = PARSE_FAILURE;
773
14
        return 0;
774
14
    }
775
776
    // Use double here to not lose precision while accumulating the result
777
66.4k
    double val = 0;
778
66.4k
    auto res = fast_float::from_chars(s + i, s + j + 1, val);
779
780
66.4k
    if (res.ptr == s + j + 1) {
781
64.1k
        *result = PARSE_SUCCESS;
782
64.1k
        return val;
783
64.1k
    } else {
784
2.28k
        *result = PARSE_FAILURE;
785
2.28k
    }
786
2.28k
    return 0;
787
66.4k
}
788
789
inline bool StringParser::string_to_bool_internal(const char* __restrict s, int len,
790
12.0k
                                                  ParseResult* result) {
791
12.0k
    *result = PARSE_SUCCESS;
792
793
12.0k
    if (len == 1) {
794
3.36k
        if (s[0] == '1' || s[0] == 't' || s[0] == 'T') {
795
751
            return true;
796
751
        }
797
2.61k
        if (s[0] == '0' || s[0] == 'f' || s[0] == 'F') {
798
1.21k
            return false;
799
1.21k
        }
800
1.39k
        *result = PARSE_FAILURE;
801
1.39k
        return false;
802
2.61k
    }
803
804
8.72k
    if (len == 2) {
805
975
        if ((s[0] == 'o' || s[0] == 'O') && (s[1] == 'n' || s[1] == 'N')) {
806
10
            return true;
807
10
        }
808
965
        if ((s[0] == 'n' || s[0] == 'N') && (s[1] == 'o' || s[1] == 'O')) {
809
9
            return false;
810
9
        }
811
965
    }
812
813
8.70k
    if (len == 3) {
814
42
        if ((s[0] == 'y' || s[0] == 'Y') && (s[1] == 'e' || s[1] == 'E') &&
815
42
            (s[2] == 's' || s[2] == 'S')) {
816
10
            return true;
817
10
        }
818
32
        if ((s[0] == 'o' || s[0] == 'O') && (s[1] == 'f' || s[1] == 'F') &&
819
32
            (s[2] == 'f' || s[2] == 'F')) {
820
9
            return false;
821
9
        }
822
32
    }
823
824
8.68k
    if (len == 4 && (s[0] == 't' || s[0] == 'T') && (s[1] == 'r' || s[1] == 'R') &&
825
8.68k
        (s[2] == 'u' || s[2] == 'U') && (s[3] == 'e' || s[3] == 'E')) {
826
3.38k
        return true;
827
3.38k
    }
828
829
5.30k
    if (len == 5 && (s[0] == 'f' || s[0] == 'F') && (s[1] == 'a' || s[1] == 'A') &&
830
5.30k
        (s[2] == 'l' || s[2] == 'L') && (s[3] == 's' || s[3] == 'S') &&
831
5.30k
        (s[4] == 'e' || s[4] == 'E')) {
832
3.42k
        return false;
833
3.42k
    }
834
835
    // No valid boolean value found
836
1.87k
    *result = PARSE_FAILURE;
837
1.87k
    return false;
838
5.30k
}
839
#include "common/compile_check_avoid_end.h"
840
} // end namespace doris