Coverage Report

Created: 2026-10-14 10:23

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
4.08M
inline std::string to_lower(const std::string& input) {
42
4.08M
    std::string output;
43
4.08M
    output.resize(input.size());
44
4.08M
    std::transform(input.begin(), input.end(), output.begin(),
45
42.7M
                   [](unsigned char c) { return std::tolower(c); });
46
4.08M
    return output;
47
4.08M
}
48
49
37
inline std::string to_upper(const std::string& input) {
50
37
    std::string output;
51
37
    output.resize(input.size());
52
37
    std::transform(input.begin(), input.end(), output.begin(),
53
161
                   [](unsigned char c) { return std::toupper(c); });
54
37
    return output;
55
37
}
56
57
1.94k
inline bool iequal(const std::string& lhs, const std::string& rhs) {
58
1.94k
    if (lhs.size() != rhs.size()) {
59
1.54k
        return false;
60
1.54k
    }
61
399
    return to_lower(lhs) == to_lower(rhs);
62
1.94k
}
63
64
9
inline bool starts_with(const std::string& value, const std::string& beginning) {
65
9
    return value.find(beginning) == 0;
66
9
}
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
7.72k
inline std::string_view trim(std::string_view sv) {
76
7.72k
    size_t start = 0;
77
7.72k
    size_t end = sv.size();
78
79
11.1k
    while (start < end && std::isspace(static_cast<unsigned char>(sv[start]))) {
80
3.44k
        ++start;
81
3.44k
    }
82
83
9.03k
    while (end > start && std::isspace(static_cast<unsigned char>(sv[end - 1]))) {
84
1.30k
        --end;
85
1.30k
    }
86
87
7.72k
    return sv.substr(start, end - start);
88
7.72k
}
89
90
2.04M
inline std::vector<std::string> split(const std::string& s, const std::string& delim) {
91
2.04M
    std::vector<std::string> out;
92
2.04M
    size_t pos {};
93
94
4.26M
    for (size_t find = 0; (find = s.find(delim, pos)) != std::string::npos;
95
2.21M
         pos = find + delim.size()) {
96
2.21M
        out.emplace_back(s.data() + pos, s.data() + find);
97
2.21M
    }
98
99
2.04M
    out.emplace_back(s.data() + pos, s.data() + s.size());
100
2.04M
    return out;
101
2.04M
}
102
103
template <typename T>
104
292
std::string join(const std::vector<T>& elems, const std::string& delim) {
105
292
    std::stringstream ss;
106
509
    for (size_t i = 0; i < elems.size(); ++i) {
107
217
        if (i != 0) {
108
97
            ss << delim.c_str();
109
97
        }
110
217
        ss << elems[i];
111
217
    }
112
292
    return ss.str();
113
292
}
114
115
struct StringCaseHasher {
116
public:
117
2.17k
    std::size_t operator()(const std::string& value) const {
118
2.17k
        std::string lower_value = to_lower(value);
119
2.17k
        return std::hash<std::string>()(lower_value);
120
2.17k
    }
121
};
122
123
struct StringCaseEqual {
124
public:
125
1.52k
    bool operator()(const std::string& lhs, const std::string& rhs) const {
126
1.52k
        if (lhs.size() != rhs.size()) {
127
194
            return false;
128
194
        }
129
1.33k
        return strncasecmp(lhs.c_str(), rhs.c_str(), lhs.size()) == 0;
130
1.52k
    }
131
};
132
133
struct StringCaseLess {
134
public:
135
794
    bool operator()(const std::string& lhs, const std::string& rhs) const {
136
794
        size_t common_size = std::min(lhs.size(), rhs.size());
137
794
        auto cmp = strncasecmp(lhs.c_str(), rhs.c_str(), common_size);
138
794
        if (cmp == 0) {
139
140
            return lhs.size() < rhs.size();
140
140
        }
141
654
        return cmp < 0;
142
794
    }
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