void LFA_Move ( LFA_FileRef srcFile, XMP_Int64 srcOffset, LFA_FileRef dstFile, XMP_Int64 dstOffset, XMP_Int64 length, XMP_AbortProc abortProc /* = 0 */, void * abortArg /* = 0 */ ) { enum { kBufferLen = 64*1024 }; XMP_Uns8 buffer [kBufferLen]; const bool checkAbort = (abortProc != 0); if ( srcOffset > dstOffset ) { // avoiding shadow effects // move down -> shift lowest packet first ! while ( length > 0 ) { if ( checkAbort && abortProc(abortArg) ) LFA_Throw ( "LFA_Move - User abort", kLFAErr_UserAbort ); XMP_Int32 ioCount = kBufferLen; if ( length < kBufferLen ) ioCount = (XMP_Int32)length; //smartly avoids 32/64 bit issues LFA_Seek ( srcFile, srcOffset, SEEK_SET ); LFA_Read ( srcFile, buffer, ioCount, kLFA_RequireAll ); LFA_Seek ( dstFile, dstOffset, SEEK_SET ); LFA_Write ( dstFile, buffer, ioCount ); length -= ioCount; srcOffset += ioCount; dstOffset += ioCount; } } else { // move up -> shift highest packet first srcOffset += length; //move to end dstOffset += length; while ( length > 0 ) { if ( checkAbort && abortProc(abortArg) ) LFA_Throw ( "LFA_Move - User abort", kLFAErr_UserAbort ); XMP_Int32 ioCount = kBufferLen; if ( length < kBufferLen ) ioCount = (XMP_Int32)length; //smartly avoids 32/64 bit issues srcOffset -= ioCount; dstOffset -= ioCount; LFA_Seek ( srcFile, srcOffset, SEEK_SET ); LFA_Read ( srcFile, buffer, ioCount, kLFA_RequireAll ); LFA_Seek ( dstFile, dstOffset, SEEK_SET ); LFA_Write ( dstFile, buffer, ioCount ); length -= ioCount; } } } // LFA_Move
bool WriteChunk ( LFA_FileRef inFileRef, long tagID, const char * data, UInt32 len ) { atag ck; ck.id = MakeUns32LE ( tagID ); ck.len = MakeUns32LE ( len ); try { LFA_Write ( inFileRef, &ck, 8 ); LFA_Write ( inFileRef, data, len ); } catch ( ... ) { return false; } return true; }
bool MarkChunkAsPadding ( LFA_FileRef inFileRef, RiffState & inOutRiffState, long riffType, long tagID, long subtypeID ) { UInt32 len; UInt64 pos; atag tag; try { bool found = FindChunk ( inOutRiffState, tagID, riffType, subtypeID, NULL, &len, &pos ); if ( ! found ) return false; if ( subtypeID != 0 ) { pos -= 12; } else { pos -= 8; } tag.id = MakeUns32LE ( ckidPremierePadding ); LFA_Seek ( inFileRef, pos, SEEK_SET ); LFA_Write ( inFileRef, &tag, 4 ); pos += 8; AddTag ( inOutRiffState, ckidPremierePadding, len, pos, 0, 0, 0 ); } catch(...) { return false; // If a write fails, it throws, so we return false. } return true; }
bool WriteXMPTag ( LFA_FileRef fileRef, XMP_Uns32 len, const char* inBuffer ) { bool ret = false; XMP_Uns16 code = MakeUns16LE ( (SWF_TAG_ID_METADATA << 6) | 0x3F ); XMP_Uns32 length = MakeUns32LE ( len ); try { LFA_Write (fileRef, &code, 2 ); LFA_Write (fileRef, &length, 4 ); LFA_Write (fileRef, inBuffer, len ); ret = true; } catch ( ... ) {} return ret; } // WriteXMPTag
bool PutChunk ( LFA_FileRef inFileRef, RiffState & inOutRiffState, long riffType, long tagID, const char * inBuffer, UInt32 inBufferSize ) { UInt32 len; UInt64 pos; atag tag; // Make sure we're writting an even number of bytes. Required by the RIFF specification. XMP_Assert ( (inBufferSize & 1) == 0 ); try { bool found = FindChunk ( inOutRiffState, tagID, 0, 0, NULL, &len, &pos ); if ( found ) { if ( len == inBufferSize ) { LFA_Seek ( inFileRef, pos, SEEK_SET ); LFA_Write ( inFileRef, inBuffer, inBufferSize ); return true; } pos -= 8; tag.id = MakeUns32LE ( ckidPremierePadding ); LFA_Seek ( inFileRef, pos, SEEK_SET ); LFA_Write ( inFileRef, &tag, 4 ); if ( len > inBufferSize ) { pos += 8; AddTag ( inOutRiffState, ckidPremierePadding, len, pos, 0, 0, 0 ); } } } catch ( ... ) { // If a write fails, it throws, so we return false return false; } bool ok = MakeChunk ( inFileRef, inOutRiffState, riffType, (inBufferSize + 8) ); if ( ! ok ) return false; return WriteChunk ( inFileRef, tagID, inBuffer, inBufferSize ); }
int FileInfo::Encode ( LFA_FileRef fileRef, LFA_FileRef updateRef, SWF_MODE swfMode, CompressionFnc cmpFnc ) { LFA_Seek ( updateRef, 0, SEEK_SET ); if ( swfMode == CWS ) { LFA_Write ( updateRef, SWF_C_SIGNATURE_DATA, SWF_SIGNATURE_LEN ); } else { XMP_Assert ( swfMode == FWS ); LFA_Write ( updateRef, SWF_F_SIGNATURE_DATA, SWF_SIGNATURE_LEN ); } LFA_Seek ( fileRef, SWF_SIGNATURE_LEN, SEEK_SET ); LFA_Seek ( updateRef, SWF_SIGNATURE_LEN, SEEK_SET ); LFA_Copy ( fileRef, updateRef, 5 ); int ret = cmpFnc ( fileRef, updateRef ); LFA_Flush ( updateRef ); return ret; } // FileInfo::Encode
bool WriteFileAttrFlags ( LFA_FileRef fileRef, const TagData& fileAttrTag, XMP_Uns32 flags ) { try { XMP_Uns32 bitMask = MakeUns32LE ( flags ); LFA_Seek ( fileRef, fileAttrTag.pos + fileAttrTag.offset, SEEK_SET ); LFA_Write ( fileRef, &bitMask, 4 ); return true; } catch ( ... ) {} return false; } // WriteFileAttrFlags
bool WriteBuffer ( LFA_FileRef fileRef, XMP_Uns64& pos, XMP_Uns32 len, const char* inBuffer ) { try { if ( (fileRef == 0) || (inBuffer == 0) ) return false; LFA_Seek ( fileRef, pos, SEEK_SET ); LFA_Write ( fileRef, inBuffer, len ); return true; } catch ( ... ) {} return false; } // WriteBuffer
bool RewriteChunk ( LFA_FileRef inFileRef, RiffState & inOutRiffState, long tagID, long parentID, const char * inData ) { UInt32 len; UInt64 pos; try { if ( FindChunk ( inOutRiffState, tagID, parentID, 0, NULL, &len, &pos ) ) { LFA_Seek ( inFileRef, pos, SEEK_SET ); LFA_Write ( inFileRef, inData, len ); } } catch ( ... ) { return false; } return true; }
bool UpdateHeader ( LFA_FileRef fileRef ) { try { XMP_Int64 length64 = LFA_Measure ( fileRef ); if ( (length64 < 8) || (length64 > (XMP_Int64)0xFFFFFFFFULL) ) return false; XMP_Uns32 length32 = MakeUns32LE ( (XMP_Uns32)length64 ); LFA_Seek ( fileRef, 4, SEEK_SET ); LFA_Write ( fileRef, &length32, 4 ); return true; } catch ( ... ) {} return false; } // UpdateHeader
/* note! function does not rewind (LFA_Seek)) */ void LFA_Copy ( LFA_FileRef sourceFile, LFA_FileRef destFile, XMP_Int64 length, XMP_AbortProc abortProc /* = 0 */, void * abortArg /* = 0 */ ) { enum { kBufferLen = 64*1024 }; XMP_Uns8 buffer [kBufferLen]; const bool checkAbort = (abortProc != 0); while ( length > 0 ) { if ( checkAbort && abortProc(abortArg) ) { LFA_Throw ( "LFA_Copy - User abort", kLFAErr_UserAbort ); } XMP_Int32 ioCount = kBufferLen; if ( length < kBufferLen ) ioCount = (XMP_Int32)length; LFA_Read ( sourceFile, buffer, ioCount, kLFA_RequireAll ); LFA_Write ( destFile, buffer, ioCount ); length -= ioCount; } } // LFA_Copy
XMP_Uns32 PSIR_FileWriter::UpdateFileResources ( LFA_FileRef sourceRef, LFA_FileRef destRef, IOBuffer * ioBuf, XMP_AbortProc abortProc, void * abortArg ) { IgnoreParam(ioBuf); const XMP_Uns32 zero32 = 0; const bool checkAbort = (abortProc != 0); struct RsrcHeader { XMP_Uns32 type; XMP_Uns16 id; }; XMP_Assert ( (offsetof(RsrcHeader,type) == 0) && (offsetof(RsrcHeader,id) == 4) ); if ( this->memParsed ) XMP_Throw ( "Not file based", kXMPErr_EnforceFailure ); XMP_Int64 destLenOffset = LFA_Seek ( destRef, 0, SEEK_CUR ); XMP_Uns32 destLength = 0; LFA_Write ( destRef, &destLength, 4 ); // Write a placeholder for the new PSIR section length. #if 0 { printf ( "\nPSIR_FileWriter::UpdateFileResources, count = %d\n", this->imgRsrcs.size() ); InternalRsrcMap::iterator irPos = this->imgRsrcs.begin(); InternalRsrcMap::iterator irEnd = this->imgRsrcs.end(); for ( ; irPos != irEnd; ++irPos ) { InternalRsrcInfo& thisRsrc = irPos->second; printf ( " #%d, dataLen %d, origOffset %d (0x%X)%s\n", thisRsrc.id, thisRsrc.dataLen, thisRsrc.origOffset, thisRsrc.origOffset, (thisRsrc.changed ? ", changed" : "") ); } } #endif // First write all of the '8BIM' resources from the map. Use the internal data if present, else // copy the data from the file. RsrcHeader outHeader; outHeader.type = MakeUns32BE ( k8BIM ); InternalRsrcMap::iterator rsrcPos = this->imgRsrcs.begin(); InternalRsrcMap::iterator rsrcEnd = this->imgRsrcs.end(); // printf ( "\nPSIR_FileWriter::UpdateFileResources - 8BIM resources\n" ); for ( ; rsrcPos != rsrcEnd; ++rsrcPos ) { InternalRsrcInfo& currRsrc = rsrcPos->second; outHeader.id = MakeUns16BE ( currRsrc.id ); LFA_Write ( destRef, &outHeader, 6 ); destLength += 6; if ( currRsrc.rsrcName == 0 ) { LFA_Write ( destRef, &zero32, 2 ); destLength += 2; } else { XMP_Assert ( currRsrc.rsrcName[0] != 0 ); XMP_Uns16 nameLen = currRsrc.rsrcName[0]; // ! Include room for +1. XMP_Uns16 paddedLen = (nameLen + 2) & 0xFFFE; // ! Round up to an even total. Yes, +2! LFA_Write ( destRef, currRsrc.rsrcName, paddedLen ); destLength += paddedLen; } XMP_Uns32 dataLen = MakeUns32BE ( currRsrc.dataLen ); LFA_Write ( destRef, &dataLen, 4 ); // printf ( " #%d, offset %d (0x%X), dataLen %d\n", currRsrc.id, destLength, destLength, currRsrc.dataLen ); if ( currRsrc.dataPtr != 0 ) { LFA_Write ( destRef, currRsrc.dataPtr, currRsrc.dataLen ); } else { LFA_Seek ( sourceRef, currRsrc.origOffset, SEEK_SET ); LFA_Copy ( sourceRef, destRef, currRsrc.dataLen ); } destLength += 4 + currRsrc.dataLen; if ( (currRsrc.dataLen & 1) != 0 ) { LFA_Write ( destRef, &zero32, 1 ); // ! Pad the data to an even length. ++destLength; } } // Now write all of the non-8BIM resources. Copy the entire resource chunk from the source file. // printf ( "\nPSIR_FileWriter::UpdateFileResources - other resources\n" ); for ( size_t i = 0; i < this->otherRsrcs.size(); ++i ) { // printf ( " offset %d (0x%X), length %d", // this->otherRsrcs[i].rsrcOffset, this->otherRsrcs[i].rsrcOffset, this->otherRsrcs[i].rsrcLength ); LFA_Seek ( sourceRef, this->otherRsrcs[i].rsrcOffset, SEEK_SET ); LFA_Copy ( sourceRef, destRef, this->otherRsrcs[i].rsrcLength ); destLength += this->otherRsrcs[i].rsrcLength; // Alignment padding is already included. } // Write the final PSIR section length, seek back to the end of the file, return the length. // printf ( "\nPSIR_FileWriter::UpdateFileResources - final length %d (0x%X)\n", destLength, destLength ); LFA_Seek ( destRef, destLenOffset, SEEK_SET ); XMP_Uns32 outLen = MakeUns32BE ( destLength ); LFA_Write ( destRef, &outLen, 4 ); LFA_Seek ( destRef, 0, SEEK_END ); // *** Not rebuilding the internal map - turns out we never want it, why pay for the I/O. // *** Should probably add an option for all of these cases, memory and file based. return destLength; } // PSIR_FileWriter::UpdateFileResources
// ================================================================================================= // MP3_MetaHandler::UpdateFile // =========================== void MP3_MetaHandler::UpdateFile ( bool doSafeUpdate ) { if ( doSafeUpdate ) XMP_Throw ( "UCF_MetaHandler::UpdateFile: Safe update not supported", kXMPErr_Unavailable ); LFA_FileRef file ( this->parent->fileRef ); // leave 2.3 resp. 2.4 header, since we want to let alone // and don't know enough about the encoding of unrelated frames... XMP_Assert( this->containsXMP ); tagIsDirty = false; mustShift = false; // write out native properties: // * update existing ones // * create new frames as needed // * delete frames if property is gone! // see what there is to do for us: // RECON LOOP START for (int r=0; reconProps[r].frameID != 0; r++) { std::string value; bool needDescriptor = false; bool need16LE = true; bool needEncodingByte = true; XMP_Uns32 frameID = GetUns32BE( reconProps[r].frameID ); // the would-be frame ID3v2Frame* frame = framesMap[ frameID ]; // the actual frame (if already existing) // get XMP property // * honour specific exceptions // * leave value empty() if it doesn't exist ==> frame must be delete/not created switch( frameID ) { case 0x54434D50: // TCMP if exists: part of compilation need16LE = false; if ( xmpObj.GetProperty( kXMP_NS_DM, "partOfCompilation", &value, 0 ) && ( 0 == stricmp( value.c_str(), "true" ) )) value = "1"; // set a TCMP frame of value 1 else value.erase(); // delete/prevent creation of frame break; case 0x54495432: // TIT2 -> title["x-default"] case 0x54434F50: // TCOP -> rights["x-default"] if (! xmpObj.GetLocalizedText( reconProps[r].ns, reconProps[r].prop, "", "x-default", 0, &value, 0 )) //jaja, side effect. value.erase(); // if not, erase string. break; case 0x54434F4E: // TCON -> genre { if (! xmpObj.GetProperty( reconProps[r].ns, reconProps[r].prop, &value, 0 )) { // nothing found? -> Erase string. (Leads to Unset below) value.erase(); break; } // genre: we need to get the number back, if possible XMP_Int16 iFound = -1; // flag as "not found" for ( int i=0; i < 127; ++i ) { if ( (value.size() == strlen(Genres[i])) && (stricmp( value.c_str(), Genres[i] ) == 0) ) //fixing stricmp buggy on PPC { iFound = i; // Found break; } } if ( iFound == -1 ) // not found known numeric genre? break; // stick with the literal value (also for v2.3, since this is common practice!) need16LE = false; // no unicode need for (##) char strGenre[64]; snprintf ( strGenre, sizeof(strGenre), "(%d)", iFound ); // AUDIT: Using sizeof(strGenre) is safe. value.assign(strGenre); } break; case 0x434F4D4D: // COMM case 0x55534C54: // USLT, both need descriptor. needDescriptor = true; if (! xmpObj.GetProperty( reconProps[r].ns, reconProps[r].prop, &value, 0 )) value.erase(); break; case 0x54594552: //TYER case 0x54444154: //TDAT case 0x54494D45: //TIME { if ( majorVersion <= 3 ) // TYER, TIME and TDAT depricated since v. 2.4 -> else use TDRC { XMP_DateTime dateTime; if (! xmpObj.GetProperty_Date( reconProps[r].ns, reconProps[r].prop, &dateTime, 0 )) { // nothing found? -> Erase string. (Leads to Unset below) value.erase(); break; } // TYER if ( frameID == 0x54594552 ) { XMP_Validate( dateTime.year <= 9999 && dateTime.year > 0 , "Year is out of range", kXMPErr_BadParam); // get only Year! SXMPUtils::ConvertFromInt( dateTime.year, "", &value ); break; } // TDAT else if ( frameID == 0x54444154 && dateTime.hasDate ) // date validation made by "GetProperty_Date" { std::string day, month; SXMPUtils::ConvertFromInt( dateTime.day, "", &day ); SXMPUtils::ConvertFromInt( dateTime.month, "", &month ); if ( dateTime.day < 10 ) value = "0"; value += day; if ( dateTime.month < 10 ) value += "0"; value += month; break; } // TIME else if ( frameID == 0x54494D45 && dateTime.hasTime ) // time validation made by "GetProperty_Date" ) { std::string hour, minute; SXMPUtils::ConvertFromInt( dateTime.hour, "", &hour ); SXMPUtils::ConvertFromInt( dateTime.minute, "", &minute ); if ( dateTime.hour < 10 ) value = "0"; value += hour; if ( dateTime.minute < 10 ) value += "0"; value += minute; break; } else { value.erase(); break; } } else // v.2.4 --> delete TYER,TIME or TDAT & write into TDRC { value.erase(); break; } } case 0x54445243: //TDRC (only v2.4) { // only export for id3 > v2.4 if ( majorVersion > 3 ) // (only v2.4) { if (! xmpObj.GetProperty( reconProps[r].ns, reconProps[r].prop, &value, 0 )) value.erase(); } break; } break; case 0x57434F50: //WCOP needEncodingByte = false; need16LE = false; if (! xmpObj.GetProperty( reconProps[r].ns, reconProps[r].prop, &value, 0 )) value.erase(); // if not, erase string break; case 0x5452434B: // TRCK case 0x54504F53: // TPOS need16LE = false; // no break, go on: default: if (! xmpObj.GetProperty( reconProps[r].ns, reconProps[r].prop, &value, 0 )) value.erase(); // if not, erase string break; } // [XMP exist] x [frame exist] => four cases: // 1/4) nothing before, nothing now if ( value.empty() && (frame==0)) continue; // nothing to do // all else means there will be rewrite work to do: tagIsDirty = true; // 2/4) value before, now gone: if ( value.empty() && (frame!=0)) { frame->active = false; //mark for non-use continue; } // 3/4) no old value, create new value if ( frame==0) { ID3v2Frame* newFrame=new ID3v2Frame( frameID ); newFrame->setFrameValue( value, needDescriptor, need16LE, false, needEncodingByte ); //always write as utf16-le incl. BOM framesVector.push_back( newFrame ); framesMap[ frameID ] = newFrame; continue; } // 4/4) change existing value else // resp. change frame { frame->setFrameValue( value, needDescriptor, need16LE, false, needEncodingByte ); } } // RECON LOOP END ///////////////////////////////////////////////////////////////////////////////// // (Re)Build XMP frame: ID3v2Frame* frame = framesMap[ XMP_FRAME_ID ]; if ( frame == 0) { ID3v2Frame* newFrame=new ID3v2Frame( XMP_FRAME_ID ); newFrame->setFrameValue( this->xmpPacket, false, false, true ); framesVector.push_back( newFrame ); framesMap[ XMP_FRAME_ID ] = newFrame; } else frame->setFrameValue( this->xmpPacket, false, false, true ); //////////////////////////////////////////////////////////////////////////////// // Decision making newFramesSize = 0; for ( XMP_Uns32 i=0; i < framesVector.size(); i++) { if (framesVector[i]->active) newFramesSize += (10 + framesVector[i]->contentSize ); } mustShift = ( newFramesSize > (oldTagSize - 10)) || //optimization: If more than 8K can be saved by rewriting the MP3, go do it: ((newFramesSize + 8*1024) < oldTagSize ); if (!mustShift) // fill what we got newTagSize = oldTagSize; else // if need to shift anyway, get some nice 2K padding newTagSize = newFramesSize + 2048 + 10; newPadding = newTagSize -10 - newFramesSize; // shifting needed? -> shift if ( mustShift ) { XMP_Int64 filesize = LFA_Measure( file ); if ( this->hasID3Tag ) LFA_Move( file, oldTagSize, file, newTagSize , filesize - oldTagSize ); //fix [2338569] else LFA_Move( file, 0, file, newTagSize, filesize ); // move entire file up. } // correct size stuff, write out header LFA_Rewind( file ); id3Header.write( file, newTagSize); // write out tags for ( XMP_Uns32 i=0; i < framesVector.size(); i++) { if ( framesVector[i]->active) framesVector[i]->write(file, majorVersion); } // write out padding: for ( XMP_Int64 i = newPadding; i > 0;) { const XMP_Uns64 zero = 0; if ( i >= 8 ) // worthwhile optimization { LFA_Write( file, &zero, 8 ); i -= 8; continue; } LFA_Write( file, &zero, 1 ); i--; } // check end of file for ID3v1 tag XMP_Int64 possibleTruncationPoint = LFA_Seek( file, -128, SEEK_END); bool alreadyHasID3v1 = (LFA_ReadInt32_BE( file ) & 0xFFFFFF00) == 0x54414700; // "TAG" if ( ! alreadyHasID3v1 ) // extend file LFA_Extend( file, LFA_Measure( file ) + 128 ); id3v1Tag.write( file, &this->xmpObj ); this->needsUpdate = false; //do last for safety reasons } // MP3_MetaHandler::UpdateFile
bool MakeChunk ( LFA_FileRef inFileRef, RiffState & inOutRiffState, long riffType, UInt32 len ) { long starttag; UInt32 taglen; UInt32 rifflen, avail; UInt64 pos; /* look for top level Premiere padding chunk */ starttag = 0; while ( FindChunk ( inOutRiffState, ckidPremierePadding, riffType, 0, &starttag, &taglen, &pos ) ) { pos -= 8; taglen += 8; long extra = taglen - len; if ( extra < 0 ) continue; RiffIterator iter = inOutRiffState.tags.begin(); iter += (starttag - 1); if ( extra == 0 ) { iter->len = 0; } else { atag pad; UInt64 padpos; /* need 8 bytes extra to be able to split it */ extra -= 8; if ( extra < 0 ) continue; try{ padpos = pos + len; LFA_Seek ( inFileRef, padpos, SEEK_SET ); pad.id = MakeUns32LE ( ckidPremierePadding ); pad.len = MakeUns32LE ( extra ); LFA_Write ( inFileRef, &pad, sizeof(pad) ); } catch ( ... ) { return false; } iter->pos = padpos + 8; iter->len = extra; } /* seek back to start of original padding chunk */ LFA_Seek ( inFileRef, pos, SEEK_SET ); return true; } /* can't take padding chunk, so append new chunk to end of file */ rifflen = inOutRiffState.rifflen + 8; avail = AVIMAXCHUNKSIZE - rifflen; LFA_Seek ( inFileRef, 0, SEEK_END ); pos = GetFilePosition ( inFileRef ); if ( (pos & 1) == 1 ) { // The file length is odd, need a pad byte. XMP_Uns8 pad = 0; LFA_Write ( inFileRef, &pad, 1 ); ++pos; } if ( avail < len ) { /* if needed, create new AVIX chunk */ ltag avix; avix.id = MakeUns32LE ( FOURCC_RIFF ); avix.len = MakeUns32LE ( 4 + len ); avix.subid = MakeUns32LE ( formtypeAVIX ); LFA_Write(inFileRef, &avix, sizeof(avix)); pos += 12; AddTag ( inOutRiffState, avix.id, len, pos, 0, 0, 0 ); } else { /* otherwise, rewrite length of last RIFF chunk in file */ pos = inOutRiffState.riffpos + 4; rifflen = inOutRiffState.rifflen + len; XMP_Uns32 fileLen = MakeUns32LE ( rifflen ); LFA_Seek ( inFileRef, pos, SEEK_SET ); LFA_Write ( inFileRef, &fileLen, 4 ); inOutRiffState.rifflen = rifflen; /* prepare to write data */ LFA_Seek ( inFileRef, 0, SEEK_END ); } return true; }
int FileInfo::Def ( LFA_FileRef source, LFA_FileRef dest ) { int ret, flush; unsigned have; z_stream strm; unsigned char in[CHUNK]; unsigned char out[CHUNK]; // allocate deflate state strm.zalloc = Z_NULL; strm.zfree = Z_NULL; strm.opaque = Z_NULL; ret = deflateInit ( &strm, SWF_DEFAULT_COMPRESSION_LEVEL ); if ( ret != Z_OK ) return ret; // compress until end of file LFA_Seek ( source, SWF_COMPRESSION_BEGIN, SEEK_SET ); XMP_Uns64 outPos = SWF_COMPRESSION_BEGIN; try { do { strm.avail_in = LFA_Read ( source, in, CHUNK ); flush = ( (strm.avail_in < CHUNK) ? Z_FINISH : Z_NO_FLUSH ); strm.next_in = in; // run deflate() on input until output buffer not full, finish // compression if all of source has been read in do { strm.avail_out = CHUNK; strm.next_out = out; ret = deflate ( &strm, flush ); // no bad return value XMP_Assert ( ret != Z_STREAM_ERROR ); // state not clobbered have = CHUNK - strm.avail_out; LFA_Seek ( dest, outPos, SEEK_SET ); LFA_Write ( dest, out, have ); outPos += have; } while ( strm.avail_out == 0 ); XMP_Assert ( strm.avail_in == 0 ); // all input will be used // done when last data in file processed } while ( flush != Z_FINISH ); XMP_Assert ( ret == Z_STREAM_END ); // stream will be complete } catch ( ... ) { deflateEnd ( &strm ); return Z_ERRNO; } /* clean up and return */ deflateEnd ( &strm ); return Z_OK; } // FileInfo::Def
int FileInfo::Inf ( LFA_FileRef source, LFA_FileRef dest ) { int ret; unsigned have; z_stream strm; unsigned char in[CHUNK]; unsigned char out[CHUNK]; XMP_Uns64 allBytes = 0; // allocate inflate state strm.zalloc = Z_NULL; strm.zfree = Z_NULL; strm.opaque = Z_NULL; strm.avail_in = 0; strm.next_in = Z_NULL; ret = inflateInit ( &strm ); if ( ret != Z_OK ) return ret; // decompress until deflate stream ends or end of file LFA_Seek ( source, SWF_COMPRESSION_BEGIN, SEEK_SET ); XMP_Uns64 outPos = SWF_COMPRESSION_BEGIN; try { do { strm.avail_in = LFA_Read ( source, in, CHUNK ); if ( strm.avail_in == 0 ) { ret = Z_STREAM_END; break; } strm.next_in = in; // run inflate() on input until output buffer not full do { strm.avail_out = CHUNK; strm.next_out = out; ret = inflate ( &strm, Z_NO_FLUSH ); XMP_Assert ( ret != Z_STREAM_ERROR ); // state not clobbered switch ( ret ) { case Z_NEED_DICT: ret = Z_DATA_ERROR; // and fall through case Z_DATA_ERROR: case Z_MEM_ERROR: inflateEnd ( &strm ); return ret; } have = CHUNK - strm.avail_out; LFA_Seek ( dest, outPos, SEEK_SET ); LFA_Write ( dest, out, have ); outPos += have; } while ( strm.avail_out == 0 ); // done when inflate() says it's done } while ( ret != Z_STREAM_END ); } catch ( ... ) { inflateEnd ( &strm ); return Z_ERRNO; } // clean up and return inflateEnd ( &strm ); return ( (ret == Z_STREAM_END) ? Z_OK : Z_DATA_ERROR ); } // FileInfo::Inf