openMSX
CompressedFileAdapter.cc
Go to the documentation of this file.
2 #include "FileException.hh"
3 #include "hash_set.hh"
4 #include "xxhash.hh"
5 #include <cstring>
6 
7 using std::string;
8 
9 namespace openmsx {
10 
12  template<typename Ptr> const string& operator()(const Ptr& p) const {
13  return p->cachedURL;
14  }
15 };
17  GetURLFromDecompressed, XXHasher> decompressCache;
18 
19 
20 CompressedFileAdapter::CompressedFileAdapter(std::unique_ptr<FileBase> file_)
21  : file(std::move(file_)), pos(0)
22 {
23 }
24 
26 {
27  auto it = decompressCache.find(getURL());
28  decompressed.reset();
29  if (it != end(decompressCache) && it->unique()) {
30  // delete last user of Decompressed, remove from cache
31  decompressCache.erase(it);
32  }
33 }
34 
35 void CompressedFileAdapter::decompress()
36 {
37  if (decompressed) return;
38 
39  string url = getURL();
40  auto it = decompressCache.find(url);
41  if (it != end(decompressCache)) {
42  decompressed = *it;
43  } else {
44  decompressed = std::make_shared<Decompressed>();
45  decompress(*file, *decompressed);
46  decompressed->cachedModificationDate = getModificationDate();
47  decompressed->cachedURL = std::move(url);
48  decompressCache.insert_noDuplicateCheck(decompressed);
49  }
50 
51  // close original file after succesful decompress
52  file.reset();
53 }
54 
55 void CompressedFileAdapter::read(void* buffer, size_t num)
56 {
57  decompress();
58  if (decompressed->size < (pos + num)) {
59  throw FileException("Read beyond end of file");
60  }
61  const auto& buf = decompressed->buf;
62  memcpy(buffer, buf.data() + pos, num);
63  pos += num;
64 }
65 
66 void CompressedFileAdapter::write(const void* /*buffer*/, size_t /*num*/)
67 {
68  throw FileException("Writing to compressed files not yet supported");
69 }
70 
72 {
73  decompress();
74  return { decompressed->buf.data(), decompressed->size };
75 }
76 
78 {
79  // nothing
80 }
81 
83 {
84  decompress();
85  return decompressed->size;
86 }
87 
88 void CompressedFileAdapter::seek(size_t newpos)
89 {
90  pos = newpos;
91 }
92 
94 {
95  return pos;
96 }
97 
98 void CompressedFileAdapter::truncate(size_t /*size*/)
99 {
100  throw FileException("Truncating compressed files not yet supported.");
101 }
102 
104 {
105  // nothing because writing is not supported
106 }
107 
109 {
110  return file ? file->getURL() : decompressed->cachedURL;
111 }
112 
114 {
115  decompress();
116  return decompressed->originalName;
117 }
118 
120 {
121  return true;
122 }
123 
125 {
126  return file ? file->getModificationDate()
127  : decompressed->cachedModificationDate;
128 }
129 
130 } // namespace openmsx
FileException.hh
xxhash.hh
openmsx::CompressedFileAdapter::seek
void seek(size_t pos) final override
Definition: CompressedFileAdapter.cc:88
openmsx::CompressedFileAdapter::isReadOnly
bool isReadOnly() const final override
Definition: CompressedFileAdapter.cc:119
openmsx::CompressedFileAdapter::decompress
virtual void decompress(FileBase &file, Decompressed &decompressed)=0
openmsx::CompressedFileAdapter::mmap
span< uint8_t > mmap() final override
Definition: CompressedFileAdapter.cc:71
XXHasher
Definition: xxhash.hh:153
hash_set.hh
span
Definition: span.hh:34
openmsx::CompressedFileAdapter::getPos
size_t getPos() final override
Definition: CompressedFileAdapter.cc:93
openmsx::CompressedFileAdapter::truncate
void truncate(size_t size) final override
Definition: CompressedFileAdapter.cc:98
openmsx::FileException
Definition: FileException.hh:8
CompressedFileAdapter.hh
openmsx::CompressedFileAdapter::getSize
size_t getSize() final override
Definition: CompressedFileAdapter.cc:82
openmsx::CompressedFileAdapter::munmap
void munmap() final override
Definition: CompressedFileAdapter.cc:77
openmsx::GetURLFromDecompressed::operator()
const string & operator()(const Ptr &p) const
Definition: CompressedFileAdapter.cc:12
openmsx::GetURLFromDecompressed
Definition: CompressedFileAdapter.cc:11
hash_set
Definition: hash_set.hh:265
openmsx::CompressedFileAdapter::write
void write(const void *buffer, size_t num) final override
Definition: CompressedFileAdapter.cc:66
openmsx::CompressedFileAdapter::getOriginalName
std::string getOriginalName() final override
Definition: CompressedFileAdapter.cc:113
openmsx::CompressedFileAdapter::~CompressedFileAdapter
~CompressedFileAdapter() override
Definition: CompressedFileAdapter.cc:25
openmsx::CompressedFileAdapter::getURL
std::string getURL() const final override
Definition: CompressedFileAdapter.cc:108
openmsx::CompressedFileAdapter::CompressedFileAdapter
CompressedFileAdapter(std::unique_ptr< FileBase > file)
Definition: CompressedFileAdapter.cc:20
openmsx::CompressedFileAdapter::getModificationDate
time_t getModificationDate() final override
Definition: CompressedFileAdapter.cc:124
openmsx
Thanks to enen for testing this on a real cartridge:
Definition: Autofire.cc:5
openmsx::CompressedFileAdapter::read
void read(void *buffer, size_t num) final override
Definition: CompressedFileAdapter.cc:55
openmsx::CompressedFileAdapter::flush
void flush() final override
Definition: CompressedFileAdapter.cc:103