OpenClonk
C4Reloc.cpp
Go to the documentation of this file.
1 /*
2  * OpenClonk, http://www.openclonk.org
3  *
4  * Copyright (c) 2011-2016, The OpenClonk Team and contributors
5  *
6  * Distributed under the terms of the ISC license; see accompanying file
7  * "COPYING" for details.
8  *
9  * "Clonk" is a registered trademark of Matthes Bender, used with permission.
10  * See accompanying file "TRADEMARK" for details.
11  *
12  * To redistribute this file separately, substitute the full license texts
13  * for the above references.
14  */
15 
16 #include "C4Include.h"
17 #include "config/C4Reloc.h"
18 
19 #include "game/C4Application.h"
20 
21 C4Reloc Reloc; // singleton
22 
24 {
25  Paths.clear();
26 
27  // The system folder (i.e. installation path) has higher priority than the user path
28  // Although this is counter-intuitive (the user may want to overload system files in the user path),
29  // people had trouble when they downloaded e.g. an Objects.ocd file in a network lobby and that copy permanently
30  // ruined their OpenClonk installation with no obvious way to fix it.
31  // Not even reinstalling would fix the problem because reinstallation does not overwrite user data.
32  // We currently don't have any valid case where overloading system files would make sense so just give higher priority to the system path for now.
33 #ifndef __APPLE__
34  // Add planet subfolder with highest priority because it's used when starting directly from the repository with binaries in the root folder
36  planet.AppendBackslash();
37  planet.Append("planet");
38  if (DirectoryExists(planet.getData()))
39  {
40  // Only add planet if it's a valid contents folder.
41  // Because users may create a folder "planet" in their source repos.
42  StdCopyStrBuf planet_system_check(planet);
43  planet_system_check.AppendBackslash();
44  planet_system_check.Append(C4CFN_System);
45  if (ItemExists(planet_system_check.getData()))
46  {
47  AddPath(planet.getData());
48  }
49  }
50 #endif
51  // Add main system path (unless it's using planet/ anyway, in which we would just slow down scenario enumeration by looking throug hthe whole source folder)
52  if (!Paths.size())
53  {
55  }
56  // Add mods directory before the user path.
58  // Add user path for additional data (player files, user scenarios, etc.)
60 }
61 
62 bool C4Reloc::AddPath(const char* path, PathType pathType)
63 {
64  if (!IsGlobalPath(path))
65  {
66  return false;
67  }
68 
69  if (std::find(Paths.begin(), Paths.end(), path) != Paths.end())
70  {
71  return false;
72  }
73 
74  Paths.emplace_back(StdCopyStrBuf(path), pathType);
75  return true;
76 }
77 
78 
80 {
81  if (subdirIters.empty())
82  {
83  if ((*pathListIter).pathType == C4Reloc::PathType::PATH_IncludingSubdirectories)
84  {
85  DirectoryIterator subdir((*pathListIter).strBuf.getData());
86  if (*subdir)
87  subdirIters.emplace(subdir);
88  else
89  ++pathListIter;
90  }
91  else
92  {
93  ++pathListIter;
94  }
95  }
96  else // Currently in a subdir?
97  {
98  DirectoryIterator &currentSubdir = subdirIters.top();
99 
100  if ((!*currentSubdir) || !*(++currentSubdir))
101  {
102  subdirIters.pop();
103  if (subdirIters.empty())
104  ++pathListIter;
105  }
106  else
107  {
108  // Go deeper?
109  if (DirectoryExists(*currentSubdir))
110  {
111  DirectoryIterator subdir(*currentSubdir);
112  if (*subdir) // Make sure there is at least one file/subdir.
113  subdirIters.emplace(subdir);
114  }
115  }
116  }
117  return *this;
118 }
120 {
121  if (!subdirIters.empty())
122  {
123  const DirectoryIterator &currentSubdir = subdirIters.top();
124  temporaryPathInfo.reset(new C4Reloc::PathInfo(StdStrBuf(*currentSubdir), PathType::PATH_Regular));
125  return *temporaryPathInfo;
126  }
127  return *pathListIter;
128 }
129 
131 {
132  if (!a.subdirIters.empty()) return false;
133  if (!b.subdirIters.empty()) return false;
134  return a.pathListIter == b.pathListIter;
135 }
136 
138 {
139  return !(a == b);
140 }
141 
143 {
144  C4Reloc::iterator iter;
145  iter.pathListIter = Paths.begin();
146  return std::move(iter);
147 }
148 
150 {
151  C4Reloc::iterator iter;
152  iter.pathListIter = Paths.end();
153  return std::move(iter);
154 }
155 
156 bool C4Reloc::Open(C4Group& group, const char* filename) const
157 {
158  if (IsGlobalPath(filename))
159  {
160  return group.Open(filename);
161  }
162 
163  for (const auto & iter : *this)
164  {
165  if (group.Open((iter.strBuf + DirSep + filename).getData()))
166  {
167  return true;
168  }
169  }
170 
171  return false;
172 }
173 
174 bool C4Reloc::LocateItem(const char* filename, StdStrBuf& str) const
175 {
176  if (IsGlobalPath(filename))
177  {
178  str.Copy(filename);
179  return true;
180  }
181 
182  for(const auto & iter : *this)
183  {
184  str.Copy(iter.strBuf + DirSep + filename);
185  if (ItemExists(str.getData()))
186  {
187  return true;
188  }
189  }
190 
191  return false;
192 }
#define C4CFN_System
Definition: C4Components.h:29
C4Config Config
Definition: C4Config.cpp:930
#define a
#define b
C4Reloc Reloc
Definition: C4Reloc.cpp:21
bool operator!=(const C4Reloc::const_iterator &a, const C4Reloc::const_iterator &b)
Definition: C4Reloc.cpp:137
bool operator==(const C4Reloc::const_iterator &a, const C4Reloc::const_iterator &b)
Definition: C4Reloc.cpp:130
#define DirSep
bool DirectoryExists(const char *szFilename)
Definition: StdFile.cpp:708
bool IsGlobalPath(const char *szPath)
Definition: StdFile.cpp:224
bool ItemExists(const char *szItemName)
Definition: StdFile.h:75
StdCopyStrBuf ExePath
Definition: C4Config.h:54
char SystemDataPath[CFG_MaxString+1]
Definition: C4Config.h:58
char UserDataPath[CFG_MaxString+1]
Definition: C4Config.h:56
char ModsDataPath[CFG_MaxString+1]
Definition: C4Config.h:57
C4ConfigGeneral General
Definition: C4Config.h:255
bool Open(const char *group_name, bool do_create=false)
Definition: C4Group.cpp:660
PathList::const_iterator pathListIter
Definition: C4Reloc.h:68
const_iterator & operator++()
Definition: C4Reloc.cpp:79
const PathInfo & operator*() const
Definition: C4Reloc.cpp:119
std::stack< DirectoryIterator > subdirIters
Definition: C4Reloc.h:69
PathType
Definition: C4Reloc.h:26
@ PATH_PreferredInstallationLocation
Definition: C4Reloc.h:28
@ PATH_IncludingSubdirectories
Definition: C4Reloc.h:29
bool LocateItem(const char *filename, StdStrBuf &str) const
Definition: C4Reloc.cpp:174
iterator end() const
Definition: C4Reloc.cpp:149
void Init()
Definition: C4Reloc.cpp:23
bool AddPath(const char *path, PathType pathType=PATH_Regular)
Definition: C4Reloc.cpp:62
bool Open(C4Group &group, const char *filename) const
Definition: C4Reloc.cpp:156
iterator begin() const
Definition: C4Reloc.cpp:142
const char * getData() const
Definition: StdBuf.h:442
void AppendBackslash()
Definition: StdBuf.cpp:248
void Copy()
Definition: StdBuf.h:467
void Append(const char *pnData, size_t iChars)
Definition: StdBuf.h:519