📄 tntclasses.pas
字号:
Result := True;
break; { found a string with non-ASCII chars (> 127) }
end;
end;
end;
{$ENDIF}
begin
inherited DefineProperties(Filer); { Handles main 'Strings' property.' }
Filer.DefineProperty('WideStrings', ReadData, nil, False);
Filer.DefineProperty('WideStringsW', ReadDataUTF8, nil, False);
{$IFDEF COMPILER_7_UP}
Filer.DefineProperty('WideStrings_UTF7', ReadDataUTF7, WriteDataUTF7, False);
{$ELSE}
Filer.DefineProperty('WideStrings_UTF7', ReadDataUTF7, WriteDataUTF7, DoWrite and DoWriteAsUTF7);
{$ENDIF}
end;
procedure TTntStrings.LoadFromFile(const FileName: WideString);
var
Stream: TStream;
begin
Stream := TTntFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
try
FLastFileCharSet := AutoDetectCharacterSet(Stream);
Stream.Position := 0;
LoadFromStream(Stream);
finally
Stream.Free;
end;
end;
procedure TTntStrings.LoadFromStream(Stream: TStream);
begin
LoadFromStream_BOM(Stream, True);
end;
procedure TTntStrings.LoadFromStream_BOM(Stream: TStream; WithBOM: Boolean);
var
DataLeft: Integer;
StreamCharSet: TTntStreamCharSet;
SW: WideString;
SA: AnsiString;
begin
BeginUpdate;
try
if WithBOM then
StreamCharSet := AutoDetectCharacterSet(Stream)
else
StreamCharSet := csUnicode;
DataLeft := Stream.Size - Stream.Position;
if (StreamCharSet in [csUnicode, csUnicodeSwapped]) then
begin
// BOM indicates Unicode text stream
if DataLeft < SizeOf(WideChar) then
SW := ''
else begin
SetLength(SW, DataLeft div SizeOf(WideChar));
Stream.Read(PWideChar(SW)^, DataLeft);
if StreamCharSet = csUnicodeSwapped then
StrSwapByteOrder(PWideChar(SW));
end;
SetTextStr(SW);
end
else if StreamCharSet = csUtf8 then
begin
// BOM indicates UTF-8 text stream
SetLength(SA, DataLeft div SizeOf(AnsiChar));
Stream.Read(PAnsiChar(SA)^, DataLeft);
SetTextStr(UTF8ToWideString(SA));
end
else
begin
// without byte order mark it is assumed that we are loading ANSI text
SetLength(SA, DataLeft div SizeOf(AnsiChar));
Stream.Read(PAnsiChar(SA)^, DataLeft);
SetTextStr(SA);
end;
finally
EndUpdate;
end;
end;
procedure TTntStrings.ReadData(Reader: TReader);
begin
if Reader.NextValue in [vaString, vaLString] then
SetTextStr(Reader.ReadString) {JCL compatiblity}
else if Reader.NextValue = vaWString then
SetTextStr(Reader.ReadWideString) {JCL compatiblity}
else begin
BeginUpdate;
try
Clear;
Reader.ReadListBegin;
while not Reader.EndOfList do
if Reader.NextValue in [vaString, vaLString] then
Add(Reader.ReadString) {TStrings compatiblity}
else
Add(Reader.ReadWideString);
Reader.ReadListEnd;
finally
EndUpdate;
end;
end;
end;
procedure TTntStrings.ReadDataUTF7(Reader: TReader);
begin
Reader.ReadListBegin;
if ReaderNeedsUtfHelp(Reader) then
begin
BeginUpdate;
try
Clear;
while not Reader.EndOfList do
Add(UTF7ToWideString(Reader.ReadString))
finally
EndUpdate;
end;
end else begin
while not Reader.EndOfList do
Reader.ReadString; { do nothing with Result }
end;
Reader.ReadListEnd;
end;
procedure TTntStrings.ReadDataUTF8(Reader: TReader);
begin
Reader.ReadListBegin;
if ReaderNeedsUtfHelp(Reader)
or (Count = 0){ Legacy support where 'WideStrings' was never written in lieu of WideStringsW }
then begin
BeginUpdate;
try
Clear;
while not Reader.EndOfList do
Add(UTF8ToWideString(Reader.ReadString))
finally
EndUpdate;
end;
end else begin
while not Reader.EndOfList do
Reader.ReadString; { do nothing with Result }
end;
Reader.ReadListEnd;
end;
procedure TTntStrings.SaveToFile(const FileName: WideString);
var
Stream: TStream;
begin
Stream := TTntFileStream.Create(FileName, fmCreate);
try
SaveToStream(Stream);
finally
Stream.Free;
end;
end;
procedure TTntStrings.SaveToStream(Stream: TStream);
begin
SaveToStream_BOM(Stream, True);
end;
procedure TTntStrings.SaveToStream_BOM(Stream: TStream; WithBOM: Boolean);
// Saves the currently loaded text into the given stream.
// WithBOM determines whether to write a byte order mark or not.
var
SW: WideString;
BOM: WideChar;
begin
if WithBOM then begin
BOM := UNICODE_BOM;
Stream.WriteBuffer(BOM, SizeOf(WideChar));
end;
SW := GetTextStr;
Stream.WriteBuffer(PWideChar(SW)^, Length(SW) * SizeOf(WideChar));
end;
procedure TTntStrings.WriteDataUTF7(Writer: TWriter);
var
I: Integer;
begin
Writer.WriteListBegin;
for I := 0 to Count-1 do
Writer.WriteString(WideStringToUTF7(Get(I)));
Writer.WriteListEnd;
end;
{ TTntStringList }
destructor TTntStringList.Destroy;
begin
FOnChange := nil;
FOnChanging := nil;
inherited Destroy;
if FCount <> 0 then Finalize(FList^[0], FCount);
FCount := 0;
SetCapacity(0);
end;
function TTntStringList.Add(const S: WideString): Integer;
begin
Result := AddObject(S, nil);
end;
function TTntStringList.AddObject(const S: WideString; AObject: TObject): Integer;
begin
if not Sorted then
Result := FCount
else
if Find(S, Result) then
case Duplicates of
dupIgnore: Exit;
dupError: Error(PResStringRec(@SDuplicateString), 0);
end;
InsertItem(Result, S, AObject);
end;
procedure TTntStringList.Changed;
begin
if (not FUpdating) and Assigned(FOnChange) then
FOnChange(Self);
end;
procedure TTntStringList.Changing;
begin
if (not FUpdating) and Assigned(FOnChanging) then
FOnChanging(Self);
end;
procedure TTntStringList.Clear;
begin
if FCount <> 0 then
begin
Changing;
Finalize(FList^[0], FCount);
FCount := 0;
SetCapacity(0);
Changed;
end;
end;
procedure TTntStringList.Delete(Index: Integer);
begin
if (Index < 0) or (Index >= FCount) then Error(PResStringRec(@SListIndexError), Index);
Changing;
Finalize(FList^[Index]);
Dec(FCount);
if Index < FCount then
System.Move(FList^[Index + 1], FList^[Index],
(FCount - Index) * SizeOf(TWideStringItem));
Changed;
end;
procedure TTntStringList.Exchange(Index1, Index2: Integer);
begin
if (Index1 < 0) or (Index1 >= FCount) then Error(PResStringRec(@SListIndexError), Index1);
if (Index2 < 0) or (Index2 >= FCount) then Error(PResStringRec(@SListIndexError), Index2);
Changing;
ExchangeItems(Index1, Index2);
Changed;
end;
procedure TTntStringList.ExchangeItems(Index1, Index2: Integer);
var
Temp: Integer;
Item1, Item2: PWideStringItem;
begin
Item1 := @FList^[Index1];
Item2 := @FList^[Index2];
Temp := Integer(Item1^.FString);
Integer(Item1^.FString) := Integer(Item2^.FString);
Integer(Item2^.FString) := Temp;
Temp := Integer(Item1^.FObject);
Integer(Item1^.FObject) := Integer(Item2^.FObject);
Integer(Item2^.FObject) := Temp;
end;
function TTntStringList.Find(const S: WideString; var Index: Integer): Boolean;
var
L, H, I, C: Integer;
begin
Result := False;
L := 0;
H := FCount - 1;
while L <= H do
begin
I := (L + H) shr 1;
C := CompareStrings(FList^[I].FString, S);
if C < 0 then L := I + 1 else
begin
H := I - 1;
if C = 0 then
begin
Result := True;
if Duplicates <> dupAccept then L := I;
end;
end;
end;
Index := L;
end;
function TTntStringList.Get(Index: Integer): WideString;
begin
if (Index < 0) or (Index >= FCount) then Error(PResStringRec(@SListIndexError), Index);
Result := FList^[Index].FString;
end;
function TTntStringList.GetCapacity: Integer;
begin
Result := FCapacity;
end;
function TTntStringList.GetCount: Integer;
begin
Result := FCount;
end;
function TTntStringList.GetObject(Index: Integer): TObject;
begin
if (Index < 0) or (Index >= FCount) then Error(PResStringRec(@SListIndexError), Index);
Result := FList^[Index].FObject;
end;
procedure TTntStringList.Grow;
var
Delta: Integer;
begin
if FCapacity > 64 then Delta := FCapacity div 4 else
if FCapacity > 8 then Delta := 16 else
Delta := 4;
SetCapacity(FCapacity + Delta);
end;
function TTntStringList.IndexOf(const S: WideString): Integer;
begin
if not Sorted then Result := inherited IndexOf(S) else
if not Find(S, Result) then Result := -1;
end;
function TTntStringList.IndexOfName(const Name: WideString): Integer;
var
NameKey: WideString;
begin
if not Sorted then
Result := inherited IndexOfName(Name)
else begin
// use sort to find index more quickly
NameKey := Name + NameValueSeparator;
Find(NameKey, Result);
if (Result < 0) or (Result > Count - 1) then
Result := -1
else if CompareStrings(NameKey, Copy(Strings[Result], 1, Length(NameKey))) <> 0 then
Result := -1
end;
end;
procedure TTntStringList.Insert(Index: Integer; const S: WideString);
begin
InsertObject(Index, S, nil);
end;
procedure TTntStringList.InsertObject(Index: Integer; const S: WideString;
AObject: TObject);
begin
if Sorted then Error(PResStringRec(@SSortedListError), 0);
if (Index < 0) or (Index > FCount) then Error(PResStringRec(@SListIndexError), Index);
InsertItem(Index, S, AObject);
end;
procedure TTntStringList.InsertItem(Index: Integer; const S: WideString; AObject: TObject);
begin
Changing;
if FCount = FCapacity then Grow;
if Index < FCount then
System.Move(FList^[Index], FList^[Index + 1],
(FCount - Index) * SizeOf(TWideStringItem));
with FList^[Index] do
begin
Pointer(FString) := nil;
FObject := AObject;
FString := S;
end;
Inc(FCount);
Changed;
end;
procedure TTntStringList.Put(Index: Integer; const S: WideString);
begin
if Sorted then Error(PResStringRec(@SSortedListError), 0);
if (Index < 0) or (Index >= FCount) then Error(PResStringRec(@SListIndexError), Index);
Changing;
FList^[Index].FString := S;
Changed;
end;
procedure TTntStringList.PutObject(Index: Integer; AObject: TObject);
begin
if (Index < 0) or (Index >= FCount) then Error(PResStringRec(@SListIndexError), Index);
Changing;
FList^[Index].FObject := AObject;
Changed;
end;
procedure TTntStringList.QuickSort(L, R: Integer; SCompare: TWideStringListSortCompare);
var
I, J, P: Integer;
begin
repeat
I := L;
J := R;
P := (L + R) shr 1;
repeat
while SCompare(Self, I, P) < 0 do Inc(I);
while SCompare(Self, J, P) > 0 do Dec(J);
if I <= J then
begin
ExchangeItems(I, J);
if P = I then
P := J
else if P = J then
P := I;
Inc(I);
Dec(J);
end;
until I > J;
if L < J then QuickSort(L, J, SCompare);
L := I;
until I >= R;
end;
procedure TTntStringList.SetCapacity(NewCapacity: Integer);
begin
ReallocMem(FList, NewCapacity * SizeOf(TWideStringItem));
FCapacity := NewCapacity;
end;
procedure TTntStringList.SetSorted(Value: Boolean);
begin
if FSorted <> Value then
begin
if Value then Sort;
FSorted := Value;
end;
end;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -