source: trunk/lib/utility.cc @ 796

Last change on this file since 796 was 796, checked in by Peter Johansson, 12 years ago

added a function mkdir_p(1)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 7.9 KB
RevLine 
[62]1// $Id: utility.cc 796 2009-07-01 00:55:02Z peter $
2
[84]3/*
[755]4  Copyright (C) 2006, 2007, 2009 Jari Häkkinen, Peter Johansson
[796]5  Copyright (C) 2008, 2009 Peter Johansson
[84]6
[687]7  This file is part of svndigest, http://dev.thep.lu.se/svndigest
[84]8
[149]9  svndigest is free software; you can redistribute it and/or modify it
[84]10  under the terms of the GNU General Public License as published by
[693]11  the Free Software Foundation; either version 3 of the License, or
[84]12  (at your option) any later version.
13
[149]14  svndigest is distributed in the hope that it will be useful, but
[84]15  WITHOUT ANY WARRANTY; without even the implied warranty of
[149]16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
[84]17  General Public License for more details.
18
19  You should have received a copy of the GNU General Public License
[693]20  along with svndigest. If not, see <http://www.gnu.org/licenses/>.
[84]21*/
22
[62]23#include "utility.h"
24
[620]25#include "subversion_info.h"
26#include "config.h"
27
[516]28#include <cassert>
[482]29#include <cerrno> 
[755]30#include <cstdio>
[198]31#include <cstdlib>
[755]32#include <cstring>
[62]33#include <fstream>
34#include <sstream>
[151]35#include <stdexcept>
[62]36#include <string>
[115]37#include <sys/param.h>
[705]38#include <sys/stat.h>
[115]39#include <unistd.h>
[62]40
[201]41#include <iostream>
42
[62]43namespace theplu{
[149]44namespace svndigest{
[62]45
[151]46  int access_rights(const std::string& path, const std::string& bits)
47  {
[163]48    if (access(path.c_str(),F_OK)) {
[151]49      throw std::runtime_error(std::string("access_rights: ") + path +
50                               "' does not exist.");
51    }
52    int mode=0;
[589]53    for (unsigned int i=0; i<bits.length(); ++i)
[151]54      switch (bits[i]) {
55          case 'r':
56            mode|=R_OK;
57            break;
58          case 'w':
59            mode|=W_OK;
60            break;
61          case 'x':
62            mode|=X_OK;
63            break;
64      }
65    return access(path.c_str(),mode);
66  }
67
68
[705]69  std::string concatenate_path(std::string dir, std::string base)
70  {
[709]71    if (dir.empty() || dir==".")
[705]72      return base;
73    if (dir[dir.size()-1]!='/')
74      dir.append("/");
75    return dir+base;
76  }
77
78
[462]79  void copy_file(const std::string& source, const std::string& target)
80  {
81    std::ofstream o(target.c_str());
82    std::ifstream i(source.c_str());
83    while (i.good()) {
84      char ch=i.get();
85      if (i.good())
86        o.put(ch);
87      if (!o.good())
88        throw std::runtime_error(std::string("copy_file: ") +
89                                 "writing target file failed '" + target + "'");
90    }
91    if (!i.eof() && (i.bad() || i.fail()))  // fail on everything except eof
92      throw std::runtime_error(std::string("copy_file: ") +
93                               "error reading source file '" + source + "'");
94    i.close(); o.close();
95  }
96
97
[482]98  std::string directory_name(std::string path)
99  {
100    size_t pos = path.find_last_of("/");
[705]101    if (pos==std::string::npos)
102      return ".";
[482]103    if (pos==path.size()-1)
104      return directory_name(path.substr(0,path.size()-2));
105    return path.substr(0,pos+1);
106  }
107
108
[507]109  bool equal(std::string::const_iterator first1, 
110             std::string::const_iterator end1,
111             std::string::const_iterator first2,
112             std::string::const_iterator end2)
113  {
114    if (first1==end1 && first2==end2)
115      return true;
116    if (first1!=end1 && first2!=end2 && 
[508]117        (*first1==*first2 || *first1=='*' || *first2=='*' ||
118         *first1=='?' || *first2=='?') && 
[507]119        equal(first1+1, end1, first2+1, end2) )
120      return true;
[523]121    if ( (first1!=end1 && first2!=end2 && (*first1=='*'|| *first2=='*') ) && 
122         (equal(first1+1, end1, first2, end2) || 
123          equal(first1, end1, first2+1, end2))
124         )
[507]125      return true;
126    return false;
127  }
128
129
[100]130  std::string file_name(const std::string& full_path)
131  {
132    std::stringstream ss(full_path);
133    std::string name;
134    while (getline(ss,name,'/')) {}
135    return name;
136  }
137
[151]138
[198]139  std::string getenv(const std::string& var)
140  {
141    char* buffer=std::getenv(var.c_str());
142    if (!buffer)
143      throw std::runtime_error("Environment variable "+var+" is not set");
144    return std::string(buffer);
145  }
146
147
[589]148  std::string hex(int x, unsigned int width)
[373]149  {
150    std::stringstream ss;
151    ss << std::hex << x;
152    if (!width)
153      return ss.str();
154    if (ss.str().size()<width) 
155      return std::string(width-ss.str().size(), '0') + ss.str();
156    return ss.str().substr(0, width);
157  }
158
159
[226]160  std::string htrim(std::string str)
161  {
162    size_t length=str.size();
163    while(length && isspace(str[length-1]))
164      --length;
165    return str.substr(0,length);
166  }
167
168
169  std::string ltrim(std::string str)
170  {
171    size_t i = 0;
172    while(i<str.size() && isspace(str[i]))
173      ++i;
174    return str.substr(i);
175  }
176
[482]177  void mkdir(const std::string& dir)
178  { 
179    int code = ::mkdir(dir.c_str(),0777);
180    if (code){
181      std::stringstream ss;
[750]182      ss << "mkdir(" << dir << "): failed\n" << strerror(errno);
[482]183      throw std::runtime_error(ss.str());
184    }
[313]185  }
186
187
[796]188  void mkdir_p(const std::string& dir)
189  { 
190    std::string mother = directory_name(dir);
191    if (!node_exist(mother))
192      mkdir_p(mother);
193    if (!node_exist(dir))
194      mkdir(dir);
195  }
196
197
[226]198  bool node_exist(const std::string& path)
199  {
200    struct stat buf;
201    return !stat(path.c_str(),&buf);
202  }
203
204
[482]205  int percent(int a, int b)
206  {
207    if (b)
208      return (100*a)/b;
209    return 0;
210  }
211
212
[115]213  std::string pwd(void)
214  {
215    char buffer[MAXPATHLEN];
[151]216    if (!getcwd(buffer, MAXPATHLEN))
217      throw std::runtime_error("Failed to get current working directory");
[115]218    return std::string(buffer);
219  }
220
[297]221
[516]222  bool regexp(std::string::const_iterator first1, 
223              std::string::const_iterator last1,
224              std::string::const_iterator first2,
225              std::string::const_iterator last2,
226              std::vector<std::string>& vec)
227  {
228    if (vec.empty())
229      vec.push_back("");
230
231    // first two cases when ranges are empty
232    if (first1==last1 && first2==last2){
233      vec.pop_back();
234      return true;
235    }
236    if (first1==last1 || first2==last2)
237      return false;
238
239    // then we take care of the real stuff
240    if (*first2 == '*'){
241      // trying '*' to consume another character
242      vec.back().append(1, *first1);
243      if (regexp(first1+1, last1, first2, last2, vec) )
244        return true;
245      assert(vec.back().size());
246      vec.back().resize(vec.back().size()-1);
247
248      // stepping away from the '*'
249      vec.push_back("");
250      if (regexp(first1, last1, first2+1, last2, vec)) 
251        return true;
252      vec.pop_back();
253      return false;
254    }
255    else if (*first2 == '?'){
256      // eating a character
257      vec.back() = std::string(first1, first1+1);
258      vec.push_back("");
259      if (regexp(first1+1, last1, first2+1, last2, vec) )
260        return true;
261      vec.pop_back();
262      // ? interpreted as zero characters
263      vec.back() = "";
264      vec.push_back("");
265      if (regexp(first1, last1, first2+1, last2, vec) )
266        return true;
267      vec.pop_back();
268      return false;
269    }
270    if (*first1 != *first2)
271      return false;
272    return regexp(++first1, last1, ++first2, last2, vec);
273  }
274
275
[514]276  void replace(std::string& str, std::string old_str, std::string new_str)
277  {
278    std::string::iterator iter(str.begin());
279    while ((iter=search(iter, str.end(), old_str)) != str.end()) {
280      size_t i = iter-str.begin();
281      str = std::string(str.begin(), iter) + new_str + 
282        std::string(iter+old_str.size(), str.end());
283      // pointing to char after substr we just inserted
284      iter = str.begin() + (i+new_str.size()); 
285    }
286  }
287
288
[297]289  void touch(std::string str)
290  {
291    if (!node_exist(str)) {
292      std::ofstream os(str.c_str());
293      os.close();
294    }
295  }
296
[201]297  time_t str2time(const std::string& str)
298  {
299    //  str in format 2006-09-09T10:55:52.132733Z
300    std::stringstream sstream(str);
301    time_t rawtime;
302    struct tm * timeinfo;
303    time ( &rawtime );
304    timeinfo =  gmtime ( &rawtime );
305
[589]306    unsigned int year, month, day, hour, minute, second;
[201]307    std::string tmp;
308    getline(sstream,tmp,'-');
309    year=atoi(tmp.c_str());
310    timeinfo->tm_year = year - 1900;
311
312    getline(sstream,tmp,'-');
313    month=atoi(tmp.c_str());
314    timeinfo->tm_mon = month - 1;
315
316    getline(sstream,tmp,'T');
317    day=atoi(tmp.c_str());
318    timeinfo->tm_mday = day;
319
320    getline(sstream,tmp,':');
321    hour=atoi(tmp.c_str());
322    timeinfo->tm_hour = hour;
323
324    getline(sstream,tmp,':');
325    minute=atoi(tmp.c_str());
326    timeinfo->tm_min = minute;
327
328    getline(sstream,tmp,'.');
329    second=atoi(tmp.c_str());
330    timeinfo->tm_sec = second;
331
332    return mktime(timeinfo);
333  }
334
335
[309]336  std::string match(std::string::const_iterator& first,
337                    const std::string::const_iterator& last,
338                    std::string str)
339  {
340    if (match_begin(first, last, str)){
341      first+=str.size();
342      return str;
343    }
344    return std::string();
345  }
346
[149]347}} // end of namespace svndigest and namespace theplu
Note: See TracBrowser for help on using the repository browser.