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 <memory>
12 
13 using std::string;
14 using std::vector;
15 
16 namespace openmsx {
17 
18 class Sha1SumCommand final : public Command
19 {
20 public:
21  Sha1SumCommand(CommandController& commandController, FilePool& filePool);
22  void execute(span<const TclObject> tokens, TclObject& result) override;
23  string help(const vector<string>& tokens) const override;
24  void tabCompletion(vector<string>& tokens) const override;
25 private:
26  FilePool& filePool;
27 };
28 
29 
30 static string initialFilePoolSettingValue()
31 {
32  TclObject result;
33 
34  for (auto& p : systemFileContext().getPaths()) {
35  result.addListElement(
36  makeTclDict("-path", FileOperations::join(p, "systemroms"),
37  "-types", "system_rom"),
38  makeTclDict("-path", FileOperations::join(p, "software"),
39  "-types", "rom disk tape"));
40  }
41  return string(result.getString());
42 }
43 
45  : core(FileOperations::getUserDataDir() + "/.filecache",
46  [&] { return getDirectories(); },
47  [&](const std::string& message) { reportProgress(message); })
48  , filePoolSetting(
49  controller, "__filepool",
50  "This is an internal setting. Don't change this directly, "
51  "instead use the 'filepool' command.",
52  initialFilePoolSettingValue())
53  , reactor(reactor_)
54 {
55  filePoolSetting.attach(*this);
57 
58  sha1SumCommand = std::make_unique<Sha1SumCommand>(controller, *this);
59 }
60 
62 {
64  filePoolSetting.detach(*this);
65 }
66 
67 File FilePool::getFile(FileType fileType, const Sha1Sum& sha1sum)
68 {
69  return core.getFile(fileType, sha1sum);
70 }
71 
73 {
74  return core.getSha1Sum(file);
75 }
76 
77 static FileType parseTypes(Interpreter& interp, const TclObject& list)
78 {
79  auto result = FileType::NONE;
80  unsigned num = list.getListLength(interp);
81  for (unsigned i = 0; i < num; ++i) {
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  unsigned numLines = all.getListLength(interp);
105  for (unsigned i = 0; i < numLines; ++i) {
106  FilePoolCore::Dir dir;
107  bool hasPath = false;
108  dir.types = FileType::NONE;
109  TclObject line = all.getListIndex(interp, i);
110  unsigned numItems = line.getListLength(interp);
111  if (numItems & 1) {
112  throw CommandException(
113  "Expected a list with an even number "
114  "of elements, but got ", line.getString());
115  }
116  for (unsigned j = 0; j < numItems; j += 2) {
117  std::string_view name = line.getListIndex(interp, j + 0).getString();
118  TclObject value = line.getListIndex(interp, j + 1);
119  if (name == "-path") {
120  dir.path = value.getString();
121  hasPath = true;
122  } else if (name == "-types") {
123  dir.types = parseTypes(interp, value);
124  } else {
125  throw CommandException("Unknown item: ", name);
126  }
127  }
128  if (!hasPath) {
129  throw CommandException(
130  "Missing -path item: ", line.getString());
131  }
132  if (dir.types == FileType::NONE) {
133  throw CommandException(
134  "Missing -types item: ", line.getString());
135  }
136  result.push_back(dir);
137  }
138  } catch (CommandException& e) {
139  reactor.getCliComm().printWarning(
140  "Error while parsing '__filepool' setting", e.getMessage());
141  }
142  return result;
143 }
144 
145 void FilePool::update(const Setting& setting)
146 {
147  assert(&setting == &filePoolSetting); (void)setting;
148  getDirectories(); // check for syntax errors
149 }
150 
151 void FilePool::reportProgress(const std::string& message)
152 {
153  if (quit) core.abort();
154  reactor.getCliComm().printProgress(message);
155  reactor.getDisplay().repaintDelayed(0);
156 }
157 
158 int FilePool::signalEvent(const std::shared_ptr<const Event>& event)
159 {
160  (void)event; // avoid warning for non-assert compiles
161  assert(event->getType() == OPENMSX_QUIT_EVENT);
162  quit = true;
163  return 0;
164 }
165 
166 
167 // class Sha1SumCommand
168 
170  CommandController& commandController_, FilePool& filePool_)
171  : Command(commandController_, "sha1sum")
172  , filePool(filePool_)
173 {
174 }
175 
177 {
178  checkNumArgs(tokens, 2, "filename");
179  File file(tokens[1].getString());
180  result = filePool.getSha1Sum(file).toString();
181 }
182 
183 string Sha1SumCommand::help(const vector<string>& /*tokens*/) const
184 {
185  return "Calculate sha1 value for the given file. If the file is "
186  "(g)zipped the sha1 is calculated on the unzipped version.";
187 }
188 
189 void Sha1SumCommand::tabCompletion(vector<string>& tokens) const
190 {
192 }
193 
194 } // namespace openmsx
openmsx::Sha1SumCommand::execute
void execute(span< const TclObject > tokens, TclObject &result) override
Execute this command.
Definition: FilePool.cc:176
openmsx::Completer::checkNumArgs
void checkNumArgs(span< const TclObject > tokens, unsigned exactly, const char *errMessage) const
Definition: Completer.cc:177
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:18
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:232
openmsx::Reactor::getDisplay
Display & getDisplay()
Definition: Reactor.hh:85
openmsx::Sha1SumCommand::tabCompletion
void tabCompletion(vector< string > &tokens) const override
Attempt tab completion for this command.
Definition: FilePool.cc:189
openmsx::CliComm::printProgress
void printProgress(std::string_view message)
Definition: CliComm.cc:20
TclObject.hh
openmsx::FileType
FileType
Definition: FilePoolCore.hh:22
openmsx::Setting::getValue
const TclObject & getValue() const final override
Gets the current value of this setting as a TclObject.
Definition: Setting.hh:135
openmsx::FilePoolCore::Directories
std::vector< Dir > Directories
Definition: FilePoolCore.hh:44
openmsx::makeTclDict
TclObject makeTclDict(Args &&... args)
Definition: TclObject.hh:286
openmsx::Sha1SumCommand::Sha1SumCommand
Sha1SumCommand(CommandController &commandController, FilePool &filePool)
Definition: FilePool.cc:169
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:454
openmsx::userFileContext
FileContext userFileContext(string_view savePath)
Definition: FileContext.cc:164
openmsx::Subject::attach
void attach(Observer< T > &observer)
Definition: Subject.hh:50
openmsx::TclObject::getListIndex
TclObject getListIndex(Interpreter &interp, unsigned index) const
Definition: TclObject.cc:134
openmsx::FileOperations::join
string join(string_view part1, string_view part2)
Join two paths.
Definition: FileOperations.cc:423
openmsx::Display::repaintDelayed
void repaintDelayed(uint64_t delta)
Definition: Display.cc:367
openmsx::FilePool::FilePool
FilePool(CommandController &controller, Reactor &reactor)
Definition: FilePool.cc:44
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:72
openmsx::TclObject::addListElement
void addListElement(T t)
Definition: TclObject.hh:121
openmsx::FileOperations::getUserDataDir
string getUserDataDir()
Get the openMSX data dir in the user's home directory.
Definition: FileOperations.cc:549
File.hh
openmsx::FilePool::getFile
File getFile(FileType fileType, const Sha1Sum &sha1sum)
Search file with the given sha1sum.
Definition: FilePool.cc:67
EventDistributor.hh
openmsx::Sha1SumCommand
Definition: FilePool.cc:19
openmsx::Sha1SumCommand::help
string help(const vector< string > &tokens) const override
Print help for this command.
Definition: FilePool.cc:183
openmsx::FilePoolCore::getFile
File getFile(FileType fileType, const Sha1Sum &sha1sum)
Search file with the given sha1sum.
Definition: FilePoolCore.cc:247
openmsx::Sha1Sum
This class represents the result of a sha1 calculation (a 160-bit value).
Definition: sha1.hh:20
FilePool.hh
openmsx::FileType::ROM
@ ROM
FileContext.hh
openmsx::FileType::NONE
@ NONE
openmsx::FilePool::~FilePool
~FilePool()
Definition: FilePool.cc:61
FileOperations.hh
openmsx::File
Definition: File.hh:16
openmsx::Reactor::getCliComm
CliComm & getCliComm()
Definition: Reactor.cc:306
openmsx::TclObject::getString
std::string_view getString() const
Definition: TclObject.cc:102
openmsx::Command
Definition: Command.hh:41
openmsx::FilePool
Definition: FilePool.hh:16
openmsx::TclObject
Definition: TclObject.hh:22
openmsx::TclObject::getListLength
unsigned getListLength(Interpreter &interp) const
Definition: TclObject.cc:116
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:17
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
openmsx::systemFileContext
FileContext systemFileContext()
Definition: FileContext.cc:152