1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2001-2019 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v2.0
6 // which accompanies this distribution, and is available at
7 // http://www.eclipse.org/legal/epl-v20.html
8 // SPDX-License-Identifier: EPL-2.0
9 /****************************************************************************/
10 /// @file FileHelpers.h
11 /// @author Daniel Krajzewicz
12 /// @author Michael Behrisch
13 /// @author Jakob Erdmann
14 /// @date Mon, 17 Dec 2001
15 /// @version $Id$
16 ///
17 // Functions for an easier usage of files
18 /****************************************************************************/
19 #ifndef FileHelpers_h
20 #define FileHelpers_h
21
22
23 // ===========================================================================
24 // included modules
25 // ===========================================================================
26
27 #include <cassert>
28 #include <fstream>
29 #include <string>
30 #include <vector>
31 #include "SUMOTime.h"
32
33
34 // ===========================================================================
35 // class definitions
36 // ===========================================================================
37 /**
38 * @class FileHelpers
39 * @brief Functions for an easier usage of files and paths
40 */
41 class FileHelpers {
42 public:
43 /// @name file access functions
44 //@{
45
46 /** @brief Checks whether the given file is readable
47 *
48 * @param[in] path The path to the file that shall be examined
49 * @return Whether the named file is readable
50 */
51 static bool isReadable(std::string path);
52 //@}
53
54
55
56 /// @name file path evaluating functions
57 //@{
58
59 /** @brief Removes the file information from the given path
60 *
61 * @param[in] path The path to the file to return the folder it is located in
62 * @return The directory of the named file
63 */
64 static std::string getFilePath(const std::string& path);
65
66
67 /** @brief Returns the second path as a relative path to the first file
68 *
69 * Given the position of the configuration file, and the information where a second
70 * file is relative to the configuration file's position, we want to known where
71 * this second file can be found. This method gets the path to the configuration file
72 * (including the configuration file name) and the path to get the relative position
73 * of and returns this relative position.
74 *
75 * @param[in] configPath The path the configuration file (including the config's file name)
76 * @param[in] path The path to the references file (relativ to configuration path)
77 * @return The file's position (relative to curent working directory)
78 */
79 static std::string getConfigurationRelative(const std::string& configPath,
80 const std::string& path);
81
82
83 /** @brief Returns the information whether the given name represents a socket
84 *
85 * A file name is meant to describe a socket address if a colon is found at a position
86 * larger than one.
87 *
88 * @param[in] name The name of a file
89 * @return Whether the name names a socket
90 */
91 static bool isSocket(const std::string& name);
92
93
94 /** @brief Returns the information whether the given path is absolute
95 *
96 * A path is meant to be absolute, if
97 * @arg it is a socket
98 * @arg it starts with a "/" (Linux)
99 * @arg it has a ':' at the second position (Windows)
100 *
101 * @param[in] path The path to examine
102 * @return Whether the path is absolute
103 */
104 static bool isAbsolute(const std::string& path);
105
106
107 /** @brief Returns the path from a configuration so that it is accessable from the current working directory
108 *
109 * If the path is absolute, it is returned. Otherwise, the file's position
110 * is computed regarding the configuration path (see getConfigurationRelative).
111 *
112 * @see isAbsolute
113 * @see getConfigurationRelative
114 * @param[in] filename The path to the file to be examined
115 * @param[in] basePath The path the configuration file (including the config's file name)
116 * @return The file's position
117 */
118 static std::string checkForRelativity(const std::string& filename,
119 const std::string& basePath);
120
121 /// @brief prepend the given prefix to the last path component of the given file path
122 static std::string prependToLastPathComponent(const std::string& prefix, const std::string& path);
123
124 //@}
125
126
127
128 /// @name binary writing functions
129 //@{
130
131 /** @brief Writes an integer binary
132 *
133 * @param[in, out] strm The stream to write into
134 * @param[in] value The integer to write
135 * @return Reference to the stream
136 */
137 static std::ostream& writeInt(std::ostream& strm, int value);
138
139
140 /** @brief Writes a float binary
141 *
142 * This method behaves differently depending on the definition of double at compile time.
143 *
144 * @param[in, out] strm The stream to write into
145 * @param[in] value The float to write
146 * @return Reference to the stream
147 */
148 static std::ostream& writeFloat(std::ostream& strm, double value);
149
150
151 /** @brief Writes a byte binary
152 *
153 * @param[in, out] strm The stream to write into
154 * @param[in] value The byte to write
155 * @return Reference to the stream
156 */
157 static std::ostream& writeByte(std::ostream& strm, unsigned char value);
158
159
160 /** @brief Writes a string binary
161 *
162 * Writes the length of the string, first, using writeInt. Writes then the string's
163 * characters.
164 *
165 * @see writeInt
166 * @param[in, out] strm The stream to write into
167 * @param[in] value The string to write
168 * @return Reference to the stream
169 */
170 static std::ostream& writeString(std::ostream& strm, const std::string& value);
171
172
173 /** @brief Writes a time description binary
174 *
175 * This method behaves differently depending on the definition of SUMOTime at compile time,
176 * which in turn depends on the enabling of subsecond timesteps.
177 *
178 * @param[in, out] strm The stream to write into
179 * @param[in] value The time to write
180 * @return Reference to the stream
181 */
182 static std::ostream& writeTime(std::ostream& strm, SUMOTime value);
183
184
185 /** @brief Writes an edge vector binary
186 *
187 * @param[in, out] os The stream to write into
188 * @param[in] edges The edges to write
189 * @return Reference to the stream
190 */
191 template <typename E>
192 static std::ostream& writeEdgeVector(std::ostream& os, const std::vector<E>& edges);
193
194
195 /** @brief Reads an edge vector binary
196 *
197 * @param[in] is The stream to read from
198 * @param[out] edges The edge vector to write into
199 * @return Reference to the stream
200 */
201 template <typename E>
202 static void readEdgeVector(std::istream& in, std::vector<const E*>& edges, const std::string& rid);
203 //@}
204
205
206 };
207
208
209 template <typename E>
writeEdgeVector(std::ostream & os,const std::vector<E> & edges)210 std::ostream& FileHelpers::writeEdgeVector(std::ostream& os, const std::vector<E>& edges) {
211 FileHelpers::writeInt(os, (int)edges.size());
212 std::vector<int> follow;
213 int maxFollow = 0;
214 E prev = edges.front();
215 for (typename std::vector<E>::const_iterator i = edges.begin() + 1; i != edges.end(); ++i) {
216 int idx = 0;
217 for (; idx < prev->getNumSuccessors(); ++idx) {
218 if (idx > 15) {
219 break;
220 }
221 if (prev->getSuccessors()[idx] == (*i)) {
222 follow.push_back(idx);
223 if (idx > maxFollow) {
224 maxFollow = idx;
225 }
226 break;
227 }
228 }
229 if (idx > 15 || idx == prev->getNumSuccessors()) {
230 follow.clear();
231 break;
232 }
233 prev = *i;
234 }
235 if (follow.empty()) {
236 for (typename std::vector<E>::const_iterator i = edges.begin(); i != edges.end(); ++i) {
237 FileHelpers::writeInt(os, (*i)->getNumericalID());
238 }
239 } else {
240 const int bits = maxFollow > 3 ? 4 : 2;
241 const int numFields = 8 * sizeof(int) / bits;
242 FileHelpers::writeInt(os, -bits);
243 FileHelpers::writeInt(os, edges.front()->getNumericalID());
244 int data = 0;
245 int field = 0;
246 for (std::vector<int>::const_iterator i = follow.begin(); i != follow.end(); ++i) {
247 data |= *i;
248 field++;
249 if (field == numFields) {
250 FileHelpers::writeInt(os, data);
251 data = 0;
252 field = 0;
253 } else {
254 data <<= bits;
255 }
256 }
257 if (field > 0) {
258 FileHelpers::writeInt(os, data << ((numFields - field - 1) * bits));
259 }
260 }
261 return os;
262 }
263
264
265 template <typename E>
readEdgeVector(std::istream & in,std::vector<const E * > & edges,const std::string & rid)266 void FileHelpers::readEdgeVector(std::istream& in, std::vector<const E*>& edges, const std::string& rid) {
267 int size;
268 in.read((char*) &size, sizeof(int));
269 edges.reserve(size);
270 int bitsOrEntry;
271 in.read((char*) &bitsOrEntry, sizeof(int));
272 if (bitsOrEntry < 0) {
273 const int bits = -bitsOrEntry;
274 const int numFields = 8 * sizeof(int) / bits;
275 const int mask = (1 << bits) - 1;
276 int edgeID;
277 in.read((char*) &edgeID, sizeof(int));
278 const E* prev = E::getAllEdges()[edgeID];
279 assert(prev != 0);
280 edges.push_back(prev);
281 size--;
282 int data = 0;
283 int field = numFields;
284 for (; size > 0; size--) {
285 if (field == numFields) {
286 in.read((char*) &data, sizeof(int));
287 field = 0;
288 }
289 int followIndex = (data >> ((numFields - field - 1) * bits)) & mask;
290 if (followIndex >= prev->getNumSuccessors()) {
291 throw ProcessError("Invalid follower index in route '" + rid + "'!");
292 }
293 prev = prev->getSuccessors()[followIndex];
294 edges.push_back(prev);
295 field++;
296 }
297 } else {
298 while (size > 0) {
299 const E* edge = E::getAllEdges()[bitsOrEntry];
300 if (edge == 0) {
301 throw ProcessError("An edge within the route '" + rid + "' is not known!");
302 }
303 edges.push_back(edge);
304 size--;
305 if (size > 0) {
306 in.read((char*) &bitsOrEntry, sizeof(int));
307 }
308 }
309 }
310 }
311 #endif
312
313 /****************************************************************************/
314
315