Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
FileHelpers.cpp
Go to the documentation of this file.
1/****************************************************************************/
2// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3// Copyright (C) 2001-2024 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/****************************************************************************/
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
50bool
51FileHelpers::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
64bool
65FileHelpers::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
82std::string
83FileHelpers::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
92std::string
93FileHelpers::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
110std::string
111FileHelpers::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
139std::string
140FileHelpers::getConfigurationRelative(const std::string& configPath, const std::string& path) {
141 std::string retPath = getFilePath(configPath);
142 return retPath + path;
143}
144
145
146bool
147FileHelpers::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
153bool
154FileHelpers::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
176std::string
177FileHelpers::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
194std::string
196 char buffer[1024];
197 char* answer = getcwd(buffer, sizeof(buffer));
198 if (answer) {
199 return answer;
200 }
201 return "";
202}
203
204
205std::vector<std::string>
206FileHelpers::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
219std::string
220FileHelpers::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
263std::string
264FileHelpers::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
277std::ostream&
278FileHelpers::writeInt(std::ostream& strm, int value) {
279 strm.write((char*) &value, sizeof(int));
280 return strm;
281}
282
283
284std::ostream&
285FileHelpers::writeFloat(std::ostream& strm, double value) {
286 strm.write((char*) &value, sizeof(double));
287 return strm;
288}
289
290
291std::ostream&
292FileHelpers::writeByte(std::ostream& strm, unsigned char value) {
293 strm.write((char*) &value, sizeof(char));
294 return strm;
295}
296
297
298std::ostream&
299FileHelpers::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
308std::ostream&
309FileHelpers::writeTime(std::ostream& strm, SUMOTime value) {
310 strm.write((char*) &value, sizeof(SUMOTime));
311 return strm;
312}
313
314
315/****************************************************************************/
long long int SUMOTime
Definition GUI.h:36
#define TLF(string,...)
Definition MsgHandler.h:317
std::string joinToString(const std::vector< T > &v, const T_BETWEEN &between, std::streamsize accuracy=gPrecision)
Definition ToString.h:283
static std::string fixRelative(const std::string &filename, const std::string &basePath, const bool force, std::string curDir="")
Fixes the relative path for the given filename in relation to the basePath (usually a config file).
static bool isAbsolute(const std::string &path)
Returns the information whether the given path is absolute.
static std::ostream & writeFloat(std::ostream &strm, double value)
Writes a float binary.
static std::string getConfigurationRelative(const std::string &configPath, const std::string &path)
Returns the second path as a relative path to the first file.
static std::string checkForRelativity(const std::string &filename, const std::string &basePath)
Returns the path from a configuration so that it is accessable from the current working directory.
static std::string addExtension(const std::string &path, const std::string &extension)
Add an extension to the given file path.
static std::ostream & writeString(std::ostream &strm, const std::string &value)
Writes a string binary.
static bool isReadable(std::string path)
Checks whether the given file is readable.
static std::vector< std::string > splitDirs(const std::string &filename)
Splits the given file path into directory components.
static std::string getFilePath(const std::string &path)
Removes the file information from the given path.
static std::ostream & writeTime(std::ostream &strm, SUMOTime value)
Writes a time description binary.
static std::ostream & writeInt(std::ostream &strm, int value)
Writes an integer binary.
static bool isSocket(const std::string &name)
Returns the information whether the given name represents a socket.
static std::string getFileFromPath(std::string path, const bool removeExtension)
Removes the path information from the given path.
static bool isDirectory(std::string path)
Checks whether the given file is a directory.
static std::string getCurrentDir()
Get the current working directory.
static std::ostream & writeByte(std::ostream &strm, unsigned char value)
Writes a byte binary.
static std::string prependToLastPathComponent(const std::string &prefix, const std::string &path)
prepend the given prefix to the last path component of the given file path
std::vector< std::string > getVector()
return vector of strings
static std::string transcodeToLocal(const std::string &utf8String)
convert a string from UTF-8 to the local codepage