123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197 |
- #include "rar.hpp"
- RawRead::RawRead()
- {
- RawRead::SrcFile=NULL;
- Reset();
- }
- RawRead::RawRead(File *SrcFile)
- {
- RawRead::SrcFile=SrcFile;
- Reset();
- }
- void RawRead::Reset()
- {
- Data.SoftReset();
- ReadPos=0;
- DataSize=0;
- Crypt=NULL;
- }
- size_t RawRead::Read(size_t Size)
- {
- size_t ReadSize=0;
- #if !defined(RAR_NOCRYPT)
- if (Crypt!=NULL)
- {
- // Full size of buffer with already read data including data read
- // for encryption block alignment.
- size_t FullSize=Data.Size();
- // Data read for alignment and not processed yet.
- size_t DataLeft=FullSize-DataSize;
- if (Size>DataLeft) // Need to read more than we already have.
- {
- size_t SizeToRead=Size-DataLeft;
- size_t AlignedReadSize=SizeToRead+((~SizeToRead+1) & CRYPT_BLOCK_MASK);
- Data.Add(AlignedReadSize);
- ReadSize=SrcFile->Read(&Data[FullSize],AlignedReadSize);
- Crypt->DecryptBlock(&Data[FullSize],AlignedReadSize);
- DataSize+=ReadSize==0 ? 0:Size;
- }
- else // Use buffered data, no real read.
- {
- ReadSize=Size;
- DataSize+=Size;
- }
- }
- else
- #endif
- if (Size!=0)
- {
- Data.Add(Size);
- ReadSize=SrcFile->Read(&Data[DataSize],Size);
- DataSize+=ReadSize;
- }
- return ReadSize;
- }
- void RawRead::Read(byte *SrcData,size_t Size)
- {
- if (Size!=0)
- {
- Data.Add(Size);
- memcpy(&Data[DataSize],SrcData,Size);
- DataSize+=Size;
- }
- }
- byte RawRead::Get1()
- {
- return ReadPos<DataSize ? Data[ReadPos++]:0;
- }
- ushort RawRead::Get2()
- {
- if (ReadPos+1<DataSize)
- {
- ushort Result=Data[ReadPos]+(Data[ReadPos+1]<<8);
- ReadPos+=2;
- return Result;
- }
- return 0;
- }
- uint RawRead::Get4()
- {
- if (ReadPos+3<DataSize)
- {
- uint Result=Data[ReadPos]+(Data[ReadPos+1]<<8)+(Data[ReadPos+2]<<16)+
- (Data[ReadPos+3]<<24);
- ReadPos+=4;
- return Result;
- }
- return 0;
- }
- uint64 RawRead::Get8()
- {
- uint Low=Get4(),High=Get4();
- return INT32TO64(High,Low);
- }
- uint64 RawRead::GetV()
- {
- uint64 Result=0;
- // Need to check Shift<64, because for shift greater than or equal to
- // the width of the promoted left operand, the behavior is undefined.
- for (uint Shift=0;ReadPos<DataSize && Shift<64;Shift+=7)
- {
- byte CurByte=Data[ReadPos++];
- Result+=uint64(CurByte & 0x7f)<<Shift;
- if ((CurByte & 0x80)==0)
- return Result; // Decoded successfully.
- }
- return 0; // Out of buffer border.
- }
- // Return a number of bytes in current variable length integer.
- uint RawRead::GetVSize(size_t Pos)
- {
- for (size_t CurPos=Pos;CurPos<DataSize;CurPos++)
- if ((Data[CurPos] & 0x80)==0)
- return int(CurPos-Pos+1);
- return 0; // Buffer overflow.
- }
- size_t RawRead::GetB(void *Field,size_t Size)
- {
- byte *F=(byte *)Field;
- size_t CopySize=Min(DataSize-ReadPos,Size);
- if (CopySize>0)
- memcpy(F,&Data[ReadPos],CopySize);
- if (Size>CopySize)
- memset(F+CopySize,0,Size-CopySize);
- ReadPos+=CopySize;
- return CopySize;
- }
- void RawRead::GetW(wchar *Field,size_t Size)
- {
- if (ReadPos+2*Size-1<DataSize)
- {
- RawToWide(&Data[ReadPos],Field,Size);
- ReadPos+=sizeof(wchar)*Size;
- }
- else
- memset(Field,0,sizeof(wchar)*Size);
- }
- uint RawRead::GetCRC15(bool ProcessedOnly) // RAR 1.5 block CRC.
- {
- if (DataSize<=2)
- return 0;
- uint HeaderCRC=CRC32(0xffffffff,&Data[2],(ProcessedOnly ? ReadPos:DataSize)-2);
- return ~HeaderCRC & 0xffff;
- }
- uint RawRead::GetCRC50() // RAR 5.0 block CRC.
- {
- if (DataSize<=4)
- return 0xffffffff;
- return CRC32(0xffffffff,&Data[4],DataSize-4) ^ 0xffffffff;
- }
- // Read vint from arbitrary byte array.
- uint64 RawGetV(const byte *Data,uint &ReadPos,uint DataSize,bool &Overflow)
- {
- Overflow=false;
- uint64 Result=0;
- for (uint Shift=0;ReadPos<DataSize;Shift+=7)
- {
- byte CurByte=Data[ReadPos++];
- Result+=uint64(CurByte & 0x7f)<<Shift;
- if ((CurByte & 0x80)==0)
- return Result; // Decoded successfully.
- }
- Overflow=true;
- return 0; // Out of buffer border.
- }
|