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> [[nodiscard]] 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_))
22 {
23 }
24 
26 {
27  if (decompressed) {
28  auto it = decompressCache.find(getURL());
29  assert(it != end(decompressCache));
30  assert(it->get() == decompressed);
31  --(*it)->useCount;
32  if ((*it)->useCount == 0) {
33  // delete last user of Decompressed, remove from cache
34  decompressCache.erase(it);
35  }
36  }
37 }
38 
39 void CompressedFileAdapter::decompress()
40 {
41  if (decompressed) return;
42 
43  const std::string& url = getURL();
44  auto it = decompressCache.find(url);
45  if (it == end(decompressCache)) {
46  auto d = std::make_unique<Decompressed>();
47  decompress(*file, *d);
48  d->cachedModificationDate = getModificationDate();
49  d->cachedURL = url;
50  it = decompressCache.insert_noDuplicateCheck(std::move(d));
51  }
52  ++(*it)->useCount;
53  decompressed = it->get();
54 
55  // close original file after successful decompress
56  file.reset();
57 }
58 
59 void CompressedFileAdapter::read(void* buffer, size_t num)
60 {
61  decompress();
62  if (decompressed->size < (pos + num)) {
63  throw FileException("Read beyond end of file");
64  }
65  const auto& buf = decompressed->buf;
66  memcpy(buffer, buf.data() + pos, num);
67  pos += num;
68 }
69 
70 void CompressedFileAdapter::write(const void* /*buffer*/, size_t /*num*/)
71 {
72  throw FileException("Writing to compressed files not yet supported");
73 }
74 
76 {
77  decompress();
78  return { decompressed->buf.data(), decompressed->size };
79 }
80 
82 {
83  // nothing
84 }
85 
87 {
88  decompress();
89  return decompressed->size;
90 }
91 
92 void CompressedFileAdapter::seek(size_t newpos)
93 {
94  pos = newpos;
95 }
96 
98 {
99  return pos;
100 }
101 
102 void CompressedFileAdapter::truncate(size_t /*size*/)
103 {
104  throw FileException("Truncating compressed files not yet supported.");
105 }
106 
108 {
109  // nothing because writing is not supported
110 }
111 
112 const string& CompressedFileAdapter::getURL() const
113 {
114  return file ? file->getURL() : decompressed->cachedURL;
115 }
116 
118 {
119  decompress();
120  return decompressed->originalName;
121 }
122 
124 {
125  return true;
126 }
127 
129 {
130  return file ? file->getModificationDate()
131  : decompressed->cachedModificationDate;
132 }
133 
134 } // namespace openmsx
std::string_view getOriginalName() final
virtual void decompress(FileBase &file, Decompressed &decompressed)=0
void write(const void *buffer, size_t num) final
span< const uint8_t > mmap() final
CompressedFileAdapter(std::unique_ptr< FileBase > file)
const std::string & getURL() const final
void read(void *buffer, size_t num) final
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:5
const string & operator()(const Ptr &p) const
constexpr auto end(const zstring_view &x)
Definition: zstring_view.hh:83