ciderpress/app/ACUArchive.h
Andy McFadden d8223dbcfd Relocate method comments
This moves method comments from the .cpp file to the .h file,
where users of the methods can find them.  This also makes it
possible for the IDE to show the comments when you mouse-hover over
the method name, though Visual Studio is a bit weak in this regard.

Also, added "override" keywords on overridden methods.  Reasonably
current versions of popular compilers seem to support this.

Also, don't have the return type on a separate line in the .cpp file.
The motivation for the practice -- quickly finding a method definition
with "^name" -- is less useful in C++ than C, and modern IDEs provide
more convenient ways to do the same thing.

Also, do some more conversion from unsigned types to uintXX_t.

This commit is primarily for the "app" directory.
2014-11-21 22:33:39 -08:00

298 lines
10 KiB
C++

/*
* CiderPress
* Copyright (C) 2007 by faddenSoft, LLC. All Rights Reserved.
* See the file LICENSE for distribution terms.
*/
/*
* AppleLink Compression Utility archive support.
*/
#ifndef APP_ACUARCHIVE_H
#define APP_ACUARCHIVE_H
#include "GenericArchive.h"
class AcuArchive;
/*
* One file in an ACU archive.
*/
class AcuEntry : public GenericEntry {
public:
AcuEntry(AcuArchive* pArchive) :
fpArchive(pArchive), fIsSqueezed(false), fOffset(-1)
{}
virtual ~AcuEntry(void) {}
virtual int ExtractThreadToBuffer(int which, char** ppText, long* pLength,
CString* pErrMsg) const override;
virtual int ExtractThreadToFile(int which, FILE* outfp, ConvertEOL conv,
ConvertHighASCII convHA, CString* pErrMsg) const override;
// doesn't matter
virtual long GetSelectionSerial(void) const override { return -1; }
virtual bool GetFeatureFlag(Feature feature) const override {
if (feature == kFeaturePascalTypes || feature == kFeatureDOSTypes ||
feature == kFeatureHasSimpleAccess)
return false;
else
return true;
}
/*
* Test this entry by extracting it.
*
* If the file isn't compressed, just make sure the file is big enough. If
* it's squeezed, invoke the un-squeeze function with a "NULL" buffer pointer.
*/
NuError TestEntry(CWnd* pMsgWnd);
bool GetSqueezed(void) const { return fIsSqueezed; }
void SetSqueezed(bool val) { fIsSqueezed = val; }
long GetOffset(void) const { return fOffset; }
void SetOffset(long offset) { fOffset = offset; }
private:
/*
* Copy data from the seeked archive to outfp, possibly converting EOL along
* the way.
*/
NuError CopyData(FILE* outfp, ConvertEOL conv, ConvertHighASCII convHA,
CString* pMsg) const;
//NuError BNYUnSqueeze(ExpandBuffer* outExp) const;
AcuArchive* fpArchive; // holds FILE* for archive
bool fIsSqueezed;
long fOffset;
};
/*
* ACU archive definition.
*/
class AcuArchive : public GenericArchive {
public:
AcuArchive(void) : fIsReadOnly(false), fFp(NULL)
{}
virtual ~AcuArchive(void) { (void) Close(); }
/*
* Perform one-time initialization. There really isn't any for us.
*
* Returns 0 on success, nonzero on error.
*/
static CString AppInit(void);
/*
* Open an ACU archive.
*
* Returns an error string on failure, or "" on success.
*/
virtual OpenResult Open(const WCHAR* filename, bool readOnly,
CString* pErrMsg) override;
/*
* Finish instantiating an AcuArchive object by creating a new archive.
*
* Returns an error string on failure, or "" on success.
*/
virtual CString New(const WCHAR* filename, const void* options) override;
virtual CString Flush(void) override { return ""; }
virtual CString Reload(void) override;
virtual bool IsReadOnly(void) const override { return fIsReadOnly; };
virtual bool IsModified(void) const override { return false; }
virtual void GetDescription(CString* pStr) const override
{ *pStr = "AppleLink ACU"; }
virtual bool BulkAdd(ActionProgressDialog* pActionProgress,
const AddFilesDialog* pAddOpts) override
{ ASSERT(false); return false; }
virtual bool AddDisk(ActionProgressDialog* pActionProgress,
const AddFilesDialog* pAddOpts) override
{ ASSERT(false); return false; }
virtual bool CreateSubdir(CWnd* pMsgWnd, GenericEntry* pParentEntry,
const WCHAR* newName) override
{ ASSERT(false); return false; }
virtual bool TestSelection(CWnd* pMsgWnd, SelectionSet* pSelSet) override;
virtual bool DeleteSelection(CWnd* pMsgWnd, SelectionSet* pSelSet) override
{ ASSERT(false); return false; }
virtual bool RenameSelection(CWnd* pMsgWnd, SelectionSet* pSelSet) override
{ ASSERT(false); return false; }
virtual bool RenameVolume(CWnd* pMsgWnd, DiskFS* pDiskFS,
const WCHAR* newName) override
{ ASSERT(false); return false; }
virtual CString TestVolumeName(const DiskFS* pDiskFS,
const WCHAR* newName) const override
{ ASSERT(false); return "!"; }
virtual CString TestPathName(const GenericEntry* pGenericEntry,
const CString& basePath, const CString& newName, char newFssep) const override
{ ASSERT(false); return "!"; }
virtual bool RecompressSelection(CWnd* pMsgWnd, SelectionSet* pSelSet,
const RecompressOptionsDialog* pRecompOpts) override
{ ASSERT(false); return false; }
virtual XferStatus XferSelection(CWnd* pMsgWnd, SelectionSet* pSelSet,
ActionProgressDialog* pActionProgress,
const XferFileOptions* pXferOpts) override
{ ASSERT(false); return kXferFailed; }
virtual bool GetComment(CWnd* pMsgWnd, const GenericEntry* pEntry,
CString* pStr) override
{ ASSERT(false); return false; }
virtual bool SetComment(CWnd* pMsgWnd, GenericEntry* pEntry,
const CString& str) override
{ ASSERT(false); return false; }
virtual bool DeleteComment(CWnd* pMsgWnd, GenericEntry* pEntry) override
{ ASSERT(false); return false; }
virtual bool SetProps(CWnd* pMsgWnd, GenericEntry* pEntry,
const FileProps* pProps) override
{ ASSERT(false); return false; }
virtual void PreferencesChanged(void) override {}
virtual long GetCapability(Capability cap) override;
friend class AcuEntry;
private:
virtual CString Close(void) {
if (fFp != NULL) {
fclose(fFp);
fFp = NULL;
}
return "";
}
virtual void XferPrepare(const XferFileOptions* pXferOpts) override
{ ASSERT(false); }
virtual CString XferFile(FileDetails* pDetails, uint8_t** pDataBuf,
long dataLen, uint8_t** pRsrcBuf, long rsrcLen) override
{ ASSERT(false); return "!"; }
virtual void XferAbort(CWnd* pMsgWnd) override
{ ASSERT(false); }
virtual void XferFinish(CWnd* pMsgWnd) override
{ ASSERT(false); }
virtual ArchiveKind GetArchiveKind(void) override { return kArchiveACU; }
virtual NuError DoAddFile(const AddFilesDialog* pAddOpts,
FileDetails* pDetails) override
{ ASSERT(false); return kNuErrGeneric; }
enum {
kAcuMaxFileName = 256, // nice big number
kAcuMasterHeaderLen = 20,
kAcuEntryHeaderLen = 54,
};
/*
* The header at the front of an ACU archive.
*/
typedef struct AcuMasterHeader {
unsigned short fileCount;
unsigned short unknown1; // 0x01 00 -- might be "version 1?"
unsigned char fZink[6]; // "fZink", low ASCII
unsigned char unknown2[11]; // 0x01 36 00 00 00 00 00 00 00 00 dd
} AcuMasterHeader;
/*
* An entry in an ACU archive. Each archive is essentially a stream
* of files; only the "filesToFollow" value gives any indication that
* something else follows this entry.
*
* We read this from the archive and then unpack the interesting parts
* into GenericEntry fields in an AcuEntry.
*/
struct AcuFileEntry;
friend struct AcuFileEntry;
typedef struct AcuFileEntry {
unsigned char compressionType;
unsigned short dataChecksum; // ??
unsigned short blockCount; // total blocks req'd to hold file
unsigned long dataStorageLen; // length of data within archive
unsigned short access;
unsigned short fileType;
unsigned long auxType;
unsigned char storageType;
unsigned long dataEof;
unsigned short prodosModDate;
unsigned short prodosModTime;
NuDateTime modWhen; // computed from previous two fields
unsigned short prodosCreateDate;
unsigned short prodosCreateTime;
NuDateTime createWhen; // computed from previous two fields
unsigned short fileNameLen;
unsigned short headerChecksum; // ??
char fileName[kAcuMaxFileName+1];
// possibilities for mystery fields:
// - OS type (note ProDOS is $00)
// - forked file support
} AcuFileEntry;
/* known compression types */
enum CompressionType {
kAcuCompNone = 0,
kAcuCompSqueeze = 3,
};
/*
* Load the contents of the archive.
*
* Returns 0 on success, < 0 if this is not an ACU archive > 0 if this appears
* to be an ACU archive but it's damaged.
*/
int LoadContents(void);
/*
* Read the archive header. The archive file is left seeked to the point
* at the end of the header.
*
* Returns 0 on success, -1 on failure. Sets *pNumEntries to the number of
* entries in the archive.
*/
int ReadMasterHeader(int* pNumEntries);
/*
* Read and decode an AppleLink Compression Utility file entry header.
* This leaves the file seeked to the point immediately past the filename.
*/
NuError ReadFileHeader(AcuFileEntry* pEntry);
/*
* Dump the contents of an AcuFileEntry struct.
*/
void DumpFileHeader(const AcuFileEntry* pEntry);
/*
* Given an AcuFileEntry structure, add an appropriate entry to the list.
*/
int CreateEntry(const AcuFileEntry* pEntry);
/*
* Test if this entry is a directory.
*/
bool IsDir(const AcuFileEntry* pEntry);
/*
* Wrapper for fread(). Note the arguments resemble read(2) rather
* than fread(3S).
*/
NuError AcuRead(void* buf, size_t nbyte);
/*
* Seek within an archive. Because we need to handle streaming archives,
* and don't need to special-case anything, we only allow relative
* forward seeks.
*/
NuError AcuSeek(long offset);
/*
* Convert from ProDOS compact date format to the expanded DateTime format.
*/
void AcuConvertDateTime(uint16_t prodosDate,
uint16_t prodosTime, NuDateTime* pWhen);
FILE* fFp;
bool fIsReadOnly;
};
#endif /*APP_ACUARCHIVE_H*/