Hack compilation using the latest MinGW release.
[wxWidgets.git] / src / common / fs_mem.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/fs_mem.cpp
3 // Purpose: in-memory file system
4 // Author: Vaclav Slavik
5 // Copyright: (c) 2000 Vaclav Slavik
6 // Licence: wxWindows licence
7 /////////////////////////////////////////////////////////////////////////////
8
9 #include "wx/wxprec.h"
10
11 #ifdef __BORLANDC__
12 #pragma hdrstop
13 #endif
14
15 #if wxUSE_FILESYSTEM && wxUSE_STREAMS
16
17 #include "wx/fs_mem.h"
18
19 #ifndef WX_PRECOMP
20 #include "wx/intl.h"
21 #include "wx/log.h"
22 #include "wx/wxcrtvararg.h"
23 #if wxUSE_GUI
24 #include "wx/image.h"
25 #endif // wxUSE_GUI
26 #endif
27
28 #include "wx/mstream.h"
29
30 // represents a file entry in wxMemoryFS
31 class wxMemoryFSFile
32 {
33 public:
34 wxMemoryFSFile(const void *data, size_t len, const wxString& mime)
35 {
36 m_Data = new char[len];
37 memcpy(m_Data, data, len);
38 m_Len = len;
39 m_MimeType = mime;
40 InitTime();
41 }
42
43 wxMemoryFSFile(const wxMemoryOutputStream& stream, const wxString& mime)
44 {
45 m_Len = stream.GetSize();
46 m_Data = new char[m_Len];
47 stream.CopyTo(m_Data, m_Len);
48 m_MimeType = mime;
49 InitTime();
50 }
51
52 virtual ~wxMemoryFSFile()
53 {
54 delete[] m_Data;
55 }
56
57 char *m_Data;
58 size_t m_Len;
59 wxString m_MimeType;
60 #if wxUSE_DATETIME
61 wxDateTime m_Time;
62 #endif // wxUSE_DATETIME
63
64 private:
65 void InitTime()
66 {
67 #if wxUSE_DATETIME
68 m_Time = wxDateTime::Now();
69 #endif // wxUSE_DATETIME
70 }
71
72 wxDECLARE_NO_COPY_CLASS(wxMemoryFSFile);
73 };
74
75 #if wxUSE_BASE
76
77
78 //--------------------------------------------------------------------------------
79 // wxMemoryFSHandler
80 //--------------------------------------------------------------------------------
81
82
83 wxMemoryFSHash wxMemoryFSHandlerBase::m_Hash;
84
85
86 wxMemoryFSHandlerBase::wxMemoryFSHandlerBase() : wxFileSystemHandler()
87 {
88 }
89
90 wxMemoryFSHandlerBase::~wxMemoryFSHandlerBase()
91 {
92 // as only one copy of FS handler is supposed to exist, we may silently
93 // delete static data here. (There is no way how to remove FS handler from
94 // wxFileSystem other than releasing _all_ handlers.)
95 WX_CLEAR_HASH_MAP(wxMemoryFSHash, m_Hash);
96 }
97
98 bool wxMemoryFSHandlerBase::CanOpen(const wxString& location)
99 {
100 return GetProtocol(location) == "memory";
101 }
102
103 wxFSFile * wxMemoryFSHandlerBase::OpenFile(wxFileSystem& WXUNUSED(fs),
104 const wxString& location)
105 {
106 wxMemoryFSHash::const_iterator i = m_Hash.find(GetRightLocation(location));
107 if ( i == m_Hash.end() )
108 return NULL;
109
110 const wxMemoryFSFile * const obj = i->second;
111
112 return new wxFSFile
113 (
114 new wxMemoryInputStream(obj->m_Data, obj->m_Len),
115 location,
116 obj->m_MimeType,
117 GetAnchor(location)
118 #if wxUSE_DATETIME
119 , obj->m_Time
120 #endif // wxUSE_DATETIME
121 );
122 }
123
124 wxString wxMemoryFSHandlerBase::FindFirst(const wxString& url, int flags)
125 {
126 if ( (flags & wxDIR) && !(flags & wxFILE) )
127 {
128 // we only store files, not directories, so we don't risk finding
129 // anything
130 return wxString();
131 }
132
133 const wxString spec = GetRightLocation(url);
134 if ( spec.find_first_of("?*") == wxString::npos )
135 {
136 // simple case: there are no wildcard characters so we can return
137 // either 0 or 1 results and we can find the potential match quickly
138 return m_Hash.count(spec) ? url : wxString();
139 }
140 //else: deal with wildcards in FindNext()
141
142 m_findArgument = spec;
143 m_findIter = m_Hash.begin();
144
145 return FindNext();
146 }
147
148 wxString wxMemoryFSHandlerBase::FindNext()
149 {
150 // m_findArgument is used to indicate that search is in progress, we reset
151 // it to empty string after iterating over all elements
152 while ( !m_findArgument.empty() )
153 {
154 // test for the match before (possibly) clearing m_findArgument below
155 const bool found = m_findIter->first.Matches(m_findArgument);
156
157 // advance m_findIter first as we need to do it anyhow, whether it
158 // matches or not
159 const wxMemoryFSHash::const_iterator current = m_findIter;
160
161 if ( ++m_findIter == m_Hash.end() )
162 m_findArgument.clear();
163
164 if ( found )
165 return "memory:" + current->first;
166 }
167
168 return wxString();
169 }
170
171 bool wxMemoryFSHandlerBase::CheckDoesntExist(const wxString& filename)
172 {
173 if ( m_Hash.count(filename) )
174 {
175 wxLogError(_("Memory VFS already contains file '%s'!"), filename);
176 return false;
177 }
178
179 return true;
180 }
181
182
183 /*static*/
184 void wxMemoryFSHandlerBase::AddFileWithMimeType(const wxString& filename,
185 const wxString& textdata,
186 const wxString& mimetype)
187 {
188 const wxCharBuffer buf(textdata.To8BitData());
189
190 AddFileWithMimeType(filename, buf.data(), buf.length(), mimetype);
191 }
192
193
194 /*static*/
195 void wxMemoryFSHandlerBase::AddFileWithMimeType(const wxString& filename,
196 const void *binarydata, size_t size,
197 const wxString& mimetype)
198 {
199 if ( !CheckDoesntExist(filename) )
200 return;
201
202 m_Hash[filename] = new wxMemoryFSFile(binarydata, size, mimetype);
203 }
204
205 /*static*/
206 void wxMemoryFSHandlerBase::AddFile(const wxString& filename,
207 const wxString& textdata)
208 {
209 AddFileWithMimeType(filename, textdata, wxEmptyString);
210 }
211
212
213 /*static*/
214 void wxMemoryFSHandlerBase::AddFile(const wxString& filename,
215 const void *binarydata, size_t size)
216 {
217 AddFileWithMimeType(filename, binarydata, size, wxEmptyString);
218 }
219
220
221
222 /*static*/ void wxMemoryFSHandlerBase::RemoveFile(const wxString& filename)
223 {
224 wxMemoryFSHash::iterator i = m_Hash.find(filename);
225 if ( i == m_Hash.end() )
226 {
227 wxLogError(_("Trying to remove file '%s' from memory VFS, "
228 "but it is not loaded!"),
229 filename);
230 return;
231 }
232
233 delete i->second;
234 m_Hash.erase(i);
235 }
236
237 #endif // wxUSE_BASE
238
239 #if wxUSE_GUI
240
241 #if wxUSE_IMAGE
242 /*static*/ void
243 wxMemoryFSHandler::AddFile(const wxString& filename,
244 const wxImage& image,
245 wxBitmapType type)
246 {
247 if ( !CheckDoesntExist(filename) )
248 return;
249
250 wxMemoryOutputStream mems;
251 if ( image.IsOk() && image.SaveFile(mems, type) )
252 {
253 m_Hash[filename] = new wxMemoryFSFile
254 (
255 mems,
256 wxImage::FindHandler(type)->GetMimeType()
257 );
258 }
259 else
260 {
261 wxLogError(_("Failed to store image '%s' to memory VFS!"), filename);
262 }
263 }
264
265 /*static*/ void
266 wxMemoryFSHandler::AddFile(const wxString& filename,
267 const wxBitmap& bitmap,
268 wxBitmapType type)
269 {
270 wxImage img = bitmap.ConvertToImage();
271 AddFile(filename, img, type);
272 }
273
274 #endif // wxUSE_IMAGE
275
276 #endif // wxUSE_GUI
277
278
279 #endif // wxUSE_FILESYSTEM && wxUSE_FS_ZIP