/[pcsx2_0.9.7]/trunk/3rdparty/wxWidgets/src/common/fs_arc.cpp
ViewVC logotype

Annotation of /trunk/3rdparty/wxWidgets/src/common/fs_arc.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 31 - (hide annotations) (download)
Tue Sep 7 03:24:11 2010 UTC (10 years, 4 months ago) by william
File size: 14139 byte(s)
committing r3113 initial commit again...
1 william 31 /////////////////////////////////////////////////////////////////////////////
2     // Name: fs_arc.cpp
3     // Purpose: wxArchive file system
4     // Author: Vaclav Slavik, Mike Wetherell
5     // Copyright: (c) 1999 Vaclav Slavik, (c) 2006 Mike Wetherell
6     // CVS-ID: $Id: fs_arc.cpp 51495 2008-02-01 16:44:56Z MW $
7     // Licence: wxWindows licence
8     /////////////////////////////////////////////////////////////////////////////
9    
10     #include "wx/wxprec.h"
11    
12     #ifdef __BORLANDC__
13     #pragma hdrstop
14     #endif
15    
16     #if wxUSE_FS_ARCHIVE
17    
18     #include "wx/fs_arc.h"
19    
20     #ifndef WXPRECOMP
21     #include "wx/intl.h"
22     #include "wx/log.h"
23     #endif
24    
25     #if WXWIN_COMPATIBILITY_2_6 && wxUSE_ZIPSTREAM
26     #include "wx/zipstrm.h"
27     #else
28     #include "wx/archive.h"
29     #endif
30    
31     #include "wx/private/fileback.h"
32    
33     //---------------------------------------------------------------------------
34     // wxArchiveFSCacheDataImpl
35     //
36     // Holds the catalog of an archive file, and if it is being read from a
37     // non-seekable stream, a copy of its backing file.
38     //
39     // This class is actually the reference counted implementation for the
40     // wxArchiveFSCacheData class below. It was done that way to allow sharing
41     // between instances of wxFileSystem, though that's a feature not used in this
42     // version.
43     //---------------------------------------------------------------------------
44    
45     WX_DECLARE_STRING_HASH_MAP(wxArchiveEntry*, wxArchiveFSEntryHash);
46    
47     struct wxArchiveFSEntry
48     {
49     wxArchiveEntry *entry;
50     wxArchiveFSEntry *next;
51     };
52    
53     class wxArchiveFSCacheDataImpl
54     {
55     public:
56     wxArchiveFSCacheDataImpl(const wxArchiveClassFactory& factory,
57     const wxBackingFile& backer);
58     wxArchiveFSCacheDataImpl(const wxArchiveClassFactory& factory,
59     wxInputStream *stream);
60    
61     ~wxArchiveFSCacheDataImpl();
62    
63     void Release() { if (--m_refcount == 0) delete this; }
64     wxArchiveFSCacheDataImpl *AddRef() { m_refcount++; return this; }
65    
66     wxArchiveEntry *Get(const wxString& name);
67     wxInputStream *NewStream() const;
68    
69     wxArchiveFSEntry *GetNext(wxArchiveFSEntry *fse);
70    
71     private:
72     wxArchiveFSEntry *AddToCache(wxArchiveEntry *entry);
73     void CloseStreams();
74    
75     int m_refcount;
76    
77     wxArchiveFSEntryHash m_hash;
78     wxArchiveFSEntry *m_begin;
79     wxArchiveFSEntry **m_endptr;
80    
81     wxBackingFile m_backer;
82     wxInputStream *m_stream;
83     wxArchiveInputStream *m_archive;
84     };
85    
86     wxArchiveFSCacheDataImpl::wxArchiveFSCacheDataImpl(
87     const wxArchiveClassFactory& factory,
88     const wxBackingFile& backer)
89     : m_refcount(1),
90     m_begin(NULL),
91     m_endptr(&m_begin),
92     m_backer(backer),
93     m_stream(new wxBackedInputStream(backer)),
94     m_archive(factory.NewStream(*m_stream))
95     {
96     }
97    
98     wxArchiveFSCacheDataImpl::wxArchiveFSCacheDataImpl(
99     const wxArchiveClassFactory& factory,
100     wxInputStream *stream)
101     : m_refcount(1),
102     m_begin(NULL),
103     m_endptr(&m_begin),
104     m_stream(stream),
105     m_archive(factory.NewStream(*m_stream))
106     {
107     }
108    
109     wxArchiveFSCacheDataImpl::~wxArchiveFSCacheDataImpl()
110     {
111     WX_CLEAR_HASH_MAP(wxArchiveFSEntryHash, m_hash);
112    
113     wxArchiveFSEntry *entry = m_begin;
114    
115     while (entry)
116     {
117     wxArchiveFSEntry *next = entry->next;
118     delete entry;
119     entry = next;
120     }
121    
122     CloseStreams();
123     }
124    
125     wxArchiveFSEntry *wxArchiveFSCacheDataImpl::AddToCache(wxArchiveEntry *entry)
126     {
127     m_hash[entry->GetName(wxPATH_UNIX)] = entry;
128     wxArchiveFSEntry *fse = new wxArchiveFSEntry;
129     *m_endptr = fse;
130     (*m_endptr)->entry = entry;
131     (*m_endptr)->next = NULL;
132     m_endptr = &(*m_endptr)->next;
133     return fse;
134     }
135    
136     void wxArchiveFSCacheDataImpl::CloseStreams()
137     {
138     delete m_archive;
139     m_archive = NULL;
140     delete m_stream;
141     m_stream = NULL;
142     }
143    
144     wxArchiveEntry *wxArchiveFSCacheDataImpl::Get(const wxString& name)
145     {
146     wxArchiveFSEntryHash::iterator it = m_hash.find(name);
147    
148     if (it != m_hash.end())
149     return it->second;
150    
151     if (!m_archive)
152     return NULL;
153    
154     wxArchiveEntry *entry;
155    
156     while ((entry = m_archive->GetNextEntry()) != NULL)
157     {
158     AddToCache(entry);
159    
160     if (entry->GetName(wxPATH_UNIX) == name)
161     return entry;
162     }
163    
164     CloseStreams();
165    
166     return NULL;
167     }
168    
169     wxInputStream* wxArchiveFSCacheDataImpl::NewStream() const
170     {
171     if (m_backer)
172     return new wxBackedInputStream(m_backer);
173     else
174     return NULL;
175     }
176    
177     wxArchiveFSEntry *wxArchiveFSCacheDataImpl::GetNext(wxArchiveFSEntry *fse)
178     {
179     wxArchiveFSEntry *next = fse ? fse->next : m_begin;
180    
181     if (!next && m_archive)
182     {
183     wxArchiveEntry *entry = m_archive->GetNextEntry();
184    
185     if (entry)
186     next = AddToCache(entry);
187     else
188     CloseStreams();
189     }
190    
191     return next;
192     }
193    
194     //---------------------------------------------------------------------------
195     // wxArchiveFSCacheData
196     //
197     // This is the inteface for wxArchiveFSCacheDataImpl above. Holds the catalog
198     // of an archive file, and if it is being read from a non-seekable stream, a
199     // copy of its backing file.
200     //---------------------------------------------------------------------------
201    
202     class wxArchiveFSCacheData
203     {
204     public:
205     wxArchiveFSCacheData() : m_impl(NULL) { }
206     wxArchiveFSCacheData(const wxArchiveClassFactory& factory,
207     const wxBackingFile& backer);
208     wxArchiveFSCacheData(const wxArchiveClassFactory& factory,
209     wxInputStream *stream);
210    
211     wxArchiveFSCacheData(const wxArchiveFSCacheData& data);
212     wxArchiveFSCacheData& operator=(const wxArchiveFSCacheData& data);
213    
214     ~wxArchiveFSCacheData() { if (m_impl) m_impl->Release(); }
215    
216     wxArchiveEntry *Get(const wxString& name) { return m_impl->Get(name); }
217     wxInputStream *NewStream() const { return m_impl->NewStream(); }
218     wxArchiveFSEntry *GetNext(wxArchiveFSEntry *fse)
219     { return m_impl->GetNext(fse); }
220    
221     private:
222     wxArchiveFSCacheDataImpl *m_impl;
223     };
224    
225     wxArchiveFSCacheData::wxArchiveFSCacheData(
226     const wxArchiveClassFactory& factory,
227     const wxBackingFile& backer)
228     : m_impl(new wxArchiveFSCacheDataImpl(factory, backer))
229     {
230     }
231    
232     wxArchiveFSCacheData::wxArchiveFSCacheData(
233     const wxArchiveClassFactory& factory,
234     wxInputStream *stream)
235     : m_impl(new wxArchiveFSCacheDataImpl(factory, stream))
236     {
237     }
238    
239     wxArchiveFSCacheData::wxArchiveFSCacheData(const wxArchiveFSCacheData& data)
240     : m_impl(data.m_impl ? data.m_impl->AddRef() : NULL)
241     {
242     }
243    
244     wxArchiveFSCacheData& wxArchiveFSCacheData::operator=(
245     const wxArchiveFSCacheData& data)
246     {
247     if (data.m_impl != m_impl)
248     {
249     if (m_impl)
250     m_impl->Release();
251    
252     m_impl = data.m_impl;
253    
254     if (m_impl)
255     m_impl->AddRef();
256     }
257    
258     return *this;
259     }
260    
261     //---------------------------------------------------------------------------
262     // wxArchiveFSCache
263     //
264     // wxArchiveFSCacheData caches a single archive, and this class holds a
265     // collection of them to cache all the archives accessed by this instance
266     // of wxFileSystem.
267     //---------------------------------------------------------------------------
268    
269     WX_DECLARE_STRING_HASH_MAP(wxArchiveFSCacheData, wxArchiveFSCacheDataHash);
270    
271     class wxArchiveFSCache
272     {
273     public:
274     wxArchiveFSCache() { }
275     ~wxArchiveFSCache() { }
276    
277     wxArchiveFSCacheData* Add(const wxString& name,
278     const wxArchiveClassFactory& factory,
279     wxInputStream *stream);
280    
281     wxArchiveFSCacheData *Get(const wxString& name);
282    
283     private:
284     wxArchiveFSCacheDataHash m_hash;
285     };
286    
287     wxArchiveFSCacheData* wxArchiveFSCache::Add(
288     const wxString& name,
289     const wxArchiveClassFactory& factory,
290     wxInputStream *stream)
291     {
292     wxArchiveFSCacheData& data = m_hash[name];
293    
294     if (stream->IsSeekable())
295     data = wxArchiveFSCacheData(factory, stream);
296     else
297     data = wxArchiveFSCacheData(factory, wxBackingFile(stream));
298    
299     return &data;
300     }
301    
302     wxArchiveFSCacheData *wxArchiveFSCache::Get(const wxString& name)
303     {
304     wxArchiveFSCacheDataHash::iterator it;
305    
306     if ((it = m_hash.find(name)) != m_hash.end())
307     return &it->second;
308    
309     return NULL;
310     }
311    
312     //----------------------------------------------------------------------------
313     // wxArchiveFSHandler
314     //----------------------------------------------------------------------------
315    
316     IMPLEMENT_DYNAMIC_CLASS(wxArchiveFSHandler, wxFileSystemHandler)
317    
318     wxArchiveFSHandler::wxArchiveFSHandler()
319     : wxFileSystemHandler()
320     {
321     m_Archive = NULL;
322     m_FindEntry = NULL;
323     m_ZipFile = m_Pattern = m_BaseDir = wxEmptyString;
324     m_AllowDirs = m_AllowFiles = true;
325     m_DirsFound = NULL;
326     m_cache = NULL;
327     }
328    
329     wxArchiveFSHandler::~wxArchiveFSHandler()
330     {
331     Cleanup();
332     delete m_cache;
333     }
334    
335     void wxArchiveFSHandler::Cleanup()
336     {
337     wxDELETE(m_DirsFound);
338     }
339    
340     bool wxArchiveFSHandler::CanOpen(const wxString& location)
341     {
342     wxString p = GetProtocol(location);
343     return wxArchiveClassFactory::Find(p) != NULL;
344     }
345    
346     wxFSFile* wxArchiveFSHandler::OpenFile(
347     wxFileSystem& WXUNUSED(fs),
348     const wxString& location)
349     {
350     wxString right = GetRightLocation(location);
351     wxString left = GetLeftLocation(location);
352     wxString protocol = GetProtocol(location);
353     wxString key = left + wxT("#") + protocol + wxT(":");
354    
355     if (right.Contains(wxT("./")))
356     {
357     if (right.GetChar(0) != wxT('/')) right = wxT('/') + right;
358     wxFileName rightPart(right, wxPATH_UNIX);
359     rightPart.Normalize(wxPATH_NORM_DOTS, wxT("/"), wxPATH_UNIX);
360     right = rightPart.GetFullPath(wxPATH_UNIX);
361     }
362    
363     if (right.GetChar(0) == wxT('/')) right = right.Mid(1);
364    
365     if (!m_cache)
366     m_cache = new wxArchiveFSCache;
367    
368     const wxArchiveClassFactory *factory;
369     factory = wxArchiveClassFactory::Find(protocol);
370     if (!factory)
371     return NULL;
372    
373     wxArchiveFSCacheData *cached = m_cache->Get(key);
374     if (!cached)
375     {
376     wxFSFile *leftFile = m_fs.OpenFile(left);
377     if (!leftFile)
378     return NULL;
379     cached = m_cache->Add(key, *factory, leftFile->DetachStream());
380     delete leftFile;
381     }
382    
383     wxArchiveEntry *entry = cached->Get(right);
384     if (!entry)
385     return NULL;
386    
387     wxInputStream *leftStream = cached->NewStream();
388     if (!leftStream)
389     {
390     wxFSFile *leftFile = m_fs.OpenFile(left);
391     if (!leftFile)
392     return NULL;
393     leftStream = leftFile->DetachStream();
394     delete leftFile;
395     }
396    
397     wxArchiveInputStream *s = factory->NewStream(leftStream);
398     s->OpenEntry(*entry);
399    
400     if (s && s->IsOk())
401     {
402     #if WXWIN_COMPATIBILITY_2_6 && wxUSE_ZIPSTREAM
403     if (factory->IsKindOf(CLASSINFO(wxZipClassFactory)))
404     ((wxZipInputStream*)s)->m_allowSeeking = true;
405     #endif // WXWIN_COMPATIBILITY_2_6
406    
407     return new wxFSFile(s,
408     key + right,
409     GetMimeTypeFromExt(location),
410     GetAnchor(location)
411     #if wxUSE_DATETIME
412     , entry->GetDateTime()
413     #endif // wxUSE_DATETIME
414     );
415     }
416    
417     delete s;
418     return NULL;
419     }
420    
421     wxString wxArchiveFSHandler::FindFirst(const wxString& spec, int flags)
422     {
423     wxString right = GetRightLocation(spec);
424     wxString left = GetLeftLocation(spec);
425     wxString protocol = GetProtocol(spec);
426     wxString key = left + wxT("#") + protocol + wxT(":");
427    
428     if (!right.empty() && right.Last() == wxT('/')) right.RemoveLast();
429    
430     if (!m_cache)
431     m_cache = new wxArchiveFSCache;
432    
433     const wxArchiveClassFactory *factory;
434     factory = wxArchiveClassFactory::Find(protocol);
435     if (!factory)
436     return wxEmptyString;
437    
438     m_Archive = m_cache->Get(key);
439     if (!m_Archive)
440     {
441     wxFSFile *leftFile = m_fs.OpenFile(left);
442     if (!leftFile)
443     return wxEmptyString;
444     m_Archive = m_cache->Add(key, *factory, leftFile->DetachStream());
445     delete leftFile;
446     }
447    
448     m_FindEntry = NULL;
449    
450     switch (flags)
451     {
452     case wxFILE:
453     m_AllowDirs = false, m_AllowFiles = true; break;
454     case wxDIR:
455     m_AllowDirs = true, m_AllowFiles = false; break;
456     default:
457     m_AllowDirs = m_AllowFiles = true; break;
458     }
459    
460     m_ZipFile = key;
461    
462     m_Pattern = right.AfterLast(wxT('/'));
463     m_BaseDir = right.BeforeLast(wxT('/'));
464     if (m_BaseDir.StartsWith(wxT("/")))
465     m_BaseDir = m_BaseDir.Mid(1);
466    
467     if (m_Archive)
468     {
469     if (m_AllowDirs)
470     {
471     delete m_DirsFound;
472     m_DirsFound = new wxArchiveFilenameHashMap();
473     if (right.empty()) // allow "/" to match the archive root
474     return spec;
475     }
476     return DoFind();
477     }
478     return wxEmptyString;
479     }
480    
481     wxString wxArchiveFSHandler::FindNext()
482     {
483     if (!m_Archive) return wxEmptyString;
484     return DoFind();
485     }
486    
487     wxString wxArchiveFSHandler::DoFind()
488     {
489     wxString namestr, dir, filename;
490     wxString match = wxEmptyString;
491    
492     while (match == wxEmptyString)
493     {
494     m_FindEntry = m_Archive->GetNext(m_FindEntry);
495    
496     if (!m_FindEntry)
497     {
498     m_Archive = NULL;
499     m_FindEntry = NULL;
500     break;
501     }
502     namestr = m_FindEntry->entry->GetName(wxPATH_UNIX);
503    
504     if (m_AllowDirs)
505     {
506     dir = namestr.BeforeLast(wxT('/'));
507     while (!dir.empty())
508     {
509     if( m_DirsFound->find(dir) == m_DirsFound->end() )
510     {
511     (*m_DirsFound)[dir] = 1;
512     filename = dir.AfterLast(wxT('/'));
513     dir = dir.BeforeLast(wxT('/'));
514     if (!filename.empty() && m_BaseDir == dir &&
515     wxMatchWild(m_Pattern, filename, false))
516     match = m_ZipFile + dir + wxT("/") + filename;
517     }
518     else
519     break; // already tranversed
520     }
521     }
522    
523     filename = namestr.AfterLast(wxT('/'));
524     dir = namestr.BeforeLast(wxT('/'));
525     if (m_AllowFiles && !filename.empty() && m_BaseDir == dir &&
526     wxMatchWild(m_Pattern, filename, false))
527     match = m_ZipFile + namestr;
528     }
529    
530     return match;
531     }
532    
533     #endif // wxUSE_FS_ARCHIVE

  ViewVC Help
Powered by ViewVC 1.1.22