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 auto result = FileType::NONE;
76 for (auto i : xrange(list.getListLength(interp))) {
77 std::string_view elem = list.getListIndex(interp, i).getString();
78 if (elem == "system_rom") {
79 result |= FileType::SYSTEM_ROM;
80 } else if (elem == "rom") {
81 result |= FileType::ROM;
82 } else if (elem == "disk") {
83 result |= FileType::DISK;
84 } else if (elem == "tape") {
85 result |= FileType::TAPE;
86 } else {
87 throw CommandException("Unknown type: ", elem);
88 }
89 }
90 return result;
91}
92
94{
96 try {
97 auto& interp = filePoolSetting.getInterpreter();
98 const TclObject& all = filePoolSetting.getValue();
99 for (auto i : xrange(all.getListLength(interp))) {
101 bool hasPath = false;
102 dir.types = FileType::NONE;
103 TclObject line = all.getListIndex(interp, i);
104 unsigned numItems = line.getListLength(interp);
105 if (numItems & 1) {
106 throw CommandException(
107 "Expected a list with an even number "
108 "of elements, but got ", line.getString());
109 }
110 for (unsigned j = 0; j < numItems; j += 2) {
111 std::string_view name = line.getListIndex(interp, j + 0).getString();
112 TclObject value = line.getListIndex(interp, j + 1);
113 if (name == "-path") {
114 dir.path = value.getString();
115 hasPath = true;
116 } else if (name == "-types") {
117 dir.types = parseTypes(interp, value);
118 } else {
119 throw CommandException("Unknown item: ", name);
120 }
121 }
122 if (!hasPath) {
123 throw CommandException(
124 "Missing -path item: ", line.getString());
125 }
126 if (dir.types == FileType::NONE) {
127 throw CommandException(
128 "Missing -types item: ", line.getString());
129 }
130 result.push_back(std::move(dir));
131 }
132 } catch (CommandException& e) {
133 reactor.getCliComm().printWarning(
134 "Error while parsing '__filepool' setting", e.getMessage());
135 }
136 return result;
137}
138
139void FilePool::update(const Setting& setting) noexcept
140{
141 assert(&setting == &filePoolSetting); (void)setting;
142 (void)getDirectories(); // check for syntax errors
143}
144
145void FilePool::reportProgress(std::string_view message, float fraction)
146{
147 if (quit) core.abort();
148 reactor.getCliComm().printProgress(message, fraction);
149 reactor.getDisplay().repaint();
150}
151
152int FilePool::signalEvent(const Event& event)
153{
154 (void)event; // avoid warning for non-assert compiles
155 assert(getType(event) == EventType::QUIT);
156 quit = true;
157 return 0;
158}
159
160
161// class Sha1SumCommand
162
163FilePool::Sha1SumCommand::Sha1SumCommand(
164 CommandController& commandController_)
165 : Command(commandController_, "sha1sum")
166{
167}
168
169void FilePool::Sha1SumCommand::execute(std::span<const TclObject> tokens, TclObject& result)
170{
171 checkNumArgs(tokens, 2, "filename");
172 File file(FileOperations::expandTilde(std::string(tokens[1].getString())));
173 auto& filePool = OUTER(FilePool, sha1SumCommand);
174 result = filePool.getSha1Sum(file).toString();
175}
176
177std::string FilePool::Sha1SumCommand::help(std::span<const TclObject> /*tokens*/) const
178{
179 return "Calculate sha1 value for the given file. If the file is "
180 "(g)zipped the sha1 is calculated on the unzipped version.";
181}
182
183void FilePool::Sha1SumCommand::tabCompletion(std::vector<std::string>& tokens) const
184{
185 completeFileName(tokens, userFileContext());
186}
187
188} // 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:372
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:93
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:72
Display & getDisplay()
Definition Reactor.hh:90
CliComm & getCliComm()
Definition Reactor.cc:324
EventDistributor & getEventDistributor()
Definition Reactor.hh:86
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:133
This class represents the result of a sha1 calculation (a 160-bit value).
Definition sha1.hh:23
void detach(Observer< T > &observer)
Definition Subject.hh:56
unsigned getListLength(Interpreter &interp) const
Definition TclObject.cc:156
TclObject getListIndex(Interpreter &interp, unsigned index) const
Definition TclObject.cc:174
void addListElement(const T &t)
Definition TclObject.hh:127
zstring_view getString() const
Definition TclObject.cc:142
string expandTilde(string path)
Expand the '~' character to the users home directory.
This file implemented 3 utility functions:
Definition Autofire.cc:9
const FileContext & systemFileContext()
EventType getType(const Event &event)
Definition Event.hh:526
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:454
TclObject makeTclDict(Args &&... args)
Definition TclObject.hh:295
#define OUTER(type, member)
Definition outer.hh:41
TemporaryString tmpStrCat(Ts &&... ts)
Definition strCat.hh:742
constexpr auto xrange(T e)
Definition xrange.hh:132