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