SLProject  4.2.000
A platform independent 3D computer graphics framework for desktop OS, Android, iOS and online in web browsers
Utils.cpp
Go to the documentation of this file.
1 /**
2  * \file: Utils.cpp
3  * \brief Implementation of various utility functions defined in Utils.h
4  * \date May 2019
5  * \authors Marcus Hudritsch
6  * \copyright http://opensource.org/licenses/GPL-3.0
7  * \remarks Please use clangformat to format the code. See more code style on
8  * https://github.com/cpvrlab/SLProject4/wiki/SLProject-Coding-Style
9 */
10 
11 #include <Utils.h>
12 #include <cstddef>
13 #include <iostream>
14 #include <fstream>
15 #include <sstream>
16 #include <iomanip>
17 #include <string>
18 #include <cstdarg>
19 #include <cstring>
20 #include <utility>
21 #include <vector>
22 #include <algorithm>
23 #include <thread>
24 
25 #ifndef __EMSCRIPTEN__
26 # include <asio.hpp>
27 # include <asio/ip/tcp.hpp>
28 #endif
29 
30 #if defined(_WIN32)
31 # if _MSC_VER >= 1912
32 # define _SILENCE_EXPERIMENTAL_FILESYSTEM_DEPRECATION_WARNING
33 # include <experimental/filesystem>
34 # define USE_STD_FILESYSTEM
35 namespace fs = std::experimental::filesystem;
36 # else
37 # include <direct.h> //_getcwd
38 # endif
39 #elif defined(__APPLE__)
40 # if defined(TARGET_OS_IOS) && (TARGET_OS_IOS == 1)
41 # include "Utils_iOS.h"
42 # include <dirent.h> //dirent
43 # include <sys/stat.h> //dirent
44 # include <unistd.h> //getcwd
45 # else
46 # include <filesystem>
47 # define USE_STD_FILESYSTEM
48 namespace fs = std::filesystem;
49 # endif
50 #elif defined(ANDROID) || defined(ANDROID_NDK)
51 # include <android/log.h>
52 # include <dirent.h>
53 # include <unistd.h> //getcwd
54 # include <sys/stat.h>
55 # include <sys/time.h>
56 # include <sys/system_properties.h>
57 #elif defined(linux) || defined(__linux) || defined(__linux__)
58 # include <dirent.h>
59 # include <unistd.h> //getcwd
60 # include <sys/types.h>
61 # include <sys/stat.h>
62 #elif defined(__EMSCRIPTEN__)
63 # include <emscripten.h>
64 # include <dirent.h>
65 # include <unistd.h>
66 # include <sys/types.h>
67 # include <sys/stat.h>
68 #endif
69 
70 #ifndef __EMSCRIPTEN__
71 using asio::ip::tcp;
72 #endif
73 
74 using std::fstream;
75 
76 namespace Utils
77 {
78 ///////////////////////////////
79 // Global variables //
80 ///////////////////////////////
81 
82 std::unique_ptr<CustomLog> customLog;
83 
84 bool onlyErrorLogs = false;
85 
86 ///////////////////////////////
87 // String Handling Functions //
88 ///////////////////////////////
89 
90 //-----------------------------------------------------------------------------
91 // Returns a string from a float with max. one trailing zero
92 string toString(float f, int roundedDecimals)
93 {
94  stringstream ss;
95  ss << std::fixed << std::setprecision(roundedDecimals) << f;
96  string num = ss.str();
97  if (num == "-0.0") num = "0.0";
98  return num;
99 }
100 //-----------------------------------------------------------------------------
101 // Returns a string from a double with max. one trailing zero
102 string toString(double d, int roundedDecimals)
103 {
104  stringstream ss;
105  ss << std::fixed << std::setprecision(roundedDecimals) << d;
106  string num = ss.str();
107  if (num == "-0.0") num = "0.0";
108  return num;
109 }
110 //-----------------------------------------------------------------------------
111 // Returns a string in lower case
112 string toLowerString(string s)
113 {
114  string cpy(std::move(s));
115  transform(cpy.begin(), cpy.end(), cpy.begin(), ::tolower);
116  return cpy;
117 }
118 //-----------------------------------------------------------------------------
119 // Returns a string in upper case
120 string toUpperString(string s)
121 {
122  string cpy(std::move(s));
123  transform(cpy.begin(), cpy.end(), cpy.begin(), ::toupper);
124  return cpy;
125 }
126 //-----------------------------------------------------------------------------
127 // trims a string at both ends
128 string trimString(const string& s, const string& drop)
129 {
130  string r = s;
131  r = r.erase(r.find_last_not_of(drop) + 1);
132  return r.erase(0, r.find_first_not_of(drop));
133 }
134 //-----------------------------------------------------------------------------
135 // trims a string at the right end
136 string trimRightString(const string& s, const string& drop)
137 {
138  string r = s;
139  r = r.erase(r.find_last_not_of(drop) + 1);
140  return r;
141 }
142 //-----------------------------------------------------------------------------
143 // trims a string at the left end
144 string trimLeftString(const string& s, const string& drop)
145 {
146  string r = s;
147  r = r.erase(r.find_first_not_of(drop) + 1);
148  return r;
149 }
150 //-----------------------------------------------------------------------------
151 // Splits an input string at a delimiter character into a string vector
152 void splitString(const string& s,
153  char delimiter,
154  vector<string>& splits)
155 {
156  string::size_type i = 0;
157  string::size_type j = s.find(delimiter);
158 
159  while (j != string::npos)
160  {
161  splits.push_back(s.substr(i, j - i));
162  i = ++j;
163  j = s.find(delimiter, j);
164  if (j == string::npos)
165  splits.push_back(s.substr(i, s.length()));
166  }
167 }
168 //-----------------------------------------------------------------------------
169 // Replaces in the source-string the from-string by the to-string
170 void replaceString(string& source,
171  const string& from,
172  const string& to)
173 {
174  // Code from: http://stackoverflow.com/questions/2896600/
175  // how-to-replace-all-occurrences-of-a-character-in-string
176  string newString;
177  newString.reserve(source.length()); // avoids a few memory allocations
178 
179  string::size_type lastPos = 0;
180  string::size_type findPos = 0;
181 
182  while (string::npos != (findPos = source.find(from, lastPos)))
183  {
184  newString.append(source, lastPos, findPos - lastPos);
185  newString += to;
186  lastPos = findPos + from.length();
187  }
188 
189  // Care for the rest after last occurrence
190  newString += source.substr(lastPos);
191  source.swap(newString);
192 }
193 //-----------------------------------------------------------------------------
194 // Returns a vector of string one per line of a multiline string
195 vector<string> getStringLines(const string& multiLineString)
196 {
197  std::stringstream stream(multiLineString);
198  std::vector<std::string> res;
199  while (1)
200  {
201  std::string line;
202  std::getline(stream, line);
203  line = Utils::trimString(line, "\r");
204  res.push_back(line);
205  if (!stream.good())
206  break;
207  }
208  return res;
209 }
210 //-----------------------------------------------------------------------------
211 // Loads a file into a string and returns it
212 string readTextFileIntoString(const char* logTag, const string& pathAndFilename)
213 {
214  fstream shaderFile(pathAndFilename.c_str(), std::ios::in);
215 
216  if (!shaderFile.is_open())
217  {
218  log(logTag,
219  "File open failed in readTextFileIntoString: %s",
220  pathAndFilename.c_str());
221  exit(1);
222  }
223 
224  std::stringstream buffer;
225  buffer << shaderFile.rdbuf();
226  return buffer.str();
227 }
228 //-----------------------------------------------------------------------------
229 // Writes a string into a text file
230 void writeStringIntoTextFile(const char* logTag,
231  const string& stringToWrite,
232  const string& pathAndFilename)
233 {
234  std::ofstream file(pathAndFilename);
235  file << stringToWrite;
236  if (file.bad())
237  log(logTag,
238  "Writing file failed in writeStringIntoTextFile: %s",
239  pathAndFilename.c_str());
240  file.close();
241 }
242 //-----------------------------------------------------------------------------
243 // deletes non-filename characters: /\|?%*:"<>'
244 string replaceNonFilenameChars(string src, const char replaceChar)
245 {
246  std::replace(src.begin(), src.end(), '/', replaceChar);
247  std::replace(src.begin(), src.end(), '\\', replaceChar);
248  std::replace(src.begin(), src.end(), '|', replaceChar);
249  std::replace(src.begin(), src.end(), '?', replaceChar);
250  std::replace(src.begin(), src.end(), '%', replaceChar);
251  std::replace(src.begin(), src.end(), '*', replaceChar);
252  std::replace(src.begin(), src.end(), ':', replaceChar);
253  std::replace(src.begin(), src.end(), '"', replaceChar);
254  return src;
255 }
256 //-----------------------------------------------------------------------------
257 // Returns local time as string like "Wed Feb 13 15:46:11 2019"
259 {
260  time_t tm = 0;
261  time(&tm);
262  struct tm* t2 = localtime(&tm);
263  char buf[1024];
264  strftime(buf, sizeof(buf), "%c", t2);
265  return string(buf);
266 }
267 //-----------------------------------------------------------------------------
268 // Returns local time as string like "13.02.19-15:46"
270 {
271  time_t tm = 0;
272  time(&tm);
273  struct tm* t = localtime(&tm);
274 
275  static char shortTime[50];
276  snprintf(shortTime,
277  sizeof(shortTime),
278  "%.2d.%.2d.%.2d-%.2d:%.2d",
279  t->tm_mday,
280  t->tm_mon + 1,
281  t->tm_year - 100,
282  t->tm_hour,
283  t->tm_min);
284 
285  return string(shortTime);
286 }
287 //-----------------------------------------------------------------------------
288 // Returns local time as string like "20190213-154611"
290 {
291  time_t tm = 0;
292  time(&tm);
293  struct tm* t = localtime(&tm);
294 
295  static char shortTime[50];
296  snprintf(shortTime,
297  sizeof(shortTime),
298  "%.4d%.2d%.2d-%.2d%.2d%.2d",
299  1900 + t->tm_year,
300  t->tm_mon + 1,
301  t->tm_mday,
302  t->tm_hour,
303  t->tm_min,
304  t->tm_sec);
305 
306  return string(shortTime);
307 }
308 //-----------------------------------------------------------------------------
309 // Returns the hostname from boost asio
310 string getHostName()
311 {
312 #ifndef __EMSCRIPTEN__
313  return asio::ip::host_name();
314 #else
315  return "0.0.0.0";
316 #endif
317 }
318 //-----------------------------------------------------------------------------
319 // Returns a formatted string as sprintf
320 string formatString(string fmt_str, ...)
321 {
322  // Reserve two times as much as the length of the fmt_str
323  int final_n = 0;
324  int n = ((int)fmt_str.size()) * 2;
325 
326  string str;
327  std::unique_ptr<char[]> formatted;
328  va_list ap;
329  while (true)
330  {
331  formatted.reset(new char[n]);
332  strcpy(&formatted[0], fmt_str.c_str());
333  va_start(ap, fmt_str);
334  final_n = vsnprintf(&formatted[0], (unsigned long)n, fmt_str.c_str(), ap);
335  va_end(ap);
336  if (final_n < 0 || final_n >= n)
337  n += abs(final_n - n + 1);
338  else
339  break;
340  }
341  return string(formatted.get());
342 }
343 //-----------------------------------------------------------------------------
344 // Returns true if container contains the search string
345 bool containsString(const string& container, const string& search)
346 {
347  return (container.find(search) != string::npos);
348 }
349 //-----------------------------------------------------------------------------
350 // Return true if the container string starts with the startStr
351 bool startsWithString(const string& container, const string& startStr)
352 {
353  return container.find(startStr) == 0;
354 }
355 //-----------------------------------------------------------------------------
356 // Return true if the container string ends with the endStr
357 bool endsWithString(const string& container, const string& endStr)
358 {
359  if (container.length() >= endStr.length())
360  return (0 == container.compare(container.length() - endStr.length(),
361  endStr.length(),
362  endStr));
363  else
364  return false;
365 }
366 //-----------------------------------------------------------------------------
367 // Returns inputDir with unified forward slashes
368 string unifySlashes(const string& inputDir, bool withTrailingSlash)
369 {
370  string copy = inputDir;
371  string curr;
372  string delimiter = "\\";
373  size_t pos = 0;
374  string token;
375  while ((pos = copy.find(delimiter)) != string::npos)
376  {
377  token = copy.substr(0, pos);
378  copy.erase(0, pos + delimiter.length());
379  curr.append(token);
380  curr.append("/");
381  }
382 
383  curr.append(copy);
384 
385  if (withTrailingSlash && !curr.empty() && curr.back() != '/')
386  curr.append("/");
387 
388  return curr;
389 }
390 //-----------------------------------------------------------------------------
391 // Returns the path w. '\\' of path-filename string
392 string getPath(const string& pathFilename)
393 {
394  size_t i1 = pathFilename.rfind('\\', pathFilename.length());
395  size_t i2 = pathFilename.rfind('/', pathFilename.length());
396  if ((i1 != string::npos && i2 == string::npos) ||
397  (i1 != string::npos && i1 > i2))
398  {
399  return (pathFilename.substr(0, i1 + 1));
400  }
401 
402  if ((i2 != string::npos && i1 == string::npos) ||
403  (i2 != string::npos && i2 > i1))
404  {
405  return (pathFilename.substr(0, i2 + 1));
406  }
407  return pathFilename;
408 }
409 //-----------------------------------------------------------------------------
410 // Returns true if content of file could be put in a vector of strings
411 bool getFileContent(const string& fileName,
412  vector<string>& vecOfStrings)
413 {
414 
415  // Open the File
416  std::ifstream in(fileName.c_str());
417 
418  // Check if object is valid
419  if (!in)
420  {
421  std::cerr << "Cannot open the File : " << fileName << std::endl;
422  return false;
423  }
424 
425  // Read the next line from File untill it reaches the end.
426  std::string str;
427  while (std::getline(in, str))
428  {
429  // Line contains string of length > 0 then save it in vector
430  if (!str.empty())
431  vecOfStrings.push_back(str);
432  }
433 
434  // Close The File
435  in.close();
436  return true;
437 }
438 //-----------------------------------------------------------------------------
439 // Naturally compares two strings (used for filename sorting)
440 /*! String comparison as most filesystem do it.
441 Source: https://www.o-rho.com/naturalsort
442 
443 std::sort compareNatural
444 --------- --------------
445 1.txt 1.txt
446 10.txt 1_t.txt
447 1_t.txt 10.txt
448 20 20
449 20.txt 20.txt
450 ABc ABc
451 aBCd aBCd
452 aBCd(01) aBCd(1)
453 aBCd(1) aBCd(01)
454 aBCd(12) aBCd(2)
455 aBCd(2) aBCd(12)
456 aBc aBc
457 aBcd aBcd
458 aaA aaA
459 aaa aaa
460 z10.txt z2.txt
461 z100.txt z10.txt
462 z2.txt z100.txt
463  */
464 bool compareNatural(const string& a, const string& b)
465 {
466  const char* p1 = a.c_str();
467  const char* p2 = b.c_str();
468  const unsigned short st_scan = 0;
469  const unsigned short st_alpha = 1;
470  const unsigned short st_numeric = 2;
471  unsigned short state = st_scan;
472  const char* numstart1 = nullptr;
473  const char* numstart2 = nullptr;
474  const char* numend1 = nullptr;
475  const char* numend2 = nullptr;
476  unsigned long sz1 = 0;
477  unsigned long sz2 = 0;
478 
479  while (*p1 && *p2)
480  {
481  switch (state)
482  {
483  case st_scan:
484  if (!isdigit(*p1) && !isdigit(*p2))
485  {
486  state = st_alpha;
487  if (*p1 == *p2)
488  {
489  p1++;
490  p2++;
491  }
492  else
493  return *p1 < *p2;
494  }
495  else if (isdigit(*p1) && !isdigit(*p2))
496  return true;
497  else if (!isdigit(*p1) && isdigit(*p2))
498  return false;
499  else
500  {
501  state = st_numeric;
502  if (sz1 == 0)
503  while (*p1 == '0')
504  {
505  p1++;
506  sz1++;
507  }
508  else
509  while (*p1 == '0') p1++;
510  if (sz2 == 0)
511  while (*p2 == '0')
512  {
513  p2++;
514  sz2++;
515  }
516  else
517  while (*p2 == '0') p2++;
518  if (sz1 == sz2)
519  {
520  sz1 = 0;
521  sz2 = 0;
522  }
523  if (!isdigit(*p1)) p1--;
524  if (!isdigit(*p2)) p2--;
525  numstart1 = p1;
526  numstart2 = p2;
527  numend1 = numstart1;
528  numend2 = numstart2;
529  }
530  break;
531  case st_alpha:
532  if (!isdigit(*p1) && !isdigit(*p2))
533  {
534  if (*p1 == *p2)
535  {
536  p1++;
537  p2++;
538  }
539  else
540  return *p1 < *p2;
541  }
542  else
543  state = st_scan;
544  break;
545  case st_numeric:
546  while (isdigit(*p1)) numend1 = p1++;
547  while (isdigit(*p2)) numend2 = p2++;
548  if (numend1 - numstart1 == numend2 - numstart2 &&
549  !strncmp(numstart1, numstart2, numend2 - numstart2 + 1))
550  state = st_scan;
551  else
552  {
553  if (numend1 - numstart1 != numend2 - numstart2)
554  return numend1 - numstart1 < numend2 - numstart2;
555  while (*numstart1 && *numstart2)
556  {
557  if (*numstart1 != *numstart2) return *numstart1 < *numstart2;
558  numstart1++;
559  numstart2++;
560  }
561  }
562  break;
563  default: break;
564  }
565  }
566  if (sz1 < sz2) return true;
567  if (sz1 > sz2) return false;
568  if (*p1 == 0 && *p2 != 0) return true;
569  if (*p1 != 0 && *p2 == 0) return false;
570  return false;
571 }
572 //-----------------------------------------------------------------------------
573 
574 /////////////////////////////
575 // File Handling Functions //
576 /////////////////////////////
577 
578 //-----------------------------------------------------------------------------
579 // Returns the filename of path-filename string
580 string getFileName(const string& pathFilename)
581 {
582  size_t i1 = pathFilename.rfind('\\', pathFilename.length());
583  size_t i2 = pathFilename.rfind('/', pathFilename.length());
584  int i = -1;
585 
586  if (i1 != string::npos && i2 != string::npos)
587  i = (int)std::max(i1, i2);
588  else if (i1 != string::npos)
589  i = (int)i1;
590  else if (i2 != string::npos)
591  i = (int)i2;
592 
593  return pathFilename.substr(i + 1, pathFilename.length() - i);
594 }
595 
596 //-----------------------------------------------------------------------------
597 // Returns the path of a path-filename combo
598 string getDirName(const string& pathFilename)
599 {
600  size_t i1 = pathFilename.rfind('\\', pathFilename.length());
601  size_t i2 = pathFilename.rfind('/', pathFilename.length());
602  int i = -1;
603 
604  if (i1 != string::npos && i2 != string::npos)
605  i = (int)std::max(i1, i2);
606  else if (i1 != string::npos)
607  i = (int)i1;
608  else if (i2 != string::npos)
609  i = (int)i2;
610 
611  return pathFilename.substr(0, i + 1);
612 }
613 
614 //-----------------------------------------------------------------------------
615 // Returns the filename without extension
616 string getFileNameWOExt(const string& pathFilename)
617 {
618  string filename = getFileName(pathFilename);
619  size_t i = filename.rfind('.', filename.length());
620  if (i != string::npos)
621  {
622  return (filename.substr(0, i));
623  }
624 
625  return (filename);
626 }
627 //-----------------------------------------------------------------------------
628 // Returns the file extension without dot in lower case
629 string getFileExt(const string& filename)
630 {
631  size_t i = filename.rfind('.', filename.length());
632  if (i != string::npos)
633  return toLowerString(filename.substr(i + 1, filename.length() - i));
634  return ("");
635 }
636 //-----------------------------------------------------------------------------
637 // Returns a vector of unsorted directory names with path in dir
638 vector<string> getDirNamesInDir(const string& dirName, bool fullPath)
639 {
640  vector<string> filePathNames;
641 
642 #if defined(USE_STD_FILESYSTEM)
643  if (fs::exists(dirName) && fs::is_directory(dirName))
644  {
645  for (const auto& entry : fs::directory_iterator(dirName))
646  {
647  auto filename = entry.path().filename();
648  if (fs::is_directory(entry.status()))
649  {
650  if (fullPath)
651  filePathNames.push_back(dirName + "/" + filename.u8string());
652  else
653  filePathNames.push_back(filename.u8string());
654  }
655  }
656  }
657 #else
658  DIR* dir = opendir(dirName.c_str());
659 
660  if (dir)
661  {
662  struct dirent* dirContent = nullptr;
663 
664  while ((dirContent = readdir(dir)) != nullptr)
665  {
666  string name(dirContent->d_name);
667 
668  if (name != "." && name != "..")
669  {
670  struct stat path_stat
671  {
672  };
673  stat((dirName + name).c_str(), &path_stat);
674  if (!S_ISREG(path_stat.st_mode))
675  {
676  if (fullPath)
677  filePathNames.push_back(dirName + "/" + name);
678  else
679  filePathNames.push_back(name);
680  }
681  }
682  }
683  closedir(dir);
684  }
685 #endif
686 
687  return filePathNames;
688 }
689 //-----------------------------------------------------------------------------
690 // Returns a vector of unsorted names (files and directories) with path in dir
691 vector<string> getAllNamesInDir(const string& dirName, bool fullPath)
692 {
693  vector<string> filePathNames;
694 
695 #if defined(USE_STD_FILESYSTEM)
696  if (fs::exists(dirName) && fs::is_directory(dirName))
697  {
698  for (const auto& entry : fs::directory_iterator(dirName))
699  {
700  auto filename = entry.path().filename();
701  if (fullPath)
702  filePathNames.push_back(dirName + "/" + filename.u8string());
703  else
704  filePathNames.push_back(filename.u8string());
705  }
706  }
707 #else
708 # if defined(TARGET_OS_IOS) && (TARGET_OS_IOS == 1)
709  return Utils_iOS::getAllNamesInDir(dirName, fullPath);
710 # else
711  DIR* dir = opendir(dirName.c_str());
712 
713  if (dir)
714  {
715  struct dirent* dirContent = nullptr;
716 
717  while ((dirContent = readdir(dir)) != nullptr)
718  {
719  string name(dirContent->d_name);
720  if (name != "." && name != "..")
721  {
722  if (fullPath)
723  filePathNames.push_back(dirName + "/" + name);
724  else
725  filePathNames.push_back(name);
726  }
727  }
728  closedir(dir);
729  }
730 # endif
731 #endif
732 
733  return filePathNames;
734 }
735 //-----------------------------------------------------------------------------
736 // Returns a vector of unsorted filesnames with path in dir
737 vector<string> getFileNamesInDir(const string& dirName, bool fullPath)
738 {
739  vector<string> filePathNames;
740 
741 #if defined(USE_STD_FILESYSTEM)
742  if (fs::exists(dirName) && fs::is_directory(dirName))
743  {
744  for (const auto& entry : fs::directory_iterator(dirName))
745  {
746  auto filename = entry.path().filename();
747  if (fs::is_regular_file(entry.status()))
748  {
749  if (fullPath)
750  filePathNames.push_back(dirName + "/" + filename.u8string());
751  else
752  filePathNames.push_back(filename.u8string());
753  }
754  }
755  }
756 #else
757  // todo: does this part also return directories? It should only return file names..
758  DIR* dir = opendir(dirName.c_str());
759 
760  if (dir)
761  {
762  struct dirent* dirContent = nullptr;
763 
764  while ((dirContent = readdir(dir)) != nullptr)
765  {
766  string name(dirContent->d_name);
767  if (name != "." && name != "..")
768  {
769  struct stat path_stat
770  {
771  };
772  stat((dirName + name).c_str(), &path_stat);
773  if (S_ISREG(path_stat.st_mode))
774  {
775  if (fullPath)
776  filePathNames.push_back(dirName + name);
777  else
778  filePathNames.push_back(name);
779  }
780  }
781  }
782  closedir(dir);
783  }
784 #endif
785 
786  return filePathNames;
787 }
788 //-----------------------------------------------------------------------------
789 // Returns true if a directory exists.
790 bool dirExists(const string& path)
791 {
792 #if defined(__EMSCRIPTEN__)
793  return true;
794 #elif defined(USE_STD_FILESYSTEM)
795  return fs::exists(path) && fs::is_directory(path);
796 #else
797  struct stat info
798  {
799  };
800  if (stat(path.c_str(), &info) != 0)
801  return false;
802  else if (info.st_mode & S_IFDIR)
803  return true;
804  else
805  return false;
806 #endif
807 }
808 //-----------------------------------------------------------------------------
809 // Creates a directory with given path
810 bool makeDir(const string& path)
811 {
812 #if defined(USE_STD_FILESYSTEM)
813  return fs::create_directories(path);
814 #else
815 # if defined(_WIN32)
816  return _mkdir(path.c_str());
817 # else
818  int failed = mkdir(path.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
819  bool result = !failed;
820  return result;
821 # endif
822 #endif
823 }
824 //-----------------------------------------------------------------------------
825 // Creates a directory with given path recursively
826 bool makeDirRecurse(std::string path)
827 {
828  std::string delimiter = "/";
829 
830  size_t pos = 0;
831  std::string token;
832 
833  std::string createdPath;
834 
835  while ((pos = path.find(delimiter)) != std::string::npos)
836  {
837  createdPath += path.substr(0, pos) + "/";
838 
839  if (!dirExists(createdPath))
840  {
841  if (!makeDir(createdPath))
842  {
843  return false;
844  }
845  }
846 
847  path.erase(0, pos + delimiter.length());
848  }
849 
850  return true;
851 }
852 //-----------------------------------------------------------------------------
853 // Removes a directory with given path
854 void removeDir(const string& path)
855 {
856 
857 #if defined(USE_STD_FILESYSTEM)
858  fs::remove_all(path);
859 #else
860 # if defined(_WIN32)
861  int ret = _rmdir(path.c_str());
862  if (ret != 0)
863  {
864  errno_t err;
865  _get_errno(&err);
866  log("Could not remove directory: %s\nErrno: %s\n", path.c_str(), strerror(errno));
867  }
868 # else
869  rmdir(path.c_str());
870 # endif
871 #endif
872 }
873 //-----------------------------------------------------------------------------
874 // Removes a file with given path
875 void removeFile(const string& path)
876 {
877  if (fileExists(path))
878  {
879 #if defined(USE_STD_FILESYSTEM)
880  fs::remove(path);
881 #else
882 # if defined(_WIN32)
883  DeleteFileA(path.c_str());
884 # else
885  unlink(path.c_str());
886 # endif
887 
888 #endif
889  }
890  else
891  log("Could not remove file : %s\nErrno: %s\n",
892  path.c_str(),
893  "file does not exist");
894 }
895 //-----------------------------------------------------------------------------
896 // Returns true if a file exists.
897 bool fileExists(const string& pathfilename)
898 {
899 #if defined(__EMSCRIPTEN__)
900  return false;
901 #elif defined(USE_STD_FILESYSTEM)
902  return fs::exists(pathfilename);
903 #else
904  struct stat info
905  {
906  };
907  return (stat(pathfilename.c_str(), &info) == 0) && ((info.st_mode & S_IFDIR) == 0);
908 #endif
909 }
910 //-----------------------------------------------------------------------------
911 // Returns the file size in bytes
912 unsigned int getFileSize(const string& pathfilename)
913 {
914 #if defined(USE_STD_FILESYSTEM)
915  if (fs::exists(pathfilename))
916  return (unsigned int)fs::file_size(pathfilename);
917  else
918  return 0;
919 #else
920  struct stat st
921  {
922  };
923  if (stat(pathfilename.c_str(), &st) != 0)
924  return 0;
925  return (unsigned int)st.st_size;
926 #endif
927 }
928 //-----------------------------------------------------------------------------
929 // Returns the file size in bytes
930 unsigned int getFileSize(std::ifstream& fs)
931 {
932  fs.seekg(0, std::ios::beg);
933  std::streampos begin = fs.tellg();
934  fs.seekg(0, std::ios::end);
935  std::streampos end = fs.tellg();
936  fs.seekg(0, std::ios::beg);
937  return (unsigned int)(end - begin);
938 }
939 
940 //-----------------------------------------------------------------------------
941 // Returns the writable configuration directory with trailing forward slash
942 string getAppsWritableDir(string appName)
943 {
944 #if defined(_WIN32)
945  string appData = getenv("APPDATA");
946  string configDir = appData + "/" + appName;
947  replaceString(configDir, "\\", "/");
948  if (!dirExists(configDir))
949  makeDir(configDir.c_str());
950  return configDir + "/";
951 #elif defined(__APPLE__)
952  string home = getenv("HOME");
953  string appData = home + "/Library/Application Support";
954  string configDir = appData + "/" + appName;
955  if (!dirExists(configDir))
956  mkdir(configDir.c_str(), S_IRWXU);
957  return configDir + "/";
958 #elif defined(ANDROID) || defined(ANDROID_NDK)
959  // @todo Where is the app data path on Andoroid?
960 #elif defined(linux) || defined(__linux) || defined(__linux__)
961  // @todo Where is the app data path on Linux?
962  string home = getenv("HOME");
963  string configDir = home + "/." + appName;
964  if (!dirExists(configDir))
965  mkdir(configDir.c_str(), S_IRWXU | S_IRWXG | S_IRWXO);
966  return configDir + "/";
967 #elif defined(__EMSCRIPTEN__)
968  return "?";
969 #else
970 # error "No port to this OS"
971 #endif
972  return "";
973 }
974 //-----------------------------------------------------------------------------
975 // Returns the working directory with forward slashes inbetween and at the end
977 {
978 #if defined(_WIN32)
979 # if defined(USE_STD_FILESYSTEM)
980  return fs::current_path().u8string();
981 # else
982  int size = 256;
983  char* buffer = (char*)malloc(size);
984  if (_getcwd(buffer, size) == buffer)
985  {
986  string dir = buffer;
987  replaceString(dir, "\\", "/");
988  return dir + "/";
989  }
990 
991  free(buffer);
992  return "";
993 # endif
994 #elif !defined(__EMSCRIPTEN__)
995  size_t size = 256;
996  char* buffer = (char*)malloc(size);
997  if (getcwd(buffer, size) == buffer)
998  return string(buffer) + "/";
999 
1000  free(buffer);
1001  return "";
1002 #else
1003  return "/";
1004 #endif
1005 }
1006 //-----------------------------------------------------------------------------
1007 // Deletes a file on the filesystem
1008 bool deleteFile(string& pathfilename)
1009 {
1010  if (fileExists(pathfilename))
1011  return remove(pathfilename.c_str()) != 0;
1012  return false;
1013 }
1014 //-----------------------------------------------------------------------------
1015 // process all files and folders recursively naturally sorted
1016 void loopFileSystemRec(const string& path,
1017  function<void(string path, string baseName, int depth)> processFile,
1018  function<void(string path, string baseName, int depth)> processDir,
1019  const int depth)
1020 {
1021  // be sure that the folder slashes are correct
1022  string folder = unifySlashes(path);
1023 
1024  if (dirExists(folder))
1025  {
1026  vector<string> unsortedNames = getAllNamesInDir(folder);
1027 
1028  processDir(getDirName(trimRightString(folder, "/")),
1029  getFileName(trimRightString(folder, "/")),
1030  depth);
1031  sort(unsortedNames.begin(), unsortedNames.end(), Utils::compareNatural);
1032 
1033  for (const auto& fileOrFolder : unsortedNames)
1034  {
1035  if (dirExists(fileOrFolder))
1036  loopFileSystemRec(fileOrFolder, processFile, processDir, depth + 1);
1037  else
1038  processFile(folder, getFileName(fileOrFolder), depth);
1039  }
1040  }
1041  else
1042  {
1043  processFile(getDirName(trimRightString(path, "/")),
1044  getFileName(trimRightString(path, "/")),
1045  depth);
1046  }
1047 }
1048 
1049 //-----------------------------------------------------------------------------
1050 // Dumps all files and folders on stdout recursively naturally sorted
1051 void dumpFileSystemRec(const char* logtag, const string& folderPath)
1052 {
1053  const char* tab = " ";
1054 
1056  folderPath,
1057  [logtag, tab](string path, string baseName, int depth) -> void {
1058  string indent;
1059  for (int d = 0; d < depth; ++d)
1060  indent += tab;
1061  string indentFolderName = indent + baseName;
1062  Utils::log(logtag, "%s", indentFolderName.c_str());
1063  },
1064  [logtag, tab](string path, string baseName, int depth) -> void {
1065  string indent;
1066  for (int d = 0; d < depth; ++d)
1067  indent += tab;
1068  string indentFolderName = indent + "[" + baseName + "]";
1069  Utils::log(logtag, "%s", indentFolderName.c_str());
1070  });
1071 }
1072 //-----------------------------------------------------------------------------
1073 // findFile return the full path with filename
1074 /* Unfortunatelly the relative folder structure on different OS are not identical.
1075  * This function allows to search on for a file on different paths.
1076  */
1077 string findFile(const string& filename, const vector<string>& pathsToCheck)
1078 {
1079  if (Utils::fileExists(filename))
1080  return filename;
1081 
1082  // Check file existence
1083  for (const auto& path : pathsToCheck)
1084  {
1085  string pathPlusFilename = Utils::unifySlashes(path) + filename;
1086  if (Utils::fileExists(pathPlusFilename))
1087  return pathPlusFilename;
1088  }
1089  return "";
1090 }
1091 //----------------------------------------------------------------------------
1092 
1093 ///////////////////////
1094 // Logging Functions //
1095 ///////////////////////
1096 //-----------------------------------------------------------------------------
1097 void initFileLog(const string& logDir, bool forceFlush)
1098 {
1099  fileLog = std::make_unique<FileLog>(logDir, forceFlush);
1100 }
1101 //-----------------------------------------------------------------------------
1102 // logs a formatted string platform independently
1103 void log(const char* tag, const char* format, ...)
1104 {
1105  char log[4096];
1106 
1107  va_list argptr;
1108  va_start(argptr, format);
1109  vsnprintf(log, sizeof(log), format, argptr);
1110  va_end(argptr);
1111 
1112  char msg[4096];
1113  strcpy(msg, tag);
1114  strcat(msg, ": ");
1115  strcat(msg, log);
1116  strcat(msg, "\n");
1117 
1118  if (fileLog)
1119  fileLog->post(msg);
1120 
1121  if (customLog)
1122  customLog->post(msg);
1123 
1125  return;
1126 
1127 #if defined(ANDROID) || defined(ANDROID_NDK)
1128  __android_log_print(ANDROID_LOG_INFO, tag, msg);
1129 #else
1130  std::cout << msg << std::flush;
1131 #endif
1132 }
1133 //-----------------------------------------------------------------------------
1134 // Terminates the application with a message. No leak checking.
1135 void exitMsg(const char* tag,
1136  const char* msg,
1137  const int line,
1138  const char* file)
1139 {
1140  errorMsg(tag, msg, line, file);
1141  exit(-1);
1142 }
1143 //-----------------------------------------------------------------------------
1144 // Warn message output
1145 void warnMsg(const char* tag,
1146  const char* msg,
1147  const int line,
1148  const char* file)
1149 {
1150 #if defined(ANDROID) || defined(ANDROID_NDK)
1151  __android_log_print(ANDROID_LOG_WARN,
1152  tag,
1153  "Warning: %s at line %d in %s\n",
1154  msg,
1155  line,
1156  file);
1157 #else
1158  std::cout << "--------------------------------\n"
1159  << "Warning:\n"
1160  << "Tag: " << tag << '\n'
1161  << "Location: " << file << ":" << line << '\n'
1162  << "Message: " << msg << '\n'
1163  << "--------------------------------" << std::endl;
1164 #endif
1165 }
1166 //-----------------------------------------------------------------------------
1167 // Error message output (same as warn but with another tag for android)
1168 void errorMsg(const char* tag,
1169  const char* msg,
1170  const int line,
1171  const char* file)
1172 {
1173 #if defined(ANDROID) || defined(ANDROID_NDK)
1174  __android_log_print(ANDROID_LOG_ERROR,
1175  tag,
1176  "Error: %s at line %d in %s\n",
1177  msg,
1178  line,
1179  file);
1180 #else
1181  std::cout << "--------------------------------\n"
1182  << "Error:\n"
1183  << "Tag: " << tag << '\n'
1184  << "Location: " << file << ":" << line << '\n'
1185  << "Message: " << msg << '\n'
1186  << "--------------------------------" << std::endl;
1187 #endif
1188 }
1189 //-----------------------------------------------------------------------------
1190 // Returns in release config the max. NO. of threads otherwise 1
1191 unsigned int maxThreads()
1192 {
1193 #if defined(DEBUG) || defined(_DEBUG)
1194  return 1;
1195 #else
1196  return std::max(std::thread::hardware_concurrency(), 1U);
1197 #endif
1198 }
1199 //-----------------------------------------------------------------------------
1200 
1201 ////////////////////
1202 // Math Utilities //
1203 ////////////////////
1204 
1205 //-----------------------------------------------------------------------------
1206 // Greatest common divisor of two integer numbers (ggT = grösster gemeinsame Teiler)
1207 int gcd(int a, int b)
1208 {
1209  if (b == 0)
1210  return a;
1211  return gcd(b, a % b);
1212 }
1213 //-----------------------------------------------------------------------------
1214 // Lowest common multiple (kgV = kleinstes gemeinsames Vielfache)
1215 int lcm(int a, int b)
1216 {
1217  return (a * b) / Utils::gcd(a, b);
1218 }
1219 //-----------------------------------------------------------------------------
1220 // Returns the closest power of 2 to a passed number.
1221 unsigned closestPowerOf2(unsigned num)
1222 {
1223  unsigned nextPow2 = 1;
1224  if (num <= 0) return 1;
1225 
1226  while (nextPow2 <= num)
1227  nextPow2 <<= 1;
1228  unsigned prevPow2 = nextPow2 >> 1;
1229 
1230  if (num - prevPow2 < nextPow2 - num)
1231  return prevPow2;
1232  else
1233  return nextPow2;
1234 }
1235 //-----------------------------------------------------------------------------
1236 // Returns the next power of 2 to a passed number.
1237 unsigned nextPowerOf2(unsigned num)
1238 {
1239  unsigned nextPow2 = 1;
1240  if (num == 0) return 1;
1241 
1242  while (nextPow2 <= num)
1243  nextPow2 <<= 1;
1244  return nextPow2;
1245 }
1246 //-----------------------------------------------------------------------------
1247 
1248 //-----------------------------------------------------------------------------
1249 // ComputerInfos
1250 //-----------------------------------------------------------------------------
1251 std::string ComputerInfos::user = "USER?";
1252 std::string ComputerInfos::name = "NAME?";
1253 std::string ComputerInfos::brand = "BRAND?";
1254 std::string ComputerInfos::model = "MODEL?";
1255 std::string ComputerInfos::os = "OS?";
1256 std::string ComputerInfos::osVer = "OSVER?";
1257 std::string ComputerInfos::arch = "ARCH?";
1258 std::string ComputerInfos::id = "ID?";
1259 
1260 //-----------------------------------------------------------------------------
1261 std::string ComputerInfos::get()
1262 {
1263 #if defined(_WIN32) //..................................................
1264 
1265  // Computer user name
1266  const char* envvar = std::getenv("USER");
1267  user = envvar ? string(envvar) : "USER?";
1268  if (user == "USER?")
1269  {
1270  const char* envvar = std::getenv("USERNAME");
1271  user = envvar ? string(envvar) : "USER?";
1272  }
1274 
1275  // Get architecture
1276  SYSTEM_INFO siSysInfo;
1277  GetSystemInfo(&siSysInfo);
1278  switch (siSysInfo.wProcessorArchitecture)
1279  {
1280  case PROCESSOR_ARCHITECTURE_AMD64: arch = "x64"; break;
1281  case PROCESSOR_ARCHITECTURE_ARM: arch = "ARM"; break;
1282  case 12: arch = "ARM64"; break; // PROCESSOR_ARCHITECTURE_ARM64
1283  case PROCESSOR_ARCHITECTURE_IA64: arch = "IA64"; break;
1284  case PROCESSOR_ARCHITECTURE_INTEL: arch = "x86"; break;
1285  default: arch = "???";
1286  }
1287 
1288  // Windows OS version
1289  OSVERSIONINFO osInfo;
1290  ZeroMemory(&osInfo, sizeof(OSVERSIONINFO));
1291  osInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
1292  GetVersionEx(&osInfo);
1293  char osVersion[50];
1294  sprintf(osVersion, "%lu.%lu", osInfo.dwMajorVersion, osInfo.dwMinorVersion);
1295  osVer = string(osVersion);
1296 
1297  brand = "BRAND?";
1298  model = "MODEL?";
1299  os = "Windows";
1300 
1301 #elif defined(__APPLE__)
1302 # if defined(TARGET_OS_IOS) && (TARGET_OS_IOS == 1)
1303  // Model and architecture are retrieved before in iOS under Objective C
1304  brand = "Apple";
1305  os = "iOS";
1306  const char* envvar = std::getenv("USER");
1307  user = envvar ? string(envvar) : "USER?";
1308  if (user == "USER?")
1309  {
1310  const char* envvar = std::getenv("USERNAME");
1311  user = envvar ? string(envvar) : "USER?";
1312  }
1314 # else
1315  // Computer user name
1316  const char* envvar = std::getenv("USER");
1317  user = envvar ? string(envvar) : "USER?";
1318 
1319  if (user == "USER?")
1320  {
1321  const char* envvarUN = std::getenv("USERNAME");
1322  user = envvarUN ? string(envvarUN) : "USER?";
1323  }
1324 
1326  brand = "Apple";
1327  os = "MacOS";
1328 
1329  // Get MacOS version
1330  // SInt32 majorV, minorV, bugfixV;
1331  // Gestalt(gestaltSystemVersionMajor, &majorV);
1332  // Gestalt(gestaltSystemVersionMinor, &minorV);
1333  // Gestalt(gestaltSystemVersionBugFix, &bugfixV);
1334  // char osVer[50];
1335  // sprintf(osVer, "%d.%d.%d", majorV, minorV, bugfixV);
1336  // osVer = string(osVer);
1337 
1338  // Get model
1339  // size_t len = 0;
1340  // sysctlbyname("hw.model", nullptr, &len, nullptr, 0);
1341  // char model[255];
1342  // sysctlbyname("hw.model", model, &len, nullptr, 0);
1343  // model = model;
1344 # endif
1345 
1346 #elif defined(ANDROID) //................................................
1347 
1348  os = "Android";
1349 
1350  /*
1351  "ro.build.version.release" // * The user-visible version string. E.g., "1.0" or "3.4b5".
1352  "ro.build.version.incremental" // The internal value used by the underlying source control to represent this build.
1353  "ro.build.version.codename" // The current development codename, or the string "REL" if this is a release build.
1354  "ro.build.version.sdk" // The user-visible SDK version of the framework.
1355 
1356  "ro.product.model" // * The end-user-visible name for the end product..
1357  "ro.product.manufacturer" // The manufacturer of the product/hardware.
1358  "ro.product.board" // The name of the underlying board, like "goldfish".
1359  "ro.product.brand" // The brand (e.g., carrier) the software is customized for, if any.
1360  "ro.product.device" // The name of the industrial design.
1361  "ro.product.name" // The name of the overall product.
1362  "ro.hardware" // The name of the hardware (from the kernel command line or /proc).
1363  "ro.product.cpu.abi" // The name of the instruction set (CPU type + ABI convention) of native code.
1364  "ro.product.cpu.abi2" // The name of the second instruction set (CPU type + ABI convention) of native code.
1365 
1366  "ro.build.display.id" // * A build ID string meant for displaying to the user.
1367  "ro.build.host"
1368  "ro.build.user"
1369  "ro.build.id" // Either a changelist number, or a label like "M4-rc20".
1370  "ro.build.type" // The type of build, like "user" or "eng".
1371  "ro.build.tags" // Comma-separated tags describing the build, like "unsigned,debug".
1372  */
1373 
1374  int len;
1375 
1376  char hostC[PROP_VALUE_MAX];
1377  len = __system_property_get("ro.build.host", hostC);
1378  name = !string(hostC).empty() ? string(hostC) : "NAME?";
1379 
1380  char userC[PROP_VALUE_MAX];
1381  len = __system_property_get("ro.build.user", userC);
1382  user = !string(userC).empty() ? string(userC) : "USER?";
1383 
1384  char brandC[PROP_VALUE_MAX];
1385  len = __system_property_get("ro.product.brand", brandC);
1386  brand = string(brandC);
1387 
1388  char modelC[PROP_VALUE_MAX];
1389  len = __system_property_get("ro.product.model", modelC);
1390  model = string(modelC);
1391 
1392  char osVerC[PROP_VALUE_MAX];
1393  len = __system_property_get("ro.build.version.release", osVerC);
1394  osVer = string(osVerC);
1395 
1396  char archC[PROP_VALUE_MAX];
1397  len = __system_property_get("ro.product.cpu.abi", archC);
1398  arch = string(archC);
1399 
1400 #elif defined(linux) || defined(__linux) || defined(__linux__) //..................................................
1401 
1402  os = "Linux";
1403  user = "USER?";
1405  brand = "BRAND?";
1406  model = "MODEL?";
1407  osVer = "OSVER?";
1408  arch = "ARCH?";
1409 #endif
1410 
1411  // build a unique as possible ID string that can be used in a filename
1412  id = user + "-" + name + "-" + model;
1413  if (model.find("SM-") != string::npos)
1414  // Don't use computerName on Samsung phones. It's not constant!
1415  id = user + "-" + model;
1416  else
1417  id = user + "-" + name + "-" + model;
1419  std::replace(id.begin(), id.end(), '_', '-');
1420  return id;
1421 }
1422 //-----------------------------------------------------------------------------
1423 }
SLScene * s
Definition: SLScene.h:31
The SLScene class represents the top level instance holding the scene structure.
Definition: SLScene.h:47
static std::string model
Definition: Utils.h:293
static std::string get()
Definition: Utils.cpp:1261
static std::string brand
Definition: Utils.h:292
static std::string user
Definition: Utils.h:290
static std::string os
Definition: Utils.h:294
static std::string id
Definition: Utils.h:297
static std::string osVer
Definition: Utils.h:295
static std::string arch
Definition: Utils.h:296
static std::string name
Definition: Utils.h:291
static std::vector< std::string > getAllNamesInDir(const std::string &dirName, bool fullPath=true)
Returns all files and folders in a directory as a vector.
bool exists(std::string path, SLIOStreamKind kind)
Checks whether a given file exists.
Utils provides utilities for string & file handling, logging and math functions.
Definition: Averaged.h:22
string findFile(const string &filename, const vector< string > &pathsToCheck)
Tries to find a filename on various paths to check.
Definition: Utils.cpp:1077
vector< string > getDirNamesInDir(const string &dirName, bool fullPath)
Returns a vector directory names with path in dir.
Definition: Utils.cpp:638
string getDateTime2String()
Returns local time as string like "20190213-154611".
Definition: Utils.cpp:289
string unifySlashes(const string &inputDir, bool withTrailingSlash)
Returns the inputDir string with unified forward slashes, e.g.: "dirA/dirB/".
Definition: Utils.cpp:368
bool fileExists(const string &pathfilename)
Returns true if a file exists.
Definition: Utils.cpp:897
bool dirExists(const string &path)
Returns true if a directory exists.
Definition: Utils.cpp:790
bool makeDir(const string &path)
Creates a directory with given path.
Definition: Utils.cpp:810
T abs(T a)
Definition: Utils.h:249
bool getFileContent(const string &fileName, vector< string > &vecOfStrings)
Returns true if content of file could be put in a vector of strings.
Definition: Utils.cpp:411
unsigned nextPowerOf2(unsigned num)
Returns the next power of 2 to a passed number.
Definition: Utils.cpp:1237
void removeDir(const string &path)
RemoveDir deletes a directory with given path.
Definition: Utils.cpp:854
int lcm(int a, int b)
Definition: Utils.cpp:1215
string getHostName()
Returns the computer name.
Definition: Utils.cpp:310
bool containsString(const string &container, const string &search)
Returns true if container contains the search string.
Definition: Utils.cpp:345
void dumpFileSystemRec(const char *logtag, const string &folderPath)
Dumps all folders and files recursovely.
Definition: Utils.cpp:1051
vector< string > getStringLines(const string &multiLineString)
Returns a vector of string one per line of a multiline string.
Definition: Utils.cpp:195
void errorMsg(const char *tag, const char *msg, const int line, const char *file)
Platform independent error message output.
Definition: Utils.cpp:1168
string getFileNameWOExt(const string &pathFilename)
Returns the filename without extension.
Definition: Utils.cpp:616
bool compareNatural(const string &a, const string &b)
Naturally compares two strings (used for filename sorting)
Definition: Utils.cpp:464
string trimLeftString(const string &s, const string &drop)
trims a string at the left end
Definition: Utils.cpp:144
std::unique_ptr< CustomLog > customLog
custom log instance, e.g. log to a ui log window
Definition: Utils.cpp:82
unsigned int getFileSize(const string &pathfilename)
Returns the file size in bytes.
Definition: Utils.cpp:912
string formatString(string fmt_str,...)
Returns a formatted string as sprintf.
Definition: Utils.cpp:320
string getFileName(const string &pathFilename)
Returns the filename of path-filename string.
Definition: Utils.cpp:580
string replaceNonFilenameChars(string src, const char replaceChar)
replaces non-filename characters: /|?%*:"<>'
Definition: Utils.cpp:244
void splitString(const string &s, char delimiter, vector< string > &splits)
Splits an input string at a delimiter character into a string vector.
Definition: Utils.cpp:152
string getPath(const string &pathFilename)
Returns the path w. '\' of path-filename string.
Definition: Utils.cpp:392
void warnMsg(const char *tag, const char *msg, const int line, const char *file)
Platform independent warn message output.
Definition: Utils.cpp:1145
void exitMsg(const char *tag, const char *msg, const int line, const char *file)
Terminates the application with a message. No leak checking.
Definition: Utils.cpp:1135
string toUpperString(string s)
Returns a string in upper case.
Definition: Utils.cpp:120
static std::unique_ptr< FileLog > fileLog
Definition: Utils.h:198
unsigned int maxThreads()
Returns in release config the max. NO. of threads otherwise 1.
Definition: Utils.cpp:1191
vector< string > getFileNamesInDir(const string &dirName, bool fullPath)
Returns a vector of sorted filesnames in dirName.
Definition: Utils.cpp:737
string getDirName(const string &pathFilename)
Strip last component from file name.
Definition: Utils.cpp:598
void removeFile(const string &path)
RemoveFile deletes a file with given path.
Definition: Utils.cpp:875
vector< string > getAllNamesInDir(const string &dirName, bool fullPath)
Returns a vector of sorted names (files and directories) with path in dir.
Definition: Utils.cpp:691
string getCurrentWorkingDir()
Returns the working directory.
Definition: Utils.cpp:976
unsigned closestPowerOf2(unsigned num)
Returns the closest power of 2 to a passed number.
Definition: Utils.cpp:1221
string getLocalTimeString()
Returns local time as string like "Wed Feb 13 15:46:11 2019".
Definition: Utils.cpp:258
string trimString(const string &s, const string &drop)
Trims a string at both end.
Definition: Utils.cpp:128
string getAppsWritableDir(string appName)
Returns the writable configuration directory.
Definition: Utils.cpp:942
int gcd(int a, int b)
Greatest common divisor of two integer numbers (ggT = grösster gemeinsame Teiler)
Definition: Utils.cpp:1207
string trimRightString(const string &s, const string &drop)
trims a string at the right end
Definition: Utils.cpp:136
bool makeDirRecurse(std::string path)
Definition: Utils.cpp:826
bool startsWithString(const string &container, const string &startStr)
Return true if the container string starts with the startStr.
Definition: Utils.cpp:351
void loopFileSystemRec(const string &path, function< void(string path, string baseName, int depth)> processFile, function< void(string path, string baseName, int depth)> processDir, const int depth)
process all files and folders recursively naturally sorted
Definition: Utils.cpp:1016
string toString(float f, int roundedDecimals)
Returns a string from a float with max. one trailing zero.
Definition: Utils.cpp:92
bool endsWithString(const string &container, const string &endStr)
Return true if the container string ends with the endStr.
Definition: Utils.cpp:357
void replaceString(string &source, const string &from, const string &to)
Replaces in the source string the from string by the to string.
Definition: Utils.cpp:170
bool deleteFile(string &pathfilename)
Deletes a file on the filesystem.
Definition: Utils.cpp:1008
string readTextFileIntoString(const char *logTag, const string &pathAndFilename)
Reads a text file into a string and returns it.
Definition: Utils.cpp:212
string getDateTime1String()
Returns local time as string like "13.02.19-15:46".
Definition: Utils.cpp:269
bool onlyErrorLogs
if this flag is set to true all calls to log get ignored
Definition: Utils.cpp:84
string toLowerString(string s)
Returns a string in lower case.
Definition: Utils.cpp:112
void log(const char *tag, const char *format,...)
logs a formatted string platform independently
Definition: Utils.cpp:1103
void writeStringIntoTextFile(const char *logTag, const string &stringToWrite, const string &pathAndFilename)
Writes a string into a text file.
Definition: Utils.cpp:230
void initFileLog(const string &logDir, bool forceFlush)
Definition: Utils.cpp:1097
string getFileExt(const string &filename)
Returns the file extension without dot in lower case.
Definition: Utils.cpp:629