Flow123d  release_3.0.0-1106-ga3b2e4c
file_path.cc
Go to the documentation of this file.
1 /*!
2  *
3  * Copyright (C) 2015 Technical University of Liberec. All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it under
6  * the terms of the GNU General Public License version 3 as published by the
7  * Free Software Foundation. (http://www.gnu.org/licenses/gpl-3.0.en.html)
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12  *
13  *
14  * @file file_path.cc
15  * @brief
16  */
17 
18 #include <boost/filesystem.hpp>
19 #include <fstream>
20 
21 #include "file_path.hh"
22 #include "system.hh"
23 #include <type_traits>
24 
25 
26 
27 /**
28  * Helper method, create path string from vector of strings
29  */
31  ASSERT_GT(sub_paths.size(), 0).error();
32 
33  if (sub_paths.size() == 1) {
34  return sub_paths[0];
35  } else {
36  boost::filesystem::path path = sub_paths[0];
37  for (unsigned int i=1; i<sub_paths.size(); ++i)
38  path = path / sub_paths[i];
39  return path.string();
40  }
41 }
42 
43 
44 // static data members
46 std::shared_ptr<boost::filesystem::path> FilePath::output_dir=std::make_shared<boost::filesystem::path>(".");
47 std::shared_ptr<boost::filesystem::path> FilePath::root_dir=std::make_shared<boost::filesystem::path>(".");
48 
49 
50 FilePath::FilePath(string file_path, const FileType ft)
51 : file_type_(ft)
52 {
53  if (*output_dir == boost::filesystem::path(".")) {
54  WarningOut() << "Creating FileName object before set_io_dirs is called. No file path resolving." << std::endl;
55  abs_file_path_ = std::make_shared<boost::filesystem::path>(file_path);
56  return;
57  }
58 
59  substitute_value(file_path);
60  bool is_abs_path = boost::filesystem::path( convert_for_check_absolute(file_path) ).is_absolute();
61  abs_file_path_ = std::make_shared<boost::filesystem::path>(file_path);
62  if (ft == input_file) {
63  if ( is_abs_path ) {
64  } else {
65  abs_file_path_ = std::make_shared<boost::filesystem::path>(*root_dir / file_path);
66  }
67  } else if (ft == output_file) {
68  if ( is_abs_path ) {
69  if (abs_file_path_->string().substr(0, output_dir->string().size()) == output_dir->string()) {
70  abs_file_path_ = std::make_shared<boost::filesystem::path>( abs_file_path_->string().substr(output_dir->string().size()+1) );
71  } else {
72  THROW( ExcAbsOutputPath() << EI_Path( abs_file_path_->string() ) );
73  }
74  }
75  abs_file_path_ = std::make_shared<boost::filesystem::path>(*output_dir / *abs_file_path_);
76  }
77 
78 }
79 
80 
82 : FilePath(create_path_from_vec(sub_paths), ft) {}
83 
84 
85 FilePath::FilePath(string file_path)
86 : FilePath(file_path, FilePath::output_file) {}
87 
88 
90  : abs_file_path_( std::make_shared<boost::filesystem::path>("/__NO_FILE_NAME_GIVEN__") ),
92 {}
93 
94 
95 
96 void FilePath::set_io_dirs(const string working_dir, const string root, const string input, const string output) {
97  ASSERT_EQ(working_dir, ".").error();
98  FilePath::set_dirs(root, input, output);
99 }
100 
101 
102 void FilePath::set_dirs(const string root, const string input, const string output) {
103  // root directory
104  if (boost::filesystem::path( convert_for_check_absolute(root) ).is_absolute()) {
105  root_dir = std::make_shared<boost::filesystem::path>(root);
106  } else {
107  boost::filesystem::path abs_root_path = boost::filesystem::canonical( boost::filesystem::current_path() / root );
108  root_dir = std::make_shared<boost::filesystem::path>(abs_root_path);
109  }
110 
111  // set output directory
112  // if param output is absolute output_dir = output
113  // else output_dir = root / output
114  // the resulting relative path is always completed to absulute path
115  boost::filesystem::path full_output_path;
116  if ( !boost::filesystem::path( convert_for_check_absolute(output) ).is_absolute() ) {
117  if (boost::filesystem::path( convert_for_check_absolute(root) ).is_absolute()) {
118  full_output_path = boost::filesystem::path(root) / output;
119 
120  create_dir(full_output_path);
121  } else {
122  boost::filesystem::path output_path = boost::filesystem::path(root) / output;
123  create_dir( output_path );
124  full_output_path = boost::filesystem::canonical( boost::filesystem::current_path() / output_path);
125  }
126  } else {
127  full_output_path = boost::filesystem::path(output);
128  create_dir(full_output_path);
129  }
130  output_dir = std::make_shared<boost::filesystem::path>( full_output_path );
131 
132  // the relative input is relative to the directory of the main input file
133  add_placeholder("$INPUT_DIR$", input);
134 }
135 
136 
137 string FilePath::set_dirs_from_input(const string main_yaml, const string input, const string output) {
138  boost::filesystem::path input_path;
139  if ( !boost::filesystem::path( convert_for_check_absolute(main_yaml) ).is_absolute() ) {
140  input_path = boost::filesystem::path(".") / main_yaml;
141  } else {
142  input_path = boost::filesystem::path(main_yaml);
143  }
144  if (! boost::filesystem::exists(input_path))
145  THROW(ExcFileOpen() << EI_Path(input_path.string()));
146 
147  FilePath::set_dirs(input_path.parent_path().string(), input, output);
148 
149 
150  return input_path.filename().string();
151 }
152 
153 
154 
155 void FilePath::add_placeholder(string key,string value) {
156  placeholder[key] = value;
157 }
158 
159 
160 void FilePath::substitute_value(string &path) {
161  for (std::map<std::string,std::string>::const_iterator it = this->placeholder.begin(); it != this->placeholder.end(); ++it) {
162  size_t i = path.find(it->first,0);
163  if (i != std::string::npos) {
164  ASSERT(it->second != "")(it->first).warning("Substituting placeholder with empty value.");
165  path.replace(i, it->first.size(), it->second);
166  }
167  }
168 }
169 
170 
172  return boost::filesystem::current_path().string() + "/";
173 }
174 
175 
177  if (file_type_ == output_file) {
178  create_dir( abs_file_path_->parent_path() );
179  }
180 }
181 
182 
183 string FilePath::parent_path() const {
184  return abs_file_path_->parent_path().string();
185 }
186 
187 
188 string FilePath::filename() const {
189  return abs_file_path_->filename().string();
190 }
191 
192 
193 string FilePath::stem() const {
194  return abs_file_path_->stem().string();
195 }
196 
197 
198 string FilePath::extension() const {
199  return abs_file_path_->extension().string();
200 }
201 
202 
203 string FilePath::cut_extension() const {
204  boost::filesystem::path path = abs_file_path_->parent_path() / abs_file_path_->stem();
205  return path.string();
206 }
207 
208 
209 
210 template <class Stream>
211 void FilePath::open_stream(Stream &stream) const
212 {
213  if ( std::is_same<Stream, ifstream>::value ) ASSERT(file_type_ == FileType::input_file);
214  if ( std::is_same<Stream, ofstream>::value ) ASSERT(file_type_ == FileType::output_file);
215 
216  if (file_type_ == FileType::input_file)
217  stream.open(abs_file_path_->string().c_str(), ios_base::in);
218  else
219  stream.open(abs_file_path_->string().c_str(), ios_base::out);
220 
221  if (! stream.is_open())
222  THROW(ExcFileOpen() << EI_Path(abs_file_path_->string()));
223 
224 }
225 
226 
227 
228 bool FilePath::exists() const
229 {
230  return boost::filesystem::exists( *(this->abs_file_path_) );
231 }
232 
233 
234 
235 template void FilePath::open_stream(ifstream &stream) const;
236 template void FilePath::open_stream(ofstream &stream) const;
237 template void FilePath::open_stream( fstream &stream) const;
238 
239 string FilePath::convert_for_check_absolute(const string path) {
240  ASSERT(path.length()).error("Empty path.");
241 
242  if (path[0] == '/') {
243  return "/" + path;
244  } else {
245  return path;
246  }
247 }
248 
249 
250 
251 FilePath::operator string() const {
252  return abs_file_path_->string();
253 }
254 
255 
256 void FilePath::create_dir(const boost::filesystem::path &dir)
257 {
258  try {
259  boost::filesystem::create_directories(dir);
260  } catch (boost::filesystem::filesystem_error &e) {
261  THROW(ExcMkdirFail() << EI_Path( dir.string() ) << make_nested_message(e) );
262  }
263 }
264 
265 
266 bool FilePath::operator ==(const FilePath &other) const
267  {return *abs_file_path_ == boost::filesystem::path( string(other) ); }
268 
269 
270 std::ostream& operator<<(std::ostream& stream, const FilePath& fp) {
271  return ( stream << string(fp) );
272 }
string stem() const
Definition: file_path.cc:193
FilePath()
Definition: file_path.cc:89
void create_output_dir()
Definition: file_path.cc:176
FileType
Possible types of file.
Definition: file_path.hh:67
std::ostream & operator<<(std::ostream &stream, const FilePath &fp)
Allow redirect FilePath to stream.
Definition: file_path.cc:270
#define ASSERT_GT(a, b)
Definition of comparative assert macro (Greater Than)
Definition: asserts.hh:311
#define ASSERT(expr)
Allow use shorter versions of macro names if these names is not used with external library...
Definition: asserts.hh:346
static std::shared_ptr< boost::filesystem::path > root_dir
Prefix path for input files (directory of the main input file).
Definition: file_path.hh:239
EI_NestedMessage make_nested_message(Exc &e)
Definition: exceptions.hh:285
static string set_dirs_from_input(const string main_yaml, const string input, const string output)
Method for set input and output directories.
Definition: file_path.cc:137
static void set_io_dirs(const string working_dir, const string root, const string input, const string output)
Obsolete method for set input and output directories.
Definition: file_path.cc:96
static constexpr bool value
Definition: json.hpp:87
void open_stream(Stream &stream) const
Definition: file_path.cc:211
static void add_placeholder(string key, string value)
Add new item to place holder.
Definition: file_path.cc:155
std::shared_ptr< boost::filesystem::path > abs_file_path_
Final absolute path to the file.
Definition: file_path.hh:227
bool exists() const
Definition: file_path.cc:228
string create_path_from_vec(vector< string > sub_paths)
Definition: file_path.cc:30
string cut_extension() const
Definition: file_path.cc:203
static string convert_for_check_absolute(string path)
Prepare path string for check absolute path.
Definition: file_path.cc:239
string parent_path() const
Definition: file_path.cc:183
string extension() const
Definition: file_path.cc:198
static const string get_absolute_working_dir()
Definition: file_path.cc:171
Dedicated class for storing path to input and output files.
Definition: file_path.hh:54
bool operator==(const FilePath &other) const
Equality comparison operators for FilePaths.
Definition: file_path.cc:266
static std::map< string, string > placeholder
dictionary of placeholders
Definition: file_path.hh:233
static std::shared_ptr< boost::filesystem::path > output_dir
Prefix path for output files.
Definition: file_path.hh:236
#define WarningOut()
Macro defining &#39;warning&#39; record of log.
Definition: logger.hh:246
string filename() const
Definition: file_path.cc:188
static void create_dir(const boost::filesystem::path &dir)
Definition: file_path.cc:256
static void set_dirs(const string root, const string input, const string output)
Method for set input and output directories.
Definition: file_path.cc:102
void substitute_value(string &path)
Definition: file_path.cc:160
#define THROW(whole_exception_expr)
Wrapper for throw. Saves the throwing point.
Definition: exceptions.hh:53
FileType file_type_
File type.
Definition: file_path.hh:230
#define ASSERT_EQ(a, b)
Definition of comparative assert macro (EQual)
Definition: asserts.hh:327