1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/fs_mem.cpp
3 // Purpose: in-memory file system
4 // Author: Vaclav Slavik
6 // Copyright: (c) 2000 Vaclav Slavik
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
10 #include "wx/wxprec.h"
16 #if wxUSE_FILESYSTEM && wxUSE_STREAMS
18 #include "wx/fs_mem.h"
23 #include "wx/wxcrtvararg.h"
29 #include "wx/mstream.h"
31 // represents a file entry in wxMemoryFS
35 wxMemoryFSFile(const void *data
, size_t len
, const wxString
& mime
)
37 m_Data
= new char[len
];
38 memcpy(m_Data
, data
, len
);
44 wxMemoryFSFile(const wxMemoryOutputStream
& stream
, const wxString
& mime
)
46 m_Len
= stream
.GetSize();
47 m_Data
= new char[m_Len
];
48 stream
.CopyTo(m_Data
, m_Len
);
53 virtual ~wxMemoryFSFile()
63 #endif // wxUSE_DATETIME
69 m_Time
= wxDateTime::Now();
70 #endif // wxUSE_DATETIME
73 wxDECLARE_NO_COPY_CLASS(wxMemoryFSFile
);
79 //--------------------------------------------------------------------------------
81 //--------------------------------------------------------------------------------
84 wxMemoryFSHash
wxMemoryFSHandlerBase::m_Hash
;
87 wxMemoryFSHandlerBase::wxMemoryFSHandlerBase() : wxFileSystemHandler()
91 wxMemoryFSHandlerBase::~wxMemoryFSHandlerBase()
93 // as only one copy of FS handler is supposed to exist, we may silently
94 // delete static data here. (There is no way how to remove FS handler from
95 // wxFileSystem other than releasing _all_ handlers.)
96 WX_CLEAR_HASH_MAP(wxMemoryFSHash
, m_Hash
);
99 bool wxMemoryFSHandlerBase::CanOpen(const wxString
& location
)
101 return GetProtocol(location
) == "memory";
104 wxFSFile
* wxMemoryFSHandlerBase::OpenFile(wxFileSystem
& WXUNUSED(fs
),
105 const wxString
& location
)
107 wxMemoryFSHash::const_iterator i
= m_Hash
.find(GetRightLocation(location
));
108 if ( i
== m_Hash
.end() )
111 const wxMemoryFSFile
* const obj
= i
->second
;
115 new wxMemoryInputStream(obj
->m_Data
, obj
->m_Len
),
121 #endif // wxUSE_DATETIME
125 wxString
wxMemoryFSHandlerBase::FindFirst(const wxString
& url
, int flags
)
127 if ( (flags
& wxDIR
) && !(flags
& wxFILE
) )
129 // we only store files, not directories, so we don't risk finding
134 const wxString spec
= GetRightLocation(url
);
135 if ( spec
.find_first_of("?*") == wxString::npos
)
137 // simple case: there are no wildcard characters so we can return
138 // either 0 or 1 results and we can find the potential match quickly
139 return m_Hash
.count(spec
) ? url
: wxString();
141 //else: deal with wildcards in FindNext()
143 m_findArgument
= spec
;
144 m_findIter
= m_Hash
.begin();
149 wxString
wxMemoryFSHandlerBase::FindNext()
151 // m_findArgument is used to indicate that search is in progress, we reset
152 // it to empty string after iterating over all elements
153 while ( !m_findArgument
.empty() )
155 // test for the match before (possibly) clearing m_findArgument below
156 const bool found
= m_findIter
->first
.Matches(m_findArgument
);
158 // advance m_findIter first as we need to do it anyhow, whether it
160 const wxMemoryFSHash::const_iterator current
= m_findIter
;
162 if ( ++m_findIter
== m_Hash
.end() )
163 m_findArgument
.clear();
166 return "memory:" + current
->first
;
172 bool wxMemoryFSHandlerBase::CheckDoesntExist(const wxString
& filename
)
174 if ( m_Hash
.count(filename
) )
176 wxLogError(_("Memory VFS already contains file '%s'!"), filename
);
185 void wxMemoryFSHandlerBase::AddFileWithMimeType(const wxString
& filename
,
186 const wxString
& textdata
,
187 const wxString
& mimetype
)
190 const wxScopedCharBuffer
data(textdata
.To8BitData());
192 const wxString
& data
= textdata
;
195 AddFileWithMimeType(filename
,
196 static_cast<const char *>(data
), data
.length(),
202 void wxMemoryFSHandlerBase::AddFileWithMimeType(const wxString
& filename
,
203 const void *binarydata
, size_t size
,
204 const wxString
& mimetype
)
206 if ( !CheckDoesntExist(filename
) )
209 m_Hash
[filename
] = new wxMemoryFSFile(binarydata
, size
, mimetype
);
213 void wxMemoryFSHandlerBase::AddFile(const wxString
& filename
,
214 const wxString
& textdata
)
216 AddFileWithMimeType(filename
, textdata
, wxEmptyString
);
221 void wxMemoryFSHandlerBase::AddFile(const wxString
& filename
,
222 const void *binarydata
, size_t size
)
224 AddFileWithMimeType(filename
, binarydata
, size
, wxEmptyString
);
229 /*static*/ void wxMemoryFSHandlerBase::RemoveFile(const wxString
& filename
)
231 wxMemoryFSHash::iterator i
= m_Hash
.find(filename
);
232 if ( i
== m_Hash
.end() )
234 wxLogError(_("Trying to remove file '%s' from memory VFS, "
235 "but it is not loaded!"),
250 wxMemoryFSHandler::AddFile(const wxString
& filename
,
251 const wxImage
& image
,
254 if ( !CheckDoesntExist(filename
) )
257 wxMemoryOutputStream mems
;
258 if ( image
.Ok() && image
.SaveFile(mems
, type
) )
260 m_Hash
[filename
] = new wxMemoryFSFile
263 wxImage::FindHandler(type
)->GetMimeType()
268 wxLogError(_("Failed to store image '%s' to memory VFS!"), filename
);
273 wxMemoryFSHandler::AddFile(const wxString
& filename
,
274 const wxBitmap
& bitmap
,
277 wxImage img
= bitmap
.ConvertToImage();
278 AddFile(filename
, img
, type
);
281 #endif // wxUSE_IMAGE
286 #endif // wxUSE_FILESYSTEM && wxUSE_FS_ZIP