source: trunk/yat/utility/utility.cc

Last change on this file was 4359, checked in by Peter, 6 weeks ago

update copyright years using svndigest 0.11 (in contrast to 0.10.x previously)

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