A library for working with phylogenetic and population genetic data.
v0.27.0
fs.cpp
Go to the documentation of this file.
1 /*
2  Genesis - A toolkit for working with phylogenetic data.
3  Copyright (C) 2014-2021 Lucas Czech
4 
5  This program is free software: you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation, either version 3 of the License, or
8  (at your option) any later version.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 
18  Contact:
19  Lucas Czech <lczech@carnegiescience.edu>
20  Department of Plant Biology, Carnegie Institution For Science
21  260 Panama Street, Stanford, CA 94305, USA
22 */
23 
32 
33 #include <cassert>
34 #include <cctype>
35 #include <dirent.h>
36 #include <errno.h>
37 #include <fcntl.h>
38 #include <fstream>
39 #include <functional>
40 #include <limits.h>
41 #include <regex>
42 #include <set>
43 #include <sstream>
44 #include <stdexcept>
45 #include <stdlib.h>
46 #include <streambuf>
47 #include <sys/stat.h>
48 #include <unistd.h>
49 #include <utility>
50 
59 
60 namespace genesis {
61 namespace utils {
62 
63 // =================================================================================================
64 // File Access
65 // =================================================================================================
66 
67 bool path_exists( std::string const& path )
68 {
69  struct stat info;
70  return ( stat( path.c_str(), &info ) == 0 );
71 }
72 
73 bool is_file( std::string const& path )
74 {
75  return file_exists( path );
76 }
77 
78 bool file_exists( std::string const& filename )
79 {
80  // There are plenty of discussions on stackoverflow on how to do this correctly,
81  // e.g., https://stackoverflow.com/a/12774387
82  // None of them worked for me, meaning that they also returned true for directories.
83  // Thus, we use a simple approach that does a basic check, and then also tests for dir...
84 
85  std::ifstream instream(filename);
86  instream.seekg( 0, std::ios::end);
87  return instream.good() && ! is_dir( filename );
88 }
89 
90 std::string file_read( std::string const& filename, bool detect_compression )
91 {
92  // Create string beforehand to enable copy elision.
93  std::string str;
94 
95  if( detect_compression && is_gzip_compressed_file( filename )) {
96 
97  // Open decompressing stream
98  GzipIFStream instream( filename );
99  if( !instream.good() ) {
100  throw std::runtime_error( "Cannot read from file '" + filename + "'." );
101  }
102 
103  // Can't assess file size for compressed files, so just read.
104  str.assign(
105  std::istreambuf_iterator<char>(instream),
106  std::istreambuf_iterator<char>()
107  );
108  return str;
109  }
110 
111  // Open normal stream
112  std::ifstream instream(filename);
113  if( !instream.good() ) {
114  throw std::runtime_error( "Cannot read from file '" + filename + "'." );
115  }
116 
117  // Get file size, so that we do not waste time and space for string concats.
118  instream.seekg(0, std::ios::end);
119  str.reserve(instream.tellg());
120  instream.seekg(0, std::ios::beg);
121 
122  // Read content
123  str.assign(
124  std::istreambuf_iterator<char>(instream),
125  std::istreambuf_iterator<char>()
126  );
127  return str;
128 }
129 
130 std::vector<std::string> file_read_lines( std::string const& filename, bool detect_compression )
131 {
132  std::vector<std::string> result;
133  utils::InputStream it( from_file( filename, detect_compression ));
134  while( it ) {
135  result.push_back( read_to_end_of_line( it ));
136  assert( !it || *it == '\n' );
137  ++it;
138  }
139  return result;
140 }
141 
142 void file_write( std::string const& content, std::string const& filename, bool create_dirs )
143 {
144  std::ofstream ofs;
145  utils::file_output_stream( filename, ofs, std::ios_base::out, create_dirs );
146  ofs << content;
147 }
148 
149 void file_append( std::string const& content, std::string const& filename, bool create_dirs )
150 {
151  // TODO maybe merge with file_write and use mode as optional parameter.
152 
153  if( create_dirs ) {
154  auto const path = file_path( filename );
155  dir_create( path );
156  }
157 
158  std::ofstream out_stream( filename, std::ofstream::app );
159  if( out_stream.fail() ) {
160  throw std::runtime_error( "Cannot append to file '" + filename + "'." );
161  }
162  out_stream << content;
163 }
164 
165 // =================================================================================================
166 // Directory Access
167 // =================================================================================================
168 
169 bool is_dir( std::string const& path )
170 {
171  return dir_exists( path );
172 }
173 
174 bool dir_exists( std::string const& dir )
175 {
176  struct stat info;
177  if (stat (dir.c_str(), &info) != 0) {
178  return false;
179  }
180  return static_cast<bool>( info.st_mode & S_IFDIR );
181 
182  // alternative implementation:
183  // DIR* dp = opendir(dir);
184  // if (dp) {
185  // closedir(dir);
186  // return dp;
187  // } else {
188  // return false;
189  // }
190 }
191 
192 void dir_create( std::string const& path, bool with_parents )
193 {
194  mode_t mode = 0775;
195  struct stat info;
196 
197  // Checks. If it is the current dir, do nothing.
198  auto const path_no_bs = utils::trim_right( path, "/\\");
199  if( path_no_bs.empty() ) {
200  return;
201  }
202 
203  // Run recursively.
204  if( with_parents ) {
205  if( ! dir_exists( path_no_bs ) && path_no_bs.size() > 0 ) {
206  dir_create( file_path( path_no_bs ), true );
207  }
208  }
209 
210  // Try to make dir.
211  if( stat (path.c_str(), &info) != 0 ) {
212  if( mkdir( path.c_str(), mode ) != 0 && errno != EEXIST ) {
213  throw std::runtime_error( "Cannot create directory: " + path );
214  }
215  } else if( !S_ISDIR(info.st_mode) ) {
216  throw std::runtime_error( "Path exists, but is not a directory: " + path );
217  }
218 }
219 
220 std::string dir_normalize_path( std::string const& path )
221 {
222  return utils::trim_right( path, "/") + "/";
223 }
224 
225 static std::vector<std::string> dir_list_contents_(
226  std::string const& dir,
227  bool full_path,
228  std::string const& regex,
229  std::function<bool( std::string const& )> condition
230 ) {
231  std::vector<std::string> list;
232  auto const dir_path = dir_normalize_path( dir );
233  std::regex pattern( regex );
234 
235  DIR* dp;
236  struct dirent* dirp;
237 
238  if( ( dp = opendir( dir.c_str() )) == nullptr) {
239  throw std::runtime_error( "Cannot open directory '" + dir + "'." );
240  }
241  while ((dirp = readdir(dp)) != nullptr) {
242  auto const fn = std::string( dirp->d_name );
243 
244  if (fn == "." || fn == "..") {
245  continue;
246  }
247  if( ! regex.empty() && ! regex_match( fn, pattern ) ) {
248  continue;
249  }
250  if( ! condition( dir_path + fn ) ) {
251  continue;
252  }
253 
254  if( full_path ) {
255  list.push_back( dir_path + fn );
256  } else {
257  list.push_back( fn );
258  }
259  }
260  closedir(dp);
261 
262  //~ std::sort(list.begin(), list.end());
263  return list;
264 }
265 
266 std::vector<std::string> dir_list_contents(
267  std::string const& dir,
268  bool full_path,
269  std::string const& regex
270 ) {
271  return dir_list_contents_(
272  dir, full_path, regex,
273  []( std::string const& ){ return true; }
274  );
275 }
276 
277 std::vector<std::string> dir_list_files(
278  std::string const& dir,
279  bool full_path,
280  std::string const& regex
281 ) {
282  return dir_list_contents_(
283  dir, full_path, regex, is_file
284  );
285 }
286 
287 std::vector<std::string> dir_list_directories(
288  std::string const& dir,
289  bool full_path,
290  std::string const& regex
291 ) {
292  return dir_list_contents_(
293  dir, full_path, regex, is_dir
294  );
295 }
296 
297 // =================================================================================================
298 // Path Information
299 // =================================================================================================
300 
301 static std::string current_path_getcwd_()
302 {
303  // Wrapper for the standard getcwd() function to bring it into C++
304  // Adapted from https://stackoverflow.com/a/2203853/4184258
305 
306  // The local buffer of size PATH_MAX is fine for Windows, but pretty much no other OS.
307  char temp[ PATH_MAX ];
308  errno = 0;
309  if( getcwd( temp, PATH_MAX ) != nullptr ) {
310  return dir_normalize_path( std::string( temp ));
311  }
312 
313  int error = errno;
314  switch( error ) {
315  case EACCES:
316  throw std::runtime_error( "Cannot read current directory. Access denied." );
317 
318  case ENOMEM:
319  throw std::runtime_error( "Cannot read current directory. Insufficient storage." );
320 
321  default: {
322  std::ostringstream str;
323  str << "Cannot read current directory. Unrecognised error: " << error;
324  throw std::runtime_error( str.str() );
325  }
326  }
327 
328  // Make compilers happy.
329  return "";
330 }
331 
332 static std::string current_path_unix_()
333 {
334  // Code adapted from http://insanecoding.blogspot.com/2007/11/pathmax-simply-isnt.html
335  // Does not work on Windows systems.
336 
337  std::string path;
338  typedef std::pair<dev_t, ino_t> file_id;
339 
340  // Keep track of start directory, so can jump back to it later
341  int start_fd = open(".", O_RDONLY);
342  if( start_fd == -1 ) {
343  throw std::runtime_error( "Cannot read current directory." );
344  }
345 
346  struct stat sb;
347  if( fstat(start_fd, &sb) ) {
348  throw std::runtime_error( "Cannot read current directory." );
349  }
350 
351  // Get info for root directory, so we can determine when we hit it
352  file_id current_id(sb.st_dev, sb.st_ino);
353  if( stat( "/", &sb )) {
354  throw std::runtime_error( "Cannot read current directory." );
355  }
356 
357  std::vector<std::string> path_components;
358  file_id root_id(sb.st_dev, sb.st_ino);
359 
360  // If they're equal, we've obtained enough info to build the path
361  while( current_id != root_id ) {
362  bool pushed = false;
363 
364  // Keep recursing towards root each iteration
365  if( ! chdir("..") ) {
366  DIR *dir = opendir(".");
367  if( dir ) {
368  dirent *entry;
369 
370  // We loop through each entry trying to find where we came from
371  while(( entry = readdir(dir) )) {
372  if(
373  strcmp(entry->d_name, ".")
374  && strcmp(entry->d_name, "..")
375  && !lstat(entry->d_name, &sb)
376  ) {
377  file_id child_id(sb.st_dev, sb.st_ino);
378 
379  // We found where we came from, add its name to the list
380  if( child_id == current_id ) {
381  path_components.push_back(entry->d_name);
382  pushed = true;
383  break;
384  }
385  }
386  }
387  closedir(dir);
388 
389  // If we have a reason to continue, we update the current dir id
390  if( pushed && !stat(".", &sb) ) {
391  current_id = file_id(sb.st_dev, sb.st_ino);
392  }
393  // Else, Uh oh, can't read information at this level
394  }
395  }
396 
397  // If we didn't obtain any info this pass, no reason to continue
398  if( ! pushed ) {
399  break;
400  }
401  }
402 
403  // Unless they're equal, we failed above
404  if( current_id == root_id ) {
405 
406  // Built the path, will always end with a slash
407  path = "/";
408  for( auto i = path_components.rbegin(); i != path_components.rend(); ++i ) {
409  path += *i + "/";
410  }
411  } else {
412  throw std::runtime_error( "Cannot read current directory." );
413  }
414 
415  if( fchdir(start_fd) ) {
416  throw std::runtime_error( "Cannot change directory." );
417  }
418  close(start_fd);
419 
420  return path;
421 }
422 
423 std::string current_path()
424 {
425  // We use our own implementations here, which depend on the OS.
426  #if defined( _WIN32 ) || defined( _WIN64 )
427  return current_path_getcwd_();
428  #else
429  return current_path_unix_();
430  #endif
431 
432  // We use conditional compilation. Silence compiler warnings about unused functions.
433  (void) current_path_getcwd_;
434  (void) current_path_unix_;
435 }
436 
437 // The following set of helper functions is adapted from
438 // http://insanecoding.blogspot.com/2007/11/implementing-realpath-in-c.html
439 // See there for details.
440 
441 static void relative_dir_base_split_( std::string const& path, std::string& dir, std::string& base )
442 {
443  // Find the last slash
444  auto slash_pos = path.rfind("/");
445 
446  // If there is a slash
447  if (slash_pos != std::string::npos) {
448  slash_pos++;
449 
450  // Directory is before slash
451  dir = path.substr(0, slash_pos);
452 
453  // And obviously, the file is after
454  base = path.substr(slash_pos);
455  } else {
456  // Otherwise, there is no directory present
457  dir.clear();
458  base = path;
459  }
460 }
461 
462 static std::string chdir_getcwd_( std::string const& dir )
463 {
464  // Open current directory so we can save a handle to it
465  int start_fd = open(".", O_RDONLY);
466  if (start_fd == -1) {
467  throw std::runtime_error( "Cannot open current directory." );
468  }
469 
470  // Change to directory
471  if( chdir(dir.c_str()) ) {
472  throw std::runtime_error( "Cannot change directory." );
473  }
474 
475  // And get its path
476  auto const path = current_path();
477 
478  // And change back of course
479  if( fchdir(start_fd) ) {
480  throw std::runtime_error( "Cannot change directory." );
481  }
482  close(start_fd);
483 
484  return path;
485 }
486 
487 static std::string realpath_file_(const std::string& path )
488 {
489  std::string dir;
490  std::string base;
491  relative_dir_base_split_(path, dir, base);
492 
493  // If there is a directory, get the realpath() for it, otherwise the current directory
494  auto resolved_path = dir.size() ? chdir_getcwd_(dir) : current_path();
495  return resolved_path + base;
496 }
497 
498 static bool readlink_internal_(const std::string& path, std::string& buffer, ssize_t length)
499 {
500  bool success = false;
501  if (length > 0) {
502  // Room for Null
503  char *buf = new(std::nothrow) char[length+1];
504 
505  if (buf) {
506  // Give room for failure
507  ssize_t amount = ::readlink(path.c_str(), buf, length+1);
508 
509  // If > length, it was modified mid check
510  if ((amount > 0) && (amount <= length)) {
511  buf[amount] = 0;
512  buffer = buf;
513  success = true;
514  }
515  delete[] buf;
516  }
517  }
518 
519  return success;
520 }
521 
522 static void build_path_base_swap_(std::string &path, const std::string& newbase)
523 {
524  std::string dir;
525  std::string base;
526  relative_dir_base_split_(path, dir, base);
527 
528  if (dir.size()) {
529  path = dir + newbase;
530  } else {
531  path = newbase;
532  }
533 }
534 
535 static bool symlink_resolve_( const std::string& start, std::string& end )
536 {
537  typedef std::pair<dev_t, ino_t> file_id;
538 
539  bool success = false;
540  if (start.size()) {
541  // Need a modifyable copy
542  std::string path = start;
543  struct stat sb;
544  std::set<file_id> seen_links;
545 
546  bool resolved_link;
547  // The symlink resolve loop
548  do {
549  resolved_link = false;
550  if (!lstat(path.c_str(), &sb)) {
551  file_id current_id(sb.st_dev, sb.st_ino);
552  // Not a link we've seen
553  if (seen_links.find(current_id) == seen_links.end()) {
554  // Add to our set
555  seen_links.insert(current_id);
556 
557  // Another link
558  if (S_ISLNK(sb.st_mode)) {
559  std::string newpath;
560  if (readlink_internal_(path, newpath, sb.st_size)) {
561  // Absolute
562  if (newpath[0] == '/') {
563  path = newpath;
564  } else {
565  // We need to calculate the relative path in relation to the current
566  build_path_base_swap_(path, newpath);
567  }
568  resolved_link = true;
569  // Else, Link can't be read, time to quit
570  }
571  } else {
572  // Yay, it's not a link! got to the last part finally!
573  end = realpath_file_( path );
574  success = true;
575  }
576  // Else, Nice try, someone linked a link back into a previous link
577  // during the scan to try to trick us into an infinite loop.
578  }
579  // Else, Dangling link, can't resolve
580  }
581  } while (resolved_link);
582  }
583  return(success);
584 }
585 
586 static std::string real_path_unix_( std::string const& path, bool resolve_link )
587 {
588  // Custom implementation, using the above helper functions. Based on
589  // http://insanecoding.blogspot.com/2007/11/implementing-realpath-in-c.html
590  // See there for details.
591 
592  // Edge case.
593  if( ! path.size()) {
594  return path;
595  }
596 
597  struct stat sb;
598  if( stat(path.c_str(), &sb) ) {
599  throw std::runtime_error( "Cannot read path." );
600  }
601 
602  if( S_ISDIR( sb.st_mode )) {
603  return chdir_getcwd_( path );
604  } else {
605  if( resolve_link ) {
606  std::string result;
607  if( ! symlink_resolve_( path, result ) ) {
608  throw std::runtime_error( "Cannot determine real path." );
609  }
610  return result;
611  } else {
612  return realpath_file_( path );
613  }
614  }
615 
616  // Make compilers happy.
617  return path;
618 }
619 
620 static std::string real_path_realpath_( std::string const& path, bool resolve_link )
621 {
622  // Wrapper for the standard realpath() function to bring it into C++
623  // Works on Windows.
624 
625  // Not supported in this function...
626  (void) resolve_link;
627 
628  errno = 0;
629  char resolved_path[PATH_MAX];
630  auto ptr = realpath( path.c_str(), resolved_path );
631  if( errno != 0 ) {
632  throw std::runtime_error( "Cannot determine real path." );
633  }
634  return std::string( ptr );
635 }
636 
637 std::string real_path( std::string const& path, bool resolve_link )
638 {
639  // We use our own implementations here, which depend on the OS.
640  #if defined( _WIN32 ) || defined( _WIN64 )
641  return real_path_realpath_( path, resolve_link );
642  #else
643  return real_path_unix_( path, resolve_link );
644  #endif
645 
646  // We use conditional compilation. Silence compiler warnings about unused functions.
647  (void) real_path_realpath_;
648  (void) real_path_unix_;
649 }
650 
651 // =================================================================================================
652 // File Information
653 // =================================================================================================
654 
655 std::unordered_map<std::string, std::string> file_info( std::string const& filename )
656 {
657  std::string basename = file_basename(filename);
658  std::unordered_map<std::string, std::string> res;
659 
660  res["path"] = file_path(filename);
661  res["basename"] = basename;
662  res["filename"] = file_filename(basename);
663  res["extension"] = file_extension(basename);
664 
665  return res;
666 }
667 
668 size_t file_size( std::string const& filename )
669 {
670  auto result = filename;
671  std::ifstream in(result, std::ifstream::ate | std::ifstream::binary);
672  return static_cast<size_t>(in.tellg());
673 }
674 
675 std::string file_path( std::string const& filename )
676 {
677  auto result = filename;
678  const size_t idx = result.find_last_of("\\/");
679  if( idx == std::string::npos ) {
680  return "";
681  }
682 
683  result.erase(idx);
684  return result;
685 }
686 
687 std::string file_basename( std::string const& filename )
688 {
689  auto result = filename;
690  const size_t idx = result.find_last_of("\\/");
691  if( idx != std::string::npos ) {
692  result.erase(0, idx + 1);
693  }
694  return result;
695 }
696 
697 std::string file_basename(
698  std::string const& filename,
699  std::vector<std::string> const& remove_extensions
700 ) {
701  auto bn = file_basename( filename );
702  for( auto const& ext : remove_extensions ) {
703  if( utils::ends_with( bn, ext ) ) {
704  bn.erase( bn.size() - ext.size() );
705  }
706  }
707  return bn;
708 }
709 
710 std::string file_filename( std::string const& filename )
711 {
712  auto result = filename;
713  const size_t idx = result.rfind('.');
714  if( idx != 0 && idx != std::string::npos ) {
715  result.erase(idx);
716  }
717  return result;
718 }
719 
720 std::string file_extension( std::string const& filename )
721 {
722  auto result = filename;
723  const size_t idx = result.rfind('.');
724  if( idx != 0 && idx != std::string::npos ) {
725  result.erase(0, idx + 1);
726  }
727  return result;
728 }
729 
730 // =================================================================================================
731 // File Names
732 // =================================================================================================
733 
734 bool is_valid_filename( std::string const& filename )
735 {
736  // No empty filenames.
737  if( trim( filename ) == "" ) {
738  return false;
739  }
740 
741  // No space at beginning or end.
742  if( starts_with( filename, " " ) || ends_with( filename, " " )) {
743  return false;
744  }
745 
746  // Check forbidden chars of Win and Unix systems.
747  if( filename.find_first_of( "<>:\"\\/|?*" ) != std::string::npos ) {
748  return false;
749  }
750 
751  // Check for non-printable chars.
752  // They might be allowed on most systems, but better be conservative here.
753  for( auto c : filename ) {
754  if( ! isprint( c ) ) {
755  return false;
756  }
757  }
758 
759  return true;
760 }
761 
762 std::string sanitize_filename( std::string const& filename )
763 {
764  // Prepare result.
765  std::string result = "";
766  result.reserve( filename.size() );
767 
768  // Copy all printable chars, drop the others.
769  for( auto c : filename ) {
770  if( isprint( c ) ) {
771  result += c;
772  }
773  }
774 
775  // No spaces around the name, and replace all forbidden chars by underscores.
776  result = trim( result );
777  result = replace_all_chars( result, "<>:\"\\/|?*", '_' );
778 
779  if( result == "" ) {
780  throw std::runtime_error( "Invalid filename." );
781  }
782 
783  return result;
784 }
785 
786 } // namespace utils
787 } // namespace genesis
genesis::utils::current_path
std::string current_path()
Return the current (working) directory, simiar to getcwd().
Definition: fs.cpp:423
genesis::utils::readlink_internal_
static bool readlink_internal_(const std::string &path, std::string &buffer, ssize_t length)
Definition: fs.cpp:498
genesis::utils::InputStream
Stream interface for reading data from an InputSource, that keeps track of line and column counters.
Definition: input_stream.hpp:81
algorithm.hpp
Provides some valuable algorithms that are not part of the C++ 11 STL.
genesis::utils::chdir_getcwd_
static std::string chdir_getcwd_(std::string const &dir)
Definition: fs.cpp:462
genesis::utils::trim_right
std::string trim_right(std::string const &s, std::string const &delimiters)
Return a copy of the input string, with left trimmed white spaces.
Definition: string.cpp:578
genesis::utils::symlink_resolve_
static bool symlink_resolve_(const std::string &start, std::string &end)
Definition: fs.cpp:535
fs.hpp
Provides functions for accessing the file system.
genesis::utils::dir_create
void dir_create(std::string const &path, bool with_parents)
Create a directory.
Definition: fs.cpp:192
genesis::utils::file_size
size_t file_size(std::string const &filename)
Return the size of a file.
Definition: fs.cpp:668
genesis::utils::from_file
std::shared_ptr< BaseInputSource > from_file(std::string const &file_name, bool detect_compression=true)
Obtain an input source for reading from a file.
Definition: input_source.hpp:67
genesis::utils::dir_list_directories
std::vector< std::string > dir_list_directories(std::string const &dir, bool full_path, std::string const &regex)
Get a list of directories in a directory.
Definition: fs.cpp:287
genesis::utils::relative_dir_base_split_
static void relative_dir_base_split_(std::string const &path, std::string &dir, std::string &base)
Definition: fs.cpp:441
genesis::utils::file_info
std::unordered_map< std::string, std::string > file_info(std::string const &filename)
Return information about a file.
Definition: fs.cpp:655
output_stream.hpp
genesis::utils::current_path_getcwd_
static std::string current_path_getcwd_()
Definition: fs.cpp:301
genesis::tree::length
double length(Tree const &tree)
Get the length of the tree, i.e., the sum of all branch lengths.
Definition: tree/common_tree/functions.cpp:160
genesis::utils::trim
std::string trim(std::string const &s, std::string const &delimiters)
Return a copy of the input string, with trimmed white spaces.
Definition: string.cpp:602
gzip.hpp
genesis::utils::GzipIFStream
Input file stream that offers on-the-fly gzip-decompression if needed.
Definition: gzip_stream.hpp:276
genesis::utils::file_path
std::string file_path(std::string const &filename)
Return the path leading to a file.
Definition: fs.cpp:675
genesis::utils::replace_all_chars
std::string replace_all_chars(std::string const &text, std::string const &search_chars, char replace)
Replace all occurrences of the search_chars in text by the replace char.
Definition: string.cpp:564
genesis::utils::current_path_unix_
static std::string current_path_unix_()
Definition: fs.cpp:332
genesis::utils::dir_exists
bool dir_exists(std::string const &dir)
Return true iff the directory exists.
Definition: fs.cpp:174
input_source.hpp
genesis::utils::sanitize_filename
std::string sanitize_filename(std::string const &filename)
Remove or replace all invalid parts of a filename.
Definition: fs.cpp:762
genesis::utils::file_filename
std::string file_filename(std::string const &filename)
Remove extension if present.
Definition: fs.cpp:710
genesis::utils::build_path_base_swap_
static void build_path_base_swap_(std::string &path, const std::string &newbase)
Definition: fs.cpp:522
genesis::tree::path
utils::Range< IteratorPath< true > > path(ElementType const &start, ElementType const &finish)
Definition: path.hpp:337
string.hpp
Provides some commonly used string utility functions.
genesis::utils::file_read
std::string file_read(std::string const &filename, bool detect_compression)
Return the contents of a file as a string.
Definition: fs.cpp:90
input_stream.hpp
genesis::utils::real_path
std::string real_path(std::string const &path, bool resolve_link)
Return the real path of a file or directory, similar to realpath().
Definition: fs.cpp:637
genesis::utils::realpath_file_
static std::string realpath_file_(const std::string &path)
Definition: fs.cpp:487
gzip_stream.hpp
genesis::utils::is_gzip_compressed_file
bool is_gzip_compressed_file(std::string const &file_name)
Return whether a given file is gzip-compressed.
Definition: gzip.cpp:58
genesis::utils::starts_with
bool starts_with(std::string const &text, std::string const &start)
Return whether a string starts with another string.
Definition: string.cpp:81
genesis::utils::is_dir
bool is_dir(std::string const &path)
Return true iff the provided path is a directory.
Definition: fs.cpp:169
genesis::utils::real_path_unix_
static std::string real_path_unix_(std::string const &path, bool resolve_link)
Definition: fs.cpp:586
genesis::utils::file_read_lines
std::vector< std::string > file_read_lines(std::string const &filename, bool detect_compression)
Return the contents of a file as a vector of strings, one entry for each line.
Definition: fs.cpp:130
genesis
Container namespace for all symbols of genesis in order to keep them separate when used as a library.
Definition: placement/formats/edge_color.cpp:42
genesis::utils::path_exists
bool path_exists(std::string const &path)
Return whether a path exists, i.e., is a file or directory.
Definition: fs.cpp:67
genesis::utils::ends_with
bool ends_with(std::string const &text, std::string const &ending)
Return whether a string ends with another string.
Definition: string.cpp:89
genesis::utils::real_path_realpath_
static std::string real_path_realpath_(std::string const &path, bool resolve_link)
Definition: fs.cpp:620
genesis::utils::is_file
bool is_file(std::string const &path)
Return true iff the provided path is a file.
Definition: fs.cpp:73
genesis::utils::file_exists
bool file_exists(std::string const &filename)
Return true iff the file exists.
Definition: fs.cpp:78
genesis::utils::dir_list_contents
std::vector< std::string > dir_list_contents(std::string const &dir, bool full_path, std::string const &regex)
Get a list of files and directories in a directory.
Definition: fs.cpp:266
genesis::utils::dir_list_contents_
static std::vector< std::string > dir_list_contents_(std::string const &dir, bool full_path, std::string const &regex, std::function< bool(std::string const &)> condition)
Definition: fs.cpp:225
scanner.hpp
genesis::utils::file_basename
std::string file_basename(std::string const &filename)
Remove directory name from file name if present.
Definition: fs.cpp:687
genesis::utils::is_valid_filename
bool is_valid_filename(std::string const &filename)
Check whether a file name is valid.
Definition: fs.cpp:734
genesis::utils::dir_normalize_path
std::string dir_normalize_path(std::string const &path)
Normalize a dir name, i.e., make sure that the given path ends with exaclty one slash.
Definition: fs.cpp:220
genesis::utils::file_write
void file_write(std::string const &content, std::string const &filename, bool create_dirs)
Write the content of a string to a file.
Definition: fs.cpp:142
genesis::utils::file_append
void file_append(std::string const &content, std::string const &filename, bool create_dirs)
Append the content of a string to a file.
Definition: fs.cpp:149
genesis::utils::file_extension
std::string file_extension(std::string const &filename)
Return the extension name of a file.
Definition: fs.cpp:720
genesis::utils::read_to_end_of_line
std::string read_to_end_of_line(InputStream &source)
Lexing function that reads until the end of the line (i.e., to the new line char),...
Definition: scanner.hpp:134
genesis::utils::dir_list_files
std::vector< std::string > dir_list_files(std::string const &dir, bool full_path, std::string const &regex)
Get a list of files in a directory.
Definition: fs.cpp:277
genesis::utils::file_output_stream
void file_output_stream(std::string const &filename, std::ofstream &out_stream, std::ios_base::openmode mode=std::ios_base::out, bool create_dirs=true)
Helper function to obtain an output stream to a file.
Definition: output_stream.hpp:69