| // FindSignature.cpp |
| |
| #include "StdAfx.h" |
| |
| #include "Common/Buffer.h" |
| |
| #include "FindSignature.h" |
| |
| #include "../../Common/StreamUtils.h" |
| |
| HRESULT FindSignatureInStream(ISequentialInStream *stream, |
| const Byte *signature, unsigned signatureSize, |
| const UInt64 *limit, UInt64 &resPos) |
| { |
| resPos = 0; |
| CByteBuffer byteBuffer2; |
| byteBuffer2.SetCapacity(signatureSize); |
| RINOK(ReadStream_FALSE(stream, byteBuffer2, signatureSize)); |
| |
| if (memcmp(byteBuffer2, signature, signatureSize) == 0) |
| return S_OK; |
| |
| const UInt32 kBufferSize = (1 << 16); |
| CByteBuffer byteBuffer; |
| byteBuffer.SetCapacity(kBufferSize); |
| Byte *buffer = byteBuffer; |
| UInt32 numPrevBytes = signatureSize - 1; |
| memcpy(buffer, (const Byte *)byteBuffer2 + 1, numPrevBytes); |
| resPos = 1; |
| for (;;) |
| { |
| if (limit != NULL) |
| if (resPos > *limit) |
| return S_FALSE; |
| do |
| { |
| UInt32 numReadBytes = kBufferSize - numPrevBytes; |
| UInt32 processedSize; |
| RINOK(stream->Read(buffer + numPrevBytes, numReadBytes, &processedSize)); |
| numPrevBytes += processedSize; |
| if (processedSize == 0) |
| return S_FALSE; |
| } |
| while (numPrevBytes < signatureSize); |
| UInt32 numTests = numPrevBytes - signatureSize + 1; |
| for (UInt32 pos = 0; pos < numTests; pos++) |
| { |
| Byte b = signature[0]; |
| for (; buffer[pos] != b && pos < numTests; pos++); |
| if (pos == numTests) |
| break; |
| if (memcmp(buffer + pos, signature, signatureSize) == 0) |
| { |
| resPos += pos; |
| return S_OK; |
| } |
| } |
| resPos += numTests; |
| numPrevBytes -= numTests; |
| memmove(buffer, buffer + numTests, numPrevBytes); |
| } |
| } |