openMSX
FilePool.cc
Go to the documentation of this file.
1 #include "FilePool.hh"
2 #include "File.hh"
3 #include "FileContext.hh"
4 #include "FileOperations.hh"
5 #include "TclObject.hh"
6 #include "CommandException.hh"
7 #include "Display.hh"
8 #include "EventDistributor.hh"
9 #include "CliComm.hh"
10 #include "Reactor.hh"
11 #include "xrange.hh"
12 #include <memory>
13 
14 using std::string;
15 using std::vector;
16 
17 namespace openmsx {
18 
19 class Sha1SumCommand final : public Command
20 {
21 public:
22  Sha1SumCommand(CommandController& commandController, FilePool& filePool);
23  void execute(span<const TclObject> tokens, TclObject& result) override;
24  [[nodiscard]] string help(const vector<string>& tokens) const override;
25  void tabCompletion(vector<string>& tokens) const override;
26 private:
27  FilePool& filePool;
28 };
29 
30 
31 [[nodiscard]] static string initialFilePoolSettingValue()
32 {
33  TclObject result;
34 
35  for (auto& p : systemFileContext().getPaths()) {
36  result.addListElement(
37  makeTclDict("-path", tmpStrCat(p, "/systemroms"),
38  "-types", "system_rom"),
39  makeTclDict("-path", tmpStrCat(p, "/software"),
40  "-types", "rom disk tape"));
41  }
42  return string(result.getString());
43 }
44 
46  : core(FileOperations::getUserDataDir() + "/.filecache",
47  [&] { return getDirectories(); },
48  [&](std::string_view message) { reportProgress(message); })
49  , filePoolSetting(
50  controller, "__filepool",
51  "This is an internal setting. Don't change this directly, "
52  "instead use the 'filepool' command.",
53  initialFilePoolSettingValue())
54  , reactor(reactor_)
55 {
56  filePoolSetting.attach(*this);
58 
59  sha1SumCommand = std::make_unique<Sha1SumCommand>(controller, *this);
60 }
61 
63 {
65  filePoolSetting.detach(*this);
66 }
67 
68 File FilePool::getFile(FileType fileType, const Sha1Sum& sha1sum)
69 {
70  return core.getFile(fileType, sha1sum);
71 }
72 
74 {
75  return core.getSha1Sum(file);
76 }
77 
78 [[nodiscard]] static FileType parseTypes(Interpreter& interp, const TclObject& list)
79 {
80  auto result = FileType::NONE;
81  for (auto i : xrange(list.getListLength(interp))) {
82  std::string_view elem = list.getListIndex(interp, i).getString();
83  if (elem == "system_rom") {
84  result |= FileType::SYSTEM_ROM;
85  } else if (elem == "rom") {
86  result |= FileType::ROM;
87  } else if (elem == "disk") {
88  result |= FileType::DISK;
89  } else if (elem == "tape") {
90  result |= FileType::TAPE;
91  } else {
92  throw CommandException("Unknown type: ", elem);
93  }
94  }
95  return result;
96 }
97 
98 FilePoolCore::Directories FilePool::getDirectories() const
99 {
101  try {
102  auto& interp = filePoolSetting.getInterpreter();
103  const TclObject& all = filePoolSetting.getValue();
104  for (auto i : xrange(all.getListLength(interp))) {
105  FilePoolCore::Dir dir;
106  bool hasPath = false;
107  dir.types = FileType::NONE;
108  TclObject line = all.getListIndex(interp, i);
109  unsigned numItems = line.getListLength(interp);
110  if (numItems & 1) {
111  throw CommandException(
112  "Expected a list with an even number "
113  "of elements, but got ", line.getString());
114  }
115  for (unsigned j = 0; j < numItems; j += 2) {
116  std::string_view name = line.getListIndex(interp, j + 0).getString();
117  TclObject value = line.getListIndex(interp, j + 1);
118  if (name == "-path") {
119  dir.path = value.getString();
120  hasPath = true;
121  } else if (name == "-types") {
122  dir.types = parseTypes(interp, value);
123  } else {
124  throw CommandException("Unknown item: ", name);
125  }
126  }
127  if (!hasPath) {
128  throw CommandException(
129  "Missing -path item: ", line.getString());
130  }
131  if (dir.types == FileType::NONE) {
132  throw CommandException(
133  "Missing -types item: ", line.getString());
134  }
135  result.push_back(std::move(dir));
136  }
137  } catch (CommandException& e) {
138  reactor.getCliComm().printWarning(
139  "Error while parsing '__filepool' setting", e.getMessage());
140  }
141  return result;
142 }
143 
144 void FilePool::update(const Setting& setting)
145 {
146  assert(&setting == &filePoolSetting); (void)setting;
147  (void)getDirectories(); // check for syntax errors
148 }
149 
150 void FilePool::reportProgress(std::string_view message)
151 {
152  if (quit) core.abort();
153  reactor.getCliComm().printProgress(message);
154  reactor.getDisplay().repaint();
155 }
156 
157 int FilePool::signalEvent(const std::shared_ptr<const Event>& event)
158 {
159  (void)event; // avoid warning for non-assert compiles
160  assert(event->getType() == OPENMSX_QUIT_EVENT);
161  quit = true;
162  return 0;
163 }
164 
165 
166 // class Sha1SumCommand
167 
169  CommandController& commandController_, FilePool& filePool_)
170  : Command(commandController_, "sha1sum")
171  , filePool(filePool_)
172 {
173 }
174 
176 {
177  checkNumArgs(tokens, 2, "filename");
178  File file(FileOperations::expandTilde(string(tokens[1].getString())));
179  result = filePool.getSha1Sum(file).toString();
180 }
181 
182 string Sha1SumCommand::help(const vector<string>& /*tokens*/) const
183 {
184  return "Calculate sha1 value for the given file. If the file is "
185  "(g)zipped the sha1 is calculated on the unzipped version.";
186 }
187 
188 void Sha1SumCommand::tabCompletion(vector<string>& tokens) const
189 {
191 }
192 
193 } // namespace openmsx
openmsx::Sha1SumCommand::execute
void execute(span< const TclObject > tokens, TclObject &result) override
Execute this command.
Definition: FilePool.cc:175
openmsx::Completer::checkNumArgs
void checkNumArgs(span< const TclObject > tokens, unsigned exactly, const char *errMessage) const
Definition: Completer.cc:181
openmsx::Setting::getInterpreter
Interpreter & getInterpreter() const
Definition: Setting.cc:162
openmsx::OPENMSX_QUIT_EVENT
@ OPENMSX_QUIT_EVENT
Definition: Event.hh:33
openmsx::Subject::detach
void detach(Observer< T > &observer)
Definition: Subject.hh:56
openmsx::CommandController
Definition: CommandController.hh:19
Display.hh
openmsx::Completer::completeFileName
static void completeFileName(std::vector< std::string > &tokens, const FileContext &context, const RANGE &extra)
Definition: Completer.hh:139
openmsx::Sha1Sum::toString
std::string toString() const
Definition: utils/sha1.cc:234
openmsx::Reactor::getDisplay
Display & getDisplay()
Definition: Reactor.hh:85
xrange
constexpr auto xrange(T e)
Definition: xrange.hh:155
openmsx::Sha1SumCommand::tabCompletion
void tabCompletion(vector< string > &tokens) const override
Attempt tab completion for this command.
Definition: FilePool.cc:188
openmsx::CliComm::printProgress
void printProgress(std::string_view message)
Definition: CliComm.cc:20
TclObject.hh
openmsx::FileType
FileType
Definition: FilePoolCore.hh:22
openmsx::FilePoolCore::Directories
std::vector< Dir > Directories
Definition: FilePoolCore.hh:44
openmsx::makeTclDict
TclObject makeTclDict(Args &&... args)
Definition: TclObject.hh:296
openmsx::Sha1SumCommand::Sha1SumCommand
Sha1SumCommand(CommandController &commandController, FilePool &filePool)
Definition: FilePool.cc:168
openmsx::Reactor::getEventDistributor
EventDistributor & getEventDistributor()
Definition: Reactor.hh:81
openmsx::FilePoolCore::getSha1Sum
Sha1Sum getSha1Sum(File &file)
Calculate sha1sum for the given File object.
Definition: FilePoolCore.cc:455
openmsx::userFileContext
FileContext userFileContext(string_view savePath)
Definition: FileContext.cc:172
openmsx::Subject::attach
void attach(Observer< T > &observer)
Definition: Subject.hh:50
openmsx::TclObject::addListElement
void addListElement(const T &t)
Definition: TclObject.hh:130
openmsx::TclObject::getListIndex
TclObject getListIndex(Interpreter &interp, unsigned index) const
Definition: TclObject.cc:143
openmsx::FilePool::FilePool
FilePool(CommandController &controller, Reactor &reactor)
Definition: FilePool.cc:45
span
Definition: span.hh:126
openmsx::Reactor
Contains the main loop of openMSX.
Definition: Reactor.hh:67
Reactor.hh
openmsx::CliComm::printWarning
void printWarning(std::string_view message)
Definition: CliComm.cc:10
openmsx::FilePool::getSha1Sum
Sha1Sum getSha1Sum(File &file)
Calculate sha1sum for the given File object.
Definition: FilePool.cc:73
File.hh
openmsx::FilePool::getFile
File getFile(FileType fileType, const Sha1Sum &sha1sum)
Search file with the given sha1sum.
Definition: FilePool.cc:68
EventDistributor.hh
openmsx::Sha1SumCommand
Definition: FilePool.cc:20
openmsx::Setting::getValue
const TclObject & getValue() const final
Gets the current value of this setting as a TclObject.
Definition: Setting.hh:142
openmsx::Sha1SumCommand::help
string help(const vector< string > &tokens) const override
Print help for this command.
Definition: FilePool.cc:182
openmsx::FilePoolCore::getFile
File getFile(FileType fileType, const Sha1Sum &sha1sum)
Search file with the given sha1sum.
Definition: FilePoolCore.cc:248
openmsx::Sha1Sum
This class represents the result of a sha1 calculation (a 160-bit value).
Definition: sha1.hh:22
FilePool.hh
openmsx::FileType::ROM
@ ROM
FileContext.hh
openmsx::FileType::NONE
@ NONE
tmpStrCat
TemporaryString tmpStrCat(Ts &&... ts)
Definition: strCat.hh:659
openmsx::FilePool::~FilePool
~FilePool()
Definition: FilePool.cc:62
FileOperations.hh
openmsx::File
Definition: File.hh:16
openmsx::Reactor::getCliComm
CliComm & getCliComm()
Definition: Reactor.cc:310
openmsx::Command
Definition: Command.hh:41
openmsx::Display::repaint
void repaint()
Redraw the display.
Definition: Display.cc:328
openmsx::FilePool
Definition: FilePool.hh:17
openmsx::systemFileContext
const FileContext & systemFileContext()
Definition: FileContext.cc:156
openmsx::TclObject
Definition: TclObject.hh:24
openmsx::TclObject::getListLength
unsigned getListLength(Interpreter &interp) const
Definition: TclObject.cc:125
openmsx::FileOperations::getUserDataDir
const string & getUserDataDir()
Get the openMSX data dir in the user's home directory.
Definition: FileOperations.cc:434
openmsx::EventDistributor::registerEventListener
void registerEventListener(EventType type, EventListener &listener, Priority priority=OTHER)
Registers a given object to receive certain events.
Definition: EventDistributor.cc:23
CliComm.hh
openmsx::EventDistributor::unregisterEventListener
void unregisterEventListener(EventType type, EventListener &listener)
Unregisters a previously registered event listener.
Definition: EventDistributor.cc:35
openmsx::Interpreter
Definition: Interpreter.hh:19
CommandException.hh
openmsx::FilePoolCore::abort
void abort()
This is only meaningful to call from within the 'reportProgress' callback (constructor parameter).
Definition: FilePoolCore.hh:68
openmsx
This file implemented 3 utility functions:
Definition: Autofire.cc:5
xrange.hh
openmsx::FileOperations::expandTilde
string expandTilde(string path)
Expand the '~' character to the users home directory.
Definition: FileOperations.cc:84
openmsx::TclObject::getString
zstring_view getString() const
Definition: TclObject.cc:111