source: trunk/yat/utility/utility.cc

Last change on this file was 3999, checked in by Peter, 10 months ago

update copyright years

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 6.0 KB
Line 
1// $Id: utility.cc 3999 2020-10-08 23:22:32Z peter $
2
3/*
4  Copyright (C) 2005, 2006 Jari Häkkinen, Markus Ringnér
5  Copyright (C) 2007, 2008 Jari Häkkinen, Peter Johansson
6  Copyright (C) 2010, 2012, 2013, 2014, 2017, 2018, 2019, 2020 Peter Johansson
7
8  This file is part of the yat library, http://dev.thep.lu.se/yat
9
10  The yat library is free software; you can redistribute it and/or
11  modify it under the terms of the GNU General Public License as
12  published by the Free Software Foundation; either version 3 of the
13  License, or (at your option) any later version.
14
15  The yat library is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18  General Public License for more details.
19
20  You should have received a copy of the GNU General Public License
21  along with yat. If not, see <http://www.gnu.org/licenses/>.
22*/
23
24#include <config.h>
25
26#include "utility.h"
27
28#include "Exception.h"
29#include "FileUtil.h"
30#include "stl_utility.h"
31
32#include <cassert>
33#include <cerrno>
34#include <fnmatch.h>
35#include <fstream>
36#include <sstream>
37#include <string>
38#include <sys/stat.h>
39
40namespace theplu {
41namespace yat {
42namespace utility {
43
44  std::string basename(const std::string& path)
45  {
46    if (path.empty())
47      return ".";
48    if (path.size()==1)
49      return path;
50    size_t pos = path.find_last_of('/');
51    if (pos==std::string::npos)
52      return path;
53    if (pos==path.size()-1)
54      return basename(path.substr(0, path.size()-1));
55    return path.substr(pos+1);
56  }
57
58
59  void chdir(const std::string& dir)
60  {
61    if (::chdir(dir.c_str()) )
62      throw errno_error("chdir: '" + dir + "': ");
63  }
64
65
66  void chmod(const std::string& filename, mode_t mode)
67  {
68    if (::chmod(filename.c_str(), mode))
69      throw errno_error("chmod: '" + filename + "': ");
70  }
71
72
73  void copy_file(const std::string& source, const std::string& target)
74  {
75    std::ifstream is;
76    std::ofstream os;
77
78    is.open(source.c_str(), std::ios::in | std::ios::binary);
79    os.open(target.c_str(), std::ios::out | std::ios::binary);
80    os << is.rdbuf();
81    if (!os.good()) {
82      std::ostringstream ss;
83      ss << "copy_file failed writing to '" << target << "'\n";
84      throw runtime_error(ss.str());
85    }
86    if (is.bad() || is.fail()) {
87      std::ostringstream ss;
88      ss << "copy_file failed reading from '" << source << "'\n";
89      throw runtime_error(ss.str());
90    }
91    is.close();
92    os.close();
93
94    // copy permissions
95    struct stat nodestat;
96    stat(source.c_str(), &nodestat);
97    chmod(target.c_str(), nodestat.st_mode);
98  }
99
100
101  std::string dirname(const std::string& path)
102  {
103    if (path.size()<=1) {
104      if (path=="/")
105        return path;
106      else
107        return ".";
108    }
109    assert(path.size()>=2);
110    size_t pos = path.find_last_of('/', path.size()-2);
111    if (pos==std::string::npos)
112      return ".";
113    if (pos==0)
114      return "/";
115    return path.substr(0,pos);
116  }
117
118
119  bool fnmatch(const std::string& pattern, const std::string& str, int flags)
120  {
121    int res = ::fnmatch(pattern.c_str(), str.c_str(), flags);
122    if (res==0)
123      return true;
124    if (res!=FNM_NOMATCH) {
125      std::stringstream ss;
126      ss << "fnmatch(" << pattern << ", " << str << ")";
127      throw runtime_error(ss.str());
128    }
129    return false;
130  }
131
132
133  std::string getcwd(void)
134  {
135    char buffer[256];
136    if (::getcwd(buffer, 256))
137      return std::string(buffer);
138    if (errno == ERANGE) {
139      char buffer2[4096];
140      if (::getcwd(buffer2, 4096))
141        return std::string(buffer2);
142    }
143    throw errno_error("getcwd failed: ");
144    return "";
145  }
146
147
148  void gsl_error_handler(const char* reason, const char* file,
149                         int line, int gsl_errno)
150  {
151    std::ostringstream msg;
152    msg << file << ":" << line << ": " << reason << ": ";
153    throw GSL_error(msg.str(), gsl_errno);
154  }
155
156
157  bool is_double(const std::string& s)
158  {
159    return is<double>(s);
160  }
161 
162
163  bool is_equal(std::string s, std::string other)
164  {
165    std::stringstream ss(s);
166    std::string s2;
167    ss >> s2; // to trim surrounding whitespaces
168    to_lower(s2);
169    if (s2!=other)
170      return false;
171    // Check that nothing is left on stream
172    std::string s3;
173    ss >> s3;
174    return s3.empty();
175  }
176
177
178  bool is_float(const std::string& s)
179  {
180    return is<float>(s);
181  }
182
183
184  bool is_int(const std::string& s)
185  {
186    return is<int>(s);
187  }
188
189  bool is_nan(const std::string& s)
190  {
191    return is_equal(s, "nan");
192  }
193
194
195  void mkdir(const std::string& dir, mode_t mode)
196  {
197    int code = ::mkdir(dir.c_str(), mode);
198    if (code){
199      std::stringstream ss;
200      ss << "mkdir: '" << dir << "': ";
201      throw errno_error(ss.str());
202    }
203  }
204
205
206  void mkdir_p(const std::string& dir, mode_t mode)
207  {
208    if (FileUtil(dir).exists())
209      return;
210    mkdir_p(dirname(dir), mode);
211    mkdir(dir, mode);
212  }
213
214
215  void print_what(const std::exception& error, std::ostream& out)
216  {
217    // implemented as example at
218    // http://www.cplusplus.com/reference/exception/rethrow_if_nested/
219    out << error.what() << "\n";
220    try {
221      std::rethrow_if_nested(error);
222    }
223    catch (const std::exception& nested) {
224      print_what(nested, out);
225    }
226  }
227
228
229  void remove(const std::string& fn)
230  {
231    if (::remove(fn.c_str())) {
232      std::string msg("remove: '");
233      msg += fn;
234      msg += "': ";
235      throw errno_error(msg);
236    }
237  }
238
239
240  void rename(const std::string& from, const std::string& to)
241  {
242    if (::rename(from.c_str(), to.c_str())) {
243      std::stringstream ss;
244      ss << "rename '" << from << "' to '" << to << "': ";
245      throw errno_error(ss.str());
246    }
247  }
248
249
250  void replace(std::string& str, std::string old_value, std::string new_value)
251  {
252    assert(old_value.size());
253    std::string result;
254    std::back_insert_iterator<std::string> out(result);
255    std::string::iterator c = str.begin();
256    while (c!=str.end()) {
257      if (str.end() - c >= static_cast<int>(old_value.size()) &&
258          std::equal(old_value.begin(), old_value.end(), c)) {
259        std::copy(new_value.begin(), new_value.end(), out);
260        c += old_value.size();
261      }
262      else {
263        *out = *c;
264        ++c;
265      }
266    }
267    str.swap(result);
268  }
269
270
271  void symlink(const std::string& path1, const std::string& path2)
272  {
273    if (::symlink(path1.c_str(), path2.c_str())) {
274      std::string msg("symlink: '");
275      msg += path1;
276      msg += "' -> '";
277      msg += path2;
278      msg += "': ";
279      throw errno_error(msg);
280    }
281  }
282
283
284}}} // end of namespace utility, yat and thep
Note: See TracBrowser for help on using the repository browser.