diff --git a/nufxlib-0/ChangeLog.txt b/nufxlib-0/ChangeLog.txt index a580d59..0ed372f 100644 --- a/nufxlib-0/ChangeLog.txt +++ b/nufxlib-0/ChangeLog.txt @@ -1,3 +1,12 @@ +2003/02/08 fadden + - Upped version to v2.0.0. + - Changed DataSource API. Removed "doClose" and added an optional + callback function that handles releasing of resources. Necessary + to make Win32 DLLs work right with unsuspecting apps. + - Changed DataSource "copy" function to use refcounting. Still + not quite right, but it'll do for now. Memory leaks in DataSource + handling appear to be fixed. (I love valgrind.) + 2003/01/10 fadden - Added version numbers to header. - Added kNuValueMaskThreadless to control handling of "threadless" @@ -5,7 +14,7 @@ the application does need to handle them specially. 2002/12/06 fadden - - Made changes to allow NufxLib to be built as a DLL. + - Made changes to allow NufxLib to be built as a Win32 DLL. 2002/10/20 ***** v1.1.0 shipped ***** diff --git a/nufxlib-0/Deferred.c b/nufxlib-0/Deferred.c index 37b01bf..74a5d76 100644 --- a/nufxlib-0/Deferred.c +++ b/nufxlib-0/Deferred.c @@ -39,7 +39,7 @@ Nu_ThreadModAdd_New(NuArchive* pArchive, NuThreadID threadID, (*ppThreadMod)->entry.add.threadIdx = Nu_GetNextThreadIdx(pArchive); (*ppThreadMod)->entry.add.threadID = threadID; (*ppThreadMod)->entry.add.threadFormat = threadFormat; - (*ppThreadMod)->entry.add.pDataSource = pDataSource; + (*ppThreadMod)->entry.add.pDataSource = Nu_DataSourceCopy(pDataSource); /* decide if this is a pre-sized thread [do we want to do this here??] */ (*ppThreadMod)->entry.add.isPresized = Nu_IsPresizedThreadID(threadID); @@ -1302,14 +1302,15 @@ Nu_ConstructNewRecord(NuArchive* pArchive, NuRecord* pRecord, FILE* fp) len = strlen(pRecord->filename); maxLen = len > kNuDefaultFilenameThreadSize ? len : kNuDefaultFilenameThreadSize; - err = Nu_DataSourceBuffer_New(kNuThreadFormatUncompressed, false, + err = Nu_DataSourceBuffer_New(kNuThreadFormatUncompressed, maxLen, (const uchar*)pRecord->filename, 0, - strlen(pRecord->filename), &pTmpDataSource); + strlen(pRecord->filename), nil, &pTmpDataSource); BailError(err); - /* put in a new "add" threadMod */ + /* put in a new "add" threadMod (which copies the data source) */ err = Nu_ThreadModAdd_New(pArchive, kNuThreadIDFilename, kNuThreadFormatUncompressed, pTmpDataSource, &pNewThreadMod); + Nu_DataSourceFree(pTmpDataSource); BailError(err); /* add it to the list */ @@ -2060,8 +2061,8 @@ Nu_AddCommentToFirstNewRecord(NuArchive* pArchive) err = kNuErrNone; /* create a new data source with nothing in it */ - err = Nu_DataSourceBuffer_New(kNuThreadFormatUncompressed, false, - kNuDefaultCommentSize, nil, 0, 0, &pDataSource); + err = Nu_DataSourceBuffer_New(kNuThreadFormatUncompressed, + kNuDefaultCommentSize, nil, 0, 0, nil, &pDataSource); BailError(err); Assert(pDataSource != nil); @@ -2070,7 +2071,7 @@ Nu_AddCommentToFirstNewRecord(NuArchive* pArchive) kNuThreadFormatUncompressed, pDataSource, &pThreadMod); BailError(err); Assert(pThreadMod != nil); - pDataSource = nil; /* don't free on exit */ + /*pDataSource = nil;*/ /* ThreadModAdd_New makes a copy */ /* add the thread mod to the record */ Nu_RecordAddThreadMod(pRecord, pThreadMod); @@ -2479,10 +2480,13 @@ bail: * we are able to do so. This retains any BXY/BSE wrapper padding. */ if (!writeToTemp) { - err = Nu_TruncateOpenFile(pArchive->archiveFp, initialEOF); - if (err == kNuErrNone) { - DBUG(("+++ truncating orig archive back to %ld\n", + NuError err2; + err2 = Nu_TruncateOpenFile(pArchive->archiveFp, initialEOF); + if (err2 == kNuErrNone) { + DBUG(("+++ truncated orig archive back to %ld\n", initialEOF)); + } else { + DBUG(("+++ truncate orig failed (err=%d)\n", err2)); } } } else { diff --git a/nufxlib-0/Entry.c b/nufxlib-0/Entry.c index 168cd3d..c471306 100644 --- a/nufxlib-0/Entry.c +++ b/nufxlib-0/Entry.c @@ -555,30 +555,30 @@ NuDebugDumpArchive(NuArchive* pArchive) */ NUFXLIB_API NuError -NuCreateDataSourceForFile(NuThreadFormat threadFormat, short doClose, +NuCreateDataSourceForFile(NuThreadFormat threadFormat, unsigned long otherLen, const char* pathname, short isFromRsrcFork, NuDataSource** ppDataSource) { - return Nu_DataSourceFile_New(threadFormat, (Boolean)(doClose != 0), - otherLen, pathname, (Boolean)(isFromRsrcFork != 0), ppDataSource); + return Nu_DataSourceFile_New(threadFormat, otherLen, + pathname, (Boolean)(isFromRsrcFork != 0), ppDataSource); } NUFXLIB_API NuError -NuCreateDataSourceForFP(NuThreadFormat threadFormat, short doClose, +NuCreateDataSourceForFP(NuThreadFormat threadFormat, unsigned long otherLen, FILE* fp, long offset, long length, - NuDataSource** ppDataSource) + NuCallback fcloseFunc, NuDataSource** ppDataSource) { - return Nu_DataSourceFP_New(threadFormat, (Boolean)(doClose != 0), - otherLen, fp, offset, length, ppDataSource); + return Nu_DataSourceFP_New(threadFormat, otherLen, + fp, offset, length, fcloseFunc, ppDataSource); } NUFXLIB_API NuError -NuCreateDataSourceForBuffer(NuThreadFormat threadFormat, short doClose, +NuCreateDataSourceForBuffer(NuThreadFormat threadFormat, unsigned long otherLen, const unsigned char* buffer, long offset, - long length, NuDataSource** ppDataSource) + long length, NuCallback freeFunc, NuDataSource** ppDataSource) { - return Nu_DataSourceBuffer_New(threadFormat, (Boolean)(doClose != 0), - otherLen, buffer, offset, length, ppDataSource); + return Nu_DataSourceBuffer_New(threadFormat, otherLen, + buffer, offset, length, freeFunc, ppDataSource); } NUFXLIB_API NuError diff --git a/nufxlib-0/MiscUtils.c b/nufxlib-0/MiscUtils.c index fe9b8af..6fdba7d 100644 --- a/nufxlib-0/MiscUtils.c +++ b/nufxlib-0/MiscUtils.c @@ -366,3 +366,15 @@ Nu_Free(NuArchive* pArchive, void* ptr) } #endif +/* + * If somebody internal wants to set doClose on a buffer DataSource + * (looks like "Rename" does), we need to supply a "free" callback. + */ +NuResult +Nu_InternalFreeCallback(NuArchive* pArchive, void* args) +{ + DBUG(("+++ internal free callback 0x%08lx\n", (long) args)); + Nu_Free(nil, args); + return kNuOK; +} + diff --git a/nufxlib-0/NufxLib.h b/nufxlib-0/NufxLib.h index 9a23a59..105e318 100644 --- a/nufxlib-0/NufxLib.h +++ b/nufxlib-0/NufxLib.h @@ -760,14 +760,14 @@ NUFXLIB_API NuError NuDebugDumpArchive(NuArchive* pArchive); /* sources and sinks */ NUFXLIB_API NuError NuCreateDataSourceForFile(NuThreadFormat threadFormat, - short doClose, unsigned long otherLen, const char* pathname, + unsigned long otherLen, const char* pathname, short isFromRsrcFork, NuDataSource** ppDataSource); NUFXLIB_API NuError NuCreateDataSourceForFP(NuThreadFormat threadFormat, - short doClose, unsigned long otherLen, FILE* fp, long offset, - long length, NuDataSource** ppDataSource); + unsigned long otherLen, FILE* fp, long offset, long length, + NuCallback closeFunc, NuDataSource** ppDataSource); NUFXLIB_API NuError NuCreateDataSourceForBuffer(NuThreadFormat threadFormat, - short doClose, unsigned long otherLen, const unsigned char* buffer, - long offset, long length, NuDataSource** ppDataSource); + unsigned long otherLen, const unsigned char* buffer, long offset, + long length, NuCallback freeFunc, NuDataSource** ppDataSource); NUFXLIB_API NuError NuFreeDataSource(NuDataSource* pDataSource); NUFXLIB_API NuError NuDataSourceSetRawCrc(NuDataSource* pDataSource, unsigned short crc); @@ -809,6 +809,7 @@ NUFXLIB_API NuError NuSetOutputPathnameFilter(NuArchive* pArchive, NuCallback filterFunc); NUFXLIB_API NuError NuSetProgressUpdater(NuArchive* pArchive, NuCallback updateFunc); +NUFXLIB_API NuError NuSetFreeHandler(NuArchive* pArchive, NuCallback freeFunc); NUFXLIB_API NuError NuSetErrorHandler(NuArchive* pArchive,NuCallback errorFunc); NUFXLIB_API NuError NuSetErrorMessageHandler(NuArchive* pArchive, NuCallback messageHandlerFunc); diff --git a/nufxlib-0/NufxLibPriv.h b/nufxlib-0/NufxLibPriv.h index 342105f..c610a20 100644 --- a/nufxlib-0/NufxLibPriv.h +++ b/nufxlib-0/NufxLibPriv.h @@ -319,9 +319,10 @@ typedef struct NuDataSourceCommon { NuDataSourceType sourceType; NuThreadFormat threadFormat; /* is it already compressed? */ ushort rawCrc; /* crc for already-compressed data*/ - Boolean doClose; /* close on completion? */ + /*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 { @@ -342,6 +343,8 @@ union NuDataSource { NuDataSourceCommon common; FILE* fp; long offset; /* starting offset */ + + NuCallback fcloseFunc; /* how to fclose the file */ } fromFP; struct { @@ -351,6 +354,8 @@ union NuDataSource { long curOffset; /* current offset */ long curDataLen; /* remaining data */ + + NuCallback freeFunc; /* how to free data */ } fromBuffer; }; @@ -679,6 +684,7 @@ 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); @@ -739,15 +745,15 @@ NuError Nu_Delete(NuArchive* pArchive); NuError Nu_DeleteRecord(NuArchive* pArchive, NuRecordIdx rec); /* SourceSink.c */ -NuError Nu_DataSourceFile_New(NuThreadFormat threadFormat, Boolean doClose, +NuError Nu_DataSourceFile_New(NuThreadFormat threadFormat, ulong otherLen, const char* pathname, Boolean isFromRsrcFork, NuDataSource** ppDataSource); -NuError Nu_DataSourceFP_New(NuThreadFormat threadFormat, Boolean doClose, +NuError Nu_DataSourceFP_New(NuThreadFormat threadFormat, ulong otherLen, FILE* fp, long offset, long length, - NuDataSource** ppDataSource); + NuCallback fcloseFunc, NuDataSource** ppDataSource); NuError Nu_DataSourceBuffer_New(NuThreadFormat threadFormat, - Boolean doClose, ulong otherLen, const uchar* buffer, long offset, - long length, NuDataSource** ppDataSource); + 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); diff --git a/nufxlib-0/Record.c b/nufxlib-0/Record.c index b7a92bd..0d49e1a 100644 --- a/nufxlib-0/Record.c +++ b/nufxlib-0/Record.c @@ -2301,7 +2301,7 @@ Nu_AddFileThreadMod(NuArchive* pArchive, NuRecord* pRecord, threadFormat = kNuThreadFormatUncompressed; /* create a data source for this file, which is assumed uncompressed */ - err = Nu_DataSourceFile_New(kNuThreadFormatUncompressed, false, 0, + err = Nu_DataSourceFile_New(kNuThreadFormatUncompressed, 0, pathname, fromRsrcFork, &pDataSource); BailError(err); @@ -2310,7 +2310,7 @@ Nu_AddFileThreadMod(NuArchive* pArchive, NuRecord* pRecord, pDataSource, &pThreadMod); BailError(err); Assert(pThreadMod != nil); - pDataSource = nil; /* don't free on exit */ + /*pDataSource = nil;*/ /* ThreadModAdd_New makes a copy */ /* add the thread mod to the record */ Nu_RecordAddThreadMod(pRecord, pThreadMod); @@ -2552,9 +2552,10 @@ Nu_Rename(NuArchive* pArchive, NuRecordIdx recIdx, const char* pathname, /* create a data source for the filename, if needed */ if (doAdd || doUpdate) { Assert(newCapacity); - err = Nu_DataSourceBuffer_New(kNuThreadFormatUncompressed, true, + err = Nu_DataSourceBuffer_New(kNuThreadFormatUncompressed, newCapacity, (const uchar*)strdup(pathname), 0, - requiredCapacity /*(strlen)*/, &pDataSource); + requiredCapacity /*(strlen)*/, Nu_InternalFreeCallback, + &pDataSource); BailError(err); } @@ -2570,7 +2571,7 @@ Nu_Rename(NuArchive* pArchive, NuRecordIdx recIdx, const char* pathname, err = Nu_ThreadModAdd_New(pArchive, kNuThreadIDFilename, kNuThreadFormatUncompressed, pDataSource, &pNewThreadMod); BailError(err); - pDataSource = nil; /* successful, don't free */ + /*pDataSource = nil;*/ /* ThreadModAdd_New makes a copy */ Nu_RecordAddThreadMod(pRecord, pNewThreadMod); pNewThreadMod = nil; /* successful, don't free */ } @@ -2579,7 +2580,7 @@ Nu_Rename(NuArchive* pArchive, NuRecordIdx recIdx, const char* pathname, err = Nu_ThreadModUpdate_New(pArchive, pFilenameThread->threadIdx, pDataSource, &pNewThreadMod); BailError(err); - pDataSource = nil; /* successful, don't free */ + /*pDataSource = nil;*/ /* ThreadModAdd_New makes a copy */ Nu_RecordAddThreadMod(pRecord, pNewThreadMod); pNewThreadMod = nil; /* successful, don't free */ } diff --git a/nufxlib-0/SourceSink.c b/nufxlib-0/SourceSink.c index e49acf9..b210e15 100644 --- a/nufxlib-0/SourceSink.c +++ b/nufxlib-0/SourceSink.c @@ -35,18 +35,28 @@ Nu_DataSourceNew(NuDataSource** ppDataSource) /* - * Make a copy of a DataSource. + * Make a copy of a DataSource. Actually just increments a reference count. * - * IMPORTANT: if the original had the "doClose" flag set, it will be cleared, - * but left set in the duplicate. The assumption is that the original will - * be thrown out before the duplicate. If this isn't the case, you will - * need to fix the flags on the copied data. + * What we *really* want to be doing is copying the structure (since we + * can't guarantee copy-on-write semantics for the fields without adding + * more stuff) and refcounting the underlying resource, so that "auto-free" + * semantics work out right. + * + * We're okay for now, since for the most part we only do work on one + * copy of each. (I wish I could remember why this copying thing was + * needed in the first place.) Buffer sources are a little scary since + * they include a "curOffset" value. * * Returns nil on error. */ NuDataSource* Nu_DataSourceCopy(NuDataSource* pDataSource) { + Assert(pDataSource->common.refCount >= 1); + pDataSource->common.refCount++; + return pDataSource; + +#if 0 /* we used to copy them -- very bad idea */ NuDataSource* pNewDataSource; Assert(pDataSource != nil); @@ -72,6 +82,7 @@ Nu_DataSourceCopy(NuDataSource* pDataSource) } return pNewDataSource; +#endif } @@ -84,6 +95,12 @@ Nu_DataSourceFree(NuDataSource* pDataSource) if (pDataSource == nil) return kNuErrNone; + Assert(pDataSource->common.refCount > 0); + if (pDataSource->common.refCount > 1) { + pDataSource->common.refCount--; + return kNuErrNone; + } + switch (pDataSource->sourceType) { case kNuDataSourceFromFile: Nu_Free(nil, pDataSource->fromFile.pathname); @@ -93,14 +110,17 @@ Nu_DataSourceFree(NuDataSource* pDataSource) } break; case kNuDataSourceFromFP: - if (pDataSource->common.doClose) { - fclose(pDataSource->fromFile.fp); - pDataSource->fromFile.fp = nil; + if (pDataSource->fromFP.fcloseFunc != nil && + pDataSource->fromFP.fp != nil) + { + (*pDataSource->fromFP.fcloseFunc)(nil, pDataSource->fromFP.fp); + pDataSource->fromFP.fp = nil; } break; case kNuDataSourceFromBuffer: - if (pDataSource->common.doClose) { - Nu_Free(nil, (char*)pDataSource->fromBuffer.buffer); + if (pDataSource->fromBuffer.freeFunc != nil) { + (*pDataSource->fromBuffer.freeFunc)(nil, + (void*)pDataSource->fromBuffer.buffer); pDataSource->fromBuffer.buffer = nil; } break; @@ -120,14 +140,12 @@ Nu_DataSourceFree(NuDataSource* pDataSource) * Create a data source for an unopened file. */ NuError -Nu_DataSourceFile_New(NuThreadFormat threadFormat, Boolean doClose, - ulong otherLen, const char* pathname, Boolean isFromRsrcFork, - NuDataSource** ppDataSource) +Nu_DataSourceFile_New(NuThreadFormat threadFormat, ulong otherLen, + const char* pathname, Boolean isFromRsrcFork, NuDataSource** ppDataSource) { NuError err; - if (!(doClose == true || doClose == false) || - pathname == nil || + if (pathname == nil || !(isFromRsrcFork == true || isFromRsrcFork == false) || ppDataSource == nil) { @@ -139,12 +157,13 @@ Nu_DataSourceFile_New(NuThreadFormat threadFormat, Boolean doClose, (*ppDataSource)->common.sourceType = kNuDataSourceFromFile; (*ppDataSource)->common.threadFormat = threadFormat; - (*ppDataSource)->common.doClose = doClose; + (*ppDataSource)->common.rawCrc = 0; + (*ppDataSource)->common.dataLen = 0; /* to be filled in later */ (*ppDataSource)->common.otherLen = otherLen; + (*ppDataSource)->common.refCount = 1; + (*ppDataSource)->fromFile.pathname = strdup(pathname); (*ppDataSource)->fromFile.fromRsrcFork = isFromRsrcFork; - - (*ppDataSource)->common.dataLen = 0; /* to be filled in later */ (*ppDataSource)->fromFile.fp = nil; /* to be filled in later */ bail: @@ -157,14 +176,13 @@ bail: * must be seekable. */ NuError -Nu_DataSourceFP_New(NuThreadFormat threadFormat, Boolean doClose, - ulong otherLen, FILE* fp, long offset, long length, +Nu_DataSourceFP_New(NuThreadFormat threadFormat, ulong otherLen, + FILE* fp, long offset, long length, NuCallback fcloseFunc, NuDataSource** ppDataSource) { NuError err; - if (!(doClose == true || doClose == false) || - fp == nil || offset < 0 || length < 0 || + if (fp == nil || offset < 0 || length < 0 || ppDataSource == nil) { return kNuErrInvalidArg; @@ -181,11 +199,14 @@ Nu_DataSourceFP_New(NuThreadFormat threadFormat, Boolean doClose, (*ppDataSource)->common.sourceType = kNuDataSourceFromFP; (*ppDataSource)->common.threadFormat = threadFormat; - (*ppDataSource)->common.doClose = doClose; + (*ppDataSource)->common.rawCrc = 0; (*ppDataSource)->common.dataLen = length; (*ppDataSource)->common.otherLen = otherLen; + (*ppDataSource)->common.refCount = 1; + (*ppDataSource)->fromFP.fp = fp; (*ppDataSource)->fromFP.offset = offset; + (*ppDataSource)->fromFP.fcloseFunc = fcloseFunc; bail: return err; @@ -200,23 +221,21 @@ bail: * blank comment fields. */ NuError -Nu_DataSourceBuffer_New(NuThreadFormat threadFormat, Boolean doClose, - ulong otherLen, const uchar* buffer, long offset, long length, +Nu_DataSourceBuffer_New(NuThreadFormat threadFormat, ulong otherLen, + const uchar* buffer, long offset, long length, NuCallback freeFunc, NuDataSource** ppDataSource) { NuError err; - if (!(doClose == true || doClose == false) || - offset < 0 || length < 0 || ppDataSource == nil) - { + if (offset < 0 || length < 0 || ppDataSource == nil) return kNuErrInvalidArg; - } if (buffer == nil && (offset != 0 || length != 0)) - { return kNuErrInvalidArg; + + if (buffer == nil) { + DBUG(("+++ zeroing freeFunc for empty-buffer DataSource\n")); + freeFunc = nil; } - if (buffer == nil) - doClose = false; if (otherLen && otherLen < (ulong)length) { DBUG(("--- rejecting buffer len=%ld other=%ld\n", length, otherLen)); @@ -229,14 +248,16 @@ Nu_DataSourceBuffer_New(NuThreadFormat threadFormat, Boolean doClose, (*ppDataSource)->common.sourceType = kNuDataSourceFromBuffer; (*ppDataSource)->common.threadFormat = threadFormat; - (*ppDataSource)->common.doClose = doClose; + (*ppDataSource)->common.rawCrc = 0; (*ppDataSource)->common.dataLen = length; (*ppDataSource)->common.otherLen = otherLen; + (*ppDataSource)->common.refCount = 1; + (*ppDataSource)->fromBuffer.buffer = buffer; (*ppDataSource)->fromBuffer.offset = offset; - (*ppDataSource)->fromBuffer.curOffset = offset; (*ppDataSource)->fromBuffer.curDataLen = length; + (*ppDataSource)->fromBuffer.freeFunc = freeFunc; bail: return err; diff --git a/nufxlib-0/Thread.c b/nufxlib-0/Thread.c index 14c5f00..6c0366c 100644 --- a/nufxlib-0/Thread.c +++ b/nufxlib-0/Thread.c @@ -1126,7 +1126,7 @@ Nu_AddThread(NuArchive* pArchive, NuRecordIdx recIdx, NuThreadID threadID, } DBUG(("--- using threadFormat = %d\n", threadFormat)); - /* create a new ThreadMod */ + /* create a new ThreadMod (which makes a copy of the data source) */ err = Nu_ThreadModAdd_New(pArchive, threadID, threadFormat, pDataSource, &pThreadMod); BailError(err); @@ -1151,6 +1151,11 @@ Nu_AddThread(NuArchive* pArchive, NuRecordIdx recIdx, NuThreadID threadID, bail: if (pThreadMod != nil) Nu_ThreadModFree(pArchive, pThreadMod); + if (err == kNuErrNone && pDataSource != nil) { + /* on success, we have ownership of the data source. ThreadMod + made its own copy, so get rid of this one */ + Nu_DataSourceFree(pDataSource); + } return err; } diff --git a/nufxlib-0/samples/Exerciser.c b/nufxlib-0/samples/Exerciser.c index 5a70312..88eaeb3 100644 --- a/nufxlib-0/samples/Exerciser.c +++ b/nufxlib-0/samples/Exerciser.c @@ -300,6 +300,15 @@ ErrorHandler(NuArchive* pArchive, void* vErrorStatus) return result; } +/* + * This gets called when a buffer DataSource is no longer needed. + */ +NuResult +FreeCallback(NuArchive* pArchive, void* args) +{ + free(args); +} + /* * =========================================================================== @@ -448,7 +457,7 @@ AddThreadFunc(ExerciserState* pState, int argc, char** argv) } err = NuCreateDataSourceForFile(kNuThreadFormatUncompressed, - true, 0, lineBuf, false, &pDataSource); + 0, lineBuf, false, &pDataSource); if (err != kNuErrNone) { fprintf(stderr, "Exerciser: file data source create failed (err=%d)\n", err); @@ -477,7 +486,8 @@ AddThreadFunc(ExerciserState* pState, int argc, char** argv) /* create a data source from the buffer */ err = NuCreateDataSourceForBuffer(kNuThreadFormatUncompressed, - true, maxLen, (unsigned char*)lineBuf, 0, ourLen, &pDataSource); + maxLen, (unsigned char*)lineBuf, 0, ourLen, FreeCallback, + &pDataSource); if (err != kNuErrNone) { fprintf(stderr, "Exerciser: buffer data source create failed (err=%d)\n", err); @@ -1004,7 +1014,8 @@ UpdatePresizedThreadFunc(ExerciserState* pState, int argc, char** argv) /* use "ourLen" for both buffer len and data len */ err = NuCreateDataSourceForBuffer(kNuThreadFormatUncompressed, - true, ourLen, (unsigned char*)lineBuf, 0, ourLen, &pDataSource); + ourLen, (unsigned char*)lineBuf, 0, ourLen, FreeCallback, + &pDataSource); if (err != kNuErrNone) { fprintf(stderr, "Exerciser: data source create failed (err=%d)\n", err); @@ -1303,7 +1314,7 @@ CommandLoop(void) } if (pState != nil) - free(pState); + ExerciserState_Free(pState); if (argv != nil) free(argv); return kNuErrNone; diff --git a/nufxlib-0/samples/ImgConv.c b/nufxlib-0/samples/ImgConv.c index 95fb387..359f4d5 100644 --- a/nufxlib-0/samples/ImgConv.c +++ b/nufxlib-0/samples/ImgConv.c @@ -212,16 +212,38 @@ DumpImgHeader(ImgHeader* pHeader) typedef enum ArchiveKind { kKindUnknown, kKindShk, kKindImg } ArchiveKind; +/* + * This gets called when a buffer DataSource is no longer needed. + */ +NuResult +FreeCallback(NuArchive* pArchive, void* args) +{ + free(args); +} + +/* + * This gets called when an "FP" DataSource is no longer needed. + */ +NuResult +FcloseCallback(NuArchive* pArchive, void* args) +{ + fclose((FILE*) args); +} + /* * Create a data source for a ProDOS-ordered image. Since this is already * in the correct format, we just point at the correct offset in the 2MG file. + * + * This supplies an FcloseCallback so that we can exercise that feature + * of NufxLib. We could just as easily not set it and call fclose() + * ourselves, because the structure of this program is pretty simple. */ NuError CreateProdosSource(const ImgHeader* pHeader, FILE* fp, NuDataSource** ppDataSource) { - return NuCreateDataSourceForFP(kNuThreadFormatUncompressed, false, 0, fp, - pHeader->dataOffset, pHeader->dataLen, ppDataSource); + return NuCreateDataSourceForFP(kNuThreadFormatUncompressed, 0, fp, + pHeader->dataOffset, pHeader->dataLen, FcloseCallback,ppDataSource); } /* @@ -290,9 +312,9 @@ CreateDosSource(const ImgHeader* pHeader, FILE* fp, * Create a data source for the buffer. We set the "doClose" flag to * "true", so NufxLib will free the buffer for us. */ - err = NuCreateDataSourceForBuffer(kNuThreadFormatUncompressed, true, 0, + err = NuCreateDataSourceForBuffer(kNuThreadFormatUncompressed, 0, (const unsigned char*) diskBuffer, 0, pHeader->dataLen, - ppDataSource); + FreeCallback, ppDataSource); if (err == kNuErrNone) diskBuffer = nil; @@ -405,9 +427,11 @@ ConvertFromImgToShk(const char* srcName, const char* dstName) switch (header.imageFormat) { case kImageFormatDOS: err = CreateDosSource(&header, fp, &pDataSource); + fp = nil; break; case kImageFormatProDOS: err = CreateProdosSource(&header, fp, &pDataSource); + fp = nil; break; default: fprintf(stderr, "How the heck did I get here?"); diff --git a/nufxlib-0/samples/Launder.c b/nufxlib-0/samples/Launder.c index c4d1a83..caa20e3 100644 --- a/nufxlib-0/samples/Launder.c +++ b/nufxlib-0/samples/Launder.c @@ -44,6 +44,14 @@ char gSentRecordWarning = false; +/* + * This gets called when a buffer DataSource is no longer needed. + */ +NuResult +FreeCallback(NuArchive* pArchive, void* args) +{ + free(args); +} /* * Copy a thread, expanding and recompressing it. @@ -107,18 +115,18 @@ CopyThreadRecompressed(NuArchive* pInArchive, NuArchive* pOutArchive, * the right thing. */ if (NuIsPresizedThreadID(NuGetThreadID(pThread))) { - err = NuCreateDataSourceForBuffer(kNuThreadFormatUncompressed, true, + err = NuCreateDataSourceForBuffer(kNuThreadFormatUncompressed, pThread->thCompThreadEOF, buffer, 0, - pThread->actualThreadEOF, &pDataSource); + pThread->actualThreadEOF, FreeCallback, &pDataSource); if (err != kNuErrNone) { fprintf(stderr, "ERROR: unable to create pre-sized data source (err=%d)\n",err); goto bail; } } else { - err = NuCreateDataSourceForBuffer(kNuThreadFormatUncompressed, true, - 0, buffer, 0, - pThread->actualThreadEOF, &pDataSource); + err = NuCreateDataSourceForBuffer(kNuThreadFormatUncompressed, + 0, buffer, 0, pThread->actualThreadEOF, + FreeCallback, &pDataSource); if (err != kNuErrNone) { fprintf(stderr, "ERROR: unable to create data source (err=%d)\n", err); @@ -234,18 +242,18 @@ CopyThreadUncompressed(NuArchive* pInArchive, NuArchive* pOutArchive, * for disk archives created by certain versions of ShrinkIt. */ if (NuIsPresizedThreadID(NuGetThreadID(pThread))) { - err = NuCreateDataSourceForBuffer(pThread->thThreadFormat, true, + err = NuCreateDataSourceForBuffer(pThread->thThreadFormat, pThread->thCompThreadEOF, buffer, 0, - pThread->actualThreadEOF, &pDataSource); + pThread->actualThreadEOF, FreeCallback, &pDataSource); if (err != kNuErrNone) { fprintf(stderr, "ERROR: unable to create pre-sized data source (err=%d)\n",err); goto bail; } } else { - err = NuCreateDataSourceForBuffer(pThread->thThreadFormat, true, + err = NuCreateDataSourceForBuffer(pThread->thThreadFormat, pThread->actualThreadEOF, buffer, 0, - pThread->thCompThreadEOF, &pDataSource); + pThread->thCompThreadEOF, FreeCallback, &pDataSource); if (err != kNuErrNone) { fprintf(stderr, "ERROR: unable to create data source (err=%d)\n", err); diff --git a/nufxlib-0/samples/TestBasic.c b/nufxlib-0/samples/TestBasic.c index b143537..702769b 100644 --- a/nufxlib-0/samples/TestBasic.c +++ b/nufxlib-0/samples/TestBasic.c @@ -91,6 +91,15 @@ ErrorMessageHandler(NuArchive* pArchive, void* vErrorMessage) return kNuOK; } +/* + * This gets called when a buffer DataSource is no longer needed. + */ +NuResult +FreeCallback(NuArchive* pArchive, void* args) +{ + free(args); +} + /* * =========================================================================== @@ -186,8 +195,8 @@ Test_AddStuff(NuArchive* pArchive) *(buf+i) = i & 0xff; FAIL_OK; - err = NuCreateDataSourceForBuffer(kNuThreadFormatUncompressed, true, - 0, nil, 0, 131072, &pDataSource); + err = NuCreateDataSourceForBuffer(kNuThreadFormatUncompressed, + 0, nil, 0, 131072, FreeCallback, &pDataSource); FAIL_BAD; if (err == kNuErrNone) { fprintf(stderr, "ERROR: that should've failed!\n"); @@ -197,8 +206,8 @@ Test_AddStuff(NuArchive* pArchive) /* * Create a data source for the big batch of bytes. */ - err = NuCreateDataSourceForBuffer(kNuThreadFormatUncompressed, true, - 0, buf, 0, 131072, &pDataSource); + err = NuCreateDataSourceForBuffer(kNuThreadFormatUncompressed, + 0, buf, 0, 131072, FreeCallback, &pDataSource); if (err != kNuErrNone) { fprintf(stderr, "ERROR: 'bytes' data source create failed (err=%d)\n", err); @@ -225,8 +234,8 @@ Test_AddStuff(NuArchive* pArchive) * Create a data source for our lovely text message. */ printf("... add 'English' record\n"); - err = NuCreateDataSourceForBuffer(kNuThreadFormatUncompressed, false, - 0, (const uchar*)testMsg, 0, strlen(testMsg), &pDataSource); + err = NuCreateDataSourceForBuffer(kNuThreadFormatUncompressed, + 0, (const uchar*)testMsg, 0, strlen(testMsg), nil, &pDataSource); if (err != kNuErrNone) { fprintf(stderr, "ERROR: 'English' source create failed (err=%d)\n", err); @@ -269,8 +278,8 @@ Test_AddStuff(NuArchive* pArchive) * Create an empty file with a rather non-empty name. */ printf("... add 'long' record\n"); - err = NuCreateDataSourceForBuffer(kNuThreadFormatUncompressed, false, - 0, nil, 0, 0, &pDataSource); + err = NuCreateDataSourceForBuffer(kNuThreadFormatUncompressed, + 0, nil, 0, 0, nil, &pDataSource); if (err != kNuErrNone) { fprintf(stderr, "ERROR: 'English' source create failed (err=%d)\n", err);