nulib2/nufxlib/NufxLibPriv.h

871 lines
35 KiB
C

/*
* NuFX archive manipulation library
* Copyright (C) 2000-2007 by Andy McFadden, All Rights Reserved.
* This is free software; you can redistribute it and/or modify it under the
* terms of the BSD License, see the file COPYING-LIB.
*
* Global internal declarations and definitions.
*/
#ifndef __NufxLibPriv__
#define __NufxLibPriv__
/* include files that everybody needs */
#include "SysDefs.h"
#include "NufxLib.h"
#include "MiscStuff.h"
#ifdef USE_DMALLOC
/* enable with something like "dmalloc -l logfile -i 100 medium" */
# include "dmalloc.h"
#endif
/*
* ===========================================================================
* NuArchive definition
* ===========================================================================
*/
/*
* Archives can be opened in streaming read-only, non-streaming read-only,
* and non-streaming read-write mode.
*/
typedef enum NuOpenMode {
kNuOpenUnknown,
kNuOpenStreamingRO,
kNuOpenRO,
kNuOpenRW
} NuOpenMode;
#define Nu_IsStreaming(pArchive) ((pArchive)->openMode == kNuOpenStreamingRO)
#define Nu_IsReadOnly(pArchive) ((pArchive)->openMode == kNuOpenStreamingRO ||\
(pArchive)->openMode == kNuOpenRO)
#ifdef FOPEN_WANTS_B
# define kNuFileOpenReadOnly "rb"
# define kNuFileOpenReadWrite "r+b"
# define kNuFileOpenWriteTrunc "wb"
# define kNuFileOpenReadWriteCreat "w+b"
#else
# define kNuFileOpenReadOnly "r"
# define kNuFileOpenReadWrite "r+"
# define kNuFileOpenWriteTrunc "w"
# define kNuFileOpenReadWriteCreat "w+"
#endif
/*
* Some NuFX and Binary II definitions.
*/
#define kNuMasterHeaderSize 48 /* size of fixed-length master header */
#define kNuRecordHeaderBaseSize 58 /* size of rec hdr up to variable stuff */
#define kNuThreadHeaderSize 16 /* size of fixed-length thread header */
#define kNuDefaultFilenameThreadSize 32 /* default size of filename thred */
#define kNuDefaultCommentSize 200 /* size of GSHK-mimic comments */
#define kNuBinary2BlockSize 128 /* size of bxy header and padding */
#define kNuSEAOffset 0x2ee5 /* fixed(??) offset to data in SEA */
#define kNuInitialChunkCRC 0x0000 /* start for CRC in LZW/1 chunk */
#define kNuInitialThreadCRC 0xffff /* start for CRC in v3 thread header */
/* size of general-purpose compression buffer */
#define kNuGenCompBufSize 32768
#define kNuCharLF 0x0a
#define kNuCharCR 0x0d
/*
* A list of records. Generally we use one of these for read-only
* archives, and two for read-write.
*
* The "loaded" flag is set when we've made some use of the record set.
* Relying on "numRecords" won't always work; for example, if the "copy"
* record set was initialized from "orig", and then had all of its records
* deleted, you couldn't look at "numRecords" and decide whether it was
* appropriate to use "orig" or not.
*/
typedef struct NuRecordSet {
Boolean loaded;
ulong numRecords;
NuRecord* nuRecordHead;
NuRecord* nuRecordTail;
} NuRecordSet;
/*
* Archive state.
*/
struct NuArchive {
ulong structMagic;
Boolean busy;
NuOpenMode openMode;
Boolean newlyCreated;
char* archivePathname; /* pathname or "(stream)" */
FILE* archiveFp;
NuArchiveType archiveType;
/* stuff before NuFX; both offsets are from 0, i.e. hdrOff includes junk */
long junkOffset; /* skip past leading junk */
long headerOffset; /* adjustment for BXY/SEA/BSE */
char* tmpPathname; /* temp file, for writes */
FILE* tmpFp;
/* used during initial processing; helps avoid ftell() calls */
long currentOffset;
/* setting this changes Extract into Test */
Boolean testMode;
/* clumsy way of remembering name used for other fork in forked file */
const char* lastFileCreated;
/* clumsy way to avoid trying to create the same subdir several times */
const char* lastDirCreated;
/* master header from the archive */
NuMasterHeader masterHeader; /* original */
NuMasterHeader newMasterHeader; /* working copy during update */
/* list of records from archive, plus some extra state */
NuRecordIdx recordIdxSeed; /* where the NuRecordIdxs start */
NuRecordIdx nextRecordIdx; /* next record gets this value */
Boolean haveToc; /* set if we have full TOC */
NuRecordSet origRecordSet; /* records from archive */
NuRecordSet copyRecordSet; /* copy of orig, for write ops */
NuRecordSet newRecordSet; /* newly-added records */
/* state for compression functions */
uchar* compBuf; /* large general-purpose buffer */
void* lzwCompressState; /* state for LZW/1 and LZW/2 */
void* lzwExpandState; /* state for LZW/1 and LZW/2 */
/* options and attributes that the user can set */
/* (these can be changed by a callback, so don't cache them internally) */
void* extraData; /* application-defined pointer */
NuValue valAllowDuplicates; /* allow dups when adding? */
NuValue valConvertExtractedEOL; /* convert EOL during extract? */
NuValue valDataCompression; /* how to compress when adding? */
NuValue valDiscardWrapper; /* remove BNY or SEA header? */
NuValue valEOL; /* EOL value to convert to */
NuValue valHandleExisting; /* how to deal with existing files*/
NuValue valIgnoreCRC; /* don't compute or test CRCs */
NuValue valMaskDataless; /* alter Records w/o data threads */
NuValue valMimicSHK; /* mimic some ShrinkIt quirks */
NuValue valModifyOrig; /* modify original arc in place? */
NuValue valOnlyUpdateOlder; /* modify original arc in place? */
NuValue valStripHighASCII; /* during EOL conv, strip hi bit? */
NuValue valJunkSkipMax; /* scan this far for header */
NuValue valIgnoreLZW2Len; /* don't verify LZW/II len field */
NuValue valHandleBadMac; /* handle "bad Mac" archives */
/* callback functions */
NuCallback selectionFilterFunc;
NuCallback outputPathnameFunc;
NuCallback progressUpdaterFunc;
NuCallback errorHandlerFunc;
NuCallback messageHandlerFunc;
};
#define kNuArchiveStructMagic 0xc0edbabe
#define kNuDefaultRecordName "UNKNOWN"
/*
* ===========================================================================
* ThreadMod definition
* ===========================================================================
*/
/* operations we can perform on threads in a record */
typedef enum ThreadModKind {
kNuThreadModUnknown = 0,
kNuThreadModAdd,
kNuThreadModUpdate,
kNuThreadModDelete
} ThreadModKind;
/*
* We attach a list of these to records we plan to modify. Care is taken
* to ensure that they don't conflict, e.g. you can't update a thread
* right after you delete it, nor delete one you have modified.
*/
struct NuThreadMod {
union {
ThreadModKind kind;
struct {
ThreadModKind kind;
Boolean used;
} generic;
struct {
ThreadModKind kind;
Boolean used;
Boolean isPresized;
NuThreadIdx threadIdx;
NuThreadID threadID;
NuThreadFormat threadFormat;
NuDataSource* pDataSource;
} add;
struct {
ThreadModKind kind;
Boolean used;
NuThreadIdx threadIdx;
NuDataSource* pDataSource;
} update;
struct {
ThreadModKind kind;
Boolean used;
NuThreadIdx threadIdx;
NuThreadID threadID; /* used for watching filename threads */
} delete;
} entry;
struct NuThreadMod* pNext;
};
/*
* ===========================================================================
* NuFunnel/NuStraw definition
* ===========================================================================
*/
#define kNuFunnelBufSize 16384
/*
* File funnel definition. This is used for writing output to files
* (so we can do things like pipe compressed output through an LF->CR
* converter) and archive files (so we can halt compression when the
* output size exceeds the uncompressed original). [ for various reasons,
* I'm not using this on the archive anymore. ]
*
* Funnels are unidirectional. You write data into them with a
* function call; the top-level action (which is usually compressing or
* expanding data) reads from the input and crams things into the pipe.
* We could fully abstract the concept, and write the compression
* functions so that they operate as a Funnel filter, but it's much
* easier to write block-oriented compression than stream-oriented (and
* more to the point, the ShrinkIt LZW functions are very much
* block-oriented).
*/
typedef struct NuFunnel {
/* data storage */
uchar* buffer; /* kNuFunnelBufSize worth of storage */
long bufCount; /* #of bytes in buffer */
/* text conversion; if "auto", on first flush we convert to "on" or "off" */
NuValue convertEOL; /* on/off/auto */
NuValue convertEOLTo; /* EOL to switch to */
NuValue convertEOLFrom; /* EOL terminator we think we found */
Boolean checkStripHighASCII; /* do we want to check for it? */
Boolean doStripHighASCII; /* strip high ASCII during EOL conv */
Boolean lastCR; /* was last char a CR? */
Boolean isFirstWrite; /* cleared on first write */
#if 0
ulong inCount; /* total #of bytes in the top */
ulong outCount; /* total #of bytes out the bottom */
ulong outMax; /* flag an err when outCount exceeds this */
Boolean outMaxExceeded; /* in fact, it's this flag */
#endif
/* update this when stuff happens */
NuProgressData* pProgress;
/* data goeth out here */
NuDataSink* pDataSink;
} NuFunnel;
/*
* File straw definition. This is used for slurping up input data.
*
* Mostly this is an encapsulation of an input source and a progress
* updater, useful for reading uncompressed data and feeding it to a
* compressor. It doesn't make sense to show a thermometer based on
* compressed output, since we don't know how big the eventual result
* will be, so we want to do it for the input.
*/
typedef struct NuStraw {
/* update this when stuff happens */
NuProgressData* pProgress;
/* data cometh in here */
NuDataSource* pDataSource;
/* progress update fields */
ulong lastProgress;
ulong lastDisplayed;
} NuStraw;
/*NuError Nu_CopyStreamToStream(FILE* outfp, FILE* infp, ulong count);*/
/*
* ===========================================================================
* Data source and sink abstractions
* ===========================================================================
*/
/*
* DataSource is used when adding data to an archive.
*/
typedef enum NuDataSourceType {
kNuDataSourceUnknown = 0,
kNuDataSourceFromFile,
kNuDataSourceFromFP,
kNuDataSourceFromBuffer
} NuDataSourceType;
typedef struct NuDataSourceCommon {
NuDataSourceType sourceType;
NuThreadFormat threadFormat; /* is it already compressed? */
ushort rawCrc; /* crc for already-compressed data*/
/*Boolean doClose; \* close on completion? */
ulong dataLen; /* length of data (var for buf) */
ulong otherLen; /* uncomp len or preset buf size */
int refCount; /* so we can copy structs */
} NuDataSourceCommon;
union NuDataSource {
NuDataSourceType sourceType;
NuDataSourceCommon common;
struct {
NuDataSourceCommon common;
char* pathname;
Boolean fromRsrcFork;
/* temp storage; only valid when processing in library */
FILE* fp;
} fromFile;
struct {
NuDataSourceCommon common;
FILE* fp;
long offset; /* starting offset */
NuCallback fcloseFunc; /* how to fclose the file */
} fromFP;
struct {
NuDataSourceCommon common;
const uchar* buffer; /* non-const if doClose=true */
long offset; /* starting offset */
long curOffset; /* current offset */
long curDataLen; /* remaining data */
NuCallback freeFunc; /* how to free data */
} fromBuffer;
};
/*
* DataSink is used when extracting data from an archive.
*/
typedef enum NuDataSinkType {
kNuDataSinkUnknown = 0,
kNuDataSinkToFile,
kNuDataSinkToFP,
kNuDataSinkToBuffer,
kNuDataSinkToVoid
} NuDataSinkType;
typedef struct NuDataSinkCommon {
NuDataSinkType sinkType;
Boolean doExpand; /* expand file? */
NuValue convertEOL; /* convert EOL? (req "expand") */
ulong outCount;
} NuDataSinkCommon;
union NuDataSink {
NuDataSinkType sinkType;
NuDataSinkCommon common;
struct {
NuDataSinkCommon common;
char* pathname; /* file to open */
char fssep;
/* temp storage; must be nil except when processing in library */
FILE* fp;
} toFile;
struct {
NuDataSinkCommon common;
FILE* fp;
} toFP;
struct {
NuDataSinkCommon common;
uchar* buffer;
ulong bufLen; /* max amount of data "buffer" holds */
NuError stickyErr;
} toBuffer;
};
/*
* ===========================================================================
* Function prototypes
* ===========================================================================
*/
/*
* This is a little unpleasant. This blob of stuff gets stuffed in as
* the first arguments to Nu_ReportError, so we don't have to type them
* in every time we use the function. It would've been much easier to
* use a gcc-style varargs macro, but not everybody uses gcc.
*/
#ifdef DEBUG_MSGS
#ifdef HAS__FUNCTION__
#define _FUNCTION_ __FUNCTION__
#else
#define _FUNCTION_ ""
#endif
#define NU_BLOB pArchive, __FILE__, __LINE__, _FUNCTION_, false
#define NU_BLOB_DEBUG pArchive, __FILE__, __LINE__, _FUNCTION_, true
#define NU_NILBLOB NULL, __FILE__, __LINE__, _FUNCTION_, false
#define DebugShowError(err) \
Nu_ReportError(pArchive, __FILE__, __LINE__, _FUNCTION_, \
true, err, "(DEBUG)");
#else
#define NU_BLOB pArchive, "", 0, "", false
#define NU_BLOB_DEBUG pArchive, "", 0, "", true
#define NU_NILBLOB NULL, "", 0, "", false
#define DebugShowError(err) ((void)0)
#endif
/*
* The BailError macro serves two purposes. First, it's a convenient
* way to avoid typing, "if (err != kNuErrNone) goto bail;". Second,
* when the library is built with debugging enabled, it vitually gives
* us a stack trace of exiting functions. This makes it easier to debug
* problems sent in as screen dumps via e-mail.
*/
#define BailError(err) { \
if ((err) != kNuErrNone) { \
/* [should this be debug-only, or all the time?] */ \
DebugShowError(err); \
goto bail; \
} \
}
#define BailErrorQuiet(err) { \
if ((err) != kNuErrNone) \
goto bail; \
}
#define BailNil(val) { \
if ((val) == nil) { \
err = kNuErrUnexpectedNil; \
BailError(err); \
} \
}
#define BailAlloc(val) { \
if ((val) == nil) { \
err = kNuErrMalloc; \
BailError(err); \
} \
}
/*
* Internal function prototypes and inline functions.
*/
/* Archive.c */
void Nu_MasterHeaderCopy(NuArchive* pArchive, NuMasterHeader* pDstHeader,
const NuMasterHeader* pSrcHeader);
NuError Nu_GetMasterHeader(NuArchive* pArchive,
const NuMasterHeader** ppMasterHeader);
NuRecordIdx Nu_GetNextRecordIdx(NuArchive* pArchive);
NuThreadIdx Nu_GetNextThreadIdx(NuArchive* pArchive);
NuError Nu_CopyWrapperToTemp(NuArchive* pArchive);
NuError Nu_UpdateWrapper(NuArchive* pArchive, FILE* fp);
NuError Nu_AdjustWrapperPadding(NuArchive* pArchive, FILE* fp);
NuError Nu_AllocCompressionBufferIFN(NuArchive* pArchive);
NuError Nu_StreamOpenRO(FILE* infp, NuArchive** ppArchive);
NuError Nu_OpenRO(const char* filename, NuArchive** ppArchive);
NuError Nu_OpenRW(const char* archivePathname, const char* tempPathname,
ulong flags, NuArchive** ppArchive);
NuError Nu_WriteMasterHeader(NuArchive* pArchive, FILE* fp,
NuMasterHeader* pMasterHeader);
NuError Nu_Close(NuArchive* pArchive);
NuError Nu_Abort(NuArchive* pArchive);
NuError Nu_RenameTempToArchive(NuArchive* pArchive);
NuError Nu_DeleteArchiveFile(NuArchive* pArchive);
/* ArchiveIO.c */
uchar Nu_ReadOneC(NuArchive* pArchive, FILE* fp, ushort* pCrc);
uchar Nu_ReadOne(NuArchive* pArchive, FILE* fp);
void Nu_WriteOneC(NuArchive* pArchive, FILE* fp, uchar val, ushort* pCrc);
void Nu_WriteOne(NuArchive* pArchive, FILE* fp, uchar val);
ushort Nu_ReadTwoC(NuArchive* pArchive, FILE* fp, ushort* pCrc);
ushort Nu_ReadTwo(NuArchive* pArchive, FILE* fp);
void Nu_WriteTwoC(NuArchive* pArchive, FILE* fp, ushort val, ushort* pCrc);
void Nu_WriteTwo(NuArchive* pArchive, FILE* fp, ushort val);
ulong Nu_ReadFourC(NuArchive* pArchive, FILE* fp, ushort* pCrc);
ulong Nu_ReadFour(NuArchive* pArchive, FILE* fp);
void Nu_WriteFourC(NuArchive* pArchive, FILE* fp, ulong val, ushort* pCrc);
void Nu_WriteFour(NuArchive* pArchive, FILE* fp, ulong val);
NuDateTime Nu_ReadDateTimeC(NuArchive* pArchive, FILE* fp, ushort* pCrc);
NuDateTime Nu_ReadDateTime(NuArchive* pArchive, FILE* fp, ushort* pCrc);
void Nu_WriteDateTimeC(NuArchive* pArchive, FILE* fp, NuDateTime dateTime,
ushort* pCrc);
void Nu_WriteDateTime(NuArchive* pArchive, FILE* fp, NuDateTime dateTime);
void Nu_ReadBytesC(NuArchive* pArchive, FILE* fp, void* vbuffer, long count,
ushort* pCrc);
void Nu_ReadBytes(NuArchive* pArchive, FILE* fp, void* vbuffer, long count);
void Nu_WriteBytesC(NuArchive* pArchive, FILE* fp, const void* vbuffer,
long count, ushort* pCrc);
void Nu_WriteBytes(NuArchive* pArchive, FILE* fp, const void* vbuffer,
long count);
NuError Nu_HeaderIOFailed(NuArchive* pArchive, FILE* fp);
NuError Nu_SeekArchive(NuArchive* pArchive, FILE* fp, long offset,
int ptrname);
NuError Nu_RewindArchive(NuArchive* pArchive);
/* Bzip2.c */
NuError Nu_CompressBzip2(NuArchive* pArchive, NuStraw* pStraw, FILE* fp,
ulong srcLen, ulong* pDstLen, ushort* pCrc);
NuError Nu_ExpandBzip2(NuArchive* pArchive, const NuRecord* pRecord,
const NuThread* pThread, FILE* infp, NuFunnel* pFunnel, ushort* pCrc);
/* Compress.c */
NuError Nu_CompressToArchive(NuArchive* pArchive, NuDataSource* pDataSource,
NuThreadID threadID, NuThreadFormat sourceFormat,
NuThreadFormat targetFormat, NuProgressData* progressData, FILE* dstFp,
NuThread* pThread);
NuError Nu_CopyPresizedToArchive(NuArchive* pArchive,
NuDataSource* pDataSource, NuThreadID threadID, FILE* dstFp,
NuThread* pThread, char** ppSavedCopy);
/* Crc16.c */
extern const ushort gNuCrc16Table[256];
ushort Nu_CalcCRC16(ushort seed, const uchar* ptr, int count);
#ifdef __Crc16_c__ /* just doing "static inline" warns def-but-not-used */
#define CRC_INLINE /**/
#else
#define CRC_INLINE extern inline
#endif
#if defined(inline) && !defined(__Crc16_c__) /* somebody ovrd inline def? */
ushort Nu_UpdateCRC16(uchar val, ushort crc);
#else
CRC_INLINE ushort
Nu_UpdateCRC16(uchar val, ushort crc)
{
return (gNuCrc16Table[((crc >> 8) & 0xFF) ^ val] ^ (crc << 8)) & 0xFFFF;
}
#endif
/* Debug.c */
#if defined(DEBUG_MSGS) || !defined(NDEBUG)
void Nu_DebugDumpAll(NuArchive* pArchive);
void Nu_DebugDumpThread(const NuThread* pThread);
#endif
/* Deferred.c */
NuError Nu_ThreadModAdd_New(NuArchive* pArchive, NuThreadID threadID,
NuThreadFormat threadFormat, NuDataSource* pDataSource,
NuThreadMod** ppThreadMod);
NuError Nu_ThreadModUpdate_New(NuArchive* pArchive, NuThreadIdx threadIdx,
NuDataSource* pDataSource, NuThreadMod** ppThreadMod);
NuError Nu_ThreadModDelete_New(NuArchive* pArchive, NuThreadIdx threadIdx,
NuThreadID threadID, NuThreadMod** ppThreadMod);
void Nu_ThreadModFree(NuArchive* pArchive, NuThreadMod* pThreadMod);
NuError Nu_ThreadModAdd_FindByThreadID(const NuRecord* pRecord,
NuThreadID threadID, NuThreadMod** ppThreadMod);
void Nu_FreeThreadMods(NuArchive* pArchive, NuRecord* pRecord);
NuThreadMod* Nu_ThreadMod_FindByThreadIdx(const NuRecord* pRecord,
NuThreadIdx threadIdx);
NuError Nu_Flush(NuArchive* pArchive, long* pStatusFlags);
/* Deflate.c */
NuError Nu_CompressDeflate(NuArchive* pArchive, NuStraw* pStraw, FILE* fp,
ulong srcLen, ulong* pDstLen, ushort* pCrc);
NuError Nu_ExpandDeflate(NuArchive* pArchive, const NuRecord* pRecord,
const NuThread* pThread, FILE* infp, NuFunnel* pFunnel, ushort* pCrc);
/* Expand.c */
NuError Nu_ExpandStream(NuArchive* pArchive, const NuRecord* pRecord,
const NuThread* pThread, FILE* infp, NuFunnel* pFunnel);
/* FileIO.c */
void Nu_SetCurrentDateTime(NuDateTime* pDateTime);
Boolean Nu_IsOlder(const NuDateTime* pWhen1, const NuDateTime* pWhen2);
NuError Nu_OpenOutputFile(NuArchive* pArchive, const NuRecord* pRecord,
const NuThread* pThread, const char* newPathname, char newFssep,
FILE** pFp);
NuError Nu_CloseOutputFile(NuArchive* pArchive, const NuRecord* pRecord,
FILE* fp, const char* pathname);
NuError Nu_OpenInputFile(NuArchive* pArchive, const char* pathname,
Boolean openRsrc, FILE** pFp);
NuError Nu_DeleteFile(const char* pathname);
NuError Nu_RenameFile(const char* fromPath, const char* toPath);
NuError Nu_FTell(FILE* fp, long* pOffset);
NuError Nu_FSeek(FILE* fp, long offset, int ptrname);
NuError Nu_FRead(FILE* fp, void* buf, size_t nbyte);
NuError Nu_FWrite(FILE* fp, const void* buf, size_t nbyte);
NuError Nu_CopyFileSection(NuArchive* pArchive, FILE* dstFp, FILE* srcFp,
long length);
NuError Nu_GetFileLength(NuArchive* pArchive, FILE* fp, long* pLength);
NuError Nu_TruncateOpenFile(FILE* fp, long length);
/* Funnel.c */
NuError Nu_ProgressDataInit_Compress(NuArchive* pArchive,
NuProgressData* pProgressData, const NuRecord* pRecord,
const char* origPathname);
NuError Nu_ProgressDataInit_Expand(NuArchive* pArchive,
NuProgressData* pProgressData, const NuRecord* pRecord,
const char* newPathname, char newFssep, NuValue convertEOL);
NuError Nu_SendInitialProgress(NuArchive* pArchive, NuProgressData* pProgress);
NuError Nu_FunnelNew(NuArchive* pArchive, NuDataSink* pDataSink,
NuValue convertEOL, NuValue convertEOLTo, NuProgressData* pProgress,
NuFunnel** ppFunnel);
NuError Nu_FunnelFree(NuArchive* pArchive, NuFunnel* pFunnel);
/*void Nu_FunnelSetMaxOutput(NuFunnel* pFunnel, ulong maxBytes);*/
NuError Nu_FunnelWrite(NuArchive* pArchive, NuFunnel* pFunnel,
const uchar* buffer, ulong count);
NuError Nu_FunnelFlush(NuArchive* pArchive, NuFunnel* pFunnel);
NuError Nu_ProgressDataCompressPrep(NuArchive* pArchive, NuStraw* pStraw,
NuThreadFormat threadFormat, ulong sourceLen);
NuError Nu_ProgressDataExpandPrep(NuArchive* pArchive, NuFunnel* pFunnel,
const NuThread* pThread);
NuError Nu_FunnelSetProgressState(NuFunnel* pFunnel, NuProgressState state);
NuError Nu_FunnelSendProgressUpdate(NuArchive* pArchive, NuFunnel* pFunnel);
Boolean Nu_FunnelGetDoExpand(NuFunnel* pFunnel);
NuError Nu_StrawNew(NuArchive* pArchive, NuDataSource* pDataSource,
NuProgressData* pProgress, NuStraw** ppStraw);
NuError Nu_StrawFree(NuArchive* pArchive, NuStraw* pStraw);
NuError Nu_StrawSetProgressState(NuStraw* pStraw, NuProgressState state);
NuError Nu_StrawSendProgressUpdate(NuArchive* pArchive, NuStraw* pStraw);
NuError Nu_StrawRead(NuArchive* pArchive, NuStraw* pStraw, uchar* buffer,
long len);
NuError Nu_StrawRewind(NuArchive* pArchive, NuStraw* pStraw);
/* Lzc.c */
NuError Nu_CompressLZC12(NuArchive* pArchive, NuStraw* pStraw, FILE* fp,
ulong srcLen, ulong* pDstLen, ushort* pCrc);
NuError Nu_CompressLZC16(NuArchive* pArchive, NuStraw* pStraw, FILE* fp,
ulong srcLen, ulong* pDstLen, ushort* pCrc);
NuError Nu_ExpandLZC(NuArchive* pArchive, const NuRecord* pRecord,
const NuThread* pThread, FILE* infp, NuFunnel* pFunnel, ushort* pCrc);
/* Lzw.c */
NuError Nu_CompressLZW1(NuArchive* pArchive, NuStraw* pStraw, FILE* fp,
ulong srcLen, ulong* pDstLen, ushort* pCrc);
NuError Nu_CompressLZW2(NuArchive* pArchive, NuStraw* pStraw, FILE* fp,
ulong srcLen, ulong* pDstLen, ushort* pCrc);
NuError Nu_ExpandLZW(NuArchive* pArchive, const NuRecord* pRecord,
const NuThread* pThread, FILE* infp, NuFunnel* pFunnel, ushort* pThreadCrc);
/* MiscUtils.c */
/*extern const char* kNufxLibName;*/
extern NuCallback gNuGlobalErrorMessageHandler;
const char* Nu_StrError(NuError err);
void Nu_ReportError(NuArchive* pArchive, const char* file, int line,
const char* function, Boolean isDebug, NuError err, const char* format, ...)
#if defined(__GNUC__)
__attribute__ ((format(printf, 7, 8)))
#endif
;
#ifdef USE_DMALLOC /* want file and line numbers for calls */
# define Nu_Malloc(archive, size) malloc(size)
# define Nu_Calloc(archive, size) calloc(1, size)
# define Nu_Realloc(archive, ptr, size) realloc(ptr, size)
# define Nu_Free(archive, ptr) (ptr != nil ? free(ptr) : (void)0)
#else
void* Nu_Malloc(NuArchive* pArchive, size_t size);
void* Nu_Calloc(NuArchive* pArchive, size_t size);
void* Nu_Realloc(NuArchive* pArchive, void* ptr, size_t size);
void Nu_Free(NuArchive* pArchive, void* ptr);
#endif
NuResult Nu_InternalFreeCallback(NuArchive* pArchive, void* args);
/* Record.c */
void Nu_RecordAddThreadMod(NuRecord* pRecord, NuThreadMod* pThreadMod);
Boolean Nu_RecordIsEmpty(NuArchive* pArchive, const NuRecord* pRecord);
Boolean Nu_RecordSet_GetLoaded(const NuRecordSet* pRecordSet);
ulong Nu_RecordSet_GetNumRecords(const NuRecordSet* pRecordSet);
void Nu_RecordSet_SetNumRecords(NuRecordSet* pRecordSet, ulong val);
void Nu_RecordSet_IncNumRecords(NuRecordSet* pRecordSet);
NuRecord* Nu_RecordSet_GetListHead(const NuRecordSet* pRecordSet);
NuRecord** Nu_RecordSet_GetListHeadPtr(NuRecordSet* pRecordSet);
NuRecord* Nu_RecordSet_GetListTail(const NuRecordSet* pRecordSet);
Boolean Nu_RecordSet_IsEmpty(const NuRecordSet* pRecordSet);
NuError Nu_RecordSet_FreeAllRecords(NuArchive* pArchive,
NuRecordSet* pRecordSet);
NuError Nu_RecordSet_DeleteRecordPtr(NuArchive* pArchive,
NuRecordSet* pRecordSet, NuRecord** ppRecord);
NuError Nu_RecordSet_DeleteRecord(NuArchive* pArchive, NuRecordSet* pRecordSet,
NuRecord* pRecord);
NuError Nu_RecordSet_Clone(NuArchive* pArchive, NuRecordSet* pDstSet,
const NuRecordSet* pSrcSet);
NuError Nu_RecordSet_MoveAllRecords(NuArchive* pArchive, NuRecordSet* pDstSet,
NuRecordSet* pSrcSet);
NuError Nu_RecordSet_FindByIdx(const NuRecordSet* pRecordSet, NuRecordIdx rec,
NuRecord** ppRecord);
NuError Nu_RecordSet_FindByThreadIdx(NuRecordSet* pRecordSet,
NuThreadIdx threadIdx, NuRecord** ppRecord, NuThread** ppThread);
NuError Nu_RecordSet_ReplaceRecord(NuArchive* pArchive, NuRecordSet* pBadSet,
NuRecord* pBadRecord, NuRecordSet* pGoodSet, NuRecord** ppGoodRecord);
Boolean Nu_ShouldIgnoreBadCRC(NuArchive* pArchive, const NuRecord* pRecord,
NuError err);
NuError Nu_WriteRecordHeader(NuArchive* pArchive, NuRecord* pRecord, FILE* fp);
NuError Nu_GetTOCIfNeeded(NuArchive* pArchive);
NuError Nu_StreamContents(NuArchive* pArchive, NuCallback contentFunc);
NuError Nu_StreamExtract(NuArchive* pArchive);
NuError Nu_StreamTest(NuArchive* pArchive);
NuError Nu_Contents(NuArchive* pArchive, NuCallback contentFunc);
NuError Nu_Extract(NuArchive* pArchive);
NuError Nu_ExtractRecord(NuArchive* pArchive, NuRecordIdx recIdx);
NuError Nu_Test(NuArchive* pArchive);
NuError Nu_TestRecord(NuArchive* pArchive, NuRecordIdx recIdx);
NuError Nu_GetRecord(NuArchive* pArchive, NuRecordIdx recordIdx,
const NuRecord** ppRecord);
NuError Nu_GetRecordIdxByName(NuArchive* pArchive, const char* name,
NuRecordIdx* pRecordIdx);
NuError Nu_GetRecordIdxByPosition(NuArchive* pArchive, ulong position,
NuRecordIdx* pRecordIdx);
NuError Nu_FindRecordForWriteByIdx(NuArchive* pArchive, NuRecordIdx recIdx,
NuRecord** ppFoundRecord);
NuError Nu_AddFile(NuArchive* pArchive, const char* pathname,
const NuFileDetails* pFileDetails, Boolean fromRsrcFork,
NuRecordIdx* pRecordIdx);
NuError Nu_AddRecord(NuArchive* pArchive, const NuFileDetails* pFileDetails,
NuRecordIdx* pRecordIdx, NuRecord** ppRecord);
NuError Nu_Rename(NuArchive* pArchive, NuRecordIdx recIdx,
const char* pathname, char fssep);
NuError Nu_SetRecordAttr(NuArchive* pArchive, NuRecordIdx recordIdx,
const NuRecordAttr* pRecordAttr);
NuError Nu_Delete(NuArchive* pArchive);
NuError Nu_DeleteRecord(NuArchive* pArchive, NuRecordIdx rec);
/* SourceSink.c */
NuError Nu_DataSourceFile_New(NuThreadFormat threadFormat,
ulong otherLen, const char* pathname, Boolean isFromRsrcFork,
NuDataSource** ppDataSource);
NuError Nu_DataSourceFP_New(NuThreadFormat threadFormat,
ulong otherLen, FILE* fp, long offset, long length,
NuCallback fcloseFunc, NuDataSource** ppDataSource);
NuError Nu_DataSourceBuffer_New(NuThreadFormat threadFormat,
ulong otherLen, const uchar* buffer, long offset, long length,
NuCallback freeFunc, NuDataSource** ppDataSource);
NuDataSource* Nu_DataSourceCopy(NuDataSource* pDataSource);
NuError Nu_DataSourceFree(NuDataSource* pDataSource);
NuDataSourceType Nu_DataSourceGetType(const NuDataSource* pDataSource);
NuThreadFormat Nu_DataSourceGetThreadFormat(const NuDataSource* pDataSource);
ulong Nu_DataSourceGetDataLen(const NuDataSource* pDataSource);
ulong Nu_DataSourceGetOtherLen(const NuDataSource* pDataSource);
void Nu_DataSourceSetOtherLen(NuDataSource* pDataSource, long otherLen);
ushort Nu_DataSourceGetRawCrc(const NuDataSource* pDataSource);
void Nu_DataSourceSetRawCrc(NuDataSource* pDataSource, ushort crc);
NuError Nu_DataSourcePrepareInput(NuArchive* pArchive,
NuDataSource* pDataSource);
void Nu_DataSourceUnPrepareInput(NuArchive* pArchive,
NuDataSource* pDataSource);
const char* Nu_DataSourceFile_GetPathname(NuDataSource* pDataSource);
NuError Nu_DataSourceGetBlock(NuDataSource* pDataSource, uchar* buf, ulong len);
NuError Nu_DataSourceRewind(NuDataSource* pDataSource);
NuError Nu_DataSinkFile_New(Boolean doExpand, NuValue convertEOL,
const char* pathname, char fssep, NuDataSink** ppDataSink);
NuError Nu_DataSinkFP_New(Boolean doExpand, NuValue convertEOL, FILE* fp,
NuDataSink** ppDataSink);
NuError Nu_DataSinkBuffer_New(Boolean doExpand, NuValue convertEOL,
uchar* buffer, ulong bufLen, NuDataSink** ppDataSink);
NuError Nu_DataSinkVoid_New(Boolean doExpand, NuValue convertEOL,
NuDataSink** ppDataSink);
NuError Nu_DataSinkFree(NuDataSink* pDataSink);
NuDataSinkType Nu_DataSinkGetType(const NuDataSink* pDataSink);
Boolean Nu_DataSinkGetDoExpand(const NuDataSink* pDataSink);
NuValue Nu_DataSinkGetConvertEOL(const NuDataSink* pDataSink);
ulong Nu_DataSinkGetOutCount(const NuDataSink* pDataSink);
const char* Nu_DataSinkFile_GetPathname(const NuDataSink* pDataSink);
char Nu_DataSinkFile_GetFssep(const NuDataSink* pDataSink);
FILE* Nu_DataSinkFile_GetFP(const NuDataSink* pDataSink);
void Nu_DataSinkFile_SetFP(NuDataSink* pDataSink, FILE* fp);
void Nu_DataSinkFile_Close(NuDataSink* pDataSink);
NuError Nu_DataSinkPutBlock(NuDataSink* pDataSink, const uchar* buf, ulong len);
NuError Nu_DataSinkGetError(NuDataSink* pDataSink);
/* Squeeze.c */
NuError Nu_CompressHuffmanSQ(NuArchive* pArchive, NuStraw* pStraw, FILE* fp,
ulong srcLen, ulong* pDstLen, ushort* pCrc);
NuError Nu_ExpandHuffmanSQ(NuArchive* pArchive, const NuRecord* pRecord,
const NuThread* pThread, FILE* infp, NuFunnel* pFunnel, ushort* pCrc);
/* Thread.c */
#ifdef __Thread_c__
#define THREAD_INLINE /**/
#else
#define THREAD_INLINE extern inline
#endif
#if defined(inline) && !defined(__Thread_c__) /* somebody ovrd inline def? */
NuThread* Nu_GetThread(const NuRecord* pRecord, int idx);
#else
THREAD_INLINE NuThread*
Nu_GetThread(const NuRecord* pRecord, int idx)
{
if (idx >= (int)pRecord->recTotalThreads)
return nil;
else
return &pRecord->pThreads[idx];
}
#endif
void Nu_StripHiIfAllSet(char* str);
Boolean Nu_IsPresizedThreadID(NuThreadID threadID);
Boolean Nu_IsCompressibleThreadID(NuThreadID threadID);
Boolean Nu_ThreadHasCRC(long recordVersion, NuThreadID threadID);
NuError Nu_FindThreadByIdx(const NuRecord* pRecord, NuThreadIdx thread,
NuThread** ppThread);
NuError Nu_FindThreadByID(const NuRecord* pRecord, NuThreadID threadID,
NuThread** ppThread);
void Nu_CopyThreadContents(NuThread* pDstThread, const NuThread* pSrcThread);
NuError Nu_ReadThreadHeaders(NuArchive* pArchive, NuRecord* pRecord,
ushort* pCrc);
NuError Nu_WriteThreadHeaders(NuArchive* pArchive, NuRecord* pRecord, FILE* fp,
ushort* pCrc);
NuError Nu_ComputeThreadData(NuArchive* pArchive, NuRecord* pRecord);
NuError Nu_ScanThreads(NuArchive* pArchive, NuRecord* pRecord,long numThreads);
NuError Nu_ExtractThreadBulk(NuArchive* pArchive, const NuRecord* pRecord,
const NuThread* pThread);
NuError Nu_SkipThread(NuArchive* pArchive, const NuRecord* pRecord,
const NuThread* pThread);
NuError Nu_ExtractThread(NuArchive* pArchive, NuThreadIdx threadIdx,
NuDataSink* pDataSink);
NuError Nu_OkayToAddThread(NuArchive* pArchive, const NuRecord* pRecord,
NuThreadID threadID);
NuError Nu_AddThread(NuArchive* pArchive, NuRecordIdx rec, NuThreadID threadID,
NuDataSource* pDataSource, NuThreadIdx* pThreadIdx);
NuError Nu_UpdatePresizedThread(NuArchive* pArchive, NuThreadIdx threadIdx,
NuDataSource* pDataSource, long* pMaxLen);
NuError Nu_DeleteThread(NuArchive* pArchive, NuThreadIdx threadIdx);
/* Value.c */
NuError Nu_GetValue(NuArchive* pArchive, NuValueID ident, NuValue* pValue);
NuError Nu_SetValue(NuArchive* pArchive, NuValueID ident, NuValue value);
NuError Nu_GetAttr(NuArchive* pArchive, NuAttrID ident, NuAttr* pAttr);
NuThreadFormat Nu_ConvertCompressValToFormat(NuArchive* pArchive,
NuValue compValue);
/* Version.c */
NuError Nu_GetVersion(long* pMajorVersion, long* pMinorVersion,
long* pBugVersion, const char** ppBuildDate, const char** ppBuildFlags);
#endif /*__NufxLibPriv__*/