gambit is hosted by Hepforge, IPPP Durham
GAMBIT  v1.5.0-252-gf9a3f78
a Global And Modular Bsm Inference Tool
util_functions.cpp
Go to the documentation of this file.
1 // GAMBIT: Global and Modular BSM Inference Tool
2 // *********************************************
21 
23 #include <cstring>
24 #include <chrono> // chrono::system_clock
25 #include <ctime> // localtime
26 #include <cctype> // ::tolower function
27 #include <sstream> // stringstream
28 #include <string> // string
29 #include <regex> // regular expressions
30 
32 #include <stdio.h>
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <dirent.h>
36 #include <libgen.h>
37 #include <unistd.h>
38 
41 #include "gambit/cmake/cmake_variables.hpp"
43 
45 #include <boost/algorithm/string/iter_find.hpp>
46 #include <boost/algorithm/string/finder.hpp>
47 #include <boost/algorithm/string/replace.hpp>
48 
49 namespace Gambit
50 {
51 
52  namespace Utils
53  {
54 
55  const char* whitespaces[] = {" ", "\t", "\n", "\f", "\r"};
56 
59  {
60  #ifdef WITH_MPI
61  static const str master_procID = std::to_string(GMPI::Comm().MasterPID());
62  #else
63  static const str master_procID = std::to_string(getpid());
64  #endif
65  static const str path = ensure_path_exists(GAMBIT_DIR "/scratch/run_time/machine_" + std::to_string(gethostid()) + "/master_process_" + master_procID + "/");
66  return path;
67  }
68 
71  std::vector<str> delimiterSplit(str s, str delim)
72  {
73  std::vector<str> vec;
74  // Get rid of any whitespace around the delimiters
75  std::regex rgx1("\\s+"+delim), rgx2(delim+"\\s+");
76  s = std::regex_replace(s, rgx1, delim);
77  s = std::regex_replace(s, rgx2, delim);
78  if (s == "") return vec;
79  // Split up the list of versions by the delimiters
80  boost::split(vec, s, boost::is_any_of(delim), boost::token_compress_on);
81  return vec;
82  }
83 
86  {
87  std::regex expression("(^|[\\s\\*\\&\\(\\,\\[])"+ns+"::");
88  s = std::regex_replace(s, expression, str("$1"));
89  return s;
90  }
91 
94  {
95  std::regex expression("(^|[\\s\\*\\&\\(\\,\\[])"+ns+"::");
96  s = std::regex_replace(s, expression, str("$1")+ns_new+"::");
97  return s;
98  }
99 
102  {
103  str tempstr("__TEMP__"), empty(""), constdec2("const ");
104  std::regex constdec1("const\\s+"), temp(tempstr), whitespace("\\s+");
105  s = std::regex_replace(s, constdec1, tempstr);
106  s = std::regex_replace(s, whitespace, empty);
107  s = std::regex_replace(s, temp, constdec2);
108  }
109 
112  {
113  if (s.at(0) == '(') s = s.substr(1, s.size());
114  if (*s.rbegin() == ')') s = s.substr(0, s.size()-1);
115  }
116 
118  bool sspairset_contains(const str& el, const std::set<std::pair<str,str>>& set)
119  {
120  for (std::pair<str,str> x : set) { if (x.first == el) return true; }
121  return false;
122  }
123 
125  bool sspairset_contains(const str& el1, const str& el2, const std::set<std::pair<str,str>>& set)
126  {
127  return sspairset_contains(std::pair<str,str>(el1, el2), set);
128  }
129 
131  bool sspairset_contains(const sspair& quantity, const std::set<sspair>& set)
132  {
133  return std::find(set.begin(), set.end(), quantity) != set.end();
134  }
135 
137  str str_fixed_len(str s, int len)
138  {
139  int oldlen = s.length();
140  if (oldlen > len)
141  {
142  return s.substr(0,len-1);
143  }
144  else if (oldlen < len)
145  {
146  s.append(len-oldlen,' ');
147  }
148  return s;
149  }
150 
153  bool isInteger(const std::string & s)
154  {
155  if(s.empty() || ((!isdigit(s[0])) && (s[0] != '-') && (s[0] != '+'))) return false ;
156 
157  char * p ;
158  strtol(s.c_str(), &p, 10) ;
159 
160  return (*p == 0) ;
161  }
162 
164  void strcpy2f(char* arr, int len, str s)
165  {
166  s = str_fixed_len(s, len-1);
167  strcpy(arr, s.c_str());
168  arr[len-1] = ' ';
169  }
170 
173  bool iequals(const std::string& a, const std::string& b, bool case_sensitive)
174  {
175  if(case_sensitive)
176  return a==b;
177  unsigned int sz = a.size();
178  if (b.size() != sz)
179  return false;
180  for (unsigned int i = 0; i < sz; ++i)
181  if (tolower(a[i]) != tolower(b[i]))
182  return false;
183  return true;
184  }
185 
187  std::vector<std::string> split(const std::string& input, const std::string& delimiter)
188  {
189  std::vector<std::string> result;
190  boost::iter_split(result, input, boost::algorithm::first_finder(delimiter));
191  return result;
192  }
193 
194 
196  const std::string& ensure_path_exists(const std::string& path)
197  {
198  // Split off potential filename
199  // If only path is provided, it must end in a slash!!!
200  size_t found = path.find_last_of("/\\");
201  if (found != std::string::npos)
202  {
203  std::string prefix = path.substr(0,found);
204  recursive_mkdir( prefix.c_str() );
205  }
206  return path;
207  }
208 
210  bool file_exists(const std::string& filename)
211  {
212  //std::ifstream file(filename);
213  //return not file.fail();
214  struct stat buffer;
215  return (stat(filename.c_str(), &buffer) == 0);
216  }
217 
220  std::vector<std::string> ls_dir(const std::string& dir)
221  {
222  std::vector<std::string> dir_contents;
223  DIR *dp;
224  struct dirent *ep;
225  dp = opendir(dir.c_str());
226 
227  if( dp != NULL )
228  {
229  while( (ep = readdir(dp)) )
230  {
231  dir_contents.push_back(ep->d_name);
232  }
233  (void) closedir(dp);
234  }
235  else
236  {
237  std::string msg = "Utils::ls_dir function failed to open the directory '"+dir+"'!";
238  std::cerr << msg << std::endl;
239  abort();
240  }
241  return dir_contents;
242  }
243 
245  std::string dir_name(const std::string& path)
246  {
247  char buffer[1000]; // temporary buffer for dirname to work with (it is a C function)
248  path.copy(buffer, path.size()); //TODO: error if path.size()>1000
249  buffer[path.size()] = '\0';
250  std::string result = dirname(&buffer[0]); // should use the C function...
251  return result;
252  }
253 
255  std::string base_name(const std::string& path)
256  {
257  char buffer[1000]; // temporary buffer for basename to work with (it is a C function)
258  path.copy(buffer, path.size()); //TODO: error if path.size()>1000
259  buffer[path.size()] = '\0';
260  std::string result = basename(&buffer[0]); // should use the C function...
261  return result;
262  }
263 
265  int remove_all_files_in(const str& dirname, bool error_if_absent)
266  {
267  struct dirent *pDirent;
268  DIR *pDir;
269  pDir = opendir(dirname.c_str());
270  if (pDir == NULL)
271  {
272  if (error_if_absent)
273  {
274  utils_error().raise(LOCAL_INFO, "Directory "+dirname+" not found.");
275  }
276  else
277  {
278  return 1;
279  }
280  }
281  while ( (pDirent = readdir(pDir)) != NULL )
282  {
283  // Delete the contents
284  if ( strcmp(pDirent->d_name, ".") and strcmp(pDirent->d_name, "..") )
285  {
286  std::ostringstream ss;
287  ss << dirname << pDirent->d_name;
288  cout << "Deleting " << ss.str() << endl;
289  remove(ss.str().c_str());
290  }
291  }
292  closedir (pDir);
293  return 0;
294  }
295 
298  {
299  return std::chrono::system_clock::now();
300  }
301 
303  std::string return_time_and_date(const time_point& in)
304  {
305  std::time_t t = std::chrono::system_clock::to_time_t(in);
306 
307  std::string ts = std::ctime(&t); // for example : Tue Sep 27 14:21:13 2011\n
308  ts.resize(ts.size()-1); // Remove the annoying trailing newline
309  return ts;
310  }
311 
314  bool are_similar(const std::string& s1, const std::string& s2)
315  {
316  if(check1(s1,s2) or check1(s2,s1)){ return true; }
317  else if(check2(s1,s2)){ return true; } // symmetric
318  else{ return false; }
319  //TODO: Add more checks? These ones are pretty minimal. Maybe something that computes percentage match between strings...
320  }
321 
323  bool check1(const std::string& s1, const std::string& s2)
324  {
325  if(s2.length() - s1.length() != 1){ return false; }
326  unsigned int i,j;
327  for(i=0,j=0; i<s2.length(); i++,j++)
328  {
329  if(s2[i] == s1[j])
330  {/*do nothing*/}
331  else if(i == j)
332  { j++;}
333  else
334  {return false;}
335  }
336  return true;
337  }
338 
340  bool check2(const std::string& s1, const std::string& s2)
341  {
342  unsigned int error_limit = 2;
343  unsigned int number_of_errors = 0;
344 
345  if(s2.length() != s1.length()){ return false; }
346  unsigned int i,j;
347  for(i=0,j=0; i<s2.length(); i++,j++)
348  {
349  if(s2[i] == s1[j])
350  {/*do nothing*/}
351  else if(number_of_errors <= error_limit)
352  { number_of_errors++;}
353  else
354  {return false;}
355  }
356  return true;
357  }
358 
360  double sqr(double a)
361  {
362  return a * a;
363  }
364 
366  // credit: http://stackoverflow.com/a/41041484/1447953
367  bool endsWith(const std::string& str, const std::string& suffix)
368  {
369  if (&suffix == &str) return true; // str and suffix are the same string
370  if (suffix.length() > str.length()) return false;
371  size_t delta = str.length() - suffix.length();
372  for (size_t i = 0; i < suffix.length(); ++i) {
373  if (suffix[i] != str[delta + i]) return false;
374  }
375  return true;
376  }
377 
378  // Inspired by the above. Checks whether 'str' begins with 'prefix'
379  bool startsWith(const std::string& str, const std::string& prefix, bool case_sensitive)
380  {
381  if (&prefix == &str) return true; // str and prefix are the same string
382  if (prefix.length() > str.length()) return false;
383  for (size_t i = 0; i < prefix.length(); ++i) {
384  if(case_sensitive)
385  {
386  if (prefix[i] != str[i]) return false;
387  }
388  else
389  {
390  if (tolower(prefix[i]) != tolower(str[i])) return false;
391  }
392  }
393  return true;
394  }
395 
396 
397  }
398 
399 }
EXPORT_SYMBOLS str dir_name(const str &path)
Get directory name from full path+filename (POSIX)
EXPORT_SYMBOLS std::vector< std::string > split(const std::string &input, const std::string &delimiter)
Split string into vector of strings, using a delimiter string.
EXPORT_SYMBOLS str replace_leading_namespace(str s, str ns, str ns_new)
Replaces a namespace at the start of a string, or after "const".
EXPORT_SYMBOLS error & utils_error()
Utility errors.
Funk delta(std::string arg, double pos, double width)
Definition: daFunk.hpp:902
std::chrono::time_point< std::chrono::system_clock > time_point
Definition: logging.hpp:46
#define LOCAL_INFO
Definition: local_info.hpp:34
EXPORT_SYMBOLS void strip_parentheses(str &)
Strips leading and/or trailing parentheses from a string.
EXPORT_SYMBOLS bool sspairset_contains(const str &, const std::set< sspair > &)
Test if a set of str,str pairs contains any entry with first element matching a given string...
const char * whitespaces[]
EXPORT_SYMBOLS bool isInteger(const std::string &)
Check if a string represents an integer From: http://stackoverflow.com/a/2845275/1447953.
START_MODEL b
Definition: demo.hpp:235
EXPORT_SYMBOLS std::vector< str > ls_dir(const str &dir)
Return a vector of strings listing the contents of a directory (POSIX)
EXPORT_SYMBOLS double sqr(double a)
returns square of double - saves tedious repetition
std::pair< str, str > sspair
Shorthand for a pair of standard strings.
Definition: util_types.hpp:64
General small utility functions.
EXPORT_SYMBOLS bool endsWith(const std::string &str, const std::string &suffix)
Checks whether `str&#39; ends with `suffix&#39;.
EXPORT_SYMBOLS str return_time_and_date(const time_point &in)
Get date and time.
EXPORT_SYMBOLS void strcpy2f(char *, int, str)
Copy a str to a character array, stripping the null termination character.
EXPORT_SYMBOLS bool startsWith(const std::string &str, const std::string &prefix, bool case_sensitive=true)
Checks whether `str&#39; begins with `prefix&#39;.
bool check2(const str &s1, const str &s2)
Sub-check for are_similar.
EXPORT_SYMBOLS bool file_exists(const std::string &filename)
Check if a file exists.
EXPORT_SYMBOLS int remove_all_files_in(const str &dirname, bool error_if_absent=true)
Delete all files in a directory (does not act recursively)
EXPORT_SYMBOLS void strip_whitespace_except_after_const(str &)
Strip all whitespace except that following "const", in which case the whitespace is replaced by a sin...
EXPORT_SYMBOLS bool iequals(const std::string &a, const std::string &b, bool case_sensitive=false)
Perform a (possibly) case-insensitive string comparison.
EXPORT_SYMBOLS str base_name(const str &path)
Get file name from full path+filename (POSIX)
hb_ModelParameters void
std::string str
Shorthand for a standard string.
Definition: Analysis.hpp:35
EXPORT_SYMBOLS const str & ensure_path_exists(const str &)
Ensure that a path exists (and then return the path, for chaining purposes)
EXPORT_SYMBOLS const str & runtime_scratch()
Return the path the the run-specific scratch directory.
A simple C++ wrapper for the MPI C bindings.
EXPORT_SYMBOLS std::vector< str > delimiterSplit(str s, str delim)
Split a string into a vector of strings, using a delimiter, and removing any whitespace around the de...
bool check1(const str &s1, const str &s2)
Sub-check for are_similar.
EXPORT_SYMBOLS str strip_leading_namespace(str s, str ns)
Strips namespace from the start of a string, or after "const".
EXPORT_SYMBOLS str str_fixed_len(str, int)
Created a str of a specified length.
std::vector< T > vec(std::vector< T > vector)
Definition: daFunk.hpp:142
TODO: see if we can use this one:
Definition: Analysis.hpp:33
time_point get_clock_now()
Get clock time.
EXPORT_SYMBOLS bool are_similar(const str &s1, const str &s2)
Check if two strings are a "close" match Used for "did you mean?" type checking during command line a...