gambit is hosted by Hepforge, IPPP Durham
GAMBIT  v1.5.0-2191-ga4742ac
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 
60  {
61  static const str path = construct_runtime_scratch();
62  return path;
63  }
64 
68  #ifdef WITH_MPI
69  fail_on_mpi_uninitialised
70  #endif
71  )
72  {
73  str master_procID;
74  #ifdef WITH_MPI
75  if (GMPI::Is_initialized() and not GMPI::Is_finalized())
76  {
77  master_procID = "/master_process_" + std::to_string(GMPI::Comm().MasterPID());
78  }
79  else
80  {
81  if (fail_on_mpi_uninitialised)
82  utils_error().raise(LOCAL_INFO, "Tried to call construct_runtime_scratch without MPI initialised!");
83  master_procID = "/unattached_MPI_process_" + std::to_string(getpid());
84  }
85  #else
86  master_procID = "/master_process_" + std::to_string(getpid());
87  #endif
88  return ensure_path_exists(GAMBIT_DIR "/scratch/run_time/machine_" + std::to_string(gethostid()) + master_procID + "/");
89  }
90 
93  std::vector<str> delimiterSplit(str s, str delim)
94  {
95  std::vector<str> vec;
96  // Get rid of any whitespace around the delimiters
97  std::regex rgx1("\\s+"+delim), rgx2(delim+"\\s+");
98  s = std::regex_replace(s, rgx1, delim);
99  s = std::regex_replace(s, rgx2, delim);
100  if (s == "") return vec;
101  // Split up the list of versions by the delimiters
102  boost::split(vec, s, boost::is_any_of(delim), boost::token_compress_on);
103  return vec;
104  }
105 
108  {
109  std::regex expression("(^|[\\s\\*\\&\\(\\,\\[])"+ns+"::");
110  s = std::regex_replace(s, expression, str("$1"));
111  return s;
112  }
113 
116  {
117  std::regex expression("(^|[\\s\\*\\&\\(\\,\\[])"+ns+"::");
118  s = std::regex_replace(s, expression, str("$1")+ns_new+"::");
119  return s;
120  }
121 
124  {
125  str tempstr("__TEMP__"), empty(""), constdec2("const ");
126  std::regex constdec1("const\\s+"), temp(tempstr), whitespace("\\s+");
127  s = std::regex_replace(s, constdec1, tempstr);
128  s = std::regex_replace(s, whitespace, empty);
129  s = std::regex_replace(s, temp, constdec2);
130  }
131 
134  {
135  if (s.at(0) == '(') s = s.substr(1, s.size());
136  if (*s.rbegin() == ')') s = s.substr(0, s.size()-1);
137  }
138 
140  bool sspairset_contains(const str& el, const std::set<std::pair<str,str>>& set)
141  {
142  for (std::pair<str,str> x : set) { if (x.first == el) return true; }
143  return false;
144  }
145 
147  bool sspairset_contains(const str& el1, const str& el2, const std::set<std::pair<str,str>>& set)
148  {
149  return sspairset_contains(std::pair<str,str>(el1, el2), set);
150  }
151 
153  bool sspairset_contains(const sspair& quantity, const std::set<sspair>& set)
154  {
155  return std::find(set.begin(), set.end(), quantity) != set.end();
156  }
157 
159  str str_fixed_len(str s, int len)
160  {
161  int oldlen = s.length();
162  if (oldlen > len)
163  {
164  return s.substr(0,len-1);
165  }
166  else if (oldlen < len)
167  {
168  s.append(len-oldlen,' ');
169  }
170  return s;
171  }
172 
175  bool isInteger(const std::string & s)
176  {
177  if(s.empty() || ((!isdigit(s[0])) && (s[0] != '-') && (s[0] != '+'))) return false ;
178 
179  char * p ;
180  strtol(s.c_str(), &p, 10) ;
181 
182  return (*p == 0) ;
183  }
184 
186  void strcpy2f(char* arr, int len, str s)
187  {
188  s = str_fixed_len(s, len-1);
189  strcpy(arr, s.c_str());
190  arr[len-1] = ' ';
191  }
192 
195  bool iequals(const std::string& a, const std::string& b, bool case_sensitive)
196  {
197  if(case_sensitive)
198  return a==b;
199  unsigned int sz = a.size();
200  if (b.size() != sz)
201  return false;
202  for (unsigned int i = 0; i < sz; ++i)
203  if (tolower(a[i]) != tolower(b[i]))
204  return false;
205  return true;
206  }
207 
209  std::vector<std::string> split(const std::string& input, const std::string& delimiter)
210  {
211  std::vector<std::string> result;
212  boost::iter_split(result, input, boost::algorithm::first_finder(delimiter));
213  return result;
214  }
215 
217  std::string strtolower(const std::string& a)
218  {
219  unsigned int sz = a.size();
220  std::string b = a;
221  for (unsigned int i = 0; i < sz; ++i)
222  { b[i] = tolower(a[i]); }
223  return b;
224  }
225 
227  const std::string& ensure_path_exists(const std::string& path)
228  {
229  // Split off potential filename
230  // If only path is provided, it must end in a slash!!!
231  size_t found = path.find_last_of("/\\");
232  if (found != std::string::npos)
233  {
234  std::string prefix = path.substr(0,found);
235  recursive_mkdir( prefix.c_str() );
236  }
237  return path;
238  }
239 
241  bool file_exists(const std::string& filename)
242  {
243  //std::ifstream file(filename);
244  //return not file.fail();
245  struct stat buffer;
246  return (stat(filename.c_str(), &buffer) == 0);
247  }
248 
251  std::vector<std::string> ls_dir(const std::string& dir)
252  {
253  std::vector<std::string> dir_contents;
254  DIR *dp;
255  struct dirent *ep;
256  dp = opendir(dir.c_str());
257 
258  if( dp != NULL )
259  {
260  while( (ep = readdir(dp)) )
261  {
262  dir_contents.push_back(ep->d_name);
263  }
264  (void) closedir(dp);
265  }
266  else
267  {
268  std::string msg = "Utils::ls_dir function failed to open the directory '"+dir+"'!";
269  std::cerr << msg << std::endl;
270  abort();
271  }
272  return dir_contents;
273  }
274 
276  std::string dir_name(const std::string& path)
277  {
278  char buffer[1000]; // temporary buffer for dirname to work with (it is a C function)
279  path.copy(buffer, path.size()); //TODO: error if path.size()>1000
280  buffer[path.size()] = '\0';
281  std::string result = dirname(&buffer[0]); // should use the C function...
282  return result;
283  }
284 
286  std::string base_name(const std::string& path)
287  {
288  char buffer[1000]; // temporary buffer for basename to work with (it is a C function)
289  path.copy(buffer, path.size()); //TODO: error if path.size()>1000
290  buffer[path.size()] = '\0';
291  std::string result = basename(&buffer[0]); // should use the C function...
292  return result;
293  }
294 
296  int remove_all_files_in(const str& dirname, bool error_if_absent)
297  {
298  struct dirent *pDirent;
299  DIR *pDir;
300  pDir = opendir(dirname.c_str());
301  if (pDir == NULL)
302  {
303  if (error_if_absent)
304  {
305  utils_error().raise(LOCAL_INFO, "Directory "+dirname+" not found.");
306  }
307  else
308  {
309  return 1;
310  }
311  }
312  while ( (pDirent = readdir(pDir)) != NULL )
313  {
314  // Delete the contents
315  if ( strcmp(pDirent->d_name, ".") and strcmp(pDirent->d_name, "..") )
316  {
317  std::ostringstream ss;
318  ss << dirname << pDirent->d_name;
319  cout << "Deleting " << ss.str() << endl;
320  remove(ss.str().c_str());
321  }
322  }
323  closedir (pDir);
324  return 0;
325  }
326 
329  {
330  return std::chrono::system_clock::now();
331  }
332 
334  std::string return_time_and_date(const time_point& in)
335  {
336  std::time_t t = std::chrono::system_clock::to_time_t(in);
337 
338  std::string ts = std::ctime(&t); // for example : Tue Sep 27 14:21:13 2011\n
339  ts.resize(ts.size()-1); // Remove the annoying trailing newline
340  return ts;
341  }
342 
345  bool are_similar(const std::string& s1, const std::string& s2)
346  {
347  if(check1(s1,s2) or check1(s2,s1)){ return true; }
348  else if(check2(s1,s2)){ return true; } // symmetric
349  else{ return false; }
350  //TODO: Add more checks? These ones are pretty minimal. Maybe something that computes percentage match between strings...
351  }
352 
354  bool check1(const std::string& s1, const std::string& s2)
355  {
356  if(s2.length() - s1.length() != 1){ return false; }
357  unsigned int i,j;
358  for(i=0,j=0; i<s2.length(); i++,j++)
359  {
360  if(s2[i] == s1[j])
361  {/*do nothing*/}
362  else if(i == j)
363  { j++;}
364  else
365  {return false;}
366  }
367  return true;
368  }
369 
371  bool check2(const std::string& s1, const std::string& s2)
372  {
373  unsigned int error_limit = 2;
374  unsigned int number_of_errors = 0;
375 
376  if(s2.length() != s1.length()){ return false; }
377  unsigned int i,j;
378  for(i=0,j=0; i<s2.length(); i++,j++)
379  {
380  if(s2[i] == s1[j])
381  {/*do nothing*/}
382  else if(number_of_errors <= error_limit)
383  { number_of_errors++;}
384  else
385  {return false;}
386  }
387  return true;
388  }
389 
391  double sqr(double a)
392  {
393  return a * a;
394  }
395 
397  // credit: http://stackoverflow.com/a/41041484/1447953
398  bool endsWith(const std::string& str, const std::string& suffix)
399  {
400  if (&suffix == &str) return true; // str and suffix are the same string
401  if (suffix.length() > str.length()) return false;
402  size_t delta = str.length() - suffix.length();
403  for (size_t i = 0; i < suffix.length(); ++i) {
404  if (suffix[i] != str[delta + i]) return false;
405  }
406  return true;
407  }
408 
409  // Inspired by the above. Checks whether 'str' begins with 'prefix'
410  bool startsWith(const std::string& str, const std::string& prefix, bool case_sensitive)
411  {
412  if (&prefix == &str) return true; // str and prefix are the same string
413  if (prefix.length() > str.length()) return false;
414  for (size_t i = 0; i < prefix.length(); ++i) {
415  if(case_sensitive)
416  {
417  if (prefix[i] != str[i]) return false;
418  }
419  else
420  {
421  if (tolower(prefix[i]) != tolower(str[i])) return false;
422  }
423  }
424  return true;
425  }
426 
427 
428  }
429 
430 }
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
EXPORT_SYMBOLS std::string strtolower(const std::string &a)
Convert a whole string to lowercase.
#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.
EXPORT_SYMBOLS str construct_runtime_scratch(bool fail_on_mpi_uninitialised=true)
Construct the path to the run-specific scratch directory This version is safe to call from a destruct...
START_MODEL b
Definition: demo.hpp:270
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 to the run-specific scratch directory Don&#39;t call this from a destructor, as the internal static str may have already been destroyed.
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...