TrueReality  v0.1.1912
PathUtils.cpp
Go to the documentation of this file.
1 /*
2 * True Reality Open Source Game and Simulation Engine
3 * Copyright © 2021 Acid Rain Studios LLC
4 *
5 * The Base of this class has been adopted from the Delta3D engine
6 *
7 * This library is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU Lesser General Public License as published by the Free
9 * Software Foundation; either version 3.0 of the License, or (at your option)
10 * any later version.
11 *
12 * This library is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
15 * details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this library; if not, write to the Free Software Foundation, Inc.,
19 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 *
21 * @author David Guthrie
22 * @author John K. Grant
23 * @author William E. Johnson II
24 * @author Chris Osborn
25 * @author Maxim Serebrennik
26 */
27 
28 #include <trUtil/PathUtils.h>
29 
30 #include <trUtil/EnvVariables.h>
31 #include <trUtil/FileUtils.h>
32 #include <trUtil/PlatformMacros.h>
33 #include <trUtil/StringUtils.h>
34 #include <trUtil/Logging/Log.h>
35 
36 #include <osgDB/FileUtils>
37 #include <osgDB/FileNameUtils>
38 
39 #ifdef TR_APPLE
40  #include <AvailabilityMacros.h>
41  #include <Foundation/Foundation.h>
42 #endif
43 
44 #ifdef TR_WIN
45  #include <Shlobj.h>
46 #else
47  #include <pwd.h>
48  #include <unistd.h>
49 #endif
50 
51 namespace trUtil::PathUtils
52 {
53  static OpenThreads::Mutex gDatapathMutex;
54 
56 
58  std::string GetUserHomeDirectory()
59  {
60  std::string homedir;
61 #ifdef TR_WIN
62  char path[MAX_PATH];
63  if (SUCCEEDED(SHGetFolderPathA(nullptr, CSIDL_PROFILE, nullptr, 0, path))) {
64  homedir = path;
65  }
66 #else
67  int maxSize = sysconf(_SC_GETPW_R_SIZE_MAX);
68  char* buffer = new char[maxSize];
69  struct passwd pw, *resultOut = NULL;
70  int rc = getpwuid_r(getuid(), &pw, buffer, maxSize, &resultOut);
71  if (rc == 0 && resultOut != NULL)
72  {
73  homedir = pw.pw_dir;
74  }
75  delete[] buffer;
76  buffer = NULL;
77 #endif
78  return homedir;
79  }
80 
82  std::string GetDataPath()
83  {
84  std::string result;
85 
86  if (mDataPath != trUtil::StringUtils::STR_BLANK)
87  {
88  result = mDataPath;
89  }
90  else
91  {
93  {
95  }
96  else
97  {
98  result = GetRootPath() + DATA_PATH_DEFAULT;
99  }
100  mDataPath = result;
101  }
102 #ifdef TR_APPLE
103  // Have to recheck because the get environment call doesn't currently return empty when it doesn't exist.
104  char* ptr = getenv(EnvVariables::TR_DATA);
105 
106  if (mDataPath != trUtil::StringUtils::STR_BLANK)
107  {
108  result = mDataPath;
109  }
110  else if(ptr == NULL)
111  {
112  result = GetBundleResourcesPath() + DATA_PATH_DEFAULT;
113  }
114 #endif
115 
116  return result;
117  }
118 
120  void SetDataPath(std::string& path)
121  {
122  mDataPath = path;
123  }
124 
127  {
128  try
129  {
139  }
140  catch (const trUtil::Exception& ex)
141  {
142  ex.LogException();
143  }
144  }
145 
148  {
149  try
150  {
160  }
161  catch (const trUtil::Exception& ex)
162  {
163  ex.LogException();
164  }
165  }
166 
169  {
170  try
171  {
174  }
175  catch (const trUtil::Exception& ex)
176  {
177  ex.LogException();
178  }
179  }
180 
182  std::string GetRootPath()
183  {
184  std::string result;
186  {
188  }
189  else
190  {
191  //The Root folder should be one level up from the Bin folder, so just return the parent
192  result = "../";
193  }
194 #ifdef TR_APPLE
195  // Have to recheck because the get environment call doesn't currently return empty when it doesn't exist.
196  char* ptr = getenv(EnvVariables::TR_ROOT);
197  if (ptr == NULL)
198  {
199  result = GetBundleResourcesPath();
200  }
201 #endif
202  return result;
203  }
204 
206  std::string GetLogPath()
207  {
209  {
211  }
212  else
213  {
214  return GetUserDataPath();
215  }
216  }
217 
219  std::string GetUserDataPath()
220  {
222  {
224  }
225  else
226  {
227  std::string userDir;
228 #ifdef TR_WIN
229  char path[MAX_PATH];
230  if (SUCCEEDED(SHGetFolderPathA(nullptr, CSIDL_MYDOCUMENTS, nullptr, 0, path)))
231  {
232  userDir = path + DEFAULT_TR_FOLDER;
233  }
234 #else
236 #endif
237  return userDir;
238  }
239  }
240 
242  void SetDataFilePathList(const std::string& pathList)
243  {
244  OpenThreads::ScopedLock<OpenThreads::Mutex> lock(gDatapathMutex);
245 
246  std::string modpath = pathList;
247  std::string::size_type pathLength = pathList.size();
248  for (std::string::size_type i = 0; i < pathLength; ++i)
249  {
250 #ifdef TR_WIN
251  try
252  {
253  // TODO: Determine why this silly thing is even being done.
254  // Did anyone consider that this would destroy a path with
255  // drive letter such as C:/... ? How about we do not concatenate
256  // paths with colons? CR
257  if (modpath.at(i) == ':' && (i + 1 >= pathLength || modpath.at(i + 1) != '\\'))
258  {
259  modpath.at(i) = ';';
260  }
261  }
262  catch (std::out_of_range &myexcept)
263  {
264  LOG_W(myexcept.what());
265  }
266 #else
267  if (modpath[i] == ';')
268  {
269  modpath[i] = ':';
270  }
271 #endif
272  }
273  osgDB::setDataFilePathList(modpath);
274  }
275 
277  std::string GetDataFilePathList()
278  {
279  OpenThreads::ScopedLock<OpenThreads::Mutex> lock(gDatapathMutex);
280 
281  osgDB::FilePathList pathList = osgDB::getDataFilePathList();
282 
283  std::string pathString = "";
284 
285  using StringDeque = std::deque<std::string>;
286  for (StringDeque::iterator itr = pathList.begin(); itr != pathList.end(); ++itr)
287  {
288  pathString += *itr;
289 
290  StringDeque::iterator next = itr + 1; if (next != pathList.end())
291  {
292 #ifdef TR_WIN
293  pathString += ';';
294 #else
295  pathString += ':';
296 #endif
297  }
298  }
299 
300  return pathString;
301  }
302 
304  std::string FindFile(const std::string& fileName)
305  {
306  OpenThreads::ScopedLock<OpenThreads::Mutex> lock(gDatapathMutex);
307 
308  std::string filePath = osgDB::findDataFile(fileName, osgDB::CASE_INSENSITIVE);
309 
310  // In some cases, filePath will contain a url that is
311  // relative to the current working directory so for
312  // consistency, be sure to return the full path every time
313  if (!filePath.empty())
314  {
315  filePath = osgDB::getRealPath(filePath);
316  }
317 
318  return filePath;
319 
320  }
321 
323  std::string FindFile(const std::string& fileName, std::vector<std::string> pathList, bool caseInsensitive)
324  {
325  std::vector<std::string>::const_iterator itor;
326 
328  std::string path;
329  for (itor = pathList.begin(); itor != pathList.end(); ++itor)
330  {
331  path = *itor;
332  //Make sure we remove any trailing slashes from the cache path.
333  if (path[path.length() - 1] == '/' || path[path.length() - 1] == '\\')
334  path = path.substr(0, path.length() - 1);
335 
336  FileInfo fi = fileUtils.GetFileInfo(path + FileUtils::PATH_SEPARATOR + fileName, caseInsensitive);
337  if (fi.fileType != FILE_NOT_FOUND)
338  {
339  return fi.fileName;
340  }
341  }
342 
343  return std::string();
344  }
345 
347  std::string GetEnvironment(const std::string& env)
348  {
349 #ifdef TR_WIN
350  const size_t bufferSize = 32767;
351  TCHAR buffer[bufferSize], buffer2[bufferSize];
352  size_t sizeOut1 = GetEnvironmentVariable(env.c_str(), buffer, bufferSize);
353  size_t sizeOut2 = ExpandEnvironmentStrings(buffer, buffer2, bufferSize);
354  if (sizeOut1 <= bufferSize && sizeOut2 <= bufferSize && sizeOut1 > 0 && sizeOut2 > 0)
355  {
356  return buffer2;
357  }
358 #endif
359  char* ptr = getenv(env.c_str());
360  if (ptr != nullptr)
361  {
362  return std::string(ptr);
363  }
364  else
365  {
366  return std::string("./");
367  }
368  }
369 
371  void SetEnvironment(const std::string& name, const std::string& value)
372  {
373 #ifdef TR_WIN
374  //technically we have to do both because windows has two different environments
375  SetEnvironmentVariable(name.c_str(), value.c_str());
376  _putenv_s(name.c_str(), value.c_str());
377 #else
378  setenv(name.c_str(), value.c_str(), true);
379 #endif
380  }
381 
382 #ifdef TR_APPLE
383  std::string GetBundleResourcesPath()
385  {
386  // Since this is currently the only Objective-C code in the
387  // library, we need an autoreleasepool for obj-c memory management.
388  // If more Obj-C is added, we might move this pool to another
389  // location so it can be shared. Pools seem to be stackable,
390  // so I don't think there will be a problem if multiple pools
391  // exist at a time.
392  NSAutoreleasePool* mypool = [[NSAutoreleasePool alloc] init];
393 
394  // This is the path to the resources inside the app bundle.
395  NSString* resourcePathNS = [[NSBundle mainBundle] resourcePath];
396 
397  // Make a c string from the cocoa one tack data on the end.
398  std::string result = std::string([resourcePathNS UTF8String]);
399 
400  // Clean up the autorelease pool
401  [mypool release];
402  return result;
403  }
404 
406  std::string GetBundlePlugInsPath()
407  {
408  // Since this is currently the only Objective-C code in the
409  // library, we need an autoreleasepool for obj-c memory management.
410  // If more Obj-C is added, we might move this pool to another
411  // location so it can be shared. Pools seem to be stackable,
412  // so I don't think there will be a problem if multiple pools
413  // exist at a time.
414  NSAutoreleasePool* mypool = [[NSAutoreleasePool alloc] init];
415 
416  // This is the path to the resources inside the app bundle.
417  NSString* resourcePathNS = [[NSBundle mainBundle] builtInPlugInsPath];
418 
419  // Make a c string from the cocoa one tack data on the end.
420  std::string result = std::string([resourcePathNS UTF8String]);
421 
422  // Clean up the autorelease pool
423  [mypool release];
424  return result;
425  }
426 
428  std::string GetBundlePath()
429  {
430  // Since this is currently the only Objective-C code in the
431  // library, we need an autoreleasepool for obj-c memory management.
432  // If more Obj-C is added, we might move this pool to another
433  // location so it can be shared. Pools seem to be stackable,
434  // so I don't think there will be a problem if multiple pools
435  // exist at a time.
436  NSAutoreleasePool* mypool = [[NSAutoreleasePool alloc] init];
437 
438  // This is the path to the resources inside the app bundle.
439  NSString* resourcePathNS = [[NSBundle mainBundle] bundlePath];
440 
441  // Make a c string from the cocoa one tack data on the end.
442  std::string result = std::string([resourcePathNS UTF8String]);
443 
444  // Clean up the autorelease pool
445  [mypool release];
446  return result;
447  }
448 
450  void RemovePSNCommandLineOption(int& argc, char**& argv)
451  {
452  static std::string osxPSN("-psn_");
453  for (int i = 0; i < argc; ++i)
454  {
455  if (std::string(argv[i]).compare(0, osxPSN.length(), osxPSN) == 0)
456  {
457  for (int j = i; j < argc; ++j)
458  {
459  if (j == argc - 1)
460  {
461  argv[j] = 0;
462  }
463  else
464  {
465  argv[j] = argv[j + 1];
466  }
467  }
468  --argc;
469  }
470  }
471  }
472 #endif
473 
475  bool IsEnvironment(const std::string& env)
476  {
477  if (getenv(env.c_str()))
478  {
479  return true;
480  }
481  else
482  {
483  return false;
484  }
485  }
486 
488  std::string GetStaticMeshesPath()
489  {
490  return GetDataPath() + STATIC_MESHES_PATH;
491  }
492 
494  std::string GetSkeletalMeshesPath()
495  {
497  }
498 
500  std::string GetSoundsPath()
501  {
502  return GetDataPath() + SOUNDS_PATH;
503  }
504 
506  std::string GetParticlesPath()
507  {
508  return GetDataPath() + PARTICLES_PATH;
509  }
510 
512  std::string GetTexturesPath()
513  {
514  return GetDataPath() + TEXTURES_PATH;
515  }
516 
518  std::string GetTerrainsPath()
519  {
520  return GetDataPath() + TERRAINS_PATH;
521  }
522 
524  std::string GetShadersPath()
525  {
526  return GetDataPath() + SHADERS_PATH;
527  }
528 
530  std::string GetGUIPath()
531  {
532  return GetDataPath() + GUI_PATH;
533  }
534 
536  std::string GetConfigPath()
537  {
538  return GetDataPath() + CONFIG_PATH;
539  }
540 
543  {
545  }
546 
549  {
551  }
552 
554  std::string GetUserSoundsPath()
555  {
556  return GetUserDataPath() + SOUNDS_PATH;
557  }
558 
560  std::string GetUserParticlesPath()
561  {
562  return GetUserDataPath() + PARTICLES_PATH;
563  }
564 
566  std::string GetUserTexturesPath()
567  {
568  return GetUserDataPath() + TEXTURES_PATH;
569  }
570 
572  std::string GetUserTerrainsPath()
573  {
574  return GetUserDataPath() + TERRAINS_PATH;
575  }
576 
578  std::string GetUserShadersPath()
579  {
580  return GetUserDataPath() + SHADERS_PATH;
581  }
582 
584  std::string GetUserGUIPath()
585  {
586  return GetUserDataPath() + GUI_PATH;
587  }
588 
590  std::string GetUserConfigPath()
591  {
592  return GetUserDataPath() + CONFIG_PATH;
593  }
594 }
#define MAX_PATH
Definition: FileUtils.cpp:92
static const std::string TEXTURES_PATH("/Textures")
TR_UTIL_EXPORT std::string GetUserGUIPath()
Gets user graphical user interface path.
Definition: PathUtils.cpp:584
TR_UTIL_EXPORT std::string GetSkeletalMeshesPath()
Gets skeletal meshes path.
Definition: PathUtils.cpp:494
static const std::string SHADERS_PATH("/Shaders")
TR_UTIL_EXPORT std::string GetSoundsPath()
Gets sounds path.
Definition: PathUtils.cpp:500
This is the exception class used throughout the engine.
Definition: Exception.h:48
TR_UTIL_EXPORT std::string GetDataPath()
Get the TR Data file path.
Definition: PathUtils.cpp:82
static const std::string DEFAULT_TR_FOLDER("/.trueReality")
TR_UTIL_EXPORT std::string GetDataFilePathList()
Get the list of data file paths.
Definition: PathUtils.cpp:277
TR_UTIL_EXPORT void SetDataFilePathList(const std::string &pathList)
Set the list of data file paths.
Definition: PathUtils.cpp:242
TR_UTIL_EXPORT std::string GetRootPath()
Get the root path to the engine (equivalent to the TR_ROOT environment) If the TR_ROOT environment is...
Definition: PathUtils.cpp:182
Singleton class implementing basic file operations.
Definition: FileUtils.h:125
const struct FileInfo GetFileInfo(const std::string &strFile, bool caseInsensitive=false) const
Definition: FileUtils.cpp:441
struct holding information about a file.
Definition: FileUtils.h:81
TR_UTIL_EXPORT std::string GetUserStaticMeshesPath()
Gets user static meshes path.
Definition: PathUtils.cpp:542
TR_UTIL_EXPORT std::string GetShadersPath()
Gets shaders path.
Definition: PathUtils.cpp:524
static const std::string STR_BLANK("")
Constant value for a blank String.
TR_UTIL_EXPORT void CreateDataPathTree()
Creates all the folders in the Data (TR_DATA) folder, that includes Maps, GUI, Shaders, StaticMeshes, etc etc.
Definition: PathUtils.cpp:126
TR_UTIL_EXPORT void CreateUserDataPathTree()
Creates all the folders in the Data (TR_USER_DATA) folder, that includes Maps, GUI, Shaders, StaticMeshes, etc etc.
Definition: PathUtils.cpp:147
TR_UTIL_EXPORT std::string GetUserDataPath()
Get the folder where TR will save and store User data files It is MyDocuments on Windows and the same...
Definition: PathUtils.cpp:219
#define LOG_W(msg)
Log a WARNING message.
Definition: Log.h:156
static const std::string GUI_PATH("/GUI")
static const std::string TR_LOG_PATH
Environmental Variable holds the path of the custom Log folder.
Definition: EnvVariables.h:87
TR_UTIL_EXPORT std::string GetGUIPath()
Gets graphical user interface path.
Definition: PathUtils.cpp:530
static OpenThreads::Mutex gDatapathMutex
Definition: PathUtils.cpp:53
void LogException(trUtil::Logging::LogLevel level=trUtil::Logging::LogLevel::LOG_ERROR) const
Logs the exception to the default logger.
Definition: Exception.cpp:60
TR_UTIL_EXPORT bool IsEnvironment(const std::string &env)
Is the supplied environment variable defined?
Definition: PathUtils.cpp:475
TR_UTIL_EXPORT std::string GetUserConfigPath()
Gets user configuration path.
Definition: PathUtils.cpp:590
TR_UTIL_EXPORT std::string GetStaticMeshesPath()
Gets static meshes path.
Definition: PathUtils.cpp:488
TR_UTIL_EXPORT std::string GetEnvironment(const std::string &env)
Convenience method to get the supplied environment variable.
Definition: PathUtils.cpp:347
TR_UTIL_EXPORT std::string GetTerrainsPath()
Gets terrain path.
Definition: PathUtils.cpp:518
static const std::string STATIC_MESHES_PATH("/StaticMeshes")
TR_UTIL_EXPORT std::string GetConfigPath()
Gets configuration path.
Definition: PathUtils.cpp:536
FileType fileType
The enum value specifying the type of file.
Definition: FileUtils.h:90
static const std::string TR_USER_DATA
Environmental Variable that points to the User Data folder of the engine The Data folder should have ...
Definition: EnvVariables.h:78
TR_UTIL_EXPORT std::string GetUserParticlesPath()
Gets user particles path.
Definition: PathUtils.cpp:560
TR_UTIL_EXPORT std::string GetUserSoundsPath()
Gets user sounds path.
Definition: PathUtils.cpp:554
static std::string mDataPath
Definition: PathUtils.cpp:55
TR_UTIL_EXPORT std::string GetLogPath()
Get the folder where TR will save and store the log files It is the same as GetUserDataPath() by defa...
Definition: PathUtils.cpp:206
static const std::string SOUNDS_PATH("/Sounds")
static FileUtils & GetInstance()
Character separating the parts of a file path.
Definition: FileUtils.h:137
void RemovePSNCommandLineOption(int &, char **&)
Removes the psn command line option.
Definition: PathUtils.h:441
TR_UTIL_EXPORT std::string GetParticlesPath()
Gets particles path.
Definition: PathUtils.cpp:506
TR_UTIL_EXPORT std::string GetUserTexturesPath()
Gets user textures path.
Definition: PathUtils.cpp:566
static const std::string TR_DATA
Environmental Variable that points to the Data folder of the engine The Data folder should have gener...
Definition: EnvVariables.h:70
TR_UTIL_EXPORT void SetEnvironment(const std::string &name, const std::string &value)
Sets an environment variable.
Definition: PathUtils.cpp:371
std::string fileName
the file name with full path
Definition: FileUtils.h:83
static const std::string PARTICLES_PATH("/Particles")
TR_UTIL_EXPORT void SetDataPath(std::string &path)
Overwrites the Data path.
Definition: PathUtils.cpp:120
static const std::string TERRAINS_PATH("/Terrains")
TR_UTIL_EXPORT std::string GetUserHomeDirectory()
Get the USER Home directory.
Definition: PathUtils.cpp:58
static const std::string DATA_PATH_DEFAULT("/Data")
void MakeDirectoryEX(std::string strDir)
A more powerful version of the standard mkdir.
Definition: FileUtils.cpp:651
TR_UTIL_EXPORT std::string GetTexturesPath()
Gets textures path.
Definition: PathUtils.cpp:512
static const char PATH_SEPARATOR
Definition: FileUtils.h:128
static const std::string TR_ROOT
Environmental Variable that points to the Root folder of the engine.
Definition: EnvVariables.h:54
static const std::string SKELETAL_MESHES_PATH("/SkeletalMeshes")
TR_UTIL_EXPORT std::string GetUserShadersPath()
Gets user shaders path.
Definition: PathUtils.cpp:578
TR_UTIL_EXPORT std::string FindFile(const std::string &fileName)
Searches for a file in the list of paths found by calling GetDataFilePathList()
Definition: PathUtils.cpp:304
TR_UTIL_EXPORT void CreateDataPathTrees()
Convenience function that calls CreateDataPathTree() and CreateUserDataPathTree();.
Definition: PathUtils.cpp:168
TR_UTIL_EXPORT std::string GetUserTerrainsPath()
Gets user terrain path.
Definition: PathUtils.cpp:572
TR_UTIL_EXPORT std::string GetUserSkeletalMeshesPath()
Gets user skeletal meshes path.
Definition: PathUtils.cpp:548
static const std::string CONFIG_PATH("/Config")