1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000 |
- {
- $Id$
- This file is part of the Free Component Library (FCL)
- Copyright (c) 1999-2000 by 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.
- **********************************************************************}
- {****************************************************************************}
- {* TStrings *}
- {****************************************************************************}
- // Function to quote text. Should move maybe to sysutils !!
- // Also, it is not clear at this point what exactly should be done.
- { //!! is used to mark unsupported things. }
- Function QuoteString (Const S : String; Quote : String) : String;
- Var I,J : Longint;
- begin
- I:=0;
- J:=0;
- Result:=S;
- While I<Length(S) do
- begin
- I:=I+1;
- J:=J+1;
- if S[i]=Quote then
- begin
- System.Insert(Result,Quote,J);
- J:=J+1;
- end;
- end;
- Result:=Quote+Result+Quote;
- end;
- function TStrings.GetCommaText: string;
- Var I : Longint;
- begin
- result:='';
- For i:=0 to count-1 do
- begin
- Result:=Result+QuoteString (Strings[I],'"');
- if I<Count-1 then Result:=Result+',';
- end;
- If Length(Result)=0 then Result:='""';
- end;
- function TStrings.GetName(Index: Integer): string;
- Var L : longint;
- begin
- Result:=Strings[Index];
- L:=Pos('=',Result);
- If L<>0 then
- Result:=Copy(Result,1,L-1)
- else
- Result:='';
- end;
- Function TStrings.GetValue(const Name: string): string;
- Var L : longint;
- begin
- Result:='';
- L:=IndexOfName(Name);
- If L<>-1 then
- begin
- Result:=Strings[L];
- L:=Pos('=',Result);
- System.Delete (Result,1,L);
- end;
- end;
- Procedure TStrings.ReadData(Reader: TReader);
- begin
- end;
- Function GetQuotedString (Var P : Pchar) : AnsiString;
- Var P1,L : Pchar;
- begin
- Result:='';
- P1:=P+1;
- While P1^<>#0 do
- begin
- If (P1^='"') then
- begin
- if (P1[1]<>'"') then
- break;
- inc(p1);
- end;
- inc(p1);
- end;
- // P1 points to last quote, or to #0;
- P:=P+1;
- If P1-P>0 then
- begin
- SetLength(Result,(P1-P));
- L:=Pointer(Result);
- Move (P^,L^,P1-P);
- P:=P1+1;
- end;
- end;
- Function GetNextQuotedChar (var P : PChar; Var S : String): Boolean;
- Var PS,L : PChar;
- begin
- Result:=False;
- S:='';
- While (p^<>#0) and (byte(p^)<=byte(' ')) do
- inc(p);
- If P^=#0 then exit;
- PS:=P;
- If P^='"' then
- begin
- S:=GetQuotedString(P);
- While (p^<>#0) and (byte(p^)<=byte(' ')) do
- inc(p);
- end
- else
- begin
- While (p^>' ') and (P^<>',') do
- inc(p);
- Setlength (S,P-PS);
- L:=Pointer(S);
- Move (PS^,L,P-PS);
- end;
- if p^=',' then
- inc(p);
- Result:=True;
- end;
- Procedure TStrings.SetCommaText(const Value: string);
- Var P : Pointer;
- S : String;
- begin
- Self.Clear;
- P:=Pointer(Value);
- While GetNextQuotedChar (P,S) do
- Add (S);
- end;
- Procedure TStrings.SetStringsAdapter(const Value: IStringsAdapter);
- begin
- end;
- Procedure TStrings.SetValue(const Name, Value: string);
- Var L : longint;
- begin
- L:=IndexOfName(Name);
- if L=-1 then
- Add (Name+'='+Value)
- else
- Strings[L]:=Name+'='+value;
- end;
- Procedure TStrings.WriteData(Writer: TWriter);
- begin
- end;
- Procedure TStrings.DefineProperties(Filer: TFiler);
- begin
- end;
- Procedure TStrings.Error(const Msg: string; Data: Integer);
- begin
- Raise EStringListError.CreateFmt(Msg,[Data]) at get_caller_addr(get_frame);
- end;
- Function TStrings.GetCapacity: Integer;
- begin
- Result:=Count;
- end;
- Function TStrings.GetObject(Index: Integer): TObject;
- begin
- Result:=Nil;
- end;
- Function TStrings.GetTextStr: string;
- Const
- {$ifdef Unix}
- NewLineSize=1;
- {$else}
- NewLineSize=2;
- {$endif}
- Var P : Pchar;
- I,L : Longint;
- S : String;
- begin
- // Determine needed place
- L:=0;
- For I:=0 to count-1 do
- L:=L+Length(Strings[I])+NewLineSize;
- Setlength(Result,L);
- P:=Pointer(Result);
- For i:=0 To count-1 do
- begin
- S:=Strings[I];
- L:=Length(S);
- if L<>0 then
- System.Move(Pointer(S)^,P^,L);
- P:=P+L;
- {$ifndef Unix}
- p[0]:=#13;
- p[1]:=#10;
- {$else}
- p[0]:=#10;
- {$endif}
- P:=P+NewLineSize;
- end;
- end;
- Procedure TStrings.Put(Index: Integer; const S: string);
- Var Obj : TObject;
- begin
- Obj:=Objects[Index];
- Delete(Index);
- InsertObject(Index,S,Obj);
- end;
- Procedure TStrings.PutObject(Index: Integer; AObject: TObject);
- begin
- // Empty.
- end;
- Procedure TStrings.SetCapacity(NewCapacity: Integer);
- begin
- // Empty.
- end;
- Procedure TStrings.SetTextStr(const Value: string);
- begin
- SetText(PChar(Value));
- end;
- Procedure TStrings.SetUpdateState(Updating: Boolean);
- begin
- end;
- destructor TSTrings.Destroy;
- begin
- inherited destroy;
- end;
- Function TStrings.Add(const S: string): Integer;
- begin
- Result:=Count;
- Insert (Count,S);
- end;
- Function TStrings.AddObject(const S: string; AObject: TObject): Integer;
- begin
- Result:=Add(S);
- Objects[result]:=AObject;
- end;
- Procedure TStrings.Append(const S: string);
- begin
- Add (S);
- end;
- Procedure TStrings.AddStrings(TheStrings: TStrings);
- Var Runner : longint;
- begin
- try
- beginupdate;
- For Runner:=0 to TheStrings.Count-1 do
- self.AddObject (Thestrings[Runner],TheStrings.Objects[Runner]);
- finally
- EndUpdate;
- end;
- end;
- Procedure TStrings.Assign(Source: TPersistent);
- begin
- Try
- BeginUpdate;
- If Source is TStrings then
- begin
- clear;
- AddStrings(TStrings(Source));
- exit;
- end;
- Inherited Assign(Source);
- finally
- EndUpdate;
- end;
- end;
- Procedure TStrings.BeginUpdate;
- begin
- inc(FUpdateCount);
- if FUpdateCount = 1 then SetUpdateState(true);
- end;
- Procedure TStrings.EndUpdate;
- begin
- If FUpdateCount>0 then
- Dec(FUpdateCount);
- if FUpdateCount=0 then
- SetUpdateState(False);
- end;
- Function TStrings.Equals(TheStrings: TStrings): Boolean;
- Var Runner,Nr : Longint;
- begin
- Result:=False;
- Nr:=Self.Count;
- if Nr<>TheStrings.Count then exit;
- For Runner:=0 to Nr-1 do
- If Strings[Runner]<>TheStrings[Runner] then exit;
- Result:=True;
- end;
- Procedure TStrings.Exchange(Index1, Index2: Integer);
- Var
- Obj : TObject;
- Str : String;
- begin
- Try
- beginUpdate;
- Obj:=Objects[Index1];
- Str:=Strings[Index1];
- Objects[Index1]:=Objects[Index2];
- Strings[Index1]:=Strings[Index2];
- Objects[Index2]:=Obj;
- Strings[Index2]:=Str;
- finally
- EndUpdate;
- end;
- end;
- Function TStrings.GetText: PChar;
- begin
- Result:=StrNew(Pchar(Self.Text));
- end;
- Function TStrings.IndexOf(const S: string): Integer;
- begin
- Result:=0;
- While (Result<Count) and (Strings[Result]<>S) do Result:=Result+1;
- if Result=Count then Result:=-1;
- end;
- Function TStrings.IndexOfName(const Name: string): Integer;
- Var len : longint;
- begin
- Result:=0;
- while (Result<Count) do
- begin
- len:=pos('=',Strings[Result])-1;
- if (len>0) and (Name=Copy(Strings[Result],1,Len)) then exit;
- inc(result);
- end;
- result:=-1;
- end;
- Function TStrings.IndexOfObject(AObject: TObject): Integer;
- begin
- Result:=0;
- While (Result<count) and (Objects[Result]<>AObject) do Result:=Result+1;
- If Result=Count then Result:=-1;
- end;
- Procedure TStrings.InsertObject(Index: Integer; const S: string;
- AObject: TObject);
- begin
- Insert (Index,S);
- Objects[Index]:=AObject;
- end;
- Procedure TStrings.LoadFromFile(const FileName: string);
- Var TheStream : TFileStream;
- begin
- TheStream:=TFileStream.Create(FileName,fmOpenRead);
- LoadFromStream(TheStream);
- TheStream.Free;
- end;
- Procedure TStrings.LoadFromStream(Stream: TStream);
- {
- Borlands method is no goed, since a pipe for
- Instance doesn't have a size.
- So we must do it the hard way.
- }
- Const
- BufSize = 1024;
- Var
- Buffer : Pointer;
- BytesRead,
- BufLen : Longint;
- begin
- // reread into a buffer
- try
- beginupdate;
- Buffer:=Nil;
- BufLen:=0;
- Repeat
- ReAllocMem(Buffer,BufLen+BufSize);
- BytesRead:=Stream.Read((Buffer+BufLen)^,BufSize);
- inc(BufLen,BufSize);
- Until BytesRead<>BufSize;
- // Null-terminate !!
- Pchar(Buffer)[BufLen-BufSize+BytesRead]:=#0;
- Text:=PChar(Buffer);
- FreeMem(Buffer);
- finally
- EndUpdate;
- end;
- end;
- Procedure TStrings.Move(CurIndex, NewIndex: Integer);
- Var
- Obj : TObject;
- Str : String;
- begin
- Obj:=Objects[CurIndex];
- Str:=Strings[CurIndex];
- Delete(Curindex);
- InsertObject(NewIndex,Str,Obj);
- end;
- Procedure TStrings.SaveToFile(const FileName: string);
- Var TheStream : TFileStream;
- begin
- TheStream:=TFileStream.Create(FileName,fmCreate);
- SaveToStream(TheStream);
- TheStream.Free;
- end;
- Procedure TStrings.SaveToStream(Stream: TStream);
- Var
- S : String;
- begin
- S:=Text;
- Stream.Write(Pointer(S)^,Length(S));
- end;
- Function GetNextLine (Var P : Pchar; Var S : String) : Boolean;
- Var PS : PChar;
- begin
- S:='';
- Result:=False;
- If P^=#0 then exit;
- PS:=P;
- While not (P^ in [#0,#10,#13]) do P:=P+1;
- SetLength (S,P-PS);
- System.Move (PS^,Pointer(S)^,P-PS);
- If P^=#13 then P:=P+1;
- If P^=#10 then
- P:=P+1; // Point to character after #10(#13)
- Result:=True;
- end;
- Procedure TStrings.SetText(TheText: PChar);
- Var S : String;
- begin
- Try
- beginUpdate;
- Clear;
- While GetNextLine (TheText,S) do
- Add(S);
- finally
- EndUpdate;
- end;
- end;
- {****************************************************************************}
- {* TStringList *}
- {****************************************************************************}
- Procedure TStringList.ExchangeItems(Index1, Index2: Integer);
- Var P1,P2 : Pointer;
- begin
- P1:=Pointer(Flist^[Index1].FString);
- P2:=Pointer(Flist^[Index1].FObject);
- Pointer(Flist^[Index1].Fstring):=Pointer(Flist^[Index2].Fstring);
- Pointer(Flist^[Index1].FObject):=Pointer(Flist^[Index2].FObject);
- Pointer(Flist^[Index2].Fstring):=P1;
- Pointer(Flist^[Index2].FObject):=P2;
- end;
- Procedure TStringList.Grow;
- Var Extra : Longint;
- begin
- If FCapacity>64 then
- Extra:=FCapacity Div 4
- Else If FCapacity>8 Then
- Extra:=16
- Else
- Extra:=4;
- SetCapacity(FCapacity+Extra);
- end;
- Procedure TStringList.QuickSort(L, R: Integer; CompareFn: TStringListSortCompare);
- Var I,J, Pivot : Longint;
- begin
- Repeat;
- I:=L;
- J:=R;
- Pivot:=(L+R) div 2;
- Repeat
- While CompareFn(Self, I, Pivot)<0 do Inc(I);
- While CompareFn(Self, J, Pivot)>0 do Dec(J);
- If I<=J then
- begin
- ExchangeItems(I,J); // No check, indices are correct.
- Inc(I);
- Dec(j);
- end;
- until I>J;
- If L<J then QuickSort(L,J, CompareFn);
- L:=I;
- Until I>=R;
- end;
- Procedure TStringList.InsertItem(Index: Integer; const S: string);
- begin
- Changing;
- If FCount=Fcapacity then Grow;
- If Index<FCount then
- System.Move (FList^[Index],FList^[Index+1],
- (FCount-Index)*SizeOf(TStringItem));
- Pointer(Flist^[Index].Fstring):=Nil; // Needed to initialize...
- Flist^[Index].FString:=S;
- Flist^[Index].Fobject:=Nil;
- Inc(FCount);
- Changed;
- end;
- Procedure TStringList.SetSorted(Value: Boolean);
- begin
- If FSorted<>Value then
- begin
- If Value then sort;
- FSorted:=VAlue
- end;
- end;
- Procedure TStringList.Changed;
- begin
- If (FUpdateCount=0) Then
- If Assigned(FOnChange) then
- FOnchange(Self);
- end;
- Procedure TStringList.Changing;
- begin
- If FUpdateCount=0 then
- if Assigned(FOnChanging) then
- FOnchanging(Self);
- end;
- Function TStringList.Get(Index: Integer): string;
- begin
- If (Index<0) or (INdex>=Fcount) then
- Error (SListIndexError,Index);
- Result:=Flist^[Index].FString;
- end;
- Function TStringList.GetCapacity: Integer;
- begin
- Result:=FCapacity;
- end;
- Function TStringList.GetCount: Integer;
- begin
- Result:=FCount;
- end;
- Function TStringList.GetObject(Index: Integer): TObject;
- begin
- If (Index<0) or (INdex>=Fcount) then
- Error (SListIndexError,Index);
- Result:=Flist^[Index].FObject;
- end;
- Procedure TStringList.Put(Index: Integer; const S: string);
- begin
- If Sorted then
- Error(SSortedListError,0);
- If (Index<0) or (INdex>=Fcount) then
- Error (SListIndexError,Index);
- Changing;
- Flist^[Index].FString:=S;
- Changed;
- end;
- Procedure TStringList.PutObject(Index: Integer; AObject: TObject);
- begin
- If (Index<0) or (INdex>=Fcount) then
- Error (SListIndexError,Index);
- Changing;
- Flist^[Index].FObject:=AObject;
- Changed;
- end;
- Procedure TStringList.SetCapacity(NewCapacity: Integer);
- Var NewList : Pointer;
- MSize : Longint;
- begin
- If (NewCapacity<0) then
- Error (SListCapacityError,NewCapacity);
- If NewCapacity>FCapacity then
- begin
- GetMem (NewList,NewCapacity*SizeOf(TStringItem));
- If NewList=Nil then
- Error (SListCapacityError,NewCapacity);
- If Assigned(FList) then
- begin
- MSize:=FCapacity*Sizeof(TStringItem);
- System.Move (FList^,NewList^,MSize);
- FillWord (Pchar(NewList)[MSize],(NewCapacity-FCapacity)*WordRatio, 0);
- FreeMem (Flist,MSize);
- end;
- Flist:=NewList;
- FCapacity:=NewCapacity;
- end
- else if NewCapacity<FCapacity then
- begin
- NewList:=Flist+NewCapacity*SizeOf(TStringItem);
- FreeMem (NewList, (FCapacity-NewCapacity)*SizeOf(TStringItem));
- FCapacity:=NewCapacity;
- end;
- end;
- Procedure TStringList.SetUpdateState(Updating: Boolean);
- begin
- If Updating then
- Changing
- else
- Changed
- end;
- destructor TStringList.Destroy;
- Var I : Longint;
- begin
- FOnChange:=Nil;
- FOnChanging:=Nil;
- // This will force a dereference. Can be done better...
- For I:=0 to FCount-1 do
- FList^[I].FString:='';
- FCount:=0;
- SetCapacity(0);
- Inherited destroy;
- end;
- Function TStringList.Add(const S: string): Integer;
- begin
- If Not Sorted then
- Result:=FCount
- else
- If Find (S,Result) then
- Case DUplicates of
- DupIgnore : Exit;
- DupError : Error(SDuplicateString,0)
- end;
- InsertItem (Result,S);
- end;
- Procedure TStringList.Clear;
- Var I : longint;
- begin
- For I:=0 to FCount-1 do
- Flist^[I].FString:='';
- FCount:=0;
- SetCapacity(0);
- end;
- Procedure TStringList.Delete(Index: Integer);
- begin
- If (Index<0) or (Index>=FCount) then
- Error(SlistINdexError,Index);
- Flist^[Index].FString:='';
- Dec(FCount);
- If Index<FCount then
- System.Move(Flist^[Index+1],
- Flist^[Index],
- (Fcount-Index)*SizeOf(TStringItem));
- end;
- Procedure TStringList.Exchange(Index1, Index2: Integer);
- begin
- If (Index1<0) or (Index1>=FCount) then
- Error(SListIndexError,Index1);
- If (Index2<0) or (Index2>=FCount) then
- Error(SListIndexError,Index1);
- Changing;
- ExchangeItems(Index1,Index2);
- changed;
- end;
- Function TStringList.Find(const S: string; var Index: Integer): Boolean;
- { Searches for the first string <= S, returns True if exact match,
- sets index to the index f the found string. }
- Var I,L,R,Temp : Longint;
- begin
- Result:=False;
- // Use binary search.
- L:=0;
- R:=FCount-1;
- While L<=R do
- begin
- I:=(L+R) div 2;
- Temp:=AnsiCompareText(FList^ [I].FString,S);
- If Temp<0 then
- L:=I+1
- else
- begin
- R:=I-1;
- If Temp=0 then
- begin
- Result:=True;
- If Duplicates<>DupAccept then L:=I;
- end;
- end;
- end;
- Index:=L;
- end;
- Function TStringList.IndexOf(const S: string): Integer;
- begin
- If Not Sorted then
- Result:=Inherited indexOf(S)
- else
- // faster using binary search...
- If Not Find (S,Result) then
- Result:=-1;
- end;
- Procedure TStringList.Insert(Index: Integer; const S: string);
- begin
- If Sorted then
- Error (SSortedListError,0)
- else
- If (Index<0) or (Index>FCount) then
- Error (SListIndexError,Index)
- else
- InsertItem (Index,S);
- end;
- Procedure TStringList.CustomSort(CompareFn: TStringListSortCompare);
- begin
- If Not Sorted and (FCount>1) then
- begin
- Changing;
- QuickSort(0,FCount-1, CompareFn);
- Changed;
- end;
- end;
- function StringListAnsiCompare(List: TStringList; Index1, Index: Integer): Integer;
- begin
- Result := AnsiCompareText(List.FList^[Index1].FString,
- List.FList^[Index1].FString);
- end;
- Procedure TStringList.Sort;
- begin
- CustomSort(@StringListAnsiCompare);
- end;
- {
- $Log$
- Revision 1.6 2000-12-03 22:35:09 sg
- * Applied patch by Markus Kaemmerer (merged):
- - Added support for TStringList.CustomSort
- Revision 1.5 2000/11/22 22:44:39 peter
- * fixed commatext (merged)
- Revision 1.4 2000/11/17 13:39:49 sg
- * Extended Error methods so that exceptions are raised from the caller's
- address instead of the Error method
- Revision 1.3 2000/11/13 15:46:55 marco
- * Unix renamefest for defines.
- Revision 1.2 2000/07/13 11:33:01 michael
- + removed logs
- }
|