void teCompressFile(const teString & from, const teString & to, u32 chunkSize, c8 * chunkInputBuffer, u32 chunkInputBufferSize, c8 * chunkOutputBuffer, u32 chunkOutputBufferSize, u1 highCompression, u1 localPath) { TE_ASSERT(chunkInputBufferSize >= chunkSize); TE_ASSERT(chunkOutputBufferSize >= LZ4_compressBound(chunkSize)); teLZ4CompressionFunction compressionFunction = highCompression ? LZ4_compressHC : LZ4_compress; IBuffer * fileInput = GetFileManager()->OpenFile(from, CFileBuffer::FWM_READ, localPath); if(!fileInput) return; IBuffer * fileOutput = GetFileManager()->OpenFile(to, CFileBuffer::FWM_WRITE, localPath); if(!fileOutput) { TE_SAFE_DROP(fileInput); return; } fileInput->SetStreamMode(true); fileOutput->SetStreamMode(true); fileInput->Lock(BLT_READ); fileInput->SetPosition(0); fileOutput->Lock(BLT_WRITE); fileOutput->SetPosition(0); u32 magicNumber = ARCHIVE_MAGICNUMBER; fileOutput->Write(&magicNumber, ARCHIVE_MAGICNUMBER_SIZE); c8 * inBuffer = chunkInputBuffer; c8 * outBuffer = chunkOutputBuffer; u32 fileSize = 0; while(true) { u32 inSize = teMin(chunkSize, fileInput->GetSize() - fileInput->GetPosition()); fileInput->Read(inBuffer, inSize); fileSize += inSize; if(!inSize) break; u32 outSize = compressionFunction(inBuffer, outBuffer + 4, inSize); *(u32*)outBuffer = outSize; fileOutput->Write(outBuffer, outSize + 4); } fileInput->Unlock(); fileOutput->Unlock(); TE_SAFE_DROP(fileInput); TE_SAFE_DROP(fileOutput); }
void teDecodeFile(const teString & from, const teString & to, u32 chunkSize, c8 * chunkInputBuffer, u32 chunkInputBufferSize, c8 * chunkOutputBuffer, u32 chunkOutputBufferSize, u1 localPath) { TE_ASSERT(chunkInputBufferSize >= LZ4_compressBound(chunkSize)); TE_ASSERT(chunkOutputBufferSize >= chunkSize); IBuffer * fileInput = GetFileManager()->OpenFile(from, CFileBuffer::FWM_READ, localPath); if(!fileInput) return; IBuffer * fileOutput = GetFileManager()->OpenFile(to, CFileBuffer::FWM_WRITE, localPath); if(!fileOutput) { TE_SAFE_DROP(fileInput); return; } fileInput->SetStreamMode(true); fileOutput->SetStreamMode(true); fileInput->Lock(BLT_READ); fileInput->SetPosition(0); u32 magicNumber = u32Max; fileInput->Read(&magicNumber, ARCHIVE_MAGICNUMBER_SIZE); TE_ASSERT(magicNumber == ARCHIVE_MAGICNUMBER); fileOutput->Lock(BLT_WRITE); fileOutput->SetPosition(0); c8 * inBuffer = chunkInputBuffer; c8 * outBuffer = chunkOutputBuffer; while(true) { if((fileInput->GetSize() - fileInput->GetPosition()) < ARCHIVE_MAGICNUMBER_SIZE) break; u32 chunkSizeInFile; fileInput->Read(&chunkSizeInFile, sizeof(u32)); if(chunkSizeInFile == ARCHIVE_MAGICNUMBER) continue; fileInput->Read(inBuffer, chunkSizeInFile); s32 outputSize = LZ4_uncompress_unknownOutputSize(inBuffer, outBuffer, chunkSizeInFile, chunkSize); if(outputSize < 0) { TE_LOG_ERR("lz4 decoding failed, corrupted input\n"); fileInput->Unlock(); fileOutput->Unlock(); TE_SAFE_DROP(fileInput); TE_SAFE_DROP(fileOutput); return; } fileOutput->Write(outBuffer, (u32)outputSize); } fileInput->Unlock(); fileOutput->Unlock(); TE_SAFE_DROP(fileInput); TE_SAFE_DROP(fileOutput); }
ECode InputStreamReader::Read( /* [out] */ ArrayOf<Char32>* buffer, /* [in] */ Int32 offset, /* [in] */ Int32 count, /* [out] */ Int32* number) { VALIDATE_NOT_NULL(number); *number = -1; VALIDATE_NOT_NULL(buffer); AutoLock lock(mLock); if (!IsOpen()) { Logger::E("InputStreamReader", "InputStreamReader is closed. E_IO_EXCEPTION"); return E_IO_EXCEPTION; } FAIL_RETURN(Arrays::CheckOffsetAndCount(buffer->GetLength(), offset, count)); if (count == 0) { *number = 0; return NOERROR; } AutoPtr<ICharBuffer> out; FAIL_RETURN(CharBuffer::Wrap(buffer, offset, count, (ICharBuffer**)&out)); IBuffer* bout = IBuffer::Probe(out); AutoPtr<ICoderResult> UNDERFLOW, result; CCoderResult::GetUNDERFLOW((ICoderResult**)&UNDERFLOW); result = UNDERFLOW; // bytes.remaining() indicates number of bytes in buffer // when 1-st time entered, it'll be equal to zero Boolean hasRemaining, needInput; IBuffer* bBytes = IBuffer::Probe(mBytes); bBytes->HasRemaining(&hasRemaining); needInput = !hasRemaining; Int32 num = 0, position = 0; while (bout->HasRemaining(&hasRemaining), hasRemaining) { // fill the buffer if needed if (needInput) { mIn->Available(&num); bout->GetPosition(&position); if (num == 0 && position > offset) { // we could return the result without blocking read break; } Int32 capacity, limit, arrayOffset; bBytes->GetCapacity(&capacity); bBytes->GetLimit(&limit); bBytes->GetArrayOffset(&arrayOffset); Int32 desiredByteCount = capacity - limit; Int32 off = arrayOffset + limit; AutoPtr<ArrayOf<Byte> > buf; mBytes->GetArray((ArrayOf<Byte>**)&buf); Int32 actualByteCount; mIn->Read(buf, off, desiredByteCount, &actualByteCount); if (actualByteCount == -1) { mEndOfInput = TRUE; break; } else if (actualByteCount == 0) { break; } bBytes->SetLimit(limit + actualByteCount); needInput = FALSE; } // decode bytes result = NULL; mDecoder->Decode(mBytes, out, FALSE, (ICoderResult**)&result); Boolean isUnderflow; result->IsUnderflow(&isUnderflow); if (isUnderflow) { // compact the buffer if no space left Int32 capacity, limit; bBytes->GetLimit(&limit); bBytes->GetCapacity(&capacity); // compact the buffer if no space left if (limit == capacity) { mBytes->Compact(); bBytes->GetPosition(&position); bBytes->SetLimit(position); bBytes->SetPosition(0); } needInput = TRUE; } else { break; } } if (result.Get() == UNDERFLOW.Get() && mEndOfInput) { result = NULL; mDecoder->Decode(mBytes, out, TRUE, (ICoderResult**)&result); if (result.Get() == UNDERFLOW.Get()) { AutoPtr<ICoderResult> resultFlush; mDecoder->Flush(out, (ICoderResult**)&resultFlush); result = resultFlush; } mDecoder->Reset(); } Boolean isMalformed, isUnmappable; result->IsMalformed(&isMalformed); result->IsUnmappable(&isUnmappable); if (isMalformed || isUnmappable) { return result->ThrowException(); } bout->GetPosition(&position); *number = position - offset == 0 ? -1 : position - offset; return NOERROR; }