Coverage Report

Created: 2025-01-24 06:31

/src/cppcheck/oss-fuzz/build/utils.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Cppcheck - A tool for static C/C++ code analysis
3
 * Copyright (C) 2007-2024 Cppcheck team.
4
 *
5
 * This program is free software: you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License as published by
7
 * the Free Software Foundation, either version 3 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
 */
18
19
#include "utils.h"
20
21
#include <algorithm>
22
#include <cctype>
23
#include <cstring>
24
#include <iterator>
25
#include <stack>
26
#include <utility>
27
28
29
int caseInsensitiveStringCompare(const std::string &lhs, const std::string &rhs)
30
0
{
31
0
    if (lhs.size() != rhs.size())
32
0
        return (lhs.size() < rhs.size()) ? -1 : 1;
33
0
    for (unsigned int i = 0; i < lhs.size(); ++i) {
34
0
        const int c1 = std::toupper(lhs[i]);
35
0
        const int c2 = std::toupper(rhs[i]);
36
0
        if (c1 != c2)
37
0
            return (c1 < c2) ? -1 : 1;
38
0
    }
39
0
    return 0;
40
0
}
41
42
bool isValidGlobPattern(const std::string& pattern)
43
0
{
44
0
    for (auto i = pattern.cbegin(); i != pattern.cend(); ++i) {
45
0
        if (*i == '*' || *i == '?') {
46
0
            const auto j = i + 1;
47
0
            if (j != pattern.cend() && (*j == '*' || *j == '?')) {
48
0
                return false;
49
0
            }
50
0
        }
51
0
    }
52
0
    return true;
53
0
}
54
55
bool matchglob(const std::string& pattern, const std::string& name)
56
0
{
57
0
    const char* p = pattern.c_str();
58
0
    const char* n = name.c_str();
59
0
    std::stack<std::pair<const char*, const char*>, std::vector<std::pair<const char*, const char*>>> backtrack;
60
61
0
    for (;;) {
62
0
        bool matching = true;
63
0
        while (*p != '\0' && matching) {
64
0
            switch (*p) {
65
0
            case '*':
66
                // Step forward until we match the next character after *
67
0
                while (*n != '\0' && *n != p[1]) {
68
0
                    n++;
69
0
                }
70
0
                if (*n != '\0') {
71
                    // If this isn't the last possibility, save it for later
72
0
                    backtrack.emplace(p, n);
73
0
                }
74
0
                break;
75
0
            case '?':
76
                // Any character matches unless we're at the end of the name
77
0
                if (*n != '\0') {
78
0
                    n++;
79
0
                } else {
80
0
                    matching = false;
81
0
                }
82
0
                break;
83
0
            default:
84
                // Non-wildcard characters match literally
85
0
                if (*n == *p) {
86
0
                    n++;
87
0
                } else if (*n == '\\' && *p == '/') {
88
0
                    n++;
89
0
                } else if (*n == '/' && *p == '\\') {
90
0
                    n++;
91
0
                } else {
92
0
                    matching = false;
93
0
                }
94
0
                break;
95
0
            }
96
0
            p++;
97
0
        }
98
99
        // If we haven't failed matching and we've reached the end of the name, then success
100
0
        if (matching && *n == '\0') {
101
0
            return true;
102
0
        }
103
104
        // If there are no other paths to try, then fail
105
0
        if (backtrack.empty()) {
106
0
            return false;
107
0
        }
108
109
        // Restore pointers from backtrack stack
110
0
        p = backtrack.top().first;
111
0
        n = backtrack.top().second;
112
0
        backtrack.pop();
113
114
        // Advance name pointer by one because the current position didn't work
115
0
        n++;
116
0
    }
117
0
}
118
119
0
bool matchglobs(const std::vector<std::string> &patterns, const std::string &name) {
120
0
    return std::any_of(begin(patterns), end(patterns), [&name](const std::string &pattern) {
121
0
        return matchglob(pattern, name);
122
0
    });
123
0
}
124
125
void strTolower(std::string& str)
126
60.8k
{
127
    // This wrapper exists because Sun's CC does not allow a static_cast
128
    // from extern "C" int(*)(int) to int(*)(int).
129
243k
    std::transform(str.cbegin(), str.cend(), str.begin(), [](int c) {
130
243k
        return std::tolower(c);
131
243k
    });
132
60.8k
}
133
134
std::string trim(const std::string& s, const std::string& t)
135
0
{
136
0
    const std::string::size_type beg = s.find_first_not_of(t);
137
0
    if (beg == std::string::npos)
138
0
        return "";
139
0
    const std::string::size_type end = s.find_last_not_of(t);
140
0
    return s.substr(beg, end - beg + 1);
141
0
}
142
143
void findAndReplace(std::string &source, const std::string &searchFor, const std::string &replaceWith)
144
0
{
145
0
    std::string::size_type index = 0;
146
0
    while ((index = source.find(searchFor, index)) != std::string::npos) {
147
0
        source.replace(index, searchFor.length(), replaceWith);
148
0
        index += replaceWith.length();
149
0
    }
150
0
}
151
152
0
std::string replaceEscapeSequences(const std::string &source) {
153
0
    std::string result;
154
0
    result.reserve(source.size());
155
0
    for (std::size_t i = 0; i < source.size(); ++i) {
156
0
        if (source[i] != '\\' || i + 1 >= source.size())
157
0
            result += source[i];
158
0
        else {
159
0
            ++i;
160
0
            if (source[i] == 'n') {
161
0
                result += '\n';
162
0
            } else if (source[i] == 'r') {
163
0
                result += '\r';
164
0
            } else if (source[i] == 't') {
165
0
                result += '\t';
166
0
            } else if (source[i] == 'x') {
167
0
                std::string value = "0";
168
0
                if (i + 1 < source.size() && std::isxdigit(source[i+1]))
169
0
                    value += source[i++ + 1];
170
0
                if (i + 1 < source.size() && std::isxdigit(source[i+1]))
171
0
                    value += source[i++ + 1];
172
0
                result += static_cast<char>(std::stoi(value, nullptr, 16));
173
0
            } else if (source[i] == '0') {
174
0
                std::string value = "0";
175
0
                if (i + 1 < source.size() && source[i+1] >= '0' && source[i+1] <= '7')
176
0
                    value += source[i++ + 1];
177
0
                if (i + 1 < source.size() && source[i+1] >= '0' && source[i+1] <= '7')
178
0
                    value += source[i++ + 1];
179
0
                result += static_cast<char>(std::stoi(value, nullptr, 8));
180
0
            } else {
181
0
                result += source[i];
182
0
            }
183
0
        }
184
0
    }
185
0
    return result;
186
0
}
187
188
189
std::vector<std::string> splitString(const std::string& str, char sep)
190
0
{
191
0
    std::vector<std::string> l;
192
193
0
    std::string::size_type pos1 = 0;
194
0
    std::string::size_type pos2;
195
0
    while (true) {
196
0
        pos2 = str.find(sep, pos1);
197
0
        l.push_back(str.substr(pos1, pos2 - pos1));
198
0
        if (pos2 == std::string::npos)
199
0
            break;
200
0
        pos1 = pos2 + 1;
201
0
    }
202
0
    return l;
203
0
}