zipstrm.cpp
来自「A*算法 A*算法 A*算法 A*算法A*算法A*算法」· C++ 代码 · 共 2,276 行 · 第 1/5 页
CPP
2,276 行
m_inflate->avail_in = 0;
m_pos = 0;
m_lasterror = wxSTREAM_NO_ERROR;
m_parent_i_stream = &stream;
if (inflateReset(m_inflate) != Z_OK) {
wxLogError(_("can't re-initialize zlib inflate stream"));
m_lasterror = wxSTREAM_READ_ERROR;
return false;
}
return true;
}
/////////////////////////////////////////////////////////////////////////////
// Class to hold wxZipEntry's Extra and LocalExtra fields
class wxZipMemory
{
public:
wxZipMemory() : m_data(NULL), m_size(0), m_capacity(0), m_ref(1) { }
wxZipMemory *AddRef() { m_ref++; return this; }
void Release() { if (--m_ref == 0) delete this; }
char *GetData() const { return m_data; }
size_t GetSize() const { return m_size; }
size_t GetCapacity() const { return m_capacity; }
wxZipMemory *Unique(size_t size);
private:
~wxZipMemory() { delete [] m_data; }
char *m_data;
size_t m_size;
size_t m_capacity;
int m_ref;
};
wxZipMemory *wxZipMemory::Unique(size_t size)
{
wxZipMemory *zm;
if (m_ref > 1) {
--m_ref;
zm = new wxZipMemory;
} else {
zm = this;
}
if (zm->m_capacity < size) {
delete [] zm->m_data;
zm->m_data = new char[size];
zm->m_capacity = size;
}
zm->m_size = size;
return zm;
}
static inline wxZipMemory *AddRef(wxZipMemory *zm)
{
if (zm)
zm->AddRef();
return zm;
}
static inline void Release(wxZipMemory *zm)
{
if (zm)
zm->Release();
}
static void Copy(wxZipMemory*& dest, wxZipMemory *src)
{
Release(dest);
dest = AddRef(src);
}
static void Unique(wxZipMemory*& zm, size_t size)
{
if (!zm && size)
zm = new wxZipMemory;
if (zm)
zm = zm->Unique(size);
}
/////////////////////////////////////////////////////////////////////////////
// Collection of weak references to entries
WX_DECLARE_HASH_MAP(long, wxZipEntry*, wxIntegerHash,
wxIntegerEqual, wx__OffsetZipEntryMap);
class wxZipWeakLinks
{
public:
wxZipWeakLinks() : m_ref(1) { }
void Release(const wxZipInputStream* WXUNUSED(x))
{ if (--m_ref == 0) delete this; }
void Release(wxFileOffset key)
{ RemoveEntry(key); if (--m_ref == 0) delete this; }
wxZipWeakLinks *AddEntry(wxZipEntry *entry, wxFileOffset key);
void RemoveEntry(wxFileOffset key)
{ m_entries.erase(wx_truncate_cast(key_type, key)); }
wxZipEntry *GetEntry(wxFileOffset key) const;
bool IsEmpty() const { return m_entries.empty(); }
private:
typedef wx__OffsetZipEntryMap::key_type key_type;
~wxZipWeakLinks() { wxASSERT(IsEmpty()); }
int m_ref;
wx__OffsetZipEntryMap m_entries;
};
wxZipWeakLinks *wxZipWeakLinks::AddEntry(wxZipEntry *entry, wxFileOffset key)
{
m_entries[wx_truncate_cast(key_type, key)] = entry;
m_ref++;
return this;
}
wxZipEntry *wxZipWeakLinks::GetEntry(wxFileOffset key) const
{
wx__OffsetZipEntryMap::const_iterator it =
m_entries.find(wx_truncate_cast(key_type, key));
return it != m_entries.end() ? it->second : NULL;
}
/////////////////////////////////////////////////////////////////////////////
// ZipEntry
wxZipEntry::wxZipEntry(
const wxString& name /*=wxEmptyString*/,
const wxDateTime& dt /*=wxDateTime::Now()*/,
wxFileOffset size /*=wxInvalidOffset*/)
:
m_SystemMadeBy(wxZIP_SYSTEM_MSDOS),
m_VersionMadeBy(wxMAJOR_VERSION * 10 + wxMINOR_VERSION),
m_VersionNeeded(VERSION_NEEDED_TO_EXTRACT),
m_Flags(0),
m_Method(wxZIP_METHOD_DEFAULT),
m_DateTime(dt),
m_Crc(0),
m_CompressedSize(wxInvalidOffset),
m_Size(size),
m_Key(wxInvalidOffset),
m_Offset(wxInvalidOffset),
m_DiskStart(0),
m_InternalAttributes(0),
m_ExternalAttributes(0),
m_Extra(NULL),
m_LocalExtra(NULL),
m_zipnotifier(NULL),
m_backlink(NULL)
{
if (!name.empty())
SetName(name);
}
wxZipEntry::~wxZipEntry()
{
if (m_backlink)
m_backlink->Release(m_Key);
Release(m_Extra);
Release(m_LocalExtra);
}
wxZipEntry::wxZipEntry(const wxZipEntry& e)
: wxArchiveEntry(e),
m_SystemMadeBy(e.m_SystemMadeBy),
m_VersionMadeBy(e.m_VersionMadeBy),
m_VersionNeeded(e.m_VersionNeeded),
m_Flags(e.m_Flags),
m_Method(e.m_Method),
m_DateTime(e.m_DateTime),
m_Crc(e.m_Crc),
m_CompressedSize(e.m_CompressedSize),
m_Size(e.m_Size),
m_Name(e.m_Name),
m_Key(e.m_Key),
m_Offset(e.m_Offset),
m_Comment(e.m_Comment),
m_DiskStart(e.m_DiskStart),
m_InternalAttributes(e.m_InternalAttributes),
m_ExternalAttributes(e.m_ExternalAttributes),
m_Extra(AddRef(e.m_Extra)),
m_LocalExtra(AddRef(e.m_LocalExtra)),
m_zipnotifier(NULL),
m_backlink(NULL)
{
}
wxZipEntry& wxZipEntry::operator=(const wxZipEntry& e)
{
if (&e != this) {
m_SystemMadeBy = e.m_SystemMadeBy;
m_VersionMadeBy = e.m_VersionMadeBy;
m_VersionNeeded = e.m_VersionNeeded;
m_Flags = e.m_Flags;
m_Method = e.m_Method;
m_DateTime = e.m_DateTime;
m_Crc = e.m_Crc;
m_CompressedSize = e.m_CompressedSize;
m_Size = e.m_Size;
m_Name = e.m_Name;
m_Key = e.m_Key;
m_Offset = e.m_Offset;
m_Comment = e.m_Comment;
m_DiskStart = e.m_DiskStart;
m_InternalAttributes = e.m_InternalAttributes;
m_ExternalAttributes = e.m_ExternalAttributes;
Copy(m_Extra, e.m_Extra);
Copy(m_LocalExtra, e.m_LocalExtra);
m_zipnotifier = NULL;
if (m_backlink) {
m_backlink->Release(m_Key);
m_backlink = NULL;
}
}
return *this;
}
wxString wxZipEntry::GetName(wxPathFormat format /*=wxPATH_NATIVE*/) const
{
bool isDir = IsDir() && !m_Name.empty();
// optimisations for common (and easy) cases
switch (wxFileName::GetFormat(format)) {
case wxPATH_DOS:
{
wxString name(isDir ? m_Name + _T("\\") : m_Name);
for (size_t i = name.length() - 1; i > 0; --i)
if (name[i] == _T('/'))
name[i] = _T('\\');
return name;
}
case wxPATH_UNIX:
return isDir ? m_Name + _T("/") : m_Name;
default:
;
}
wxFileName fn;
if (isDir)
fn.AssignDir(m_Name, wxPATH_UNIX);
else
fn.Assign(m_Name, wxPATH_UNIX);
return fn.GetFullPath(format);
}
// Static - Internally tars and zips use forward slashes for the path
// separator, absolute paths aren't allowed, and directory names have a
// trailing slash. This function converts a path into this internal format,
// but without a trailing slash for a directory.
//
wxString wxZipEntry::GetInternalName(const wxString& name,
wxPathFormat format /*=wxPATH_NATIVE*/,
bool *pIsDir /*=NULL*/)
{
wxString internal;
if (wxFileName::GetFormat(format) != wxPATH_UNIX)
internal = wxFileName(name, format).GetFullPath(wxPATH_UNIX);
else
internal = name;
bool isDir = !internal.empty() && internal.Last() == '/';
if (pIsDir)
*pIsDir = isDir;
if (isDir)
internal.erase(internal.length() - 1);
while (!internal.empty() && *internal.begin() == '/')
internal.erase(0, 1);
while (!internal.empty() && internal.compare(0, 2, _T("./")) == 0)
internal.erase(0, 2);
if (internal == _T(".") || internal == _T(".."))
internal = wxEmptyString;
return internal;
}
void wxZipEntry::SetSystemMadeBy(int system)
{
int mode = GetMode();
bool wasUnix = IsMadeByUnix();
m_SystemMadeBy = (wxUint8)system;
if (!wasUnix && IsMadeByUnix()) {
SetIsDir(IsDir());
SetMode(mode);
} else if (wasUnix && !IsMadeByUnix()) {
m_ExternalAttributes &= 0xffff;
}
}
void wxZipEntry::SetIsDir(bool isDir /*=true*/)
{
if (isDir)
m_ExternalAttributes |= wxZIP_A_SUBDIR;
else
m_ExternalAttributes &= ~wxZIP_A_SUBDIR;
if (IsMadeByUnix()) {
m_ExternalAttributes &= ~wxZIP_S_IFMT;
if (isDir)
m_ExternalAttributes |= wxZIP_S_IFDIR;
else
m_ExternalAttributes |= wxZIP_S_IFREG;
}
}
// Return unix style permission bits
//
int wxZipEntry::GetMode() const
{
// return unix permissions if present
if (IsMadeByUnix())
return (m_ExternalAttributes >> 16) & 0777;
// otherwise synthesize from the dos attribs
int mode = 0644;
if (m_ExternalAttributes & wxZIP_A_RDONLY)
mode &= ~0200;
if (m_ExternalAttributes & wxZIP_A_SUBDIR)
mode |= 0111;
return mode;
}
// Set unix permissions
//
void wxZipEntry::SetMode(int mode)
{
// Set dos attrib bits to be compatible
if (mode & 0222)
m_ExternalAttributes &= ~wxZIP_A_RDONLY;
else
m_ExternalAttributes |= wxZIP_A_RDONLY;
// set the actual unix permission bits if the system type allows
if (IsMadeByUnix()) {
m_ExternalAttributes &= ~(0777L << 16);
m_ExternalAttributes |= (mode & 0777L) << 16;
}
}
const char *wxZipEntry::GetExtra() const
{
return m_Extra ? m_Extra->GetData() : NULL;
}
size_t wxZipEntry::GetExtraLen() const
{
return m_Extra ? m_Extra->GetSize() : 0;
}
void wxZipEntry::SetExtra(const char *extra, size_t len)
{
Unique(m_Extra, len);
if (len)
memcpy(m_Extra->GetData(), extra, len);
}
const char *wxZipEntry::GetLocalExtra() const
{
return m_LocalExtra ? m_LocalExtra->GetData() : NULL;
}
size_t wxZipEntry::GetLocalExtraLen() const
{
return m_LocalExtra ? m_LocalExtra->GetSize() : 0;
}
void wxZipEntry::SetLocalExtra(const char *extra, size_t len)
{
Unique(m_LocalExtra, len);
if (len)
memcpy(m_LocalExtra->GetData(), extra, len);
}
void wxZipEntry::SetNotifier(wxZipNotifier& notifier)
{
wxArchiveEntry::UnsetNotifier();
m_zipnotifier = ¬ifier;
m_zipnotifier->OnEntryUpdated(*this);
}
void wxZipEntry::Notify()
{
if (m_zipnotifier)
m_zipnotifier->OnEntryUpdated(*this);
else if (GetNotifier())
GetNotifier()->OnEntryUpdated(*this);
}
void wxZipEntry::UnsetNotifier()
{
wxArchiveEntry::UnsetNotifier();
m_zipnotifier = NULL;
}
size_t wxZipEntry::ReadLocal(wxInputStream& stream, wxMBConv& conv)
{
wxUint16 nameLen, extraLen;
wxUint32 compressedSize, size, crc;
wxDataInputStream ds(stream);
ds >> m_VersionNeeded >> m_Flags >> m_Method;
SetDateTime(wxDateTime().SetFromDOS(ds.Read32()));
ds >> crc >> compressedSize >> size >> nameLen >> extraLen;
bool sumsValid = (m_Flags & wxZIP_SUMS_FOLLOW) == 0;
if (sumsValid || crc)
m_Crc = crc;
if ((sumsValid || compressedSize) || m_Method == wxZIP_METHOD_STORE)
m_CompressedSize = compressedSize;
if ((sumsValid || size) || m_Method == wxZIP_METHOD_STORE)
m_Size = size;
SetName(ReadString(stream, nameLen, conv), wxPATH_UNIX);
if (extraLen || GetLocalExtraLen()) {
Unique(m_LocalExtra, extraLen);
if (extraLen)
stream.Read(m_LocalExtra->GetData(), extraLen);
}
return LOCAL_SIZE + nameLen + extraLen;
}
size_t wxZipEntry::WriteLocal(wxOutputStream& stream, wxMBConv& conv) const
{
wxString unixName = GetName(wxPATH_UNIX);
const wxWX2MBbuf name_buf = conv.cWX2MB(unixName);
const char *name = name_buf;
if (!name) name = "";
wxUint16 nameLen = wx_truncate_cast(wxUint16, strlen(name));
wxDataOutputStream ds(stream);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?