openMSX
CompressedFileAdapter.cc
Go to the documentation of this file.
2#include "FileException.hh"
3#include "hash_set.hh"
4#include "ranges.hh"
5#include "xxhash.hh"
6#include <cstring>
7
8namespace openmsx {
9
11 template<typename Ptr> [[nodiscard]] const std::string& operator()(const Ptr& p) const {
12 return p->cachedURL;
13 }
14};
16 GetURLFromDecompressed, XXHasher> decompressCache;
17
18
19CompressedFileAdapter::CompressedFileAdapter(std::unique_ptr<FileBase> file_)
20 : file(std::move(file_))
21{
22}
23
25{
26 if (decompressed) {
27 auto it = decompressCache.find(getURL());
28 assert(it != end(decompressCache));
29 assert(it->get() == decompressed);
30 --(*it)->useCount;
31 if ((*it)->useCount == 0) {
32 // delete last user of Decompressed, remove from cache
33 decompressCache.erase(it);
34 }
35 }
36}
37
38void CompressedFileAdapter::decompress()
39{
40 if (decompressed) return;
41
42 const std::string& url = getURL();
43 auto it = decompressCache.find(url);
44 if (it == end(decompressCache)) {
45 auto d = std::make_unique<Decompressed>();
46 decompress(*file, *d);
47 d->cachedModificationDate = getModificationDate();
48 d->cachedURL = url;
49 it = decompressCache.insert_noDuplicateCheck(std::move(d));
50 }
51 ++(*it)->useCount;
52 decompressed = it->get();
53
54 // close original file after successful decompress
55 file.reset();
56}
57
58void CompressedFileAdapter::read(std::span<uint8_t> buffer)
59{
60 decompress();
61 if (decompressed->size < (pos + buffer.size())) {
62 throw FileException("Read beyond end of file");
63 }
64 const auto& buf = decompressed->buf;
65 ranges::copy(std::span{&buf[pos], buffer.size()}, buffer);
66 pos += buffer.size();
67}
68
69void CompressedFileAdapter::write(std::span<const uint8_t> /*buffer*/)
70{
71 throw FileException("Writing to compressed files not yet supported");
72}
73
74std::span<const uint8_t> CompressedFileAdapter::mmap()
75{
76 decompress();
77 return { decompressed->buf.data(), decompressed->size };
78}
79
81{
82 // nothing
83}
84
86{
87 decompress();
88 return decompressed->size;
89}
90
91void CompressedFileAdapter::seek(size_t newPos)
92{
93 pos = newPos;
94}
95
97{
98 return pos;
99}
100
102{
103 throw FileException("Truncating compressed files not yet supported.");
104}
105
107{
108 // nothing because writing is not supported
109}
110
111const std::string& CompressedFileAdapter::getURL() const
112{
113 return file ? file->getURL() : decompressed->cachedURL;
114}
115
117{
118 decompress();
119 return decompressed->originalName;
120}
121
123{
124 return true;
125}
126
128{
129 return file ? file->getModificationDate()
130 : decompressed->cachedModificationDate;
131}
132
133} // namespace openmsx
void read(std::span< uint8_t > buffer) final
std::string_view getOriginalName() final
virtual void decompress(FileBase &file, Decompressed &decompressed)=0
std::span< const uint8_t > mmap() final
void write(std::span< const uint8_t > buffer) final
const std::string & getURL() const final
CompressedFileAdapter(std::unique_ptr< FileBase > file)
const T * data() const
Returns pointer to the start of the memory buffer.
Definition MemBuffer.hh:81
This file implemented 3 utility functions:
Definition Autofire.cc:9
auto copy(InputRange &&range, OutputIter out)
Definition ranges.hh:250
STL namespace.
const std::string & operator()(const Ptr &p) const
constexpr auto end(const zstring_view &x)