/src/wxwidgets/include/wx/archive.h
Line | Count | Source (jump to first uncovered line) |
1 | | ///////////////////////////////////////////////////////////////////////////// |
2 | | // Name: wx/archive.h |
3 | | // Purpose: Streams for archive formats |
4 | | // Author: Mike Wetherell |
5 | | // Copyright: (c) 2004 Mike Wetherell |
6 | | // Licence: wxWindows licence |
7 | | ///////////////////////////////////////////////////////////////////////////// |
8 | | |
9 | | #ifndef _WX_ARCHIVE_H__ |
10 | | #define _WX_ARCHIVE_H__ |
11 | | |
12 | | #include "wx/defs.h" |
13 | | |
14 | | #if wxUSE_STREAMS && wxUSE_ARCHIVE_STREAMS |
15 | | |
16 | | #include "wx/stream.h" |
17 | | #include "wx/filename.h" |
18 | | |
19 | | |
20 | | ///////////////////////////////////////////////////////////////////////////// |
21 | | // wxArchiveNotifier |
22 | | |
23 | | class WXDLLIMPEXP_BASE wxArchiveNotifier |
24 | | { |
25 | | public: |
26 | | virtual ~wxArchiveNotifier() = default; |
27 | | |
28 | | virtual void OnEntryUpdated(class wxArchiveEntry& entry) = 0; |
29 | | }; |
30 | | |
31 | | |
32 | | ///////////////////////////////////////////////////////////////////////////// |
33 | | // wxArchiveEntry |
34 | | // |
35 | | // Holds an entry's meta data, such as filename and timestamp. |
36 | | |
37 | | class WXDLLIMPEXP_BASE wxArchiveEntry : public wxObject |
38 | | { |
39 | | public: |
40 | | virtual ~wxArchiveEntry() = default; |
41 | | |
42 | | virtual wxDateTime GetDateTime() const = 0; |
43 | | virtual wxFileOffset GetSize() const = 0; |
44 | | virtual wxFileOffset GetOffset() const = 0; |
45 | | virtual bool IsDir() const = 0; |
46 | | virtual bool IsReadOnly() const = 0; |
47 | | virtual wxString GetInternalName() const = 0; |
48 | | virtual wxPathFormat GetInternalFormat() const = 0; |
49 | | virtual wxString GetName(wxPathFormat format = wxPATH_NATIVE) const = 0; |
50 | | |
51 | | virtual void SetDateTime(const wxDateTime& dt) = 0; |
52 | | virtual void SetSize(wxFileOffset size) = 0; |
53 | | virtual void SetIsDir(bool isDir = true) = 0; |
54 | | virtual void SetIsReadOnly(bool isReadOnly = true) = 0; |
55 | | virtual void SetName(const wxString& name, |
56 | | wxPathFormat format = wxPATH_NATIVE) = 0; |
57 | | |
58 | 0 | wxNODISCARD wxArchiveEntry *Clone() const { return DoClone(); } |
59 | | |
60 | | void SetNotifier(wxArchiveNotifier& notifier); |
61 | 0 | virtual void UnsetNotifier() { m_notifier = nullptr; } |
62 | | |
63 | | protected: |
64 | 8.26k | wxArchiveEntry() : m_notifier(nullptr) { } |
65 | 16.0k | wxArchiveEntry(const wxArchiveEntry& e) : wxObject(e), m_notifier(nullptr) { } |
66 | | |
67 | | virtual void SetOffset(wxFileOffset offset) = 0; |
68 | | virtual wxArchiveEntry* DoClone() const = 0; |
69 | | |
70 | 5.59k | wxArchiveNotifier *GetNotifier() const { return m_notifier; } |
71 | | wxArchiveEntry& operator=(const wxArchiveEntry& entry); |
72 | | |
73 | | private: |
74 | | wxArchiveNotifier *m_notifier; |
75 | | |
76 | | wxDECLARE_ABSTRACT_CLASS(wxArchiveEntry); |
77 | | }; |
78 | | |
79 | | |
80 | | ///////////////////////////////////////////////////////////////////////////// |
81 | | // wxArchiveInputStream |
82 | | // |
83 | | // GetNextEntry() returns a wxArchiveEntry object containing the meta-data |
84 | | // for the next entry in the archive (and gives away ownership). Reading from |
85 | | // the wxArchiveInputStream then returns the entry's data. Eof() becomes true |
86 | | // after an attempt has been made to read past the end of the entry's data. |
87 | | // |
88 | | // When there are no more entries, GetNextEntry() returns nullptr and sets Eof(). |
89 | | |
90 | | class WXDLLIMPEXP_BASE wxArchiveInputStream : public wxFilterInputStream |
91 | | { |
92 | | public: |
93 | | typedef wxArchiveEntry entry_type; |
94 | | |
95 | | virtual ~wxArchiveInputStream() = default; |
96 | | |
97 | | virtual bool OpenEntry(wxArchiveEntry& entry) = 0; |
98 | | virtual bool CloseEntry() = 0; |
99 | | |
100 | 0 | wxArchiveEntry *GetNextEntry() { return DoGetNextEntry(); } |
101 | | |
102 | 0 | virtual char Peek() override { return wxInputStream::Peek(); } |
103 | | |
104 | | protected: |
105 | | wxArchiveInputStream(wxInputStream& stream, wxMBConv& conv); |
106 | | wxArchiveInputStream(wxInputStream *stream, wxMBConv& conv); |
107 | | |
108 | | virtual wxArchiveEntry *DoGetNextEntry() = 0; |
109 | | |
110 | 29.8k | wxMBConv& GetConv() const { return m_conv; } |
111 | | |
112 | | private: |
113 | | wxMBConv& m_conv; |
114 | | }; |
115 | | |
116 | | |
117 | | ///////////////////////////////////////////////////////////////////////////// |
118 | | // wxArchiveOutputStream |
119 | | // |
120 | | // PutNextEntry is used to create a new entry in the output archive, then |
121 | | // the entry's data is written to the wxArchiveOutputStream. |
122 | | // |
123 | | // Only one entry can be open for output at a time; another call to |
124 | | // PutNextEntry closes the current entry and begins the next. |
125 | | // |
126 | | // The overload 'bool PutNextEntry(wxArchiveEntry *entry)' takes ownership |
127 | | // of the entry object. |
128 | | |
129 | | class WXDLLIMPEXP_BASE wxArchiveOutputStream : public wxFilterOutputStream |
130 | | { |
131 | | public: |
132 | | virtual ~wxArchiveOutputStream() = default; |
133 | | |
134 | | virtual bool PutNextEntry(wxArchiveEntry *entry) = 0; |
135 | | |
136 | | virtual bool PutNextEntry(const wxString& name, |
137 | | const wxDateTime& dt = wxDateTime::Now(), |
138 | | wxFileOffset size = wxInvalidOffset) = 0; |
139 | | |
140 | | virtual bool PutNextDirEntry(const wxString& name, |
141 | | const wxDateTime& dt = wxDateTime::Now()) = 0; |
142 | | |
143 | | virtual bool CopyEntry(wxArchiveEntry *entry, |
144 | | wxArchiveInputStream& stream) = 0; |
145 | | |
146 | | virtual bool CopyArchiveMetaData(wxArchiveInputStream& stream) = 0; |
147 | | |
148 | | virtual bool CloseEntry() = 0; |
149 | | |
150 | | protected: |
151 | | wxArchiveOutputStream(wxOutputStream& stream, wxMBConv& conv); |
152 | | wxArchiveOutputStream(wxOutputStream *stream, wxMBConv& conv); |
153 | | |
154 | 0 | wxMBConv& GetConv() const { return m_conv; } |
155 | | |
156 | | private: |
157 | | wxMBConv& m_conv; |
158 | | }; |
159 | | |
160 | | |
161 | | ///////////////////////////////////////////////////////////////////////////// |
162 | | // wxArchiveIterator |
163 | | // |
164 | | // An input iterator that can be used to transfer an archive's catalog to |
165 | | // a container. |
166 | | |
167 | | #include <iterator> |
168 | | #include <utility> |
169 | | |
170 | | template <class X, class Y> inline |
171 | | void _wxSetArchiveIteratorValue( |
172 | | X& val, Y entry, void *WXUNUSED(d)) |
173 | | { |
174 | | val = X(entry); |
175 | | } |
176 | | template <class X, class Y, class Z> inline |
177 | | void _wxSetArchiveIteratorValue( |
178 | | std::pair<X, Y>& val, Z entry, Z WXUNUSED(d)) |
179 | | { |
180 | | val = std::make_pair(X(entry->GetInternalName()), Y(entry)); |
181 | | } |
182 | | |
183 | | template <class Arc, class T = typename Arc::entry_type*> |
184 | | class wxArchiveIterator |
185 | | { |
186 | | public: |
187 | | typedef std::input_iterator_tag iterator_category; |
188 | | typedef T value_type; |
189 | | typedef ptrdiff_t difference_type; |
190 | | typedef T* pointer; |
191 | | typedef T& reference; |
192 | | |
193 | | wxArchiveIterator() : m_rep(nullptr) { } |
194 | | |
195 | | wxArchiveIterator(Arc& arc) { |
196 | | typename Arc::entry_type* entry = arc.GetNextEntry(); |
197 | | m_rep = entry ? new Rep(arc, entry) : nullptr; |
198 | | } |
199 | | |
200 | | wxArchiveIterator(const wxArchiveIterator& it) : m_rep(it.m_rep) { |
201 | | if (m_rep) |
202 | | m_rep->AddRef(); |
203 | | } |
204 | | |
205 | | ~wxArchiveIterator() { |
206 | | if (m_rep) |
207 | | m_rep->UnRef(); |
208 | | } |
209 | | |
210 | | const T& operator *() const { |
211 | | return m_rep->GetValue(); |
212 | | } |
213 | | |
214 | | const T* operator ->() const { |
215 | | return &**this; |
216 | | } |
217 | | |
218 | | wxArchiveIterator& operator =(const wxArchiveIterator& it) { |
219 | | if (it.m_rep) |
220 | | it.m_rep->AddRef(); |
221 | | if (m_rep) |
222 | | m_rep->UnRef(); |
223 | | m_rep = it.m_rep; |
224 | | return *this; |
225 | | } |
226 | | |
227 | | wxArchiveIterator& operator ++() { |
228 | | m_rep = m_rep->Next(); |
229 | | return *this; |
230 | | } |
231 | | |
232 | | wxArchiveIterator operator ++(int) { |
233 | | wxArchiveIterator it(*this); |
234 | | ++(*this); |
235 | | return it; |
236 | | } |
237 | | |
238 | | bool operator ==(const wxArchiveIterator& j) const { |
239 | | return m_rep == j.m_rep; |
240 | | } |
241 | | |
242 | | bool operator !=(const wxArchiveIterator& j) const { |
243 | | return !(*this == j); |
244 | | } |
245 | | |
246 | | private: |
247 | | class Rep { |
248 | | Arc& m_arc; |
249 | | typename Arc::entry_type* m_entry; |
250 | | T m_value; |
251 | | int m_ref; |
252 | | |
253 | | public: |
254 | | Rep(Arc& arc, typename Arc::entry_type* entry) |
255 | | : m_arc(arc), m_entry(entry), m_value(), m_ref(1) { } |
256 | | ~Rep() |
257 | | { delete m_entry; } |
258 | | |
259 | | void AddRef() { |
260 | | m_ref++; |
261 | | } |
262 | | |
263 | | void UnRef() { |
264 | | if (--m_ref == 0) |
265 | | delete this; |
266 | | } |
267 | | |
268 | | Rep *Next() { |
269 | | typename Arc::entry_type* entry = m_arc.GetNextEntry(); |
270 | | if (!entry) { |
271 | | UnRef(); |
272 | | return nullptr; |
273 | | } |
274 | | if (m_ref > 1) { |
275 | | m_ref--; |
276 | | return new Rep(m_arc, entry); |
277 | | } |
278 | | delete m_entry; |
279 | | m_entry = entry; |
280 | | m_value = T(); |
281 | | return this; |
282 | | } |
283 | | |
284 | | const T& GetValue() { |
285 | | if (m_entry) { |
286 | | _wxSetArchiveIteratorValue(m_value, m_entry, m_entry); |
287 | | m_entry = nullptr; |
288 | | } |
289 | | return m_value; |
290 | | } |
291 | | } *m_rep; |
292 | | }; |
293 | | |
294 | | typedef wxArchiveIterator<wxArchiveInputStream> wxArchiveIter; |
295 | | typedef wxArchiveIterator<wxArchiveInputStream, |
296 | | std::pair<wxString, wxArchiveEntry*> > wxArchivePairIter; |
297 | | |
298 | | |
299 | | ///////////////////////////////////////////////////////////////////////////// |
300 | | // wxArchiveClassFactory |
301 | | // |
302 | | // A wxArchiveClassFactory instance for a particular archive type allows |
303 | | // the creation of the other classes that may be needed. |
304 | | |
305 | | void WXDLLIMPEXP_BASE wxUseArchiveClasses(); |
306 | | |
307 | | class WXDLLIMPEXP_BASE wxArchiveClassFactory : public wxFilterClassFactoryBase |
308 | | { |
309 | | public: |
310 | | typedef wxArchiveEntry entry_type; |
311 | | typedef wxArchiveInputStream instream_type; |
312 | | typedef wxArchiveOutputStream outstream_type; |
313 | | typedef wxArchiveNotifier notifier_type; |
314 | | typedef wxArchiveIter iter_type; |
315 | | typedef wxArchivePairIter pairiter_type; |
316 | | |
317 | | virtual ~wxArchiveClassFactory() = default; |
318 | | |
319 | | wxArchiveEntry *NewEntry() const |
320 | 0 | { return DoNewEntry(); } |
321 | | wxArchiveInputStream *NewStream(wxInputStream& stream) const |
322 | 0 | { return DoNewStream(stream); } |
323 | | wxArchiveOutputStream *NewStream(wxOutputStream& stream) const |
324 | 0 | { return DoNewStream(stream); } |
325 | | wxArchiveInputStream *NewStream(wxInputStream *stream) const |
326 | 0 | { return DoNewStream(stream); } |
327 | | wxArchiveOutputStream *NewStream(wxOutputStream *stream) const |
328 | 0 | { return DoNewStream(stream); } |
329 | | |
330 | | virtual wxString GetInternalName( |
331 | | const wxString& name, |
332 | | wxPathFormat format = wxPATH_NATIVE) const = 0; |
333 | | |
334 | 0 | void SetConv(wxMBConv& conv) { m_pConv = &conv; } |
335 | | wxMBConv& GetConv() const |
336 | 0 | { if (m_pConv) return *m_pConv; else return wxConvLocal; } |
337 | | |
338 | | static const wxArchiveClassFactory *Find(const wxString& protocol, |
339 | | wxStreamProtocolType type |
340 | | = wxSTREAM_PROTOCOL); |
341 | | |
342 | | static const wxArchiveClassFactory *GetFirst(); |
343 | 0 | const wxArchiveClassFactory *GetNext() const { return m_next; } |
344 | | |
345 | 2 | void PushFront() { Remove(); m_next = sm_first; sm_first = this; } |
346 | | void Remove(); |
347 | | |
348 | | protected: |
349 | | // old compilers don't support covarient returns, so 'Do' methods are |
350 | | // used to simulate them |
351 | | virtual wxArchiveEntry *DoNewEntry() const = 0; |
352 | | virtual wxArchiveInputStream *DoNewStream(wxInputStream& stream) const = 0; |
353 | | virtual wxArchiveOutputStream *DoNewStream(wxOutputStream& stream) const = 0; |
354 | | virtual wxArchiveInputStream *DoNewStream(wxInputStream *stream) const = 0; |
355 | | virtual wxArchiveOutputStream *DoNewStream(wxOutputStream *stream) const = 0; |
356 | | |
357 | 2 | wxArchiveClassFactory() : m_pConv(nullptr), m_next(this) { } |
358 | | wxArchiveClassFactory& operator=(const wxArchiveClassFactory& WXUNUSED(f)) |
359 | 0 | { return *this; } |
360 | | |
361 | | private: |
362 | | wxMBConv *m_pConv; |
363 | | static wxArchiveClassFactory *sm_first; |
364 | | wxArchiveClassFactory *m_next; |
365 | | |
366 | | wxDECLARE_ABSTRACT_CLASS(wxArchiveClassFactory); |
367 | | }; |
368 | | |
369 | | #endif // wxUSE_STREAMS && wxUSE_ARCHIVE_STREAMS |
370 | | |
371 | | #endif // _WX_ARCHIVE_H__ |