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->buf.size() < (pos + buffer.size())) {
62 throw FileException("Read beyond end of file");
63 }
64 ranges::copy(decompressed->buf.subspan(pos, buffer.size()), buffer);
65 pos += buffer.size();
66}
67
68void CompressedFileAdapter::write(std::span<const uint8_t> /*buffer*/)
69{
70 throw FileException("Writing to compressed files not yet supported");
71}
72
73std::span<const uint8_t> CompressedFileAdapter::mmap()
74{
75 decompress();
76 return std::span{decompressed->buf};
77}
78
80{
81 // nothing
82}
83
85{
86 decompress();
87 return decompressed->buf.size();
88}
89
90void CompressedFileAdapter::seek(size_t newPos)
91{
92 pos = newPos;
93}
94
96{
97 return pos;
98}
99
101{
102 throw FileException("Truncating compressed files not yet supported.");
103}
104
106{
107 // nothing because writing is not supported
108}
109
110const std::string& CompressedFileAdapter::getURL() const
111{
112 return file ? file->getURL() : decompressed->cachedURL;
113}
114
116{
117 decompress();
118 return decompressed->originalName;
119}
120
122{
123 return true;
124}
125
127{
128 return file ? file->getModificationDate()
129 : decompressed->cachedModificationDate;
130}
131
132} // 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)
std::span< const T > subspan(size_t offset, size_t n=std::dynamic_extent) const
Definition MemBuffer.hh:137
size_t size() const
Definition MemBuffer.hh:101
This file implemented 3 utility functions:
Definition Autofire.cc:11
constexpr auto copy(InputRange &&range, OutputIter out)
Definition ranges.hh:252
STL namespace.
const std::string & operator()(const Ptr &p) const
constexpr auto end(const zstring_view &x)