yat/utility/utility.cc

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