📄 zip_archive.cpp
字号:
/* $Id: zip_archive.cpp,v 1.9 2003/08/04 12:45:27 mbn Exp $
**
** ClanLib Game SDK
** Copyright (C) 2003 The ClanLib Team
** For a total list of contributers see the file CREDITS.
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License as published by the Free Software Foundation; either
** version 2.1 of the License, or (at your option) any later version.
**
** This library is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
** Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public
** License along with this library; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "Core/precomp.h"
#include "API/Core/IOData/zip_archive.h"
#include "API/Core/IOData/inputsource_file.h"
#include "API/Core/IOData/inputsource_memory.h"
#include "API/Core/System/clanstring.h"
#include "zip_archive_generic.h"
#include "zip_file_header.h"
#include "zip_64_end_of_central_directory_record.h"
#include "zip_64_end_of_central_directory_locator.h"
#include "zip_end_of_central_directory_record.h"
#include "zip_file_entry_generic.h"
#include "inputsource_zip_fileentry.h"
/////////////////////////////////////////////////////////////////////////////
// CL_Zip_Archive construction:
CL_Zip_Archive::CL_Zip_Archive() : impl(new CL_Zip_Archive_Generic)
{
impl->add_ref();
}
CL_Zip_Archive::CL_Zip_Archive(const std::string &filename) : impl(new CL_Zip_Archive_Generic)
{
impl->add_ref();
impl->filename = filename;
// Load zip file structures:
CL_InputSource *input = new CL_InputSource_File(filename);
// Find end of central directory record:
int size_file = input->size();
char buffer[32*1024];
if (size_file > 32*1024) input->seek(-32*1024, CL_InputSource::seek_end);
int size_buffer = input->read(buffer, 32*1024);
int end_record_pos = -1;
for (int pos = size_buffer-4; pos >= 0; pos--)
{
if (*(unsigned int *)(buffer+pos) == 0x06054b50)
{
end_record_pos = size_file-size_buffer+pos;
input->tell();
break;
}
}
if (end_record_pos == -1)
{
delete input;
throw CL_Error("This appear not to be a zip file");
}
// Load end of central directory record:
CL_Zip_EndOfCentralDirectoryRecord end_of_directory;
input->seek(end_record_pos, CL_InputSource::seek_set);
end_of_directory.load(input);
// Look for zip64 central directory locator:
bool zip64 = false;
CL_Zip_64EndOfCentralDirectoryLocator zip64_locator;
CL_Zip_64EndOfCentralDirectoryRecord zip64_end_of_directory;
int end64_locator = end_record_pos-20;
input->seek(end64_locator, CL_InputSource::seek_set);
if (input->read_uint32() == 0x07064b50)
{
// Load zip64 structures:
input->seek(end64_locator, CL_InputSource::seek_set);
zip64_locator.load(input);
input->seek(end64_locator+zip64_locator.relative_offset_of_zip64_end_of_central_directory, CL_InputSource::seek_set);
zip64_end_of_directory.load(input);
zip64 = true;
}
// Load central directory records:
if (zip64) input->seek(zip64_end_of_directory.offset_to_start_of_central_directory, CL_InputSource::seek_set);
else input->seek(end_of_directory.offset_to_start_of_central_directory, CL_InputSource::seek_set);
cl_int64 num_entries = end_of_directory.number_of_entries_in_central_directory;
if (zip64) num_entries = zip64_end_of_directory.number_of_entries_in_central_directory;
for (int i=0; i<num_entries; i++)
{
CL_Zip_FileEntry entry;
entry.impl->record.load(input);
impl->files.push_back(entry);
}
delete input;
}
CL_Zip_Archive::CL_Zip_Archive(const CL_Zip_Archive ©) : impl(copy.impl)
{
impl->add_ref();
}
CL_Zip_Archive::~CL_Zip_Archive()
{
impl->release_ref();
}
/////////////////////////////////////////////////////////////////////////////
// CL_Zip_Archive attributes:
std::vector<CL_Zip_FileEntry> &CL_Zip_Archive::get_file_list()
{
return impl->files;
}
/////////////////////////////////////////////////////////////////////////////
// CL_Zip_Archive operations:
CL_Zip_Archive &CL_Zip_Archive::operator =(const CL_Zip_Archive ©)
{
impl->release_ref();
impl = copy.impl;
impl->add_ref();
return *this;
}
CL_InputSource *CL_Zip_Archive::open_source(const std::string &filename)
{
int size = impl->files.size();
for (int i=0; i<size; i++)
{
CL_Zip_FileEntry &entry = impl->files[i];
if (entry.impl->record.filename == filename)
{
switch (entry.impl->type)
{
case CL_Zip_FileEntry_Generic::type_file:
return new CL_InputSource_Zip_FileEntry(impl->filename, entry);
case CL_Zip_FileEntry_Generic::type_removed:
break;
case CL_Zip_FileEntry_Generic::type_added_memory:
return new CL_InputSource_Memory(entry.impl->data);
case CL_Zip_FileEntry_Generic::type_added_file:
return new CL_InputSource_File(entry.impl->filename);
}
throw CL_Error(CL_String::format("Found but hates %1", filename));
}
}
throw CL_Error(CL_String::format("Unable to find zip index %1", filename));
return 0;
}
CL_InputSourceProvider *CL_Zip_Archive::clone()
{
return new CL_Zip_Archive(*this);
}
std::string CL_Zip_Archive::get_pathname(const std::string &filename)
{
return filename;
}
CL_InputSourceProvider *CL_Zip_Archive::create_relative(const std::string &path)
{
// This is wrong. Should seperate the inputsource provider from CL_Zip_Archive,
// but don't really bother doing it right now.
// -- mbn may 10, 2003
return clone();
}
CL_OutputSource *CL_Zip_Archive::create_file(const std::string &filename, bool compress)
{
return 0;
}
void CL_Zip_Archive::add_file(const std::string &filename, bool compress)
{
}
void CL_Zip_Archive::save()
{
}
void CL_Zip_Archive::save(const std::string &filename)
{
}
/////////////////////////////////////////////////////////////////////////////
// CL_Zip_Archive implementation:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -