GCC Code Coverage Report


Directory: ./
File: lib/geogram/basic/file_system.h
Date: 2026-09-07 02:25:23
Exec Total Coverage
Lines: 0 2 0.0%
Functions: 0 1 0.0%
Branches: 0 2 0.0%

Line Branch Exec Source
1 /*
2 * Copyright (c) 2000-2022 Inria
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * * Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * * Neither the name of the ALICE Project-Team nor the names of its
14 * contributors may be used to endorse or promote products derived from this
15 * software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
28 *
29 * Contact: Bruno Levy
30 *
31 * https://www.inria.fr/fr/bruno-levy
32 *
33 * Inria,
34 * Domaine de Voluceau,
35 * 78150 Le Chesnay - Rocquencourt
36 * FRANCE
37 *
38 */
39
40 #ifndef GEOGRAM_BASIC_FILE_SYSTEM
41 #define GEOGRAM_BASIC_FILE_SYSTEM
42
43 #include <geogram/basic/common.h>
44 #include <geogram/basic/numeric.h>
45 #include <geogram/basic/counted.h>
46 #include <geogram/basic/smart_pointer.h>
47
48 #include <string>
49 #include <vector>
50 #include <map>
51
52 /**
53 * \file geogram/basic/file_system.h
54 * \brief Functions and times for filesystem manipulation
55 */
56
57 namespace GEO {
58
59 /**
60 * \brief Abstraction layer for file-system management.
61 */
62 namespace FileSystem {
63
64 /**
65 * \brief A Node in a FileSystem.
66 * \details This class abstracts a FileSystem and
67 * operations on it.
68 */
69 class GEOGRAM_API Node : public Counted {
70 public:
71 /**
72 * \brief Node constructor.
73 */
74 Node();
75
76 /**
77 * \brief Node destructor.
78 */
79 ~Node() override;
80
81 /************************** OS-dependent **************************/
82
83 /**
84 * \brief Checks if a path is a regular file.
85 * \param[in] path system path to verify.
86 * \retval true if \p path is a regular file.
87 * \retval false otherwise.
88 */
89 virtual bool is_file(const std::string& path);
90
91 /**
92 * \brief Checks if a path is a directory.
93 * \param[in] path system path to verify.
94 * \retval true if \p path is a directory.
95 * \retval false otherwise.
96 */
97 virtual bool is_directory(const std::string& path);
98
99 /**
100 * \brief Creates a directory
101 * \details This recursively creates a new directory given by its \b
102 * absolute path \p path, creating any missing intermediate
103 * directories on the fly.
104 * \param[in] path absolute path to the directory to be created.
105 * \retval true if the directory was successfully created.
106 * \retval false otherwise.
107 */
108 virtual bool create_directory(const std::string& path);
109
110 /**
111 * \brief Deletes a directory
112 * \details This deletes the directory specified by path \p path.
113 * The path must specify an empty directory.
114 * \param[in] path the path of the directory to be removed.
115 * \retval true if the directory was successfully deleted.
116 * \retval false otherwise.
117 */
118 virtual bool delete_directory(const std::string& path);
119
120 /**
121 * \brief Deletes a file
122 * \param[in] path the path of the file to be deleted.
123 * \retval true if the file path was successfully deleted
124 * \retval false otherwise
125 */
126 virtual bool delete_file(const std::string& path);
127
128 /**
129 * \brief Lists directory contents
130 * \details Lists all the files and sub-directories in the directory
131 * specified by \p path, and stores the list in \p result. Special
132 * entries "." and ".." are not stored in \p result.
133 * \param[in] path the path to the directory to list.
134 * \param[in] result output vector of files and sub-directories.
135 * \retval true if \p path specifies a readable directory.
136 * \retval false otherwise.
137 */
138 virtual bool get_directory_entries(
139 const std::string& path, std::vector<std::string>& result
140 );
141
142 /**
143 * \brief Gets the current working directory.
144 * \return The absolute path to the current directory.
145 */
146 virtual std::string get_current_working_directory();
147
148 /**
149 * \brief Sets the working directory.
150 * \param[in] path path to the new working directory.
151 * \retval true if the current directory could be
152 * changed to \p path.
153 * \retval false otherwise.
154 */
155 virtual bool set_current_working_directory(
156 const std::string& path
157 );
158
159 /**
160 * \brief Renames or moves a file.
161 * \details This renames the existing file or directory specified by
162 * path \p old_name to the new path \p new_name. The new name
163 * must not be the name of an existing file or directory.
164 * If \p old_name and \p new_name are not in the same directory,
165 * \p old_name is moved to the \p new_name.
166 * \param[in] old_name path of the file or directory to be renamed.
167 * \param[in] new_name new path of the file or directory.
168 * \retval true if the file was renamed successfully.
169 * \retval false otherwise.
170 */
171 virtual bool rename_file(
172 const std::string& old_name, const std::string& new_name
173 );
174
175 /**
176 * \brief Gets a file last modification time.
177 * \param[in] path the path to an existing file or directory.
178 * \return the last modification time in seconds
179 */
180 virtual Numeric::uint64 get_time_stamp(const std::string& path);
181
182 /**
183 * \brief Marks a filename as executable.
184 * \details On unix, it chmods the file, on Windows, does nothing.
185 * \param[in] filename name of the file to be made executable
186 * \retval true on success.
187 * \retval false otherwise.
188 */
189 virtual bool set_executable_flag(const std::string& filename);
190
191
192 /**
193 * \brief Modifies the last modification time of a file.
194 * \param[in] filename name of the file.
195 * \retval true on success.
196 * \retval false otherwise.
197 */
198 virtual bool touch(const std::string& filename);
199
200 /**
201 * \brief Normalizes a path.
202 * \details A path is normalized if it is absolute and it does not
203 * contain any "../" component.
204 * \param[in] path the path to be normalized. The path can have
205 * components that do not exist.
206 * \return the normalized path
207 */
208 virtual std::string normalized_path(const std::string& path);
209
210
211 /**
212 * \brief Gets the current user's home directory.
213 * \return The path to the current user's home directory
214 * as a string.
215 */
216 virtual std::string home_directory();
217
218 /**
219 * \brief Gets the current user's home directory.
220 * \details Under unix, it returns the content of the HOME
221 * environment
222 * variable. Under Windows, it returns the "My Documents"
223 * directory.
224 * \return The path to the current user's home directory
225 * as a string.
226 */
227 virtual std::string documents_directory();
228
229
230 /**
231 * \brief Load file contents in a string.
232 * \param[in] path the path to the file
233 * \return a string with the contents of the file.
234 */
235 virtual std::string load_file_as_string(const std::string& path);
236
237 /************************ OS-independent **************************/
238
239 /**
240 * \brief Gets a path extension
241 * \details Extracts the extension from the path \p path,
242 * that is any character that appear after the last dot (.)
243 * and after any
244 * directory separator character. If \p path has no extension, the
245 * empty string is returned.
246 *
247 * Examples
248 * - extension("/dir/file.cpp") -> "cpp"
249 * - extension("file") -> ""
250 * - extension("/dir.ext/file") -> ""
251 *
252 * \param[in] path the path to a file or directory
253 * \return the path's extension (without the dot), or the empty
254 * string if none.
255 */
256 virtual std::string extension(const std::string& path);
257
258 /**
259 * \brief Gets a path base name
260 * \details Extracts the base name from the path \p path,
261 * that is any
262 * character that appear after the last directory separator. If
263 * parameter \p remove_extension is \c true (the default), the
264 * extension is removed from the base name, otherwise is it kept. If
265 * the path does not contain any directory separator, the whole path
266 * is returned.
267 *
268 * Examples
269 * - base_name("/dir/file.cpp") -> "file"
270 * - base_name("/dir/file.cpp", false) -> "file.cpp"
271 * - base_name("file") -> "file"
272 *
273 * \param[in] path the path to a file or directory
274 * \param[in] remove_extension whether to remove the extension from
275 * the base name or not.
276 */
277 virtual std::string base_name(
278 const std::string& path, bool remove_extension = true
279 );
280
281 /**
282 * \brief Gets a path directory
283 * \details Extracts the directory from the path \p path,
284 * that is any character that appear before the last directory
285 * separator. If the path does not contain any directory
286 * separator, string "." is returned.
287 *
288 * Examples
289 * - dir_name("/dir/file.cpp") -> "dir"
290 * - dir_name("file") -> "."
291 * - dir_name("/") -> "/"
292 *
293 * \param[in] path the path to a file or directory
294 * \return the path directory or "." if none
295 */
296 virtual std::string dir_name(const std::string& path);
297
298 /**
299 * \brief Lists directory contents
300 * \details Lists all the files and sub-directories in the directory
301 * specified by \p path, and stores the list in \p result. Special
302 * entries "." and ".." are not stored in \p result. If parameter
303 * recursive is set to \c true, \p result will include the entries
304 * of all sub-directories in \p path recursively.
305 * \param[in] path the path to an existing directory
306 * \param[in] result output vector of entries in \p path
307 * \param[in] recursive recursively traverses all sub-directories in
308 * \p path
309 */
310 virtual void get_directory_entries_recursive(
311 const std::string& path,
312 std::vector<std::string>& result, bool recursive = true
313 );
314
315 /**
316 * \brief Lists files in a directory
317 * \details Lists all the files in the directory specified by
318 * \p path, and stores the list in \p result. Special entries "."
319 * and ".." are not stored in \p result. If parameter recursive
320 * is set to \c true, \p result will include the entries of all
321 * sub-directories in \p path recursively.
322 * \param[in] path the path to an existing directory
323 * \param[in] result output vector of files in \p path
324 * \param[in] recursive recursively traverses all sub-directories in
325 * \p path
326 * \see get_directory_entries()
327 */
328 virtual void get_files(
329 const std::string& path,
330 std::vector<std::string>& result, bool recursive = false
331 );
332
333 /**
334 * \brief Lists sub-directories in a directory
335 * \details Lists all the sub-directories in the directory specified
336 * by \p path, and stores the list in \p result. Special entries "."
337 * and ".." are not stored in \p result. If parameter recursive
338 * is set to \c true, \p result will include the entries of all
339 * sub-directories in \p path recursively.
340 * \param[in] path the path to an existing directory
341 * \param[in] result output vector of sub-directories in \p path
342 * \param[in] recursive recursively traverses all sub-directories in
343 * \p path
344 * \see get_directory_entries()
345 */
346 virtual void get_subdirectories_recursive(
347 const std::string& path,
348 std::vector<std::string>& result, bool recursive = true
349 );
350
351 /**
352 * \brief Converts a path to Unix format
353 * \details It changes all Windows "\" directory separators into
354 * Unix "/" directory separators.
355 * \param[in,out] path the path to be converted
356 */
357 virtual void flip_slashes(std::string& path);
358
359 /**
360 * \brief Copies a file
361 * \param[in] from name of the file to be copied
362 * \param[out] to name of the copy
363 * \retval true if the copy was successful
364 * \retval false otherwise
365 */
366 virtual bool copy_file(
367 const std::string& from, const std::string& to
368 );
369 };
370
371 /**
372 * \brief Implementation of a file system stored in memory.
373 */
374 class GEOGRAM_API MemoryNode : public Node {
375 public:
376
377 /**
378 * \brief MemoryNode constructor.
379 * \param[in] path full path to this node.
380 */
381 MemoryNode(const std::string& path="/") : path_(path) {
382 }
383
384 /** \copydoc Node::copy_file() */
385 bool copy_file(
386 const std::string& from, const std::string& to
387 ) override ;
388
389 /** \copydoc Node::load_file_as_string() */
390 std::string load_file_as_string(const std::string& path) override;
391
392 /** \copydoc Node::is_file() */
393 virtual bool is_file(const std::string& path) override;
394
395 /** \copydoc Node::is_directory() */
396 virtual bool is_directory(const std::string& path) override;
397
398 /** \copydoc Node::create_directory() */
399 virtual bool create_directory(const std::string& path) override;
400
401 /** \copydoc Node::delete_directory() */
402 virtual bool delete_directory(const std::string& path) override;
403
404 /** \copydoc Node::delete_file() */
405 virtual bool delete_file(const std::string& path) override;
406
407 /** \copydoc Node::get_directory_entries() */
408 bool get_directory_entries(
409 const std::string& path, std::vector<std::string>& result
410 ) override;
411
412
413 /** \copydoc Node::rename_file() */
414 bool rename_file(
415 const std::string& old_name, const std::string& new_name
416 ) override;
417
418 /**
419 * \brief Gets the contents of a file.
420 * \param[in] path the path to the file.
421 * \return a const pointer to the contents of the file.
422 */
423 const char* get_file_contents(const std::string& path);
424
425 /**
426 * \brief Creates a file.
427 * \param[in] path the path to the file
428 * \param[in] content a const pointer to the contents of the file
429 */
430 bool create_file(const std::string& path, const char* content);
431
432 protected:
433 /**
434 * \brief Splits a path.
435 * \param[in] path the path
436 * \param[out] leadingsubdir the leading subdirectory or the
437 * empty string
438 * \param[out] rest the rest of the path
439 */
440 static void split_path(
441 const std::string& path, std::string& leadingsubdir,
442 std::string& rest
443 );
444
445 private:
446 std::string path_;
447 std::map<std::string, SmartPointer<MemoryNode> > subnodes_;
448 std::map<std::string, const char*> files_;
449 };
450
451 typedef SmartPointer<Node> Node_var;
452
453 /**********************************************************/
454
455 /**
456 * \brief Initializes the FileSystem library.
457 * \details This function is automatically called during
458 * Geogram startup. It should not be called by client
459 * code.
460 */
461 void GEOGRAM_API initialize();
462
463 /**
464 * \brief Terminates the FileSystem library.
465 * \details This function is automatically called during
466 * Geogram shutdown. It should not be called by client
467 * code.
468 */
469 void GEOGRAM_API terminate();
470
471 /** \copydoc FileSystem::Node::is_file() */
472 bool GEOGRAM_API is_file(const std::string& path);
473
474 /** \copydoc FileSystem::Node::is_directory() */
475 bool GEOGRAM_API is_directory(const std::string& path);
476
477 /**
478 * \brief Tests whether one can read files from a directory.
479 * \param[in] path the directory to be tested, either
480 * absolute or relative to current working directory.
481 * \retval true if one can read files in \p path
482 * \retval false otherwise
483 */
484 bool GEOGRAM_API can_read_directory(const std::string& path);
485
486 /**
487 * \brief Tests whether a directory can be written to.
488 * \param[in] path the directory to be tested, either
489 * absolute or relative to current working directory.
490 * \param[in] create_missing_directories if set, then
491 * the function tentatively creates the subdirectories
492 * that do not already exist (as "mkdir -p" does).
493 */
494 bool GEOGRAM_API can_write_directory(
495 const std::string& path, bool create_missing_directories = false
496 );
497
498 /** \copydoc FileSystem::Node::create_directory() */
499 bool GEOGRAM_API create_directory(const std::string& path);
500
501 /** \copydoc FileSystem::Node::delete_directory() */
502 bool GEOGRAM_API delete_directory(const std::string& path);
503
504 /** \copydoc FileSystem::Node::delete_file() */
505 bool GEOGRAM_API delete_file(const std::string& path);
506
507 /** \copydoc FileSystem::Node::get_directory_entries() */
508 bool GEOGRAM_API get_directory_entries(
509 const std::string& path, std::vector<std::string>& result
510 );
511
512 /** \copydoc FileSystem::Node::get_current_working_directory() */
513 std::string GEOGRAM_API get_current_working_directory();
514 bool GEOGRAM_API set_current_working_directory(
515 const std::string& path
516 );
517
518 /** \copydoc FileSystem::Node::rename_file() */
519 bool GEOGRAM_API rename_file(
520 const std::string& old_name, const std::string& new_name
521 );
522
523 /** \copydoc FileSystem::Node::get_time_stamp() */
524 Numeric::uint64 GEOGRAM_API get_time_stamp(
525 const std::string& path
526 );
527
528 /** \copydoc FileSystem::Node::extension() */
529 std::string GEOGRAM_API extension(const std::string& path);
530
531 /** \copydoc FileSystem::Node::base_name() */
532 std::string GEOGRAM_API base_name(
533 const std::string& path, bool remove_extension = true
534 );
535
536 /** \copydoc FileSystem::Node::dir_name() */
537 std::string GEOGRAM_API dir_name(const std::string& path);
538
539 /** \copydoc FileSystem::Node::get_directory_entries() */
540 void GEOGRAM_API get_directory_entries_recursive(
541 const std::string& path,
542 std::vector<std::string>& result, bool recursive = true
543 );
544
545 /** \copydoc FileSystem::Node::get_files() */
546 void GEOGRAM_API get_files(
547 const std::string& path,
548 std::vector<std::string>& result, bool recursive = false
549 );
550
551 /** \copydoc FileSystem::Node::get_subdirectories() */
552 void GEOGRAM_API get_subdirectories(
553 const std::string& path,
554 std::vector<std::string>& result, bool recursive = false
555 );
556
557 /** \copydoc FileSystem::Node::flip_slashes() */
558 void GEOGRAM_API flip_slashes(std::string& path);
559
560 /** \copydoc FileSystem::Node::copy_file() */
561 bool GEOGRAM_API copy_file(
562 const std::string& from, const std::string& to
563 );
564
565 /** \copydoc FileSystem::Node::set_executable_flag() */
566 bool GEOGRAM_API set_executable_flag(const std::string& filename);
567
568 /** \copydoc FileSystem::Node::touch() */
569 bool GEOGRAM_API touch(const std::string& filename);
570
571 /** \copydoc FileSystem::Node::normalized_path() */
572 std::string GEOGRAM_API normalized_path(const std::string& path);
573
574 /** \copydoc FileSystem::Node::absolute_path() */
575 std::string GEOGRAM_API absolute_path(const std::string& path);
576
577 /** \copydoc FileSystem::Node::home_directory() */
578 std::string GEOGRAM_API home_directory();
579
580 /** \copydoc FileSystem::Node::documents_directory() */
581 std::string GEOGRAM_API documents_directory();
582
583 /**
584 * \brief Gets the root of the file system.
585 * \param[out] root a pointer to the root of
586 * the FileSystem.
587 */
588 void GEOGRAM_API get_root(Node*& root);
589
590 #ifdef GEO_OS_EMSCRIPTEN
591 /**
592 * \brief Declares a function to be called whenever the file system
593 * changes.
594 * \details The function will be called when the user loads a file
595 * using the button in the webpage.
596 * \param[in] callback the function to be called.
597 */
598 void set_file_system_changed_callback(void(*callback)());
599 #endif
600
601 }
602 }
603
604 #endif
605