initial commit
Signed-off-by: Peter Siegmund <mars3142@noreply.mars3142.dev>
This commit is contained in:
354
libs/wxWidgets-3.3.1/samples/archive/archive.cpp
Normal file
354
libs/wxWidgets-3.3.1/samples/archive/archive.cpp
Normal file
@@ -0,0 +1,354 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: samples/archive/archive.cpp
|
||||
// Purpose: A sample application to manipulate archives
|
||||
// Author: Tobias Taschner
|
||||
// Created: 2018-02-07
|
||||
// Copyright: (c) 2018 wxWidgets development team
|
||||
// Licence: wxWindows licence
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// For compilers that support precompilation, includes "wx/wx.h".
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#ifndef WX_PRECOMP
|
||||
#include "wx/wx.h"
|
||||
#endif
|
||||
|
||||
#include "wx/archive.h"
|
||||
#include "wx/app.h"
|
||||
#include "wx/cmdline.h"
|
||||
#include "wx/filename.h"
|
||||
#include "wx/vector.h"
|
||||
#include "wx/wfstream.h"
|
||||
#include "wx/zipstrm.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
class ArchiveApp: public wxAppConsole
|
||||
{
|
||||
public:
|
||||
ArchiveApp()
|
||||
{
|
||||
m_forceZip64 = false;
|
||||
m_archiveClassFactory = nullptr;
|
||||
m_filterClassFactory = nullptr;
|
||||
}
|
||||
|
||||
virtual void OnInitCmdLine(wxCmdLineParser& parser) override;
|
||||
|
||||
virtual bool OnCmdLineParsed(wxCmdLineParser& parser) override;
|
||||
|
||||
virtual int OnRun() override;
|
||||
|
||||
private:
|
||||
enum ArchiveCommandType
|
||||
{
|
||||
CMD_CREATE,
|
||||
CMD_LIST,
|
||||
CMD_EXTRACT,
|
||||
CMD_NONE
|
||||
};
|
||||
|
||||
struct ArchiveCommandDesc
|
||||
{
|
||||
ArchiveCommandType type;
|
||||
const char* id;
|
||||
const char* desc;
|
||||
};
|
||||
|
||||
static const ArchiveCommandDesc s_cmdDesc[];
|
||||
|
||||
ArchiveCommandType m_command;
|
||||
wxString m_archiveFileName;
|
||||
wxVector<wxString> m_fileNames;
|
||||
bool m_forceZip64;
|
||||
|
||||
// At most one of these pointers is non-null.
|
||||
const wxArchiveClassFactory* m_archiveClassFactory;
|
||||
const wxFilterClassFactory* m_filterClassFactory;
|
||||
|
||||
int DoCreate();
|
||||
|
||||
int DoList();
|
||||
|
||||
int DoExtract();
|
||||
|
||||
bool CopyStreamData(wxInputStream& inputStream, wxOutputStream& outputStream, wxFileOffset size);
|
||||
};
|
||||
|
||||
const ArchiveApp::ArchiveCommandDesc ArchiveApp::s_cmdDesc[] =
|
||||
{
|
||||
{CMD_CREATE, "c", "create"},
|
||||
{CMD_LIST, "l", "list"},
|
||||
{CMD_EXTRACT, "x", "extract"},
|
||||
|
||||
{CMD_NONE, nullptr, nullptr}
|
||||
};
|
||||
|
||||
// Helper function iterating over all factories of the given type (assumed to
|
||||
// derive from wxFilterClassFactoryBase) and returning a string containing all
|
||||
// comma-separated values returned from their GetProtocols() called with the
|
||||
// given protocol type.
|
||||
template <typename T>
|
||||
void AppendAllSupportedOfType(wxString& all, wxStreamProtocolType type)
|
||||
{
|
||||
for (const T* factory = T::GetFirst(); factory; factory = factory->GetNext())
|
||||
{
|
||||
const wxChar* const* exts = factory->GetProtocols(type);
|
||||
while (*exts)
|
||||
{
|
||||
if (!all.empty())
|
||||
all+= ", ";
|
||||
all += *exts++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Returns all supported protocols or extensions (depending on the type
|
||||
// parameter value) for both archive and filter factories.
|
||||
wxString GetAllSupported(wxStreamProtocolType type)
|
||||
{
|
||||
wxString all;
|
||||
AppendAllSupportedOfType<wxArchiveClassFactory>(all, type);
|
||||
AppendAllSupportedOfType<wxFilterClassFactory>(all, type);
|
||||
return all;
|
||||
}
|
||||
|
||||
void ArchiveApp::OnInitCmdLine(wxCmdLineParser& parser)
|
||||
{
|
||||
wxAppConsole::OnInitCmdLine(parser);
|
||||
|
||||
parser.AddParam("command");
|
||||
parser.AddParam("archive_name");
|
||||
parser.AddParam("file_names", wxCMD_LINE_VAL_STRING,
|
||||
wxCMD_LINE_PARAM_MULTIPLE | wxCMD_LINE_PARAM_OPTIONAL);
|
||||
parser.AddSwitch("", "force-zip64", "Force ZIP64 format when creating ZIP archives");
|
||||
|
||||
parser.AddUsageText("\ncommand:");
|
||||
for (const ArchiveCommandDesc* cmdDesc = s_cmdDesc; cmdDesc->type != CMD_NONE; cmdDesc++)
|
||||
parser.AddUsageText(wxString::Format(" %s: %s", cmdDesc->id, cmdDesc->desc));
|
||||
|
||||
parser.AddUsageText("\nsupported formats: " + GetAllSupported(wxSTREAM_PROTOCOL));
|
||||
}
|
||||
|
||||
bool ArchiveApp::OnCmdLineParsed(wxCmdLineParser& parser)
|
||||
{
|
||||
m_command = CMD_NONE;
|
||||
wxString command = parser.GetParam();
|
||||
for (const ArchiveCommandDesc* cmdDesc = s_cmdDesc; cmdDesc->type != CMD_NONE; cmdDesc++)
|
||||
{
|
||||
if (cmdDesc->id == command)
|
||||
m_command = cmdDesc->type;
|
||||
}
|
||||
if(m_command == CMD_NONE)
|
||||
{
|
||||
wxLogError("Invalid command: %s", command);
|
||||
return false;
|
||||
}
|
||||
m_archiveFileName = parser.GetParam(1);
|
||||
for (size_t i = 2; i < parser.GetParamCount(); i++)
|
||||
m_fileNames.push_back(parser.GetParam(i));
|
||||
m_forceZip64 = parser.FoundSwitch("force-zip64") == wxCMD_SWITCH_ON;
|
||||
|
||||
return wxAppConsole::OnCmdLineParsed(parser);
|
||||
}
|
||||
|
||||
bool ArchiveApp::CopyStreamData(wxInputStream& inputStream, wxOutputStream& outputStream, wxFileOffset size)
|
||||
{
|
||||
wxChar buf[128 * 1024];
|
||||
int readSize = 128 * 1024;
|
||||
wxFileOffset copiedData = 0;
|
||||
for (;;)
|
||||
{
|
||||
if (size != -1 && copiedData + readSize > size)
|
||||
readSize = size - copiedData;
|
||||
inputStream.Read(buf, readSize);
|
||||
|
||||
size_t actuallyRead = inputStream.LastRead();
|
||||
outputStream.Write(buf, actuallyRead);
|
||||
if (outputStream.LastWrite() != actuallyRead)
|
||||
{
|
||||
wxLogError("Failed to output data");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (size == -1)
|
||||
{
|
||||
if (inputStream.Eof())
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
copiedData += actuallyRead;
|
||||
if (copiedData >= size)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int ArchiveApp::DoCreate()
|
||||
{
|
||||
if (m_fileNames.empty())
|
||||
{
|
||||
wxLogError("Need at least one file to add to archive");
|
||||
return -1;
|
||||
}
|
||||
|
||||
wxTempFileOutputStream fileOutputStream(m_archiveFileName);
|
||||
if (m_archiveClassFactory)
|
||||
{
|
||||
std::unique_ptr<wxArchiveOutputStream> archiveOutputStream(m_archiveClassFactory->NewStream(fileOutputStream));
|
||||
if (m_archiveClassFactory->GetProtocol().IsSameAs("zip", false) && m_forceZip64)
|
||||
reinterpret_cast<wxZipOutputStream*>(archiveOutputStream.get())->SetFormat(wxZIP_FORMAT_ZIP64);
|
||||
|
||||
for(wxVector<wxString>::iterator fileName = m_fileNames.begin(); fileName != m_fileNames.end(); fileName++)
|
||||
{
|
||||
wxFileName inputFileName(*fileName);
|
||||
wxPrintf("Adding %s...\n", inputFileName.GetFullName());
|
||||
wxFileInputStream inputFileStream(*fileName);
|
||||
if (!inputFileStream.IsOk())
|
||||
{
|
||||
wxLogError("Could not open file");
|
||||
return 1;
|
||||
}
|
||||
if (!archiveOutputStream->PutNextEntry(inputFileName.GetFullName(), wxDateTime::Now(), inputFileStream.GetLength()))
|
||||
break;
|
||||
if (!CopyStreamData(inputFileStream, *archiveOutputStream, inputFileStream.GetLength()))
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!archiveOutputStream->Close())
|
||||
return 1;
|
||||
}
|
||||
else // use m_filterClassFactory
|
||||
{
|
||||
if (m_fileNames.size() != 1)
|
||||
{
|
||||
wxLogError("Filter-based formats only support archives consisting of a single file");
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::unique_ptr<wxFilterOutputStream> filterOutputStream(m_filterClassFactory->NewStream(fileOutputStream));
|
||||
wxFileInputStream inputFileStream(*m_fileNames.begin());
|
||||
if (!inputFileStream.IsOk())
|
||||
{
|
||||
wxLogError("Could not open file");
|
||||
return 1;
|
||||
}
|
||||
if (!CopyStreamData(inputFileStream, *filterOutputStream, inputFileStream.GetLength()))
|
||||
return 1;
|
||||
}
|
||||
|
||||
fileOutputStream.Commit();
|
||||
wxPrintf("Created archive\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ArchiveApp::DoList()
|
||||
{
|
||||
wxFileInputStream fileInputStream(m_archiveFileName);
|
||||
if (!fileInputStream.IsOk())
|
||||
return 1;
|
||||
|
||||
if (m_archiveClassFactory)
|
||||
{
|
||||
std::unique_ptr<wxArchiveInputStream> archiveStream(m_archiveClassFactory->NewStream(fileInputStream));
|
||||
wxPrintf("Archive: %s\n", m_archiveFileName);
|
||||
wxPrintf("Length Date Time Name\n");
|
||||
wxPrintf("---------- ---------- -------- ----\n");
|
||||
|
||||
wxFileOffset combinedSize = 0;
|
||||
int entryCount = 0;
|
||||
for (wxArchiveEntry* entry = archiveStream->GetNextEntry(); entry;
|
||||
entry = archiveStream->GetNextEntry())
|
||||
{
|
||||
combinedSize += entry->GetSize();
|
||||
entryCount++;
|
||||
wxPrintf("%10lld %s %s %s\n",
|
||||
entry->GetSize(),
|
||||
entry->GetDateTime().FormatISODate(),
|
||||
entry->GetDateTime().FormatISOTime(),
|
||||
entry->GetName());
|
||||
}
|
||||
wxPrintf("---------- -------\n");
|
||||
wxPrintf("%10lld %d files\n", combinedSize, entryCount);
|
||||
}
|
||||
else
|
||||
{
|
||||
wxPrintf("Archive \"%s\" contains a single file named \"%s\"\n",
|
||||
m_archiveFileName, wxFileName(m_archiveFileName).GetName());
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ArchiveApp::DoExtract()
|
||||
{
|
||||
wxFileInputStream fileInputStream(m_archiveFileName);
|
||||
if (!fileInputStream.IsOk())
|
||||
return 1;
|
||||
|
||||
if (m_archiveClassFactory)
|
||||
{
|
||||
std::unique_ptr<wxArchiveInputStream> archiveStream(m_archiveClassFactory->NewStream(fileInputStream));
|
||||
wxPrintf("Extracting from: %s\n", m_archiveFileName);
|
||||
for (wxArchiveEntry* entry = archiveStream->GetNextEntry(); entry;
|
||||
entry = archiveStream->GetNextEntry())
|
||||
{
|
||||
wxPrintf("Extracting: %s...\n", entry->GetName());
|
||||
wxTempFileOutputStream outputFileStream(entry->GetName());
|
||||
if (!CopyStreamData(*archiveStream, outputFileStream, entry->GetSize()))
|
||||
return 1;
|
||||
outputFileStream.Commit();
|
||||
}
|
||||
wxPrintf("Extracted all files\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
std::unique_ptr<wxFilterInputStream> filterStream(m_filterClassFactory->NewStream(fileInputStream));
|
||||
wxPrintf("Extracting single file from: %s\n", m_archiveFileName);
|
||||
wxTempFileOutputStream outputFileStream(wxFileName(m_archiveFileName).GetName());
|
||||
if (!CopyStreamData(*filterStream, outputFileStream, -1))
|
||||
return 1;
|
||||
outputFileStream.Commit();
|
||||
wxPrintf("Extracted successfully\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ArchiveApp::OnRun()
|
||||
{
|
||||
m_archiveClassFactory = wxArchiveClassFactory::Find(m_archiveFileName, wxSTREAM_FILEEXT);
|
||||
if (!m_archiveClassFactory)
|
||||
{
|
||||
m_filterClassFactory = wxFilterClassFactory::Find(m_archiveFileName, wxSTREAM_FILEEXT);
|
||||
if (!m_filterClassFactory)
|
||||
{
|
||||
wxLogError("File \"%s\" has unsupported extension, supported ones are: %s",
|
||||
m_archiveFileName, GetAllSupported(wxSTREAM_FILEEXT));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int result = -1;
|
||||
switch (m_command) {
|
||||
case CMD_CREATE:
|
||||
result = DoCreate();
|
||||
break;
|
||||
case CMD_LIST:
|
||||
result = DoList();
|
||||
break;
|
||||
case CMD_EXTRACT:
|
||||
result = DoExtract();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
wxIMPLEMENT_APP(ArchiveApp);
|
||||
Reference in New Issue
Block a user