1
0
mirror of https://github.com/winscp/winscp.git synced 2026-10-24 02:28:55 +03:00
Files
winscp/source/core/FileBuffer.cpp
Martin Prikryl 80bbffa39f Explicit cast
Source commit: e80d288c1fa921eab813c1b3c3ae9723482e8526
2020-05-02 01:44:17 +02:00

290 lines
8.3 KiB
C++

//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Common.h"
#include "FileBuffer.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
//---------------------------------------------------------------------------
const wchar_t * EOLTypeNames = L"LF;CRLF;CR";
//---------------------------------------------------------------------------
char * __fastcall EOLToStr(TEOLType EOLType)
{
switch (EOLType) {
case eolLF: return "\n";
case eolCRLF: return "\r\n";
case eolCR: return "\r";
default: DebugFail(); return "";
}
}
//---------------------------------------------------------------------------
__fastcall TFileBuffer::TFileBuffer()
{
FMemory = new TMemoryStream();
FSize = 0;
}
//---------------------------------------------------------------------------
__fastcall TFileBuffer::~TFileBuffer()
{
delete FMemory;
}
//---------------------------------------------------------------------------
void __fastcall TFileBuffer::SetSize(int value)
{
if (FSize != value)
{
FMemory->Size = value;
FSize = value;
}
}
//---------------------------------------------------------------------------
void __fastcall TFileBuffer::SetPosition(int value)
{
FMemory->Position = value;
}
//---------------------------------------------------------------------------
int __fastcall TFileBuffer::GetPosition() const
{
return (int)FMemory->Position;
}
//---------------------------------------------------------------------------
void __fastcall TFileBuffer::SetMemory(TMemoryStream * value)
{
if (FMemory != value)
{
if (FMemory) delete FMemory;
FMemory = value;
}
}
//---------------------------------------------------------------------------
DWORD __fastcall TFileBuffer::ReadStream(TStream * Stream, const DWORD Len, bool ForceLen)
{
DWORD Result;
try
{
Size = Position + Len;
// C++5
// FMemory->SetSize(FMemory->Position + Len);
if (ForceLen)
{
Stream->ReadBuffer(Data + Position, Len);
Result = Len;
}
else
{
Result = Stream->Read(Data + Position, Len);
}
if (Result != Len)
{
Size = Size - Len + Result;
}
FMemory->Seek(Len, soCurrent);
}
catch(EReadError &)
{
RaiseLastOSError();
}
return Result;
}
//---------------------------------------------------------------------------
DWORD __fastcall TFileBuffer::LoadStream(TStream * Stream, const DWORD Len, bool ForceLen)
{
FMemory->Seek(0, soFromBeginning);
return ReadStream(Stream, Len, ForceLen);
}
//---------------------------------------------------------------------------
void __fastcall TFileBuffer::Convert(char * Source, char * Dest, int Params,
bool & Token)
{
DebugAssert(strlen(Source) <= 2);
DebugAssert(strlen(Dest) <= 2);
if (FLAGSET(Params, cpRemoveBOM) && (Size >= 3) &&
(memcmp(Data, Bom, sizeof(Bom)) == 0))
{
Delete(0, 3);
}
if (FLAGSET(Params, cpRemoveCtrlZ) && (Size > 0) && ((*(Data + Size - 1)) == '\x1A'))
{
Delete(Size-1, 1);
}
if (strcmp(Source, Dest) == 0)
{
return;
}
char * Ptr = Data;
// one character source EOL
if (!Source[1])
{
bool PrevToken = Token;
Token = false;
for (int Index = 0; Index < Size; Index++)
{
// EOL already in destination format, make sure to pass it unmodified
if ((Index < Size - 1) && (*Ptr == Dest[0]) && (*(Ptr+1) == Dest[1]))
{
Index++;
Ptr++;
}
// last buffer ended with the first char of destination 2-char EOL format,
// which got expanded to full destination format.
// now we got the second char, so get rid of it.
else if ((Index == 0) && PrevToken && (*Ptr == Dest[1]))
{
Delete(Index, 1);
}
// we are ending with the first char of destination 2-char EOL format,
// append the second char and make sure we strip it from the next buffer, if any
else if ((*Ptr == Dest[0]) && (Index == Size - 1) && Dest[1])
{
Token = true;
Insert(Index+1, Dest+1, 1);
Index++;
Ptr = Data + Index;
}
else if (*Ptr == Source[0])
{
*Ptr = Dest[0];
if (Dest[1])
{
Insert(Index+1, Dest+1, 1);
Index++;
Ptr = Data + Index;
}
}
Ptr++;
}
}
// two character source EOL
else
{
int Index;
for (Index = 0; Index < Size - 1; Index++)
{
if ((*Ptr == Source[0]) && (*(Ptr+1) == Source[1]))
{
*Ptr = Dest[0];
if (Dest[1])
{
*(Ptr+1) = Dest[1];
Index++; Ptr++;
}
else
{
Delete(Index+1, 1);
Ptr = Data + Index;
}
}
Ptr++;
}
if ((Index < Size) && (*Ptr == Source[0]))
{
Delete(Index, 1);
}
}
}
//---------------------------------------------------------------------------
void __fastcall TFileBuffer::Convert(TEOLType Source, TEOLType Dest, int Params,
bool & Token)
{
Convert(EOLToStr(Source), EOLToStr(Dest), Params, Token);
}
//---------------------------------------------------------------------------
void __fastcall TFileBuffer::Convert(char * Source, TEOLType Dest, int Params,
bool & Token)
{
Convert(Source, EOLToStr(Dest), Params, Token);
}
//---------------------------------------------------------------------------
void __fastcall TFileBuffer::Convert(TEOLType Source, char * Dest, int Params,
bool & Token)
{
Convert(EOLToStr(Source), Dest, Params, Token);
}
//---------------------------------------------------------------------------
void __fastcall TFileBuffer::Insert(int Index, const char * Buf, int Len)
{
Size += Len;
memmove(Data + Index + Len, Data + Index, Size - Index - Len);
memmove(Data + Index, Buf, Len);
}
//---------------------------------------------------------------------------
void __fastcall TFileBuffer::Delete(int Index, int Len)
{
memmove(Data + Index, Data + Index + Len, Size - Index - Len);
Size -= Len;
}
//---------------------------------------------------------------------------
void __fastcall TFileBuffer::WriteToStream(TStream * Stream, const DWORD Len)
{
try
{
Stream->WriteBuffer(Data + Position, Len);
FMemory->Seek(Len, soCurrent);
}
catch(EWriteError &)
{
RaiseLastOSError();
}
}
//---------------------------------------------------------------------------
void __fastcall TFileBuffer::WriteToOut(TTransferOutEvent OnTransferOut, TObject * Sender, const DWORD Len)
{
OnTransferOut(Sender, reinterpret_cast<const unsigned char *>(Data) + Position, Len);
FMemory->Seek(Len, soCurrent);
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
__fastcall TSafeHandleStream::TSafeHandleStream(int AHandle) :
THandleStream(AHandle)
{
}
//---------------------------------------------------------------------------
int __fastcall TSafeHandleStream::Read(void * Buffer, int Count)
{
int Result = FileRead(FHandle, Buffer, Count);
if (Result == -1)
{
RaiseLastOSError();
}
return Result;
}
//---------------------------------------------------------------------------
int __fastcall TSafeHandleStream::Write(const void * Buffer, int Count)
{
int Result = FileWrite(FHandle, Buffer, Count);
if (Result == -1)
{
RaiseLastOSError();
}
return Result;
}
//---------------------------------------------------------------------------
int __fastcall TSafeHandleStream::Read(System::DynamicArray<System::Byte> Buffer, int Offset, int Count)
{
DebugFail(); // untested
int Result = FileRead(FHandle, Buffer, Offset, Count);
if (Result == -1)
{
RaiseLastOSError();
}
return Result;
}
//---------------------------------------------------------------------------
int __fastcall TSafeHandleStream::Write(const System::DynamicArray<System::Byte> Buffer, int Offset, int Count)
{
// This is invoked for example by TIniFileStorage::Flush
int Result = FileWrite(FHandle, Buffer, Offset, Count);
if (Result == -1)
{
RaiseLastOSError();
}
return Result;
}