PlankResult pl_LockFreeQueue_DeInit (PlankLockFreeQueueRef p) { PlankResult result = PlankResult_OK; if (p == PLANK_NULL) { result = PlankResult_MemoryError; goto exit; } if (pl_LockFreeQueue_GetSize (p) != 0) { result = PlankResult_ContainerNotEmptyOnDeInit; goto exit; } pl_LockFreeQueueElement_DeInit (&p->dummyElement); pl_AtomicPX_DeInit (&p->head); pl_AtomicPX_DeInit (&p->tail); pl_MemoryZero (p, sizeof (PlankLockFreeQueue)); exit: return result; }
PlankResult pl_LockFreeQueue_Init (PlankLockFreeQueueRef p) { PlankResult result = PlankResult_OK; if (p == PLANK_NULL) { result = PlankResult_MemoryError; goto exit; } pl_MemoryZero (p, sizeof (PlankLockFreeQueue)); pl_AtomicPX_Init (&p->head); pl_AtomicPX_Init (&p->tail); pl_LockFreeQueueElement_Init (&p->dummyElement); pl_AtomicPX_SetAllUnchecked (&p->head, &p->dummyElement, 0); pl_AtomicPX_SetAllUnchecked (&p->tail, &p->dummyElement, 0); pl_LockFreeQueueElement_SetNext (&p->dummyElement, (PlankLockFreeQueueElementRef)p); exit: return result; }
PlankMemoryRef pl_Memory_Create() { PlankMemoryRef p = (PlankMemoryRef)pl_MemoryDefaultAllocateBytes (0, sizeof (PlankMemory)); if (p != PLANK_NULL) pl_MemoryZero (p, sizeof (PlankMemory)); return p; }
PlankResult pl_Memory_DeInit (PlankMemoryRef p) { if (p == PLANK_NULL) return PlankResult_MemoryError; pl_Lock_Lock (&p->lock); pl_MemoryZero (p, sizeof (PlankMemory)); pl_Lock_Unlock (&p->lock); return PlankResult_OK; }
PlankResult pl_IffFileWriter_Init (PlankIffFileWriterRef p) { PlankResult result = PlankResult_OK; pl_MemoryZero (p, sizeof (PlankIffFileWriter)); pl_File_Init ((PlankFileRef)p); result = pl_DynamicArray_InitWithItemSizeAndCapacity (&p->chunkInfos, sizeof(PlankIffFileWriterChunkInfo), 16); //exit: return result; }
PlankSimpleMapRef pl_SimpleMap_Create() { PlankMemoryRef m; PlankSimpleMapRef p; m = pl_MemoryGlobal(); p = (PlankSimpleMapRef)pl_Memory_AllocateBytes (m, sizeof (PlankSimpleMap)); if (p != PLANK_NULL) pl_MemoryZero (p, sizeof (PlankSimpleMap)); return p; }
PlankLockRef pl_Lock_Create() { PlankMemoryRef m; PlankLockRef p; m = pl_MemoryGlobal(); p = (PlankLockRef)pl_Memory_AllocateBytes (m, sizeof (PlankLock)); if (p != PLANK_NULL) pl_MemoryZero (p, sizeof (PlankLock)); return p; }
PlankIffFileWriterRef pl_IffFileWriter_Create() { PlankMemoryRef m; PlankIffFileWriterRef p; m = pl_MemoryGlobal(); p = (PlankIffFileWriterRef)pl_Memory_AllocateBytes (m, sizeof (PlankIffFileWriter)); if (p != PLANK_NULL) pl_MemoryZero (p, sizeof (PlankIffFileWriter)); return p; }
PlankLockFreeLinkedListElementRef pl_LockFreeLinkedListElement_Create() { PlankMemoryRef m; PlankLockFreeLinkedListElementRef p; m = pl_MemoryGlobal(); // must use the lock free one when done... nope just live with it and use alogrithms that reuse the memory allocs p = (PlankLockFreeLinkedListElementRef)pl_Memory_AllocateBytes (m, sizeof (PlankLockFreeLinkedListElement)); if (p != PLANK_NULL) pl_MemoryZero (p, sizeof (PlankLockFreeLinkedListElement)); return p; }
PlankLockFreeQueueRef pl_LockFreeQueue_Create() { PlankMemoryRef m; PlankLockFreeQueueRef p; m = pl_MemoryGlobal(); // OK, creation of the queue isn't itself lock free p = (PlankLockFreeQueueRef)pl_Memory_AllocateBytes (m, sizeof (PlankLockFreeQueue)); if (p != PLANK_NULL) pl_MemoryZero (p, sizeof (PlankLockFreeQueue)); return p; }
PlankResult pl_SimpleQueue_Init (PlankSimpleQueueRef p) { PlankResult result = PlankResult_OK; if (p == PLANK_NULL) { result = PlankResult_MemoryError; goto exit; } pl_MemoryZero (p, sizeof (PlankSimpleQueue)); exit: return result; }
PlankResult pl_SimpleMap_Init (PlankSimpleMapRef p) { PlankResult result = PlankResult_OK; if (p == PLANK_NULL) { result = PlankResult_MemoryError; goto exit; } pl_MemoryZero (p, sizeof (PlankSimpleMap)); result = pl_SimpleLinkedList_Init (&p->list); exit: return result; }
PlankResult pl_Lock_DeInit (PlankLockRef p) { PlankResult result = PlankResult_OK; if (p == PLANK_NULL) { result = PlankResult_MemoryError; goto exit; } DeleteCriticalSection (&p->mutex); CloseHandle (p->condition); pl_MemoryZero (p, sizeof (PlankLock)); exit: return result; }
PlankResult pl_LockFreeLinkedListElement_DeInit (PlankLockFreeLinkedListElementRef p) { PlankResult result = PlankResult_OK; if (p == PLANK_NULL) { result = PlankResult_MemoryError; goto exit; } pl_AtomicPX_DeInit (&p->next); pl_AtomicPX_DeInit (&p->data); pl_MemoryZero (p, sizeof (PlankLockFreeLinkedListElement)); exit: return result; }
PlankResult pl_Lock_DeInit (PlankLockRef p) { PlankResult result = PlankResult_OK; if (p == PLANK_NULL) { result = PlankResult_MemoryError; goto exit; } pthread_mutex_destroy (&p->mutex); pthread_cond_destroy (&p->condition); pl_MemoryZero (p, sizeof (PlankLock)); exit: return result; }
PlankResult pl_SimpleQueue_DeInit (PlankSimpleQueueRef p) { PlankResult result = PlankResult_OK; if (p == PLANK_NULL) { result = PlankResult_MemoryError; goto exit; } if (pl_SimpleQueue_GetSize (p) != 0) result = PlankResult_ContainerNotEmptyOnDeInit; pl_MemoryZero (p, sizeof (PlankSimpleQueue)); exit: return result; }
PlankResult pl_SimpleMap_DeInit (PlankSimpleMapRef p) { PlankResult result = PlankResult_OK; if (p == PLANK_NULL) { result = PlankResult_MemoryError; goto exit; } if (pl_SimpleMap_GetSize (p) != 0) result = PlankResult_ContainerNotEmptyOnDeInit; if ((result = pl_SimpleLinkedList_DeInit (&p->list)) != PlankResult_OK) goto exit; pl_MemoryZero (p, sizeof (PlankSimpleMap)); exit: return result; }
PlankResult pl_IffFileWriter_OpenWithFile (PlankIffFileWriterRef p, PlankFileRef file, const char* mainID, const char* formatID, const int idType) { PlankResult result = PlankResult_OK; int mode; if ((result = pl_File_GetMode (file, &mode)) != PlankResult_OK) goto exit; if (! (mode & PLANKFILE_BINARY)) { result = PlankResult_AudioFileInavlidType; goto exit; } if (! (mode & PLANKFILE_READ)) { result = PlankResult_AudioFileInavlidType; goto exit; } if (! (mode & PLANKFILE_WRITE)) { result = PlankResult_AudioFileInavlidType; goto exit; } pl_MemoryCopy ((PlankFileRef)p, file, sizeof (PlankFile)); pl_MemoryZero (file, sizeof (PlankFile)); if ((result = pl_IffFileWriter_ParseMainInfo (p, mainID, formatID, idType)) != PlankResult_OK) goto exit; if ((result = pl_IffFileWriter_WriteHeader (p)) != PlankResult_OK) goto exit; exit: return result; }
void AudioFileReaderInternal::disownPeer (PlankAudioFileReaderRef otherReader) throw() { pl_MemoryCopy (otherReader, getPeerRef(), sizeof (PlankAudioFileReader)); pl_MemoryZero (getPeerRef(), sizeof (PlankAudioFileReader)); pl_AudioFileReader_Init (getPeerRef()); }
PlankResult pl_IffFileWriter_RewriteFileUpdatingChunkInfo (PlankIffFileWriterRef p, PlankIffFileWriterChunkInfo* updatedChunkInfo) { PlankUC copyBuffer[PLANKIFFFILEWRITER_COPYLENGTH]; PlankResult result = PlankResult_OK; PlankIffFileWriterChunkInfo* chunkInfos; PlankIffFileWriter tempWriter; PlankPath tempPath; int mode, numChunks, i, bytesRead, bytesThisTime; PlankLL copyChunkLengthRemain; PlankB eraseOriginalFile; char chunkIDStr[64]; char otherIDStr[64]; eraseOriginalFile = PLANK_FALSE; if ((result = pl_File_GetMode ((PlankFileRef)p, &mode)) != PlankResult_OK) return result; if (! (mode & PLANKFILE_READ)) return PlankResult_FileReadError; if ((result = pl_Path_InitTemp (&tempPath, "IffWriter-", "tmp")) != PlankResult_OK) return result; if ((result = pl_IffFileWriter_Init (&tempWriter)) != PlankResult_OK) goto earlyExit; pl_IffFile_ChunkIDString ((PlankIffFileRef)p, &p->common.headerInfo.mainID, chunkIDStr); pl_IffFile_ChunkIDString ((PlankIffFileRef)p, &p->common.headerInfo.formatID, otherIDStr); result = pl_IffFileWriter_OpenReplacing (&tempWriter, pl_Path_GetFullPath (&tempPath), pl_File_IsBigEndian ((PlankFileRef)p), chunkIDStr, otherIDStr, p->common.headerInfo.idType); if (result != PlankResult_OK) goto earlyExit; numChunks = (int)pl_DynamicArray_GetSize (&p->chunkInfos); chunkInfos = (PlankIffFileWriterChunkInfo*)pl_DynamicArray_GetArray (&p->chunkInfos); for (i = 0; i < numChunks; ++i) { if (pl_IffFile_IsNullID ((PlankIffFileRef)p, &chunkInfos[i].chunkID)) continue; // this was a deleted chunk if (! pl_IffFile_EqualIDs ((PlankIffFileRef)p, &chunkInfos[i].chunkID, &updatedChunkInfo->chunkID)) { if ((result = pl_File_SetPosition ((PlankFileRef)p, chunkInfos[i].chunkPos)) != PlankResult_OK) goto exit; copyChunkLengthRemain = chunkInfos[i].chunkLength; while (copyChunkLengthRemain > 0) { bytesThisTime = (int)pl_MinLL (copyChunkLengthRemain, PLANKIFFFILEWRITER_COPYLENGTH); if ((result = pl_File_Read ((PlankFileRef)p, copyBuffer, bytesThisTime, &bytesRead)) != PlankResult_OK) goto exit; if (bytesThisTime != bytesRead) { // something is wrong if these don't match here result = PlankResult_FileReadError; goto exit; } pl_IffFile_ChunkIDString ((PlankIffFileRef)p, &chunkInfos[i].chunkID, chunkIDStr); if ((result = pl_IffFileWriter_WriteChunk (&tempWriter, PLANKIFFFILE_CURRENTCHUNKPOSITION, chunkIDStr, copyBuffer, bytesThisTime, PLANKIFFFILEWRITER_MODEAPPEND)) != PlankResult_OK) goto exit; copyChunkLengthRemain -= bytesThisTime; } } else { if (chunkInfos[i].chunkPos != updatedChunkInfo->chunkPos) { // something is wrong if these don't match here result = PlankResult_FileReadError; goto exit; } if (updatedChunkInfo->chunkLength < chunkInfos[i].chunkLength) eraseOriginalFile = PLANK_TRUE; if ((result = pl_File_SetPosition ((PlankFileRef)p, chunkInfos[i].chunkPos)) != PlankResult_OK) goto exit; copyChunkLengthRemain = pl_MinLL (chunkInfos[i].chunkLength, updatedChunkInfo->chunkLength); while (copyChunkLengthRemain > 0) { bytesThisTime = (int)pl_MinLL (copyChunkLengthRemain, PLANKIFFFILEWRITER_COPYLENGTH); if ((result = pl_File_Read ((PlankFileRef)p, copyBuffer, bytesThisTime, &bytesRead)) != PlankResult_OK) goto exit; if ((int)bytesThisTime != bytesRead) { // something is wrong if these don't match here result = PlankResult_FileReadError; goto exit; } pl_IffFile_ChunkIDString ((PlankIffFileRef)p, &chunkInfos[i].chunkID, chunkIDStr); if ((result = pl_IffFileWriter_WriteChunk (&tempWriter, PLANKIFFFILE_CURRENTCHUNKPOSITION, chunkIDStr, copyBuffer, bytesThisTime, PLANKIFFFILEWRITER_MODEAPPEND)) != PlankResult_OK) goto exit; copyChunkLengthRemain -= bytesThisTime; } // pad with zero for the larger size, no need to round to even bytes as pl_IffFileWriter_WriteChunk does this for us if (updatedChunkInfo->chunkLength > chunkInfos[i].chunkLength) { bytesThisTime = (int)(updatedChunkInfo->chunkLength - chunkInfos[i].chunkLength); pl_MemoryZero (copyBuffer, bytesThisTime); pl_IffFile_ChunkIDString ((PlankIffFileRef)p, &chunkInfos[i].chunkID, chunkIDStr); if ((result = pl_IffFileWriter_WriteChunk (&tempWriter, PLANKIFFFILE_CURRENTCHUNKPOSITION, chunkIDStr, copyBuffer, bytesThisTime, PLANKIFFFILEWRITER_MODEAPPEND)) != PlankResult_OK) goto exit; } } // after copying a chunk need to copy chunk infos from the temp back to this file's infos if ((result = pl_DynamicArray_GetItem (&tempWriter.chunkInfos, i, &chunkInfos[i])) != PlankResult_OK) goto exit; } if (eraseOriginalFile) { if ((result = pl_File_Clear ((PlankFileRef)p)) != PlankResult_OK) goto exit; } else { if ((result = pl_File_ResetPosition ((PlankFileRef)p)) != PlankResult_OK) goto exit; } if ((result = pl_File_ResetPosition (pl_IffFileWriter_GetFile (&tempWriter))) != PlankResult_OK) goto exit; if ((result = pl_File_Copy ((PlankFileRef)p, pl_IffFileWriter_GetFile (&tempWriter), 0)) != PlankResult_OK) goto exit; exit: pl_IffFileWriter_DeInit (&tempWriter); pl_FileErase (pl_Path_GetFullPath (&tempPath)); earlyExit: pl_Path_DeInit (&tempPath); return result; }
void TextFileInternal::disownPeer (PlankFileRef otherFile) throw() { pl_MemoryCopy (otherFile, getPeerRef(), sizeof (PlankFile)); pl_MemoryZero (getPeerRef(), sizeof (PlankFile)); pl_File_Init (getPeerRef()); }
PlankResult pl_IffFileWriter_ResizeChunk (PlankIffFileWriterRef p, const PlankLL startPosition, const char* chunkID, const PlankLL newLength, const PlankB concatenateJunk) { PlankIffFileWriterChunkInfo updatedChunkInfo; PlankIffFileWriterChunkInfo newJunkChunkInfo; PlankIffFileWriterChunkInfo* thisChunkInfo; PlankIffFileWriterChunkInfo* nextChunkInfo; PlankLL chunkChange, alignedNewLength, position; PlankIffID nextChunkID; PlankB thisChunkIsLast, nextChunkIsLast; PlankResult result; int chunkHeaderLength; char chunkIDStr[64]; result = PlankResult_OK; if ((result = pl_IffFileWriter_SeekChunk (p, startPosition, chunkID, &thisChunkInfo, &thisChunkIsLast)) != PlankResult_OK) goto exit; if (! thisChunkInfo) { result = PlankResult_IffFileReaderChunkNotFound; goto exit; } if (newLength == thisChunkInfo->chunkLength) goto exit; // nothing to do! alignedNewLength = pl_AlignLL (newLength, p->common.headerInfo.alignment); chunkChange = newLength - thisChunkInfo->chunkLength; if ((p->common.headerInfo.lengthSize == 4) && (chunkChange > 0x7fffffff)) { // could support this but it is a highly suspicious request to reserve such a large space.. result = PlankResult_UnknownError; goto exit; } chunkHeaderLength = p->common.headerInfo.lengthSize + pl_IffFile_ChunkIDLength ((PlankIffFileRef)p); if (thisChunkIsLast) { if (thisChunkIsLast && (chunkChange > 0)) { // if it is getting larger then expand the chunk adding zeros to the end if ((result = pl_File_SetPosition ((PlankFileRef)p, thisChunkInfo->chunkPos + thisChunkInfo->chunkLength)) != PlankResult_OK) goto exit; // not including the original padding byte if present if ((result = pl_File_WriteZeros ((PlankFileRef)p, (int)chunkChange + (int)(alignedNewLength - newLength))) != PlankResult_OK) goto exit; // add padding bytes based on the new length if needed if ((result = pl_File_SetPosition ((PlankFileRef)p, thisChunkInfo->chunkPos - p->common.headerInfo.lengthSize)) != PlankResult_OK) goto exit; if ((result = pl_IffFile_WriteChunkLength ((PlankIffFileRef)p, newLength)) != PlankResult_OK) goto exit; thisChunkInfo->chunkLength = newLength; } else // getting smaller { // flip the sign chunkChange = -chunkChange; // could put back more complex criteria based on alignment if (chunkChange >= chunkHeaderLength) { // if it is getting smaller, shrink it and add junk at the end if ((result = pl_File_SetPosition ((PlankFileRef)p, thisChunkInfo->chunkPos - p->common.headerInfo.lengthSize)) != PlankResult_OK) goto exit; if ((result = pl_IffFile_WriteChunkLength ((PlankIffFileRef)p, newLength)) != PlankResult_OK) goto exit; if (chunkChange > 1) // keep in case we put back the more specific criteria.. { // need to add junk newJunkChunkInfo.chunkID = p->common.headerInfo.junkID; newJunkChunkInfo.chunkPos = thisChunkInfo->chunkPos + alignedNewLength + chunkHeaderLength; newJunkChunkInfo.chunkLength = pl_AlignULL (chunkChange, p->common.headerInfo.alignment) - chunkHeaderLength; if ((p->common.headerInfo.lengthSize == 4) && (newJunkChunkInfo.chunkLength > 0xffffffff)) { // need multiple junk chunks rather than one, unlikely to need to reserve this amount of free space result = PlankResult_UnknownError; goto exit; } if ((result = pl_File_SetPosition ((PlankFileRef)p, newJunkChunkInfo.chunkPos - chunkHeaderLength)) != PlankResult_OK) goto exit; if ((result = pl_IffFile_WriteChunkID ((PlankIffFileRef)p, &newJunkChunkInfo.chunkID)) != PlankResult_OK) goto exit; if ((result = pl_IffFile_WriteChunkLength ((PlankIffFileRef)p, newJunkChunkInfo.chunkLength)) != PlankResult_OK) goto exit; if ((result = pl_DynamicArray_AddItem (&p->chunkInfos, &newJunkChunkInfo)) != PlankResult_OK) goto exit; } thisChunkInfo->chunkLength = newLength; } else goto slowCopy; } } else { // we know this isn't the last chunk so see if the next chunk is junk position = thisChunkInfo->chunkPos + pl_AlignULL (thisChunkInfo->chunkLength, p->common.headerInfo.alignment); if ((result = pl_File_SetPosition ((PlankFileRef)p, position)) != PlankResult_OK) goto exit; if ((result = pl_IffFile_ReadChunkID ((PlankIffFileRef)p, &nextChunkID)) != PlankResult_OK) goto exit; pl_IffFile_ChunkIDString ((PlankIffFileRef)p, &nextChunkID, chunkIDStr); if ((result = pl_IffFileWriter_SeekChunk (p, position, chunkIDStr, &nextChunkInfo, &nextChunkIsLast)) != PlankResult_OK) goto exit; if (! nextChunkInfo) { // something really unexpected happened, we already checked there was another chunk following... result = PlankResult_UnknownError; goto exit; } if (concatenateJunk && pl_IffFile_EqualIDs ((PlankIffFileRef)p, &nextChunkInfo->chunkID, &p->common.headerInfo.junkID)) { if (chunkChange > 0) // getting bigger { if ((chunkChange < p->common.headerInfo.alignment) && ((thisChunkInfo->chunkLength % p->common.headerInfo.alignment) != 0)) { // just change the length and leave the junk alone if ((result = pl_File_SetPosition ((PlankFileRef)p, thisChunkInfo->chunkPos - p->common.headerInfo.lengthSize)) != PlankResult_OK) goto exit; if ((result = pl_IffFile_WriteChunkLength ((PlankIffFileRef)p, newLength)) != PlankResult_OK) goto exit; thisChunkInfo->chunkLength = newLength; } else if (chunkChange <= (nextChunkInfo->chunkLength + chunkHeaderLength)) { if (chunkChange > nextChunkInfo->chunkLength) { if (((chunkChange - nextChunkInfo->chunkLength) >= p->common.headerInfo.alignment) && ((chunkChange - nextChunkInfo->chunkLength) < chunkHeaderLength)) { goto slowCopy; // incompatible length change } // zero the junk header to avoid the file looking confusing during debugging if ((result = pl_File_SetPosition ((PlankFileRef)p, nextChunkInfo->chunkPos - chunkHeaderLength)) != PlankResult_OK) goto exit; if ((result = pl_File_WriteZeros ((PlankFileRef)p, chunkHeaderLength)) != PlankResult_OK) goto exit; // expand this chunk if ((result = pl_File_SetPosition ((PlankFileRef)p, thisChunkInfo->chunkPos - p->common.headerInfo.lengthSize)) != PlankResult_OK) goto exit; if ((result = pl_IffFile_WriteChunkLength ((PlankIffFileRef)p, newLength)) != PlankResult_OK) goto exit; thisChunkInfo->chunkLength = newLength; // null the junk chunk reference pl_MemoryZero (&nextChunkInfo->chunkID, sizeof (PlankIffID)); } else { // zero the junk header to avoid the file looking confusing during debugging if ((result = pl_File_SetPosition ((PlankFileRef)p, nextChunkInfo->chunkPos - chunkHeaderLength)) != PlankResult_OK) goto exit; if ((result = pl_File_WriteZeros ((PlankFileRef)p, chunkHeaderLength)) != PlankResult_OK) goto exit; // expand this chunk if ((result = pl_File_SetPosition ((PlankFileRef)p, thisChunkInfo->chunkPos - p->common.headerInfo.lengthSize)) != PlankResult_OK) goto exit; if ((result = pl_IffFile_WriteChunkLength ((PlankIffFileRef)p, newLength)) != PlankResult_OK) goto exit; thisChunkInfo->chunkLength = newLength; //..and shrink the junk nextChunkInfo->chunkPos = thisChunkInfo->chunkPos + pl_AlignULL (thisChunkInfo->chunkLength, p->common.headerInfo.alignment) + chunkHeaderLength; nextChunkInfo->chunkLength -= chunkChange; if ((result = pl_File_SetPosition ((PlankFileRef)p, nextChunkInfo->chunkPos - chunkHeaderLength)) != PlankResult_OK) goto exit; if ((result = pl_IffFile_WriteChunkID ((PlankIffFileRef)p, &nextChunkInfo->chunkID)) != PlankResult_OK) goto exit; if ((result = pl_IffFile_WriteChunkLength ((PlankIffFileRef)p, nextChunkInfo->chunkLength)) != PlankResult_OK) goto exit; } } else { // recursively concatenate junk chunks as far as we can... alignedNewLength = thisChunkInfo->chunkLength + pl_AlignLL (nextChunkInfo->chunkLength, p->common.headerInfo.alignment) + chunkHeaderLength; if ((result = pl_IffFileWriter_ResizeChunk (p, startPosition, chunkID, alignedNewLength, PLANK_TRUE)) != PlankResult_OK) goto exit; if ((result = pl_IffFileWriter_ResizeChunk (p, startPosition, chunkID, newLength, PLANK_TRUE)) != PlankResult_OK) goto exit; } } else // getting smaller { // flip the sign chunkChange = -chunkChange; // zero the junk header to avoid the file looking confusing during debugging if ((result = pl_File_SetPosition ((PlankFileRef)p, nextChunkInfo->chunkPos - chunkHeaderLength)) != PlankResult_OK) goto exit; if ((result = pl_File_WriteZeros ((PlankFileRef)p, chunkHeaderLength)) != PlankResult_OK) goto exit; // resize this chunk if ((result = pl_File_SetPosition ((PlankFileRef)p, thisChunkInfo->chunkPos - p->common.headerInfo.lengthSize)) != PlankResult_OK) goto exit; if ((result = pl_IffFile_WriteChunkLength ((PlankIffFileRef)p, newLength)) != PlankResult_OK) goto exit; thisChunkInfo->chunkLength = newLength; // move and resize junk nextChunkInfo->chunkPos = thisChunkInfo->chunkPos + pl_AlignULL (thisChunkInfo->chunkLength, p->common.headerInfo.alignment) + chunkHeaderLength; nextChunkInfo->chunkLength += chunkChange; if ((p->common.headerInfo.lengthSize == 4) && (nextChunkInfo->chunkLength > 0xffffffff)) { // need multiple junk chunks rather than one, unlikely to need to reserve this amount of free space result = PlankResult_UnknownError; goto exit; } if ((result = pl_File_SetPosition ((PlankFileRef)p, nextChunkInfo->chunkPos - chunkHeaderLength)) != PlankResult_OK) goto exit; if ((result = pl_IffFile_WriteChunkID ((PlankIffFileRef)p, &nextChunkInfo->chunkID)) != PlankResult_OK) goto exit; if ((result = pl_IffFile_WriteChunkLength ((PlankIffFileRef)p, nextChunkInfo->chunkLength)) != PlankResult_OK) goto exit; } } else if ((chunkChange > 0) && (chunkChange < p->common.headerInfo.alignment) && ((thisChunkInfo->chunkLength % p->common.headerInfo.alignment) != 0)) { // just change the chunk length if ((result = pl_File_SetPosition ((PlankFileRef)p, thisChunkInfo->chunkPos - p->common.headerInfo.lengthSize)) != PlankResult_OK) goto exit; if ((result = pl_IffFile_WriteChunkLength ((PlankIffFileRef)p, newLength)) != PlankResult_OK) goto exit; thisChunkInfo->chunkLength = newLength; } else if (chunkChange < 0) { chunkChange = -chunkChange; if (chunkChange >= chunkHeaderLength) { // if it is getting smaller, shrink it and add junk at the end if ((result = pl_File_SetPosition ((PlankFileRef)p, thisChunkInfo->chunkPos - p->common.headerInfo.lengthSize)) != PlankResult_OK) goto exit; if ((result = pl_IffFile_WriteChunkLength ((PlankIffFileRef)p, newLength)) != PlankResult_OK) goto exit; if (chunkChange > 1) // keep in case we put back the more specific criteria.. { // need to add junk newJunkChunkInfo.chunkID = p->common.headerInfo.junkID; newJunkChunkInfo.chunkPos = thisChunkInfo->chunkPos + alignedNewLength + chunkHeaderLength; newJunkChunkInfo.chunkLength = pl_AlignULL (chunkChange, p->common.headerInfo.alignment) - chunkHeaderLength; if ((p->common.headerInfo.lengthSize == 4) && (newJunkChunkInfo.chunkLength > 0xffffffff)) { // need multiple junk chunks rather than one, unlikely to need to reserve this amount of free space result = PlankResult_UnknownError; goto exit; } if ((result = pl_File_SetPosition ((PlankFileRef)p, newJunkChunkInfo.chunkPos - chunkHeaderLength)) != PlankResult_OK) goto exit; if ((result = pl_IffFile_WriteChunkID ((PlankIffFileRef)p, &newJunkChunkInfo.chunkID)) != PlankResult_OK) goto exit; if ((result = pl_IffFile_WriteChunkLength ((PlankIffFileRef)p, newJunkChunkInfo.chunkLength)) != PlankResult_OK) goto exit; if ((result = pl_DynamicArray_AddItem (&p->chunkInfos, &newJunkChunkInfo)) != PlankResult_OK) goto exit; } thisChunkInfo->chunkLength = newLength; } else goto slowCopy; } else { slowCopy: // we're going to have to do a slow rewrite.. updatedChunkInfo.chunkID = thisChunkInfo->chunkID; updatedChunkInfo.chunkLength = newLength; updatedChunkInfo.chunkPos = thisChunkInfo->chunkPos; if ((result = pl_IffFileWriter_RewriteFileUpdatingChunkInfo (p, &updatedChunkInfo)) != PlankResult_OK) goto exit; } } // seek back to the position of the chunk's data if ((result = pl_File_SetPosition ((PlankFileRef)p, thisChunkInfo->chunkPos)) != PlankResult_OK) goto exit; p->currentChunk = thisChunkInfo; exit: return result; }