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