1///////////////////////////////////////////////////////////////////////////// 2// Name: src/common/fs_mem.cpp 3// Purpose: in-memory file system 4// Author: Vaclav Slavik 5// RCS-ID: $Id: fs_mem.cpp 46522 2007-06-18 18:37:40Z VS $ 6// Copyright: (c) 2000 Vaclav Slavik 7// Licence: wxWindows licence 8///////////////////////////////////////////////////////////////////////////// 9 10#include "wx/wxprec.h" 11 12#ifdef __BORLANDC__ 13 #pragma hdrstop 14#endif 15 16#if wxUSE_FILESYSTEM && wxUSE_STREAMS 17 18#include "wx/fs_mem.h" 19 20#ifndef WXPRECOMP 21 #include "wx/intl.h" 22 #include "wx/log.h" 23 #include "wx/hash.h" 24 #if wxUSE_GUI 25 #include "wx/bitmap.h" 26 #include "wx/image.h" 27 #endif // wxUSE_GUI 28#endif 29 30#include "wx/mstream.h" 31 32class MemFSHashObj : public wxObject 33{ 34 public: 35 36 MemFSHashObj(const void *data, size_t len, const wxString& mime) 37 { 38 m_Data = new char[len]; 39 memcpy(m_Data, data, len); 40 m_Len = len; 41 m_MimeType = mime; 42 InitTime(); 43 } 44 45 MemFSHashObj(const wxMemoryOutputStream& stream, const wxString& mime) 46 { 47 m_Len = stream.GetSize(); 48 m_Data = new char[m_Len]; 49 stream.CopyTo(m_Data, m_Len); 50 m_MimeType = mime; 51 InitTime(); 52 } 53 54 virtual ~MemFSHashObj() 55 { 56 delete[] m_Data; 57 } 58 59 char *m_Data; 60 size_t m_Len; 61 wxString m_MimeType; 62#if wxUSE_DATETIME 63 wxDateTime m_Time; 64#endif // wxUSE_DATETIME 65 66 DECLARE_NO_COPY_CLASS(MemFSHashObj) 67 68 private: 69 void InitTime() 70 { 71#if wxUSE_DATETIME 72 m_Time = wxDateTime::Now(); 73#endif // wxUSE_DATETIME 74 } 75}; 76 77#if wxUSE_BASE 78 79 80//-------------------------------------------------------------------------------- 81// wxMemoryFSHandler 82//-------------------------------------------------------------------------------- 83 84 85wxHashTable *wxMemoryFSHandlerBase::m_Hash = NULL; 86 87 88wxMemoryFSHandlerBase::wxMemoryFSHandlerBase() : wxFileSystemHandler() 89{ 90} 91 92 93 94wxMemoryFSHandlerBase::~wxMemoryFSHandlerBase() 95{ 96 // as only one copy of FS handler is supposed to exist, we may silently 97 // delete static data here. (There is no way how to remove FS handler from 98 // wxFileSystem other than releasing _all_ handlers.) 99 100 if (m_Hash) 101 { 102 WX_CLEAR_HASH_TABLE(*m_Hash); 103 delete m_Hash; 104 m_Hash = NULL; 105 } 106} 107 108 109 110bool wxMemoryFSHandlerBase::CanOpen(const wxString& location) 111{ 112 wxString p = GetProtocol(location); 113 return (p == wxT("memory")); 114} 115 116 117 118 119wxFSFile* wxMemoryFSHandlerBase::OpenFile(wxFileSystem& WXUNUSED(fs), const wxString& location) 120{ 121 if (m_Hash) 122 { 123 MemFSHashObj *obj = (MemFSHashObj*) m_Hash -> Get(GetRightLocation(location)); 124 if (obj == NULL) 125 { 126 return NULL; 127 } 128 else 129 { 130 wxString mime = obj->m_MimeType; 131 if ( mime.empty() ) 132 mime = GetMimeTypeFromExt(location); 133 return new wxFSFile 134 ( 135 new wxMemoryInputStream(obj -> m_Data, obj -> m_Len), 136 location, 137 mime, 138 GetAnchor(location) 139#if wxUSE_DATETIME 140 , obj -> m_Time 141#endif // wxUSE_DATETIME 142 ); 143 } 144 } 145 else return NULL; 146} 147 148 149 150wxString wxMemoryFSHandlerBase::FindFirst(const wxString& WXUNUSED(spec), 151 int WXUNUSED(flags)) 152{ 153 wxFAIL_MSG(wxT("wxMemoryFSHandlerBase::FindFirst not implemented")); 154 155 return wxEmptyString; 156} 157 158 159 160wxString wxMemoryFSHandlerBase::FindNext() 161{ 162 wxFAIL_MSG(wxT("wxMemoryFSHandlerBase::FindNext not implemented")); 163 164 return wxEmptyString; 165} 166 167 168bool wxMemoryFSHandlerBase::CheckHash(const wxString& filename) 169{ 170 if (m_Hash == NULL) 171 { 172 m_Hash = new wxHashTable(wxKEY_STRING); 173 } 174 175 if (m_Hash -> Get(filename) != NULL) 176 { 177 wxString s; 178 s.Printf(_("Memory VFS already contains file '%s'!"), filename.c_str()); 179 wxLogError(s); 180 return false; 181 } 182 else 183 return true; 184} 185 186 187/*static*/ 188void wxMemoryFSHandlerBase::AddFileWithMimeType(const wxString& filename, 189 const wxString& textdata, 190 const wxString& mimetype) 191{ 192 AddFileWithMimeType(filename, 193 (const void*) textdata.mb_str(), textdata.length(), 194 mimetype); 195} 196 197 198/*static*/ 199void wxMemoryFSHandlerBase::AddFileWithMimeType(const wxString& filename, 200 const void *binarydata, size_t size, 201 const wxString& mimetype) 202{ 203 if (!CheckHash(filename)) return; 204 m_Hash -> Put(filename, new MemFSHashObj(binarydata, size, mimetype)); 205} 206 207/*static*/ 208void wxMemoryFSHandlerBase::AddFile(const wxString& filename, 209 const wxString& textdata) 210{ 211 AddFileWithMimeType(filename, textdata, wxEmptyString); 212} 213 214 215/*static*/ 216void wxMemoryFSHandlerBase::AddFile(const wxString& filename, 217 const void *binarydata, size_t size) 218{ 219 AddFileWithMimeType(filename, binarydata, size, wxEmptyString); 220} 221 222 223 224/*static*/ void wxMemoryFSHandlerBase::RemoveFile(const wxString& filename) 225{ 226 if (m_Hash == NULL || 227 m_Hash -> Get(filename) == NULL) 228 { 229 wxString s; 230 s.Printf(_("Trying to remove file '%s' from memory VFS, but it is not loaded!"), filename.c_str()); 231 wxLogError(s); 232 } 233 234 else 235 delete m_Hash -> Delete(filename); 236} 237 238#endif // wxUSE_BASE 239 240#if wxUSE_GUI 241 242#if wxUSE_IMAGE 243/*static*/ void 244wxMemoryFSHandler::AddFile(const wxString& filename, 245 const wxImage& image, 246 long type) 247{ 248 if (!CheckHash(filename)) return; 249 250 wxMemoryOutputStream mems; 251 if (image.Ok() && image.SaveFile(mems, (int)type)) 252 { 253 m_Hash->Put 254 ( 255 filename, 256 new MemFSHashObj 257 ( 258 mems, 259 wxImage::FindHandler(type)->GetMimeType() 260 ) 261 ); 262 } 263 else 264 { 265 wxString s; 266 s.Printf(_("Failed to store image '%s' to memory VFS!"), filename.c_str()); 267 wxPrintf(wxT("'%s'\n"), s.c_str()); 268 wxLogError(s); 269 } 270} 271 272/*static*/ void 273wxMemoryFSHandler::AddFile(const wxString& filename, 274 const wxBitmap& bitmap, 275 long type) 276{ 277#if !defined(__WXMSW__) || wxUSE_WXDIB 278 wxImage img = bitmap.ConvertToImage(); 279 AddFile(filename, img, type); 280#endif 281} 282 283#endif // wxUSE_IMAGE 284 285#endif // wxUSE_GUI 286 287 288#endif // wxUSE_FILESYSTEM && wxUSE_FS_ZIP 289