X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/f6bcfd974ef26faf6f91a62cac09827e09463fd1..64b1cea09aac1077469090dc2dac9a139a509833:/src/common/fs_mem.cpp diff --git a/src/common/fs_mem.cpp b/src/common/fs_mem.cpp index d1e3b30179..2e9927590d 100644 --- a/src/common/fs_mem.cpp +++ b/src/common/fs_mem.cpp @@ -1,212 +1,280 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: fs_mem.cpp +// Name: src/common/fs_mem.cpp // Purpose: in-memory file system // Author: Vaclav Slavik +// RCS-ID: $Id$ // Copyright: (c) 2000 Vaclav Slavik -// Licence: wxWindows Licence +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// - -#ifdef __GNUG__ -#pragma implementation -#endif - #include "wx/wxprec.h" -#ifdef __BORDLANDC__ -#pragma hdrstop +#ifdef __BORLANDC__ + #pragma hdrstop #endif #if wxUSE_FILESYSTEM && wxUSE_STREAMS -#ifndef WXPRECOMP -#include "wx/wx.h" +#include "wx/fs_mem.h" + +#ifndef WX_PRECOMP + #include "wx/intl.h" + #include "wx/log.h" + #include "wx/wxcrtvararg.h" + #if wxUSE_GUI + #include "wx/image.h" + #endif // wxUSE_GUI #endif -#include "wx/filesys.h" -#include "wx/fs_mem.h" #include "wx/mstream.h" - -class MemFSHashObj : public wxObject +// represents a file entry in wxMemoryFS +class wxMemoryFSFile { - public: - - MemFSHashObj(const void *data, size_t len) - { - m_Data = new char[len]; - memcpy(m_Data, data, len); - m_Len = len; - m_Time = wxDateTime::Now(); - } - - MemFSHashObj(wxMemoryOutputStream& stream) - { - m_Len = stream.GetSize(); - m_Data = new char[m_Len]; - stream.CopyTo(m_Data, m_Len); - m_Time = wxDateTime::Now(); - } - - ~MemFSHashObj() - { - delete[] m_Data; - } - - char *m_Data; - size_t m_Len; - wxDateTime m_Time; +public: + wxMemoryFSFile(const void *data, size_t len, const wxString& mime) + { + m_Data = new char[len]; + memcpy(m_Data, data, len); + m_Len = len; + m_MimeType = mime; + InitTime(); + } + + wxMemoryFSFile(const wxMemoryOutputStream& stream, const wxString& mime) + { + m_Len = stream.GetSize(); + m_Data = new char[m_Len]; + stream.CopyTo(m_Data, m_Len); + m_MimeType = mime; + InitTime(); + } + + virtual ~wxMemoryFSFile() + { + delete[] m_Data; + } + + char *m_Data; + size_t m_Len; + wxString m_MimeType; +#if wxUSE_DATETIME + wxDateTime m_Time; +#endif // wxUSE_DATETIME + +private: + void InitTime() + { +#if wxUSE_DATETIME + m_Time = wxDateTime::Now(); +#endif // wxUSE_DATETIME + } + + DECLARE_NO_COPY_CLASS(wxMemoryFSFile) }; +#if wxUSE_BASE + //-------------------------------------------------------------------------------- // wxMemoryFSHandler //-------------------------------------------------------------------------------- -wxHashTable *wxMemoryFSHandler::m_Hash = NULL; +wxMemoryFSHash wxMemoryFSHandlerBase::m_Hash; -wxMemoryFSHandler::wxMemoryFSHandler() : wxFileSystemHandler() +wxMemoryFSHandlerBase::wxMemoryFSHandlerBase() : wxFileSystemHandler() { - m_Hash = NULL; } - - -wxMemoryFSHandler::~wxMemoryFSHandler() +wxMemoryFSHandlerBase::~wxMemoryFSHandlerBase() { // as only one copy of FS handler is supposed to exist, we may silently // delete static data here. (There is no way how to remove FS handler from // wxFileSystem other than releasing _all_ handlers.) - - if (m_Hash) delete m_Hash; - m_Hash = NULL; + WX_CLEAR_HASH_MAP(wxMemoryFSHash, m_Hash); } - - -bool wxMemoryFSHandler::CanOpen(const wxString& location) +bool wxMemoryFSHandlerBase::CanOpen(const wxString& location) { - wxString p = GetProtocol(location); - return (p == wxT("memory")); + return GetProtocol(location) == "memory"; } +wxFSFile * wxMemoryFSHandlerBase::OpenFile(wxFileSystem& WXUNUSED(fs), + const wxString& location) +{ + wxMemoryFSHash::const_iterator i = m_Hash.find(GetRightLocation(location)); + if ( i == m_Hash.end() ) + return NULL; + + const wxMemoryFSFile * const obj = i->second; + + return new wxFSFile + ( + new wxMemoryInputStream(obj->m_Data, obj->m_Len), + location, + obj->m_MimeType, + GetAnchor(location) +#if wxUSE_DATETIME + , obj->m_Time +#endif // wxUSE_DATETIME + ); +} - - -wxFSFile* wxMemoryFSHandler::OpenFile(wxFileSystem& WXUNUSED(fs), const wxString& location) +wxString wxMemoryFSHandlerBase::FindFirst(const wxString& url, int flags) { - if (m_Hash) + if ( (flags & wxDIR) && !(flags & wxFILE) ) { - MemFSHashObj *obj = (MemFSHashObj*) m_Hash -> Get(GetRightLocation(location)); - if (obj == NULL) return NULL; - else return new wxFSFile(new wxMemoryInputStream(obj -> m_Data, obj -> m_Len), - location, - GetMimeTypeFromExt(location), - GetAnchor(location), - obj -> m_Time); + // we only store files, not directories, so we don't risk finding + // anything + return wxString(); } - else return NULL; -} - + const wxString spec = GetRightLocation(url); + if ( spec.find_first_of("?*") == wxString::npos ) + { + // simple case: there are no wildcard characters so we can return + // either 0 or 1 results and we can find the potential match quickly + return m_Hash.count(spec) ? url : wxString(); + } + //else: deal with wildcards in FindNext() -wxString wxMemoryFSHandler::FindFirst(const wxString& WXUNUSED(spec), - int WXUNUSED(flags)) -{ - wxFAIL_MSG(wxT("wxMemoryFSHandler::FindFirst not implemented")); + m_findArgument = spec; + m_findIter = m_Hash.begin(); - return wxEmptyString; + return FindNext(); } +wxString wxMemoryFSHandlerBase::FindNext() +{ + // m_findArgument is used to indicate that search is in progress, we reset + // it to empty string after iterating over all elements + while ( !m_findArgument.empty() ) + { + // test for the match before (possibly) clearing m_findArgument below + const bool found = m_findIter->first.Matches(m_findArgument); + // advance m_findIter first as we need to do it anyhow, whether it + // matches or not + const wxMemoryFSHash::const_iterator current = m_findIter; -wxString wxMemoryFSHandler::FindNext() -{ - wxFAIL_MSG(wxT("wxMemoryFSHandler::FindNext not implemented")); + if ( ++m_findIter == m_Hash.end() ) + m_findArgument.clear(); - return wxEmptyString; -} + if ( found ) + return "memory:" + current->first; + } + return wxString(); +} -bool wxMemoryFSHandler::CheckHash(const wxString& filename) +bool wxMemoryFSHandlerBase::CheckDoesntExist(const wxString& filename) { - if (m_Hash == NULL) + if ( m_Hash.count(filename) ) { - m_Hash = new wxHashTable(wxKEY_STRING); - m_Hash -> DeleteContents(TRUE); + wxLogError(_("Memory VFS already contains file '%s'!"), filename); + return false; } - - if (m_Hash -> Get(filename) != NULL) - { - wxString s; - s.Printf(_("Memory VFS already contains file '%s'!"), filename.c_str()); - wxLogError(s); - return FALSE; - } - else - return TRUE; + + return true; } +/*static*/ +void wxMemoryFSHandlerBase::AddFileWithMimeType(const wxString& filename, + const wxString& textdata, + const wxString& mimetype) +{ + AddFileWithMimeType(filename, + (const void*) textdata.mb_str(), textdata.length(), + mimetype); +} -#if wxUSE_GUI -/*static*/ void wxMemoryFSHandler::AddFile(const wxString& filename, wxImage& image, long type) +/*static*/ +void wxMemoryFSHandlerBase::AddFileWithMimeType(const wxString& filename, + const void *binarydata, size_t size, + const wxString& mimetype) { - if (!CheckHash(filename)) return; + if ( !CheckDoesntExist(filename) ) + return; - - wxMemoryOutputStream mems; - if (image.Ok() && image.SaveFile(mems, (int)type)) - m_Hash -> Put(filename, new MemFSHashObj(mems)); - else - { - wxString s; - s.Printf(_("Failed to store image '%s' to memory VFS!"), filename.c_str()); - wxPrintf(wxT("'%s'\n"), s.c_str()); - wxLogError(s); - } + m_Hash[filename] = new wxMemoryFSFile(binarydata, size, mimetype); } - -/*static*/ void wxMemoryFSHandler::AddFile(const wxString& filename, const wxBitmap& bitmap, long type) +/*static*/ +void wxMemoryFSHandlerBase::AddFile(const wxString& filename, + const wxString& textdata) { - wxImage img(bitmap); - AddFile(filename, img, type); + AddFileWithMimeType(filename, textdata, wxEmptyString); } -#endif -/*static*/ void wxMemoryFSHandler::AddFile(const wxString& filename, const wxString& textdata) +/*static*/ +void wxMemoryFSHandlerBase::AddFile(const wxString& filename, + const void *binarydata, size_t size) { - AddFile(filename, (const void*) textdata.mb_str(), textdata.Length()); + AddFileWithMimeType(filename, binarydata, size, wxEmptyString); } -/*static*/ void wxMemoryFSHandler::AddFile(const wxString& filename, const void *binarydata, size_t size) + +/*static*/ void wxMemoryFSHandlerBase::RemoveFile(const wxString& filename) { - if (!CheckHash(filename)) return; - m_Hash -> Put(filename, new MemFSHashObj(binarydata, size)); + wxMemoryFSHash::iterator i = m_Hash.find(filename); + if ( i == m_Hash.end() ) + { + wxLogError(_("Trying to remove file '%s' from memory VFS, " + "but it is not loaded!"), + filename); + return; + } + + delete i->second; + m_Hash.erase(i); } +#endif // wxUSE_BASE +#if wxUSE_GUI -/*static*/ void wxMemoryFSHandler::RemoveFile(const wxString& filename) +#if wxUSE_IMAGE +/*static*/ void +wxMemoryFSHandler::AddFile(const wxString& filename, + const wxImage& image, + wxBitmapType type) { - if (m_Hash == NULL || - m_Hash -> Get(filename) == NULL) + if ( !CheckDoesntExist(filename) ) + return; + + wxMemoryOutputStream mems; + if ( image.Ok() && image.SaveFile(mems, type) ) { - wxString s; - s.Printf(_("Trying to remove file '%s' from memory VFS, but it is not loaded!"), filename.c_str()); - wxLogError(s); + m_Hash[filename] = new wxMemoryFSFile + ( + mems, + wxImage::FindHandler(type)->GetMimeType() + ); } - else - delete m_Hash -> Delete(filename); + { + wxLogError(_("Failed to store image '%s' to memory VFS!"), filename); + } +} + +/*static*/ void +wxMemoryFSHandler::AddFile(const wxString& filename, + const wxBitmap& bitmap, + wxBitmapType type) +{ + wxImage img = bitmap.ConvertToImage(); + AddFile(filename, img, type); } +#endif // wxUSE_IMAGE + +#endif // wxUSE_GUI #endif // wxUSE_FILESYSTEM && wxUSE_FS_ZIP