Coverage Report

Created: 2025-11-20 04:52

/root/doris/be/src/util/string_parser.hpp
Line
Count
Source (jump to first uncovered line)
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
27
#include <cstdlib>
28
// IWYU pragma: no_include <bits/std_abs.h>
29
#include <cmath> // IWYU pragma: keep
30
#include <cstdint>
31
#include <limits>
32
#include <map>
33
#include <string>
34
#include <system_error>
35
#include <type_traits>
36
#include <utility>
37
38
#include "common/compiler_util.h" // IWYU pragma: keep
39
#include "common/status.h"
40
#include "runtime/large_int_value.h"
41
#include "runtime/primitive_type.h"
42
#include "vec/common/int_exp.h"
43
#include "vec/common/string_utils/string_utils.h"
44
#include "vec/core/extended_types.h"
45
#include "vec/core/wide_integer.h"
46
#include "vec/data_types/data_type_decimal.h"
47
#include "vec/data_types/number_traits.h"
48
49
namespace doris {
50
namespace vectorized {
51
template <DecimalNativeTypeConcept T>
52
struct Decimal;
53
} // namespace vectorized
54
55
// Utility functions for doing atoi/atof on non-null terminated strings.  On micro benchmarks,
56
// this is significantly faster than libc (atoi/strtol and atof/strtod).
57
//
58
// Strings with leading and trailing whitespaces are accepted.
59
// Branching is heavily optimized for the non-whitespace successful case.
60
// All the StringTo* functions first parse the input string assuming it has no leading whitespace.
61
// If that first attempt was unsuccessful, these functions retry the parsing after removing
62
// whitespace. Therefore, strings with whitespace take a perf hit on branch mis-prediction.
63
//
64
// For overflows, we are following the mysql behavior, to cap values at the max/min value for that
65
// data type.  This is different from hive, which returns NULL for overflow slots for int types
66
// and inf/-inf for float types.
67
//
68
// Things we tried that did not work:
69
//  - lookup table for converting character to digit
70
// Improvements (TODO):
71
//  - Validate input using _sidd_compare_ranges
72
//  - Since we know the length, we can parallelize this: i.e. result = 100*s[0] + 10*s[1] + s[2]
73
class StringParser {
74
public:
75
    enum ParseResult { PARSE_SUCCESS = 0, PARSE_FAILURE, PARSE_OVERFLOW, PARSE_UNDERFLOW };
76
77
    template <typename T>
78
243k
    static T numeric_limits(bool negative) {
79
243k
        if constexpr (std::is_same_v<T, __int128>) {
  Branch (79:23): [Folded - Ignored]
  Branch (79:23): [Folded - Ignored]
  Branch (79:23): [Folded - Ignored]
  Branch (79:23): [Folded - Ignored]
  Branch (79:23): [Folded - Ignored]
  Branch (79:23): [Folded - Ignored]
  Branch (79:23): [Folded - Ignored]
  Branch (79:23): [Folded - Ignored]
  Branch (79:23): [Folded - Ignored]
  Branch (79:23): [Folded - Ignored]
  Branch (79:23): [Folded - Ignored]
80
123k
            return negative ? MIN_INT128 : MAX_INT128;
  Branch (80:20): [True: 0, False: 119k]
81
123k
        } else {
82
123k
            return negative ? std::numeric_limits<T>::min() : std::numeric_limits<T>::max();
  Branch (82:20): [True: 0, False: 115k]
  Branch (82:20): [True: 0, False: 1.97k]
  Branch (82:20): [True: 0, False: 3.82k]
  Branch (82:20): [True: 0, False: 2.10k]
  Branch (82:20): [True: 0, False: 0]
  Branch (82:20): [True: 0, False: 0]
  Branch (82:20): [True: 0, False: 21]
  Branch (82:20): [True: 0, False: 0]
  Branch (82:20): [True: 0, False: 93]
  Branch (82:20): [True: 0, False: 0]
83
123k
        }
84
243k
    }
_ZN5doris12StringParser14numeric_limitsIaEET_b
Line
Count
Source
78
115k
    static T numeric_limits(bool negative) {
79
115k
        if constexpr (std::is_same_v<T, __int128>) {
  Branch (79:23): [Folded - Ignored]
80
115k
            return negative ? MIN_INT128 : MAX_INT128;
81
115k
        } else {
82
115k
            return negative ? std::numeric_limits<T>::min() : std::numeric_limits<T>::max();
  Branch (82:20): [True: 0, False: 115k]
83
115k
        }
84
115k
    }
_ZN5doris12StringParser14numeric_limitsInEET_b
Line
Count
Source
78
119k
    static T numeric_limits(bool negative) {
79
119k
        if constexpr (std::is_same_v<T, __int128>) {
  Branch (79:23): [Folded - Ignored]
80
119k
            return negative ? MIN_INT128 : MAX_INT128;
  Branch (80:20): [True: 0, False: 119k]
81
119k
        } else {
82
119k
            return negative ? std::numeric_limits<T>::min() : std::numeric_limits<T>::max();
83
119k
        }
84
119k
    }
_ZN5doris12StringParser14numeric_limitsIsEET_b
Line
Count
Source
78
1.97k
    static T numeric_limits(bool negative) {
79
1.97k
        if constexpr (std::is_same_v<T, __int128>) {
  Branch (79:23): [Folded - Ignored]
80
1.97k
            return negative ? MIN_INT128 : MAX_INT128;
81
1.97k
        } else {
82
1.97k
            return negative ? std::numeric_limits<T>::min() : std::numeric_limits<T>::max();
  Branch (82:20): [True: 0, False: 1.97k]
83
1.97k
        }
84
1.97k
    }
_ZN5doris12StringParser14numeric_limitsIiEET_b
Line
Count
Source
78
3.82k
    static T numeric_limits(bool negative) {
79
3.82k
        if constexpr (std::is_same_v<T, __int128>) {
  Branch (79:23): [Folded - Ignored]
80
3.82k
            return negative ? MIN_INT128 : MAX_INT128;
81
3.82k
        } else {
82
3.82k
            return negative ? std::numeric_limits<T>::min() : std::numeric_limits<T>::max();
  Branch (82:20): [True: 0, False: 3.82k]
83
3.82k
        }
84
3.82k
    }
_ZN5doris12StringParser14numeric_limitsIlEET_b
Line
Count
Source
78
2.10k
    static T numeric_limits(bool negative) {
79
2.10k
        if constexpr (std::is_same_v<T, __int128>) {
  Branch (79:23): [Folded - Ignored]
80
2.10k
            return negative ? MIN_INT128 : MAX_INT128;
81
2.10k
        } else {
82
2.10k
            return negative ? std::numeric_limits<T>::min() : std::numeric_limits<T>::max();
  Branch (82:20): [True: 0, False: 2.10k]
83
2.10k
        }
84
2.10k
    }
Unexecuted instantiation: _ZN5doris12StringParser14numeric_limitsIN4wide7integerILm256EiEEEET_b
Unexecuted instantiation: _ZN5doris12StringParser14numeric_limitsIoEET_b
_ZN5doris12StringParser14numeric_limitsImEET_b
Line
Count
Source
78
21
    static T numeric_limits(bool negative) {
79
21
        if constexpr (std::is_same_v<T, __int128>) {
  Branch (79:23): [Folded - Ignored]
80
21
            return negative ? MIN_INT128 : MAX_INT128;
81
21
        } else {
82
21
            return negative ? std::numeric_limits<T>::min() : std::numeric_limits<T>::max();
  Branch (82:20): [True: 0, False: 21]
83
21
        }
84
21
    }
Unexecuted instantiation: _ZN5doris12StringParser14numeric_limitsIjEET_b
_ZN5doris12StringParser14numeric_limitsIhEET_b
Line
Count
Source
78
93
    static T numeric_limits(bool negative) {
79
93
        if constexpr (std::is_same_v<T, __int128>) {
  Branch (79:23): [Folded - Ignored]
80
93
            return negative ? MIN_INT128 : MAX_INT128;
81
93
        } else {
82
93
            return negative ? std::numeric_limits<T>::min() : std::numeric_limits<T>::max();
  Branch (82:20): [True: 0, False: 93]
83
93
        }
84
93
    }
Unexecuted instantiation: _ZN5doris12StringParser14numeric_limitsItEET_b
85
86
    template <typename T>
87
132
    static T get_scale_multiplier(int scale) {
88
132
        static_assert(std::is_same_v<T, int32_t> || std::is_same_v<T, int64_t> ||
89
132
                              std::is_same_v<T, __int128> || std::is_same_v<T, wide::Int256>,
90
132
                      "You can only instantiate as int32_t, int64_t, __int128.");
91
132
        if constexpr (std::is_same_v<T, int32_t>) {
  Branch (91:23): [Folded - Ignored]
  Branch (91:23): [Folded - Ignored]
  Branch (91:23): [Folded - Ignored]
  Branch (91:23): [Folded - Ignored]
92
116
            return common::exp10_i32(scale);
93
116
        } else if constexpr (std::is_same_v<T, int64_t>) {
  Branch (93:30): [Folded - Ignored]
  Branch (93:30): [Folded - Ignored]
  Branch (93:30): [Folded - Ignored]
94
109
            return common::exp10_i64(scale);
95
109
        } else if constexpr (std::is_same_v<T, __int128>) {
  Branch (95:30): [Folded - Ignored]
  Branch (95:30): [Folded - Ignored]
96
0
            return common::exp10_i128(scale);
97
0
        } else if constexpr (std::is_same_v<T, wide::Int256>) {
  Branch (97:30): [Folded - Ignored]
98
0
            return common::exp10_i256(scale);
99
0
        }
100
132
    }
_ZN5doris12StringParser20get_scale_multiplierIiEET_i
Line
Count
Source
87
16
    static T get_scale_multiplier(int scale) {
88
16
        static_assert(std::is_same_v<T, int32_t> || std::is_same_v<T, int64_t> ||
89
16
                              std::is_same_v<T, __int128> || std::is_same_v<T, wide::Int256>,
90
16
                      "You can only instantiate as int32_t, int64_t, __int128.");
91
16
        if constexpr (std::is_same_v<T, int32_t>) {
  Branch (91:23): [Folded - Ignored]
92
16
            return common::exp10_i32(scale);
93
16
        } else if constexpr (std::is_same_v<T, int64_t>) {
94
16
            return common::exp10_i64(scale);
95
16
        } else if constexpr (std::is_same_v<T, __int128>) {
96
16
            return common::exp10_i128(scale);
97
16
        } else if constexpr (std::is_same_v<T, wide::Int256>) {
98
16
            return common::exp10_i256(scale);
99
16
        }
100
16
    }
_ZN5doris12StringParser20get_scale_multiplierIlEET_i
Line
Count
Source
87
7
    static T get_scale_multiplier(int scale) {
88
7
        static_assert(std::is_same_v<T, int32_t> || std::is_same_v<T, int64_t> ||
89
7
                              std::is_same_v<T, __int128> || std::is_same_v<T, wide::Int256>,
90
7
                      "You can only instantiate as int32_t, int64_t, __int128.");
91
7
        if constexpr (std::is_same_v<T, int32_t>) {
  Branch (91:23): [Folded - Ignored]
92
7
            return common::exp10_i32(scale);
93
7
        } else if constexpr (std::is_same_v<T, int64_t>) {
  Branch (93:30): [Folded - Ignored]
94
7
            return common::exp10_i64(scale);
95
7
        } else if constexpr (std::is_same_v<T, __int128>) {
96
7
            return common::exp10_i128(scale);
97
7
        } else if constexpr (std::is_same_v<T, wide::Int256>) {
98
7
            return common::exp10_i256(scale);
99
7
        }
100
7
    }
_ZN5doris12StringParser20get_scale_multiplierInEET_i
Line
Count
Source
87
109
    static T get_scale_multiplier(int scale) {
88
109
        static_assert(std::is_same_v<T, int32_t> || std::is_same_v<T, int64_t> ||
89
109
                              std::is_same_v<T, __int128> || std::is_same_v<T, wide::Int256>,
90
109
                      "You can only instantiate as int32_t, int64_t, __int128.");
91
109
        if constexpr (std::is_same_v<T, int32_t>) {
  Branch (91:23): [Folded - Ignored]
92
109
            return common::exp10_i32(scale);
93
109
        } else if constexpr (std::is_same_v<T, int64_t>) {
  Branch (93:30): [Folded - Ignored]
94
109
            return common::exp10_i64(scale);
95
109
        } else if constexpr (std::is_same_v<T, __int128>) {
  Branch (95:30): [Folded - Ignored]
96
109
            return common::exp10_i128(scale);
97
109
        } else if constexpr (std::is_same_v<T, wide::Int256>) {
98
109
            return common::exp10_i256(scale);
99
109
        }
100
109
    }
Unexecuted instantiation: _ZN5doris12StringParser20get_scale_multiplierIN4wide7integerILm256EiEEEET_i
101
102
    // This is considerably faster than glibc's implementation (25x).
103
    // In the case of overflow, the max/min value for the data type will be returned.
104
    // Assumes s represents a decimal number.
105
    template <typename T>
106
149k
    static inline T string_to_int(const char* __restrict s, int len, ParseResult* result) {
107
149k
        T ans = string_to_int_internal<T>(s, len, result);
108
149k
        if (LIKELY(*result == PARSE_SUCCESS)) {
Line
Count
Source
35
119k
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 119k, False: 6]
        if (LIKELY(*result == PARSE_SUCCESS)) {
Line
Count
Source
35
26.3k
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 1.85k, False: 24.4k]
        if (LIKELY(*result == PARSE_SUCCESS)) {
Line
Count
Source
35
451
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 52, False: 399]
        if (LIKELY(*result == PARSE_SUCCESS)) {
Line
Count
Source
35
2.51k
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 90, False: 2.42k]
        if (LIKELY(*result == PARSE_SUCCESS)) {
Line
Count
Source
35
663
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 258, False: 405]
        if (LIKELY(*result == PARSE_SUCCESS)) {
Line
Count
Source
35
0
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 0, False: 0]
        if (LIKELY(*result == PARSE_SUCCESS)) {
Line
Count
Source
35
0
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 0, False: 0]
        if (LIKELY(*result == PARSE_SUCCESS)) {
Line
Count
Source
35
20
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 20, False: 0]
        if (LIKELY(*result == PARSE_SUCCESS)) {
Line
Count
Source
35
0
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 0, False: 0]
        if (LIKELY(*result == PARSE_SUCCESS)) {
Line
Count
Source
35
64
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 35, False: 29]
        if (LIKELY(*result == PARSE_SUCCESS)) {
Line
Count
Source
35
0
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 0, False: 0]
109
121k
            return ans;
110
121k
        }
111
112
27.7k
        int i = skip_leading_whitespace(s, len);
113
27.7k
        return string_to_int_internal<T>(s + i, len - i, result);
114
149k
    }
_ZN5doris12StringParser13string_to_intInEET_PKciPNS0_11ParseResultE
Line
Count
Source
106
119k
    static inline T string_to_int(const char* __restrict s, int len, ParseResult* result) {
107
119k
        T ans = string_to_int_internal<T>(s, len, result);
108
119k
        if (LIKELY(*result == PARSE_SUCCESS)) {
Line
Count
Source
35
119k
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 119k, False: 6]
109
119k
            return ans;
110
119k
        }
111
112
6
        int i = skip_leading_whitespace(s, len);
113
6
        return string_to_int_internal<T>(s + i, len - i, result);
114
119k
    }
_ZN5doris12StringParser13string_to_intIaEET_PKciPNS0_11ParseResultE
Line
Count
Source
106
26.3k
    static inline T string_to_int(const char* __restrict s, int len, ParseResult* result) {
107
26.3k
        T ans = string_to_int_internal<T>(s, len, result);
108
26.3k
        if (LIKELY(*result == PARSE_SUCCESS)) {
Line
Count
Source
35
26.3k
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 1.85k, False: 24.4k]
109
1.85k
            return ans;
110
1.85k
        }
111
112
24.4k
        int i = skip_leading_whitespace(s, len);
113
24.4k
        return string_to_int_internal<T>(s + i, len - i, result);
114
26.3k
    }
_ZN5doris12StringParser13string_to_intIsEET_PKciPNS0_11ParseResultE
Line
Count
Source
106
451
    static inline T string_to_int(const char* __restrict s, int len, ParseResult* result) {
107
451
        T ans = string_to_int_internal<T>(s, len, result);
108
451
        if (LIKELY(*result == PARSE_SUCCESS)) {
Line
Count
Source
35
451
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 52, False: 399]
109
52
            return ans;
110
52
        }
111
112
399
        int i = skip_leading_whitespace(s, len);
113
399
        return string_to_int_internal<T>(s + i, len - i, result);
114
451
    }
_ZN5doris12StringParser13string_to_intIiEET_PKciPNS0_11ParseResultE
Line
Count
Source
106
2.51k
    static inline T string_to_int(const char* __restrict s, int len, ParseResult* result) {
107
2.51k
        T ans = string_to_int_internal<T>(s, len, result);
108
2.51k
        if (LIKELY(*result == PARSE_SUCCESS)) {
Line
Count
Source
35
2.51k
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 90, False: 2.42k]
109
90
            return ans;
110
90
        }
111
112
2.42k
        int i = skip_leading_whitespace(s, len);
113
2.42k
        return string_to_int_internal<T>(s + i, len - i, result);
114
2.51k
    }
_ZN5doris12StringParser13string_to_intIlEET_PKciPNS0_11ParseResultE
Line
Count
Source
106
663
    static inline T string_to_int(const char* __restrict s, int len, ParseResult* result) {
107
663
        T ans = string_to_int_internal<T>(s, len, result);
108
663
        if (LIKELY(*result == PARSE_SUCCESS)) {
Line
Count
Source
35
663
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 258, False: 405]
109
258
            return ans;
110
258
        }
111
112
405
        int i = skip_leading_whitespace(s, len);
113
405
        return string_to_int_internal<T>(s + i, len - i, result);
114
663
    }
Unexecuted instantiation: _ZN5doris12StringParser13string_to_intIN4wide7integerILm256EiEEEET_PKciPNS0_11ParseResultE
Unexecuted instantiation: _ZN5doris12StringParser13string_to_intIoEET_PKciPNS0_11ParseResultE
_ZN5doris12StringParser13string_to_intImEET_PKciPNS0_11ParseResultE
Line
Count
Source
106
20
    static inline T string_to_int(const char* __restrict s, int len, ParseResult* result) {
107
20
        T ans = string_to_int_internal<T>(s, len, result);
108
20
        if (LIKELY(*result == PARSE_SUCCESS)) {
Line
Count
Source
35
20
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 20, False: 0]
109
20
            return ans;
110
20
        }
111
112
0
        int i = skip_leading_whitespace(s, len);
113
0
        return string_to_int_internal<T>(s + i, len - i, result);
114
20
    }
Unexecuted instantiation: _ZN5doris12StringParser13string_to_intIjEET_PKciPNS0_11ParseResultE
_ZN5doris12StringParser13string_to_intIhEET_PKciPNS0_11ParseResultE
Line
Count
Source
106
64
    static inline T string_to_int(const char* __restrict s, int len, ParseResult* result) {
107
64
        T ans = string_to_int_internal<T>(s, len, result);
108
64
        if (LIKELY(*result == PARSE_SUCCESS)) {
Line
Count
Source
35
64
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 35, False: 29]
109
35
            return ans;
110
35
        }
111
112
29
        int i = skip_leading_whitespace(s, len);
113
29
        return string_to_int_internal<T>(s + i, len - i, result);
114
64
    }
Unexecuted instantiation: _ZN5doris12StringParser13string_to_intItEET_PKciPNS0_11ParseResultE
115
116
    // This is considerably faster than glibc's implementation.
117
    // In the case of overflow, the max/min value for the data type will be returned.
118
    // Assumes s represents a decimal number.
119
    template <typename T>
120
1.37k
    static inline T string_to_unsigned_int(const char* __restrict s, int len, ParseResult* result) {
121
1.37k
        T ans = string_to_unsigned_int_internal<T>(s, len, result);
122
1.37k
        if (LIKELY(*result == PARSE_SUCCESS)) {
Line
Count
Source
35
343
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 21, False: 322]
        if (LIKELY(*result == PARSE_SUCCESS)) {
Line
Count
Source
35
343
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 21, False: 322]
        if (LIKELY(*result == PARSE_SUCCESS)) {
Line
Count
Source
35
343
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 21, False: 322]
        if (LIKELY(*result == PARSE_SUCCESS)) {
Line
Count
Source
35
343
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 21, False: 322]
123
84
            return ans;
124
84
        }
125
126
1.28k
        int i = skip_leading_whitespace(s, len);
127
1.28k
        return string_to_unsigned_int_internal<T>(s + i, len - i, result);
128
1.37k
    }
_ZN5doris12StringParser22string_to_unsigned_intIhEET_PKciPNS0_11ParseResultE
Line
Count
Source
120
343
    static inline T string_to_unsigned_int(const char* __restrict s, int len, ParseResult* result) {
121
343
        T ans = string_to_unsigned_int_internal<T>(s, len, result);
122
343
        if (LIKELY(*result == PARSE_SUCCESS)) {
Line
Count
Source
35
343
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 21, False: 322]
123
21
            return ans;
124
21
        }
125
126
322
        int i = skip_leading_whitespace(s, len);
127
322
        return string_to_unsigned_int_internal<T>(s + i, len - i, result);
128
343
    }
_ZN5doris12StringParser22string_to_unsigned_intItEET_PKciPNS0_11ParseResultE
Line
Count
Source
120
343
    static inline T string_to_unsigned_int(const char* __restrict s, int len, ParseResult* result) {
121
343
        T ans = string_to_unsigned_int_internal<T>(s, len, result);
122
343
        if (LIKELY(*result == PARSE_SUCCESS)) {
Line
Count
Source
35
343
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 21, False: 322]
123
21
            return ans;
124
21
        }
125
126
322
        int i = skip_leading_whitespace(s, len);
127
322
        return string_to_unsigned_int_internal<T>(s + i, len - i, result);
128
343
    }
_ZN5doris12StringParser22string_to_unsigned_intIjEET_PKciPNS0_11ParseResultE
Line
Count
Source
120
343
    static inline T string_to_unsigned_int(const char* __restrict s, int len, ParseResult* result) {
121
343
        T ans = string_to_unsigned_int_internal<T>(s, len, result);
122
343
        if (LIKELY(*result == PARSE_SUCCESS)) {
Line
Count
Source
35
343
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 21, False: 322]
123
21
            return ans;
124
21
        }
125
126
322
        int i = skip_leading_whitespace(s, len);
127
322
        return string_to_unsigned_int_internal<T>(s + i, len - i, result);
128
343
    }
_ZN5doris12StringParser22string_to_unsigned_intImEET_PKciPNS0_11ParseResultE
Line
Count
Source
120
343
    static inline T string_to_unsigned_int(const char* __restrict s, int len, ParseResult* result) {
121
343
        T ans = string_to_unsigned_int_internal<T>(s, len, result);
122
343
        if (LIKELY(*result == PARSE_SUCCESS)) {
Line
Count
Source
35
343
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 21, False: 322]
123
21
            return ans;
124
21
        }
125
126
322
        int i = skip_leading_whitespace(s, len);
127
322
        return string_to_unsigned_int_internal<T>(s + i, len - i, result);
128
343
    }
129
130
    // Convert a string s representing a number in given base into a decimal number.
131
    template <typename T>
132
    static inline T string_to_int(const char* __restrict s, int len, int base,
133
27.8k
                                  ParseResult* result) {
134
27.8k
        T ans = string_to_int_internal<T>(s, len, base, result);
135
27.8k
        if (LIKELY(*result == PARSE_SUCCESS)) {
Line
Count
Source
35
26.4k
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 1.91k, False: 24.5k]
        if (LIKELY(*result == PARSE_SUCCESS)) {
Line
Count
Source
35
490
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 56, False: 434]
        if (LIKELY(*result == PARSE_SUCCESS)) {
Line
Count
Source
35
441
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 49, False: 392]
        if (LIKELY(*result == PARSE_SUCCESS)) {
Line
Count
Source
35
441
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 49, False: 392]
        if (LIKELY(*result == PARSE_SUCCESS)) {
Line
Count
Source
35
1
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 1, False: 0]
136
2.06k
            return ans;
137
2.06k
        }
138
139
25.7k
        int i = skip_leading_whitespace(s, len);
140
25.7k
        return string_to_int_internal<T>(s + i, len - i, base, result);
141
27.8k
    }
_ZN5doris12StringParser13string_to_intIaEET_PKciiPNS0_11ParseResultE
Line
Count
Source
133
26.4k
                                  ParseResult* result) {
134
26.4k
        T ans = string_to_int_internal<T>(s, len, base, result);
135
26.4k
        if (LIKELY(*result == PARSE_SUCCESS)) {
Line
Count
Source
35
26.4k
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 1.91k, False: 24.5k]
136
1.91k
            return ans;
137
1.91k
        }
138
139
24.5k
        int i = skip_leading_whitespace(s, len);
140
24.5k
        return string_to_int_internal<T>(s + i, len - i, base, result);
141
26.4k
    }
_ZN5doris12StringParser13string_to_intIsEET_PKciiPNS0_11ParseResultE
Line
Count
Source
133
490
                                  ParseResult* result) {
134
490
        T ans = string_to_int_internal<T>(s, len, base, result);
135
490
        if (LIKELY(*result == PARSE_SUCCESS)) {
Line
Count
Source
35
490
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 56, False: 434]
136
56
            return ans;
137
56
        }
138
139
434
        int i = skip_leading_whitespace(s, len);
140
434
        return string_to_int_internal<T>(s + i, len - i, base, result);
141
490
    }
_ZN5doris12StringParser13string_to_intIiEET_PKciiPNS0_11ParseResultE
Line
Count
Source
133
441
                                  ParseResult* result) {
134
441
        T ans = string_to_int_internal<T>(s, len, base, result);
135
441
        if (LIKELY(*result == PARSE_SUCCESS)) {
Line
Count
Source
35
441
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 49, False: 392]
136
49
            return ans;
137
49
        }
138
139
392
        int i = skip_leading_whitespace(s, len);
140
392
        return string_to_int_internal<T>(s + i, len - i, base, result);
141
441
    }
_ZN5doris12StringParser13string_to_intIlEET_PKciiPNS0_11ParseResultE
Line
Count
Source
133
441
                                  ParseResult* result) {
134
441
        T ans = string_to_int_internal<T>(s, len, base, result);
135
441
        if (LIKELY(*result == PARSE_SUCCESS)) {
Line
Count
Source
35
441
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 49, False: 392]
136
49
            return ans;
137
49
        }
138
139
392
        int i = skip_leading_whitespace(s, len);
140
392
        return string_to_int_internal<T>(s + i, len - i, base, result);
141
441
    }
_ZN5doris12StringParser13string_to_intImEET_PKciiPNS0_11ParseResultE
Line
Count
Source
133
1
                                  ParseResult* result) {
134
1
        T ans = string_to_int_internal<T>(s, len, base, result);
135
1
        if (LIKELY(*result == PARSE_SUCCESS)) {
Line
Count
Source
35
1
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 1, False: 0]
136
1
            return ans;
137
1
        }
138
139
0
        int i = skip_leading_whitespace(s, len);
140
0
        return string_to_int_internal<T>(s + i, len - i, base, result);
141
1
    }
142
143
    template <typename T>
144
66.9k
    static inline T string_to_float(const char* __restrict s, int len, ParseResult* result) {
145
66.9k
        return string_to_float_internal<T>(s, len, result);
146
66.9k
    }
_ZN5doris12StringParser15string_to_floatIdEET_PKciPNS0_11ParseResultE
Line
Count
Source
144
58.6k
    static inline T string_to_float(const char* __restrict s, int len, ParseResult* result) {
145
58.6k
        return string_to_float_internal<T>(s, len, result);
146
58.6k
    }
_ZN5doris12StringParser15string_to_floatIfEET_PKciPNS0_11ParseResultE
Line
Count
Source
144
8.25k
    static inline T string_to_float(const char* __restrict s, int len, ParseResult* result) {
145
8.25k
        return string_to_float_internal<T>(s, len, result);
146
8.25k
    }
147
148
    // Parses a string for 'true' or 'false', case insensitive.
149
323
    static inline bool string_to_bool(const char* __restrict s, int len, ParseResult* result) {
150
323
        bool ans = string_to_bool_internal(s, len, result);
151
323
        if (LIKELY(*result == PARSE_SUCCESS)) {
Line
Count
Source
35
323
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 26, False: 297]
152
26
            return ans;
153
26
        }
154
155
297
        int i = skip_leading_whitespace(s, len);
156
297
        return string_to_bool_internal(s + i, len - i, result);
157
323
    }
158
159
    template <PrimitiveType P, typename T = PrimitiveTypeTraits<P>::CppType::NativeType,
160
              typename DecimalType = PrimitiveTypeTraits<P>::ColumnType::value_type>
161
    static inline T string_to_decimal(const char* __restrict s, int len, int type_precision,
162
                                      int type_scale, ParseResult* result);
163
164
    template <typename T>
165
    static Status split_string_to_map(const std::string& base, const T element_separator,
166
                                      const T key_value_separator,
167
                                      std::map<std::string, std::string>* result) {
168
        int key_pos = 0;
169
        int key_end;
170
        int val_pos;
171
        int val_end;
172
173
        while ((key_end = base.find(key_value_separator, key_pos)) != std::string::npos) {
174
            if ((val_pos = base.find_first_not_of(key_value_separator, key_end)) ==
175
                std::string::npos) {
176
                break;
177
            }
178
            if ((val_end = base.find(element_separator, val_pos)) == std::string::npos) {
179
                val_end = base.size();
180
            }
181
            result->insert(std::make_pair(base.substr(key_pos, key_end - key_pos),
182
                                          base.substr(val_pos, val_end - val_pos)));
183
            key_pos = val_end;
184
            if (key_pos != std::string::npos) {
185
                ++key_pos;
186
            }
187
        }
188
189
        return Status::OK();
190
    }
191
192
private:
193
    // This is considerably faster than glibc's implementation.
194
    // In the case of overflow, the max/min value for the data type will be returned.
195
    // Assumes s represents a decimal number.
196
    // Return PARSE_FAILURE on leading whitespace. Trailing whitespace is allowed.
197
    template <typename T>
198
    static inline T string_to_int_internal(const char* __restrict s, int len, ParseResult* result);
199
200
    // This is considerably faster than glibc's implementation.
201
    // In the case of overflow, the max/min value for the data type will be returned.
202
    // Assumes s represents a decimal number.
203
    // Return PARSE_FAILURE on leading whitespace. Trailing whitespace is allowed.
204
    template <typename T>
205
    static inline T string_to_unsigned_int_internal(const char* __restrict s, int len,
206
                                                    ParseResult* result);
207
208
    // Convert a string s representing a number in given base into a decimal number.
209
    // Return PARSE_FAILURE on leading whitespace. Trailing whitespace is allowed.
210
    template <typename T>
211
    static inline T string_to_int_internal(const char* __restrict s, int len, int base,
212
                                           ParseResult* result);
213
214
    // Converts an ascii string to an integer of type T assuming it cannot overflow
215
    // and the number is positive.
216
    // Leading whitespace is not allowed. Trailing whitespace will be skipped.
217
    template <typename T>
218
    static inline T string_to_int_no_overflow(const char* __restrict s, int len,
219
                                              ParseResult* result);
220
221
    // This is considerably faster than glibc's implementation (>100x why???)
222
    // No special case handling needs to be done for overflows, the floating point spec
223
    // already does it and will cap the values to -inf/inf
224
    // To avoid inaccurate conversions this function falls back to strtod for
225
    // scientific notation.
226
    // Return PARSE_FAILURE on leading whitespace. Trailing whitespace is allowed.
227
    // TODO: Investigate using intrinsics to speed up the slow strtod path.
228
    template <typename T>
229
    static inline T string_to_float_internal(const char* __restrict s, int len,
230
                                             ParseResult* result);
231
232
    // parses a string for 'true' or 'false', case insensitive
233
    // Return PARSE_FAILURE on leading whitespace. Trailing whitespace is allowed.
234
    static inline bool string_to_bool_internal(const char* __restrict s, int len,
235
                                               ParseResult* result);
236
237
    // Returns true if s only contains whitespace.
238
25.5k
    static inline bool is_all_whitespace(const char* __restrict s, int len) {
239
100k
        for (int i = 0; i < len; ++i) {
  Branch (239:25): [True: 75.6k, False: 24.8k]
240
75.6k
            if (!LIKELY(is_whitespace(s[i]))) {
Line
Count
Source
35
75.6k
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (240:17): [True: 790, False: 74.8k]
241
790
                return false;
242
790
            }
243
75.6k
        }
244
24.8k
        return true;
245
25.5k
    }
246
247
    // For strings like "3.0", "3.123", and "3.", can parse them as 3.
248
511
    static inline bool is_float_suffix(const char* __restrict s, int len) {
249
511
        return (s[0] == '.' && is_all_digit(s + 1, len - 1));
  Branch (249:17): [True: 3, False: 508]
  Branch (249:32): [True: 1, False: 2]
250
511
    }
251
252
3
    static inline bool is_all_digit(const char* __restrict s, int len) {
253
4
        for (int i = 0; i < len; ++i) {
  Branch (253:25): [True: 3, False: 1]
254
3
            if (!LIKELY(s[i] >= '0' && s[i] <= '9')) {
Line
Count
Source
35
6
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:42): [True: 3, False: 0]
  Branch (35:42): [True: 1, False: 2]
  Branch (254:17): [True: 2, False: 1]
255
2
                return false;
256
2
            }
257
3
        }
258
1
        return true;
259
3
    }
260
261
    // Returns the position of the first non-whitespace character in s.
262
55.1k
    static inline int skip_leading_whitespace(const char* __restrict s, int len) {
263
55.1k
        int i = 0;
264
204k
        while (i < len && is_whitespace(s[i])) {
  Branch (264:16): [True: 203k, False: 1.25k]
  Branch (264:27): [True: 149k, False: 53.8k]
265
149k
            ++i;
266
149k
        }
267
55.1k
        return i;
268
55.1k
    }
269
270
    // Our own definition of "isspace" that optimize on the ' ' branch.
271
495k
    static inline bool is_whitespace(const char& c) {
272
495k
        return LIKELY(c == ' ') ||
Line
Count
Source
35
990k
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 53.3k, False: 441k]
273
495k
               UNLIKELY(c == '\t' || c == '\n' || c == '\v' || c == '\f' || c == '\r');
Line
Count
Source
36
3.02M
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 252k, False: 188k]
  Branch (36:44): [True: 50.5k, False: 391k]
  Branch (36:44): [True: 50.5k, False: 340k]
  Branch (36:44): [True: 50.5k, False: 290k]
  Branch (36:44): [True: 50.5k, False: 239k]
  Branch (36:44): [True: 50.5k, False: 188k]
274
495k
    }
275
276
}; // end of class StringParser
277
278
template <typename T>
279
177k
T StringParser::string_to_int_internal(const char* __restrict s, int len, ParseResult* result) {
280
177k
    if (UNLIKELY(len <= 0)) {
Line
Count
Source
36
50.8k
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 206, False: 50.6k]
    if (UNLIKELY(len <= 0)) {
Line
Count
Source
36
119k
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 119k]
    if (UNLIKELY(len <= 0)) {
Line
Count
Source
36
850
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 850]
    if (UNLIKELY(len <= 0)) {
Line
Count
Source
36
4.94k
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 2.11k, False: 2.83k]
    if (UNLIKELY(len <= 0)) {
Line
Count
Source
36
1.06k
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 1.06k]
    if (UNLIKELY(len <= 0)) {
Line
Count
Source
36
0
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 0]
    if (UNLIKELY(len <= 0)) {
Line
Count
Source
36
0
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 0]
    if (UNLIKELY(len <= 0)) {
Line
Count
Source
36
20
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 20]
    if (UNLIKELY(len <= 0)) {
Line
Count
Source
36
0
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 0]
    if (UNLIKELY(len <= 0)) {
Line
Count
Source
36
93
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 93]
    if (UNLIKELY(len <= 0)) {
Line
Count
Source
36
0
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 0]
281
2.31k
        *result = PARSE_FAILURE;
282
2.31k
        return 0;
283
2.31k
    }
284
285
175k
    typedef typename std::make_unsigned<T>::type UnsignedT;
286
175k
    UnsignedT val = 0;
287
175k
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
288
175k
    bool negative = false;
289
175k
    int i = 0;
290
175k
    switch (*s) {
  Branch (290:13): [True: 36.7k, False: 13.9k]
  Branch (290:13): [True: 119k, False: 236]
  Branch (290:13): [True: 592, False: 258]
  Branch (290:13): [True: 2.53k, False: 302]
  Branch (290:13): [True: 812, False: 256]
  Branch (290:13): [True: 0, False: 0]
  Branch (290:13): [True: 0, False: 0]
  Branch (290:13): [True: 20, False: 0]
  Branch (290:13): [True: 0, False: 0]
  Branch (290:13): [True: 85, False: 8]
  Branch (290:13): [True: 0, False: 0]
291
14.6k
    case '-':
  Branch (291:5): [True: 13.8k, False: 36.8k]
  Branch (291:5): [True: 236, False: 119k]
  Branch (291:5): [True: 209, False: 641]
  Branch (291:5): [True: 180, False: 2.65k]
  Branch (291:5): [True: 207, False: 861]
  Branch (291:5): [True: 0, False: 0]
  Branch (291:5): [True: 0, False: 0]
  Branch (291:5): [True: 0, False: 20]
  Branch (291:5): [True: 0, False: 0]
  Branch (291:5): [True: 8, False: 85]
  Branch (291:5): [True: 0, False: 0]
292
14.6k
        negative = true;
293
14.6k
        max_val += 1;
294
14.6k
        [[fallthrough]];
295
14.9k
    case '+':
  Branch (295:5): [True: 98, False: 50.5k]
  Branch (295:5): [True: 0, False: 119k]
  Branch (295:5): [True: 49, False: 801]
  Branch (295:5): [True: 122, False: 2.71k]
  Branch (295:5): [True: 49, False: 1.01k]
  Branch (295:5): [True: 0, False: 0]
  Branch (295:5): [True: 0, False: 0]
  Branch (295:5): [True: 0, False: 20]
  Branch (295:5): [True: 0, False: 0]
  Branch (295:5): [True: 0, False: 93]
  Branch (295:5): [True: 0, False: 0]
296
14.9k
        ++i;
297
        // only one '+'/'-' char, so could return failure directly
298
14.9k
        if (UNLIKELY(len == 1)) {
Line
Count
Source
36
13.9k
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 13.9k]
        if (UNLIKELY(len == 1)) {
Line
Count
Source
36
236
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 236]
        if (UNLIKELY(len == 1)) {
Line
Count
Source
36
258
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 258]
        if (UNLIKELY(len == 1)) {
Line
Count
Source
36
302
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 6, False: 296]
        if (UNLIKELY(len == 1)) {
Line
Count
Source
36
256
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 256]
        if (UNLIKELY(len == 1)) {
Line
Count
Source
36
0
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 0]
        if (UNLIKELY(len == 1)) {
Line
Count
Source
36
0
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 0]
        if (UNLIKELY(len == 1)) {
Line
Count
Source
36
0
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 0]
        if (UNLIKELY(len == 1)) {
Line
Count
Source
36
0
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 0]
        if (UNLIKELY(len == 1)) {
Line
Count
Source
36
8
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 8]
        if (UNLIKELY(len == 1)) {
Line
Count
Source
36
0
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 0]
299
6
            *result = PARSE_FAILURE;
300
6
            return 0;
301
6
        }
302
175k
    }
303
304
    // This is the fast path where the string cannot overflow.
305
175k
    if (LIKELY(len - i < vectorized::NumberTraits::max_ascii_len<T>())) {
Line
Count
Source
35
50.6k
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 1.43k, False: 49.1k]
    if (LIKELY(len - i < vectorized::NumberTraits::max_ascii_len<T>())) {
Line
Count
Source
35
119k
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 119k, False: 15]
    if (LIKELY(len - i < vectorized::NumberTraits::max_ascii_len<T>())) {
Line
Count
Source
35
850
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 114, False: 736]
    if (LIKELY(len - i < vectorized::NumberTraits::max_ascii_len<T>())) {
Line
Count
Source
35
2.83k
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 1.57k, False: 1.25k]
    if (LIKELY(len - i < vectorized::NumberTraits::max_ascii_len<T>())) {
Line
Count
Source
35
1.06k
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 635, False: 433]
    if (LIKELY(len - i < vectorized::NumberTraits::max_ascii_len<T>())) {
Line
Count
Source
35
0
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 0, False: 0]
    if (LIKELY(len - i < vectorized::NumberTraits::max_ascii_len<T>())) {
Line
Count
Source
35
0
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 0, False: 0]
    if (LIKELY(len - i < vectorized::NumberTraits::max_ascii_len<T>())) {
Line
Count
Source
35
20
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 20, False: 0]
    if (LIKELY(len - i < vectorized::NumberTraits::max_ascii_len<T>())) {
Line
Count
Source
35
0
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 0, False: 0]
    if (LIKELY(len - i < vectorized::NumberTraits::max_ascii_len<T>())) {
Line
Count
Source
35
93
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 53, False: 40]
    if (LIKELY(len - i < vectorized::NumberTraits::max_ascii_len<T>())) {
Line
Count
Source
35
0
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 0, False: 0]
306
123k
        val = string_to_int_no_overflow<UnsignedT>(s + i, len - i, result);
307
123k
        return static_cast<T>(negative ? -val : val);
  Branch (307:31): [True: 700, False: 739]
  Branch (307:31): [True: 236, False: 119k]
  Branch (307:31): [True: 56, False: 58]
  Branch (307:31): [True: 63, False: 1.51k]
  Branch (307:31): [True: 99, False: 536]
  Branch (307:31): [True: 0, False: 0]
  Branch (307:31): [True: 0, False: 0]
  Branch (307:31): [True: 0, False: 20]
  Branch (307:31): [True: 0, False: 0]
  Branch (307:31): [True: 8, False: 45]
  Branch (307:31): [True: 0, False: 0]
308
123k
    }
309
310
51.6k
    const T max_div_10 = max_val / 10;
311
51.6k
    const T max_mod_10 = max_val % 10;
312
313
51.6k
    int first = i;
314
115k
    for (; i < len; ++i) {
  Branch (314:12): [True: 103k, False: 433]
  Branch (314:12): [True: 357, False: 3]
  Branch (314:12): [True: 2.16k, False: 24]
  Branch (314:12): [True: 3.77k, False: 17]
  Branch (314:12): [True: 4.63k, False: 27]
  Branch (314:12): [True: 0, False: 0]
  Branch (314:12): [True: 0, False: 0]
  Branch (314:12): [True: 0, False: 0]
  Branch (314:12): [True: 0, False: 0]
  Branch (314:12): [True: 40, False: 0]
  Branch (314:12): [True: 0, False: 0]
315
114k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
Line
Count
Source
35
173k
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 69.4k, False: 34.2k]
  Branch (35:42): [True: 69.8k, False: 33.8k]
  Branch (35:42): [True: 69.4k, False: 370]
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
Line
Count
Source
35
708
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 351, False: 6]
  Branch (35:42): [True: 351, False: 6]
  Branch (35:42): [True: 351, False: 0]
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
Line
Count
Source
35
3.74k
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 1.58k, False: 588]
  Branch (35:42): [True: 1.58k, False: 588]
  Branch (35:42): [True: 1.58k, False: 0]
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
Line
Count
Source
35
6.96k
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 2.66k, False: 1.11k]
  Branch (35:42): [True: 3.18k, False: 595]
  Branch (35:42): [True: 2.66k, False: 520]
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
Line
Count
Source
35
8.99k
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 4.35k, False: 288]
  Branch (35:42): [True: 4.35k, False: 288]
  Branch (35:42): [True: 4.35k, False: 0]
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
Line
Count
Source
35
0
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 0, False: 0]
  Branch (35:42): [True: 0, False: 0]
  Branch (35:42): [True: 0, False: 0]
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
Line
Count
Source
35
0
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 0, False: 0]
  Branch (35:42): [True: 0, False: 0]
  Branch (35:42): [True: 0, False: 0]
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
Line
Count
Source
35
0
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 0, False: 0]
  Branch (35:42): [True: 0, False: 0]
  Branch (35:42): [True: 0, False: 0]
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
Line
Count
Source
35
0
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 0, False: 0]
  Branch (35:42): [True: 0, False: 0]
  Branch (35:42): [True: 0, False: 0]
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
Line
Count
Source
35
76
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 0, False: 40]
  Branch (35:42): [True: 36, False: 4]
  Branch (35:42): [True: 0, False: 36]
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
Line
Count
Source
35
0
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 0, False: 0]
  Branch (35:42): [True: 0, False: 0]
  Branch (35:42): [True: 0, False: 0]
316
78.3k
            T digit = s[i] - '0';
317
            // This is a tricky check to see if adding this digit will cause an overflow.
318
78.3k
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
Line
Count
Source
36
69.4k
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 14.5k, False: 54.9k]
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
Line
Count
Source
36
351
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 6, False: 345]
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
Line
Count
Source
36
1.58k
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 124, False: 1.45k]
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
Line
Count
Source
36
2.66k
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 124, False: 2.54k]
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
Line
Count
Source
36
4.35k
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 118, False: 4.23k]
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
Line
Count
Source
36
0
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 0]
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
Line
Count
Source
36
0
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 0]
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
Line
Count
Source
36
0
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 0]
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
Line
Count
Source
36
0
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 0]
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
Line
Count
Source
36
0
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 0]
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
Line
Count
Source
36
0
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 0]
319
14.8k
                *result = PARSE_OVERFLOW;
320
14.8k
                return negative ? -max_val : max_val;
  Branch (320:24): [True: 7.23k, False: 7.28k]
  Branch (320:24): [True: 0, False: 6]
  Branch (320:24): [True: 62, False: 62]
  Branch (320:24): [True: 62, False: 62]
  Branch (320:24): [True: 56, False: 62]
  Branch (320:24): [True: 0, False: 0]
  Branch (320:24): [True: 0, False: 0]
  Branch (320:24): [True: 0, False: 0]
  Branch (320:24): [True: 0, False: 0]
  Branch (320:24): [True: 0, False: 0]
  Branch (320:24): [True: 0, False: 0]
321
14.8k
            }
322
63.4k
            val = val * 10 + digit;
323
63.4k
        } else {
324
36.2k
            if ((UNLIKELY(i == first || (!is_all_whitespace(s + i, len - i) &&
Line
Count
Source
36
57.3k
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:44): [True: 322, False: 11.0k]
  Branch (36:44): [True: 322, False: 0]
  Branch (36:44): [True: 22.8k, False: 11.3k]
            if ((UNLIKELY(i == first || (!is_all_whitespace(s + i, len - i) &&
Line
Count
Source
36
6
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:44): [True: 0, False: 0]
  Branch (36:44): [True: 0, False: 0]
  Branch (36:44): [True: 6, False: 0]
            if ((UNLIKELY(i == first || (!is_all_whitespace(s + i, len - i) &&
Line
Count
Source
36
1.00k
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:44): [True: 0, False: 210]
  Branch (36:44): [True: 0, False: 0]
  Branch (36:44): [True: 378, False: 210]
            if ((UNLIKELY(i == first || (!is_all_whitespace(s + i, len - i) &&
Line
Count
Source
36
1.58k
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:44): [True: 72, False: 126]
  Branch (36:44): [True: 72, False: 0]
  Branch (36:44): [True: 917, False: 198]
            if ((UNLIKELY(i == first || (!is_all_whitespace(s + i, len - i) &&
Line
Count
Source
36
456
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:44): [True: 0, False: 84]
  Branch (36:44): [True: 0, False: 0]
  Branch (36:44): [True: 204, False: 84]
            if ((UNLIKELY(i == first || (!is_all_whitespace(s + i, len - i) &&
Line
Count
Source
36
0
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:44): [True: 0, False: 0]
  Branch (36:44): [True: 0, False: 0]
  Branch (36:44): [True: 0, False: 0]
            if ((UNLIKELY(i == first || (!is_all_whitespace(s + i, len - i) &&
Line
Count
Source
36
0
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:44): [True: 0, False: 0]
  Branch (36:44): [True: 0, False: 0]
  Branch (36:44): [True: 0, False: 0]
            if ((UNLIKELY(i == first || (!is_all_whitespace(s + i, len - i) &&
Line
Count
Source
36
0
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:44): [True: 0, False: 0]
  Branch (36:44): [True: 0, False: 0]
  Branch (36:44): [True: 0, False: 0]
            if ((UNLIKELY(i == first || (!is_all_whitespace(s + i, len - i) &&
Line
Count
Source
36
0
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:44): [True: 0, False: 0]
  Branch (36:44): [True: 0, False: 0]
  Branch (36:44): [True: 0, False: 0]
            if ((UNLIKELY(i == first || (!is_all_whitespace(s + i, len - i) &&
Line
Count
Source
36
40
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:44): [True: 0, False: 0]
  Branch (36:44): [True: 0, False: 0]
  Branch (36:44): [True: 40, False: 0]
            if ((UNLIKELY(i == first || (!is_all_whitespace(s + i, len - i) &&
Line
Count
Source
36
0
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:44): [True: 0, False: 0]
  Branch (36:44): [True: 0, False: 0]
  Branch (36:44): [True: 0, False: 0]
  Branch (324:17): [True: 23.2k, False: 11.0k]
  Branch (324:17): [True: 6, False: 0]
  Branch (324:17): [True: 378, False: 210]
  Branch (324:17): [True: 989, False: 126]
  Branch (324:17): [True: 204, False: 84]
  Branch (324:17): [True: 0, False: 0]
  Branch (324:17): [True: 0, False: 0]
  Branch (324:17): [True: 0, False: 0]
  Branch (324:17): [True: 0, False: 0]
  Branch (324:17): [True: 40, False: 0]
  Branch (324:17): [True: 0, False: 0]
325
36.2k
                                         !is_float_suffix(s + i, len - i))))) {
326
                // Reject the string because either the first char was not a digit,
327
                // or the remaining chars are not all whitespace
328
24.8k
                *result = PARSE_FAILURE;
329
24.8k
                return 0;
330
24.8k
            }
331
            // Returning here is slightly faster than breaking the loop.
332
11.4k
            *result = PARSE_SUCCESS;
333
11.4k
            return static_cast<T>(negative ? -val : val);
  Branch (333:35): [True: 5.46k, False: 5.58k]
  Branch (333:35): [True: 0, False: 0]
  Branch (333:35): [True: 84, False: 126]
  Branch (333:35): [True: 42, False: 84]
  Branch (333:35): [True: 42, False: 42]
  Branch (333:35): [True: 0, False: 0]
  Branch (333:35): [True: 0, False: 0]
  Branch (333:35): [True: 0, False: 0]
  Branch (333:35): [True: 0, False: 0]
  Branch (333:35): [True: 0, False: 0]
  Branch (333:35): [True: 0, False: 0]
334
36.2k
        }
335
114k
    }
336
504
    *result = PARSE_SUCCESS;
337
504
    return static_cast<T>(negative ? -val : val);
  Branch (337:27): [True: 213, False: 220]
  Branch (337:27): [True: 0, False: 3]
  Branch (337:27): [True: 7, False: 17]
  Branch (337:27): [True: 7, False: 10]
  Branch (337:27): [True: 10, False: 17]
  Branch (337:27): [True: 0, False: 0]
  Branch (337:27): [True: 0, False: 0]
  Branch (337:27): [True: 0, False: 0]
  Branch (337:27): [True: 0, False: 0]
  Branch (337:27): [True: 0, False: 0]
  Branch (337:27): [True: 0, False: 0]
338
51.6k
}
_ZN5doris12StringParser22string_to_int_internalIaEET_PKciPNS0_11ParseResultE
Line
Count
Source
279
50.8k
T StringParser::string_to_int_internal(const char* __restrict s, int len, ParseResult* result) {
280
50.8k
    if (UNLIKELY(len <= 0)) {
Line
Count
Source
36
50.8k
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 206, False: 50.6k]
281
206
        *result = PARSE_FAILURE;
282
206
        return 0;
283
206
    }
284
285
50.6k
    typedef typename std::make_unsigned<T>::type UnsignedT;
286
50.6k
    UnsignedT val = 0;
287
50.6k
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
288
50.6k
    bool negative = false;
289
50.6k
    int i = 0;
290
50.6k
    switch (*s) {
  Branch (290:13): [True: 36.7k, False: 13.9k]
291
13.8k
    case '-':
  Branch (291:5): [True: 13.8k, False: 36.8k]
292
13.8k
        negative = true;
293
13.8k
        max_val += 1;
294
13.8k
        [[fallthrough]];
295
13.9k
    case '+':
  Branch (295:5): [True: 98, False: 50.5k]
296
13.9k
        ++i;
297
        // only one '+'/'-' char, so could return failure directly
298
13.9k
        if (UNLIKELY(len == 1)) {
Line
Count
Source
36
13.9k
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 13.9k]
299
0
            *result = PARSE_FAILURE;
300
0
            return 0;
301
0
        }
302
50.6k
    }
303
304
    // This is the fast path where the string cannot overflow.
305
50.6k
    if (LIKELY(len - i < vectorized::NumberTraits::max_ascii_len<T>())) {
Line
Count
Source
35
50.6k
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 1.43k, False: 49.1k]
306
1.43k
        val = string_to_int_no_overflow<UnsignedT>(s + i, len - i, result);
307
1.43k
        return static_cast<T>(negative ? -val : val);
  Branch (307:31): [True: 700, False: 739]
308
1.43k
    }
309
310
49.1k
    const T max_div_10 = max_val / 10;
311
49.1k
    const T max_mod_10 = max_val % 10;
312
313
49.1k
    int first = i;
314
104k
    for (; i < len; ++i) {
  Branch (314:12): [True: 103k, False: 433]
315
103k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
Line
Count
Source
35
173k
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 69.4k, False: 34.2k]
  Branch (35:42): [True: 69.8k, False: 33.8k]
  Branch (35:42): [True: 69.4k, False: 370]
316
69.4k
            T digit = s[i] - '0';
317
            // This is a tricky check to see if adding this digit will cause an overflow.
318
69.4k
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
Line
Count
Source
36
69.4k
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 14.5k, False: 54.9k]
319
14.5k
                *result = PARSE_OVERFLOW;
320
14.5k
                return negative ? -max_val : max_val;
  Branch (320:24): [True: 7.23k, False: 7.28k]
321
14.5k
            }
322
54.9k
            val = val * 10 + digit;
323
54.9k
        } else {
324
34.2k
            if ((UNLIKELY(i == first || (!is_all_whitespace(s + i, len - i) &&
Line
Count
Source
36
57.3k
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:44): [True: 322, False: 11.0k]
  Branch (36:44): [True: 322, False: 0]
  Branch (36:44): [True: 22.8k, False: 11.3k]
  Branch (324:17): [True: 23.2k, False: 11.0k]
325
34.2k
                                         !is_float_suffix(s + i, len - i))))) {
326
                // Reject the string because either the first char was not a digit,
327
                // or the remaining chars are not all whitespace
328
23.2k
                *result = PARSE_FAILURE;
329
23.2k
                return 0;
330
23.2k
            }
331
            // Returning here is slightly faster than breaking the loop.
332
11.0k
            *result = PARSE_SUCCESS;
333
11.0k
            return static_cast<T>(negative ? -val : val);
  Branch (333:35): [True: 5.46k, False: 5.58k]
334
34.2k
        }
335
103k
    }
336
433
    *result = PARSE_SUCCESS;
337
433
    return static_cast<T>(negative ? -val : val);
  Branch (337:27): [True: 213, False: 220]
338
49.1k
}
_ZN5doris12StringParser22string_to_int_internalInEET_PKciPNS0_11ParseResultE
Line
Count
Source
279
119k
T StringParser::string_to_int_internal(const char* __restrict s, int len, ParseResult* result) {
280
119k
    if (UNLIKELY(len <= 0)) {
Line
Count
Source
36
119k
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 119k]
281
0
        *result = PARSE_FAILURE;
282
0
        return 0;
283
0
    }
284
285
119k
    typedef typename std::make_unsigned<T>::type UnsignedT;
286
119k
    UnsignedT val = 0;
287
119k
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
288
119k
    bool negative = false;
289
119k
    int i = 0;
290
119k
    switch (*s) {
  Branch (290:13): [True: 119k, False: 236]
291
236
    case '-':
  Branch (291:5): [True: 236, False: 119k]
292
236
        negative = true;
293
236
        max_val += 1;
294
236
        [[fallthrough]];
295
236
    case '+':
  Branch (295:5): [True: 0, False: 119k]
296
236
        ++i;
297
        // only one '+'/'-' char, so could return failure directly
298
236
        if (UNLIKELY(len == 1)) {
Line
Count
Source
36
236
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 236]
299
0
            *result = PARSE_FAILURE;
300
0
            return 0;
301
0
        }
302
119k
    }
303
304
    // This is the fast path where the string cannot overflow.
305
119k
    if (LIKELY(len - i < vectorized::NumberTraits::max_ascii_len<T>())) {
Line
Count
Source
35
119k
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 119k, False: 15]
306
119k
        val = string_to_int_no_overflow<UnsignedT>(s + i, len - i, result);
307
119k
        return static_cast<T>(negative ? -val : val);
  Branch (307:31): [True: 236, False: 119k]
308
119k
    }
309
310
15
    const T max_div_10 = max_val / 10;
311
15
    const T max_mod_10 = max_val % 10;
312
313
15
    int first = i;
314
360
    for (; i < len; ++i) {
  Branch (314:12): [True: 357, False: 3]
315
357
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
Line
Count
Source
35
708
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 351, False: 6]
  Branch (35:42): [True: 351, False: 6]
  Branch (35:42): [True: 351, False: 0]
316
351
            T digit = s[i] - '0';
317
            // This is a tricky check to see if adding this digit will cause an overflow.
318
351
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
Line
Count
Source
36
351
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 6, False: 345]
319
6
                *result = PARSE_OVERFLOW;
320
6
                return negative ? -max_val : max_val;
  Branch (320:24): [True: 0, False: 6]
321
6
            }
322
345
            val = val * 10 + digit;
323
345
        } else {
324
6
            if ((UNLIKELY(i == first || (!is_all_whitespace(s + i, len - i) &&
Line
Count
Source
36
6
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:44): [True: 0, False: 0]
  Branch (36:44): [True: 0, False: 0]
  Branch (36:44): [True: 6, False: 0]
  Branch (324:17): [True: 6, False: 0]
325
6
                                         !is_float_suffix(s + i, len - i))))) {
326
                // Reject the string because either the first char was not a digit,
327
                // or the remaining chars are not all whitespace
328
6
                *result = PARSE_FAILURE;
329
6
                return 0;
330
6
            }
331
            // Returning here is slightly faster than breaking the loop.
332
0
            *result = PARSE_SUCCESS;
333
0
            return static_cast<T>(negative ? -val : val);
  Branch (333:35): [True: 0, False: 0]
334
6
        }
335
357
    }
336
3
    *result = PARSE_SUCCESS;
337
3
    return static_cast<T>(negative ? -val : val);
  Branch (337:27): [True: 0, False: 3]
338
15
}
_ZN5doris12StringParser22string_to_int_internalIsEET_PKciPNS0_11ParseResultE
Line
Count
Source
279
850
T StringParser::string_to_int_internal(const char* __restrict s, int len, ParseResult* result) {
280
850
    if (UNLIKELY(len <= 0)) {
Line
Count
Source
36
850
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 850]
281
0
        *result = PARSE_FAILURE;
282
0
        return 0;
283
0
    }
284
285
850
    typedef typename std::make_unsigned<T>::type UnsignedT;
286
850
    UnsignedT val = 0;
287
850
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
288
850
    bool negative = false;
289
850
    int i = 0;
290
850
    switch (*s) {
  Branch (290:13): [True: 592, False: 258]
291
209
    case '-':
  Branch (291:5): [True: 209, False: 641]
292
209
        negative = true;
293
209
        max_val += 1;
294
209
        [[fallthrough]];
295
258
    case '+':
  Branch (295:5): [True: 49, False: 801]
296
258
        ++i;
297
        // only one '+'/'-' char, so could return failure directly
298
258
        if (UNLIKELY(len == 1)) {
Line
Count
Source
36
258
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 258]
299
0
            *result = PARSE_FAILURE;
300
0
            return 0;
301
0
        }
302
850
    }
303
304
    // This is the fast path where the string cannot overflow.
305
850
    if (LIKELY(len - i < vectorized::NumberTraits::max_ascii_len<T>())) {
Line
Count
Source
35
850
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 114, False: 736]
306
114
        val = string_to_int_no_overflow<UnsignedT>(s + i, len - i, result);
307
114
        return static_cast<T>(negative ? -val : val);
  Branch (307:31): [True: 56, False: 58]
308
114
    }
309
310
736
    const T max_div_10 = max_val / 10;
311
736
    const T max_mod_10 = max_val % 10;
312
313
736
    int first = i;
314
2.19k
    for (; i < len; ++i) {
  Branch (314:12): [True: 2.16k, False: 24]
315
2.16k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
Line
Count
Source
35
3.74k
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 1.58k, False: 588]
  Branch (35:42): [True: 1.58k, False: 588]
  Branch (35:42): [True: 1.58k, False: 0]
316
1.58k
            T digit = s[i] - '0';
317
            // This is a tricky check to see if adding this digit will cause an overflow.
318
1.58k
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
Line
Count
Source
36
1.58k
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 124, False: 1.45k]
319
124
                *result = PARSE_OVERFLOW;
320
124
                return negative ? -max_val : max_val;
  Branch (320:24): [True: 62, False: 62]
321
124
            }
322
1.45k
            val = val * 10 + digit;
323
1.45k
        } else {
324
588
            if ((UNLIKELY(i == first || (!is_all_whitespace(s + i, len - i) &&
Line
Count
Source
36
1.00k
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:44): [True: 0, False: 210]
  Branch (36:44): [True: 0, False: 0]
  Branch (36:44): [True: 378, False: 210]
  Branch (324:17): [True: 378, False: 210]
325
588
                                         !is_float_suffix(s + i, len - i))))) {
326
                // Reject the string because either the first char was not a digit,
327
                // or the remaining chars are not all whitespace
328
378
                *result = PARSE_FAILURE;
329
378
                return 0;
330
378
            }
331
            // Returning here is slightly faster than breaking the loop.
332
210
            *result = PARSE_SUCCESS;
333
210
            return static_cast<T>(negative ? -val : val);
  Branch (333:35): [True: 84, False: 126]
334
588
        }
335
2.16k
    }
336
24
    *result = PARSE_SUCCESS;
337
24
    return static_cast<T>(negative ? -val : val);
  Branch (337:27): [True: 7, False: 17]
338
736
}
_ZN5doris12StringParser22string_to_int_internalIiEET_PKciPNS0_11ParseResultE
Line
Count
Source
279
4.94k
T StringParser::string_to_int_internal(const char* __restrict s, int len, ParseResult* result) {
280
4.94k
    if (UNLIKELY(len <= 0)) {
Line
Count
Source
36
4.94k
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 2.11k, False: 2.83k]
281
2.11k
        *result = PARSE_FAILURE;
282
2.11k
        return 0;
283
2.11k
    }
284
285
2.83k
    typedef typename std::make_unsigned<T>::type UnsignedT;
286
2.83k
    UnsignedT val = 0;
287
2.83k
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
288
2.83k
    bool negative = false;
289
2.83k
    int i = 0;
290
2.83k
    switch (*s) {
  Branch (290:13): [True: 2.53k, False: 302]
291
180
    case '-':
  Branch (291:5): [True: 180, False: 2.65k]
292
180
        negative = true;
293
180
        max_val += 1;
294
180
        [[fallthrough]];
295
302
    case '+':
  Branch (295:5): [True: 122, False: 2.71k]
296
302
        ++i;
297
        // only one '+'/'-' char, so could return failure directly
298
302
        if (UNLIKELY(len == 1)) {
Line
Count
Source
36
302
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 6, False: 296]
299
6
            *result = PARSE_FAILURE;
300
6
            return 0;
301
6
        }
302
2.83k
    }
303
304
    // This is the fast path where the string cannot overflow.
305
2.83k
    if (LIKELY(len - i < vectorized::NumberTraits::max_ascii_len<T>())) {
Line
Count
Source
35
2.83k
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 1.57k, False: 1.25k]
306
1.57k
        val = string_to_int_no_overflow<UnsignedT>(s + i, len - i, result);
307
1.57k
        return static_cast<T>(negative ? -val : val);
  Branch (307:31): [True: 63, False: 1.51k]
308
1.57k
    }
309
310
1.25k
    const T max_div_10 = max_val / 10;
311
1.25k
    const T max_mod_10 = max_val % 10;
312
313
1.25k
    int first = i;
314
3.79k
    for (; i < len; ++i) {
  Branch (314:12): [True: 3.77k, False: 17]
315
3.77k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
Line
Count
Source
35
6.96k
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 2.66k, False: 1.11k]
  Branch (35:42): [True: 3.18k, False: 595]
  Branch (35:42): [True: 2.66k, False: 520]
316
2.66k
            T digit = s[i] - '0';
317
            // This is a tricky check to see if adding this digit will cause an overflow.
318
2.66k
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
Line
Count
Source
36
2.66k
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 124, False: 2.54k]
319
124
                *result = PARSE_OVERFLOW;
320
124
                return negative ? -max_val : max_val;
  Branch (320:24): [True: 62, False: 62]
321
124
            }
322
2.54k
            val = val * 10 + digit;
323
2.54k
        } else {
324
1.11k
            if ((UNLIKELY(i == first || (!is_all_whitespace(s + i, len - i) &&
Line
Count
Source
36
1.58k
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:44): [True: 72, False: 126]
  Branch (36:44): [True: 72, False: 0]
  Branch (36:44): [True: 917, False: 198]
  Branch (324:17): [True: 989, False: 126]
325
1.11k
                                         !is_float_suffix(s + i, len - i))))) {
326
                // Reject the string because either the first char was not a digit,
327
                // or the remaining chars are not all whitespace
328
989
                *result = PARSE_FAILURE;
329
989
                return 0;
330
989
            }
331
            // Returning here is slightly faster than breaking the loop.
332
126
            *result = PARSE_SUCCESS;
333
126
            return static_cast<T>(negative ? -val : val);
  Branch (333:35): [True: 42, False: 84]
334
1.11k
        }
335
3.77k
    }
336
17
    *result = PARSE_SUCCESS;
337
17
    return static_cast<T>(negative ? -val : val);
  Branch (337:27): [True: 7, False: 10]
338
1.25k
}
_ZN5doris12StringParser22string_to_int_internalIlEET_PKciPNS0_11ParseResultE
Line
Count
Source
279
1.06k
T StringParser::string_to_int_internal(const char* __restrict s, int len, ParseResult* result) {
280
1.06k
    if (UNLIKELY(len <= 0)) {
Line
Count
Source
36
1.06k
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 1.06k]
281
0
        *result = PARSE_FAILURE;
282
0
        return 0;
283
0
    }
284
285
1.06k
    typedef typename std::make_unsigned<T>::type UnsignedT;
286
1.06k
    UnsignedT val = 0;
287
1.06k
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
288
1.06k
    bool negative = false;
289
1.06k
    int i = 0;
290
1.06k
    switch (*s) {
  Branch (290:13): [True: 812, False: 256]
291
207
    case '-':
  Branch (291:5): [True: 207, False: 861]
292
207
        negative = true;
293
207
        max_val += 1;
294
207
        [[fallthrough]];
295
256
    case '+':
  Branch (295:5): [True: 49, False: 1.01k]
296
256
        ++i;
297
        // only one '+'/'-' char, so could return failure directly
298
256
        if (UNLIKELY(len == 1)) {
Line
Count
Source
36
256
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 256]
299
0
            *result = PARSE_FAILURE;
300
0
            return 0;
301
0
        }
302
1.06k
    }
303
304
    // This is the fast path where the string cannot overflow.
305
1.06k
    if (LIKELY(len - i < vectorized::NumberTraits::max_ascii_len<T>())) {
Line
Count
Source
35
1.06k
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 635, False: 433]
306
635
        val = string_to_int_no_overflow<UnsignedT>(s + i, len - i, result);
307
635
        return static_cast<T>(negative ? -val : val);
  Branch (307:31): [True: 99, False: 536]
308
635
    }
309
310
433
    const T max_div_10 = max_val / 10;
311
433
    const T max_mod_10 = max_val % 10;
312
313
433
    int first = i;
314
4.66k
    for (; i < len; ++i) {
  Branch (314:12): [True: 4.63k, False: 27]
315
4.63k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
Line
Count
Source
35
8.99k
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 4.35k, False: 288]
  Branch (35:42): [True: 4.35k, False: 288]
  Branch (35:42): [True: 4.35k, False: 0]
316
4.35k
            T digit = s[i] - '0';
317
            // This is a tricky check to see if adding this digit will cause an overflow.
318
4.35k
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
Line
Count
Source
36
4.35k
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 118, False: 4.23k]
319
118
                *result = PARSE_OVERFLOW;
320
118
                return negative ? -max_val : max_val;
  Branch (320:24): [True: 56, False: 62]
321
118
            }
322
4.23k
            val = val * 10 + digit;
323
4.23k
        } else {
324
288
            if ((UNLIKELY(i == first || (!is_all_whitespace(s + i, len - i) &&
Line
Count
Source
36
456
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:44): [True: 0, False: 84]
  Branch (36:44): [True: 0, False: 0]
  Branch (36:44): [True: 204, False: 84]
  Branch (324:17): [True: 204, False: 84]
325
288
                                         !is_float_suffix(s + i, len - i))))) {
326
                // Reject the string because either the first char was not a digit,
327
                // or the remaining chars are not all whitespace
328
204
                *result = PARSE_FAILURE;
329
204
                return 0;
330
204
            }
331
            // Returning here is slightly faster than breaking the loop.
332
84
            *result = PARSE_SUCCESS;
333
84
            return static_cast<T>(negative ? -val : val);
  Branch (333:35): [True: 42, False: 42]
334
288
        }
335
4.63k
    }
336
27
    *result = PARSE_SUCCESS;
337
27
    return static_cast<T>(negative ? -val : val);
  Branch (337:27): [True: 10, False: 17]
338
433
}
Unexecuted instantiation: _ZN5doris12StringParser22string_to_int_internalIN4wide7integerILm256EiEEEET_PKciPNS0_11ParseResultE
Unexecuted instantiation: _ZN5doris12StringParser22string_to_int_internalIoEET_PKciPNS0_11ParseResultE
_ZN5doris12StringParser22string_to_int_internalImEET_PKciPNS0_11ParseResultE
Line
Count
Source
279
20
T StringParser::string_to_int_internal(const char* __restrict s, int len, ParseResult* result) {
280
20
    if (UNLIKELY(len <= 0)) {
Line
Count
Source
36
20
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 20]
281
0
        *result = PARSE_FAILURE;
282
0
        return 0;
283
0
    }
284
285
20
    typedef typename std::make_unsigned<T>::type UnsignedT;
286
20
    UnsignedT val = 0;
287
20
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
288
20
    bool negative = false;
289
20
    int i = 0;
290
20
    switch (*s) {
  Branch (290:13): [True: 20, False: 0]
291
0
    case '-':
  Branch (291:5): [True: 0, False: 20]
292
0
        negative = true;
293
0
        max_val += 1;
294
0
        [[fallthrough]];
295
0
    case '+':
  Branch (295:5): [True: 0, False: 20]
296
0
        ++i;
297
        // only one '+'/'-' char, so could return failure directly
298
0
        if (UNLIKELY(len == 1)) {
Line
Count
Source
36
0
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 0]
299
0
            *result = PARSE_FAILURE;
300
0
            return 0;
301
0
        }
302
20
    }
303
304
    // This is the fast path where the string cannot overflow.
305
20
    if (LIKELY(len - i < vectorized::NumberTraits::max_ascii_len<T>())) {
Line
Count
Source
35
20
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 20, False: 0]
306
20
        val = string_to_int_no_overflow<UnsignedT>(s + i, len - i, result);
307
20
        return static_cast<T>(negative ? -val : val);
  Branch (307:31): [True: 0, False: 20]
308
20
    }
309
310
0
    const T max_div_10 = max_val / 10;
311
0
    const T max_mod_10 = max_val % 10;
312
313
0
    int first = i;
314
0
    for (; i < len; ++i) {
  Branch (314:12): [True: 0, False: 0]
315
0
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
Line
Count
Source
35
0
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 0, False: 0]
  Branch (35:42): [True: 0, False: 0]
  Branch (35:42): [True: 0, False: 0]
316
0
            T digit = s[i] - '0';
317
            // This is a tricky check to see if adding this digit will cause an overflow.
318
0
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
Line
Count
Source
36
0
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 0]
319
0
                *result = PARSE_OVERFLOW;
320
0
                return negative ? -max_val : max_val;
  Branch (320:24): [True: 0, False: 0]
321
0
            }
322
0
            val = val * 10 + digit;
323
0
        } else {
324
0
            if ((UNLIKELY(i == first || (!is_all_whitespace(s + i, len - i) &&
Line
Count
Source
36
0
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:44): [True: 0, False: 0]
  Branch (36:44): [True: 0, False: 0]
  Branch (36:44): [True: 0, False: 0]
  Branch (324:17): [True: 0, False: 0]
325
0
                                         !is_float_suffix(s + i, len - i))))) {
326
                // Reject the string because either the first char was not a digit,
327
                // or the remaining chars are not all whitespace
328
0
                *result = PARSE_FAILURE;
329
0
                return 0;
330
0
            }
331
            // Returning here is slightly faster than breaking the loop.
332
0
            *result = PARSE_SUCCESS;
333
0
            return static_cast<T>(negative ? -val : val);
  Branch (333:35): [True: 0, False: 0]
334
0
        }
335
0
    }
336
0
    *result = PARSE_SUCCESS;
337
0
    return static_cast<T>(negative ? -val : val);
  Branch (337:27): [True: 0, False: 0]
338
0
}
Unexecuted instantiation: _ZN5doris12StringParser22string_to_int_internalIjEET_PKciPNS0_11ParseResultE
_ZN5doris12StringParser22string_to_int_internalIhEET_PKciPNS0_11ParseResultE
Line
Count
Source
279
93
T StringParser::string_to_int_internal(const char* __restrict s, int len, ParseResult* result) {
280
93
    if (UNLIKELY(len <= 0)) {
Line
Count
Source
36
93
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 93]
281
0
        *result = PARSE_FAILURE;
282
0
        return 0;
283
0
    }
284
285
93
    typedef typename std::make_unsigned<T>::type UnsignedT;
286
93
    UnsignedT val = 0;
287
93
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
288
93
    bool negative = false;
289
93
    int i = 0;
290
93
    switch (*s) {
  Branch (290:13): [True: 85, False: 8]
291
8
    case '-':
  Branch (291:5): [True: 8, False: 85]
292
8
        negative = true;
293
8
        max_val += 1;
294
8
        [[fallthrough]];
295
8
    case '+':
  Branch (295:5): [True: 0, False: 93]
296
8
        ++i;
297
        // only one '+'/'-' char, so could return failure directly
298
8
        if (UNLIKELY(len == 1)) {
Line
Count
Source
36
8
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 8]
299
0
            *result = PARSE_FAILURE;
300
0
            return 0;
301
0
        }
302
93
    }
303
304
    // This is the fast path where the string cannot overflow.
305
93
    if (LIKELY(len - i < vectorized::NumberTraits::max_ascii_len<T>())) {
Line
Count
Source
35
93
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 53, False: 40]
306
53
        val = string_to_int_no_overflow<UnsignedT>(s + i, len - i, result);
307
53
        return static_cast<T>(negative ? -val : val);
  Branch (307:31): [True: 8, False: 45]
308
53
    }
309
310
40
    const T max_div_10 = max_val / 10;
311
40
    const T max_mod_10 = max_val % 10;
312
313
40
    int first = i;
314
40
    for (; i < len; ++i) {
  Branch (314:12): [True: 40, False: 0]
315
40
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
Line
Count
Source
35
76
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 0, False: 40]
  Branch (35:42): [True: 36, False: 4]
  Branch (35:42): [True: 0, False: 36]
316
0
            T digit = s[i] - '0';
317
            // This is a tricky check to see if adding this digit will cause an overflow.
318
0
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
Line
Count
Source
36
0
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 0]
319
0
                *result = PARSE_OVERFLOW;
320
0
                return negative ? -max_val : max_val;
  Branch (320:24): [True: 0, False: 0]
321
0
            }
322
0
            val = val * 10 + digit;
323
40
        } else {
324
40
            if ((UNLIKELY(i == first || (!is_all_whitespace(s + i, len - i) &&
Line
Count
Source
36
40
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:44): [True: 0, False: 0]
  Branch (36:44): [True: 0, False: 0]
  Branch (36:44): [True: 40, False: 0]
  Branch (324:17): [True: 40, False: 0]
325
40
                                         !is_float_suffix(s + i, len - i))))) {
326
                // Reject the string because either the first char was not a digit,
327
                // or the remaining chars are not all whitespace
328
40
                *result = PARSE_FAILURE;
329
40
                return 0;
330
40
            }
331
            // Returning here is slightly faster than breaking the loop.
332
0
            *result = PARSE_SUCCESS;
333
0
            return static_cast<T>(negative ? -val : val);
  Branch (333:35): [True: 0, False: 0]
334
40
        }
335
40
    }
336
0
    *result = PARSE_SUCCESS;
337
0
    return static_cast<T>(negative ? -val : val);
  Branch (337:27): [True: 0, False: 0]
338
40
}
Unexecuted instantiation: _ZN5doris12StringParser22string_to_int_internalItEET_PKciPNS0_11ParseResultE
339
340
template <typename T>
341
T StringParser::string_to_unsigned_int_internal(const char* __restrict s, int len,
342
2.66k
                                                ParseResult* result) {
343
2.66k
    if (UNLIKELY(len <= 0)) {
Line
Count
Source
36
665
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 665]
    if (UNLIKELY(len <= 0)) {
Line
Count
Source
36
665
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 665]
    if (UNLIKELY(len <= 0)) {
Line
Count
Source
36
665
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 665]
    if (UNLIKELY(len <= 0)) {
Line
Count
Source
36
665
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 665]
344
0
        *result = PARSE_FAILURE;
345
0
        return 0;
346
0
    }
347
348
2.66k
    T val = 0;
349
2.66k
    T max_val = std::numeric_limits<T>::max();
350
2.66k
    int i = 0;
351
352
2.66k
    typedef typename std::make_signed<T>::type signedT;
353
    // This is the fast path where the string cannot overflow.
354
2.66k
    if (LIKELY(len - i < vectorized::NumberTraits::max_ascii_len<signedT>())) {
Line
Count
Source
35
665
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 16, False: 649]
    if (LIKELY(len - i < vectorized::NumberTraits::max_ascii_len<signedT>())) {
Line
Count
Source
35
665
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 31, False: 634]
    if (LIKELY(len - i < vectorized::NumberTraits::max_ascii_len<signedT>())) {
Line
Count
Source
35
665
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 392, False: 273]
    if (LIKELY(len - i < vectorized::NumberTraits::max_ascii_len<signedT>())) {
Line
Count
Source
35
665
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 440, False: 225]
355
879
        val = string_to_int_no_overflow<T>(s + i, len - i, result);
356
879
        return val;
357
879
    }
358
359
1.78k
    const T max_div_10 = max_val / 10;
360
1.78k
    const T max_mod_10 = max_val % 10;
361
362
1.78k
    int first = i;
363
6.54k
    for (; i < len; ++i) {
  Branch (363:12): [True: 1.18k, False: 21]
  Branch (363:12): [True: 1.46k, False: 14]
  Branch (363:12): [True: 1.59k, False: 7]
  Branch (363:12): [True: 2.26k, False: 7]
364
6.49k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
Line
Count
Source
35
1.79k
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 609, False: 572]
  Branch (35:42): [True: 609, False: 572]
  Branch (35:42): [True: 609, False: 0]
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
Line
Count
Source
35
2.35k
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 896, False: 564]
  Branch (35:42): [True: 896, False: 564]
  Branch (35:42): [True: 896, False: 0]
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
Line
Count
Source
35
2.98k
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 1.38k, False: 210]
  Branch (35:42): [True: 1.38k, False: 210]
  Branch (35:42): [True: 1.38k, False: 0]
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
Line
Count
Source
35
4.36k
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 2.10k, False: 162]
  Branch (35:42): [True: 2.10k, False: 162]
  Branch (35:42): [True: 2.10k, False: 0]
365
4.99k
            T digit = s[i] - '0';
366
            // This is a tricky check to see if adding this digit will cause an overflow.
367
4.99k
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
Line
Count
Source
36
609
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 56, False: 553]
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
Line
Count
Source
36
896
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 56, False: 840]
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
Line
Count
Source
36
1.38k
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 56, False: 1.33k]
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
Line
Count
Source
36
2.10k
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 56, False: 2.04k]
368
224
                *result = PARSE_OVERFLOW;
369
224
                return max_val;
370
224
            }
371
4.76k
            val = val * 10 + digit;
372
4.76k
        } else {
373
1.50k
            if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
Line
Count
Source
36
698
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:44): [True: 446, False: 126]
  Branch (36:44): [True: 0, False: 126]
            if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
Line
Count
Source
36
690
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:44): [True: 438, False: 126]
  Branch (36:44): [True: 0, False: 126]
            if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
Line
Count
Source
36
294
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:44): [True: 126, False: 84]
  Branch (36:44): [True: 0, False: 84]
            if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
Line
Count
Source
36
204
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:44): [True: 120, False: 42]
  Branch (36:44): [True: 0, False: 42]
  Branch (373:17): [True: 446, False: 126]
  Branch (373:17): [True: 438, False: 126]
  Branch (373:17): [True: 126, False: 84]
  Branch (373:17): [True: 120, False: 42]
374
                // Reject the string because either the first char was not a digit,
375
                // or the remaining chars are not all whitespace
376
1.13k
                *result = PARSE_FAILURE;
377
1.13k
                return 0;
378
1.13k
            }
379
            // Returning here is slightly faster than breaking the loop.
380
378
            *result = PARSE_SUCCESS;
381
378
            return val;
382
1.50k
        }
383
6.49k
    }
384
49
    *result = PARSE_SUCCESS;
385
49
    return val;
386
1.78k
}
_ZN5doris12StringParser31string_to_unsigned_int_internalIhEET_PKciPNS0_11ParseResultE
Line
Count
Source
342
665
                                                ParseResult* result) {
343
665
    if (UNLIKELY(len <= 0)) {
Line
Count
Source
36
665
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 665]
344
0
        *result = PARSE_FAILURE;
345
0
        return 0;
346
0
    }
347
348
665
    T val = 0;
349
665
    T max_val = std::numeric_limits<T>::max();
350
665
    int i = 0;
351
352
665
    typedef typename std::make_signed<T>::type signedT;
353
    // This is the fast path where the string cannot overflow.
354
665
    if (LIKELY(len - i < vectorized::NumberTraits::max_ascii_len<signedT>())) {
Line
Count
Source
35
665
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 16, False: 649]
355
16
        val = string_to_int_no_overflow<T>(s + i, len - i, result);
356
16
        return val;
357
16
    }
358
359
649
    const T max_div_10 = max_val / 10;
360
649
    const T max_mod_10 = max_val % 10;
361
362
649
    int first = i;
363
1.20k
    for (; i < len; ++i) {
  Branch (363:12): [True: 1.18k, False: 21]
364
1.18k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
Line
Count
Source
35
1.79k
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 609, False: 572]
  Branch (35:42): [True: 609, False: 572]
  Branch (35:42): [True: 609, False: 0]
365
609
            T digit = s[i] - '0';
366
            // This is a tricky check to see if adding this digit will cause an overflow.
367
609
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
Line
Count
Source
36
609
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 56, False: 553]
368
56
                *result = PARSE_OVERFLOW;
369
56
                return max_val;
370
56
            }
371
553
            val = val * 10 + digit;
372
572
        } else {
373
572
            if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
Line
Count
Source
36
698
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:44): [True: 446, False: 126]
  Branch (36:44): [True: 0, False: 126]
  Branch (373:17): [True: 446, False: 126]
374
                // Reject the string because either the first char was not a digit,
375
                // or the remaining chars are not all whitespace
376
446
                *result = PARSE_FAILURE;
377
446
                return 0;
378
446
            }
379
            // Returning here is slightly faster than breaking the loop.
380
126
            *result = PARSE_SUCCESS;
381
126
            return val;
382
572
        }
383
1.18k
    }
384
21
    *result = PARSE_SUCCESS;
385
21
    return val;
386
649
}
_ZN5doris12StringParser31string_to_unsigned_int_internalItEET_PKciPNS0_11ParseResultE
Line
Count
Source
342
665
                                                ParseResult* result) {
343
665
    if (UNLIKELY(len <= 0)) {
Line
Count
Source
36
665
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 665]
344
0
        *result = PARSE_FAILURE;
345
0
        return 0;
346
0
    }
347
348
665
    T val = 0;
349
665
    T max_val = std::numeric_limits<T>::max();
350
665
    int i = 0;
351
352
665
    typedef typename std::make_signed<T>::type signedT;
353
    // This is the fast path where the string cannot overflow.
354
665
    if (LIKELY(len - i < vectorized::NumberTraits::max_ascii_len<signedT>())) {
Line
Count
Source
35
665
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 31, False: 634]
355
31
        val = string_to_int_no_overflow<T>(s + i, len - i, result);
356
31
        return val;
357
31
    }
358
359
634
    const T max_div_10 = max_val / 10;
360
634
    const T max_mod_10 = max_val % 10;
361
362
634
    int first = i;
363
1.47k
    for (; i < len; ++i) {
  Branch (363:12): [True: 1.46k, False: 14]
364
1.46k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
Line
Count
Source
35
2.35k
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 896, False: 564]
  Branch (35:42): [True: 896, False: 564]
  Branch (35:42): [True: 896, False: 0]
365
896
            T digit = s[i] - '0';
366
            // This is a tricky check to see if adding this digit will cause an overflow.
367
896
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
Line
Count
Source
36
896
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 56, False: 840]
368
56
                *result = PARSE_OVERFLOW;
369
56
                return max_val;
370
56
            }
371
840
            val = val * 10 + digit;
372
840
        } else {
373
564
            if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
Line
Count
Source
36
690
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:44): [True: 438, False: 126]
  Branch (36:44): [True: 0, False: 126]
  Branch (373:17): [True: 438, False: 126]
374
                // Reject the string because either the first char was not a digit,
375
                // or the remaining chars are not all whitespace
376
438
                *result = PARSE_FAILURE;
377
438
                return 0;
378
438
            }
379
            // Returning here is slightly faster than breaking the loop.
380
126
            *result = PARSE_SUCCESS;
381
126
            return val;
382
564
        }
383
1.46k
    }
384
14
    *result = PARSE_SUCCESS;
385
14
    return val;
386
634
}
_ZN5doris12StringParser31string_to_unsigned_int_internalIjEET_PKciPNS0_11ParseResultE
Line
Count
Source
342
665
                                                ParseResult* result) {
343
665
    if (UNLIKELY(len <= 0)) {
Line
Count
Source
36
665
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 665]
344
0
        *result = PARSE_FAILURE;
345
0
        return 0;
346
0
    }
347
348
665
    T val = 0;
349
665
    T max_val = std::numeric_limits<T>::max();
350
665
    int i = 0;
351
352
665
    typedef typename std::make_signed<T>::type signedT;
353
    // This is the fast path where the string cannot overflow.
354
665
    if (LIKELY(len - i < vectorized::NumberTraits::max_ascii_len<signedT>())) {
Line
Count
Source
35
665
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 392, False: 273]
355
392
        val = string_to_int_no_overflow<T>(s + i, len - i, result);
356
392
        return val;
357
392
    }
358
359
273
    const T max_div_10 = max_val / 10;
360
273
    const T max_mod_10 = max_val % 10;
361
362
273
    int first = i;
363
1.60k
    for (; i < len; ++i) {
  Branch (363:12): [True: 1.59k, False: 7]
364
1.59k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
Line
Count
Source
35
2.98k
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 1.38k, False: 210]
  Branch (35:42): [True: 1.38k, False: 210]
  Branch (35:42): [True: 1.38k, False: 0]
365
1.38k
            T digit = s[i] - '0';
366
            // This is a tricky check to see if adding this digit will cause an overflow.
367
1.38k
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
Line
Count
Source
36
1.38k
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 56, False: 1.33k]
368
56
                *result = PARSE_OVERFLOW;
369
56
                return max_val;
370
56
            }
371
1.33k
            val = val * 10 + digit;
372
1.33k
        } else {
373
210
            if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
Line
Count
Source
36
294
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:44): [True: 126, False: 84]
  Branch (36:44): [True: 0, False: 84]
  Branch (373:17): [True: 126, False: 84]
374
                // Reject the string because either the first char was not a digit,
375
                // or the remaining chars are not all whitespace
376
126
                *result = PARSE_FAILURE;
377
126
                return 0;
378
126
            }
379
            // Returning here is slightly faster than breaking the loop.
380
84
            *result = PARSE_SUCCESS;
381
84
            return val;
382
210
        }
383
1.59k
    }
384
7
    *result = PARSE_SUCCESS;
385
7
    return val;
386
273
}
_ZN5doris12StringParser31string_to_unsigned_int_internalImEET_PKciPNS0_11ParseResultE
Line
Count
Source
342
665
                                                ParseResult* result) {
343
665
    if (UNLIKELY(len <= 0)) {
Line
Count
Source
36
665
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 665]
344
0
        *result = PARSE_FAILURE;
345
0
        return 0;
346
0
    }
347
348
665
    T val = 0;
349
665
    T max_val = std::numeric_limits<T>::max();
350
665
    int i = 0;
351
352
665
    typedef typename std::make_signed<T>::type signedT;
353
    // This is the fast path where the string cannot overflow.
354
665
    if (LIKELY(len - i < vectorized::NumberTraits::max_ascii_len<signedT>())) {
Line
Count
Source
35
665
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 440, False: 225]
355
440
        val = string_to_int_no_overflow<T>(s + i, len - i, result);
356
440
        return val;
357
440
    }
358
359
225
    const T max_div_10 = max_val / 10;
360
225
    const T max_mod_10 = max_val % 10;
361
362
225
    int first = i;
363
2.26k
    for (; i < len; ++i) {
  Branch (363:12): [True: 2.26k, False: 7]
364
2.26k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
Line
Count
Source
35
4.36k
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 2.10k, False: 162]
  Branch (35:42): [True: 2.10k, False: 162]
  Branch (35:42): [True: 2.10k, False: 0]
365
2.10k
            T digit = s[i] - '0';
366
            // This is a tricky check to see if adding this digit will cause an overflow.
367
2.10k
            if (UNLIKELY(val > (max_div_10 - (digit > max_mod_10)))) {
Line
Count
Source
36
2.10k
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 56, False: 2.04k]
368
56
                *result = PARSE_OVERFLOW;
369
56
                return max_val;
370
56
            }
371
2.04k
            val = val * 10 + digit;
372
2.04k
        } else {
373
162
            if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
Line
Count
Source
36
204
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:44): [True: 120, False: 42]
  Branch (36:44): [True: 0, False: 42]
  Branch (373:17): [True: 120, False: 42]
374
                // Reject the string because either the first char was not a digit,
375
                // or the remaining chars are not all whitespace
376
120
                *result = PARSE_FAILURE;
377
120
                return 0;
378
120
            }
379
            // Returning here is slightly faster than breaking the loop.
380
42
            *result = PARSE_SUCCESS;
381
42
            return val;
382
162
        }
383
2.26k
    }
384
7
    *result = PARSE_SUCCESS;
385
7
    return val;
386
225
}
387
388
template <typename T>
389
T StringParser::string_to_int_internal(const char* __restrict s, int len, int base,
390
53.6k
                                       ParseResult* result) {
391
53.6k
    typedef typename std::make_unsigned<T>::type UnsignedT;
392
53.6k
    UnsignedT val = 0;
393
53.6k
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
394
53.6k
    bool negative = false;
395
53.6k
    if (UNLIKELY(len <= 0)) {
Line
Count
Source
36
51.0k
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 51.0k]
    if (UNLIKELY(len <= 0)) {
Line
Count
Source
36
924
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 924]
    if (UNLIKELY(len <= 0)) {
Line
Count
Source
36
833
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 833]
    if (UNLIKELY(len <= 0)) {
Line
Count
Source
36
833
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 833]
    if (UNLIKELY(len <= 0)) {
Line
Count
Source
36
1
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 1]
396
0
        *result = PARSE_FAILURE;
397
0
        return 0;
398
0
    }
399
53.6k
    int i = 0;
400
53.6k
    switch (*s) {
  Branch (400:13): [True: 37.1k, False: 13.8k]
  Branch (400:13): [True: 672, False: 252]
  Branch (400:13): [True: 581, False: 252]
  Branch (400:13): [True: 581, False: 252]
  Branch (400:13): [True: 1, False: 0]
401
14.3k
    case '-':
  Branch (401:5): [True: 13.7k, False: 37.2k]
  Branch (401:5): [True: 203, False: 721]
  Branch (401:5): [True: 154, False: 679]
  Branch (401:5): [True: 203, False: 630]
  Branch (401:5): [True: 0, False: 1]
402
14.3k
        negative = true;
403
14.3k
        max_val = StringParser::numeric_limits<T>(false) + 1;
404
14.3k
        [[fallthrough]];
405
14.6k
    case '+':
  Branch (405:5): [True: 98, False: 50.9k]
  Branch (405:5): [True: 49, False: 875]
  Branch (405:5): [True: 98, False: 735]
  Branch (405:5): [True: 49, False: 784]
  Branch (405:5): [True: 0, False: 1]
406
14.6k
        i = 1;
407
53.6k
    }
408
409
53.6k
    const T max_div_base = max_val / base;
410
53.6k
    const T max_mod_base = max_val % base;
411
412
53.6k
    int first = i;
413
120k
    for (; i < len; ++i) {
  Branch (413:12): [True: 107k, False: 1.89k]
  Branch (413:12): [True: 2.54k, False: 56]
  Branch (413:12): [True: 3.50k, False: 49]
  Branch (413:12): [True: 5.69k, False: 49]
  Branch (413:12): [True: 2, False: 1]
414
118k
        T digit;
415
118k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
Line
Count
Source
35
179k
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 72.1k, False: 34.8k]
  Branch (35:42): [True: 72.7k, False: 34.2k]
  Branch (35:42): [True: 72.1k, False: 637]
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
Line
Count
Source
35
4.32k
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 1.68k, False: 854]
  Branch (35:42): [True: 1.78k, False: 756]
  Branch (35:42): [True: 1.68k, False: 98]
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
Line
Count
Source
35
6.34k
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 2.83k, False: 672]
  Branch (35:42): [True: 2.83k, False: 672]
  Branch (35:42): [True: 2.83k, False: 0]
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
Line
Count
Source
35
10.7k
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 5.01k, False: 672]
  Branch (35:42): [True: 5.01k, False: 672]
  Branch (35:42): [True: 5.01k, False: 0]
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
Line
Count
Source
35
4
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 0, False: 2]
  Branch (35:42): [True: 2, False: 0]
  Branch (35:42): [True: 0, False: 2]
416
81.6k
            digit = s[i] - '0';
417
81.6k
        } else if (s[i] >= 'a' && s[i] <= 'z') {
  Branch (417:20): [True: 539, False: 34.3k]
  Branch (417:35): [True: 539, False: 0]
  Branch (417:20): [True: 98, False: 756]
  Branch (417:35): [True: 98, False: 0]
  Branch (417:20): [True: 0, False: 672]
  Branch (417:35): [True: 0, False: 0]
  Branch (417:20): [True: 0, False: 672]
  Branch (417:35): [True: 0, False: 0]
  Branch (417:20): [True: 2, False: 0]
  Branch (417:35): [True: 2, False: 0]
418
639
            digit = (s[i] - 'a' + 10);
419
36.4k
        } else if (s[i] >= 'A' && s[i] <= 'Z') {
  Branch (419:20): [True: 98, False: 34.2k]
  Branch (419:35): [True: 98, False: 0]
  Branch (419:20): [True: 0, False: 756]
  Branch (419:35): [True: 0, False: 0]
  Branch (419:20): [True: 0, False: 672]
  Branch (419:35): [True: 0, False: 0]
  Branch (419:20): [True: 0, False: 672]
  Branch (419:35): [True: 0, False: 0]
  Branch (419:20): [True: 0, False: 0]
  Branch (419:35): [True: 0, False: 0]
420
98
            digit = (s[i] - 'A' + 10);
421
36.3k
        } else {
422
36.3k
            if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
Line
Count
Source
36
45.7k
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:44): [True: 22.7k, False: 11.5k]
  Branch (36:44): [True: 161, False: 11.3k]
            if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
Line
Count
Source
36
1.09k
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:44): [True: 420, False: 336]
  Branch (36:44): [True: 0, False: 336]
            if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
Line
Count
Source
36
966
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:44): [True: 378, False: 294]
  Branch (36:44): [True: 0, False: 294]
            if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
Line
Count
Source
36
966
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:44): [True: 378, False: 294]
  Branch (36:44): [True: 0, False: 294]
            if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
Line
Count
Source
36
0
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:44): [True: 0, False: 0]
  Branch (36:44): [True: 0, False: 0]
  Branch (422:17): [True: 22.8k, False: 11.3k]
  Branch (422:17): [True: 420, False: 336]
  Branch (422:17): [True: 378, False: 294]
  Branch (422:17): [True: 378, False: 294]
  Branch (422:17): [True: 0, False: 0]
423
                // Reject the string because either the first char was not an alpha/digit,
424
                // or the remaining chars are not all whitespace
425
24.0k
                *result = PARSE_FAILURE;
426
24.0k
                return 0;
427
24.0k
            }
428
            // skip trailing whitespace.
429
12.2k
            break;
430
36.3k
        }
431
432
        // Bail, if we encounter a digit that is not available in base.
433
82.4k
        if (digit >= base) {
  Branch (433:13): [True: 392, False: 72.4k]
  Branch (433:13): [True: 0, False: 1.78k]
  Branch (433:13): [True: 0, False: 2.83k]
  Branch (433:13): [True: 0, False: 5.01k]
  Branch (433:13): [True: 0, False: 2]
434
392
            break;
435
392
        }
436
437
        // This is a tricky check to see if adding this digit will cause an overflow.
438
82.0k
        if (UNLIKELY(val > (max_div_base - (digit > max_mod_base)))) {
Line
Count
Source
36
72.4k
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 14.5k, False: 57.8k]
        if (UNLIKELY(val > (max_div_base - (digit > max_mod_base)))) {
Line
Count
Source
36
1.78k
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 112, False: 1.67k]
        if (UNLIKELY(val > (max_div_base - (digit > max_mod_base)))) {
Line
Count
Source
36
2.83k
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 112, False: 2.72k]
        if (UNLIKELY(val > (max_div_base - (digit > max_mod_base)))) {
Line
Count
Source
36
5.01k
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 112, False: 4.90k]
        if (UNLIKELY(val > (max_div_base - (digit > max_mod_base)))) {
Line
Count
Source
36
2
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 2]
439
14.8k
            *result = PARSE_OVERFLOW;
440
14.8k
            return static_cast<T>(negative ? -max_val : max_val);
  Branch (440:35): [True: 7.22k, False: 7.28k]
  Branch (440:35): [True: 56, False: 56]
  Branch (440:35): [True: 56, False: 56]
  Branch (440:35): [True: 56, False: 56]
  Branch (440:35): [True: 0, False: 0]
441
14.8k
        }
442
67.2k
        val = val * base + digit;
443
67.2k
    }
444
14.7k
    *result = PARSE_SUCCESS;
445
14.7k
    return static_cast<T>(negative ? -val : val);
  Branch (445:27): [True: 6.46k, False: 7.15k]
  Branch (445:27): [True: 147, False: 245]
  Branch (445:27): [True: 98, False: 245]
  Branch (445:27): [True: 147, False: 196]
  Branch (445:27): [True: 0, False: 1]
446
53.6k
}
_ZN5doris12StringParser22string_to_int_internalIaEET_PKciiPNS0_11ParseResultE
Line
Count
Source
390
51.0k
                                       ParseResult* result) {
391
51.0k
    typedef typename std::make_unsigned<T>::type UnsignedT;
392
51.0k
    UnsignedT val = 0;
393
51.0k
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
394
51.0k
    bool negative = false;
395
51.0k
    if (UNLIKELY(len <= 0)) {
Line
Count
Source
36
51.0k
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 51.0k]
396
0
        *result = PARSE_FAILURE;
397
0
        return 0;
398
0
    }
399
51.0k
    int i = 0;
400
51.0k
    switch (*s) {
  Branch (400:13): [True: 37.1k, False: 13.8k]
401
13.7k
    case '-':
  Branch (401:5): [True: 13.7k, False: 37.2k]
402
13.7k
        negative = true;
403
13.7k
        max_val = StringParser::numeric_limits<T>(false) + 1;
404
13.7k
        [[fallthrough]];
405
13.8k
    case '+':
  Branch (405:5): [True: 98, False: 50.9k]
406
13.8k
        i = 1;
407
51.0k
    }
408
409
51.0k
    const T max_div_base = max_val / base;
410
51.0k
    const T max_mod_base = max_val % base;
411
412
51.0k
    int first = i;
413
108k
    for (; i < len; ++i) {
  Branch (413:12): [True: 107k, False: 1.89k]
414
107k
        T digit;
415
107k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
Line
Count
Source
35
179k
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 72.1k, False: 34.8k]
  Branch (35:42): [True: 72.7k, False: 34.2k]
  Branch (35:42): [True: 72.1k, False: 637]
416
72.1k
            digit = s[i] - '0';
417
72.1k
        } else if (s[i] >= 'a' && s[i] <= 'z') {
  Branch (417:20): [True: 539, False: 34.3k]
  Branch (417:35): [True: 539, False: 0]
418
539
            digit = (s[i] - 'a' + 10);
419
34.3k
        } else if (s[i] >= 'A' && s[i] <= 'Z') {
  Branch (419:20): [True: 98, False: 34.2k]
  Branch (419:35): [True: 98, False: 0]
420
98
            digit = (s[i] - 'A' + 10);
421
34.2k
        } else {
422
34.2k
            if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
Line
Count
Source
36
45.7k
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:44): [True: 22.7k, False: 11.5k]
  Branch (36:44): [True: 161, False: 11.3k]
  Branch (422:17): [True: 22.8k, False: 11.3k]
423
                // Reject the string because either the first char was not an alpha/digit,
424
                // or the remaining chars are not all whitespace
425
22.8k
                *result = PARSE_FAILURE;
426
22.8k
                return 0;
427
22.8k
            }
428
            // skip trailing whitespace.
429
11.3k
            break;
430
34.2k
        }
431
432
        // Bail, if we encounter a digit that is not available in base.
433
72.7k
        if (digit >= base) {
  Branch (433:13): [True: 392, False: 72.4k]
434
392
            break;
435
392
        }
436
437
        // This is a tricky check to see if adding this digit will cause an overflow.
438
72.4k
        if (UNLIKELY(val > (max_div_base - (digit > max_mod_base)))) {
Line
Count
Source
36
72.4k
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 14.5k, False: 57.8k]
439
14.5k
            *result = PARSE_OVERFLOW;
440
14.5k
            return static_cast<T>(negative ? -max_val : max_val);
  Branch (440:35): [True: 7.22k, False: 7.28k]
441
14.5k
        }
442
57.8k
        val = val * base + digit;
443
57.8k
    }
444
13.6k
    *result = PARSE_SUCCESS;
445
13.6k
    return static_cast<T>(negative ? -val : val);
  Branch (445:27): [True: 6.46k, False: 7.15k]
446
51.0k
}
_ZN5doris12StringParser22string_to_int_internalIsEET_PKciiPNS0_11ParseResultE
Line
Count
Source
390
924
                                       ParseResult* result) {
391
924
    typedef typename std::make_unsigned<T>::type UnsignedT;
392
924
    UnsignedT val = 0;
393
924
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
394
924
    bool negative = false;
395
924
    if (UNLIKELY(len <= 0)) {
Line
Count
Source
36
924
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 924]
396
0
        *result = PARSE_FAILURE;
397
0
        return 0;
398
0
    }
399
924
    int i = 0;
400
924
    switch (*s) {
  Branch (400:13): [True: 672, False: 252]
401
203
    case '-':
  Branch (401:5): [True: 203, False: 721]
402
203
        negative = true;
403
203
        max_val = StringParser::numeric_limits<T>(false) + 1;
404
203
        [[fallthrough]];
405
252
    case '+':
  Branch (405:5): [True: 49, False: 875]
406
252
        i = 1;
407
924
    }
408
409
924
    const T max_div_base = max_val / base;
410
924
    const T max_mod_base = max_val % base;
411
412
924
    int first = i;
413
2.59k
    for (; i < len; ++i) {
  Branch (413:12): [True: 2.54k, False: 56]
414
2.54k
        T digit;
415
2.54k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
Line
Count
Source
35
4.32k
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 1.68k, False: 854]
  Branch (35:42): [True: 1.78k, False: 756]
  Branch (35:42): [True: 1.68k, False: 98]
416
1.68k
            digit = s[i] - '0';
417
1.68k
        } else if (s[i] >= 'a' && s[i] <= 'z') {
  Branch (417:20): [True: 98, False: 756]
  Branch (417:35): [True: 98, False: 0]
418
98
            digit = (s[i] - 'a' + 10);
419
756
        } else if (s[i] >= 'A' && s[i] <= 'Z') {
  Branch (419:20): [True: 0, False: 756]
  Branch (419:35): [True: 0, False: 0]
420
0
            digit = (s[i] - 'A' + 10);
421
756
        } else {
422
756
            if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
Line
Count
Source
36
1.09k
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:44): [True: 420, False: 336]
  Branch (36:44): [True: 0, False: 336]
  Branch (422:17): [True: 420, False: 336]
423
                // Reject the string because either the first char was not an alpha/digit,
424
                // or the remaining chars are not all whitespace
425
420
                *result = PARSE_FAILURE;
426
420
                return 0;
427
420
            }
428
            // skip trailing whitespace.
429
336
            break;
430
756
        }
431
432
        // Bail, if we encounter a digit that is not available in base.
433
1.78k
        if (digit >= base) {
  Branch (433:13): [True: 0, False: 1.78k]
434
0
            break;
435
0
        }
436
437
        // This is a tricky check to see if adding this digit will cause an overflow.
438
1.78k
        if (UNLIKELY(val > (max_div_base - (digit > max_mod_base)))) {
Line
Count
Source
36
1.78k
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 112, False: 1.67k]
439
112
            *result = PARSE_OVERFLOW;
440
112
            return static_cast<T>(negative ? -max_val : max_val);
  Branch (440:35): [True: 56, False: 56]
441
112
        }
442
1.67k
        val = val * base + digit;
443
1.67k
    }
444
392
    *result = PARSE_SUCCESS;
445
392
    return static_cast<T>(negative ? -val : val);
  Branch (445:27): [True: 147, False: 245]
446
924
}
_ZN5doris12StringParser22string_to_int_internalIiEET_PKciiPNS0_11ParseResultE
Line
Count
Source
390
833
                                       ParseResult* result) {
391
833
    typedef typename std::make_unsigned<T>::type UnsignedT;
392
833
    UnsignedT val = 0;
393
833
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
394
833
    bool negative = false;
395
833
    if (UNLIKELY(len <= 0)) {
Line
Count
Source
36
833
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 833]
396
0
        *result = PARSE_FAILURE;
397
0
        return 0;
398
0
    }
399
833
    int i = 0;
400
833
    switch (*s) {
  Branch (400:13): [True: 581, False: 252]
401
154
    case '-':
  Branch (401:5): [True: 154, False: 679]
402
154
        negative = true;
403
154
        max_val = StringParser::numeric_limits<T>(false) + 1;
404
154
        [[fallthrough]];
405
252
    case '+':
  Branch (405:5): [True: 98, False: 735]
406
252
        i = 1;
407
833
    }
408
409
833
    const T max_div_base = max_val / base;
410
833
    const T max_mod_base = max_val % base;
411
412
833
    int first = i;
413
3.55k
    for (; i < len; ++i) {
  Branch (413:12): [True: 3.50k, False: 49]
414
3.50k
        T digit;
415
3.50k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
Line
Count
Source
35
6.34k
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 2.83k, False: 672]
  Branch (35:42): [True: 2.83k, False: 672]
  Branch (35:42): [True: 2.83k, False: 0]
416
2.83k
            digit = s[i] - '0';
417
2.83k
        } else if (s[i] >= 'a' && s[i] <= 'z') {
  Branch (417:20): [True: 0, False: 672]
  Branch (417:35): [True: 0, False: 0]
418
0
            digit = (s[i] - 'a' + 10);
419
672
        } else if (s[i] >= 'A' && s[i] <= 'Z') {
  Branch (419:20): [True: 0, False: 672]
  Branch (419:35): [True: 0, False: 0]
420
0
            digit = (s[i] - 'A' + 10);
421
672
        } else {
422
672
            if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
Line
Count
Source
36
966
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:44): [True: 378, False: 294]
  Branch (36:44): [True: 0, False: 294]
  Branch (422:17): [True: 378, False: 294]
423
                // Reject the string because either the first char was not an alpha/digit,
424
                // or the remaining chars are not all whitespace
425
378
                *result = PARSE_FAILURE;
426
378
                return 0;
427
378
            }
428
            // skip trailing whitespace.
429
294
            break;
430
672
        }
431
432
        // Bail, if we encounter a digit that is not available in base.
433
2.83k
        if (digit >= base) {
  Branch (433:13): [True: 0, False: 2.83k]
434
0
            break;
435
0
        }
436
437
        // This is a tricky check to see if adding this digit will cause an overflow.
438
2.83k
        if (UNLIKELY(val > (max_div_base - (digit > max_mod_base)))) {
Line
Count
Source
36
2.83k
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 112, False: 2.72k]
439
112
            *result = PARSE_OVERFLOW;
440
112
            return static_cast<T>(negative ? -max_val : max_val);
  Branch (440:35): [True: 56, False: 56]
441
112
        }
442
2.72k
        val = val * base + digit;
443
2.72k
    }
444
343
    *result = PARSE_SUCCESS;
445
343
    return static_cast<T>(negative ? -val : val);
  Branch (445:27): [True: 98, False: 245]
446
833
}
_ZN5doris12StringParser22string_to_int_internalIlEET_PKciiPNS0_11ParseResultE
Line
Count
Source
390
833
                                       ParseResult* result) {
391
833
    typedef typename std::make_unsigned<T>::type UnsignedT;
392
833
    UnsignedT val = 0;
393
833
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
394
833
    bool negative = false;
395
833
    if (UNLIKELY(len <= 0)) {
Line
Count
Source
36
833
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 833]
396
0
        *result = PARSE_FAILURE;
397
0
        return 0;
398
0
    }
399
833
    int i = 0;
400
833
    switch (*s) {
  Branch (400:13): [True: 581, False: 252]
401
203
    case '-':
  Branch (401:5): [True: 203, False: 630]
402
203
        negative = true;
403
203
        max_val = StringParser::numeric_limits<T>(false) + 1;
404
203
        [[fallthrough]];
405
252
    case '+':
  Branch (405:5): [True: 49, False: 784]
406
252
        i = 1;
407
833
    }
408
409
833
    const T max_div_base = max_val / base;
410
833
    const T max_mod_base = max_val % base;
411
412
833
    int first = i;
413
5.74k
    for (; i < len; ++i) {
  Branch (413:12): [True: 5.69k, False: 49]
414
5.69k
        T digit;
415
5.69k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
Line
Count
Source
35
10.7k
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 5.01k, False: 672]
  Branch (35:42): [True: 5.01k, False: 672]
  Branch (35:42): [True: 5.01k, False: 0]
416
5.01k
            digit = s[i] - '0';
417
5.01k
        } else if (s[i] >= 'a' && s[i] <= 'z') {
  Branch (417:20): [True: 0, False: 672]
  Branch (417:35): [True: 0, False: 0]
418
0
            digit = (s[i] - 'a' + 10);
419
672
        } else if (s[i] >= 'A' && s[i] <= 'Z') {
  Branch (419:20): [True: 0, False: 672]
  Branch (419:35): [True: 0, False: 0]
420
0
            digit = (s[i] - 'A' + 10);
421
672
        } else {
422
672
            if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
Line
Count
Source
36
966
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:44): [True: 378, False: 294]
  Branch (36:44): [True: 0, False: 294]
  Branch (422:17): [True: 378, False: 294]
423
                // Reject the string because either the first char was not an alpha/digit,
424
                // or the remaining chars are not all whitespace
425
378
                *result = PARSE_FAILURE;
426
378
                return 0;
427
378
            }
428
            // skip trailing whitespace.
429
294
            break;
430
672
        }
431
432
        // Bail, if we encounter a digit that is not available in base.
433
5.01k
        if (digit >= base) {
  Branch (433:13): [True: 0, False: 5.01k]
434
0
            break;
435
0
        }
436
437
        // This is a tricky check to see if adding this digit will cause an overflow.
438
5.01k
        if (UNLIKELY(val > (max_div_base - (digit > max_mod_base)))) {
Line
Count
Source
36
5.01k
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 112, False: 4.90k]
439
112
            *result = PARSE_OVERFLOW;
440
112
            return static_cast<T>(negative ? -max_val : max_val);
  Branch (440:35): [True: 56, False: 56]
441
112
        }
442
4.90k
        val = val * base + digit;
443
4.90k
    }
444
343
    *result = PARSE_SUCCESS;
445
343
    return static_cast<T>(negative ? -val : val);
  Branch (445:27): [True: 147, False: 196]
446
833
}
_ZN5doris12StringParser22string_to_int_internalImEET_PKciiPNS0_11ParseResultE
Line
Count
Source
390
1
                                       ParseResult* result) {
391
1
    typedef typename std::make_unsigned<T>::type UnsignedT;
392
1
    UnsignedT val = 0;
393
1
    UnsignedT max_val = StringParser::numeric_limits<T>(false);
394
1
    bool negative = false;
395
1
    if (UNLIKELY(len <= 0)) {
Line
Count
Source
36
1
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 1]
396
0
        *result = PARSE_FAILURE;
397
0
        return 0;
398
0
    }
399
1
    int i = 0;
400
1
    switch (*s) {
  Branch (400:13): [True: 1, False: 0]
401
0
    case '-':
  Branch (401:5): [True: 0, False: 1]
402
0
        negative = true;
403
0
        max_val = StringParser::numeric_limits<T>(false) + 1;
404
0
        [[fallthrough]];
405
0
    case '+':
  Branch (405:5): [True: 0, False: 1]
406
0
        i = 1;
407
1
    }
408
409
1
    const T max_div_base = max_val / base;
410
1
    const T max_mod_base = max_val % base;
411
412
1
    int first = i;
413
3
    for (; i < len; ++i) {
  Branch (413:12): [True: 2, False: 1]
414
2
        T digit;
415
2
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
Line
Count
Source
35
4
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 0, False: 2]
  Branch (35:42): [True: 2, False: 0]
  Branch (35:42): [True: 0, False: 2]
416
0
            digit = s[i] - '0';
417
2
        } else if (s[i] >= 'a' && s[i] <= 'z') {
  Branch (417:20): [True: 2, False: 0]
  Branch (417:35): [True: 2, False: 0]
418
2
            digit = (s[i] - 'a' + 10);
419
2
        } else if (s[i] >= 'A' && s[i] <= 'Z') {
  Branch (419:20): [True: 0, False: 0]
  Branch (419:35): [True: 0, False: 0]
420
0
            digit = (s[i] - 'A' + 10);
421
0
        } else {
422
0
            if ((UNLIKELY(i == first || !is_all_whitespace(s + i, len - i)))) {
Line
Count
Source
36
0
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:44): [True: 0, False: 0]
  Branch (36:44): [True: 0, False: 0]
  Branch (422:17): [True: 0, False: 0]
423
                // Reject the string because either the first char was not an alpha/digit,
424
                // or the remaining chars are not all whitespace
425
0
                *result = PARSE_FAILURE;
426
0
                return 0;
427
0
            }
428
            // skip trailing whitespace.
429
0
            break;
430
0
        }
431
432
        // Bail, if we encounter a digit that is not available in base.
433
2
        if (digit >= base) {
  Branch (433:13): [True: 0, False: 2]
434
0
            break;
435
0
        }
436
437
        // This is a tricky check to see if adding this digit will cause an overflow.
438
2
        if (UNLIKELY(val > (max_div_base - (digit > max_mod_base)))) {
Line
Count
Source
36
2
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 2]
439
0
            *result = PARSE_OVERFLOW;
440
0
            return static_cast<T>(negative ? -max_val : max_val);
  Branch (440:35): [True: 0, False: 0]
441
0
        }
442
2
        val = val * base + digit;
443
2
    }
444
1
    *result = PARSE_SUCCESS;
445
1
    return static_cast<T>(negative ? -val : val);
  Branch (445:27): [True: 0, False: 1]
446
1
}
447
448
template <typename T>
449
124k
T StringParser::string_to_int_no_overflow(const char* __restrict s, int len, ParseResult* result) {
450
124k
    T val = 0;
451
124k
    if (UNLIKELY(len == 0)) {
Line
Count
Source
36
1.50k
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 1.50k]
    if (UNLIKELY(len == 0)) {
Line
Count
Source
36
119k
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 119k]
    if (UNLIKELY(len == 0)) {
Line
Count
Source
36
145
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 145]
    if (UNLIKELY(len == 0)) {
Line
Count
Source
36
1.96k
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 1.96k]
    if (UNLIKELY(len == 0)) {
Line
Count
Source
36
1.09k
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 1.09k]
    if (UNLIKELY(len == 0)) {
Line
Count
Source
36
0
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 0]
452
0
        *result = PARSE_SUCCESS;
453
0
        return val;
454
0
    }
455
    // Factor out the first char for error handling speeds up the loop.
456
124k
    if (LIKELY(s[0] >= '0' && s[0] <= '9')) {
Line
Count
Source
35
3.00k
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 1.45k, False: 50]
  Branch (35:42): [True: 1.49k, False: 16]
  Branch (35:42): [True: 1.45k, False: 34]
    if (LIKELY(s[0] >= '0' && s[0] <= '9')) {
Line
Count
Source
35
239k
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 119k, False: 0]
  Branch (35:42): [True: 119k, False: 0]
  Branch (35:42): [True: 119k, False: 0]
    if (LIKELY(s[0] >= '0' && s[0] <= '9')) {
Line
Count
Source
35
266
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 119, False: 26]
  Branch (35:42): [True: 121, False: 24]
  Branch (35:42): [True: 119, False: 2]
    if (LIKELY(s[0] >= '0' && s[0] <= '9')) {
Line
Count
Source
35
3.07k
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 397, False: 1.57k]
  Branch (35:42): [True: 1.10k, False: 859]
  Branch (35:42): [True: 397, False: 712]
    if (LIKELY(s[0] >= '0' && s[0] <= '9')) {
Line
Count
Source
35
1.67k
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 575, False: 520]
  Branch (35:42): [True: 579, False: 516]
  Branch (35:42): [True: 575, False: 4]
    if (LIKELY(s[0] >= '0' && s[0] <= '9')) {
Line
Count
Source
35
0
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 0, False: 0]
  Branch (35:42): [True: 0, False: 0]
  Branch (35:42): [True: 0, False: 0]
457
122k
        val = s[0] - '0';
458
122k
    } else {
459
2.16k
        *result = PARSE_FAILURE;
460
2.16k
        return 0;
461
2.16k
    }
462
974k
    for (int i = 1; i < len; ++i) {
  Branch (462:21): [True: 1.27k, False: 1.45k]
  Branch (462:21): [True: 848k, False: 119k]
  Branch (462:21): [True: 119, False: 35]
  Branch (462:21): [True: 676, False: 87]
  Branch (462:21): [True: 2.71k, False: 264]
  Branch (462:21): [True: 0, False: 0]
463
853k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
Line
Count
Source
35
2.54k
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 1.27k, False: 0]
  Branch (35:42): [True: 1.27k, False: 0]
  Branch (35:42): [True: 1.27k, False: 0]
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
Line
Count
Source
35
1.69M
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 848k, False: 0]
  Branch (35:42): [True: 848k, False: 0]
  Branch (35:42): [True: 848k, False: 0]
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
Line
Count
Source
35
154
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 35, False: 84]
  Branch (35:42): [True: 35, False: 84]
  Branch (35:42): [True: 35, False: 0]
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
Line
Count
Source
35
1.10k
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 366, False: 310]
  Branch (35:42): [True: 424, False: 252]
  Branch (35:42): [True: 366, False: 58]
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
Line
Count
Source
35
5.14k
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 2.40k, False: 311]
  Branch (35:42): [True: 2.42k, False: 297]
  Branch (35:42): [True: 2.40k, False: 14]
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
Line
Count
Source
35
0
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 0, False: 0]
  Branch (35:42): [True: 0, False: 0]
  Branch (35:42): [True: 0, False: 0]
464
852k
            T digit = s[i] - '0';
465
852k
            val = val * 10 + digit;
466
852k
        } else {
467
705
            if ((UNLIKELY(!is_all_whitespace(s + i, len - i) &&
Line
Count
Source
36
0
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:44): [True: 0, False: 0]
  Branch (36:44): [True: 0, False: 0]
            if ((UNLIKELY(!is_all_whitespace(s + i, len - i) &&
Line
Count
Source
36
0
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:44): [True: 0, False: 0]
  Branch (36:44): [True: 0, False: 0]
            if ((UNLIKELY(!is_all_whitespace(s + i, len - i) &&
Line
Count
Source
36
84
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:44): [True: 0, False: 84]
  Branch (36:44): [True: 0, False: 0]
            if ((UNLIKELY(!is_all_whitespace(s + i, len - i) &&
Line
Count
Source
36
410
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:44): [True: 100, False: 210]
  Branch (36:44): [True: 100, False: 0]
            if ((UNLIKELY(!is_all_whitespace(s + i, len - i) &&
Line
Count
Source
36
328
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:44): [True: 17, False: 294]
  Branch (36:44): [True: 16, False: 1]
            if ((UNLIKELY(!is_all_whitespace(s + i, len - i) &&
Line
Count
Source
36
0
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:44): [True: 0, False: 0]
  Branch (36:44): [True: 0, False: 0]
  Branch (467:17): [True: 0, False: 0]
  Branch (467:17): [True: 0, False: 0]
  Branch (467:17): [True: 0, False: 84]
  Branch (467:17): [True: 100, False: 210]
  Branch (467:17): [True: 16, False: 295]
  Branch (467:17): [True: 0, False: 0]
468
705
                          !is_float_suffix(s + i, len - i)))) {
469
116
                *result = PARSE_FAILURE;
470
116
                return 0;
471
116
            }
472
589
            *result = PARSE_SUCCESS;
473
589
            return val;
474
705
        }
475
853k
    }
476
121k
    *result = PARSE_SUCCESS;
477
121k
    return val;
478
122k
}
_ZN5doris12StringParser25string_to_int_no_overflowIhEET_PKciPNS0_11ParseResultE
Line
Count
Source
449
1.50k
T StringParser::string_to_int_no_overflow(const char* __restrict s, int len, ParseResult* result) {
450
1.50k
    T val = 0;
451
1.50k
    if (UNLIKELY(len == 0)) {
Line
Count
Source
36
1.50k
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 1.50k]
452
0
        *result = PARSE_SUCCESS;
453
0
        return val;
454
0
    }
455
    // Factor out the first char for error handling speeds up the loop.
456
1.50k
    if (LIKELY(s[0] >= '0' && s[0] <= '9')) {
Line
Count
Source
35
3.00k
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 1.45k, False: 50]
  Branch (35:42): [True: 1.49k, False: 16]
  Branch (35:42): [True: 1.45k, False: 34]
457
1.45k
        val = s[0] - '0';
458
1.45k
    } else {
459
50
        *result = PARSE_FAILURE;
460
50
        return 0;
461
50
    }
462
2.72k
    for (int i = 1; i < len; ++i) {
  Branch (462:21): [True: 1.27k, False: 1.45k]
463
1.27k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
Line
Count
Source
35
2.54k
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 1.27k, False: 0]
  Branch (35:42): [True: 1.27k, False: 0]
  Branch (35:42): [True: 1.27k, False: 0]
464
1.27k
            T digit = s[i] - '0';
465
1.27k
            val = val * 10 + digit;
466
1.27k
        } else {
467
0
            if ((UNLIKELY(!is_all_whitespace(s + i, len - i) &&
Line
Count
Source
36
0
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:44): [True: 0, False: 0]
  Branch (36:44): [True: 0, False: 0]
  Branch (467:17): [True: 0, False: 0]
468
0
                          !is_float_suffix(s + i, len - i)))) {
469
0
                *result = PARSE_FAILURE;
470
0
                return 0;
471
0
            }
472
0
            *result = PARSE_SUCCESS;
473
0
            return val;
474
0
        }
475
1.27k
    }
476
1.45k
    *result = PARSE_SUCCESS;
477
1.45k
    return val;
478
1.45k
}
_ZN5doris12StringParser25string_to_int_no_overflowIoEET_PKciPNS0_11ParseResultE
Line
Count
Source
449
119k
T StringParser::string_to_int_no_overflow(const char* __restrict s, int len, ParseResult* result) {
450
119k
    T val = 0;
451
119k
    if (UNLIKELY(len == 0)) {
Line
Count
Source
36
119k
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 119k]
452
0
        *result = PARSE_SUCCESS;
453
0
        return val;
454
0
    }
455
    // Factor out the first char for error handling speeds up the loop.
456
119k
    if (LIKELY(s[0] >= '0' && s[0] <= '9')) {
Line
Count
Source
35
239k
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 119k, False: 0]
  Branch (35:42): [True: 119k, False: 0]
  Branch (35:42): [True: 119k, False: 0]
457
119k
        val = s[0] - '0';
458
119k
    } else {
459
0
        *result = PARSE_FAILURE;
460
0
        return 0;
461
0
    }
462
968k
    for (int i = 1; i < len; ++i) {
  Branch (462:21): [True: 848k, False: 119k]
463
848k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
Line
Count
Source
35
1.69M
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 848k, False: 0]
  Branch (35:42): [True: 848k, False: 0]
  Branch (35:42): [True: 848k, False: 0]
464
848k
            T digit = s[i] - '0';
465
848k
            val = val * 10 + digit;
466
848k
        } else {
467
0
            if ((UNLIKELY(!is_all_whitespace(s + i, len - i) &&
Line
Count
Source
36
0
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:44): [True: 0, False: 0]
  Branch (36:44): [True: 0, False: 0]
  Branch (467:17): [True: 0, False: 0]
468
0
                          !is_float_suffix(s + i, len - i)))) {
469
0
                *result = PARSE_FAILURE;
470
0
                return 0;
471
0
            }
472
0
            *result = PARSE_SUCCESS;
473
0
            return val;
474
0
        }
475
848k
    }
476
119k
    *result = PARSE_SUCCESS;
477
119k
    return val;
478
119k
}
_ZN5doris12StringParser25string_to_int_no_overflowItEET_PKciPNS0_11ParseResultE
Line
Count
Source
449
145
T StringParser::string_to_int_no_overflow(const char* __restrict s, int len, ParseResult* result) {
450
145
    T val = 0;
451
145
    if (UNLIKELY(len == 0)) {
Line
Count
Source
36
145
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 145]
452
0
        *result = PARSE_SUCCESS;
453
0
        return val;
454
0
    }
455
    // Factor out the first char for error handling speeds up the loop.
456
145
    if (LIKELY(s[0] >= '0' && s[0] <= '9')) {
Line
Count
Source
35
266
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 119, False: 26]
  Branch (35:42): [True: 121, False: 24]
  Branch (35:42): [True: 119, False: 2]
457
119
        val = s[0] - '0';
458
119
    } else {
459
26
        *result = PARSE_FAILURE;
460
26
        return 0;
461
26
    }
462
154
    for (int i = 1; i < len; ++i) {
  Branch (462:21): [True: 119, False: 35]
463
119
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
Line
Count
Source
35
154
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 35, False: 84]
  Branch (35:42): [True: 35, False: 84]
  Branch (35:42): [True: 35, False: 0]
464
35
            T digit = s[i] - '0';
465
35
            val = val * 10 + digit;
466
84
        } else {
467
84
            if ((UNLIKELY(!is_all_whitespace(s + i, len - i) &&
Line
Count
Source
36
84
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:44): [True: 0, False: 84]
  Branch (36:44): [True: 0, False: 0]
  Branch (467:17): [True: 0, False: 84]
468
84
                          !is_float_suffix(s + i, len - i)))) {
469
0
                *result = PARSE_FAILURE;
470
0
                return 0;
471
0
            }
472
84
            *result = PARSE_SUCCESS;
473
84
            return val;
474
84
        }
475
119
    }
476
35
    *result = PARSE_SUCCESS;
477
35
    return val;
478
119
}
_ZN5doris12StringParser25string_to_int_no_overflowIjEET_PKciPNS0_11ParseResultE
Line
Count
Source
449
1.96k
T StringParser::string_to_int_no_overflow(const char* __restrict s, int len, ParseResult* result) {
450
1.96k
    T val = 0;
451
1.96k
    if (UNLIKELY(len == 0)) {
Line
Count
Source
36
1.96k
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 1.96k]
452
0
        *result = PARSE_SUCCESS;
453
0
        return val;
454
0
    }
455
    // Factor out the first char for error handling speeds up the loop.
456
1.96k
    if (LIKELY(s[0] >= '0' && s[0] <= '9')) {
Line
Count
Source
35
3.07k
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 397, False: 1.57k]
  Branch (35:42): [True: 1.10k, False: 859]
  Branch (35:42): [True: 397, False: 712]
457
397
        val = s[0] - '0';
458
1.57k
    } else {
459
1.57k
        *result = PARSE_FAILURE;
460
1.57k
        return 0;
461
1.57k
    }
462
763
    for (int i = 1; i < len; ++i) {
  Branch (462:21): [True: 676, False: 87]
463
676
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
Line
Count
Source
35
1.10k
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 366, False: 310]
  Branch (35:42): [True: 424, False: 252]
  Branch (35:42): [True: 366, False: 58]
464
366
            T digit = s[i] - '0';
465
366
            val = val * 10 + digit;
466
366
        } else {
467
310
            if ((UNLIKELY(!is_all_whitespace(s + i, len - i) &&
Line
Count
Source
36
410
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:44): [True: 100, False: 210]
  Branch (36:44): [True: 100, False: 0]
  Branch (467:17): [True: 100, False: 210]
468
310
                          !is_float_suffix(s + i, len - i)))) {
469
100
                *result = PARSE_FAILURE;
470
100
                return 0;
471
100
            }
472
210
            *result = PARSE_SUCCESS;
473
210
            return val;
474
310
        }
475
676
    }
476
87
    *result = PARSE_SUCCESS;
477
87
    return val;
478
397
}
_ZN5doris12StringParser25string_to_int_no_overflowImEET_PKciPNS0_11ParseResultE
Line
Count
Source
449
1.09k
T StringParser::string_to_int_no_overflow(const char* __restrict s, int len, ParseResult* result) {
450
1.09k
    T val = 0;
451
1.09k
    if (UNLIKELY(len == 0)) {
Line
Count
Source
36
1.09k
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 1.09k]
452
0
        *result = PARSE_SUCCESS;
453
0
        return val;
454
0
    }
455
    // Factor out the first char for error handling speeds up the loop.
456
1.09k
    if (LIKELY(s[0] >= '0' && s[0] <= '9')) {
Line
Count
Source
35
1.67k
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 575, False: 520]
  Branch (35:42): [True: 579, False: 516]
  Branch (35:42): [True: 575, False: 4]
457
575
        val = s[0] - '0';
458
575
    } else {
459
520
        *result = PARSE_FAILURE;
460
520
        return 0;
461
520
    }
462
2.98k
    for (int i = 1; i < len; ++i) {
  Branch (462:21): [True: 2.71k, False: 264]
463
2.71k
        if (LIKELY(s[i] >= '0' && s[i] <= '9')) {
Line
Count
Source
35
5.14k
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 2.40k, False: 311]
  Branch (35:42): [True: 2.42k, False: 297]
  Branch (35:42): [True: 2.40k, False: 14]
464
2.40k
            T digit = s[i] - '0';
465
2.40k
            val = val * 10 + digit;
466
2.40k
        } else {
467
311
            if ((UNLIKELY(!is_all_whitespace(s + i, len - i) &&
Line
Count
Source
36
328
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:44): [True: 17, False: 294]
  Branch (36:44): [True: 16, False: 1]
  Branch (467:17): [True: 16, False: 295]
468
311
                          !is_float_suffix(s + i, len - i)))) {
469
16
                *result = PARSE_FAILURE;
470
16
                return 0;
471
16
            }
472
295
            *result = PARSE_SUCCESS;
473
295
            return val;
474
311
        }
475
2.71k
    }
476
264
    *result = PARSE_SUCCESS;
477
264
    return val;
478
575
}
Unexecuted instantiation: _ZN5doris12StringParser25string_to_int_no_overflowIN4wide7integerILm256EjEEEET_PKciPNS0_11ParseResultE
479
480
template <typename T>
481
66.9k
T StringParser::string_to_float_internal(const char* __restrict s, int len, ParseResult* result) {
482
66.9k
    int i = 0;
483
    // skip leading spaces
484
107k
    for (; i < len; ++i) {
  Branch (484:12): [True: 79.0k, False: 3]
  Branch (484:12): [True: 28.6k, False: 0]
485
107k
        if (!is_whitespace(s[i])) {
  Branch (485:13): [True: 58.6k, False: 20.4k]
  Branch (485:13): [True: 8.25k, False: 20.4k]
486
66.8k
            break;
487
66.8k
        }
488
107k
    }
489
490
    // skip back spaces
491
66.9k
    int j = len - 1;
492
108k
    for (; j >= i; j--) {
  Branch (492:12): [True: 79.2k, False: 3]
  Branch (492:12): [True: 28.8k, False: 0]
493
108k
        if (!is_whitespace(s[j])) {
  Branch (493:13): [True: 58.6k, False: 20.5k]
  Branch (493:13): [True: 8.25k, False: 20.5k]
494
66.8k
            break;
495
66.8k
        }
496
108k
    }
497
498
    // skip leading '+', from_chars can handle '-'
499
66.9k
    if (i < len && s[i] == '+') {
  Branch (499:9): [True: 58.6k, False: 3]
  Branch (499:20): [True: 2.64k, False: 56.0k]
  Branch (499:9): [True: 8.25k, False: 0]
  Branch (499:20): [True: 2.64k, False: 5.60k]
500
5.29k
        i++;
501
5.29k
    }
502
66.9k
    if (UNLIKELY(i > j)) {
Line
Count
Source
36
58.6k
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 3, False: 58.6k]
    if (UNLIKELY(i > j)) {
Line
Count
Source
36
8.25k
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 8.25k]
503
3
        *result = PARSE_FAILURE;
504
3
        return 0;
505
3
    }
506
507
    // Use double here to not lose precision while accumulating the result
508
66.8k
    double val = 0;
509
66.8k
    auto res = fast_float::from_chars(s + i, s + j + 1, val);
510
511
66.8k
    if (res.ec == std::errc() && res.ptr == s + j + 1) {
  Branch (511:9): [True: 57.9k, False: 744]
  Branch (511:34): [True: 56.7k, False: 1.19k]
  Branch (511:9): [True: 7.51k, False: 739]
  Branch (511:34): [True: 6.32k, False: 1.18k]
512
63.0k
        if (abs(val) == std::numeric_limits<T>::infinity()) {
  Branch (512:13): [True: 809, False: 55.9k]
  Branch (512:13): [True: 443, False: 5.88k]
513
1.25k
            auto contain_inf = false;
514
9.32k
            for (int k = i; k < j + 1; k++) {
  Branch (514:29): [True: 8.33k, False: 368]
  Branch (514:29): [True: 627, False: 2]
515
8.95k
                if (s[k] == 'i' || s[k] == 'I') {
  Branch (515:21): [True: 294, False: 8.03k]
  Branch (515:36): [True: 147, False: 7.89k]
  Branch (515:21): [True: 294, False: 333]
  Branch (515:36): [True: 147, False: 186]
516
882
                    contain_inf = true;
517
882
                    break;
518
882
                }
519
8.95k
            }
520
521
1.25k
            *result = contain_inf ? PARSE_SUCCESS : PARSE_OVERFLOW;
  Branch (521:23): [True: 441, False: 368]
  Branch (521:23): [True: 441, False: 2]
522
61.7k
        } else {
523
61.7k
            *result = PARSE_SUCCESS;
524
61.7k
        }
525
63.0k
        return val;
526
63.0k
    } else {
527
3.86k
        *result = PARSE_FAILURE;
528
3.86k
    }
529
3.86k
    return 0;
530
66.8k
}
_ZN5doris12StringParser24string_to_float_internalIdEET_PKciPNS0_11ParseResultE
Line
Count
Source
481
58.6k
T StringParser::string_to_float_internal(const char* __restrict s, int len, ParseResult* result) {
482
58.6k
    int i = 0;
483
    // skip leading spaces
484
79.0k
    for (; i < len; ++i) {
  Branch (484:12): [True: 79.0k, False: 3]
485
79.0k
        if (!is_whitespace(s[i])) {
  Branch (485:13): [True: 58.6k, False: 20.4k]
486
58.6k
            break;
487
58.6k
        }
488
79.0k
    }
489
490
    // skip back spaces
491
58.6k
    int j = len - 1;
492
79.2k
    for (; j >= i; j--) {
  Branch (492:12): [True: 79.2k, False: 3]
493
79.2k
        if (!is_whitespace(s[j])) {
  Branch (493:13): [True: 58.6k, False: 20.5k]
494
58.6k
            break;
495
58.6k
        }
496
79.2k
    }
497
498
    // skip leading '+', from_chars can handle '-'
499
58.6k
    if (i < len && s[i] == '+') {
  Branch (499:9): [True: 58.6k, False: 3]
  Branch (499:20): [True: 2.64k, False: 56.0k]
500
2.64k
        i++;
501
2.64k
    }
502
58.6k
    if (UNLIKELY(i > j)) {
Line
Count
Source
36
58.6k
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 3, False: 58.6k]
503
3
        *result = PARSE_FAILURE;
504
3
        return 0;
505
3
    }
506
507
    // Use double here to not lose precision while accumulating the result
508
58.6k
    double val = 0;
509
58.6k
    auto res = fast_float::from_chars(s + i, s + j + 1, val);
510
511
58.6k
    if (res.ec == std::errc() && res.ptr == s + j + 1) {
  Branch (511:9): [True: 57.9k, False: 744]
  Branch (511:34): [True: 56.7k, False: 1.19k]
512
56.7k
        if (abs(val) == std::numeric_limits<T>::infinity()) {
  Branch (512:13): [True: 809, False: 55.9k]
513
809
            auto contain_inf = false;
514
8.69k
            for (int k = i; k < j + 1; k++) {
  Branch (514:29): [True: 8.33k, False: 368]
515
8.33k
                if (s[k] == 'i' || s[k] == 'I') {
  Branch (515:21): [True: 294, False: 8.03k]
  Branch (515:36): [True: 147, False: 7.89k]
516
441
                    contain_inf = true;
517
441
                    break;
518
441
                }
519
8.33k
            }
520
521
809
            *result = contain_inf ? PARSE_SUCCESS : PARSE_OVERFLOW;
  Branch (521:23): [True: 441, False: 368]
522
55.9k
        } else {
523
55.9k
            *result = PARSE_SUCCESS;
524
55.9k
        }
525
56.7k
        return val;
526
56.7k
    } else {
527
1.93k
        *result = PARSE_FAILURE;
528
1.93k
    }
529
1.93k
    return 0;
530
58.6k
}
_ZN5doris12StringParser24string_to_float_internalIfEET_PKciPNS0_11ParseResultE
Line
Count
Source
481
8.25k
T StringParser::string_to_float_internal(const char* __restrict s, int len, ParseResult* result) {
482
8.25k
    int i = 0;
483
    // skip leading spaces
484
28.6k
    for (; i < len; ++i) {
  Branch (484:12): [True: 28.6k, False: 0]
485
28.6k
        if (!is_whitespace(s[i])) {
  Branch (485:13): [True: 8.25k, False: 20.4k]
486
8.25k
            break;
487
8.25k
        }
488
28.6k
    }
489
490
    // skip back spaces
491
8.25k
    int j = len - 1;
492
28.8k
    for (; j >= i; j--) {
  Branch (492:12): [True: 28.8k, False: 0]
493
28.8k
        if (!is_whitespace(s[j])) {
  Branch (493:13): [True: 8.25k, False: 20.5k]
494
8.25k
            break;
495
8.25k
        }
496
28.8k
    }
497
498
    // skip leading '+', from_chars can handle '-'
499
8.25k
    if (i < len && s[i] == '+') {
  Branch (499:9): [True: 8.25k, False: 0]
  Branch (499:20): [True: 2.64k, False: 5.60k]
500
2.64k
        i++;
501
2.64k
    }
502
8.25k
    if (UNLIKELY(i > j)) {
Line
Count
Source
36
8.25k
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 8.25k]
503
0
        *result = PARSE_FAILURE;
504
0
        return 0;
505
0
    }
506
507
    // Use double here to not lose precision while accumulating the result
508
8.25k
    double val = 0;
509
8.25k
    auto res = fast_float::from_chars(s + i, s + j + 1, val);
510
511
8.25k
    if (res.ec == std::errc() && res.ptr == s + j + 1) {
  Branch (511:9): [True: 7.51k, False: 739]
  Branch (511:34): [True: 6.32k, False: 1.18k]
512
6.32k
        if (abs(val) == std::numeric_limits<T>::infinity()) {
  Branch (512:13): [True: 443, False: 5.88k]
513
443
            auto contain_inf = false;
514
629
            for (int k = i; k < j + 1; k++) {
  Branch (514:29): [True: 627, False: 2]
515
627
                if (s[k] == 'i' || s[k] == 'I') {
  Branch (515:21): [True: 294, False: 333]
  Branch (515:36): [True: 147, False: 186]
516
441
                    contain_inf = true;
517
441
                    break;
518
441
                }
519
627
            }
520
521
443
            *result = contain_inf ? PARSE_SUCCESS : PARSE_OVERFLOW;
  Branch (521:23): [True: 441, False: 2]
522
5.88k
        } else {
523
5.88k
            *result = PARSE_SUCCESS;
524
5.88k
        }
525
6.32k
        return val;
526
6.32k
    } else {
527
1.92k
        *result = PARSE_FAILURE;
528
1.92k
    }
529
1.92k
    return 0;
530
8.25k
}
531
532
inline bool StringParser::string_to_bool_internal(const char* __restrict s, int len,
533
620
                                                  ParseResult* result) {
534
620
    *result = PARSE_SUCCESS;
535
536
620
    if (len >= 4 && (s[0] == 't' || s[0] == 'T')) {
  Branch (536:9): [True: 598, False: 22]
  Branch (536:22): [True: 170, False: 428]
  Branch (536:37): [True: 0, False: 428]
537
170
        bool match = (s[1] == 'r' || s[1] == 'R') && (s[2] == 'u' || s[2] == 'U') &&
  Branch (537:23): [True: 114, False: 56]
  Branch (537:38): [True: 0, False: 56]
  Branch (537:55): [True: 114, False: 0]
  Branch (537:70): [True: 0, False: 0]
538
170
                     (s[3] == 'e' || s[3] == 'E');
  Branch (538:23): [True: 114, False: 0]
  Branch (538:38): [True: 0, False: 0]
539
170
        if (match && LIKELY(is_all_whitespace(s + 4, len - 4))) {
Line
Count
Source
35
114
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 58, False: 56]
  Branch (539:13): [True: 114, False: 56]
540
58
            return true;
541
58
        }
542
450
    } else if (len >= 5 && (s[0] == 'f' || s[0] == 'F')) {
  Branch (542:16): [True: 426, False: 24]
  Branch (542:29): [True: 170, False: 256]
  Branch (542:44): [True: 0, False: 256]
543
170
        bool match = (s[1] == 'a' || s[1] == 'A') && (s[2] == 'l' || s[2] == 'L') &&
  Branch (543:23): [True: 114, False: 56]
  Branch (543:38): [True: 0, False: 56]
  Branch (543:55): [True: 114, False: 0]
  Branch (543:70): [True: 0, False: 0]
544
170
                     (s[3] == 's' || s[3] == 'S') && (s[4] == 'e' || s[4] == 'E');
  Branch (544:23): [True: 114, False: 0]
  Branch (544:38): [True: 0, False: 0]
  Branch (544:55): [True: 114, False: 0]
  Branch (544:70): [True: 0, False: 0]
545
170
        if (match && LIKELY(is_all_whitespace(s + 5, len - 5))) {
Line
Count
Source
35
114
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 52, False: 62]
  Branch (545:13): [True: 114, False: 56]
546
52
            return false;
547
52
        }
548
170
    }
549
550
510
    *result = PARSE_FAILURE;
551
510
    return false;
552
620
}
553
554
template <PrimitiveType P, typename T, typename DecimalType>
555
T StringParser::string_to_decimal(const char* __restrict s, int len, int type_precision,
556
231
                                  int type_scale, ParseResult* result) {
557
231
    static_assert(std::is_same_v<T, int32_t> || std::is_same_v<T, int64_t> ||
558
231
                          std::is_same_v<T, __int128> || std::is_same_v<T, wide::Int256>,
559
231
                  "Cast string to decimal only support target type int32_t, int64_t, __int128 or "
560
231
                  "wide::Int256.");
561
    // Special cases:
562
    //   1) '' == Fail, an empty string fails to parse.
563
    //   2) '   #   ' == #, leading and trailing white space is ignored.
564
    //   3) '.' == 0, a single dot parses as zero (for consistency with other types).
565
    //   4) '#.' == '#', a trailing dot is ignored.
566
567
    // Ignore leading and trailing spaces.
568
231
    while (len > 0 && is_whitespace(*s)) {
  Branch (568:12): [True: 28, False: 0]
  Branch (568:23): [True: 0, False: 28]
  Branch (568:12): [True: 35, False: 1]
  Branch (568:23): [True: 0, False: 35]
  Branch (568:12): [True: 28, False: 0]
  Branch (568:23): [True: 0, False: 28]
  Branch (568:12): [True: 1, False: 0]
  Branch (568:23): [True: 0, False: 1]
  Branch (568:12): [True: 138, False: 0]
  Branch (568:23): [True: 0, False: 138]
569
0
        ++s;
570
0
        --len;
571
0
    }
572
231
    while (len > 0 && is_whitespace(s[len - 1])) {
  Branch (572:12): [True: 28, False: 0]
  Branch (572:23): [True: 0, False: 28]
  Branch (572:12): [True: 35, False: 1]
  Branch (572:23): [True: 0, False: 35]
  Branch (572:12): [True: 28, False: 0]
  Branch (572:23): [True: 0, False: 28]
  Branch (572:12): [True: 1, False: 0]
  Branch (572:23): [True: 0, False: 1]
  Branch (572:12): [True: 138, False: 0]
  Branch (572:23): [True: 0, False: 138]
573
0
        --len;
574
0
    }
575
576
231
    bool is_negative = false;
577
231
    if (len > 0) {
  Branch (577:9): [True: 28, False: 0]
  Branch (577:9): [True: 35, False: 1]
  Branch (577:9): [True: 28, False: 0]
  Branch (577:9): [True: 1, False: 0]
  Branch (577:9): [True: 138, False: 0]
578
230
        switch (*s) {
  Branch (578:17): [True: 22, False: 6]
  Branch (578:17): [True: 28, False: 7]
  Branch (578:17): [True: 27, False: 1]
  Branch (578:17): [True: 1, False: 0]
  Branch (578:17): [True: 113, False: 25]
579
39
        case '-':
  Branch (579:9): [True: 6, False: 22]
  Branch (579:9): [True: 7, False: 28]
  Branch (579:9): [True: 1, False: 27]
  Branch (579:9): [True: 0, False: 1]
  Branch (579:9): [True: 25, False: 113]
580
39
            is_negative = true;
581
39
            [[fallthrough]];
582
39
        case '+':
  Branch (582:9): [True: 0, False: 28]
  Branch (582:9): [True: 0, False: 35]
  Branch (582:9): [True: 0, False: 28]
  Branch (582:9): [True: 0, False: 1]
  Branch (582:9): [True: 0, False: 138]
583
39
            ++s;
584
39
            --len;
585
230
        }
586
230
    }
587
588
    // Ignore leading zeros.
589
231
    bool found_value = false;
590
258
    while (len > 0 && UNLIKELY(*s == '0')) {
Line
Count
Source
36
28
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 28]
    while (len > 0 && UNLIKELY(*s == '0')) {
Line
Count
Source
36
36
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 1, False: 35]
    while (len > 0 && UNLIKELY(*s == '0')) {
Line
Count
Source
36
32
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 4, False: 28]
    while (len > 0 && UNLIKELY(*s == '0')) {
Line
Count
Source
36
1
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 1]
    while (len > 0 && UNLIKELY(*s == '0')) {
Line
Count
Source
36
155
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 22, False: 133]
  Branch (590:12): [True: 28, False: 0]
  Branch (590:12): [True: 36, False: 1]
  Branch (590:12): [True: 32, False: 0]
  Branch (590:12): [True: 1, False: 0]
  Branch (590:12): [True: 155, False: 5]
591
27
        found_value = true;
592
27
        ++s;
593
27
        --len;
594
27
    }
595
596
    // Ignore leading zeros even after a dot. This allows for differentiating between
597
    // cases like 0.01e2, which would fit in a DECIMAL(1, 0), and 0.10e2, which would
598
    // overflow.
599
231
    int scale = 0;
600
231
    int found_dot = 0;
601
231
    if (len > 0 && *s == '.') {
  Branch (601:9): [True: 28, False: 0]
  Branch (601:20): [True: 0, False: 28]
  Branch (601:9): [True: 35, False: 1]
  Branch (601:20): [True: 1, False: 34]
  Branch (601:9): [True: 28, False: 0]
  Branch (601:20): [True: 0, False: 28]
  Branch (601:9): [True: 1, False: 0]
  Branch (601:20): [True: 0, False: 1]
  Branch (601:9): [True: 133, False: 5]
  Branch (601:20): [True: 9, False: 124]
602
10
        found_dot = 1;
603
10
        ++s;
604
10
        --len;
605
16
        while (len > 0 && UNLIKELY(*s == '0')) {
Line
Count
Source
36
0
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 0]
        while (len > 0 && UNLIKELY(*s == '0')) {
Line
Count
Source
36
1
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 1, False: 0]
        while (len > 0 && UNLIKELY(*s == '0')) {
Line
Count
Source
36
0
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 0]
        while (len > 0 && UNLIKELY(*s == '0')) {
Line
Count
Source
36
0
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 0]
        while (len > 0 && UNLIKELY(*s == '0')) {
Line
Count
Source
36
12
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 5, False: 7]
  Branch (605:16): [True: 0, False: 0]
  Branch (605:16): [True: 1, False: 1]
  Branch (605:16): [True: 0, False: 0]
  Branch (605:16): [True: 0, False: 0]
  Branch (605:16): [True: 12, False: 2]
606
6
            found_value = true;
607
6
            ++scale;
608
6
            ++s;
609
6
            --len;
610
6
        }
611
10
    }
612
613
231
    int precision = 0;
614
231
    int max_digit = type_precision - type_scale;
615
231
    int cur_digit = 0;
616
231
    bool found_exponent = false;
617
231
    int8_t exponent = 0;
618
231
    T value = 0;
619
231
    bool has_round = false;
620
4.27k
    for (int i = 0; i < len; ++i) {
  Branch (620:21): [True: 306, False: 16]
  Branch (620:21): [True: 525, False: 34]
  Branch (620:21): [True: 1.04k, False: 28]
  Branch (620:21): [True: 77, False: 1]
  Branch (620:21): [True: 2.12k, False: 127]
621
4.07k
        const char& c = s[i];
622
4.07k
        if (LIKELY('0' <= c && c <= '9')) {
Line
Count
Source
35
572
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 266, False: 40]
  Branch (35:42): [True: 266, False: 40]
  Branch (35:42): [True: 266, False: 0]
        if (LIKELY('0' <= c && c <= '9')) {
Line
Count
Source
35
1.01k
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 491, False: 34]
  Branch (35:42): [True: 493, False: 32]
  Branch (35:42): [True: 491, False: 2]
        if (LIKELY('0' <= c && c <= '9')) {
Line
Count
Source
35
2.05k
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 1.01k, False: 26]
  Branch (35:42): [True: 1.01k, False: 26]
  Branch (35:42): [True: 1.01k, False: 0]
        if (LIKELY('0' <= c && c <= '9')) {
Line
Count
Source
35
153
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 76, False: 1]
  Branch (35:42): [True: 76, False: 1]
  Branch (35:42): [True: 76, False: 0]
        if (LIKELY('0' <= c && c <= '9')) {
Line
Count
Source
35
4.12k
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 2.00k, False: 118]
  Branch (35:42): [True: 2.00k, False: 113]
  Branch (35:42): [True: 2.00k, False: 5]
623
3.85k
            found_value = true;
624
            // Ignore digits once the type's precision limit is reached. This avoids
625
            // overflowing the underlying storage while handling a string like
626
            // 10000000000e-10 into a DECIMAL(1, 0). Adjustments for ignored digits and
627
            // an exponent will be made later.
628
3.85k
            if (LIKELY(type_precision > precision) && !has_round) {
Line
Count
Source
35
532
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 252, False: 14]
            if (LIKELY(type_precision > precision) && !has_round) {
Line
Count
Source
35
982
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 481, False: 10]
            if (LIKELY(type_precision > precision) && !has_round) {
Line
Count
Source
35
2.03k
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 1.01k, False: 4]
            if (LIKELY(type_precision > precision) && !has_round) {
Line
Count
Source
35
152
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 76, False: 0]
            if (LIKELY(type_precision > precision) && !has_round) {
Line
Count
Source
35
4.00k
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 1.99k, False: 8]
  Branch (628:55): [True: 252, False: 0]
  Branch (628:55): [True: 481, False: 0]
  Branch (628:55): [True: 1.01k, False: 0]
  Branch (628:55): [True: 76, False: 0]
  Branch (628:55): [True: 1.99k, False: 0]
629
3.81k
                value = (value * 10) + (c - '0'); // Benchmarks are faster with parenthesis...
630
3.81k
                ++precision;
631
3.81k
                scale += found_dot;
632
3.81k
                cur_digit = precision - scale;
633
3.81k
            } else if (!found_dot && max_digit < (precision - scale)) {
  Branch (633:24): [True: 0, False: 14]
  Branch (633:38): [True: 0, False: 0]
  Branch (633:24): [True: 0, False: 10]
  Branch (633:38): [True: 0, False: 0]
  Branch (633:24): [True: 0, False: 4]
  Branch (633:38): [True: 0, False: 0]
  Branch (633:24): [True: 0, False: 0]
  Branch (633:38): [True: 0, False: 0]
  Branch (633:24): [True: 0, False: 8]
  Branch (633:38): [True: 0, False: 0]
634
0
                *result = StringParser::PARSE_OVERFLOW;
635
0
                value = is_negative ? vectorized::min_decimal_value<DecimalType>(type_precision)
  Branch (635:25): [True: 0, False: 0]
  Branch (635:25): [True: 0, False: 0]
  Branch (635:25): [True: 0, False: 0]
  Branch (635:25): [True: 0, False: 0]
  Branch (635:25): [True: 0, False: 0]
636
0
                                    : vectorized::max_decimal_value<DecimalType>(type_precision);
637
0
                return value;
638
36
            } else if (found_dot && scale >= type_scale && !has_round) {
  Branch (638:24): [True: 14, False: 0]
  Branch (638:37): [True: 4, False: 10]
  Branch (638:60): [True: 4, False: 0]
  Branch (638:24): [True: 10, False: 0]
  Branch (638:37): [True: 4, False: 6]
  Branch (638:60): [True: 4, False: 0]
  Branch (638:24): [True: 4, False: 0]
  Branch (638:37): [True: 4, False: 0]
  Branch (638:60): [True: 4, False: 0]
  Branch (638:24): [True: 0, False: 0]
  Branch (638:37): [True: 0, False: 0]
  Branch (638:60): [True: 0, False: 0]
  Branch (638:24): [True: 8, False: 0]
  Branch (638:37): [True: 8, False: 0]
  Branch (638:60): [True: 8, False: 0]
639
                // make rounding cases
640
20
                if (c > '4') {
  Branch (640:21): [True: 0, False: 4]
  Branch (640:21): [True: 4, False: 0]
  Branch (640:21): [True: 4, False: 0]
  Branch (640:21): [True: 0, False: 0]
  Branch (640:21): [True: 0, False: 8]
641
8
                    value += 1;
642
8
                }
643
20
                has_round = true;
644
20
                continue;
645
20
            } else if (!found_dot) {
  Branch (645:24): [True: 0, False: 10]
  Branch (645:24): [True: 0, False: 6]
  Branch (645:24): [True: 0, False: 0]
  Branch (645:24): [True: 0, False: 0]
  Branch (645:24): [True: 0, False: 0]
646
0
                ++cur_digit;
647
0
            }
648
3.83k
            DCHECK(value >= 0); // For some reason //DCHECK_GE doesn't work with __int128.
649
3.83k
        } else if (c == '.' && LIKELY(!found_dot)) {
Line
Count
Source
35
28
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 28, False: 0]
        } else if (c == '.' && LIKELY(!found_dot)) {
Line
Count
Source
35
32
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 32, False: 0]
        } else if (c == '.' && LIKELY(!found_dot)) {
Line
Count
Source
35
26
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 26, False: 0]
        } else if (c == '.' && LIKELY(!found_dot)) {
Line
Count
Source
35
1
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 1, False: 0]
        } else if (c == '.' && LIKELY(!found_dot)) {
Line
Count
Source
35
107
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 107, False: 0]
  Branch (649:20): [True: 28, False: 12]
  Branch (649:20): [True: 32, False: 2]
  Branch (649:20): [True: 26, False: 0]
  Branch (649:20): [True: 1, False: 0]
  Branch (649:20): [True: 107, False: 11]
650
194
            found_dot = 1;
651
194
        } else if ((c == 'e' || c == 'E') && LIKELY(!found_exponent)) {
Line
Count
Source
35
0
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 0, False: 0]
        } else if ((c == 'e' || c == 'E') && LIKELY(!found_exponent)) {
Line
Count
Source
35
1
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 1, False: 0]
        } else if ((c == 'e' || c == 'E') && LIKELY(!found_exponent)) {
Line
Count
Source
35
0
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 0, False: 0]
        } else if ((c == 'e' || c == 'E') && LIKELY(!found_exponent)) {
Line
Count
Source
35
0
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 0, False: 0]
        } else if ((c == 'e' || c == 'E') && LIKELY(!found_exponent)) {
Line
Count
Source
35
0
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 0, False: 0]
  Branch (651:21): [True: 0, False: 12]
  Branch (651:33): [True: 0, False: 12]
  Branch (651:21): [True: 1, False: 1]
  Branch (651:33): [True: 0, False: 1]
  Branch (651:21): [True: 0, False: 0]
  Branch (651:33): [True: 0, False: 0]
  Branch (651:21): [True: 0, False: 0]
  Branch (651:33): [True: 0, False: 0]
  Branch (651:21): [True: 0, False: 11]
  Branch (651:33): [True: 0, False: 11]
652
1
            found_exponent = true;
653
1
            exponent = string_to_int_internal<int8_t>(s + i + 1, len - i - 1, result);
654
1
            if (UNLIKELY(*result != StringParser::PARSE_SUCCESS)) {
Line
Count
Source
36
0
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 0]
            if (UNLIKELY(*result != StringParser::PARSE_SUCCESS)) {
Line
Count
Source
36
1
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 1]
            if (UNLIKELY(*result != StringParser::PARSE_SUCCESS)) {
Line
Count
Source
36
0
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 0]
            if (UNLIKELY(*result != StringParser::PARSE_SUCCESS)) {
Line
Count
Source
36
0
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 0]
            if (UNLIKELY(*result != StringParser::PARSE_SUCCESS)) {
Line
Count
Source
36
0
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 0]
655
0
                if (*result == StringParser::PARSE_OVERFLOW && exponent < 0) {
  Branch (655:21): [True: 0, False: 0]
  Branch (655:64): [True: 0, False: 0]
  Branch (655:21): [True: 0, False: 0]
  Branch (655:64): [True: 0, False: 0]
  Branch (655:21): [True: 0, False: 0]
  Branch (655:64): [True: 0, False: 0]
  Branch (655:21): [True: 0, False: 0]
  Branch (655:64): [True: 0, False: 0]
  Branch (655:21): [True: 0, False: 0]
  Branch (655:64): [True: 0, False: 0]
656
0
                    *result = StringParser::PARSE_UNDERFLOW;
657
0
                }
658
0
                return 0;
659
0
            }
660
1
            break;
661
24
        } else {
662
24
            if (value == 0) {
  Branch (662:17): [True: 0, False: 12]
  Branch (662:17): [True: 1, False: 0]
  Branch (662:17): [True: 0, False: 0]
  Branch (662:17): [True: 0, False: 0]
  Branch (662:17): [True: 9, False: 2]
663
10
                *result = StringParser::PARSE_FAILURE;
664
10
                return 0;
665
10
            }
666
            // here to handle
667
14
            *result = StringParser::PARSE_SUCCESS;
668
14
            if (type_scale >= scale) {
  Branch (668:17): [True: 12, False: 0]
  Branch (668:17): [True: 0, False: 0]
  Branch (668:17): [True: 0, False: 0]
  Branch (668:17): [True: 0, False: 0]
  Branch (668:17): [True: 2, False: 0]
669
14
                value *= get_scale_multiplier<T>(type_scale - scale);
670
                // here meet non-valid character, should return the value, keep going to meet
671
                // the E/e character because we make right user-given type_precision
672
                // not max number type_precision
673
14
                if (!is_numeric_ascii(c)) {
  Branch (673:21): [True: 12, False: 0]
  Branch (673:21): [True: 0, False: 0]
  Branch (673:21): [True: 0, False: 0]
  Branch (673:21): [True: 0, False: 0]
  Branch (673:21): [True: 2, False: 0]
674
14
                    if (cur_digit > type_precision) {
  Branch (674:25): [True: 0, False: 12]
  Branch (674:25): [True: 0, False: 0]
  Branch (674:25): [True: 0, False: 0]
  Branch (674:25): [True: 0, False: 0]
  Branch (674:25): [True: 0, False: 2]
675
0
                        *result = StringParser::PARSE_OVERFLOW;
676
0
                        value = is_negative
  Branch (676:33): [True: 0, False: 0]
  Branch (676:33): [True: 0, False: 0]
  Branch (676:33): [True: 0, False: 0]
  Branch (676:33): [True: 0, False: 0]
  Branch (676:33): [True: 0, False: 0]
677
0
                                        ? vectorized::min_decimal_value<DecimalType>(type_precision)
678
0
                                        : vectorized::max_decimal_value<DecimalType>(
679
0
                                                  type_precision);
680
0
                        return value;
681
0
                    }
682
14
                    return is_negative ? T(-value) : T(value);
  Branch (682:28): [True: 6, False: 6]
  Branch (682:28): [True: 0, False: 0]
  Branch (682:28): [True: 0, False: 0]
  Branch (682:28): [True: 0, False: 0]
  Branch (682:28): [True: 0, False: 2]
683
14
                }
684
14
            }
685
686
0
            return is_negative ? T(-value) : T(value);
  Branch (686:20): [True: 0, False: 0]
  Branch (686:20): [True: 0, False: 0]
  Branch (686:20): [True: 0, False: 0]
  Branch (686:20): [True: 0, False: 0]
  Branch (686:20): [True: 0, False: 0]
687
14
        }
688
4.07k
    }
689
690
    // Find the number of truncated digits before adjusting the precision for an exponent.
691
207
    if (exponent > scale) {
  Branch (691:9): [True: 0, False: 16]
  Branch (691:9): [True: 1, False: 34]
  Branch (691:9): [True: 0, False: 28]
  Branch (691:9): [True: 0, False: 1]
  Branch (691:9): [True: 0, False: 127]
692
        // Ex: 0.1e3 (which at this point would have precision == 1 and scale == 1), the
693
        //     scale must be set to 0 and the value set to 100 which means a precision of 3.
694
1
        precision += exponent - scale;
695
696
1
        value *= get_scale_multiplier<T>(exponent - scale);
697
1
        scale = 0;
698
206
    } else {
699
        // Ex: 100e-4, the scale must be set to 4 but no adjustment to the value is needed,
700
        //     the precision must also be set to 4 but that will be done below for the
701
        //     non-exponent case anyways.
702
206
        scale -= exponent;
703
206
    }
704
    // Ex: 0.001, at this point would have precision 1 and scale 3 since leading zeros
705
    //     were ignored during previous parsing.
706
207
    if (scale > precision) {
  Branch (706:9): [True: 0, False: 16]
  Branch (706:9): [True: 1, False: 34]
  Branch (706:9): [True: 0, False: 28]
  Branch (706:9): [True: 0, False: 1]
  Branch (706:9): [True: 3, False: 124]
707
4
        precision = scale;
708
4
    }
709
710
    // Microbenchmarks show that beyond this point, returning on parse failure is slower
711
    // than just letting the function run out.
712
127
    *result = StringParser::PARSE_SUCCESS;
713
207
    if (UNLIKELY(precision - scale > type_precision - type_scale)) {
Line
Count
Source
36
16
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 4, False: 12]
    if (UNLIKELY(precision - scale > type_precision - type_scale)) {
Line
Count
Source
36
35
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 6, False: 29]
    if (UNLIKELY(precision - scale > type_precision - type_scale)) {
Line
Count
Source
36
28
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 2, False: 26]
    if (UNLIKELY(precision - scale > type_precision - type_scale)) {
Line
Count
Source
36
1
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 1]
    if (UNLIKELY(precision - scale > type_precision - type_scale)) {
Line
Count
Source
36
127
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 9, False: 118]
714
21
        *result = StringParser::PARSE_OVERFLOW;
715
21
        if constexpr (TYPE_DECIMALV2 != P) {
  Branch (715:23): [Folded - Ignored]
  Branch (715:23): [Folded - Ignored]
  Branch (715:23): [Folded - Ignored]
  Branch (715:23): [Folded - Ignored]
  Branch (715:23): [Folded - Ignored]
716
            // decimalv3 overflow will return max min value for type precision
717
12
            value = is_negative ? vectorized::min_decimal_value<DecimalType>(type_precision)
  Branch (717:21): [True: 0, False: 4]
  Branch (717:21): [True: 0, False: 6]
  Branch (717:21): [True: 0, False: 2]
  Branch (717:21): [True: 0, False: 0]
718
12
                                : vectorized::max_decimal_value<DecimalType>(type_precision);
719
12
            return value;
720
12
        }
721
186
    } else if (UNLIKELY(scale > type_scale)) {
Line
Count
Source
36
12
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 4, False: 8]
    } else if (UNLIKELY(scale > type_scale)) {
Line
Count
Source
36
29
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 29]
    } else if (UNLIKELY(scale > type_scale)) {
Line
Count
Source
36
26
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 8, False: 18]
    } else if (UNLIKELY(scale > type_scale)) {
Line
Count
Source
36
1
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 1]
    } else if (UNLIKELY(scale > type_scale)) {
Line
Count
Source
36
118
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 17, False: 101]
722
29
        *result = StringParser::PARSE_UNDERFLOW;
723
29
        int shift = scale - type_scale;
724
29
        T divisor = get_scale_multiplier<T>(shift);
725
29
        if (UNLIKELY(divisor == std::numeric_limits<T>::max())) {
Line
Count
Source
36
4
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 4]
        if (UNLIKELY(divisor == std::numeric_limits<T>::max())) {
Line
Count
Source
36
0
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 0]
        if (UNLIKELY(divisor == std::numeric_limits<T>::max())) {
Line
Count
Source
36
8
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 8]
        if (UNLIKELY(divisor == std::numeric_limits<T>::max())) {
Line
Count
Source
36
0
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 0]
        if (UNLIKELY(divisor == std::numeric_limits<T>::max())) {
Line
Count
Source
36
17
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 17]
726
0
            value = 0;
727
29
        } else {
728
29
            T remainder = value % divisor;
729
29
            value /= divisor;
730
29
            if ((remainder > 0 ? T(remainder) : T(-remainder)) >= (divisor >> 1)) {
  Branch (730:17): [True: 0, False: 4]
  Branch (730:18): [True: 4, False: 0]
  Branch (730:17): [True: 0, False: 0]
  Branch (730:18): [True: 0, False: 0]
  Branch (730:17): [True: 8, False: 0]
  Branch (730:18): [True: 8, False: 0]
  Branch (730:17): [True: 0, False: 0]
  Branch (730:18): [True: 0, False: 0]
  Branch (730:17): [True: 17, False: 0]
  Branch (730:18): [True: 17, False: 0]
731
25
                value += 1;
732
25
            }
733
29
        }
734
29
        DCHECK(value >= 0); // //DCHECK_GE doesn't work with __int128.
735
157
    } else if (UNLIKELY(!found_value && !found_dot)) {
Line
Count
Source
36
8
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 8]
  Branch (36:44): [True: 0, False: 8]
  Branch (36:44): [True: 0, False: 0]
    } else if (UNLIKELY(!found_value && !found_dot)) {
Line
Count
Source
36
30
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 1, False: 28]
  Branch (36:44): [True: 1, False: 28]
  Branch (36:44): [True: 1, False: 0]
    } else if (UNLIKELY(!found_value && !found_dot)) {
Line
Count
Source
36
18
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 18]
  Branch (36:44): [True: 0, False: 18]
  Branch (36:44): [True: 0, False: 0]
    } else if (UNLIKELY(!found_value && !found_dot)) {
Line
Count
Source
36
1
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 1]
  Branch (36:44): [True: 0, False: 1]
  Branch (36:44): [True: 0, False: 0]
    } else if (UNLIKELY(!found_value && !found_dot)) {
Line
Count
Source
36
101
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 101]
  Branch (36:44): [True: 0, False: 101]
  Branch (36:44): [True: 0, False: 0]
736
1
        *result = StringParser::PARSE_FAILURE;
737
1
    }
738
739
195
    if (type_scale > scale) {
  Branch (739:9): [True: 0, False: 12]
  Branch (739:9): [True: 6, False: 23]
  Branch (739:9): [True: 4, False: 22]
  Branch (739:9): [True: 0, False: 1]
  Branch (739:9): [True: 78, False: 49]
740
88
        value *= get_scale_multiplier<T>(type_scale - scale);
741
88
    }
742
743
195
    return is_negative ? T(-value) : T(value);
  Branch (743:12): [True: 0, False: 12]
  Branch (743:12): [True: 7, False: 22]
  Branch (743:12): [True: 1, False: 25]
  Branch (743:12): [True: 0, False: 1]
  Branch (743:12): [True: 25, False: 102]
744
80
}
_ZN5doris12StringParser17string_to_decimalILNS_13PrimitiveTypeE28EiNS_10vectorized7DecimalIiEEEET0_PKciiiPNS0_11ParseResultE
Line
Count
Source
556
28
                                  int type_scale, ParseResult* result) {
557
28
    static_assert(std::is_same_v<T, int32_t> || std::is_same_v<T, int64_t> ||
558
28
                          std::is_same_v<T, __int128> || std::is_same_v<T, wide::Int256>,
559
28
                  "Cast string to decimal only support target type int32_t, int64_t, __int128 or "
560
28
                  "wide::Int256.");
561
    // Special cases:
562
    //   1) '' == Fail, an empty string fails to parse.
563
    //   2) '   #   ' == #, leading and trailing white space is ignored.
564
    //   3) '.' == 0, a single dot parses as zero (for consistency with other types).
565
    //   4) '#.' == '#', a trailing dot is ignored.
566
567
    // Ignore leading and trailing spaces.
568
28
    while (len > 0 && is_whitespace(*s)) {
  Branch (568:12): [True: 28, False: 0]
  Branch (568:23): [True: 0, False: 28]
569
0
        ++s;
570
0
        --len;
571
0
    }
572
28
    while (len > 0 && is_whitespace(s[len - 1])) {
  Branch (572:12): [True: 28, False: 0]
  Branch (572:23): [True: 0, False: 28]
573
0
        --len;
574
0
    }
575
576
28
    bool is_negative = false;
577
28
    if (len > 0) {
  Branch (577:9): [True: 28, False: 0]
578
28
        switch (*s) {
  Branch (578:17): [True: 22, False: 6]
579
6
        case '-':
  Branch (579:9): [True: 6, False: 22]
580
6
            is_negative = true;
581
6
            [[fallthrough]];
582
6
        case '+':
  Branch (582:9): [True: 0, False: 28]
583
6
            ++s;
584
6
            --len;
585
28
        }
586
28
    }
587
588
    // Ignore leading zeros.
589
28
    bool found_value = false;
590
28
    while (len > 0 && UNLIKELY(*s == '0')) {
Line
Count
Source
36
28
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 28]
  Branch (590:12): [True: 28, False: 0]
591
0
        found_value = true;
592
0
        ++s;
593
0
        --len;
594
0
    }
595
596
    // Ignore leading zeros even after a dot. This allows for differentiating between
597
    // cases like 0.01e2, which would fit in a DECIMAL(1, 0), and 0.10e2, which would
598
    // overflow.
599
28
    int scale = 0;
600
28
    int found_dot = 0;
601
28
    if (len > 0 && *s == '.') {
  Branch (601:9): [True: 28, False: 0]
  Branch (601:20): [True: 0, False: 28]
602
0
        found_dot = 1;
603
0
        ++s;
604
0
        --len;
605
0
        while (len > 0 && UNLIKELY(*s == '0')) {
Line
Count
Source
36
0
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 0]
  Branch (605:16): [True: 0, False: 0]
606
0
            found_value = true;
607
0
            ++scale;
608
0
            ++s;
609
0
            --len;
610
0
        }
611
0
    }
612
613
28
    int precision = 0;
614
28
    int max_digit = type_precision - type_scale;
615
28
    int cur_digit = 0;
616
28
    bool found_exponent = false;
617
28
    int8_t exponent = 0;
618
28
    T value = 0;
619
28
    bool has_round = false;
620
322
    for (int i = 0; i < len; ++i) {
  Branch (620:21): [True: 306, False: 16]
621
306
        const char& c = s[i];
622
306
        if (LIKELY('0' <= c && c <= '9')) {
Line
Count
Source
35
572
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 266, False: 40]
  Branch (35:42): [True: 266, False: 40]
  Branch (35:42): [True: 266, False: 0]
623
266
            found_value = true;
624
            // Ignore digits once the type's precision limit is reached. This avoids
625
            // overflowing the underlying storage while handling a string like
626
            // 10000000000e-10 into a DECIMAL(1, 0). Adjustments for ignored digits and
627
            // an exponent will be made later.
628
266
            if (LIKELY(type_precision > precision) && !has_round) {
Line
Count
Source
35
532
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 252, False: 14]
  Branch (628:55): [True: 252, False: 0]
629
252
                value = (value * 10) + (c - '0'); // Benchmarks are faster with parenthesis...
630
252
                ++precision;
631
252
                scale += found_dot;
632
252
                cur_digit = precision - scale;
633
252
            } else if (!found_dot && max_digit < (precision - scale)) {
  Branch (633:24): [True: 0, False: 14]
  Branch (633:38): [True: 0, False: 0]
634
0
                *result = StringParser::PARSE_OVERFLOW;
635
0
                value = is_negative ? vectorized::min_decimal_value<DecimalType>(type_precision)
  Branch (635:25): [True: 0, False: 0]
636
0
                                    : vectorized::max_decimal_value<DecimalType>(type_precision);
637
0
                return value;
638
14
            } else if (found_dot && scale >= type_scale && !has_round) {
  Branch (638:24): [True: 14, False: 0]
  Branch (638:37): [True: 4, False: 10]
  Branch (638:60): [True: 4, False: 0]
639
                // make rounding cases
640
4
                if (c > '4') {
  Branch (640:21): [True: 0, False: 4]
641
0
                    value += 1;
642
0
                }
643
4
                has_round = true;
644
4
                continue;
645
10
            } else if (!found_dot) {
  Branch (645:24): [True: 0, False: 10]
646
0
                ++cur_digit;
647
0
            }
648
262
            DCHECK(value >= 0); // For some reason //DCHECK_GE doesn't work with __int128.
649
262
        } else if (c == '.' && LIKELY(!found_dot)) {
Line
Count
Source
35
28
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 28, False: 0]
  Branch (649:20): [True: 28, False: 12]
650
28
            found_dot = 1;
651
28
        } else if ((c == 'e' || c == 'E') && LIKELY(!found_exponent)) {
Line
Count
Source
35
0
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 0, False: 0]
  Branch (651:21): [True: 0, False: 12]
  Branch (651:33): [True: 0, False: 12]
652
0
            found_exponent = true;
653
0
            exponent = string_to_int_internal<int8_t>(s + i + 1, len - i - 1, result);
654
0
            if (UNLIKELY(*result != StringParser::PARSE_SUCCESS)) {
Line
Count
Source
36
0
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 0]
655
0
                if (*result == StringParser::PARSE_OVERFLOW && exponent < 0) {
  Branch (655:21): [True: 0, False: 0]
  Branch (655:64): [True: 0, False: 0]
656
0
                    *result = StringParser::PARSE_UNDERFLOW;
657
0
                }
658
0
                return 0;
659
0
            }
660
0
            break;
661
12
        } else {
662
12
            if (value == 0) {
  Branch (662:17): [True: 0, False: 12]
663
0
                *result = StringParser::PARSE_FAILURE;
664
0
                return 0;
665
0
            }
666
            // here to handle
667
12
            *result = StringParser::PARSE_SUCCESS;
668
12
            if (type_scale >= scale) {
  Branch (668:17): [True: 12, False: 0]
669
12
                value *= get_scale_multiplier<T>(type_scale - scale);
670
                // here meet non-valid character, should return the value, keep going to meet
671
                // the E/e character because we make right user-given type_precision
672
                // not max number type_precision
673
12
                if (!is_numeric_ascii(c)) {
  Branch (673:21): [True: 12, False: 0]
674
12
                    if (cur_digit > type_precision) {
  Branch (674:25): [True: 0, False: 12]
675
0
                        *result = StringParser::PARSE_OVERFLOW;
676
0
                        value = is_negative
  Branch (676:33): [True: 0, False: 0]
677
0
                                        ? vectorized::min_decimal_value<DecimalType>(type_precision)
678
0
                                        : vectorized::max_decimal_value<DecimalType>(
679
0
                                                  type_precision);
680
0
                        return value;
681
0
                    }
682
12
                    return is_negative ? T(-value) : T(value);
  Branch (682:28): [True: 6, False: 6]
683
12
                }
684
12
            }
685
686
0
            return is_negative ? T(-value) : T(value);
  Branch (686:20): [True: 0, False: 0]
687
12
        }
688
306
    }
689
690
    // Find the number of truncated digits before adjusting the precision for an exponent.
691
16
    if (exponent > scale) {
  Branch (691:9): [True: 0, False: 16]
692
        // Ex: 0.1e3 (which at this point would have precision == 1 and scale == 1), the
693
        //     scale must be set to 0 and the value set to 100 which means a precision of 3.
694
0
        precision += exponent - scale;
695
696
0
        value *= get_scale_multiplier<T>(exponent - scale);
697
0
        scale = 0;
698
16
    } else {
699
        // Ex: 100e-4, the scale must be set to 4 but no adjustment to the value is needed,
700
        //     the precision must also be set to 4 but that will be done below for the
701
        //     non-exponent case anyways.
702
16
        scale -= exponent;
703
16
    }
704
    // Ex: 0.001, at this point would have precision 1 and scale 3 since leading zeros
705
    //     were ignored during previous parsing.
706
16
    if (scale > precision) {
  Branch (706:9): [True: 0, False: 16]
707
0
        precision = scale;
708
0
    }
709
710
    // Microbenchmarks show that beyond this point, returning on parse failure is slower
711
    // than just letting the function run out.
712
16
    *result = StringParser::PARSE_SUCCESS;
713
16
    if (UNLIKELY(precision - scale > type_precision - type_scale)) {
Line
Count
Source
36
16
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 4, False: 12]
714
4
        *result = StringParser::PARSE_OVERFLOW;
715
4
        if constexpr (TYPE_DECIMALV2 != P) {
  Branch (715:23): [Folded - Ignored]
716
            // decimalv3 overflow will return max min value for type precision
717
4
            value = is_negative ? vectorized::min_decimal_value<DecimalType>(type_precision)
  Branch (717:21): [True: 0, False: 4]
718
4
                                : vectorized::max_decimal_value<DecimalType>(type_precision);
719
4
            return value;
720
4
        }
721
12
    } else if (UNLIKELY(scale > type_scale)) {
Line
Count
Source
36
12
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 4, False: 8]
722
4
        *result = StringParser::PARSE_UNDERFLOW;
723
4
        int shift = scale - type_scale;
724
4
        T divisor = get_scale_multiplier<T>(shift);
725
4
        if (UNLIKELY(divisor == std::numeric_limits<T>::max())) {
Line
Count
Source
36
4
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 4]
726
0
            value = 0;
727
4
        } else {
728
4
            T remainder = value % divisor;
729
4
            value /= divisor;
730
4
            if ((remainder > 0 ? T(remainder) : T(-remainder)) >= (divisor >> 1)) {
  Branch (730:17): [True: 0, False: 4]
  Branch (730:18): [True: 4, False: 0]
731
0
                value += 1;
732
0
            }
733
4
        }
734
4
        DCHECK(value >= 0); // //DCHECK_GE doesn't work with __int128.
735
8
    } else if (UNLIKELY(!found_value && !found_dot)) {
Line
Count
Source
36
8
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 8]
  Branch (36:44): [True: 0, False: 8]
  Branch (36:44): [True: 0, False: 0]
736
0
        *result = StringParser::PARSE_FAILURE;
737
0
    }
738
739
12
    if (type_scale > scale) {
  Branch (739:9): [True: 0, False: 12]
740
0
        value *= get_scale_multiplier<T>(type_scale - scale);
741
0
    }
742
743
12
    return is_negative ? T(-value) : T(value);
  Branch (743:12): [True: 0, False: 12]
744
16
}
_ZN5doris12StringParser17string_to_decimalILNS_13PrimitiveTypeE29ElNS_10vectorized7DecimalIlEEEET0_PKciiiPNS0_11ParseResultE
Line
Count
Source
556
36
                                  int type_scale, ParseResult* result) {
557
36
    static_assert(std::is_same_v<T, int32_t> || std::is_same_v<T, int64_t> ||
558
36
                          std::is_same_v<T, __int128> || std::is_same_v<T, wide::Int256>,
559
36
                  "Cast string to decimal only support target type int32_t, int64_t, __int128 or "
560
36
                  "wide::Int256.");
561
    // Special cases:
562
    //   1) '' == Fail, an empty string fails to parse.
563
    //   2) '   #   ' == #, leading and trailing white space is ignored.
564
    //   3) '.' == 0, a single dot parses as zero (for consistency with other types).
565
    //   4) '#.' == '#', a trailing dot is ignored.
566
567
    // Ignore leading and trailing spaces.
568
36
    while (len > 0 && is_whitespace(*s)) {
  Branch (568:12): [True: 35, False: 1]
  Branch (568:23): [True: 0, False: 35]
569
0
        ++s;
570
0
        --len;
571
0
    }
572
36
    while (len > 0 && is_whitespace(s[len - 1])) {
  Branch (572:12): [True: 35, False: 1]
  Branch (572:23): [True: 0, False: 35]
573
0
        --len;
574
0
    }
575
576
36
    bool is_negative = false;
577
36
    if (len > 0) {
  Branch (577:9): [True: 35, False: 1]
578
35
        switch (*s) {
  Branch (578:17): [True: 28, False: 7]
579
7
        case '-':
  Branch (579:9): [True: 7, False: 28]
580
7
            is_negative = true;
581
7
            [[fallthrough]];
582
7
        case '+':
  Branch (582:9): [True: 0, False: 35]
583
7
            ++s;
584
7
            --len;
585
35
        }
586
35
    }
587
588
    // Ignore leading zeros.
589
36
    bool found_value = false;
590
37
    while (len > 0 && UNLIKELY(*s == '0')) {
Line
Count
Source
36
36
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 1, False: 35]
  Branch (590:12): [True: 36, False: 1]
591
1
        found_value = true;
592
1
        ++s;
593
1
        --len;
594
1
    }
595
596
    // Ignore leading zeros even after a dot. This allows for differentiating between
597
    // cases like 0.01e2, which would fit in a DECIMAL(1, 0), and 0.10e2, which would
598
    // overflow.
599
36
    int scale = 0;
600
36
    int found_dot = 0;
601
36
    if (len > 0 && *s == '.') {
  Branch (601:9): [True: 35, False: 1]
  Branch (601:20): [True: 1, False: 34]
602
1
        found_dot = 1;
603
1
        ++s;
604
1
        --len;
605
2
        while (len > 0 && UNLIKELY(*s == '0')) {
Line
Count
Source
36
1
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 1, False: 0]
  Branch (605:16): [True: 1, False: 1]
606
1
            found_value = true;
607
1
            ++scale;
608
1
            ++s;
609
1
            --len;
610
1
        }
611
1
    }
612
613
36
    int precision = 0;
614
36
    int max_digit = type_precision - type_scale;
615
36
    int cur_digit = 0;
616
36
    bool found_exponent = false;
617
36
    int8_t exponent = 0;
618
36
    T value = 0;
619
36
    bool has_round = false;
620
559
    for (int i = 0; i < len; ++i) {
  Branch (620:21): [True: 525, False: 34]
621
525
        const char& c = s[i];
622
525
        if (LIKELY('0' <= c && c <= '9')) {
Line
Count
Source
35
1.01k
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 491, False: 34]
  Branch (35:42): [True: 493, False: 32]
  Branch (35:42): [True: 491, False: 2]
623
491
            found_value = true;
624
            // Ignore digits once the type's precision limit is reached. This avoids
625
            // overflowing the underlying storage while handling a string like
626
            // 10000000000e-10 into a DECIMAL(1, 0). Adjustments for ignored digits and
627
            // an exponent will be made later.
628
491
            if (LIKELY(type_precision > precision) && !has_round) {
Line
Count
Source
35
982
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 481, False: 10]
  Branch (628:55): [True: 481, False: 0]
629
481
                value = (value * 10) + (c - '0'); // Benchmarks are faster with parenthesis...
630
481
                ++precision;
631
481
                scale += found_dot;
632
481
                cur_digit = precision - scale;
633
481
            } else if (!found_dot && max_digit < (precision - scale)) {
  Branch (633:24): [True: 0, False: 10]
  Branch (633:38): [True: 0, False: 0]
634
0
                *result = StringParser::PARSE_OVERFLOW;
635
0
                value = is_negative ? vectorized::min_decimal_value<DecimalType>(type_precision)
  Branch (635:25): [True: 0, False: 0]
636
0
                                    : vectorized::max_decimal_value<DecimalType>(type_precision);
637
0
                return value;
638
10
            } else if (found_dot && scale >= type_scale && !has_round) {
  Branch (638:24): [True: 10, False: 0]
  Branch (638:37): [True: 4, False: 6]
  Branch (638:60): [True: 4, False: 0]
639
                // make rounding cases
640
4
                if (c > '4') {
  Branch (640:21): [True: 4, False: 0]
641
4
                    value += 1;
642
4
                }
643
4
                has_round = true;
644
4
                continue;
645
6
            } else if (!found_dot) {
  Branch (645:24): [True: 0, False: 6]
646
0
                ++cur_digit;
647
0
            }
648
487
            DCHECK(value >= 0); // For some reason //DCHECK_GE doesn't work with __int128.
649
487
        } else if (c == '.' && LIKELY(!found_dot)) {
Line
Count
Source
35
32
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 32, False: 0]
  Branch (649:20): [True: 32, False: 2]
650
32
            found_dot = 1;
651
32
        } else if ((c == 'e' || c == 'E') && LIKELY(!found_exponent)) {
Line
Count
Source
35
1
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 1, False: 0]
  Branch (651:21): [True: 1, False: 1]
  Branch (651:33): [True: 0, False: 1]
652
1
            found_exponent = true;
653
1
            exponent = string_to_int_internal<int8_t>(s + i + 1, len - i - 1, result);
654
1
            if (UNLIKELY(*result != StringParser::PARSE_SUCCESS)) {
Line
Count
Source
36
1
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 1]
655
0
                if (*result == StringParser::PARSE_OVERFLOW && exponent < 0) {
  Branch (655:21): [True: 0, False: 0]
  Branch (655:64): [True: 0, False: 0]
656
0
                    *result = StringParser::PARSE_UNDERFLOW;
657
0
                }
658
0
                return 0;
659
0
            }
660
1
            break;
661
1
        } else {
662
1
            if (value == 0) {
  Branch (662:17): [True: 1, False: 0]
663
1
                *result = StringParser::PARSE_FAILURE;
664
1
                return 0;
665
1
            }
666
            // here to handle
667
0
            *result = StringParser::PARSE_SUCCESS;
668
0
            if (type_scale >= scale) {
  Branch (668:17): [True: 0, False: 0]
669
0
                value *= get_scale_multiplier<T>(type_scale - scale);
670
                // here meet non-valid character, should return the value, keep going to meet
671
                // the E/e character because we make right user-given type_precision
672
                // not max number type_precision
673
0
                if (!is_numeric_ascii(c)) {
  Branch (673:21): [True: 0, False: 0]
674
0
                    if (cur_digit > type_precision) {
  Branch (674:25): [True: 0, False: 0]
675
0
                        *result = StringParser::PARSE_OVERFLOW;
676
0
                        value = is_negative
  Branch (676:33): [True: 0, False: 0]
677
0
                                        ? vectorized::min_decimal_value<DecimalType>(type_precision)
678
0
                                        : vectorized::max_decimal_value<DecimalType>(
679
0
                                                  type_precision);
680
0
                        return value;
681
0
                    }
682
0
                    return is_negative ? T(-value) : T(value);
  Branch (682:28): [True: 0, False: 0]
683
0
                }
684
0
            }
685
686
0
            return is_negative ? T(-value) : T(value);
  Branch (686:20): [True: 0, False: 0]
687
0
        }
688
525
    }
689
690
    // Find the number of truncated digits before adjusting the precision for an exponent.
691
35
    if (exponent > scale) {
  Branch (691:9): [True: 1, False: 34]
692
        // Ex: 0.1e3 (which at this point would have precision == 1 and scale == 1), the
693
        //     scale must be set to 0 and the value set to 100 which means a precision of 3.
694
1
        precision += exponent - scale;
695
696
1
        value *= get_scale_multiplier<T>(exponent - scale);
697
1
        scale = 0;
698
34
    } else {
699
        // Ex: 100e-4, the scale must be set to 4 but no adjustment to the value is needed,
700
        //     the precision must also be set to 4 but that will be done below for the
701
        //     non-exponent case anyways.
702
34
        scale -= exponent;
703
34
    }
704
    // Ex: 0.001, at this point would have precision 1 and scale 3 since leading zeros
705
    //     were ignored during previous parsing.
706
35
    if (scale > precision) {
  Branch (706:9): [True: 1, False: 34]
707
1
        precision = scale;
708
1
    }
709
710
    // Microbenchmarks show that beyond this point, returning on parse failure is slower
711
    // than just letting the function run out.
712
35
    *result = StringParser::PARSE_SUCCESS;
713
35
    if (UNLIKELY(precision - scale > type_precision - type_scale)) {
Line
Count
Source
36
35
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 6, False: 29]
714
6
        *result = StringParser::PARSE_OVERFLOW;
715
6
        if constexpr (TYPE_DECIMALV2 != P) {
  Branch (715:23): [Folded - Ignored]
716
            // decimalv3 overflow will return max min value for type precision
717
6
            value = is_negative ? vectorized::min_decimal_value<DecimalType>(type_precision)
  Branch (717:21): [True: 0, False: 6]
718
6
                                : vectorized::max_decimal_value<DecimalType>(type_precision);
719
6
            return value;
720
6
        }
721
29
    } else if (UNLIKELY(scale > type_scale)) {
Line
Count
Source
36
29
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 29]
722
0
        *result = StringParser::PARSE_UNDERFLOW;
723
0
        int shift = scale - type_scale;
724
0
        T divisor = get_scale_multiplier<T>(shift);
725
0
        if (UNLIKELY(divisor == std::numeric_limits<T>::max())) {
Line
Count
Source
36
0
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 0]
726
0
            value = 0;
727
0
        } else {
728
0
            T remainder = value % divisor;
729
0
            value /= divisor;
730
0
            if ((remainder > 0 ? T(remainder) : T(-remainder)) >= (divisor >> 1)) {
  Branch (730:17): [True: 0, False: 0]
  Branch (730:18): [True: 0, False: 0]
731
0
                value += 1;
732
0
            }
733
0
        }
734
0
        DCHECK(value >= 0); // //DCHECK_GE doesn't work with __int128.
735
29
    } else if (UNLIKELY(!found_value && !found_dot)) {
Line
Count
Source
36
30
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 1, False: 28]
  Branch (36:44): [True: 1, False: 28]
  Branch (36:44): [True: 1, False: 0]
736
1
        *result = StringParser::PARSE_FAILURE;
737
1
    }
738
739
29
    if (type_scale > scale) {
  Branch (739:9): [True: 6, False: 23]
740
6
        value *= get_scale_multiplier<T>(type_scale - scale);
741
6
    }
742
743
29
    return is_negative ? T(-value) : T(value);
  Branch (743:12): [True: 7, False: 22]
744
35
}
_ZN5doris12StringParser17string_to_decimalILNS_13PrimitiveTypeE30EnNS_10vectorized12Decimal128V3EEET0_PKciiiPNS0_11ParseResultE
Line
Count
Source
556
28
                                  int type_scale, ParseResult* result) {
557
28
    static_assert(std::is_same_v<T, int32_t> || std::is_same_v<T, int64_t> ||
558
28
                          std::is_same_v<T, __int128> || std::is_same_v<T, wide::Int256>,
559
28
                  "Cast string to decimal only support target type int32_t, int64_t, __int128 or "
560
28
                  "wide::Int256.");
561
    // Special cases:
562
    //   1) '' == Fail, an empty string fails to parse.
563
    //   2) '   #   ' == #, leading and trailing white space is ignored.
564
    //   3) '.' == 0, a single dot parses as zero (for consistency with other types).
565
    //   4) '#.' == '#', a trailing dot is ignored.
566
567
    // Ignore leading and trailing spaces.
568
28
    while (len > 0 && is_whitespace(*s)) {
  Branch (568:12): [True: 28, False: 0]
  Branch (568:23): [True: 0, False: 28]
569
0
        ++s;
570
0
        --len;
571
0
    }
572
28
    while (len > 0 && is_whitespace(s[len - 1])) {
  Branch (572:12): [True: 28, False: 0]
  Branch (572:23): [True: 0, False: 28]
573
0
        --len;
574
0
    }
575
576
28
    bool is_negative = false;
577
28
    if (len > 0) {
  Branch (577:9): [True: 28, False: 0]
578
28
        switch (*s) {
  Branch (578:17): [True: 27, False: 1]
579
1
        case '-':
  Branch (579:9): [True: 1, False: 27]
580
1
            is_negative = true;
581
1
            [[fallthrough]];
582
1
        case '+':
  Branch (582:9): [True: 0, False: 28]
583
1
            ++s;
584
1
            --len;
585
28
        }
586
28
    }
587
588
    // Ignore leading zeros.
589
28
    bool found_value = false;
590
32
    while (len > 0 && UNLIKELY(*s == '0')) {
Line
Count
Source
36
32
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 4, False: 28]
  Branch (590:12): [True: 32, False: 0]
591
4
        found_value = true;
592
4
        ++s;
593
4
        --len;
594
4
    }
595
596
    // Ignore leading zeros even after a dot. This allows for differentiating between
597
    // cases like 0.01e2, which would fit in a DECIMAL(1, 0), and 0.10e2, which would
598
    // overflow.
599
28
    int scale = 0;
600
28
    int found_dot = 0;
601
28
    if (len > 0 && *s == '.') {
  Branch (601:9): [True: 28, False: 0]
  Branch (601:20): [True: 0, False: 28]
602
0
        found_dot = 1;
603
0
        ++s;
604
0
        --len;
605
0
        while (len > 0 && UNLIKELY(*s == '0')) {
Line
Count
Source
36
0
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 0]
  Branch (605:16): [True: 0, False: 0]
606
0
            found_value = true;
607
0
            ++scale;
608
0
            ++s;
609
0
            --len;
610
0
        }
611
0
    }
612
613
28
    int precision = 0;
614
28
    int max_digit = type_precision - type_scale;
615
28
    int cur_digit = 0;
616
28
    bool found_exponent = false;
617
28
    int8_t exponent = 0;
618
28
    T value = 0;
619
28
    bool has_round = false;
620
1.07k
    for (int i = 0; i < len; ++i) {
  Branch (620:21): [True: 1.04k, False: 28]
621
1.04k
        const char& c = s[i];
622
1.04k
        if (LIKELY('0' <= c && c <= '9')) {
Line
Count
Source
35
2.05k
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 1.01k, False: 26]
  Branch (35:42): [True: 1.01k, False: 26]
  Branch (35:42): [True: 1.01k, False: 0]
623
1.01k
            found_value = true;
624
            // Ignore digits once the type's precision limit is reached. This avoids
625
            // overflowing the underlying storage while handling a string like
626
            // 10000000000e-10 into a DECIMAL(1, 0). Adjustments for ignored digits and
627
            // an exponent will be made later.
628
1.01k
            if (LIKELY(type_precision > precision) && !has_round) {
Line
Count
Source
35
2.03k
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 1.01k, False: 4]
  Branch (628:55): [True: 1.01k, False: 0]
629
1.01k
                value = (value * 10) + (c - '0'); // Benchmarks are faster with parenthesis...
630
1.01k
                ++precision;
631
1.01k
                scale += found_dot;
632
1.01k
                cur_digit = precision - scale;
633
1.01k
            } else if (!found_dot && max_digit < (precision - scale)) {
  Branch (633:24): [True: 0, False: 4]
  Branch (633:38): [True: 0, False: 0]
634
0
                *result = StringParser::PARSE_OVERFLOW;
635
0
                value = is_negative ? vectorized::min_decimal_value<DecimalType>(type_precision)
  Branch (635:25): [True: 0, False: 0]
636
0
                                    : vectorized::max_decimal_value<DecimalType>(type_precision);
637
0
                return value;
638
4
            } else if (found_dot && scale >= type_scale && !has_round) {
  Branch (638:24): [True: 4, False: 0]
  Branch (638:37): [True: 4, False: 0]
  Branch (638:60): [True: 4, False: 0]
639
                // make rounding cases
640
4
                if (c > '4') {
  Branch (640:21): [True: 4, False: 0]
641
4
                    value += 1;
642
4
                }
643
4
                has_round = true;
644
4
                continue;
645
4
            } else if (!found_dot) {
  Branch (645:24): [True: 0, False: 0]
646
0
                ++cur_digit;
647
0
            }
648
1.01k
            DCHECK(value >= 0); // For some reason //DCHECK_GE doesn't work with __int128.
649
1.01k
        } else if (c == '.' && LIKELY(!found_dot)) {
Line
Count
Source
35
26
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 26, False: 0]
  Branch (649:20): [True: 26, False: 0]
650
26
            found_dot = 1;
651
26
        } else if ((c == 'e' || c == 'E') && LIKELY(!found_exponent)) {
Line
Count
Source
35
0
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 0, False: 0]
  Branch (651:21): [True: 0, False: 0]
  Branch (651:33): [True: 0, False: 0]
652
0
            found_exponent = true;
653
0
            exponent = string_to_int_internal<int8_t>(s + i + 1, len - i - 1, result);
654
0
            if (UNLIKELY(*result != StringParser::PARSE_SUCCESS)) {
Line
Count
Source
36
0
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 0]
655
0
                if (*result == StringParser::PARSE_OVERFLOW && exponent < 0) {
  Branch (655:21): [True: 0, False: 0]
  Branch (655:64): [True: 0, False: 0]
656
0
                    *result = StringParser::PARSE_UNDERFLOW;
657
0
                }
658
0
                return 0;
659
0
            }
660
0
            break;
661
0
        } else {
662
0
            if (value == 0) {
  Branch (662:17): [True: 0, False: 0]
663
0
                *result = StringParser::PARSE_FAILURE;
664
0
                return 0;
665
0
            }
666
            // here to handle
667
0
            *result = StringParser::PARSE_SUCCESS;
668
0
            if (type_scale >= scale) {
  Branch (668:17): [True: 0, False: 0]
669
0
                value *= get_scale_multiplier<T>(type_scale - scale);
670
                // here meet non-valid character, should return the value, keep going to meet
671
                // the E/e character because we make right user-given type_precision
672
                // not max number type_precision
673
0
                if (!is_numeric_ascii(c)) {
  Branch (673:21): [True: 0, False: 0]
674
0
                    if (cur_digit > type_precision) {
  Branch (674:25): [True: 0, False: 0]
675
0
                        *result = StringParser::PARSE_OVERFLOW;
676
0
                        value = is_negative
  Branch (676:33): [True: 0, False: 0]
677
0
                                        ? vectorized::min_decimal_value<DecimalType>(type_precision)
678
0
                                        : vectorized::max_decimal_value<DecimalType>(
679
0
                                                  type_precision);
680
0
                        return value;
681
0
                    }
682
0
                    return is_negative ? T(-value) : T(value);
  Branch (682:28): [True: 0, False: 0]
683
0
                }
684
0
            }
685
686
0
            return is_negative ? T(-value) : T(value);
  Branch (686:20): [True: 0, False: 0]
687
0
        }
688
1.04k
    }
689
690
    // Find the number of truncated digits before adjusting the precision for an exponent.
691
28
    if (exponent > scale) {
  Branch (691:9): [True: 0, False: 28]
692
        // Ex: 0.1e3 (which at this point would have precision == 1 and scale == 1), the
693
        //     scale must be set to 0 and the value set to 100 which means a precision of 3.
694
0
        precision += exponent - scale;
695
696
0
        value *= get_scale_multiplier<T>(exponent - scale);
697
0
        scale = 0;
698
28
    } else {
699
        // Ex: 100e-4, the scale must be set to 4 but no adjustment to the value is needed,
700
        //     the precision must also be set to 4 but that will be done below for the
701
        //     non-exponent case anyways.
702
28
        scale -= exponent;
703
28
    }
704
    // Ex: 0.001, at this point would have precision 1 and scale 3 since leading zeros
705
    //     were ignored during previous parsing.
706
28
    if (scale > precision) {
  Branch (706:9): [True: 0, False: 28]
707
0
        precision = scale;
708
0
    }
709
710
    // Microbenchmarks show that beyond this point, returning on parse failure is slower
711
    // than just letting the function run out.
712
28
    *result = StringParser::PARSE_SUCCESS;
713
28
    if (UNLIKELY(precision - scale > type_precision - type_scale)) {
Line
Count
Source
36
28
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 2, False: 26]
714
2
        *result = StringParser::PARSE_OVERFLOW;
715
2
        if constexpr (TYPE_DECIMALV2 != P) {
  Branch (715:23): [Folded - Ignored]
716
            // decimalv3 overflow will return max min value for type precision
717
2
            value = is_negative ? vectorized::min_decimal_value<DecimalType>(type_precision)
  Branch (717:21): [True: 0, False: 2]
718
2
                                : vectorized::max_decimal_value<DecimalType>(type_precision);
719
2
            return value;
720
2
        }
721
26
    } else if (UNLIKELY(scale > type_scale)) {
Line
Count
Source
36
26
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 8, False: 18]
722
8
        *result = StringParser::PARSE_UNDERFLOW;
723
8
        int shift = scale - type_scale;
724
8
        T divisor = get_scale_multiplier<T>(shift);
725
8
        if (UNLIKELY(divisor == std::numeric_limits<T>::max())) {
Line
Count
Source
36
8
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 8]
726
0
            value = 0;
727
8
        } else {
728
8
            T remainder = value % divisor;
729
8
            value /= divisor;
730
8
            if ((remainder > 0 ? T(remainder) : T(-remainder)) >= (divisor >> 1)) {
  Branch (730:17): [True: 8, False: 0]
  Branch (730:18): [True: 8, False: 0]
731
8
                value += 1;
732
8
            }
733
8
        }
734
8
        DCHECK(value >= 0); // //DCHECK_GE doesn't work with __int128.
735
18
    } else if (UNLIKELY(!found_value && !found_dot)) {
Line
Count
Source
36
18
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 18]
  Branch (36:44): [True: 0, False: 18]
  Branch (36:44): [True: 0, False: 0]
736
0
        *result = StringParser::PARSE_FAILURE;
737
0
    }
738
739
26
    if (type_scale > scale) {
  Branch (739:9): [True: 4, False: 22]
740
4
        value *= get_scale_multiplier<T>(type_scale - scale);
741
4
    }
742
743
26
    return is_negative ? T(-value) : T(value);
  Branch (743:12): [True: 1, False: 25]
744
28
}
_ZN5doris12StringParser17string_to_decimalILNS_13PrimitiveTypeE35EN4wide7integerILm256EiEENS_10vectorized7DecimalIS5_EEEET0_PKciiiPNS0_11ParseResultE
Line
Count
Source
556
1
                                  int type_scale, ParseResult* result) {
557
1
    static_assert(std::is_same_v<T, int32_t> || std::is_same_v<T, int64_t> ||
558
1
                          std::is_same_v<T, __int128> || std::is_same_v<T, wide::Int256>,
559
1
                  "Cast string to decimal only support target type int32_t, int64_t, __int128 or "
560
1
                  "wide::Int256.");
561
    // Special cases:
562
    //   1) '' == Fail, an empty string fails to parse.
563
    //   2) '   #   ' == #, leading and trailing white space is ignored.
564
    //   3) '.' == 0, a single dot parses as zero (for consistency with other types).
565
    //   4) '#.' == '#', a trailing dot is ignored.
566
567
    // Ignore leading and trailing spaces.
568
1
    while (len > 0 && is_whitespace(*s)) {
  Branch (568:12): [True: 1, False: 0]
  Branch (568:23): [True: 0, False: 1]
569
0
        ++s;
570
0
        --len;
571
0
    }
572
1
    while (len > 0 && is_whitespace(s[len - 1])) {
  Branch (572:12): [True: 1, False: 0]
  Branch (572:23): [True: 0, False: 1]
573
0
        --len;
574
0
    }
575
576
1
    bool is_negative = false;
577
1
    if (len > 0) {
  Branch (577:9): [True: 1, False: 0]
578
1
        switch (*s) {
  Branch (578:17): [True: 1, False: 0]
579
0
        case '-':
  Branch (579:9): [True: 0, False: 1]
580
0
            is_negative = true;
581
0
            [[fallthrough]];
582
0
        case '+':
  Branch (582:9): [True: 0, False: 1]
583
0
            ++s;
584
0
            --len;
585
1
        }
586
1
    }
587
588
    // Ignore leading zeros.
589
1
    bool found_value = false;
590
1
    while (len > 0 && UNLIKELY(*s == '0')) {
Line
Count
Source
36
1
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 1]
  Branch (590:12): [True: 1, False: 0]
591
0
        found_value = true;
592
0
        ++s;
593
0
        --len;
594
0
    }
595
596
    // Ignore leading zeros even after a dot. This allows for differentiating between
597
    // cases like 0.01e2, which would fit in a DECIMAL(1, 0), and 0.10e2, which would
598
    // overflow.
599
1
    int scale = 0;
600
1
    int found_dot = 0;
601
1
    if (len > 0 && *s == '.') {
  Branch (601:9): [True: 1, False: 0]
  Branch (601:20): [True: 0, False: 1]
602
0
        found_dot = 1;
603
0
        ++s;
604
0
        --len;
605
0
        while (len > 0 && UNLIKELY(*s == '0')) {
Line
Count
Source
36
0
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 0]
  Branch (605:16): [True: 0, False: 0]
606
0
            found_value = true;
607
0
            ++scale;
608
0
            ++s;
609
0
            --len;
610
0
        }
611
0
    }
612
613
1
    int precision = 0;
614
1
    int max_digit = type_precision - type_scale;
615
1
    int cur_digit = 0;
616
1
    bool found_exponent = false;
617
1
    int8_t exponent = 0;
618
1
    T value = 0;
619
1
    bool has_round = false;
620
78
    for (int i = 0; i < len; ++i) {
  Branch (620:21): [True: 77, False: 1]
621
77
        const char& c = s[i];
622
77
        if (LIKELY('0' <= c && c <= '9')) {
Line
Count
Source
35
153
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 76, False: 1]
  Branch (35:42): [True: 76, False: 1]
  Branch (35:42): [True: 76, False: 0]
623
76
            found_value = true;
624
            // Ignore digits once the type's precision limit is reached. This avoids
625
            // overflowing the underlying storage while handling a string like
626
            // 10000000000e-10 into a DECIMAL(1, 0). Adjustments for ignored digits and
627
            // an exponent will be made later.
628
76
            if (LIKELY(type_precision > precision) && !has_round) {
Line
Count
Source
35
152
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 76, False: 0]
  Branch (628:55): [True: 76, False: 0]
629
76
                value = (value * 10) + (c - '0'); // Benchmarks are faster with parenthesis...
630
76
                ++precision;
631
76
                scale += found_dot;
632
76
                cur_digit = precision - scale;
633
76
            } else if (!found_dot && max_digit < (precision - scale)) {
  Branch (633:24): [True: 0, False: 0]
  Branch (633:38): [True: 0, False: 0]
634
0
                *result = StringParser::PARSE_OVERFLOW;
635
0
                value = is_negative ? vectorized::min_decimal_value<DecimalType>(type_precision)
  Branch (635:25): [True: 0, False: 0]
636
0
                                    : vectorized::max_decimal_value<DecimalType>(type_precision);
637
0
                return value;
638
0
            } else if (found_dot && scale >= type_scale && !has_round) {
  Branch (638:24): [True: 0, False: 0]
  Branch (638:37): [True: 0, False: 0]
  Branch (638:60): [True: 0, False: 0]
639
                // make rounding cases
640
0
                if (c > '4') {
  Branch (640:21): [True: 0, False: 0]
641
0
                    value += 1;
642
0
                }
643
0
                has_round = true;
644
0
                continue;
645
0
            } else if (!found_dot) {
  Branch (645:24): [True: 0, False: 0]
646
0
                ++cur_digit;
647
0
            }
648
76
            DCHECK(value >= 0); // For some reason //DCHECK_GE doesn't work with __int128.
649
76
        } else if (c == '.' && LIKELY(!found_dot)) {
Line
Count
Source
35
1
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 1, False: 0]
  Branch (649:20): [True: 1, False: 0]
650
1
            found_dot = 1;
651
1
        } else if ((c == 'e' || c == 'E') && LIKELY(!found_exponent)) {
Line
Count
Source
35
0
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 0, False: 0]
  Branch (651:21): [True: 0, False: 0]
  Branch (651:33): [True: 0, False: 0]
652
0
            found_exponent = true;
653
0
            exponent = string_to_int_internal<int8_t>(s + i + 1, len - i - 1, result);
654
0
            if (UNLIKELY(*result != StringParser::PARSE_SUCCESS)) {
Line
Count
Source
36
0
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 0]
655
0
                if (*result == StringParser::PARSE_OVERFLOW && exponent < 0) {
  Branch (655:21): [True: 0, False: 0]
  Branch (655:64): [True: 0, False: 0]
656
0
                    *result = StringParser::PARSE_UNDERFLOW;
657
0
                }
658
0
                return 0;
659
0
            }
660
0
            break;
661
0
        } else {
662
0
            if (value == 0) {
  Branch (662:17): [True: 0, False: 0]
663
0
                *result = StringParser::PARSE_FAILURE;
664
0
                return 0;
665
0
            }
666
            // here to handle
667
0
            *result = StringParser::PARSE_SUCCESS;
668
0
            if (type_scale >= scale) {
  Branch (668:17): [True: 0, False: 0]
669
0
                value *= get_scale_multiplier<T>(type_scale - scale);
670
                // here meet non-valid character, should return the value, keep going to meet
671
                // the E/e character because we make right user-given type_precision
672
                // not max number type_precision
673
0
                if (!is_numeric_ascii(c)) {
  Branch (673:21): [True: 0, False: 0]
674
0
                    if (cur_digit > type_precision) {
  Branch (674:25): [True: 0, False: 0]
675
0
                        *result = StringParser::PARSE_OVERFLOW;
676
0
                        value = is_negative
  Branch (676:33): [True: 0, False: 0]
677
0
                                        ? vectorized::min_decimal_value<DecimalType>(type_precision)
678
0
                                        : vectorized::max_decimal_value<DecimalType>(
679
0
                                                  type_precision);
680
0
                        return value;
681
0
                    }
682
0
                    return is_negative ? T(-value) : T(value);
  Branch (682:28): [True: 0, False: 0]
683
0
                }
684
0
            }
685
686
0
            return is_negative ? T(-value) : T(value);
  Branch (686:20): [True: 0, False: 0]
687
0
        }
688
77
    }
689
690
    // Find the number of truncated digits before adjusting the precision for an exponent.
691
1
    if (exponent > scale) {
  Branch (691:9): [True: 0, False: 1]
692
        // Ex: 0.1e3 (which at this point would have precision == 1 and scale == 1), the
693
        //     scale must be set to 0 and the value set to 100 which means a precision of 3.
694
0
        precision += exponent - scale;
695
696
0
        value *= get_scale_multiplier<T>(exponent - scale);
697
0
        scale = 0;
698
1
    } else {
699
        // Ex: 100e-4, the scale must be set to 4 but no adjustment to the value is needed,
700
        //     the precision must also be set to 4 but that will be done below for the
701
        //     non-exponent case anyways.
702
1
        scale -= exponent;
703
1
    }
704
    // Ex: 0.001, at this point would have precision 1 and scale 3 since leading zeros
705
    //     were ignored during previous parsing.
706
1
    if (scale > precision) {
  Branch (706:9): [True: 0, False: 1]
707
0
        precision = scale;
708
0
    }
709
710
    // Microbenchmarks show that beyond this point, returning on parse failure is slower
711
    // than just letting the function run out.
712
1
    *result = StringParser::PARSE_SUCCESS;
713
1
    if (UNLIKELY(precision - scale > type_precision - type_scale)) {
Line
Count
Source
36
1
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 1]
714
0
        *result = StringParser::PARSE_OVERFLOW;
715
0
        if constexpr (TYPE_DECIMALV2 != P) {
  Branch (715:23): [Folded - Ignored]
716
            // decimalv3 overflow will return max min value for type precision
717
0
            value = is_negative ? vectorized::min_decimal_value<DecimalType>(type_precision)
  Branch (717:21): [True: 0, False: 0]
718
0
                                : vectorized::max_decimal_value<DecimalType>(type_precision);
719
0
            return value;
720
0
        }
721
1
    } else if (UNLIKELY(scale > type_scale)) {
Line
Count
Source
36
1
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 1]
722
0
        *result = StringParser::PARSE_UNDERFLOW;
723
0
        int shift = scale - type_scale;
724
0
        T divisor = get_scale_multiplier<T>(shift);
725
0
        if (UNLIKELY(divisor == std::numeric_limits<T>::max())) {
Line
Count
Source
36
0
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 0]
726
0
            value = 0;
727
0
        } else {
728
0
            T remainder = value % divisor;
729
0
            value /= divisor;
730
0
            if ((remainder > 0 ? T(remainder) : T(-remainder)) >= (divisor >> 1)) {
  Branch (730:17): [True: 0, False: 0]
  Branch (730:18): [True: 0, False: 0]
731
0
                value += 1;
732
0
            }
733
0
        }
734
0
        DCHECK(value >= 0); // //DCHECK_GE doesn't work with __int128.
735
1
    } else if (UNLIKELY(!found_value && !found_dot)) {
Line
Count
Source
36
1
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 1]
  Branch (36:44): [True: 0, False: 1]
  Branch (36:44): [True: 0, False: 0]
736
0
        *result = StringParser::PARSE_FAILURE;
737
0
    }
738
739
1
    if (type_scale > scale) {
  Branch (739:9): [True: 0, False: 1]
740
0
        value *= get_scale_multiplier<T>(type_scale - scale);
741
0
    }
742
743
1
    return is_negative ? T(-value) : T(value);
  Branch (743:12): [True: 0, False: 1]
744
1
}
_ZN5doris12StringParser17string_to_decimalILNS_13PrimitiveTypeE20EnNS_10vectorized7DecimalInEEEET0_PKciiiPNS0_11ParseResultE
Line
Count
Source
556
138
                                  int type_scale, ParseResult* result) {
557
138
    static_assert(std::is_same_v<T, int32_t> || std::is_same_v<T, int64_t> ||
558
138
                          std::is_same_v<T, __int128> || std::is_same_v<T, wide::Int256>,
559
138
                  "Cast string to decimal only support target type int32_t, int64_t, __int128 or "
560
138
                  "wide::Int256.");
561
    // Special cases:
562
    //   1) '' == Fail, an empty string fails to parse.
563
    //   2) '   #   ' == #, leading and trailing white space is ignored.
564
    //   3) '.' == 0, a single dot parses as zero (for consistency with other types).
565
    //   4) '#.' == '#', a trailing dot is ignored.
566
567
    // Ignore leading and trailing spaces.
568
138
    while (len > 0 && is_whitespace(*s)) {
  Branch (568:12): [True: 138, False: 0]
  Branch (568:23): [True: 0, False: 138]
569
0
        ++s;
570
0
        --len;
571
0
    }
572
138
    while (len > 0 && is_whitespace(s[len - 1])) {
  Branch (572:12): [True: 138, False: 0]
  Branch (572:23): [True: 0, False: 138]
573
0
        --len;
574
0
    }
575
576
138
    bool is_negative = false;
577
138
    if (len > 0) {
  Branch (577:9): [True: 138, False: 0]
578
138
        switch (*s) {
  Branch (578:17): [True: 113, False: 25]
579
25
        case '-':
  Branch (579:9): [True: 25, False: 113]
580
25
            is_negative = true;
581
25
            [[fallthrough]];
582
25
        case '+':
  Branch (582:9): [True: 0, False: 138]
583
25
            ++s;
584
25
            --len;
585
138
        }
586
138
    }
587
588
    // Ignore leading zeros.
589
138
    bool found_value = false;
590
160
    while (len > 0 && UNLIKELY(*s == '0')) {
Line
Count
Source
36
155
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 22, False: 133]
  Branch (590:12): [True: 155, False: 5]
591
22
        found_value = true;
592
22
        ++s;
593
22
        --len;
594
22
    }
595
596
    // Ignore leading zeros even after a dot. This allows for differentiating between
597
    // cases like 0.01e2, which would fit in a DECIMAL(1, 0), and 0.10e2, which would
598
    // overflow.
599
138
    int scale = 0;
600
138
    int found_dot = 0;
601
138
    if (len > 0 && *s == '.') {
  Branch (601:9): [True: 133, False: 5]
  Branch (601:20): [True: 9, False: 124]
602
9
        found_dot = 1;
603
9
        ++s;
604
9
        --len;
605
14
        while (len > 0 && UNLIKELY(*s == '0')) {
Line
Count
Source
36
12
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 5, False: 7]
  Branch (605:16): [True: 12, False: 2]
606
5
            found_value = true;
607
5
            ++scale;
608
5
            ++s;
609
5
            --len;
610
5
        }
611
9
    }
612
613
138
    int precision = 0;
614
138
    int max_digit = type_precision - type_scale;
615
138
    int cur_digit = 0;
616
138
    bool found_exponent = false;
617
138
    int8_t exponent = 0;
618
138
    T value = 0;
619
138
    bool has_round = false;
620
2.24k
    for (int i = 0; i < len; ++i) {
  Branch (620:21): [True: 2.12k, False: 127]
621
2.12k
        const char& c = s[i];
622
2.12k
        if (LIKELY('0' <= c && c <= '9')) {
Line
Count
Source
35
4.12k
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 2.00k, False: 118]
  Branch (35:42): [True: 2.00k, False: 113]
  Branch (35:42): [True: 2.00k, False: 5]
623
2.00k
            found_value = true;
624
            // Ignore digits once the type's precision limit is reached. This avoids
625
            // overflowing the underlying storage while handling a string like
626
            // 10000000000e-10 into a DECIMAL(1, 0). Adjustments for ignored digits and
627
            // an exponent will be made later.
628
2.00k
            if (LIKELY(type_precision > precision) && !has_round) {
Line
Count
Source
35
4.00k
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 1.99k, False: 8]
  Branch (628:55): [True: 1.99k, False: 0]
629
1.99k
                value = (value * 10) + (c - '0'); // Benchmarks are faster with parenthesis...
630
1.99k
                ++precision;
631
1.99k
                scale += found_dot;
632
1.99k
                cur_digit = precision - scale;
633
1.99k
            } else if (!found_dot && max_digit < (precision - scale)) {
  Branch (633:24): [True: 0, False: 8]
  Branch (633:38): [True: 0, False: 0]
634
0
                *result = StringParser::PARSE_OVERFLOW;
635
0
                value = is_negative ? vectorized::min_decimal_value<DecimalType>(type_precision)
  Branch (635:25): [True: 0, False: 0]
636
0
                                    : vectorized::max_decimal_value<DecimalType>(type_precision);
637
0
                return value;
638
8
            } else if (found_dot && scale >= type_scale && !has_round) {
  Branch (638:24): [True: 8, False: 0]
  Branch (638:37): [True: 8, False: 0]
  Branch (638:60): [True: 8, False: 0]
639
                // make rounding cases
640
8
                if (c > '4') {
  Branch (640:21): [True: 0, False: 8]
641
0
                    value += 1;
642
0
                }
643
8
                has_round = true;
644
8
                continue;
645
8
            } else if (!found_dot) {
  Branch (645:24): [True: 0, False: 0]
646
0
                ++cur_digit;
647
0
            }
648
1.99k
            DCHECK(value >= 0); // For some reason //DCHECK_GE doesn't work with __int128.
649
1.99k
        } else if (c == '.' && LIKELY(!found_dot)) {
Line
Count
Source
35
107
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 107, False: 0]
  Branch (649:20): [True: 107, False: 11]
650
107
            found_dot = 1;
651
107
        } else if ((c == 'e' || c == 'E') && LIKELY(!found_exponent)) {
Line
Count
Source
35
0
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
  Branch (35:22): [True: 0, False: 0]
  Branch (651:21): [True: 0, False: 11]
  Branch (651:33): [True: 0, False: 11]
652
0
            found_exponent = true;
653
0
            exponent = string_to_int_internal<int8_t>(s + i + 1, len - i - 1, result);
654
0
            if (UNLIKELY(*result != StringParser::PARSE_SUCCESS)) {
Line
Count
Source
36
0
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 0]
655
0
                if (*result == StringParser::PARSE_OVERFLOW && exponent < 0) {
  Branch (655:21): [True: 0, False: 0]
  Branch (655:64): [True: 0, False: 0]
656
0
                    *result = StringParser::PARSE_UNDERFLOW;
657
0
                }
658
0
                return 0;
659
0
            }
660
0
            break;
661
11
        } else {
662
11
            if (value == 0) {
  Branch (662:17): [True: 9, False: 2]
663
9
                *result = StringParser::PARSE_FAILURE;
664
9
                return 0;
665
9
            }
666
            // here to handle
667
2
            *result = StringParser::PARSE_SUCCESS;
668
2
            if (type_scale >= scale) {
  Branch (668:17): [True: 2, False: 0]
669
2
                value *= get_scale_multiplier<T>(type_scale - scale);
670
                // here meet non-valid character, should return the value, keep going to meet
671
                // the E/e character because we make right user-given type_precision
672
                // not max number type_precision
673
2
                if (!is_numeric_ascii(c)) {
  Branch (673:21): [True: 2, False: 0]
674
2
                    if (cur_digit > type_precision) {
  Branch (674:25): [True: 0, False: 2]
675
0
                        *result = StringParser::PARSE_OVERFLOW;
676
0
                        value = is_negative
  Branch (676:33): [True: 0, False: 0]
677
0
                                        ? vectorized::min_decimal_value<DecimalType>(type_precision)
678
0
                                        : vectorized::max_decimal_value<DecimalType>(
679
0
                                                  type_precision);
680
0
                        return value;
681
0
                    }
682
2
                    return is_negative ? T(-value) : T(value);
  Branch (682:28): [True: 0, False: 2]
683
2
                }
684
2
            }
685
686
0
            return is_negative ? T(-value) : T(value);
  Branch (686:20): [True: 0, False: 0]
687
2
        }
688
2.12k
    }
689
690
    // Find the number of truncated digits before adjusting the precision for an exponent.
691
127
    if (exponent > scale) {
  Branch (691:9): [True: 0, False: 127]
692
        // Ex: 0.1e3 (which at this point would have precision == 1 and scale == 1), the
693
        //     scale must be set to 0 and the value set to 100 which means a precision of 3.
694
0
        precision += exponent - scale;
695
696
0
        value *= get_scale_multiplier<T>(exponent - scale);
697
0
        scale = 0;
698
127
    } else {
699
        // Ex: 100e-4, the scale must be set to 4 but no adjustment to the value is needed,
700
        //     the precision must also be set to 4 but that will be done below for the
701
        //     non-exponent case anyways.
702
127
        scale -= exponent;
703
127
    }
704
    // Ex: 0.001, at this point would have precision 1 and scale 3 since leading zeros
705
    //     were ignored during previous parsing.
706
127
    if (scale > precision) {
  Branch (706:9): [True: 3, False: 124]
707
3
        precision = scale;
708
3
    }
709
710
    // Microbenchmarks show that beyond this point, returning on parse failure is slower
711
    // than just letting the function run out.
712
127
    *result = StringParser::PARSE_SUCCESS;
713
127
    if (UNLIKELY(precision - scale > type_precision - type_scale)) {
Line
Count
Source
36
127
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 9, False: 118]
714
9
        *result = StringParser::PARSE_OVERFLOW;
715
9
        if constexpr (TYPE_DECIMALV2 != P) {
  Branch (715:23): [Folded - Ignored]
716
            // decimalv3 overflow will return max min value for type precision
717
9
            value = is_negative ? vectorized::min_decimal_value<DecimalType>(type_precision)
718
9
                                : vectorized::max_decimal_value<DecimalType>(type_precision);
719
9
            return value;
720
9
        }
721
118
    } else if (UNLIKELY(scale > type_scale)) {
Line
Count
Source
36
118
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 17, False: 101]
722
17
        *result = StringParser::PARSE_UNDERFLOW;
723
17
        int shift = scale - type_scale;
724
17
        T divisor = get_scale_multiplier<T>(shift);
725
17
        if (UNLIKELY(divisor == std::numeric_limits<T>::max())) {
Line
Count
Source
36
17
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 17]
726
0
            value = 0;
727
17
        } else {
728
17
            T remainder = value % divisor;
729
17
            value /= divisor;
730
17
            if ((remainder > 0 ? T(remainder) : T(-remainder)) >= (divisor >> 1)) {
  Branch (730:17): [True: 17, False: 0]
  Branch (730:18): [True: 17, False: 0]
731
17
                value += 1;
732
17
            }
733
17
        }
734
17
        DCHECK(value >= 0); // //DCHECK_GE doesn't work with __int128.
735
101
    } else if (UNLIKELY(!found_value && !found_dot)) {
Line
Count
Source
36
101
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
  Branch (36:24): [True: 0, False: 101]
  Branch (36:44): [True: 0, False: 101]
  Branch (36:44): [True: 0, False: 0]
736
0
        *result = StringParser::PARSE_FAILURE;
737
0
    }
738
739
127
    if (type_scale > scale) {
  Branch (739:9): [True: 78, False: 49]
740
78
        value *= get_scale_multiplier<T>(type_scale - scale);
741
78
    }
742
743
127
    return is_negative ? T(-value) : T(value);
  Branch (743:12): [True: 25, False: 102]
744
138
}
745
746
} // end namespace doris