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 "outer.hh"
12#include "xrange.hh"
13#include <memory>
14
15namespace openmsx {
16
17[[nodiscard]] static TclObject initialFilePoolSettingValue()
18{
19 TclObject result;
20
21 for (const auto& p : systemFileContext().getPaths()) {
22 result.addListElement(
23 makeTclDict("-path", tmpStrCat(p, "/systemroms"),
24 "-types", "system_rom"),
25 makeTclDict("-path", tmpStrCat(p, "/software"),
26 "-types", "rom disk tape"));
27 }
28 return result;
29}
30
32 : core(FileOperations::getUserDataDir() + "/.filecache",
33 [&] { return getDirectories(); },
34 [&](std::string_view message, float fraction) { reportProgress(message, fraction); })
35 , filePoolSetting(
36 controller, "__filepool",
37 "This is an internal setting. Don't change this directly, "
38 "instead use the 'filepool' command.",
39 initialFilePoolSettingValue().getString())
40 , reactor(reactor_)
41 , sha1SumCommand(controller)
42{
43 filePoolSetting.attach(*this);
44 reactor.getEventDistributor().registerEventListener(EventType::QUIT, *this);
45}
46
48{
50 filePoolSetting.detach(*this);
51}
52
53File FilePool::getFile(FileType fileType, const Sha1Sum& sha1sum)
54{
55 return core.getFile(fileType, sha1sum);
56}
57
59{
60 return core.getSha1Sum(file);
61}
62
63std::optional<Sha1Sum> FilePool::getSha1Sum(const std::string& filename)
64{
65 try {
66 File file(filename);
67 return getSha1Sum(file);
68 } catch (MSXException&) {
69 return {};
70 }
71}
72
73[[nodiscard]] static FileType parseTypes(Interpreter& interp, const TclObject& list)
74{
75 using enum FileType;
76 auto result = NONE;
77 for (auto i : xrange(list.getListLength(interp))) {
78 std::string_view elem = list.getListIndex(interp, i).getString();
79 if (elem == "system_rom") {
80 result |= SYSTEM_ROM;
81 } else if (elem == "rom") {
82 result |= ROM;
83 } else if (elem == "disk") {
84 result |= DISK;
85 } else if (elem == "tape") {
86 result |= TAPE;
87 } else {
88 throw CommandException("Unknown type: ", elem);
89 }
90 }
91 return result;
92}
93
95{
97 try {
98 auto& interp = filePoolSetting.getInterpreter();
99 const TclObject& all = filePoolSetting.getValue();
100 for (auto i : xrange(all.getListLength(interp))) {
102 bool hasPath = false;
103 dir.types = FileType::NONE;
104 TclObject line = all.getListIndex(interp, i);
105 unsigned numItems = line.getListLength(interp);
106 if (numItems & 1) {
107 throw CommandException(
108 "Expected a list with an even number "
109 "of elements, but got ", line.getString());
110 }
111 for (unsigned j = 0; j < numItems; j += 2) {
112 std::string_view name = line.getListIndex(interp, j + 0).getString();
113 TclObject value = line.getListIndex(interp, j + 1);
114 if (name == "-path") {
115 dir.path = value.getString();
116 hasPath = true;
117 } else if (name == "-types") {
118 dir.types = parseTypes(interp, value);
119 } else {
120 throw CommandException("Unknown item: ", name);
121 }
122 }
123 if (!hasPath) {
124 throw CommandException(
125 "Missing -path item: ", line.getString());
126 }
127 if (dir.types == FileType::NONE) {
128 throw CommandException(
129 "Missing -types item: ", line.getString());
130 }
131 result.push_back(std::move(dir));
132 }
133 } catch (CommandException& e) {
134 reactor.getCliComm().printWarning(
135 "Error while parsing '__filepool' setting", e.getMessage());
136 }
137 return result;
138}
139
140void FilePool::update(const Setting& setting) noexcept
141{
142 assert(&setting == &filePoolSetting); (void)setting;
143 (void)getDirectories(); // check for syntax errors
144}
145
146void FilePool::reportProgress(std::string_view message, float fraction)
147{
148 if (quit) core.abort();
149 reactor.getCliComm().printProgress(message, fraction);
150 reactor.getDisplay().repaint();
151}
152
153int FilePool::signalEvent(const Event& event)
154{
155 (void)event; // avoid warning for non-assert compiles
156 assert(getType(event) == EventType::QUIT);
157 quit = true;
158 return 0;
159}
160
161
162// class Sha1SumCommand
163
164FilePool::Sha1SumCommand::Sha1SumCommand(
165 CommandController& commandController_)
166 : Command(commandController_, "sha1sum")
167{
168}
169
170void FilePool::Sha1SumCommand::execute(std::span<const TclObject> tokens, TclObject& result)
171{
172 checkNumArgs(tokens, 2, "filename");
173 File file(FileOperations::expandTilde(std::string(tokens[1].getString())));
174 auto& filePool = OUTER(FilePool, sha1SumCommand);
175 result = filePool.getSha1Sum(file).toString();
176}
177
178std::string FilePool::Sha1SumCommand::help(std::span<const TclObject> /*tokens*/) const
179{
180 return "Calculate sha1 value for the given file. If the file is "
181 "(g)zipped the sha1 is calculated on the unzipped version.";
182}
183
184void FilePool::Sha1SumCommand::tabCompletion(std::vector<std::string>& tokens) const
185{
186 completeFileName(tokens, userFileContext());
187}
188
189} // namespace openmsx
BaseSetting * setting
void printProgress(std::string_view message, float fraction)
Definition CliComm.cc:20
void printWarning(std::string_view message)
Definition CliComm.cc:10
void repaint()
Redraw the display.
Definition Display.cc:365
void unregisterEventListener(EventType type, EventListener &listener)
Unregisters a previously registered event listener.
Sha1Sum getSha1Sum(File &file)
Calculate sha1sum for the given File object.
File getFile(FileType fileType, const Sha1Sum &sha1sum)
Search file with the given sha1sum.
void abort()
This is only meaningful to call from within the 'reportProgress' callback (constructor parameter).
std::vector< Dir > Directories
FilePool(CommandController &controller, Reactor &reactor)
Definition FilePool.cc:31
FilePoolCore::Directories getDirectories() const
Definition FilePool.cc:94
Sha1Sum getSha1Sum(File &file)
Calculate sha1sum for the given File object.
Definition FilePool.cc:58
File getFile(FileType fileType, const Sha1Sum &sha1sum)
Search file with the given sha1sum.
Definition FilePool.cc:53
Contains the main loop of openMSX.
Definition Reactor.hh:74
Display & getDisplay()
Definition Reactor.hh:92
CliComm & getCliComm()
Definition Reactor.cc:323
EventDistributor & getEventDistributor()
Definition Reactor.hh:88
Interpreter & getInterpreter() const
Definition Setting.cc:139
const TclObject & getValue() const final
Gets the current value of this setting as a TclObject.
Definition Setting.hh:134
This class represents the result of a sha1 calculation (a 160-bit value).
Definition sha1.hh:24
void detach(Observer< T > &observer)
Definition Subject.hh:60
unsigned getListLength(Interpreter &interp) const
Definition TclObject.cc:155
TclObject getListIndex(Interpreter &interp, unsigned index) const
Definition TclObject.cc:173
void addListElement(const T &t)
Definition TclObject.hh:131
zstring_view getString() const
Definition TclObject.cc:141
string expandTilde(string path)
Expand the '~' character to the users home directory.
This file implemented 3 utility functions:
Definition Autofire.cc:11
const FileContext & systemFileContext()
EventType getType(const Event &event)
Definition Event.hh:518
const FileContext & userFileContext()
std::variant< KeyUpEvent, KeyDownEvent, MouseMotionEvent, MouseButtonUpEvent, MouseButtonDownEvent, MouseWheelEvent, JoystickAxisMotionEvent, JoystickHatEvent, JoystickButtonUpEvent, JoystickButtonDownEvent, OsdControlReleaseEvent, OsdControlPressEvent, WindowEvent, TextEvent, FileDropEvent, QuitEvent, FinishFrameEvent, CliCommandEvent, GroupEvent, BootEvent, FrameDrawnEvent, BreakEvent, SwitchRendererEvent, TakeReverseSnapshotEvent, AfterTimedEvent, MachineLoadedEvent, MachineActivatedEvent, MachineDeactivatedEvent, MidiInReaderEvent, MidiInWindowsEvent, MidiInCoreMidiEvent, MidiInCoreMidiVirtualEvent, MidiInALSAEvent, Rs232TesterEvent, Rs232NetEvent, ImGuiDelayedActionEvent, ImGuiActiveEvent > Event
Definition Event.hh:446
TclObject makeTclDict(Args &&... args)
Definition TclObject.hh:299
#define OUTER(type, member)
Definition outer.hh:42
TemporaryString tmpStrCat(Ts &&... ts)
Definition strCat.hh:742
constexpr auto xrange(T e)
Definition xrange.hh:132