SLProject  4.3.020
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  std::unique_ptr<char[]> formatted;
327  va_list ap;
328  while (true)
329  {
330  formatted.reset(new char[n]);
331  strcpy(&formatted[0], fmt_str.c_str());
332  va_start(ap, fmt_str);
333  final_n = vsnprintf(&formatted[0], (unsigned long)n, fmt_str.c_str(), ap);
334  va_end(ap);
335  if (final_n < 0 || final_n >= n)
336  n += abs(final_n - n + 1);
337  else
338  break;
339  }
340  return string(formatted.get());
341 }
342 //-----------------------------------------------------------------------------
343 // Returns true if container contains the search string
344 bool containsString(const string& container, const string& search)
345 {
346  return (container.find(search) != string::npos);
347 }
348 //-----------------------------------------------------------------------------
349 // Return true if the container string starts with the startStr
350 bool startsWithString(const string& container, const string& startStr)
351 {
352  return container.find(startStr) == 0;
353 }
354 //-----------------------------------------------------------------------------
355 // Return true if the container string ends with the endStr
356 bool endsWithString(const string& container, const string& endStr)
357 {
358  if (container.length() >= endStr.length())
359  return (0 == container.compare(container.length() - endStr.length(),
360  endStr.length(),
361  endStr));
362  else
363  return false;
364 }
365 //-----------------------------------------------------------------------------
366 // Returns inputDir with unified forward slashes
367 string unifySlashes(const string& inputDir, bool withTrailingSlash)
368 {
369  string copy = inputDir;
370  string curr;
371  string delimiter = "\\";
372  size_t pos = 0;
373  string token;
374  while ((pos = copy.find(delimiter)) != string::npos)
375  {
376  token = copy.substr(0, pos);
377  copy.erase(0, pos + delimiter.length());
378  curr.append(token);
379  curr.append("/");
380  }
381 
382  curr.append(copy);
383 
384  if (withTrailingSlash && !curr.empty() && curr.back() != '/')
385  curr.append("/");
386 
387  return curr;
388 }
389 //-----------------------------------------------------------------------------
390 // Returns the path w. '\\' of path-filename string
391 string getPath(const string& pathFilename)
392 {
393  size_t i1 = pathFilename.rfind('\\', pathFilename.length());
394  size_t i2 = pathFilename.rfind('/', pathFilename.length());
395  if ((i1 != string::npos && i2 == string::npos) ||
396  (i1 != string::npos && i1 > i2))
397  {
398  return (pathFilename.substr(0, i1 + 1));
399  }
400 
401  if ((i2 != string::npos && i1 == string::npos) ||
402  (i2 != string::npos && i2 > i1))
403  {
404  return (pathFilename.substr(0, i2 + 1));
405  }
406  return pathFilename;
407 }
408 //-----------------------------------------------------------------------------
409 // Returns true if content of file could be put in a vector of strings
410 bool getFileContent(const string& fileName,
411  vector<string>& vecOfStrings)
412 {
413 
414  // Open the File
415  std::ifstream in(fileName.c_str());
416 
417  // Check if object is valid
418  if (!in)
419  {
420  std::cerr << "Cannot open the File : " << fileName << std::endl;
421  return false;
422  }
423 
424  // Read the next line from File untill it reaches the end.
425  std::string str;
426  while (std::getline(in, str))
427  {
428  // Line contains string of length > 0 then save it in vector
429  if (!str.empty())
430  vecOfStrings.push_back(str);
431  }
432 
433  // Close The File
434  in.close();
435  return true;
436 }
437 //-----------------------------------------------------------------------------
438 // Naturally compares two strings (used for filename sorting)
439 /*! String comparison as most filesystem do it.
440 Source: https://www.o-rho.com/naturalsort
441 
442 std::sort compareNatural
443 --------- --------------
444 1.txt 1.txt
445 10.txt 1_t.txt
446 1_t.txt 10.txt
447 20 20
448 20.txt 20.txt
449 ABc ABc
450 aBCd aBCd
451 aBCd(01) aBCd(1)
452 aBCd(1) aBCd(01)
453 aBCd(12) aBCd(2)
454 aBCd(2) aBCd(12)
455 aBc aBc
456 aBcd aBcd
457 aaA aaA
458 aaa aaa
459 z10.txt z2.txt
460 z100.txt z10.txt
461 z2.txt z100.txt
462  */
463 bool compareNatural(const string& a, const string& b)
464 {
465  const char* p1 = a.c_str();
466  const char* p2 = b.c_str();
467  const unsigned short st_scan = 0;
468  const unsigned short st_alpha = 1;
469  const unsigned short st_numeric = 2;
470  unsigned short state = st_scan;
471  const char* numstart1 = nullptr;
472  const char* numstart2 = nullptr;
473  const char* numend1 = nullptr;
474  const char* numend2 = nullptr;
475  unsigned long sz1 = 0;
476  unsigned long sz2 = 0;
477 
478  while (*p1 && *p2)
479  {
480  switch (state)
481  {
482  case st_scan:
483  if (!isdigit(*p1) && !isdigit(*p2))
484  {
485  state = st_alpha;
486  if (*p1 == *p2)
487  {
488  p1++;
489  p2++;
490  }
491  else
492  return *p1 < *p2;
493  }
494  else if (isdigit(*p1) && !isdigit(*p2))
495  return true;
496  else if (!isdigit(*p1) && isdigit(*p2))
497  return false;
498  else
499  {
500  state = st_numeric;
501  if (sz1 == 0)
502  while (*p1 == '0')
503  {
504  p1++;
505  sz1++;
506  }
507  else
508  while (*p1 == '0') p1++;
509  if (sz2 == 0)
510  while (*p2 == '0')
511  {
512  p2++;
513  sz2++;
514  }
515  else
516  while (*p2 == '0') p2++;
517  if (sz1 == sz2)
518  {
519  sz1 = 0;
520  sz2 = 0;
521  }
522  if (!isdigit(*p1)) p1--;
523  if (!isdigit(*p2)) p2--;
524  numstart1 = p1;
525  numstart2 = p2;
526  numend1 = numstart1;
527  numend2 = numstart2;
528  }
529  break;
530  case st_alpha:
531  if (!isdigit(*p1) && !isdigit(*p2))
532  {
533  if (*p1 == *p2)
534  {
535  p1++;
536  p2++;
537  }
538  else
539  return *p1 < *p2;
540  }
541  else
542  state = st_scan;
543  break;
544  case st_numeric:
545  while (isdigit(*p1)) numend1 = p1++;
546  while (isdigit(*p2)) numend2 = p2++;
547  if (numend1 - numstart1 == numend2 - numstart2 &&
548  !strncmp(numstart1, numstart2, numend2 - numstart2 + 1))
549  state = st_scan;
550  else
551  {
552  if (numend1 - numstart1 != numend2 - numstart2)
553  return numend1 - numstart1 < numend2 - numstart2;
554  while (*numstart1 && *numstart2)
555  {
556  if (*numstart1 != *numstart2) return *numstart1 < *numstart2;
557  numstart1++;
558  numstart2++;
559  }
560  }
561  break;
562  default: break;
563  }
564  }
565  if (sz1 < sz2) return true;
566  if (sz1 > sz2) return false;
567  if (*p1 == 0 && *p2 != 0) return true;
568  if (*p1 != 0 && *p2 == 0) return false;
569  return false;
570 }
571 //-----------------------------------------------------------------------------
572 
573 /////////////////////////////
574 // File Handling Functions //
575 /////////////////////////////
576 
577 //-----------------------------------------------------------------------------
578 // Returns the filename of path-filename string
579 string getFileName(const string& pathFilename)
580 {
581  size_t i1 = pathFilename.rfind('\\', pathFilename.length());
582  size_t i2 = pathFilename.rfind('/', pathFilename.length());
583  int i = -1;
584 
585  if (i1 != string::npos && i2 != string::npos)
586  i = (int)std::max(i1, i2);
587  else if (i1 != string::npos)
588  i = (int)i1;
589  else if (i2 != string::npos)
590  i = (int)i2;
591 
592  return pathFilename.substr(i + 1, pathFilename.length() - i);
593 }
594 
595 //-----------------------------------------------------------------------------
596 // Returns the path of a path-filename combo
597 string getDirName(const string& pathFilename)
598 {
599  size_t i1 = pathFilename.rfind('\\', pathFilename.length());
600  size_t i2 = pathFilename.rfind('/', pathFilename.length());
601  int i = -1;
602 
603  if (i1 != string::npos && i2 != string::npos)
604  i = (int)std::max(i1, i2);
605  else if (i1 != string::npos)
606  i = (int)i1;
607  else if (i2 != string::npos)
608  i = (int)i2;
609 
610  return pathFilename.substr(0, i + 1);
611 }
612 
613 //-----------------------------------------------------------------------------
614 // Returns the filename without extension
615 string getFileNameWOExt(const string& pathFilename)
616 {
617  string filename = getFileName(pathFilename);
618  size_t i = filename.rfind('.', filename.length());
619  if (i != string::npos)
620  {
621  return (filename.substr(0, i));
622  }
623 
624  return (filename);
625 }
626 //-----------------------------------------------------------------------------
627 // Returns the file extension without dot in lower case
628 string getFileExt(const string& filename)
629 {
630  size_t i = filename.rfind('.', filename.length());
631  if (i != string::npos)
632  return toLowerString(filename.substr(i + 1, filename.length() - i));
633  return ("");
634 }
635 //-----------------------------------------------------------------------------
636 // Returns a vector of unsorted directory names with path in dir
637 vector<string> getDirNamesInDir(const string& dirName, bool fullPath)
638 {
639  vector<string> filePathNames;
640 
641 #if defined(USE_STD_FILESYSTEM)
642  if (fs::exists(dirName) && fs::is_directory(dirName))
643  {
644  for (const auto& entry : fs::directory_iterator(dirName))
645  {
646  auto filename = entry.path().filename();
647  if (fs::is_directory(entry.status()))
648  {
649  if (fullPath)
650  filePathNames.push_back(dirName + "/" + filename.u8string());
651  else
652  filePathNames.push_back(filename.u8string());
653  }
654  }
655  }
656 #else
657  DIR* dir = opendir(dirName.c_str());
658 
659  if (dir)
660  {
661  struct dirent* dirContent = nullptr;
662 
663  while ((dirContent = readdir(dir)) != nullptr)
664  {
665  string name(dirContent->d_name);
666 
667  if (name != "." && name != "..")
668  {
669  struct stat path_stat
670  {
671  };
672  stat((dirName + name).c_str(), &path_stat);
673  if (!S_ISREG(path_stat.st_mode))
674  {
675  if (fullPath)
676  filePathNames.push_back(dirName + "/" + name);
677  else
678  filePathNames.push_back(name);
679  }
680  }
681  }
682  closedir(dir);
683  }
684 #endif
685 
686  return filePathNames;
687 }
688 //-----------------------------------------------------------------------------
689 // Returns a vector of unsorted names (files and directories) with path in dir
690 vector<string> getAllNamesInDir(const string& dirName, bool fullPath)
691 {
692  vector<string> filePathNames;
693 
694 #if defined(USE_STD_FILESYSTEM)
695  if (fs::exists(dirName) && fs::is_directory(dirName))
696  {
697  for (const auto& entry : fs::directory_iterator(dirName))
698  {
699  auto filename = entry.path().filename();
700  if (fullPath)
701  filePathNames.push_back(dirName + "/" + filename.u8string());
702  else
703  filePathNames.push_back(filename.u8string());
704  }
705  }
706 #else
707 # if defined(TARGET_OS_IOS) && (TARGET_OS_IOS == 1)
708  return Utils_iOS::getAllNamesInDir(dirName, fullPath);
709 # else
710  DIR* dir = opendir(dirName.c_str());
711 
712  if (dir)
713  {
714  struct dirent* dirContent = nullptr;
715 
716  while ((dirContent = readdir(dir)) != nullptr)
717  {
718  string name(dirContent->d_name);
719  if (name != "." && name != "..")
720  {
721  if (fullPath)
722  filePathNames.push_back(dirName + "/" + name);
723  else
724  filePathNames.push_back(name);
725  }
726  }
727  closedir(dir);
728  }
729 # endif
730 #endif
731 
732  return filePathNames;
733 }
734 //-----------------------------------------------------------------------------
735 // Returns a vector of unsorted filesnames with path in dir
736 vector<string> getFileNamesInDir(const string& dirName, bool fullPath)
737 {
738  vector<string> filePathNames;
739 
740 #if defined(USE_STD_FILESYSTEM)
741  if (fs::exists(dirName) && fs::is_directory(dirName))
742  {
743  for (const auto& entry : fs::directory_iterator(dirName))
744  {
745  auto filename = entry.path().filename();
746  if (fs::is_regular_file(entry.status()))
747  {
748  if (fullPath)
749  filePathNames.push_back(dirName + "/" + filename.u8string());
750  else
751  filePathNames.push_back(filename.u8string());
752  }
753  }
754  }
755 #else
756  // todo: does this part also return directories? It should only return file names..
757  DIR* dir = opendir(dirName.c_str());
758 
759  if (dir)
760  {
761  struct dirent* dirContent = nullptr;
762 
763  while ((dirContent = readdir(dir)) != nullptr)
764  {
765  string name(dirContent->d_name);
766  if (name != "." && name != "..")
767  {
768  struct stat path_stat
769  {
770  };
771  stat((dirName + name).c_str(), &path_stat);
772  if (S_ISREG(path_stat.st_mode))
773  {
774  if (fullPath)
775  filePathNames.push_back(dirName + name);
776  else
777  filePathNames.push_back(name);
778  }
779  }
780  }
781  closedir(dir);
782  }
783 #endif
784 
785  return filePathNames;
786 }
787 //-----------------------------------------------------------------------------
788 // Returns true if a directory exists.
789 bool dirExists(const string& path)
790 {
791 #if defined(__EMSCRIPTEN__)
792  return true;
793 #elif defined(USE_STD_FILESYSTEM)
794  return fs::exists(path) && fs::is_directory(path);
795 #else
796  struct stat info
797  {
798  };
799  if (stat(path.c_str(), &info) != 0)
800  return false;
801  else if (info.st_mode & S_IFDIR)
802  return true;
803  else
804  return false;
805 #endif
806 }
807 //-----------------------------------------------------------------------------
808 // Creates a directory with given path
809 bool makeDir(const string& path)
810 {
811 #if defined(USE_STD_FILESYSTEM)
812  return fs::create_directories(path);
813 #else
814 # if defined(_WIN32)
815  return _mkdir(path.c_str());
816 # else
817  int failed = mkdir(path.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
818  bool result = !failed;
819  return result;
820 # endif
821 #endif
822 }
823 //-----------------------------------------------------------------------------
824 // Creates a directory with given path recursively
825 bool makeDirRecurse(std::string path)
826 {
827  std::string delimiter = "/";
828 
829  size_t pos = 0;
830  std::string createdPath;
831 
832  while ((pos = path.find(delimiter)) != std::string::npos)
833  {
834  createdPath += path.substr(0, pos) + "/";
835 
836  if (!dirExists(createdPath))
837  {
838  if (!makeDir(createdPath))
839  {
840  return false;
841  }
842  }
843 
844  path.erase(0, pos + delimiter.length());
845  }
846 
847  return true;
848 }
849 //-----------------------------------------------------------------------------
850 // Removes a directory with given path
851 void removeDir(const string& path)
852 {
853 
854 #if defined(USE_STD_FILESYSTEM)
855  fs::remove_all(path);
856 #else
857 # if defined(_WIN32)
858  int ret = _rmdir(path.c_str());
859  if (ret != 0)
860  {
861  errno_t err;
862  _get_errno(&err);
863  log("Could not remove directory: %s\nErrno: %s\n", path.c_str(), strerror(errno));
864  }
865 # else
866  rmdir(path.c_str());
867 # endif
868 #endif
869 }
870 //-----------------------------------------------------------------------------
871 // Removes a file with given path
872 void removeFile(const string& path)
873 {
874  if (fileExists(path))
875  {
876 #if defined(USE_STD_FILESYSTEM)
877  fs::remove(path);
878 #else
879 # if defined(_WIN32)
880  DeleteFileA(path.c_str());
881 # else
882  unlink(path.c_str());
883 # endif
884 
885 #endif
886  }
887  else
888  log("Could not remove file : %s\nErrno: %s\n",
889  path.c_str(),
890  "file does not exist");
891 }
892 //-----------------------------------------------------------------------------
893 // Returns true if a file exists.
894 bool fileExists(const string& pathfilename)
895 {
896 #if defined(__EMSCRIPTEN__)
897  return false;
898 #elif defined(USE_STD_FILESYSTEM)
899  return fs::exists(pathfilename);
900 #else
901  struct stat info
902  {
903  };
904  return (stat(pathfilename.c_str(), &info) == 0) && ((info.st_mode & S_IFDIR) == 0);
905 #endif
906 }
907 //-----------------------------------------------------------------------------
908 // Returns the file size in bytes
909 unsigned int getFileSize(const string& pathfilename)
910 {
911 #if defined(USE_STD_FILESYSTEM)
912  if (fs::exists(pathfilename))
913  return (unsigned int)fs::file_size(pathfilename);
914  else
915  return 0;
916 #else
917  struct stat st
918  {
919  };
920  if (stat(pathfilename.c_str(), &st) != 0)
921  return 0;
922  return (unsigned int)st.st_size;
923 #endif
924 }
925 //-----------------------------------------------------------------------------
926 // Returns the file size in bytes
927 unsigned int getFileSize(std::ifstream& fs)
928 {
929  fs.seekg(0, std::ios::beg);
930  std::streampos begin = fs.tellg();
931  fs.seekg(0, std::ios::end);
932  std::streampos end = fs.tellg();
933  fs.seekg(0, std::ios::beg);
934  return (unsigned int)(end - begin);
935 }
936 
937 //-----------------------------------------------------------------------------
938 // Returns the writable configuration directory with trailing forward slash
939 string getAppsWritableDir(string appName)
940 {
941 #if defined(_WIN32)
942  string appData = getenv("APPDATA");
943  string configDir = appData + "/" + appName;
944  replaceString(configDir, "\\", "/");
945  if (!dirExists(configDir))
946  makeDir(configDir.c_str());
947  return configDir + "/";
948 #elif defined(__APPLE__)
949  string home = getenv("HOME");
950  string appData = home + "/Library/Application Support";
951  string configDir = appData + "/" + appName;
952  if (!dirExists(configDir))
953  mkdir(configDir.c_str(), S_IRWXU);
954  return configDir + "/";
955 #elif defined(ANDROID) || defined(ANDROID_NDK)
956  // @todo Where is the app data path on Andoroid?
957 #elif defined(linux) || defined(__linux) || defined(__linux__)
958  // @todo Where is the app data path on Linux?
959  string home = getenv("HOME");
960  string configDir = home + "/." + appName;
961  if (!dirExists(configDir))
962  mkdir(configDir.c_str(), S_IRWXU | S_IRWXG | S_IRWXO);
963  return configDir + "/";
964 #elif defined(__EMSCRIPTEN__)
965  return "?";
966 #else
967 # error "No port to this OS"
968 #endif
969  return "";
970 }
971 //-----------------------------------------------------------------------------
972 // Returns the working directory with forward slashes inbetween and at the end
974 {
975 #if defined(_WIN32)
976 # if defined(USE_STD_FILESYSTEM)
977  return fs::current_path().u8string();
978 # else
979  int size = 256;
980  char* buffer = (char*)malloc(size);
981  if (_getcwd(buffer, size) == buffer)
982  {
983  string dir = buffer;
984  replaceString(dir, "\\", "/");
985  return dir + "/";
986  }
987 
988  free(buffer);
989  return "";
990 # endif
991 #elif !defined(__EMSCRIPTEN__)
992  size_t size = 256;
993  char* buffer = (char*)malloc(size);
994  if (getcwd(buffer, size) == buffer)
995  return string(buffer) + "/";
996 
997  free(buffer);
998  return "";
999 #else
1000  return "/";
1001 #endif
1002 }
1003 //-----------------------------------------------------------------------------
1004 // Deletes a file on the filesystem
1005 bool deleteFile(string& pathfilename)
1006 {
1007  if (fileExists(pathfilename))
1008  return remove(pathfilename.c_str()) != 0;
1009  return false;
1010 }
1011 //-----------------------------------------------------------------------------
1012 // process all files and folders recursively naturally sorted
1013 void loopFileSystemRec(const string& path,
1014  function<void(string path, string baseName, int depth)> processFile,
1015  function<void(string path, string baseName, int depth)> processDir,
1016  const int depth)
1017 {
1018  // be sure that the folder slashes are correct
1019  string folder = unifySlashes(path);
1020 
1021  if (dirExists(folder))
1022  {
1023  vector<string> unsortedNames = getAllNamesInDir(folder);
1024 
1025  processDir(getDirName(trimRightString(folder, "/")),
1026  getFileName(trimRightString(folder, "/")),
1027  depth);
1028  sort(unsortedNames.begin(), unsortedNames.end(), Utils::compareNatural);
1029 
1030  for (const auto& fileOrFolder : unsortedNames)
1031  {
1032  if (dirExists(fileOrFolder))
1033  loopFileSystemRec(fileOrFolder, processFile, processDir, depth + 1);
1034  else
1035  processFile(folder, getFileName(fileOrFolder), depth);
1036  }
1037  }
1038  else
1039  {
1040  processFile(getDirName(trimRightString(path, "/")),
1041  getFileName(trimRightString(path, "/")),
1042  depth);
1043  }
1044 }
1045 
1046 //-----------------------------------------------------------------------------
1047 // Dumps all files and folders on stdout recursively naturally sorted
1048 void dumpFileSystemRec(const char* logtag, const string& folderPath)
1049 {
1050  const char* tab = " ";
1051 
1053  folderPath,
1054  [logtag, tab](string path, string baseName, int depth) -> void {
1055  string indent;
1056  for (int d = 0; d < depth; ++d)
1057  indent += tab;
1058  string indentFolderName = indent + baseName;
1059  Utils::log(logtag, "%s", indentFolderName.c_str());
1060  },
1061  [logtag, tab](string path, string baseName, int depth) -> void {
1062  string indent;
1063  for (int d = 0; d < depth; ++d)
1064  indent += tab;
1065  string indentFolderName = indent + "[" + baseName + "]";
1066  Utils::log(logtag, "%s", indentFolderName.c_str());
1067  });
1068 }
1069 //-----------------------------------------------------------------------------
1070 // findFile return the full path with filename
1071 /* Unfortunatelly the relative folder structure on different OS are not identical.
1072  * This function allows to search on for a file on different paths.
1073  */
1074 string findFile(const string& filename, const vector<string>& pathsToCheck)
1075 {
1076  if (Utils::fileExists(filename))
1077  return filename;
1078 
1079  // Check file existence
1080  for (const auto& path : pathsToCheck)
1081  {
1082  string pathPlusFilename = Utils::unifySlashes(path) + filename;
1083  if (Utils::fileExists(pathPlusFilename))
1084  return pathPlusFilename;
1085  }
1086  return "";
1087 }
1088 //----------------------------------------------------------------------------
1089 
1090 ///////////////////////
1091 // Logging Functions //
1092 ///////////////////////
1093 //-----------------------------------------------------------------------------
1094 void initFileLog(const string& logDir, bool forceFlush)
1095 {
1096  fileLog = std::make_unique<FileLog>(logDir, forceFlush);
1097 }
1098 //-----------------------------------------------------------------------------
1099 // logs a formatted string platform independently
1100 void log(const char* tag, const char* format, ...)
1101 {
1102  char log[4096];
1103 
1104  va_list argptr;
1105  va_start(argptr, format);
1106  vsnprintf(log, sizeof(log), format, argptr);
1107  va_end(argptr);
1108 
1109  char msg[4096];
1110  strcpy(msg, tag);
1111  strcat(msg, ": ");
1112  strcat(msg, log);
1113  strcat(msg, "\n");
1114 
1115  if (fileLog)
1116  fileLog->post(msg);
1117 
1118  if (customLog)
1119  customLog->post(msg);
1120 
1122  return;
1123 
1124 #if defined(ANDROID) || defined(ANDROID_NDK)
1125  __android_log_print(ANDROID_LOG_INFO, tag, msg);
1126 #else
1127  std::cout << msg << std::flush;
1128 #endif
1129 }
1130 //-----------------------------------------------------------------------------
1131 // Terminates the application with a message. No leak checking.
1132 void exitMsg(const char* tag,
1133  const char* msg,
1134  const int line,
1135  const char* file)
1136 {
1137  errorMsg(tag, msg, line, file);
1138  exit(-1);
1139 }
1140 //-----------------------------------------------------------------------------
1141 // Warn message output
1142 void warnMsg(const char* tag,
1143  const char* msg,
1144  const int line,
1145  const char* file)
1146 {
1147 #if defined(ANDROID) || defined(ANDROID_NDK)
1148  __android_log_print(ANDROID_LOG_WARN,
1149  tag,
1150  "Warning: %s at line %d in %s\n",
1151  msg,
1152  line,
1153  file);
1154 #else
1155  std::cout << "--------------------------------\n"
1156  << "Warning:\n"
1157  << "Tag: " << tag << '\n'
1158  << "Location: " << file << ":" << line << '\n'
1159  << "Message: " << msg << '\n'
1160  << "--------------------------------" << std::endl;
1161 #endif
1162 }
1163 //-----------------------------------------------------------------------------
1164 // Error message output (same as warn but with another tag for android)
1165 void errorMsg(const char* tag,
1166  const char* msg,
1167  const int line,
1168  const char* file)
1169 {
1170 #if defined(ANDROID) || defined(ANDROID_NDK)
1171  __android_log_print(ANDROID_LOG_ERROR,
1172  tag,
1173  "Error: %s at line %d in %s\n",
1174  msg,
1175  line,
1176  file);
1177 #else
1178  std::cout << "--------------------------------\n"
1179  << "Error:\n"
1180  << "Tag: " << tag << '\n'
1181  << "Location: " << file << ":" << line << '\n'
1182  << "Message: " << msg << '\n'
1183  << "--------------------------------" << std::endl;
1184 #endif
1185 }
1186 //-----------------------------------------------------------------------------
1187 // Returns in release config the max. NO. of threads otherwise 1
1188 unsigned int maxThreads()
1189 {
1190 #if defined(DEBUG) || defined(_DEBUG)
1191  return 1;
1192 #else
1193  return std::max(std::thread::hardware_concurrency(), 1U);
1194 #endif
1195 }
1196 //-----------------------------------------------------------------------------
1197 
1198 ////////////////////
1199 // Math Utilities //
1200 ////////////////////
1201 
1202 //-----------------------------------------------------------------------------
1203 // Greatest common divisor of two integer numbers (ggT = grösster gemeinsame Teiler)
1204 int gcd(int a, int b)
1205 {
1206  if (b == 0)
1207  return a;
1208  return gcd(b, a % b);
1209 }
1210 //-----------------------------------------------------------------------------
1211 // Lowest common multiple (kgV = kleinstes gemeinsames Vielfache)
1212 int lcm(int a, int b)
1213 {
1214  return (a * b) / Utils::gcd(a, b);
1215 }
1216 //-----------------------------------------------------------------------------
1217 // Returns the closest power of 2 to a passed number.
1218 unsigned closestPowerOf2(unsigned num)
1219 {
1220  unsigned nextPow2 = 1;
1221  if (num <= 0) return 1;
1222 
1223  while (nextPow2 <= num)
1224  nextPow2 <<= 1;
1225  unsigned prevPow2 = nextPow2 >> 1;
1226 
1227  if (num - prevPow2 < nextPow2 - num)
1228  return prevPow2;
1229  else
1230  return nextPow2;
1231 }
1232 //-----------------------------------------------------------------------------
1233 // Returns the next power of 2 to a passed number.
1234 unsigned nextPowerOf2(unsigned num)
1235 {
1236  unsigned nextPow2 = 1;
1237  if (num == 0) return 1;
1238 
1239  while (nextPow2 <= num)
1240  nextPow2 <<= 1;
1241  return nextPow2;
1242 }
1243 //-----------------------------------------------------------------------------
1244 
1245 //-----------------------------------------------------------------------------
1246 // ComputerInfos
1247 //-----------------------------------------------------------------------------
1248 std::string ComputerInfos::user = "USER?";
1249 std::string ComputerInfos::name = "NAME?";
1250 std::string ComputerInfos::brand = "BRAND?";
1251 std::string ComputerInfos::model = "MODEL?";
1252 std::string ComputerInfos::os = "OS?";
1253 std::string ComputerInfos::osVer = "OSVER?";
1254 std::string ComputerInfos::arch = "ARCH?";
1255 std::string ComputerInfos::id = "ID?";
1256 
1257 //-----------------------------------------------------------------------------
1258 std::string ComputerInfos::get()
1259 {
1260 #if defined(_WIN32) //..................................................
1261 
1262  // Computer user name
1263  const char* envvar = std::getenv("USER");
1264  user = envvar ? string(envvar) : "USER?";
1265  if (user == "USER?")
1266  {
1267  const char* envvar = std::getenv("USERNAME");
1268  user = envvar ? string(envvar) : "USER?";
1269  }
1271 
1272  // Get architecture
1273  SYSTEM_INFO siSysInfo;
1274  GetSystemInfo(&siSysInfo);
1275  switch (siSysInfo.wProcessorArchitecture)
1276  {
1277  case PROCESSOR_ARCHITECTURE_AMD64: arch = "x64"; break;
1278  case PROCESSOR_ARCHITECTURE_ARM: arch = "ARM"; break;
1279  case 12: arch = "ARM64"; break; // PROCESSOR_ARCHITECTURE_ARM64
1280  case PROCESSOR_ARCHITECTURE_IA64: arch = "IA64"; break;
1281  case PROCESSOR_ARCHITECTURE_INTEL: arch = "x86"; break;
1282  default: arch = "???";
1283  }
1284 
1285  // Windows OS version. GetVersionEx is deprecated since Windows 8.1 and
1286  // reports 6.2 for anything newer unless the app ships a compatibility
1287  // manifest, which none of our apps do. RtlGetVersion is not subject to
1288  // that shimming. It is resolved dynamically to avoid a DDK dependency.
1289  RTL_OSVERSIONINFOW osInfo;
1290  ZeroMemory(&osInfo, sizeof(osInfo));
1291  osInfo.dwOSVersionInfoSize = sizeof(osInfo);
1292 
1293  typedef LONG(WINAPI * RtlGetVersionPtr)(PRTL_OSVERSIONINFOW);
1294  if (HMODULE ntdll = GetModuleHandleW(L"ntdll.dll"))
1295  {
1296  auto rtlGetVersion = reinterpret_cast<RtlGetVersionPtr>(
1297  GetProcAddress(ntdll, "RtlGetVersion"));
1298  if (rtlGetVersion)
1299  rtlGetVersion(&osInfo);
1300  }
1301 
1302  // The build number is included because Windows 10 and 11 both report 10.0
1303  // and only the build (>= 22000 is Windows 11) tells them apart.
1304  char osVersion[50];
1305  snprintf(osVersion,
1306  sizeof(osVersion),
1307  "%lu.%lu.%lu",
1308  osInfo.dwMajorVersion,
1309  osInfo.dwMinorVersion,
1310  osInfo.dwBuildNumber);
1311  osVer = string(osVersion);
1312 
1313  brand = "BRAND?";
1314  model = "MODEL?";
1315  os = "Windows";
1316 
1317 #elif defined(__APPLE__)
1318 # if defined(TARGET_OS_IOS) && (TARGET_OS_IOS == 1)
1319  // Model and architecture are retrieved before in iOS under Objective C
1320  brand = "Apple";
1321  os = "iOS";
1322  const char* envvar = std::getenv("USER");
1323  user = envvar ? string(envvar) : "USER?";
1324  if (user == "USER?")
1325  {
1326  const char* envvar = std::getenv("USERNAME");
1327  user = envvar ? string(envvar) : "USER?";
1328  }
1330 # else
1331  // Computer user name
1332  const char* envvar = std::getenv("USER");
1333  user = envvar ? string(envvar) : "USER?";
1334 
1335  if (user == "USER?")
1336  {
1337  const char* envvarUN = std::getenv("USERNAME");
1338  user = envvarUN ? string(envvarUN) : "USER?";
1339  }
1340 
1342  brand = "Apple";
1343  os = "MacOS";
1344 
1345  // Get MacOS version
1346  // SInt32 majorV, minorV, bugfixV;
1347  // Gestalt(gestaltSystemVersionMajor, &majorV);
1348  // Gestalt(gestaltSystemVersionMinor, &minorV);
1349  // Gestalt(gestaltSystemVersionBugFix, &bugfixV);
1350  // char osVer[50];
1351  // sprintf(osVer, "%d.%d.%d", majorV, minorV, bugfixV);
1352  // osVer = string(osVer);
1353 
1354  // Get model
1355  // size_t len = 0;
1356  // sysctlbyname("hw.model", nullptr, &len, nullptr, 0);
1357  // char model[255];
1358  // sysctlbyname("hw.model", model, &len, nullptr, 0);
1359  // model = model;
1360 # endif
1361 
1362 #elif defined(ANDROID) //................................................
1363 
1364  os = "Android";
1365 
1366  /*
1367  "ro.build.version.release" // * The user-visible version string. E.g., "1.0" or "3.4b5".
1368  "ro.build.version.incremental" // The internal value used by the underlying source control to represent this build.
1369  "ro.build.version.codename" // The current development codename, or the string "REL" if this is a release build.
1370  "ro.build.version.sdk" // The user-visible SDK version of the framework.
1371 
1372  "ro.product.model" // * The end-user-visible name for the end product..
1373  "ro.product.manufacturer" // The manufacturer of the product/hardware.
1374  "ro.product.board" // The name of the underlying board, like "goldfish".
1375  "ro.product.brand" // The brand (e.g., carrier) the software is customized for, if any.
1376  "ro.product.device" // The name of the industrial design.
1377  "ro.product.name" // The name of the overall product.
1378  "ro.hardware" // The name of the hardware (from the kernel command line or /proc).
1379  "ro.product.cpu.abi" // The name of the instruction set (CPU type + ABI convention) of native code.
1380  "ro.product.cpu.abi2" // The name of the second instruction set (CPU type + ABI convention) of native code.
1381 
1382  "ro.build.display.id" // * A build ID string meant for displaying to the user.
1383  "ro.build.host"
1384  "ro.build.user"
1385  "ro.build.id" // Either a changelist number, or a label like "M4-rc20".
1386  "ro.build.type" // The type of build, like "user" or "eng".
1387  "ro.build.tags" // Comma-separated tags describing the build, like "unsigned,debug".
1388  */
1389 
1390  int len;
1391 
1392  char hostC[PROP_VALUE_MAX];
1393  len = __system_property_get("ro.build.host", hostC);
1394  name = !string(hostC).empty() ? string(hostC) : "NAME?";
1395 
1396  char userC[PROP_VALUE_MAX];
1397  len = __system_property_get("ro.build.user", userC);
1398  user = !string(userC).empty() ? string(userC) : "USER?";
1399 
1400  char brandC[PROP_VALUE_MAX];
1401  len = __system_property_get("ro.product.brand", brandC);
1402  brand = string(brandC);
1403 
1404  char modelC[PROP_VALUE_MAX];
1405  len = __system_property_get("ro.product.model", modelC);
1406  model = string(modelC);
1407 
1408  char osVerC[PROP_VALUE_MAX];
1409  len = __system_property_get("ro.build.version.release", osVerC);
1410  osVer = string(osVerC);
1411 
1412  char archC[PROP_VALUE_MAX];
1413  len = __system_property_get("ro.product.cpu.abi", archC);
1414  arch = string(archC);
1415 
1416 #elif defined(linux) || defined(__linux) || defined(__linux__) //..................................................
1417 
1418  os = "Linux";
1419  user = "USER?";
1421  brand = "BRAND?";
1422  model = "MODEL?";
1423  osVer = "OSVER?";
1424  arch = "ARCH?";
1425 #endif
1426 
1427  // build a unique as possible ID string that can be used in a filename
1428  id = user + "-" + name + "-" + model;
1429  if (model.find("SM-") != string::npos)
1430  // Don't use computerName on Samsung phones. It's not constant!
1431  id = user + "-" + model;
1432  else
1433  id = user + "-" + name + "-" + model;
1435  std::replace(id.begin(), id.end(), '_', '-');
1436  return id;
1437 }
1438 //-----------------------------------------------------------------------------
1439 }
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:1258
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:1074
vector< string > getDirNamesInDir(const string &dirName, bool fullPath)
Returns a vector directory names with path in dir.
Definition: Utils.cpp:637
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:367
bool fileExists(const string &pathfilename)
Returns true if a file exists.
Definition: Utils.cpp:894
bool dirExists(const string &path)
Returns true if a directory exists.
Definition: Utils.cpp:789
bool makeDir(const string &path)
Creates a directory with given path.
Definition: Utils.cpp:809
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:410
unsigned nextPowerOf2(unsigned num)
Returns the next power of 2 to a passed number.
Definition: Utils.cpp:1234
void removeDir(const string &path)
RemoveDir deletes a directory with given path.
Definition: Utils.cpp:851
int lcm(int a, int b)
Definition: Utils.cpp:1212
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:344
void dumpFileSystemRec(const char *logtag, const string &folderPath)
Dumps all folders and files recursovely.
Definition: Utils.cpp:1048
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:1165
string getFileNameWOExt(const string &pathFilename)
Returns the filename without extension.
Definition: Utils.cpp:615
bool compareNatural(const string &a, const string &b)
Naturally compares two strings (used for filename sorting)
Definition: Utils.cpp:463
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:909
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:579
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:391
void warnMsg(const char *tag, const char *msg, const int line, const char *file)
Platform independent warn message output.
Definition: Utils.cpp:1142
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:1132
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:1188
vector< string > getFileNamesInDir(const string &dirName, bool fullPath)
Returns a vector of sorted filesnames in dirName.
Definition: Utils.cpp:736
string getDirName(const string &pathFilename)
Strip last component from file name.
Definition: Utils.cpp:597
void removeFile(const string &path)
RemoveFile deletes a file with given path.
Definition: Utils.cpp:872
vector< string > getAllNamesInDir(const string &dirName, bool fullPath)
Returns a vector of sorted names (files and directories) with path in dir.
Definition: Utils.cpp:690
string getCurrentWorkingDir()
Returns the working directory.
Definition: Utils.cpp:973
unsigned closestPowerOf2(unsigned num)
Returns the closest power of 2 to a passed number.
Definition: Utils.cpp:1218
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:939
int gcd(int a, int b)
Greatest common divisor of two integer numbers (ggT = grösster gemeinsame Teiler)
Definition: Utils.cpp:1204
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:825
bool startsWithString(const string &container, const string &startStr)
Return true if the container string starts with the startStr.
Definition: Utils.cpp:350
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:1013
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:356
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:1005
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:1100
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:1094
string getFileExt(const string &filename)
Returns the file extension without dot in lower case.
Definition: Utils.cpp:628