Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/utils/common/FileHelpers.cpp
169678 views
1
/****************************************************************************/
2
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3
// Copyright (C) 2001-2025 German Aerospace Center (DLR) and others.
4
// This program and the accompanying materials are made available under the
5
// terms of the Eclipse Public License 2.0 which is available at
6
// https://www.eclipse.org/legal/epl-2.0/
7
// This Source Code may also be made available under the following Secondary
8
// Licenses when the conditions for such availability set forth in the Eclipse
9
// Public License 2.0 are satisfied: GNU General Public License, version 2
10
// or later which is available at
11
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13
/****************************************************************************/
14
/// @file FileHelpers.cpp
15
/// @author Daniel Krajzewicz
16
/// @author Michael Behrisch
17
/// @date Mon, 17 Dec 2001
18
///
19
// Functions for an easier usage of files
20
/****************************************************************************/
21
#include <config.h>
22
23
#include <string>
24
#ifdef WIN32
25
// this is how fox does it in xincs.h
26
#include <io.h>
27
#define access _access
28
#define R_OK 4 /* Test for read permission. */
29
#include <direct.h>
30
#define getcwd _getcwd // stupid MSFT "deprecation" warning
31
#else
32
#include <unistd.h>
33
#endif
34
#include <fstream>
35
#include <sys/stat.h>
36
#include "FileHelpers.h"
37
#include "StringTokenizer.h"
38
#include "StringUtils.h"
39
#include "MsgHandler.h"
40
41
42
// ===========================================================================
43
// method definitions
44
// ===========================================================================
45
46
// ---------------------------------------------------------------------------
47
// file access functions
48
// ---------------------------------------------------------------------------
49
50
bool
51
FileHelpers::isReadable(std::string path) {
52
if (path.length() == 0) {
53
return false;
54
}
55
while (path[path.length() - 1] == '/' || path[path.length() - 1] == '\\') {
56
path.erase(path.end() - 1);
57
}
58
if (path.length() == 0) {
59
return false;
60
}
61
return access(StringUtils::transcodeToLocal(path).c_str(), R_OK) == 0;
62
}
63
64
bool
65
FileHelpers::isDirectory(std::string path) {
66
#ifdef _MSC_VER
67
struct _stat64 fileInfo;
68
if (_stat64(StringUtils::transcodeToLocal(path).c_str(), &fileInfo) != 0) {
69
#else
70
struct stat fileInfo;
71
if (stat(StringUtils::transcodeToLocal(path).c_str(), &fileInfo) != 0) {
72
#endif
73
throw ProcessError(TLF("Cannot get file attributes for file '%'!", path));
74
}
75
return (fileInfo.st_mode & S_IFMT) == S_IFDIR;
76
}
77
78
// ---------------------------------------------------------------------------
79
// file path evaluating functions
80
// ---------------------------------------------------------------------------
81
82
std::string
83
FileHelpers::getFilePath(const std::string& path) {
84
const auto beg = path.find_last_of("\\/");
85
if (beg == std::string::npos) {
86
return "";
87
}
88
return path.substr(0, beg + 1);
89
}
90
91
92
std::string
93
FileHelpers::getFileFromPath(std::string path, const bool removeExtension) {
94
// first remove extension
95
if (removeExtension) {
96
const auto begExtension = path.find_last_of(".");
97
if (begExtension != std::string::npos) {
98
path = path.substr(0, begExtension);
99
}
100
}
101
// now remove path
102
const auto begPath = path.find_last_of("\\/");
103
if (begPath != std::string::npos) {
104
path = path.substr(begPath + 1, path.size());
105
}
106
return path;
107
}
108
109
110
std::string
111
FileHelpers::addExtension(const std::string& path, const std::string& extension) {
112
if (path.empty()) {
113
return "";
114
} else if (extension.empty()) {
115
return path;
116
} else if (path == extension) {
117
return "";
118
} else if (path.size() < extension.size()) {
119
return path + extension;
120
} else {
121
// declare two reverse iterator for every string
122
std::string::const_reverse_iterator it_path = path.rbegin();
123
std::string::const_reverse_iterator it_extension = extension.rbegin();
124
// iterate over extension and compare both characters
125
while (it_extension != extension.rend()) {
126
// if both characters are different, then return path + extension
127
if (*it_path != *it_extension) {
128
return path + extension;
129
}
130
it_path++;
131
it_extension++;
132
}
133
// if comparison was successful, then the path has already the extension
134
return path;
135
}
136
}
137
138
139
std::string
140
FileHelpers::getConfigurationRelative(const std::string& configPath, const std::string& path) {
141
std::string retPath = getFilePath(configPath);
142
return retPath + path;
143
}
144
145
146
bool
147
FileHelpers::isSocket(const std::string& name) {
148
const std::string::size_type colonPos = name.find(":");
149
return (colonPos != std::string::npos) && (colonPos > 1 || name[0] == '[');
150
}
151
152
153
bool
154
FileHelpers::isAbsolute(const std::string& path) {
155
if (isSocket(path)) {
156
return true;
157
}
158
// check UNIX - absolute paths
159
if (path.length() > 0 && path[0] == '/') {
160
return true;
161
}
162
// check Windows - absolute paths
163
if (path.length() > 0 && path[0] == '\\') {
164
return true;
165
}
166
if (path.length() > 1 && path[1] == ':') {
167
return true;
168
}
169
if (path == "nul" || path == "NUL") {
170
return true;
171
}
172
return false;
173
}
174
175
176
std::string
177
FileHelpers::checkForRelativity(const std::string& filename, const std::string& basePath) {
178
if (filename == "stdout" || filename == "STDOUT" || filename == "-") {
179
return "stdout";
180
}
181
if (filename == "stderr" || filename == "STDERR") {
182
return "stderr";
183
}
184
if (filename == "nul" || filename == "NUL") {
185
return "/dev/null";
186
}
187
if (!isAbsolute(filename)) {
188
return getConfigurationRelative(basePath, filename);
189
}
190
return filename;
191
}
192
193
194
std::string
195
FileHelpers::getCurrentDir() {
196
char buffer[1024];
197
char* answer = getcwd(buffer, sizeof(buffer));
198
if (answer) {
199
return answer;
200
}
201
return "";
202
}
203
204
205
std::vector<std::string>
206
FileHelpers::splitDirs(const std::string& filename) {
207
std::vector<std::string> result;
208
for (const std::string& d : StringTokenizer(filename, "\\/", true).getVector()) {
209
if (d == ".." && !result.empty() && result.back() != "..") {
210
result.pop_back();
211
} else if ((d == "" && result.empty()) || (d != "" && d != ".")) {
212
result.push_back(d);
213
}
214
}
215
return result;
216
}
217
218
219
std::string
220
FileHelpers::fixRelative(const std::string& filename, const std::string& basePath, const bool force, std::string curDir) {
221
if (filename == "stdout" || filename == "STDOUT" || filename == "-") {
222
return "stdout";
223
}
224
if (filename == "stderr" || filename == "STDERR") {
225
return "stderr";
226
}
227
if (filename == "nul" || filename == "NUL" || filename == "/dev/null") {
228
return "/dev/null";
229
}
230
if (isSocket(filename) || (isAbsolute(filename) && !force)) {
231
return filename;
232
}
233
std::vector<std::string> filePathSplit = splitDirs(filename);
234
std::vector<std::string> basePathSplit = splitDirs(basePath);
235
if (isAbsolute(filename) || isAbsolute(basePath) || basePathSplit[0] == "..") {
236
// if at least one is absolute we need to make the other absolute too
237
// the same is true if the basePath refers to a parent dir
238
if (curDir == "") {
239
curDir = getCurrentDir();
240
}
241
if (!isAbsolute(filename)) {
242
filePathSplit = splitDirs(curDir + "/" + filename);
243
}
244
if (!isAbsolute(basePath)) {
245
basePathSplit = splitDirs(curDir + "/" + basePath);
246
}
247
if (filePathSplit[0] != basePathSplit[0]) {
248
// don't try to make something relative on different windows disks
249
return joinToString(filePathSplit, "/");
250
}
251
}
252
while (!filePathSplit.empty() && !basePathSplit.empty() && filePathSplit[0] == basePathSplit[0]) {
253
filePathSplit.erase(filePathSplit.begin());
254
basePathSplit.erase(basePathSplit.begin());
255
}
256
for (int i = 0; i < (int)basePathSplit.size() - 1; i++) {
257
filePathSplit.insert(filePathSplit.begin(), "..");
258
}
259
return joinToString(filePathSplit, "/");
260
}
261
262
263
std::string
264
FileHelpers::prependToLastPathComponent(const std::string& prefix, const std::string& path) {
265
const std::string::size_type sep_index = path.find_last_of("\\/");
266
if (sep_index == std::string::npos) {
267
return prefix + path;
268
} else {
269
return path.substr(0, sep_index + 1) + prefix + path.substr(sep_index + 1);
270
}
271
}
272
273
// ---------------------------------------------------------------------------
274
// binary reading/writing functions
275
// ---------------------------------------------------------------------------
276
277
std::ostream&
278
FileHelpers::writeInt(std::ostream& strm, int value) {
279
strm.write((char*) &value, sizeof(int));
280
return strm;
281
}
282
283
284
std::ostream&
285
FileHelpers::writeFloat(std::ostream& strm, double value) {
286
strm.write((char*) &value, sizeof(double));
287
return strm;
288
}
289
290
291
std::ostream&
292
FileHelpers::writeByte(std::ostream& strm, unsigned char value) {
293
strm.write((char*) &value, sizeof(char));
294
return strm;
295
}
296
297
298
std::ostream&
299
FileHelpers::writeString(std::ostream& strm, const std::string& value) {
300
int size = (int)value.length();
301
const char* cstr = value.c_str();
302
writeInt(strm, size);
303
strm.write((char*) cstr, (std::streamsize)(sizeof(char)*size));
304
return strm;
305
}
306
307
308
std::ostream&
309
FileHelpers::writeTime(std::ostream& strm, SUMOTime value) {
310
strm.write((char*) &value, sizeof(SUMOTime));
311
return strm;
312
}
313
314
315
/****************************************************************************/
316
317