source: trunk/lib/utility.cc

Last change on this file was 1571, checked in by Peter Johansson, 6 years ago

merge patch release 0.10.1 into trunk

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 8.9 KB
Line 
1// $Id: utility.cc 1571 2015-02-05 08:26:55Z peter $
2
3/*
4  Copyright (C) 2006, 2007, 2008, 2009 Jari Häkkinen, Peter Johansson
5  Copyright (C) 2010, 2011, 2012 Peter Johansson
6
7  This file is part of svndigest, http://dev.thep.lu.se/svndigest
8
9  svndigest is free software; you can redistribute it and/or modify it
10  under the terms of the GNU General Public License as published by
11  the Free Software Foundation; either version 3 of the License, or
12  (at your option) any later version.
13
14  svndigest is distributed in the hope that it will be useful, but
15  WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  General Public License for more details.
18
19  You should have received a copy of the GNU General Public License
20  along with svndigest. If not, see <http://www.gnu.org/licenses/>.
21*/
22
23#include <config.h>
24
25#include "utility.h"
26
27#include "yat/Exception.h"
28
29#include <cassert>
30#include <cstdio>
31#include <cstdlib>
32#include <cstring>
33#include <fnmatch.h>
34#include <fstream>
35#include <sstream>
36#include <stdexcept>
37#include <string>
38#include <sys/stat.h>
39#include <unistd.h>
40
41#include <iostream>
42
43#include <libgen.h>
44
45namespace theplu{
46namespace svndigest{
47
48  std::string absolute_path(const std::string& path)
49  {
50    if (is_absolute_path(path))
51      return path;
52    return concatenate_path(pwd(), path);
53  }
54
55  int access_rights(const std::string& path, const std::string& bits)
56  {
57    if (access(path.c_str(),F_OK)) {
58      throw std::runtime_error(std::string("access_rights: ") + path +
59                               "' does not exist.");
60    }
61    int mode=0;
62    for (unsigned int i=0; i<bits.length(); ++i)
63      switch (bits[i]) {
64          case 'r':
65            mode|=R_OK;
66            break;
67          case 'w':
68            mode|=W_OK;
69            break;
70          case 'x':
71            mode|=X_OK;
72            break;
73      }
74    return access(path.c_str(),mode);
75  }
76
77
78  void chdir(const std::string& dir)
79  {
80    if (::chdir(dir.c_str()) )
81      throw yat::utility::errno_error("chdir: " + dir + ":");
82  }
83
84
85  void chmod(const std::string& filename, mode_t mode)
86  {
87    if (::chmod(filename.c_str(), mode))
88      throw yat::utility::errno_error("chmod: ");
89  }
90
91
92  std::string concatenate_path(std::string dir, std::string base)
93  {
94    if (dir.empty() || dir==".")
95      return base;
96    if (dir[dir.size()-1]!='/')
97      dir.append("/");
98    return dir+base;
99  }
100
101
102  void copy_file(const std::string& source, const std::string& target)
103  {
104    std::ofstream o(target.c_str());
105    std::ifstream i(source.c_str());
106    while (i.good()) {
107      char ch=i.get();
108      if (i.good())
109        o.put(ch);
110      if (!o.good())
111        throw std::runtime_error(std::string("copy_file: ") +
112                                 "writing target file failed '" + target + "'");
113    }
114    if (!i.eof() && (i.bad() || i.fail()))  // fail on everything except eof
115      throw std::runtime_error(std::string("copy_file: ") +
116                               "error reading source file '" + source + "'");
117    i.close(); o.close();
118    // copy permissions
119    struct stat nodestat;
120    stat(source.c_str(),&nodestat);
121    chmod(target.c_str(), nodestat.st_mode);
122  }
123
124
125  std::string directory_name(const std::string& path)
126  {
127    if (path.size()==1) {
128      if (path=="/")
129        return path;
130      else
131        return ".";
132    }
133    assert(path.size()>=2);
134    size_t pos = path.find_last_of('/', path.size()-2);
135    if (pos==std::string::npos)
136      return ".";
137    if (pos==0)
138      return "/";
139    return path.substr(0,pos);
140    return "";
141  }
142
143
144  std::string file_name(const std::string& path)
145  {
146    if (path.size()==1)
147      return path;
148    size_t pos = path.find_last_of('/');
149    if (pos==std::string::npos)
150      return path;
151    if (pos==path.size()-1)
152      return file_name(path.substr(0, path.size()-1));
153    return path.substr(pos+1);
154  }
155
156
157  std::string getenv(const std::string& var)
158  {
159    char* buffer=std::getenv(var.c_str());
160    if (!buffer)
161      throw std::runtime_error("Environment variable "+var+" is not set");
162    return std::string(buffer);
163  }
164
165
166  std::string hex(int x, unsigned int width)
167  {
168    std::stringstream ss;
169    ss << std::hex << x;
170    if (!width)
171      return ss.str();
172    if (ss.str().size()<width)
173      return std::string(width-ss.str().size(), '0') + ss.str();
174    return ss.str().substr(0, width);
175  }
176
177
178  std::string htrim(std::string str)
179  {
180    size_t length=str.size();
181    while(length && isspace(str[length-1]))
182      --length;
183    return str.substr(0,length);
184  }
185
186
187  bool fnmatch(const std::string& pattern, const std::string& str)
188  {
189    int res = ::fnmatch(pattern.c_str(), str.c_str(), 0);
190    if (res==0)
191      return true;
192    if (res!=FNM_NOMATCH) {
193      std::stringstream ss;
194      ss << "fnmatch with args: " << pattern << ", " << str;
195      throw std::runtime_error(ss.str());
196    }
197    return false;
198  }
199
200
201  bool is_absolute_path(const std::string& path)
202  {
203    return path.size() && path[0]=='/';
204  }
205
206
207  void lstat(const std::string path, struct stat* nodestat)
208  {
209    int res = ::lstat(path.c_str(), nodestat);
210    if (res) {
211      throw yat::utility::errno_error("lstat: ");
212    }
213  }
214
215
216  std::string ltrim(std::string str)
217  {
218    size_t i = 0;
219    while(i<str.size() && isspace(str[i]))
220      ++i;
221    return str.substr(i);
222  }
223
224  void mkdir(const std::string& dir)
225  {
226    int code = ::mkdir(dir.c_str(),0777);
227    if (code){
228      std::stringstream ss;
229      ss << "mkdir: '" << dir << "': ";
230      throw yat::utility::errno_error(ss.str());
231    }
232  }
233
234
235  void mkdir_p(const std::string& dir)
236  {
237    if (node_exist(dir))
238      return;
239    std::string mother = directory_name(dir);
240    mkdir_p(mother);
241    mkdir(dir);
242  }
243
244
245  bool node_exist(const std::string& path)
246  {
247    struct stat buf;
248    return !stat(path.c_str(),&buf);
249  }
250
251
252  int percent(int a, int b)
253  {
254    if (b)
255      return (100*a)/b;
256    return 0;
257  }
258
259
260  std::string pwd(void)
261  {
262    char buffer[FILENAME_MAX];
263    if (!getcwd(buffer, FILENAME_MAX))
264      throw yat::utility::errno_error("pwd: ");
265    return std::string(buffer);
266  }
267
268
269  bool regexp(const std::string& pattern, const std::string& str,
270              std::vector<std::string>& vec)
271  {
272    bool regexp__(std::string::const_iterator first1,
273                  std::string::const_iterator last1,
274                  std::string::const_iterator first2,
275                  std::string::const_iterator last2,
276                  std::vector<std::string>::iterator item);
277
278    // find number of special chars
279    size_t count=0;
280    for (std::string::const_iterator i=pattern.begin(); i!=pattern.end(); ++i)
281      if (*i=='*' || *i=='?' || *i=='[')
282        ++count;
283    vec.resize(count);
284    return regexp__(pattern.begin(), pattern.end(), str.begin(), str.end(),
285                    vec.begin());
286  }
287
288  bool regexp__(std::string::const_iterator first1,
289                std::string::const_iterator last1,
290                std::string::const_iterator first2,
291                std::string::const_iterator last2,
292                std::vector<std::string>::iterator item)
293  {
294    if (first1==last1) {
295      return first2==last2;
296    }
297    if (*first1 == '*') {
298      if (first2<last2) {
299        item->push_back(*first2);
300        if (regexp__(first1, last1, first2+1, last2, item))
301          return true;
302        item->resize(item->size()-1);
303      }
304      return regexp__(first1+1, last1, first2, last2, item+1);
305    }
306    if (*first1 == '?') {
307      if (first2==last2)
308        return false;
309      *item = *first2;
310      return regexp__(first1+1, last1, first2+1, last2, item+1);
311    }
312    if (*first1 == '[') {
313      if (first2==last2)
314        return false;
315      while (*first1 != ']') {
316        if (*first1 == *first2) {
317          *item = *first2;
318        }
319        ++first1;
320        assert(first1!=last1);
321      }
322      return regexp__(first1+1, last1, first2+1, last2, item+1);
323    }
324
325    if (first2==last2)
326      return false;
327    if (*first1 != *first2)
328      return false;
329    return regexp__(first1+1, last1, first2+1, last2, item);
330  }
331
332
333  std::string relative_path(const std::string& abs_path,const std::string& dir)
334  {
335    if (abs_path == dir)
336      return ".";
337
338    if (abs_path.substr(0,dir.size())==dir) {
339      size_t pos = dir.size();
340      if (abs_path[pos] == '/') {
341        ++pos;
342        if (pos==abs_path.size())
343          return ".";
344      }
345      return abs_path.substr(pos);
346    }
347    assert(0 && "this case is not implemented");
348    return "";
349  }
350
351
352  void remove(const std::string& fn)
353  {
354    if (::remove(fn.c_str())) {
355      std::string msg("remove: ");
356      msg += fn;
357      throw yat::utility::errno_error(msg);
358    }
359  }
360
361
362  void rename(const std::string& from, const std::string to)
363  {
364    int code = ::rename(from.c_str(), to.c_str());
365    if (code){
366      std::stringstream ss;
367      ss << "rename" << from << " to " << to << ": ";
368      throw yat::utility::errno_error(ss.str());
369    }
370  }
371
372
373  void replace(std::string& str, std::string old_str, std::string new_str)
374  {
375    std::string::iterator iter(str.begin());
376    while ((iter=search(iter, str.end(), old_str)) != str.end()) {
377      size_t i = iter-str.begin();
378      str = std::string(str.begin(), iter) + new_str +
379        std::string(iter+old_str.size(), str.end());
380      // pointing to char after substr we just inserted
381      iter = str.begin() + (i+new_str.size());
382    }
383  }
384
385
386  void touch(std::string str)
387  {
388    if (!node_exist(str)) {
389      std::ofstream os(str.c_str());
390      os.close();
391    }
392  }
393
394
395  std::string match(std::string::const_iterator& first,
396                    const std::string::const_iterator& last,
397                    std::string str)
398  {
399    if (match_begin(first, last, str)){
400      first+=str.size();
401      return str;
402    }
403    return std::string();
404  }
405
406}} // end of namespace svndigest and namespace theplu
Note: See TracBrowser for help on using the repository browser.