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 namespace openmsx {
8 
10  template<typename Ptr> [[nodiscard]] const std::string& operator()(const Ptr& p) const {
11  return p->cachedURL;
12  }
13 };
15  GetURLFromDecompressed, XXHasher> decompressCache;
16 
17 
18 CompressedFileAdapter::CompressedFileAdapter(std::unique_ptr<FileBase> file_)
19  : file(std::move(file_))
20 {
21 }
22 
24 {
25  if (decompressed) {
26  auto it = decompressCache.find(getURL());
27  assert(it != end(decompressCache));
28  assert(it->get() == decompressed);
29  --(*it)->useCount;
30  if ((*it)->useCount == 0) {
31  // delete last user of Decompressed, remove from cache
32  decompressCache.erase(it);
33  }
34  }
35 }
36 
37 void CompressedFileAdapter::decompress()
38 {
39  if (decompressed) return;
40 
41  const std::string& url = getURL();
42  auto it = decompressCache.find(url);
43  if (it == end(decompressCache)) {
44  auto d = std::make_unique<Decompressed>();
45  decompress(*file, *d);
46  d->cachedModificationDate = getModificationDate();
47  d->cachedURL = url;
48  it = decompressCache.insert_noDuplicateCheck(std::move(d));
49  }
50  ++(*it)->useCount;
51  decompressed = it->get();
52 
53  // close original file after successful decompress
54  file.reset();
55 }
56 
57 void CompressedFileAdapter::read(void* buffer, size_t num)
58 {
59  decompress();
60  if (decompressed->size < (pos + num)) {
61  throw FileException("Read beyond end of file");
62  }
63  const auto& buf = decompressed->buf;
64  memcpy(buffer, buf.data() + pos, num);
65  pos += num;
66 }
67 
68 void CompressedFileAdapter::write(const void* /*buffer*/, size_t /*num*/)
69 {
70  throw FileException("Writing to compressed files not yet supported");
71 }
72 
74 {
75  decompress();
76  return { decompressed->buf.data(), decompressed->size };
77 }
78 
80 {
81  // nothing
82 }
83 
85 {
86  decompress();
87  return decompressed->size;
88 }
89 
90 void CompressedFileAdapter::seek(size_t newpos)
91 {
92  pos = newpos;
93 }
94 
96 {
97  return pos;
98 }
99 
100 void CompressedFileAdapter::truncate(size_t /*size*/)
101 {
102  throw FileException("Truncating compressed files not yet supported.");
103 }
104 
106 {
107  // nothing because writing is not supported
108 }
109 
110 const 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
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
const std::string & getURL() const final
CompressedFileAdapter(std::unique_ptr< FileBase > file)
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:9
const std::string & operator()(const Ptr &p) const
constexpr auto end(const zstring_view &x)
Definition: zstring_view.hh:84