openMSX
FileContext.cc
Go to the documentation of this file.
1 #include "FileContext.hh"
2 #include "FileOperations.hh"
3 #include "FileException.hh"
4 #include "StringOp.hh"
5 #include "serialize.hh"
6 #include "serialize_stl.hh"
7 #include "stl.hh"
8 #include <cassert>
9 #include <utility>
10 
11 using std::string;
12 using std::string_view;
13 using std::vector;
14 
15 namespace openmsx {
16 
17 const string USER_DIRS = "{{USER_DIRS}}";
18 const string USER_OPENMSX = "{{USER_OPENMSX}}";
19 const string USER_DATA = "{{USER_DATA}}";
20 const string SYSTEM_DATA = "{{SYSTEM_DATA}}";
21 
22 
23 static string subst(string_view path, string_view before, string_view after)
24 {
25  assert(StringOp::startsWith(path, before));
26  return strCat(after, path.substr(before.size()));
27 }
28 
29 static vector<string> getPathsHelper(const vector<string>& input)
30 {
31  vector<string> result;
32  for (auto& s : input) {
34  result.push_back(subst(s, USER_OPENMSX,
36  } else if (StringOp::startsWith(s, USER_DATA)) {
37  result.push_back(subst(s, USER_DATA,
39  } else if (StringOp::startsWith(s, SYSTEM_DATA)) {
40  result.push_back(subst(s, SYSTEM_DATA,
42  } else if (s == USER_DIRS) {
43  // Nothing. Keep USER_DIRS for isUserContext()
44  } else {
45  result.push_back(s);
46  }
47  }
48  for (const auto& s : result) {
49  assert(FileOperations::expandTilde(s) == s); (void)s;
50  }
51  return result;
52 }
53 
54 static string resolveHelper(const vector<string>& pathList,
55  string_view filename)
56 {
58  filepath = FileOperations::expandTilde(filepath);
59  if (FileOperations::isAbsolutePath(filepath)) {
60  // absolute path, don't resolve
61  return filepath;
62  }
63 
64  for (auto& p : pathList) {
65  string name = FileOperations::join(p, filename);
66  assert(FileOperations::expandTilde(name) == name);
67  if (FileOperations::exists(name)) {
68  return name;
69  }
70  }
71  // not found in any path
72  throw FileException(filename, " not found in this context");
73 }
74 
75 FileContext::FileContext(vector<string>&& paths_, vector<string>&& savePaths_)
76  : paths(std::move(paths_)), savePaths(std::move(savePaths_))
77 {
78 }
79 
80 string FileContext::resolve(string_view filename) const
81 {
82  vector<string> pathList = getPathsHelper(paths);
83  string result = resolveHelper(pathList, filename);
84  assert(FileOperations::expandTilde(result) == result);
85  return result;
86 }
87 
88 string FileContext::resolveCreate(string_view filename) const
89 {
90  string result;
91  vector<string> pathList = getPathsHelper(savePaths);
92  try {
93  result = resolveHelper(pathList, filename);
94  } catch (FileException&) {
95  string path = pathList.front();
96  try {
98  } catch (FileException&) {
99  // ignore
100  }
101  result = FileOperations::join(path, filename);
102  }
103  assert(FileOperations::expandTilde(result) == result);
104  return result;
105 }
106 
107 vector<string> FileContext::getPaths() const
108 {
109  return getPathsHelper(paths);
110 }
111 
113 {
114  return contains(paths, USER_DIRS);
115 }
116 
117 template<typename Archive>
118 void FileContext::serialize(Archive& ar, unsigned /*version*/)
119 {
120  ar.serialize("paths", paths,
121  "savePaths", savePaths);
122 }
124 
126 
127 static string backSubstSymbols(const string& path)
128 {
129  const string& systemData = FileOperations::getSystemDataDir();
130  if (StringOp::startsWith(path, systemData)) {
131  return subst(path, systemData, SYSTEM_DATA);
132  }
133  const string& userData = FileOperations::getSystemDataDir();
134  if (StringOp::startsWith(path, userData)) {
135  return subst(path, userData, SYSTEM_DATA);
136  }
137  const string& userDir = FileOperations::getUserOpenMSXDir();
138  if (StringOp::startsWith(path, userDir)) {
139  return subst(path, userDir, USER_OPENMSX);
140  }
141  // TODO USER_DIRS (not needed ATM)
142  return path;
143 }
144 
145 FileContext configFileContext(string_view path, string_view hwDescr, string_view userName)
146 {
147  return { { backSubstSymbols(FileOperations::expandTilde(path)) },
149  USER_OPENMSX, "persistent", hwDescr, userName) } };
150 }
151 
153 {
154  return { { USER_DATA, SYSTEM_DATA },
155  { USER_DATA } };
156 }
157 
159 {
160  return { { SYSTEM_DATA, USER_DATA }, // first system dir
161  {} };
162 }
163 
164 FileContext userFileContext(string_view savePath)
165 {
166  vector<string> savePaths;
167  if (!savePath.empty()) {
168  savePaths = { FileOperations::join(
169  USER_OPENMSX, "persistent", savePath) };
170  }
171  return { { string{}, USER_DIRS }, std::move(savePaths) };
172 }
173 
174 FileContext userDataFileContext(string_view subDir)
175 {
176  return { { string{}, strCat(USER_OPENMSX, '/', subDir) },
177  {} };
178 }
179 
181 {
182  return {{string{}}, {string{}}};
183 }
184 
185 } // namespace openmsx
FileException.hh
StringOp::startsWith
bool startsWith(string_view total, string_view part)
Definition: StringOp.cc:71
openmsx::userDataFileContext
FileContext userDataFileContext(string_view subDir)
Definition: FileContext.cc:174
serialize.hh
openmsx::FileContext::getPaths
std::vector< std::string > getPaths() const
Definition: FileContext.cc:107
openmsx::FileContext::resolve
std::string resolve(std::string_view filename) const
Definition: FileContext.cc:80
openmsx::FileOperations::isAbsolutePath
bool isAbsolutePath(string_view path)
Checks whether it's a absolute path or not.
Definition: FileOperations.cc:491
contains
bool contains(ITER first, ITER last, const VAL &val)
Check if a range contains a given value, using linear search.
Definition: stl.hh:92
openmsx::USER_OPENMSX
const string USER_OPENMSX
Definition: FileContext.cc:18
openmsx::USER_DIRS
const string USER_DIRS
Definition: FileContext.cc:17
openmsx::FileContext::resolveCreate
std::string resolveCreate(std::string_view filename) const
Definition: FileContext.cc:88
openmsx::userFileContext
FileContext userFileContext(string_view savePath)
Definition: FileContext.cc:164
openmsx::FileOperations::join
string join(string_view part1, string_view part2)
Join two paths.
Definition: FileOperations.cc:423
openmsx::FileContext
Definition: FileContext.hh:10
openmsx::FileOperations::mkdirp
void mkdirp(string_view path_)
Acts like the unix command "mkdir -p".
Definition: FileOperations.cc:248
openmsx::FileOperations::getSystemDataDir
string getSystemDataDir()
Get system directory.
Definition: FileOperations.cc:556
openmsx::FileOperations::getUserDataDir
string getUserDataDir()
Get the openMSX data dir in the user's home directory.
Definition: FileOperations.cc:549
openmsx::currentDirFileContext
FileContext currentDirFileContext()
Definition: FileContext.cc:180
openmsx::FileOperations::expandTilde
string expandTilde(string_view path)
Expand the '~' character to the users home directory.
Definition: FileOperations.cc:195
openmsx::SYSTEM_DATA
const string SYSTEM_DATA
Definition: FileContext.cc:20
openmsx::filename
constexpr const char *const filename
Definition: FirmwareSwitch.cc:10
openmsx::FileContext::isUserContext
bool isUserContext() const
Definition: FileContext.cc:112
openmsx::FileOperations::getUserOpenMSXDir
const string & getUserOpenMSXDir()
Get the openMSX dir in the user's home directory.
Definition: FileOperations.cc:535
INSTANTIATE_SERIALIZE_METHODS
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)
Definition: serialize.hh:981
openmsx::FileException
Definition: FileException.hh:9
openmsx::FileOperations::expandCurrentDirFromDrive
string expandCurrentDirFromDrive(string_view path)
Get the current directory of the specified drive Linux: just return an empty string.
Definition: FileOperations.cc:599
serialize_stl.hh
openmsx::FileContext::FileContext
FileContext()=default
FileContext.hh
openmsx::FileContext::serialize
void serialize(Archive &ar, unsigned version)
Definition: FileContext.cc:118
FileOperations.hh
StringOp.hh
openmsx::USER_DATA
const string USER_DATA
Definition: FileContext.cc:19
stl.hh
openmsx::FileOperations::exists
bool exists(const std::string &filename)
Does this file (directory) exists?
Definition: FileOperations.cc:665
openmsx::configFileContext
FileContext configFileContext(string_view path, string_view hwDescr, string_view userName)
Definition: FileContext.cc:145
strCat
std::string strCat(Ts &&...ts)
Definition: strCat.hh:573
openmsx
This file implemented 3 utility functions:
Definition: Autofire.cc:5
openmsx::preferSystemFileContext
FileContext preferSystemFileContext()
Definition: FileContext.cc:158
openmsx::systemFileContext
FileContext systemFileContext()
Definition: FileContext.cc:152