• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

PredatorCZ / PreCore / 460

pending completion
460

push

github-actions-ci

PredatorCZ
try fix coverage

3204 of 6095 relevant lines covered (52.57%)

354.19 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

54.84
/src/directory_scanner.cpp
1
/*  source for DirectoryScanner class
2

3
    Copyright 2019-2021 Lukas Cone
4

5
    Licensed under the Apache License, Version 2.0 (the "License");
6
    you may not use this file except in compliance with the License.
7
    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, software
12
    distributed under the License is distributed on an "AS IS" BASIS,
13
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
    See the License for the specific language governing permissions and
15
    limitations under the License.
16
*/
17

18
#include "spike/io/directory_scanner.hpp"
19

20
#if defined(_MSC_VER) || defined(__MINGW64__)
21
#define USEWIN
22
#include "spike/type/tchar.hpp"
23
#include <windows.h>
24
#elif defined(__GNUC__) || defined(__GNUG__)
25
#include <dirent.h>
26
#endif
27

28
#include <cstring>
29

30
bool PathFilter::IsFiltered(std::string_view fileName_) const {
5,202✔
31
  if (!filters.size()) {
5,202✔
32
    return true;
33
  }
34

35
  std::string_view fileName(fileName_);
1,732✔
36

37
  for (auto &f : filters) {
3,410✔
38
    std::string_view kvi(f);
2,656✔
39
    bool clampBegin = kvi.front() == '^';
2,656✔
40
    bool clampEnd = kvi.back() == '$';
2,656✔
41

42
    if (clampBegin) {
2,656✔
43
      kvi.remove_prefix(1);
44
    }
45

46
    if (clampEnd) {
2,656✔
47
      kvi.remove_suffix(1);
48
    }
49

50
    auto wildcharPos = kvi.find_first_of('*');
51
    bool useWildchar = wildcharPos != kvi.npos;
52

53
    if (useWildchar) {
2,656✔
54
      auto part1 = kvi.substr(0, wildcharPos);
×
55
      auto part2 = kvi.substr(wildcharPos + 1);
×
56

57
      // cases ^foo*bar or ^foo*bar$
58
      if (clampBegin) {
×
59
        if (fileName.starts_with(part1)) {
×
60
          if ((clampEnd && fileName.ends_with(part2)) || !clampEnd) {
×
61
            return true;
×
62
          }
63
        }
64
      }
65
      // cases foo*bar$ only
66
      else if (clampEnd) {
×
67
        if (fileName.ends_with(part2) &&
×
68
            fileName.find(part1) != fileName.npos) {
69
          return true;
70
        }
71
      }
72
      // cases foo*bar only
73
      else if (fileName.find(part1) != fileName.npos &&
×
74
               fileName.find(part2) != fileName.npos) {
75
        return true;
76
      }
77
    } else if (clampBegin) {
2,656✔
78
      if (fileName.starts_with(kvi)) {
×
79
        return true;
80
      }
81
    } else if (clampEnd) {
2,656✔
82
      if (fileName.ends_with(kvi)) {
×
83
        return true;
84
      }
85
    } else if (fileName.find(kvi) != f.npos) {
2,656✔
86
      return true;
87
    }
88
  }
89

90
  return false;
91
}
92

93
void DirectoryScanner::Scan(std::string dir) {
399✔
94
  if (!dir.empty()) {
399✔
95
    char lastWord = *std::prev(dir.end());
396✔
96

97
    if (lastWord == '"') {
396✔
98
      dir.pop_back();
99
    }
100

101
    if (lastWord != '\\' && lastWord != '/') {
396✔
102
      dir.push_back('/');
396✔
103
    }
104
  }
105

106
#ifndef USEWIN
107
  dir.push_back('.');
399✔
108

109
  DIR *cDir = opendir(dir.data());
399✔
110

111
  if (!cDir) {
399✔
112
    return;
113
  }
114

115
  dirent *cFile = nullptr;
116

117
  while ((cFile = readdir(cDir)) != nullptr) {
6,795✔
118
    if (!strcmp(cFile->d_name, ".") || !strcmp(cFile->d_name, "..")) {
6,396✔
119
      continue;
798✔
120
    }
121

122
    std::string miniFile(cFile->d_name);
5,598✔
123
    std::string subFile = dir;
124
    subFile.pop_back();
125
    subFile += miniFile;
126

127
    if (cFile->d_type == DT_DIR) {
5,598✔
128
      numFolders++;
396✔
129
      Scan(subFile);
792✔
130
    } else {
131
      numFiles++;
5,202✔
132
      if (IsFiltered(miniFile)) {
5,202✔
133
        files.push_back(subFile);
4,448✔
134
      }
135
    }
136

137
    if (scanCb) {
5,598✔
138
      scanCb(scanCbData, numFolders, numFiles, files.size());
×
139
    }
140
  }
141

142
  closedir(cDir);
399✔
143
#else
144
  dir.push_back('*');
145
  const auto wdir = ToTSTRING(dir);
146

147
  WIN32_FIND_DATA foundData = {};
148
  HANDLE fleHandle = FindFirstFile(wdir.data(), &foundData);
149

150
  if (fleHandle == INVALID_HANDLE_VALUE) {
151
    return;
152
  }
153

154
  while (FindNextFile(fleHandle, &foundData)) {
155
    if (!_tcscmp(foundData.cFileName, _T(".")) ||
156
        !_tcscmp(foundData.cFileName, _T("..")) ||
157
        (foundData.dwFileAttributes & FILE_ATTRIBUTE_DEVICE) != 0) {
158
      continue;
159
    }
160

161
    std::string subFile = dir;
162
    subFile.pop_back();
163
    std::string cFileName = std::to_string(foundData.cFileName);
164
    subFile += cFileName;
165

166
    if ((foundData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) {
167
      numFolders++;
168
      Scan(subFile);
169
    } else {
170
      numFiles++;
171
      if (IsFiltered(cFileName)) {
172
        files.push_back(subFile);
173
      }
174
    }
175

176
    if (scanCb) {
177
      scanCb(scanCbData, numFolders, numFiles, files.size());
178
    }
179
  }
180

181
  FindClose(fleHandle);
182
#endif
183
}
184

185
void DirectoryScanner::ScanFolders(std::string dir) {
×
186
  if (!dir.empty()) {
×
187
    char lastWord = *std::prev(dir.end());
×
188

189
    if (lastWord == '"') {
×
190
      dir.pop_back();
191
    }
192

193
    if (lastWord != '\\' && lastWord != '/') {
×
194
      dir.push_back('/');
×
195
    }
196
  }
197

198
#ifndef USEWIN
199
  dir.push_back('.');
×
200

201
  DIR *cDir = opendir(dir.data());
×
202

203
  if (!cDir) {
×
204
    return;
205
  }
206

207
  dirent *cFile = nullptr;
208

209
  while ((cFile = readdir(cDir)) != nullptr) {
×
210
    if (!strcmp(cFile->d_name, ".") || !strcmp(cFile->d_name, "..")) {
×
211
      continue;
×
212
    }
213

214
    std::string miniFile(cFile->d_name);
×
215
    std::string subFile = dir;
216
    subFile.pop_back();
217
    subFile += miniFile;
218

219
    if (cFile->d_type == DT_DIR) {
×
220
      files.push_back(subFile);
×
221
    }
222
  }
223

224
  closedir(cDir);
×
225
#else
226
  dir.push_back('*');
227
  const auto wdir = ToTSTRING(dir);
228

229
  WIN32_FIND_DATA foundData = {};
230
  HANDLE fleHandle = FindFirstFile(wdir.data(), &foundData);
231

232
  if (fleHandle == INVALID_HANDLE_VALUE) {
233
    return;
234
  }
235

236
  while (FindNextFile(fleHandle, &foundData)) {
237
    if (!_tcscmp(foundData.cFileName, _T(".")) ||
238
        !_tcscmp(foundData.cFileName, _T("..")) ||
239
        (foundData.dwFileAttributes & FILE_ATTRIBUTE_DEVICE) != 0) {
240
      continue;
241
    }
242

243
    std::string subFile = dir;
244
    subFile.pop_back();
245
    std::string cFileName = std::to_string(foundData.cFileName);
246
    subFile += cFileName;
247

248
    if ((foundData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) {
249
      files.push_back(subFile);
250
    }
251
  }
252

253
  FindClose(fleHandle);
254
#endif
255
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc