]> git.saurik.com Git - wxWidgets.git/blob - src/common/fs_mem.cpp
fix for always terminating intermediate UniChar String for 4 bytes wchar_t
[wxWidgets.git] / src / common / fs_mem.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: 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
10 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) && !defined(__EMX__)
11 // Some older compilers (such as EMX) cannot handle
12 // #pragma interface/implementation correctly, iff
13 // #pragma implementation is used in _two_ translation
14 // units (as created by e.g. event.cpp compiled for
15 // libwx_base and event.cpp compiled for libwx_gui_core).
16 // So we must not use those pragmas for those compilers in
17 // such files.
18 #pragma implementation "fs_mem.h"
19 #endif
20
21 #include "wx/wxprec.h"
22
23 #ifdef __BORLANDC__
24 #pragma hdrstop
25 #endif
26
27 #if wxUSE_FILESYSTEM && wxUSE_STREAMS
28
29 #include "wx/fs_mem.h"
30
31 #if wxUSE_GUI
32 #include "wx/image.h"
33 #include "wx/bitmap.h"
34 #endif // wxUSE_GUI
35
36 #ifndef WXPRECOMP
37 #include "wx/intl.h"
38 #include "wx/log.h"
39 #include "wx/hash.h"
40 #endif
41
42 #include "wx/mstream.h"
43
44 class MemFSHashObj : public wxObject
45 {
46 public:
47
48 MemFSHashObj(const void *data, size_t len)
49 {
50 m_Data = new char[len];
51 memcpy(m_Data, data, len);
52 m_Len = len;
53 InitTime();
54 }
55
56 MemFSHashObj(wxMemoryOutputStream& stream)
57 {
58 m_Len = stream.GetSize();
59 m_Data = new char[m_Len];
60 stream.CopyTo(m_Data, m_Len);
61 InitTime();
62 }
63
64 ~MemFSHashObj()
65 {
66 delete[] m_Data;
67 }
68
69 char *m_Data;
70 size_t m_Len;
71 #if wxUSE_DATETIME
72 wxDateTime m_Time;
73 #endif // wxUSE_DATETIME
74
75 DECLARE_NO_COPY_CLASS(MemFSHashObj)
76
77 private:
78 void InitTime()
79 {
80 #if wxUSE_DATETIME
81 m_Time = wxDateTime::Now();
82 #endif // wxUSE_DATETIME
83 }
84 };
85
86 #if wxUSE_BASE
87
88
89 //--------------------------------------------------------------------------------
90 // wxMemoryFSHandler
91 //--------------------------------------------------------------------------------
92
93
94 wxHashTable *wxMemoryFSHandlerBase::m_Hash = NULL;
95
96
97 wxMemoryFSHandlerBase::wxMemoryFSHandlerBase() : wxFileSystemHandler()
98 {
99 }
100
101
102
103 wxMemoryFSHandlerBase::~wxMemoryFSHandlerBase()
104 {
105 // as only one copy of FS handler is supposed to exist, we may silently
106 // delete static data here. (There is no way how to remove FS handler from
107 // wxFileSystem other than releasing _all_ handlers.)
108
109 if (m_Hash)
110 {
111 WX_CLEAR_HASH_TABLE(*m_Hash);
112 delete m_Hash;
113 m_Hash = NULL;
114 }
115 }
116
117
118
119 bool wxMemoryFSHandlerBase::CanOpen(const wxString& location)
120 {
121 wxString p = GetProtocol(location);
122 return (p == wxT("memory"));
123 }
124
125
126
127
128 wxFSFile* wxMemoryFSHandlerBase::OpenFile(wxFileSystem& WXUNUSED(fs), const wxString& location)
129 {
130 if (m_Hash)
131 {
132 MemFSHashObj *obj = (MemFSHashObj*) m_Hash -> Get(GetRightLocation(location));
133 if (obj == NULL) return NULL;
134 else return new wxFSFile(new wxMemoryInputStream(obj -> m_Data, obj -> m_Len),
135 location,
136 GetMimeTypeFromExt(location),
137 GetAnchor(location)
138 #if wxUSE_DATETIME
139 , obj -> m_Time
140 #endif // wxUSE_DATETIME
141 );
142 }
143 else return NULL;
144 }
145
146
147
148 wxString wxMemoryFSHandlerBase::FindFirst(const wxString& WXUNUSED(spec),
149 int WXUNUSED(flags))
150 {
151 wxFAIL_MSG(wxT("wxMemoryFSHandlerBase::FindFirst not implemented"));
152
153 return wxEmptyString;
154 }
155
156
157
158 wxString wxMemoryFSHandlerBase::FindNext()
159 {
160 wxFAIL_MSG(wxT("wxMemoryFSHandlerBase::FindNext not implemented"));
161
162 return wxEmptyString;
163 }
164
165
166 bool wxMemoryFSHandlerBase::CheckHash(const wxString& filename)
167 {
168 if (m_Hash == NULL)
169 {
170 m_Hash = new wxHashTable(wxKEY_STRING);
171 }
172
173 if (m_Hash -> Get(filename) != NULL)
174 {
175 wxString s;
176 s.Printf(_("Memory VFS already contains file '%s'!"), filename.c_str());
177 wxLogError(s);
178 return FALSE;
179 }
180 else
181 return TRUE;
182 }
183
184
185 /*static*/ void wxMemoryFSHandlerBase::AddFile(const wxString& filename, const wxString& textdata)
186 {
187 AddFile(filename, (const void*) textdata.mb_str(), textdata.Length());
188 }
189
190
191 /*static*/ void wxMemoryFSHandlerBase::AddFile(const wxString& filename, const void *binarydata, size_t size)
192 {
193 if (!CheckHash(filename)) return;
194 m_Hash -> Put(filename, new MemFSHashObj(binarydata, size));
195 }
196
197
198
199 /*static*/ void wxMemoryFSHandlerBase::RemoveFile(const wxString& filename)
200 {
201 if (m_Hash == NULL ||
202 m_Hash -> Get(filename) == NULL)
203 {
204 wxString s;
205 s.Printf(_("Trying to remove file '%s' from memory VFS, but it is not loaded!"), filename.c_str());
206 wxLogError(s);
207 }
208
209 else
210 delete m_Hash -> Delete(filename);
211 }
212
213 #endif // wxUSE_BASE
214
215 #if wxUSE_GUI
216
217 #if wxUSE_IMAGE
218 /*static*/ void
219 wxMemoryFSHandler::AddFile(const wxString& filename, wxImage& image, long type)
220 {
221 if (!CheckHash(filename)) return;
222
223 wxMemoryOutputStream mems;
224 if (image.Ok() && image.SaveFile(mems, (int)type))
225 m_Hash -> Put(filename, new MemFSHashObj(mems));
226 else
227 {
228 wxString s;
229 s.Printf(_("Failed to store image '%s' to memory VFS!"), filename.c_str());
230 wxPrintf(wxT("'%s'\n"), s.c_str());
231 wxLogError(s);
232 }
233 }
234
235 /*static*/ void wxMemoryFSHandler::AddFile(const wxString& filename, const wxBitmap& bitmap, long type)
236 {
237 wxImage img = bitmap.ConvertToImage();
238 AddFile(filename, img, type);
239 }
240
241 #endif // wxUSE_IMAGE
242
243 #endif // wxUSE_GUI
244
245
246 #endif // wxUSE_FILESYSTEM && wxUSE_FS_ZIP
247