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.org/sumo
3 // Copyright (C) 2001-2022 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("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 std::string::size_type 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::addExtension(const std::string& path, const std::string& extension) {
94  if (path.empty()) {
95  return "";
96  } else if (extension.empty()) {
97  return path;
98  } else if (path == extension) {
99  return "";
100  } else if (path.size() < extension.size()) {
101  return path + extension;
102  } else {
103  // declare two reverse iterator for every string
104  std::string::const_reverse_iterator it_path = path.rbegin();
105  std::string::const_reverse_iterator it_extension = extension.rbegin();
106  // iterate over extension and compare both characters
107  while (it_extension != extension.rend()) {
108  // if both characters are different, then return path + extension
109  if (*it_path != *it_extension) {
110  return path + extension;
111  }
112  it_path++;
113  it_extension++;
114  }
115  // if comparison was successful, then the path has already the extension
116  return path;
117  }
118 }
119 
120 
121 std::string
122 FileHelpers::getConfigurationRelative(const std::string& configPath, const std::string& path) {
123  std::string retPath = getFilePath(configPath);
124  return retPath + path;
125 }
126 
127 
128 bool
129 FileHelpers::isSocket(const std::string& name) {
130  const std::string::size_type colonPos = name.find(":");
131  return (colonPos != std::string::npos) && (colonPos > 1);
132 }
133 
134 
135 bool
136 FileHelpers::isAbsolute(const std::string& path) {
137  if (isSocket(path)) {
138  return true;
139  }
140  // check UNIX - absolute paths
141  if (path.length() > 0 && path[0] == '/') {
142  return true;
143  }
144  // check Windows - absolute paths
145  if (path.length() > 0 && path[0] == '\\') {
146  return true;
147  }
148  if (path.length() > 1 && path[1] == ':') {
149  return true;
150  }
151  if (path == "nul" || path == "NUL") {
152  return true;
153  }
154  return false;
155 }
156 
157 
158 std::string
159 FileHelpers::checkForRelativity(const std::string& filename, const std::string& basePath) {
160  if (filename == "stdout" || filename == "STDOUT" || filename == "-") {
161  return "stdout";
162  }
163  if (filename == "stderr" || filename == "STDERR") {
164  return "stderr";
165  }
166  if (filename == "nul" || filename == "NUL") {
167  return "/dev/null";
168  }
169  if (!isAbsolute(filename)) {
170  return getConfigurationRelative(basePath, filename);
171  }
172  return filename;
173 }
174 
175 
176 std::string
178  char buffer[1024];
179  char* answer = getcwd(buffer, sizeof(buffer));
180  if (answer) {
181  return answer;
182  }
183  return "";
184 }
185 
186 
187 std::vector<std::string>
188 FileHelpers::splitDirs(const std::string& filename) {
189  std::vector<std::string> result;
190  for (const std::string& d : StringTokenizer(filename, "\\/", true).getVector()) {
191  if (d == ".." && !result.empty() && result.back() != "..") {
192  result.pop_back();
193  } else if ((d == "" && result.empty()) || (d != "" && d != ".")) {
194  result.push_back(d);
195  }
196  }
197  return result;
198 }
199 
200 
201 std::string
202 FileHelpers::fixRelative(const std::string& filename, const std::string& basePath, const bool force, std::string curDir) {
203  if (filename == "stdout" || filename == "STDOUT" || filename == "-") {
204  return "stdout";
205  }
206  if (filename == "stderr" || filename == "STDERR") {
207  return "stderr";
208  }
209  if (filename == "nul" || filename == "NUL" || filename == "/dev/null") {
210  return "/dev/null";
211  }
212  if (isSocket(filename) || (isAbsolute(filename) && !force)) {
213  return filename;
214  }
215  std::vector<std::string> filePathSplit = splitDirs(filename);
216  std::vector<std::string> basePathSplit = splitDirs(basePath);
217  if (isAbsolute(filename) || isAbsolute(basePath) || basePathSplit[0] == "..") {
218  // if at least one is absolute we need to make the other absolute too
219  // the same is true if the basePath refers to a parent dir
220  if (curDir == "") {
221  curDir = getCurrentDir();
222  }
223  if (!isAbsolute(filename)) {
224  filePathSplit = splitDirs(curDir + "/" + filename);
225  }
226  if (!isAbsolute(basePath)) {
227  basePathSplit = splitDirs(curDir + "/" + basePath);
228  }
229  if (filePathSplit[0] != basePathSplit[0]) {
230  // don't try to make something relative on different windows disks
231  return joinToString(filePathSplit, "/");
232  }
233  }
234  while (!filePathSplit.empty() && !basePathSplit.empty() && filePathSplit[0] == basePathSplit[0]) {
235  filePathSplit.erase(filePathSplit.begin());
236  basePathSplit.erase(basePathSplit.begin());
237  }
238  for (int i = 0; i < (int)basePathSplit.size() - 1; i++) {
239  filePathSplit.insert(filePathSplit.begin(), "..");
240  }
241  return joinToString(filePathSplit, "/");
242 }
243 
244 
245 std::string
246 FileHelpers::prependToLastPathComponent(const std::string& prefix, const std::string& path) {
247  const std::string::size_type sep_index = path.find_last_of("\\/");
248  if (sep_index == std::string::npos) {
249  return prefix + path;
250  } else {
251  return path.substr(0, sep_index + 1) + prefix + path.substr(sep_index + 1);
252  }
253 }
254 
255 // ---------------------------------------------------------------------------
256 // binary reading/writing functions
257 // ---------------------------------------------------------------------------
258 
259 std::ostream&
260 FileHelpers::writeInt(std::ostream& strm, int value) {
261  strm.write((char*) &value, sizeof(int));
262  return strm;
263 }
264 
265 
266 std::ostream&
267 FileHelpers::writeFloat(std::ostream& strm, double value) {
268  strm.write((char*) &value, sizeof(double));
269  return strm;
270 }
271 
272 
273 std::ostream&
274 FileHelpers::writeByte(std::ostream& strm, unsigned char value) {
275  strm.write((char*) &value, sizeof(char));
276  return strm;
277 }
278 
279 
280 std::ostream&
281 FileHelpers::writeString(std::ostream& strm, const std::string& value) {
282  int size = (int)value.length();
283  const char* cstr = value.c_str();
284  writeInt(strm, size);
285  strm.write((char*) cstr, (std::streamsize)(sizeof(char)*size));
286  return strm;
287 }
288 
289 
290 std::ostream&
291 FileHelpers::writeTime(std::ostream& strm, SUMOTime value) {
292  strm.write((char*) &value, sizeof(SUMOTime));
293  return strm;
294 }
295 
296 
297 /****************************************************************************/
long long int SUMOTime
Definition: GUI.h:35
std::string joinToString(const std::vector< T > &v, const T_BETWEEN &between, std::streamsize accuracy=gPrecision)
Definition: ToString.h:282
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.
Definition: FileHelpers.cpp:93
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 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