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
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("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 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
92std::string
93FileHelpers::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
121std::string
122FileHelpers::getConfigurationRelative(const std::string& configPath, const std::string& path) {
123 std::string retPath = getFilePath(configPath);
124 return retPath + path;
125}
126
127
128bool
129FileHelpers::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
135bool
136FileHelpers::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
158std::string
159FileHelpers::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
176std::string
178 char buffer[1024];
179 char* answer = getcwd(buffer, sizeof(buffer));
180 if (answer) {
181 return answer;
182 }
183 return "";
184}
185
186
187std::vector<std::string>
188FileHelpers::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
201std::string
202FileHelpers::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
245std::string
246FileHelpers::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
259std::ostream&
260FileHelpers::writeInt(std::ostream& strm, int value) {
261 strm.write((char*) &value, sizeof(int));
262 return strm;
263}
264
265
266std::ostream&
267FileHelpers::writeFloat(std::ostream& strm, double value) {
268 strm.write((char*) &value, sizeof(double));
269 return strm;
270}
271
272
273std::ostream&
274FileHelpers::writeByte(std::ostream& strm, unsigned char value) {
275 strm.write((char*) &value, sizeof(char));
276 return strm;
277}
278
279
280std::ostream&
281FileHelpers::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
290std::ostream&
291FileHelpers::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:36
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