Eclipse SUMO - Simulation of Urban MObility
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 
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);
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
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 /****************************************************************************/
long long int SUMOTime
Definition: GUI.h:35
#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.
Definition: FileHelpers.cpp:51
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.
Definition: FileHelpers.cpp:83
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.
Definition: FileHelpers.cpp:93
static bool isDirectory(std::string path)
Checks whether the given file is a directory.
Definition: FileHelpers.cpp:65
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
static std::string transcodeToLocal(const std::string &utf8String)
convert a string from UTF-8 to the local codepage