mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-05-12 03:13:01 +02:00
858 lines
23 KiB
PHP
858 lines
23 KiB
PHP
{
|
|
*********************************************************************
|
|
Copyright (C) 2012 Paul Ishenin,
|
|
member of the Free Pascal Development Team
|
|
|
|
See the file COPYING.FPC, included in this distribution,
|
|
for details about the copyright.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
*********************************************************************
|
|
}
|
|
|
|
{ TEncoding }
|
|
|
|
class function TEncoding.GetANSI: TEncoding;
|
|
begin
|
|
{$ifdef FPC_HAS_FEATURE_THREADING}
|
|
EnterCriticalSection(FLock);
|
|
try
|
|
{$endif}
|
|
if not Assigned(FStandardEncodings[seAnsi]) then
|
|
begin
|
|
if Assigned(widestringmanager.GetStandardCodePageProc) then
|
|
FStandardEncodings[seAnsi] := TMBCSEncoding.Create(widestringmanager.GetStandardCodePageProc(scpAnsi))
|
|
else
|
|
FStandardEncodings[seAnsi] := TMBCSEncoding.Create(DefaultSystemCodePage);
|
|
end;
|
|
{$ifdef FPC_HAS_FEATURE_THREADING}
|
|
finally
|
|
LeaveCriticalSection(FLock);
|
|
end;
|
|
{$endif}
|
|
Result := FStandardEncodings[seAnsi];
|
|
end;
|
|
|
|
function TEncoding.GetAnsiBytes(const S: string): TBytes;
|
|
begin
|
|
if S='' then
|
|
Result := nil
|
|
else
|
|
Result := GetAnsiBytes(S, 1, Length(S));
|
|
end;
|
|
|
|
function TEncoding.GetAnsiBytes(const S: string; CharIndex, CharCount: Integer
|
|
): TBytes;
|
|
begin
|
|
Result := GetAnsiBytes(Pointer(@S[CharIndex]), CharCount);
|
|
end;
|
|
|
|
function TEncoding.GetAnsiString(const Bytes: TBytes): string;
|
|
begin
|
|
if Length(Bytes)=0 then
|
|
Result := ''
|
|
else
|
|
Result := GetAnsiString(Bytes, 0, Length(Bytes));
|
|
end;
|
|
|
|
function TEncoding.GetAnsiString(const Bytes: TBytes; ByteIndex,
|
|
ByteCount: Integer): string;
|
|
begin
|
|
Result := GetAnsiString(Pointer(@Bytes[ByteIndex]), ByteCount);
|
|
SetCodePage(RawByteString(Result), DefaultSystemCodePage, False);
|
|
end;
|
|
|
|
class function TEncoding.GetASCII: TEncoding;
|
|
begin
|
|
{$ifdef FPC_HAS_FEATURE_THREADING}
|
|
EnterCriticalSection(FLock);
|
|
try
|
|
{$endif}
|
|
if not Assigned(FStandardEncodings[seAscii]) then
|
|
FStandardEncodings[seAscii] := TMBCSEncoding.Create(CP_ASCII);
|
|
{$ifdef FPC_HAS_FEATURE_THREADING}
|
|
finally
|
|
LeaveCriticalSection(FLock);
|
|
end;
|
|
{$endif}
|
|
Result := FStandardEncodings[seAscii];
|
|
end;
|
|
|
|
class function TEncoding.GetBigEndianUnicode: TEncoding;
|
|
begin
|
|
{$ifdef FPC_HAS_FEATURE_THREADING}
|
|
EnterCriticalSection(FLock);
|
|
try
|
|
{$endif}
|
|
if not Assigned(FStandardEncodings[seBigEndianUnicode]) then
|
|
FStandardEncodings[seBigEndianUnicode] := TBigEndianUnicodeEncoding.Create;
|
|
{$ifdef FPC_HAS_FEATURE_THREADING}
|
|
finally
|
|
LeaveCriticalSection(FLock);
|
|
end;
|
|
{$endif}
|
|
Result := FStandardEncodings[seBigEndianUnicode];
|
|
end;
|
|
|
|
class function TEncoding.GetDefault: TEncoding;
|
|
begin
|
|
Result := GetSystemEncoding;
|
|
end;
|
|
|
|
class function TEncoding.GetSystemEncoding: TEncoding;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
{$ifdef FPC_HAS_FEATURE_THREADING}
|
|
EnterCriticalSection(FLock);
|
|
try
|
|
{$endif}
|
|
for I := Low(FSystemEncodings) to High(FSystemEncodings) do
|
|
begin
|
|
if FSystemEncodings[I].CodePage=DefaultSystemCodePage then
|
|
begin
|
|
Result := FSystemEncodings[I];
|
|
if I<>Low(FSystemEncodings) then // exchange with first position to find it faster the next time
|
|
begin
|
|
FSystemEncodings[I] := FSystemEncodings[Low(FSystemEncodings)];
|
|
FSystemEncodings[Low(FSystemEncodings)] := Result;
|
|
end;
|
|
Exit;
|
|
end;
|
|
end;
|
|
// not found - create new encoding at first position
|
|
Result := TMBCSEncoding.Create(DefaultSystemCodePage);
|
|
SetLength(FSystemEncodings, Length(FSystemEncodings)+1);
|
|
if High(FSystemEncodings)<>Low(FSystemEncodings) then
|
|
FSystemEncodings[High(FSystemEncodings)] := FSystemEncodings[Low(FSystemEncodings)];
|
|
FSystemEncodings[Low(FSystemEncodings)] := Result;
|
|
{$ifdef FPC_HAS_FEATURE_THREADING}
|
|
finally
|
|
LeaveCriticalSection(FLock);
|
|
end;
|
|
{$endif}
|
|
end;
|
|
|
|
class function TEncoding.GetUnicode: TEncoding;
|
|
begin
|
|
{$ifdef FPC_HAS_FEATURE_THREADING}
|
|
EnterCriticalSection(FLock);
|
|
try
|
|
{$endif}
|
|
if not Assigned(FStandardEncodings[seUnicode]) then
|
|
FStandardEncodings[seUnicode] := TUnicodeEncoding.Create;
|
|
{$ifdef FPC_HAS_FEATURE_THREADING}
|
|
finally
|
|
LeaveCriticalSection(FLock);
|
|
end;
|
|
{$endif}
|
|
Result := FStandardEncodings[seUnicode];
|
|
end;
|
|
|
|
class function TEncoding.GetUTF7: TEncoding;
|
|
begin
|
|
{$ifdef FPC_HAS_FEATURE_THREADING}
|
|
EnterCriticalSection(FLock);
|
|
try
|
|
{$endif}
|
|
if not Assigned(FStandardEncodings[seUTF7]) then
|
|
FStandardEncodings[seUTF7] := TUTF7Encoding.Create;
|
|
{$ifdef FPC_HAS_FEATURE_THREADING}
|
|
finally
|
|
LeaveCriticalSection(FLock);
|
|
end;
|
|
{$endif}
|
|
Result := FStandardEncodings[seUTF7];
|
|
end;
|
|
|
|
class function TEncoding.GetUTF8: TEncoding;
|
|
begin
|
|
{$ifdef FPC_HAS_FEATURE_THREADING}
|
|
EnterCriticalSection(FLock);
|
|
try
|
|
{$endif}
|
|
if not Assigned(FStandardEncodings[seUTF8]) then
|
|
FStandardEncodings[seUTF8] := TUTF8Encoding.Create;
|
|
{$ifdef FPC_HAS_FEATURE_THREADING}
|
|
finally
|
|
LeaveCriticalSection(FLock);
|
|
end;
|
|
{$endif}
|
|
Result := FStandardEncodings[seUTF8];
|
|
end;
|
|
|
|
class procedure TEncoding.FreeEncodings;
|
|
var
|
|
E: TStandardEncoding;
|
|
I: Integer;
|
|
begin
|
|
{$ifdef FPC_HAS_FEATURE_THREADING}
|
|
EnterCriticalSection(FLock);
|
|
try
|
|
{$endif}
|
|
for E := Low(FStandardEncodings) to High(FStandardEncodings) do
|
|
FreeAndNil(FStandardEncodings[E]);
|
|
for I := Low(FSystemEncodings) to High(FSystemEncodings) do
|
|
FSystemEncodings[I].Free;
|
|
SetLength(FSystemEncodings, 0);
|
|
{$ifdef FPC_HAS_FEATURE_THREADING}
|
|
finally
|
|
LeaveCriticalSection(FLock);
|
|
end;
|
|
{$endif}
|
|
end;
|
|
|
|
class constructor TEncoding.Create;
|
|
var
|
|
E: TStandardEncoding;
|
|
begin
|
|
for E := Low(FStandardEncodings) to High(FStandardEncodings) do
|
|
FStandardEncodings[E] := nil;
|
|
{$ifdef FPC_HAS_FEATURE_THREADING}
|
|
InitCriticalSection(FLock);
|
|
{$endif}
|
|
end;
|
|
|
|
class destructor TEncoding.Destroy;
|
|
begin
|
|
FreeEncodings;
|
|
{$ifdef FPC_HAS_FEATURE_THREADING}
|
|
DoneCriticalSection(FLock);
|
|
{$endif}
|
|
end;
|
|
|
|
function TEncoding.Clone: TEncoding;
|
|
begin
|
|
Result := nil;
|
|
end;
|
|
|
|
class function TEncoding.Convert(Source, Destination: TEncoding;
|
|
const Bytes: TBytes): TBytes;
|
|
begin
|
|
Result := Destination.GetBytes(Source.GetChars(Bytes));
|
|
end;
|
|
|
|
class function TEncoding.Convert(Source, Destination: TEncoding;
|
|
const Bytes: TBytes; StartIndex, Count: Integer): TBytes;
|
|
begin
|
|
Result := Destination.GetBytes(Source.GetChars(Bytes, StartIndex, Count));
|
|
end;
|
|
|
|
class function TEncoding.IsStandardEncoding(AEncoding: TEncoding): Boolean;
|
|
var
|
|
Encoding: TEncoding;
|
|
begin
|
|
if Assigned(AEncoding) then
|
|
begin
|
|
for Encoding in FStandardEncodings do
|
|
if Encoding = AEncoding then
|
|
Exit(True);
|
|
for Encoding in FSystemEncodings do
|
|
if Encoding = AEncoding then
|
|
Exit(True);
|
|
end;
|
|
Result := False;
|
|
end;
|
|
|
|
class function TEncoding.GetBufferEncoding(const Buffer: TBytes; var AEncoding: TEncoding): Integer;
|
|
begin
|
|
Result := GetBufferEncoding(Buffer, AEncoding, Default);
|
|
end;
|
|
|
|
class function TEncoding.GetBufferEncoding(const Buffer: TBytes;
|
|
var AEncoding: TEncoding; ADefaultEncoding: TEncoding): Integer;
|
|
|
|
function CheckEncoding(AEncoding: TEncoding; out ByteCount: Integer): Boolean;
|
|
var
|
|
Preamble: TBytes;
|
|
begin
|
|
Preamble := AEncoding.GetPreamble;
|
|
ByteCount := Length(Preamble);
|
|
Result := (Length(Buffer) >= ByteCount) and (ByteCount > 0);
|
|
if Result then
|
|
Result := CompareMem(@Preamble[0], @Buffer[0], ByteCount);
|
|
end;
|
|
|
|
begin
|
|
if Assigned(AEncoding) then
|
|
begin
|
|
if not CheckEncoding(AEncoding, Result) then
|
|
Result := 0;
|
|
end
|
|
else
|
|
if CheckEncoding(Unicode, Result) then
|
|
AEncoding := Unicode
|
|
else
|
|
if CheckEncoding(BigEndianUnicode, Result) then
|
|
AEncoding := BigEndianUnicode
|
|
else
|
|
if CheckEncoding(UTF8, Result) then
|
|
AEncoding := UTF8
|
|
else
|
|
begin
|
|
AEncoding := ADefaultEncoding;
|
|
Result := 0;
|
|
end;
|
|
end;
|
|
|
|
function TEncoding.GetByteCount(const Chars: TUnicodeCharArray): Integer;
|
|
begin
|
|
if Length(Chars)=0 then
|
|
Result := 0
|
|
else
|
|
Result := GetByteCount(Chars, 0, Length(Chars));
|
|
end;
|
|
|
|
function TEncoding.GetByteCount(const Chars: TUnicodeCharArray; CharIndex,
|
|
CharCount: Integer): Integer;
|
|
begin
|
|
if (CharCount < 0) or (Length(Chars) < CharCount + CharIndex) then
|
|
raise EEncodingError.CreateFmt(SInvalidCount, [CharCount]);
|
|
if (CharIndex < 0) then
|
|
raise EEncodingError.CreateFmt(SCharacterIndexOutOfBounds, [CharIndex]);
|
|
Result := GetByteCount(@Chars[CharIndex], CharCount);
|
|
end;
|
|
|
|
function TEncoding.GetByteCount(const S: UnicodeString): Integer;
|
|
begin
|
|
if S='' then
|
|
Result := 0
|
|
else
|
|
Result := GetByteCount(PUnicodeChar(S), Length(S));
|
|
end;
|
|
|
|
function TEncoding.GetByteCount(const S: UnicodeString; CharIndex, CharCount: Integer): Integer;
|
|
begin
|
|
if (CharIndex < 1) then
|
|
raise EEncodingError.CreateFmt(SCharacterIndexOutOfBounds, [CharIndex]);
|
|
if (CharCount < 0) or (Length(S) < CharCount + CharIndex - 1) then
|
|
raise EEncodingError.CreateFmt(SInvalidCount, [CharCount]);
|
|
Result := GetByteCount(@S[CharIndex], CharCount);
|
|
end;
|
|
|
|
function TEncoding.GetBytes(const Chars: TUnicodeCharArray): TBytes;
|
|
begin
|
|
SetLength(Result, GetByteCount(Chars));
|
|
if Length(Result)>0 then
|
|
GetBytes(@Chars[0], Length(Chars), @Result[0], Length(Result));
|
|
end;
|
|
|
|
function TEncoding.GetBytes(const Chars: TUnicodeCharArray; CharIndex,
|
|
CharCount: Integer): TBytes;
|
|
begin
|
|
if (CharCount < 0) or (Length(Chars) < CharCount + CharIndex) then
|
|
raise EEncodingError.CreateFmt(SInvalidCount, [CharCount]);
|
|
if (CharIndex < 0) then
|
|
raise EEncodingError.CreateFmt(SCharacterIndexOutOfBounds, [CharIndex]);
|
|
SetLength(Result, GetByteCount(Chars, CharIndex, CharCount));
|
|
GetBytes(@Chars[CharIndex], CharCount, @Result[0], Length(Result));
|
|
end;
|
|
|
|
function TEncoding.GetBytes(const Chars: TUnicodeCharArray; CharIndex,
|
|
CharCount: Integer; const Bytes: TBytes; ByteIndex: Integer): Integer;
|
|
var
|
|
ByteLen: Integer;
|
|
begin
|
|
ByteLen := Length(Bytes);
|
|
if (ByteLen = 0) and (CharCount > 0) then
|
|
raise EEncodingError.Create(SInvalidDestinationArray);
|
|
if (ByteIndex < 0) or (ByteLen < ByteIndex) then
|
|
raise EEncodingError.CreateFmt(SInvalidDestinationIndex, [ByteIndex]);
|
|
if (CharCount < 0) or (Length(Chars) < CharCount + CharIndex) then
|
|
raise EEncodingError.CreateFmt(SInvalidCount, [CharCount]);
|
|
if (CharIndex < 0) then
|
|
raise EEncodingError.CreateFmt(SCharacterIndexOutOfBounds, [CharIndex]);
|
|
Result := GetBytes(@Chars[CharIndex], CharCount, @Bytes[ByteIndex], ByteLen - ByteIndex);
|
|
end;
|
|
|
|
function TEncoding.GetBytes(const S: UnicodeString): TBytes;
|
|
begin
|
|
SetLength(Result, GetByteCount(S));
|
|
if Length(Result)>0 then
|
|
GetBytes(@S[1], Length(S), @Result[0], Length(Result));
|
|
end;
|
|
|
|
function TEncoding.GetBytes(const S: UnicodeString; CharIndex, CharCount: Integer;
|
|
const Bytes: TBytes; ByteIndex: Integer): Integer;
|
|
var
|
|
ByteLen: Integer;
|
|
begin
|
|
ByteLen := Length(Bytes);
|
|
if (ByteLen = 0) and (CharCount > 0) then
|
|
raise EEncodingError.Create(SInvalidDestinationArray);
|
|
if (ByteIndex < 0) or (ByteLen < ByteIndex) then
|
|
raise EEncodingError.CreateFmt(SInvalidDestinationIndex, [ByteIndex]);
|
|
if (CharIndex < 1) then
|
|
raise EEncodingError.CreateFmt(SCharacterIndexOutOfBounds, [CharIndex]);
|
|
if (CharCount < 0) or (Length(S) < CharCount + CharIndex - 1) then
|
|
raise EEncodingError.CreateFmt(SInvalidCount, [CharCount]);
|
|
Result := GetBytes(@S[CharIndex], CharCount, @Bytes[ByteIndex], ByteLen - ByteIndex);
|
|
end;
|
|
|
|
function TEncoding.GetCharCount(const Bytes: TBytes): Integer;
|
|
begin
|
|
if Length(Bytes)=0 then
|
|
Result := 0
|
|
else
|
|
Result := GetCharCount(@Bytes[0], Length(Bytes));
|
|
end;
|
|
|
|
function TEncoding.GetCharCount(const Bytes: TBytes; ByteIndex,
|
|
ByteCount: Integer): Integer;
|
|
begin
|
|
if (ByteIndex < 0) or (Length(Bytes) < ByteIndex) then
|
|
raise EEncodingError.CreateFmt(SInvalidDestinationIndex, [ByteIndex]);
|
|
Result := GetCharCount(@Bytes[ByteIndex], ByteCount);
|
|
end;
|
|
|
|
function TEncoding.GetChars(const Bytes: TBytes): TUnicodeCharArray;
|
|
begin
|
|
SetLength(Result, GetCharCount(Bytes));
|
|
if Length(Result)>0 then
|
|
GetChars(@Bytes[0], Length(Bytes), @Result[0], Length(Result));
|
|
end;
|
|
|
|
function TEncoding.GetChars(const Bytes: TBytes; ByteIndex, ByteCount: Integer): TUnicodeCharArray;
|
|
begin
|
|
if (ByteIndex < 0) or (Length(Bytes) < ByteIndex) then
|
|
raise EEncodingError.CreateFmt(SInvalidDestinationIndex, [ByteIndex]);
|
|
SetLength(Result, GetCharCount(Bytes, ByteIndex, ByteCount));
|
|
GetChars(@Bytes[ByteIndex], ByteCount, @Result[0], Length(Result));
|
|
end;
|
|
|
|
function TEncoding.GetChars(const Bytes: TBytes; ByteIndex, ByteCount: Integer;
|
|
const Chars: TUnicodeCharArray; CharIndex: Integer): Integer;
|
|
var
|
|
CharLen: Integer;
|
|
begin
|
|
if (ByteIndex < 0) or (Length(Bytes) <= ByteIndex) then
|
|
raise EEncodingError.CreateFmt(SInvalidDestinationIndex, [ByteIndex]);
|
|
CharLen := Length(Chars);
|
|
if (CharIndex < 0) or (CharLen <= CharIndex) then
|
|
raise EEncodingError.CreateFmt(SCharacterIndexOutOfBounds, [CharIndex]);
|
|
Result := GetChars(@Bytes[ByteIndex], ByteCount, @Chars[CharIndex], CharLen - CharIndex);
|
|
end;
|
|
|
|
class function TEncoding.GetEncoding(CodePage: Integer): TEncoding;
|
|
begin
|
|
case CodePage of
|
|
CP_UTF16: Result := TUnicodeEncoding.Create;
|
|
CP_UTF16BE: Result := TBigEndianUnicodeEncoding.Create;
|
|
CP_UTF7: Result := TUTF7Encoding.Create;
|
|
CP_UTF8: Result := TUTF8Encoding.Create;
|
|
else
|
|
Result := TMBCSEncoding.Create(CodePage);
|
|
end;
|
|
end;
|
|
|
|
class function TEncoding.GetEncoding(const EncodingName: UnicodeString): TEncoding;
|
|
var
|
|
ACodePage: TSystemCodePage;
|
|
begin
|
|
ACodePage := CodePageNameToCodePage(AnsiString(EncodingName));
|
|
if ACodePage = $FFFF then
|
|
raise EEncodingError.CreateFmt(SNotValidCodePageName, [EncodingName]);
|
|
Result := GetEncoding(ACodePage);
|
|
end;
|
|
|
|
function TEncoding.GetString(const Bytes: TBytes): UnicodeString;
|
|
var
|
|
Chars: TUnicodeCharArray;
|
|
begin
|
|
if Length(Bytes)=0 then
|
|
Result := ''
|
|
else
|
|
begin
|
|
Chars := GetChars(Bytes);
|
|
SetString(Result, PUnicodeChar(Chars), Length(Chars));
|
|
end;
|
|
end;
|
|
|
|
function TEncoding.GetString(const Bytes: TBytes; ByteIndex, ByteCount: Integer): UnicodeString;
|
|
var
|
|
Chars: TUnicodeCharArray;
|
|
begin
|
|
Chars := GetChars(Bytes, ByteIndex, ByteCount);
|
|
SetString(Result, PUnicodeChar(Chars), Length(Chars));
|
|
end;
|
|
|
|
{ TMBCSEncoding }
|
|
|
|
function TMBCSEncoding.GetByteCount(Chars: PUnicodeChar; CharCount: Integer): Integer;
|
|
var
|
|
S: RawByteString;
|
|
begin
|
|
widestringmanager.Unicode2AnsiMoveProc(Chars, S, CodePage, CharCount);
|
|
Result := Length(S);
|
|
end;
|
|
|
|
function TMBCSEncoding.GetBytes(Chars: PUnicodeChar; CharCount: Integer; Bytes: PByte;
|
|
ByteCount: Integer): Integer;
|
|
var
|
|
S: RawByteString;
|
|
begin
|
|
widestringmanager.Unicode2AnsiMoveProc(Chars, S, CodePage, CharCount);
|
|
Result := Length(S);
|
|
if ByteCount < Result then
|
|
Result := ByteCount;
|
|
if Result > 0 then
|
|
Move(S[1], Bytes[0], Result);
|
|
end;
|
|
|
|
function TMBCSEncoding.GetCharCount(Bytes: PByte; ByteCount: Integer): Integer;
|
|
var
|
|
U: UnicodeString;
|
|
begin
|
|
widestringmanager.Ansi2UnicodeMoveProc(PChar(Bytes), CodePage, U, ByteCount);
|
|
Result := Length(U);
|
|
end;
|
|
|
|
function TMBCSEncoding.GetChars(Bytes: PByte; ByteCount: Integer; Chars: PUnicodeChar;
|
|
CharCount: Integer): Integer;
|
|
var
|
|
U: UnicodeString;
|
|
begin
|
|
widestringmanager.Ansi2UnicodeMoveProc(PChar(Bytes), CodePage, U, ByteCount);
|
|
Result := Length(U);
|
|
if CharCount < Result then
|
|
Result := CharCount;
|
|
if Result > 0 then
|
|
Move(U[1], Chars[0], Result * SizeOf(UnicodeChar));
|
|
end;
|
|
|
|
function TMBCSEncoding.GetCodePage: Cardinal;
|
|
begin
|
|
Result := FCodePage;
|
|
end;
|
|
|
|
function TMBCSEncoding.GetEncodingName: UnicodeString;
|
|
begin
|
|
Result := UnicodeString(CodePageToCodePageName(CodePage));
|
|
end;
|
|
|
|
constructor TMBCSEncoding.Create;
|
|
begin
|
|
Create(DefaultSystemCodePage, 0, 0);
|
|
end;
|
|
|
|
constructor TMBCSEncoding.Create(ACodePage: Integer);
|
|
begin
|
|
Create(ACodePage, 0, 0);
|
|
end;
|
|
|
|
constructor TMBCSEncoding.Create(ACodePage, MBToWCharFlags,
|
|
WCharToMBFlags: Integer);
|
|
begin
|
|
FCodePage := ACodePage;
|
|
FMBToWCharFlags := MBToWCharFlags;
|
|
FWCharToMBFlags := WCharToMBFlags;
|
|
case ACodePage of
|
|
CP_UTF7, CP_UTF8, CP_UTF16, CP_UTF16BE: FIsSingleByte := False;
|
|
else
|
|
FIsSingleByte := True;
|
|
end;
|
|
end;
|
|
|
|
function TMBCSEncoding.Clone: TEncoding;
|
|
begin
|
|
Result := TMBCSEncoding.Create(FCodePage, FMBToWCharFlags, FWCharToMBFlags);
|
|
end;
|
|
|
|
function TMBCSEncoding.GetAnsiBytes(Chars: PChar; CharCount: Integer): TBytes;
|
|
var
|
|
S: RawByteString;
|
|
begin
|
|
SetString(S, Chars, CharCount);
|
|
SetCodePage(S, DefaultSystemCodePage, False);
|
|
SetCodePage(S, GetCodePage, True);
|
|
SetLength(Result, Length(S));
|
|
if Length(S)>0 then
|
|
Move(S[1], Result[0], Length(S));
|
|
end;
|
|
|
|
function TMBCSEncoding.GetAnsiString(Bytes: PByte; ByteCount: Integer): string;
|
|
begin
|
|
SetString(Result, Pointer(Bytes), ByteCount);
|
|
SetCodePage(RawByteString(Result), GetCodePage, False);
|
|
SetCodePage(RawByteString(Result), DefaultSystemCodePage, True);
|
|
end;
|
|
|
|
function TMBCSEncoding.GetMaxByteCount(CharCount: Integer): Integer;
|
|
begin
|
|
Result := CharCount;
|
|
end;
|
|
|
|
function TMBCSEncoding.GetMaxCharCount(ByteCount: Integer): Integer;
|
|
begin
|
|
Result := ByteCount;
|
|
end;
|
|
|
|
function TMBCSEncoding.GetPreamble: TBytes;
|
|
begin
|
|
case CodePage of
|
|
CP_UTF8:
|
|
begin
|
|
SetLength(Result, 3);
|
|
Result[0] := $EF;
|
|
Result[1] := $BB;
|
|
Result[2] := $BF;
|
|
end;
|
|
CP_UTF16:
|
|
begin
|
|
SetLength(Result, 2);
|
|
Result[0] := $FF;
|
|
Result[1] := $FE;
|
|
end;
|
|
CP_UTF16BE:
|
|
begin
|
|
SetLength(Result, 2);
|
|
Result[0] := $FE;
|
|
Result[1] := $FF;
|
|
end;
|
|
else
|
|
Result := nil;
|
|
end;
|
|
end;
|
|
|
|
{ TUTF7Encoding }
|
|
|
|
constructor TUTF7Encoding.Create;
|
|
begin
|
|
inherited Create(CP_UTF7);
|
|
FIsSingleByte := False;
|
|
end;
|
|
|
|
function TUTF7Encoding.Clone: TEncoding;
|
|
begin
|
|
Result := TUTF7Encoding.Create;
|
|
end;
|
|
|
|
function TUTF7Encoding.GetMaxByteCount(CharCount: Integer): Integer;
|
|
begin
|
|
Result := CharCount * 3 + 2;
|
|
end;
|
|
|
|
function TUTF7Encoding.GetMaxCharCount(ByteCount: Integer): Integer;
|
|
begin
|
|
Result := ByteCount;
|
|
end;
|
|
|
|
{ TUTF8Encoding }
|
|
|
|
constructor TUTF8Encoding.Create;
|
|
begin
|
|
inherited Create(CP_UTF8);
|
|
FIsSingleByte := False;
|
|
end;
|
|
|
|
function TUTF8Encoding.Clone: TEncoding;
|
|
begin
|
|
Result := TUTF8Encoding.Create;
|
|
end;
|
|
|
|
function TUTF8Encoding.GetMaxByteCount(CharCount: Integer): Integer;
|
|
begin
|
|
Result := CharCount * 3;
|
|
end;
|
|
|
|
function TUTF8Encoding.GetMaxCharCount(ByteCount: Integer): Integer;
|
|
begin
|
|
Result := ByteCount;
|
|
end;
|
|
|
|
function TUTF8Encoding.GetPreamble: TBytes;
|
|
begin
|
|
SetLength(Result, 3);
|
|
Result[0] := $EF;
|
|
Result[1] := $BB;
|
|
Result[2] := $BF;
|
|
end;
|
|
|
|
{ TUnicodeEncoding }
|
|
|
|
function TUnicodeEncoding.GetByteCount(Chars: PUnicodeChar; CharCount: Integer): Integer;
|
|
begin
|
|
Result := CharCount * SizeOf(UnicodeChar);
|
|
end;
|
|
|
|
function TUnicodeEncoding.GetBytes(Chars: PUnicodeChar; CharCount: Integer;
|
|
Bytes: PByte; ByteCount: Integer): Integer;
|
|
begin
|
|
Result := CharCount * SizeOf(UnicodeChar);
|
|
if ByteCount < Result then
|
|
Result := ByteCount;
|
|
if Result > 0 then
|
|
Move(Chars[0], Bytes[0], Result);
|
|
end;
|
|
|
|
function TUnicodeEncoding.GetCharCount(Bytes: PByte; ByteCount: Integer): Integer;
|
|
begin
|
|
Result := ByteCount div SizeOf(UnicodeChar);
|
|
end;
|
|
|
|
function TUnicodeEncoding.GetChars(Bytes: PByte; ByteCount: Integer;
|
|
Chars: PUnicodeChar; CharCount: Integer): Integer;
|
|
begin
|
|
Result := ByteCount div 2;
|
|
if CharCount < Result then
|
|
Result := CharCount;
|
|
Move(Bytes[0], Chars[0], Result * SizeOf(UnicodeChar));
|
|
end;
|
|
|
|
function TUnicodeEncoding.GetCodePage: Cardinal;
|
|
begin
|
|
Result := CP_UTF16;
|
|
end;
|
|
|
|
function TUnicodeEncoding.GetEncodingName: UnicodeString;
|
|
begin
|
|
Result := UnicodeString(CodePageToCodePageName(CodePage));
|
|
end;
|
|
|
|
constructor TUnicodeEncoding.Create;
|
|
begin
|
|
inherited Create;
|
|
FIsSingleByte := False;
|
|
FMaxCharSize := SizeOf(UnicodeChar);
|
|
end;
|
|
|
|
function TUnicodeEncoding.Clone: TEncoding;
|
|
begin
|
|
Result := TUnicodeEncoding.Create;
|
|
end;
|
|
|
|
function TUnicodeEncoding.GetAnsiBytes(Chars: PChar; CharCount: Integer
|
|
): TBytes;
|
|
var
|
|
U: UnicodeString;
|
|
begin
|
|
widestringmanager.Ansi2UnicodeMoveProc(Chars, DefaultSystemCodePage, U, CharCount);
|
|
SetLength(Result, Length(U)*SizeOf(UnicodeChar));
|
|
if Length(Result)>0 then
|
|
Move(U[1], Result[0], Length(Result));
|
|
end;
|
|
|
|
function TUnicodeEncoding.GetAnsiString(Bytes: PByte; ByteCount: Integer
|
|
): string;
|
|
begin
|
|
widestringmanager.Unicode2AnsiMoveProc(PUnicodeChar(Bytes), RawByteString(Result), DefaultSystemCodePage, ByteCount div SizeOf(UnicodeChar));
|
|
end;
|
|
|
|
function TUnicodeEncoding.GetMaxByteCount(CharCount: Integer): Integer;
|
|
begin
|
|
Result := CharCount * SizeOf(UnicodeChar);
|
|
end;
|
|
|
|
function TUnicodeEncoding.GetMaxCharCount(ByteCount: Integer): Integer;
|
|
begin
|
|
Result := ByteCount div SizeOf(UnicodeChar);
|
|
end;
|
|
|
|
function TUnicodeEncoding.GetPreamble: TBytes;
|
|
begin
|
|
SetLength(Result, 2);
|
|
Result[0] := $FF;
|
|
Result[1] := $FE;
|
|
end;
|
|
|
|
{ TBigEndianUnicodeEncoding }
|
|
|
|
function TBigEndianUnicodeEncoding.GetBytes(Chars: PUnicodeChar; CharCount: Integer;
|
|
Bytes: PByte; ByteCount: Integer): Integer;
|
|
var
|
|
LastByte: PByte;
|
|
begin
|
|
Result := CharCount * SizeOf(UnicodeChar);
|
|
if ByteCount < Result then
|
|
Result := ByteCount;
|
|
LastByte := @Bytes[Result];
|
|
while Bytes < LastByte do
|
|
begin
|
|
Bytes^ := Hi(Word(Chars^));
|
|
inc(Bytes);
|
|
if Bytes < LastByte then
|
|
Bytes^ := Lo(Word(Chars^));
|
|
inc(Bytes);
|
|
inc(Chars);
|
|
end;
|
|
end;
|
|
|
|
function TBigEndianUnicodeEncoding.GetChars(Bytes: PByte; ByteCount: Integer;
|
|
Chars: PUnicodeChar; CharCount: Integer): Integer;
|
|
var
|
|
LastChar: PUnicodeChar;
|
|
begin
|
|
Result := ByteCount div SizeOf(UnicodeChar);
|
|
if CharCount < Result then
|
|
Result := CharCount;
|
|
LastChar := @Chars[Result];
|
|
while Chars < LastChar do
|
|
begin
|
|
Chars^ := UnicodeChar(Bytes[1] + Bytes[0] shl 8);
|
|
inc(Bytes, SizeOf(UnicodeChar));
|
|
inc(Chars);
|
|
end;
|
|
end;
|
|
|
|
function TBigEndianUnicodeEncoding.GetCodePage: Cardinal;
|
|
begin
|
|
Result := CP_UTF16BE;
|
|
end;
|
|
|
|
function TBigEndianUnicodeEncoding.GetEncodingName: UnicodeString;
|
|
begin
|
|
Result := UnicodeString(CodePageToCodePageName(CodePage));
|
|
end;
|
|
|
|
function TBigEndianUnicodeEncoding.Clone: TEncoding;
|
|
begin
|
|
Result := TBigEndianUnicodeEncoding.Create;
|
|
end;
|
|
|
|
function TBigEndianUnicodeEncoding.GetAnsiBytes(Chars: PChar; CharCount: Integer
|
|
): TBytes;
|
|
begin
|
|
Result := TEncoding.Unicode.GetAnsiBytes(Chars, CharCount);
|
|
Swap(Result);
|
|
end;
|
|
|
|
function TBigEndianUnicodeEncoding.GetAnsiString(Bytes: PByte;
|
|
ByteCount: Integer): string;
|
|
var
|
|
B: TBytes;
|
|
begin
|
|
if ByteCount=0 then
|
|
Exit('');
|
|
|
|
SetLength(B, ByteCount);
|
|
Move(Bytes^, B[0], ByteCount);
|
|
Swap(B);
|
|
|
|
Result := TEncoding.Unicode.GetAnsiString(PByte(@B[0]), ByteCount);
|
|
end;
|
|
|
|
function TBigEndianUnicodeEncoding.GetPreamble: TBytes;
|
|
begin
|
|
SetLength(Result, 2);
|
|
Result[0] := $FE;
|
|
Result[1] := $FF;
|
|
end;
|
|
|
|
procedure TBigEndianUnicodeEncoding.Swap(var B: TBytes);
|
|
var
|
|
LastB, I: Integer;
|
|
C: Byte;
|
|
begin
|
|
LastB := Length(B)-1;
|
|
I := 0;
|
|
while I < LastB do
|
|
begin
|
|
C := B[I];
|
|
B[I] := B[I+1];
|
|
B[I+1] := C;
|
|
Inc(I, 2);
|
|
end;
|
|
end;
|