mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-09-17 15:21:16 +00:00
279 lines
7.1 KiB
C++
279 lines
7.1 KiB
C++
/////////////////////////////////////////////////////////////////////////////
|
|
// Name: src/common/fs_mem.cpp
|
|
// Purpose: in-memory file system
|
|
// Author: Vaclav Slavik
|
|
// Copyright: (c) 2000 Vaclav Slavik
|
|
// Licence: wxWindows licence
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "wx/wxprec.h"
|
|
|
|
#ifdef __BORLANDC__
|
|
#pragma hdrstop
|
|
#endif
|
|
|
|
#if wxUSE_FILESYSTEM && wxUSE_STREAMS
|
|
|
|
#include "wx/fs_mem.h"
|
|
|
|
#ifndef WX_PRECOMP
|
|
#include "wx/intl.h"
|
|
#include "wx/log.h"
|
|
#include "wx/wxcrtvararg.h"
|
|
#if wxUSE_GUI
|
|
#include "wx/image.h"
|
|
#endif // wxUSE_GUI
|
|
#endif
|
|
|
|
#include "wx/mstream.h"
|
|
|
|
// represents a file entry in wxMemoryFS
|
|
class wxMemoryFSFile
|
|
{
|
|
public:
|
|
wxMemoryFSFile(const void *data, size_t len, const wxString& mime)
|
|
{
|
|
m_Data = new char[len];
|
|
memcpy(m_Data, data, len);
|
|
m_Len = len;
|
|
m_MimeType = mime;
|
|
InitTime();
|
|
}
|
|
|
|
wxMemoryFSFile(const wxMemoryOutputStream& stream, const wxString& mime)
|
|
{
|
|
m_Len = stream.GetSize();
|
|
m_Data = new char[m_Len];
|
|
stream.CopyTo(m_Data, m_Len);
|
|
m_MimeType = mime;
|
|
InitTime();
|
|
}
|
|
|
|
virtual ~wxMemoryFSFile()
|
|
{
|
|
delete[] m_Data;
|
|
}
|
|
|
|
char *m_Data;
|
|
size_t m_Len;
|
|
wxString m_MimeType;
|
|
#if wxUSE_DATETIME
|
|
wxDateTime m_Time;
|
|
#endif // wxUSE_DATETIME
|
|
|
|
private:
|
|
void InitTime()
|
|
{
|
|
#if wxUSE_DATETIME
|
|
m_Time = wxDateTime::Now();
|
|
#endif // wxUSE_DATETIME
|
|
}
|
|
|
|
wxDECLARE_NO_COPY_CLASS(wxMemoryFSFile);
|
|
};
|
|
|
|
#if wxUSE_BASE
|
|
|
|
|
|
//--------------------------------------------------------------------------------
|
|
// wxMemoryFSHandler
|
|
//--------------------------------------------------------------------------------
|
|
|
|
|
|
wxMemoryFSHash wxMemoryFSHandlerBase::m_Hash;
|
|
|
|
|
|
wxMemoryFSHandlerBase::wxMemoryFSHandlerBase() : wxFileSystemHandler()
|
|
{
|
|
}
|
|
|
|
wxMemoryFSHandlerBase::~wxMemoryFSHandlerBase()
|
|
{
|
|
// as only one copy of FS handler is supposed to exist, we may silently
|
|
// delete static data here. (There is no way how to remove FS handler from
|
|
// wxFileSystem other than releasing _all_ handlers.)
|
|
WX_CLEAR_HASH_MAP(wxMemoryFSHash, m_Hash);
|
|
}
|
|
|
|
bool wxMemoryFSHandlerBase::CanOpen(const wxString& location)
|
|
{
|
|
return GetProtocol(location) == "memory";
|
|
}
|
|
|
|
wxFSFile * wxMemoryFSHandlerBase::OpenFile(wxFileSystem& WXUNUSED(fs),
|
|
const wxString& location)
|
|
{
|
|
wxMemoryFSHash::const_iterator i = m_Hash.find(GetRightLocation(location));
|
|
if ( i == m_Hash.end() )
|
|
return NULL;
|
|
|
|
const wxMemoryFSFile * const obj = i->second;
|
|
|
|
return new wxFSFile
|
|
(
|
|
new wxMemoryInputStream(obj->m_Data, obj->m_Len),
|
|
location,
|
|
obj->m_MimeType,
|
|
GetAnchor(location)
|
|
#if wxUSE_DATETIME
|
|
, obj->m_Time
|
|
#endif // wxUSE_DATETIME
|
|
);
|
|
}
|
|
|
|
wxString wxMemoryFSHandlerBase::FindFirst(const wxString& url, int flags)
|
|
{
|
|
if ( (flags & wxDIR) && !(flags & wxFILE) )
|
|
{
|
|
// we only store files, not directories, so we don't risk finding
|
|
// anything
|
|
return wxString();
|
|
}
|
|
|
|
const wxString spec = GetRightLocation(url);
|
|
if ( spec.find_first_of("?*") == wxString::npos )
|
|
{
|
|
// simple case: there are no wildcard characters so we can return
|
|
// either 0 or 1 results and we can find the potential match quickly
|
|
return m_Hash.count(spec) ? url : wxString();
|
|
}
|
|
//else: deal with wildcards in FindNext()
|
|
|
|
m_findArgument = spec;
|
|
m_findIter = m_Hash.begin();
|
|
|
|
return FindNext();
|
|
}
|
|
|
|
wxString wxMemoryFSHandlerBase::FindNext()
|
|
{
|
|
// m_findArgument is used to indicate that search is in progress, we reset
|
|
// it to empty string after iterating over all elements
|
|
while ( !m_findArgument.empty() )
|
|
{
|
|
// test for the match before (possibly) clearing m_findArgument below
|
|
const bool found = m_findIter->first.Matches(m_findArgument);
|
|
|
|
// advance m_findIter first as we need to do it anyhow, whether it
|
|
// matches or not
|
|
const wxMemoryFSHash::const_iterator current = m_findIter;
|
|
|
|
if ( ++m_findIter == m_Hash.end() )
|
|
m_findArgument.clear();
|
|
|
|
if ( found )
|
|
return "memory:" + current->first;
|
|
}
|
|
|
|
return wxString();
|
|
}
|
|
|
|
bool wxMemoryFSHandlerBase::CheckDoesntExist(const wxString& filename)
|
|
{
|
|
if ( m_Hash.count(filename) )
|
|
{
|
|
wxLogError(_("Memory VFS already contains file '%s'!"), filename);
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
/*static*/
|
|
void wxMemoryFSHandlerBase::AddFileWithMimeType(const wxString& filename,
|
|
const wxString& textdata,
|
|
const wxString& mimetype)
|
|
{
|
|
const wxCharBuffer buf(textdata.To8BitData());
|
|
|
|
AddFileWithMimeType(filename, buf.data(), buf.length(), mimetype);
|
|
}
|
|
|
|
|
|
/*static*/
|
|
void wxMemoryFSHandlerBase::AddFileWithMimeType(const wxString& filename,
|
|
const void *binarydata, size_t size,
|
|
const wxString& mimetype)
|
|
{
|
|
if ( !CheckDoesntExist(filename) )
|
|
return;
|
|
|
|
m_Hash[filename] = new wxMemoryFSFile(binarydata, size, mimetype);
|
|
}
|
|
|
|
/*static*/
|
|
void wxMemoryFSHandlerBase::AddFile(const wxString& filename,
|
|
const wxString& textdata)
|
|
{
|
|
AddFileWithMimeType(filename, textdata, wxEmptyString);
|
|
}
|
|
|
|
|
|
/*static*/
|
|
void wxMemoryFSHandlerBase::AddFile(const wxString& filename,
|
|
const void *binarydata, size_t size)
|
|
{
|
|
AddFileWithMimeType(filename, binarydata, size, wxEmptyString);
|
|
}
|
|
|
|
|
|
|
|
/*static*/ void wxMemoryFSHandlerBase::RemoveFile(const wxString& filename)
|
|
{
|
|
wxMemoryFSHash::iterator i = m_Hash.find(filename);
|
|
if ( i == m_Hash.end() )
|
|
{
|
|
wxLogError(_("Trying to remove file '%s' from memory VFS, "
|
|
"but it is not loaded!"),
|
|
filename);
|
|
return;
|
|
}
|
|
|
|
delete i->second;
|
|
m_Hash.erase(i);
|
|
}
|
|
|
|
#endif // wxUSE_BASE
|
|
|
|
#if wxUSE_GUI
|
|
|
|
#if wxUSE_IMAGE
|
|
/*static*/ void
|
|
wxMemoryFSHandler::AddFile(const wxString& filename,
|
|
const wxImage& image,
|
|
wxBitmapType type)
|
|
{
|
|
if ( !CheckDoesntExist(filename) )
|
|
return;
|
|
|
|
wxMemoryOutputStream mems;
|
|
if ( image.IsOk() && image.SaveFile(mems, type) )
|
|
{
|
|
m_Hash[filename] = new wxMemoryFSFile
|
|
(
|
|
mems,
|
|
wxImage::FindHandler(type)->GetMimeType()
|
|
);
|
|
}
|
|
else
|
|
{
|
|
wxLogError(_("Failed to store image '%s' to memory VFS!"), filename);
|
|
}
|
|
}
|
|
|
|
/*static*/ void
|
|
wxMemoryFSHandler::AddFile(const wxString& filename,
|
|
const wxBitmap& bitmap,
|
|
wxBitmapType type)
|
|
{
|
|
wxImage img = bitmap.ConvertToImage();
|
|
AddFile(filename, img, type);
|
|
}
|
|
|
|
#endif // wxUSE_IMAGE
|
|
|
|
#endif // wxUSE_GUI
|
|
|
|
|
|
#endif // wxUSE_FILESYSTEM && wxUSE_FS_ZIP
|