Coverage Report

Created: 2026-10-15 05:03

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
be/src/util/string_util.h
Line
Count
Source
1
// Licensed to the Apache Software Foundation (ASF) under one
2
// or more contributor license agreements.  See the NOTICE file
3
// distributed with this work for additional information
4
// regarding copyright ownership.  The ASF licenses this file
5
// to you under the Apache License, Version 2.0 (the
6
// "License"); you may not use this file except in compliance
7
// with the License.  You may obtain a copy of the License at
8
//
9
//   http://www.apache.org/licenses/LICENSE-2.0
10
//
11
// Unless required by applicable law or agreed to in writing,
12
// software distributed under the License is distributed on an
13
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
// KIND, either express or implied.  See the License for the
15
// specific language governing permissions and limitations
16
// under the License.
17
18
#pragma once
19
20
#include <strings.h>
21
22
#include <algorithm>
23
#include <boost/token_functions.hpp>
24
#include <boost/tokenizer.hpp>
25
#include <cctype>
26
#include <cstddef>
27
#include <cstdint>
28
#include <map>
29
#include <set>
30
#include <sstream>
31
#include <string>
32
#include <unordered_map>
33
#include <unordered_set>
34
#include <vector>
35
36
#include "common/exception.h"
37
#include "common/status.h"
38
39
namespace doris {
40
41
61.6M
inline std::string to_lower(const std::string& input) {
42
61.6M
    std::string output;
43
61.6M
    output.resize(input.size());
44
61.6M
    std::transform(input.begin(), input.end(), output.begin(),
45
491M
                   [](unsigned char c) { return std::tolower(c); });
46
61.6M
    return output;
47
61.6M
}
48
49
14.6k
inline std::string to_upper(const std::string& input) {
50
14.6k
    std::string output;
51
14.6k
    output.resize(input.size());
52
14.6k
    std::transform(input.begin(), input.end(), output.begin(),
53
180k
                   [](unsigned char c) { return std::toupper(c); });
54
14.6k
    return output;
55
14.6k
}
56
57
184k
inline bool iequal(const std::string& lhs, const std::string& rhs) {
58
184k
    if (lhs.size() != rhs.size()) {
59
155k
        return false;
60
155k
    }
61
29.5k
    return to_lower(lhs) == to_lower(rhs);
62
184k
}
63
64
159
inline bool starts_with(const std::string& value, const std::string& beginning) {
65
159
    return value.find(beginning) == 0;
66
159
}
67
68
187
inline bool ends_with(std::string const& value, std::string const& ending) {
69
187
    if (ending.size() > value.size()) {
70
1
        return false;
71
1
    }
72
186
    return std::equal(ending.rbegin(), ending.rend(), value.rbegin());
73
187
}
74
75
54.8k
inline std::string_view trim(std::string_view sv) {
76
54.8k
    size_t start = 0;
77
54.8k
    size_t end = sv.size();
78
79
59.0k
    while (start < end && std::isspace(static_cast<unsigned char>(sv[start]))) {
80
4.19k
        ++start;
81
4.19k
    }
82
83
56.5k
    while (end > start && std::isspace(static_cast<unsigned char>(sv[end - 1]))) {
84
1.64k
        --end;
85
1.64k
    }
86
87
54.8k
    return sv.substr(start, end - start);
88
54.8k
}
89
90
4.90M
inline std::vector<std::string> split(const std::string& s, const std::string& delim) {
91
4.90M
    std::vector<std::string> out;
92
4.90M
    size_t pos {};
93
94
10.2M
    for (size_t find = 0; (find = s.find(delim, pos)) != std::string::npos;
95
5.32M
         pos = find + delim.size()) {
96
5.32M
        out.emplace_back(s.data() + pos, s.data() + find);
97
5.32M
    }
98
99
4.90M
    out.emplace_back(s.data() + pos, s.data() + s.size());
100
4.90M
    return out;
101
4.90M
}
102
103
template <typename T>
104
296
std::string join(const std::vector<T>& elems, const std::string& delim) {
105
296
    std::stringstream ss;
106
517
    for (size_t i = 0; i < elems.size(); ++i) {
107
221
        if (i != 0) {
108
97
            ss << delim.c_str();
109
97
        }
110
221
        ss << elems[i];
111
221
    }
112
296
    return ss.str();
113
296
}
114
115
struct StringCaseHasher {
116
public:
117
250k
    std::size_t operator()(const std::string& value) const {
118
250k
        std::string lower_value = to_lower(value);
119
250k
        return std::hash<std::string>()(lower_value);
120
250k
    }
121
};
122
123
struct StringCaseEqual {
124
public:
125
158k
    bool operator()(const std::string& lhs, const std::string& rhs) const {
126
158k
        if (lhs.size() != rhs.size()) {
127
23.1k
            return false;
128
23.1k
        }
129
134k
        return strncasecmp(lhs.c_str(), rhs.c_str(), lhs.size()) == 0;
130
158k
    }
131
};
132
133
struct StringCaseLess {
134
public:
135
139k
    bool operator()(const std::string& lhs, const std::string& rhs) const {
136
139k
        size_t common_size = std::min(lhs.size(), rhs.size());
137
139k
        auto cmp = strncasecmp(lhs.c_str(), rhs.c_str(), common_size);
138
139k
        if (cmp == 0) {
139
27.5k
            return lhs.size() < rhs.size();
140
27.5k
        }
141
111k
        return cmp < 0;
142
139k
    }
143
};
144
145
size_t hash_of_path(const std::string& identifier, const std::string& path);
146
Result<int> safe_stoi(const std::string& input, const std::string& name);
147
Result<int64_t> safe_stoll(const std::string& input, const std::string& name);
148
using StringCaseSet = std::set<std::string, StringCaseLess>;
149
using StringCaseUnorderedSet = std::unordered_set<std::string, StringCaseHasher, StringCaseEqual>;
150
template <class T>
151
using StringCaseMap = std::map<std::string, T, StringCaseLess>;
152
template <class T>
153
using StringCaseUnorderedMap =
154
        std::unordered_map<std::string, T, StringCaseHasher, StringCaseEqual>;
155
156
template <typename T>
157
auto get_json_token(T& path_string) {
158
    try {
159
        return boost::tokenizer<boost::escaped_list_separator<char>>(
160
                path_string, boost::escaped_list_separator<char>("\\", ".", "\""));
161
    } catch (const boost::escaped_list_error& err) {
162
        throw doris::Exception(ErrorCode::INVALID_JSON_PATH, "meet error {}", err.what());
163
    }
164
}
165
166
#ifdef USE_LIBCPP
167
template <>
168
auto get_json_token(std::string_view& path_string) = delete;
169
#endif
170
171
} // namespace doris