stringl.inc 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044
  1. {
  2. $Id$
  3. This file is part of the Free Component Library (FCL)
  4. Copyright (c) 1999-2000 by the Free Pascal development team
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. {****************************************************************************}
  12. {* TStrings *}
  13. {****************************************************************************}
  14. // Function to quote text. Should move maybe to sysutils !!
  15. // Also, it is not clear at this point what exactly should be done.
  16. { //!! is used to mark unsupported things. }
  17. Function QuoteString (Const S : String; Quote : String) : String;
  18. Var
  19. I,J : Integer;
  20. begin
  21. J:=0;
  22. Result:=S;
  23. for i:=1to length(s) do
  24. begin
  25. inc(j);
  26. if S[i]=Quote then
  27. begin
  28. System.Insert(Quote,Result,J);
  29. inc(j);
  30. end;
  31. end;
  32. Result:=Quote+Result+Quote;
  33. end;
  34. function TStrings.GetCommaText: string;
  35. Var
  36. I : integer;
  37. p : pchar;
  38. begin
  39. result:='';
  40. For i:=0 to count-1 do
  41. begin
  42. p:=pchar(strings[i]);
  43. while not(p^ in [#0..' ','"',',']) do
  44. inc(p);
  45. if p^<>#0 then
  46. Result:=Result+QuoteString (Strings[I],'"')
  47. else
  48. result:=result+strings[i];
  49. if I<Count-1 then Result:=Result+',';
  50. end;
  51. If Length(Result)=0 then
  52. Result:='""';
  53. end;
  54. function TStrings.GetName(Index: Integer): string;
  55. Var L : longint;
  56. begin
  57. Result:=Strings[Index];
  58. L:=Pos('=',Result);
  59. If L<>0 then
  60. Result:=Copy(Result,1,L-1)
  61. else
  62. Result:='';
  63. end;
  64. Function TStrings.GetValue(const Name: string): string;
  65. Var L : longint;
  66. begin
  67. Result:='';
  68. L:=IndexOfName(Name);
  69. If L<>-1 then
  70. begin
  71. Result:=Strings[L];
  72. L:=Pos('=',Result);
  73. System.Delete (Result,1,L);
  74. end;
  75. end;
  76. procedure TStrings.ReadData(Reader: TReader);
  77. begin
  78. Reader.ReadListBegin;
  79. BeginUpdate;
  80. try
  81. Clear;
  82. while not Reader.EndOfList do
  83. Add(Reader.ReadString);
  84. finally
  85. EndUpdate;
  86. end;
  87. Reader.ReadListEnd;
  88. end;
  89. Function GetQuotedString (Var P : Pchar) : AnsiString;
  90. Var P1,L : Pchar;
  91. begin
  92. Result:='';
  93. P1:=P+1;
  94. While P1^<>#0 do
  95. begin
  96. If (P1^='"') then
  97. begin
  98. if (P1[1]<>'"') then
  99. break;
  100. inc(p1);
  101. end;
  102. inc(p1);
  103. end;
  104. // P1 points to last quote, or to #0;
  105. P:=P+1;
  106. If P1-P>0 then
  107. begin
  108. SetLength(Result,(P1-P));
  109. L:=Pointer(Result);
  110. Move (P^,L^,P1-P);
  111. P:=P1+1;
  112. end;
  113. end;
  114. Function GetNextQuotedChar (var P : PChar; Var S : String): Boolean;
  115. Var PS,L : PChar;
  116. begin
  117. Result:=False;
  118. S:='';
  119. While (p^<>#0) and (byte(p^)<=byte(' ')) do
  120. inc(p);
  121. If P^=#0 then exit;
  122. PS:=P;
  123. If P^='"' then
  124. begin
  125. S:=GetQuotedString(P);
  126. While (p^<>#0) and (byte(p^)<=byte(' ')) do
  127. inc(p);
  128. end
  129. else
  130. begin
  131. While (p^>' ') and (P^<>',') do
  132. inc(p);
  133. Setlength (S,P-PS);
  134. L:=Pointer(S);
  135. Move (PS^,L^,P-PS);
  136. end;
  137. if p^=',' then
  138. inc(p);
  139. Result:=True;
  140. end;
  141. Procedure TStrings.SetCommaText(const Value: string);
  142. Var
  143. P : PChar;
  144. S : String;
  145. begin
  146. BeginUpdate;
  147. try
  148. Clear;
  149. P:=PChar(Value);
  150. if assigned(p) then
  151. begin
  152. While GetNextQuotedChar (P,S) do
  153. Add (S);
  154. end;
  155. finally
  156. EndUpdate;
  157. end;
  158. end;
  159. Procedure TStrings.SetStringsAdapter(const Value: IStringsAdapter);
  160. begin
  161. end;
  162. Procedure TStrings.SetValue(const Name, Value: string);
  163. Var L : longint;
  164. begin
  165. L:=IndexOfName(Name);
  166. if L=-1 then
  167. Add (Name+'='+Value)
  168. else
  169. Strings[L]:=Name+'='+value;
  170. end;
  171. procedure TStrings.WriteData(Writer: TWriter);
  172. var
  173. i: Integer;
  174. begin
  175. Writer.WriteListBegin;
  176. for i := 0 to Count - 1 do
  177. Writer.WriteString(Strings[i]);
  178. Writer.WriteListEnd;
  179. end;
  180. procedure TStrings.DefineProperties(Filer: TFiler);
  181. var
  182. HasData: Boolean;
  183. begin
  184. if Assigned(Filer.Ancestor) then
  185. // Only serialize if string list is different from ancestor
  186. if Filer.Ancestor.InheritsFrom(TStrings) then
  187. HasData := not Equals(TStrings(Filer.Ancestor))
  188. else
  189. HasData := True
  190. else
  191. HasData := Count > 0;
  192. Filer.DefineProperty('Strings', @ReadData, @WriteData, HasData);
  193. end;
  194. Procedure TStrings.Error(const Msg: string; Data: Integer);
  195. begin
  196. {$ifdef VER1_0}
  197. Raise EStringListError.CreateFmt(Msg,[Data]) at get_caller_addr(get_frame);
  198. {$else VER1_0}
  199. Raise EStringListError.CreateFmt(Msg,[Data]) at pointer(get_caller_addr(get_frame));
  200. {$endif VER1_0}
  201. end;
  202. Function TStrings.GetCapacity: Integer;
  203. begin
  204. Result:=Count;
  205. end;
  206. Function TStrings.GetObject(Index: Integer): TObject;
  207. begin
  208. Result:=Nil;
  209. end;
  210. Function TStrings.GetTextStr: string;
  211. Const
  212. {$ifdef Unix}
  213. NewLineSize=1;
  214. {$else}
  215. NewLineSize=2;
  216. {$endif}
  217. Var P : Pchar;
  218. I,L : Longint;
  219. S : String;
  220. begin
  221. // Determine needed place
  222. L:=0;
  223. For I:=0 to count-1 do
  224. L:=L+Length(Strings[I])+NewLineSize;
  225. Setlength(Result,L);
  226. P:=Pointer(Result);
  227. For i:=0 To count-1 do
  228. begin
  229. S:=Strings[I];
  230. L:=Length(S);
  231. if L<>0 then
  232. System.Move(Pointer(S)^,P^,L);
  233. P:=P+L;
  234. {$ifndef Unix}
  235. p[0]:=#13;
  236. p[1]:=#10;
  237. {$else}
  238. p[0]:=#10;
  239. {$endif}
  240. P:=P+NewLineSize;
  241. end;
  242. end;
  243. Procedure TStrings.Put(Index: Integer; const S: string);
  244. Var Obj : TObject;
  245. begin
  246. Obj:=Objects[Index];
  247. Delete(Index);
  248. InsertObject(Index,S,Obj);
  249. end;
  250. Procedure TStrings.PutObject(Index: Integer; AObject: TObject);
  251. begin
  252. // Empty.
  253. end;
  254. Procedure TStrings.SetCapacity(NewCapacity: Integer);
  255. begin
  256. // Empty.
  257. end;
  258. Procedure TStrings.SetTextStr(const Value: string);
  259. begin
  260. SetText(PChar(Value));
  261. end;
  262. Procedure TStrings.SetUpdateState(Updating: Boolean);
  263. begin
  264. end;
  265. destructor TSTrings.Destroy;
  266. begin
  267. inherited destroy;
  268. end;
  269. Function TStrings.Add(const S: string): Integer;
  270. begin
  271. Result:=Count;
  272. Insert (Count,S);
  273. end;
  274. Function TStrings.AddObject(const S: string; AObject: TObject): Integer;
  275. begin
  276. Result:=Add(S);
  277. Objects[result]:=AObject;
  278. end;
  279. Procedure TStrings.Append(const S: string);
  280. begin
  281. Add (S);
  282. end;
  283. Procedure TStrings.AddStrings(TheStrings: TStrings);
  284. Var Runner : longint;
  285. begin
  286. try
  287. beginupdate;
  288. For Runner:=0 to TheStrings.Count-1 do
  289. self.AddObject (Thestrings[Runner],TheStrings.Objects[Runner]);
  290. finally
  291. EndUpdate;
  292. end;
  293. end;
  294. Procedure TStrings.Assign(Source: TPersistent);
  295. begin
  296. Try
  297. BeginUpdate;
  298. If Source is TStrings then
  299. begin
  300. clear;
  301. AddStrings(TStrings(Source));
  302. exit;
  303. end;
  304. Inherited Assign(Source);
  305. finally
  306. EndUpdate;
  307. end;
  308. end;
  309. Procedure TStrings.BeginUpdate;
  310. begin
  311. inc(FUpdateCount);
  312. if FUpdateCount = 1 then SetUpdateState(true);
  313. end;
  314. Procedure TStrings.EndUpdate;
  315. begin
  316. If FUpdateCount>0 then
  317. Dec(FUpdateCount);
  318. if FUpdateCount=0 then
  319. SetUpdateState(False);
  320. end;
  321. Function TStrings.Equals(TheStrings: TStrings): Boolean;
  322. Var Runner,Nr : Longint;
  323. begin
  324. Result:=False;
  325. Nr:=Self.Count;
  326. if Nr<>TheStrings.Count then exit;
  327. For Runner:=0 to Nr-1 do
  328. If Strings[Runner]<>TheStrings[Runner] then exit;
  329. Result:=True;
  330. end;
  331. Procedure TStrings.Exchange(Index1, Index2: Integer);
  332. Var
  333. Obj : TObject;
  334. Str : String;
  335. begin
  336. Try
  337. beginUpdate;
  338. Obj:=Objects[Index1];
  339. Str:=Strings[Index1];
  340. Objects[Index1]:=Objects[Index2];
  341. Strings[Index1]:=Strings[Index2];
  342. Objects[Index2]:=Obj;
  343. Strings[Index2]:=Str;
  344. finally
  345. EndUpdate;
  346. end;
  347. end;
  348. Function TStrings.GetText: PChar;
  349. begin
  350. Result:=StrNew(Pchar(Self.Text));
  351. end;
  352. Function TStrings.IndexOf(const S: string): Integer;
  353. begin
  354. Result:=0;
  355. While (Result<Count) and (Strings[Result]<>S) do Result:=Result+1;
  356. if Result=Count then Result:=-1;
  357. end;
  358. Function TStrings.IndexOfName(const Name: string): Integer;
  359. Var len : longint;
  360. begin
  361. Result:=0;
  362. while (Result<Count) do
  363. begin
  364. len:=pos('=',Strings[Result])-1;
  365. if (len>0) and (Name=Copy(Strings[Result],1,Len)) then exit;
  366. inc(result);
  367. end;
  368. result:=-1;
  369. end;
  370. Function TStrings.IndexOfObject(AObject: TObject): Integer;
  371. begin
  372. Result:=0;
  373. While (Result<count) and (Objects[Result]<>AObject) do Result:=Result+1;
  374. If Result=Count then Result:=-1;
  375. end;
  376. Procedure TStrings.InsertObject(Index: Integer; const S: string;
  377. AObject: TObject);
  378. begin
  379. Insert (Index,S);
  380. Objects[Index]:=AObject;
  381. end;
  382. Procedure TStrings.LoadFromFile(const FileName: string);
  383. Var TheStream : TFileStream;
  384. begin
  385. TheStream:=TFileStream.Create(FileName,fmOpenRead);
  386. LoadFromStream(TheStream);
  387. TheStream.Free;
  388. end;
  389. Procedure TStrings.LoadFromStream(Stream: TStream);
  390. {
  391. Borlands method is no goed, since a pipe for
  392. Instance doesn't have a size.
  393. So we must do it the hard way.
  394. }
  395. Const
  396. BufSize = 1024;
  397. Var
  398. Buffer : Pointer;
  399. BytesRead,
  400. BufLen : Longint;
  401. begin
  402. // reread into a buffer
  403. try
  404. beginupdate;
  405. Buffer:=Nil;
  406. BufLen:=0;
  407. Repeat
  408. ReAllocMem(Buffer,BufLen+BufSize);
  409. BytesRead:=Stream.Read((Buffer+BufLen)^,BufSize);
  410. inc(BufLen,BufSize);
  411. Until BytesRead<>BufSize;
  412. // Null-terminate !!
  413. Pchar(Buffer)[BufLen-BufSize+BytesRead]:=#0;
  414. Text:=PChar(Buffer);
  415. FreeMem(Buffer);
  416. finally
  417. EndUpdate;
  418. end;
  419. end;
  420. Procedure TStrings.Move(CurIndex, NewIndex: Integer);
  421. Var
  422. Obj : TObject;
  423. Str : String;
  424. begin
  425. Obj:=Objects[CurIndex];
  426. Str:=Strings[CurIndex];
  427. Delete(Curindex);
  428. InsertObject(NewIndex,Str,Obj);
  429. end;
  430. Procedure TStrings.SaveToFile(const FileName: string);
  431. Var TheStream : TFileStream;
  432. begin
  433. TheStream:=TFileStream.Create(FileName,fmCreate);
  434. SaveToStream(TheStream);
  435. TheStream.Free;
  436. end;
  437. Procedure TStrings.SaveToStream(Stream: TStream);
  438. Var
  439. S : String;
  440. begin
  441. S:=Text;
  442. Stream.Write(Pointer(S)^,Length(S));
  443. end;
  444. Function GetNextLine (Var P : Pchar; Var S : String) : Boolean;
  445. Var PS : PChar;
  446. begin
  447. S:='';
  448. Result:=False;
  449. If P^=#0 then exit;
  450. PS:=P;
  451. While not (P^ in [#0,#10,#13]) do P:=P+1;
  452. SetLength (S,P-PS);
  453. System.Move (PS^,Pointer(S)^,P-PS);
  454. If P^=#13 then P:=P+1;
  455. If P^=#10 then
  456. P:=P+1; // Point to character after #10(#13)
  457. Result:=True;
  458. end;
  459. Procedure TStrings.SetText(TheText: PChar);
  460. Var S : String;
  461. begin
  462. Try
  463. beginUpdate;
  464. Clear;
  465. While GetNextLine (TheText,S) do
  466. Add(S);
  467. finally
  468. EndUpdate;
  469. end;
  470. end;
  471. {****************************************************************************}
  472. {* TStringList *}
  473. {****************************************************************************}
  474. Procedure TStringList.ExchangeItems(Index1, Index2: Integer);
  475. Var P1,P2 : Pointer;
  476. begin
  477. P1:=Pointer(Flist^[Index1].FString);
  478. P2:=Pointer(Flist^[Index1].FObject);
  479. Pointer(Flist^[Index1].Fstring):=Pointer(Flist^[Index2].Fstring);
  480. Pointer(Flist^[Index1].FObject):=Pointer(Flist^[Index2].FObject);
  481. Pointer(Flist^[Index2].Fstring):=P1;
  482. Pointer(Flist^[Index2].FObject):=P2;
  483. end;
  484. Procedure TStringList.Grow;
  485. Var Extra : Longint;
  486. begin
  487. If FCapacity>64 then
  488. Extra:=FCapacity Div 4
  489. Else If FCapacity>8 Then
  490. Extra:=16
  491. Else
  492. Extra:=4;
  493. SetCapacity(FCapacity+Extra);
  494. end;
  495. Procedure TStringList.QuickSort(L, R: Integer; CompareFn: TStringListSortCompare);
  496. Var I,J, Pivot : Longint;
  497. begin
  498. Repeat
  499. I:=L;
  500. J:=R;
  501. Pivot:=(L+R) div 2;
  502. Repeat
  503. While CompareFn(Self, I, Pivot)<0 do Inc(I);
  504. While CompareFn(Self, J, Pivot)>0 do Dec(J);
  505. If I<=J then
  506. begin
  507. ExchangeItems(I,J); // No check, indices are correct.
  508. if Pivot=I then
  509. Pivot:=J
  510. else if Pivot=J then
  511. Pivot := I;
  512. Inc(I);
  513. Dec(j);
  514. end;
  515. until I>J;
  516. If L<J then QuickSort(L,J, CompareFn);
  517. L:=I;
  518. Until I>=R;
  519. end;
  520. Procedure TStringList.InsertItem(Index: Integer; const S: string);
  521. begin
  522. Changing;
  523. If FCount=Fcapacity then Grow;
  524. If Index<FCount then
  525. System.Move (FList^[Index],FList^[Index+1],
  526. (FCount-Index)*SizeOf(TStringItem));
  527. Pointer(Flist^[Index].Fstring):=Nil; // Needed to initialize...
  528. Flist^[Index].FString:=S;
  529. Flist^[Index].Fobject:=Nil;
  530. Inc(FCount);
  531. Changed;
  532. end;
  533. Procedure TStringList.SetSorted(Value: Boolean);
  534. begin
  535. If FSorted<>Value then
  536. begin
  537. If Value then sort;
  538. FSorted:=VAlue
  539. end;
  540. end;
  541. Procedure TStringList.Changed;
  542. begin
  543. If (FUpdateCount=0) Then
  544. If Assigned(FOnChange) then
  545. FOnchange(Self);
  546. end;
  547. Procedure TStringList.Changing;
  548. begin
  549. If FUpdateCount=0 then
  550. if Assigned(FOnChanging) then
  551. FOnchanging(Self);
  552. end;
  553. Function TStringList.Get(Index: Integer): string;
  554. begin
  555. If (Index<0) or (INdex>=Fcount) then
  556. Error (SListIndexError,Index);
  557. Result:=Flist^[Index].FString;
  558. end;
  559. Function TStringList.GetCapacity: Integer;
  560. begin
  561. Result:=FCapacity;
  562. end;
  563. Function TStringList.GetCount: Integer;
  564. begin
  565. Result:=FCount;
  566. end;
  567. Function TStringList.GetObject(Index: Integer): TObject;
  568. begin
  569. If (Index<0) or (INdex>=Fcount) then
  570. Error (SListIndexError,Index);
  571. Result:=Flist^[Index].FObject;
  572. end;
  573. Procedure TStringList.Put(Index: Integer; const S: string);
  574. begin
  575. If Sorted then
  576. Error(SSortedListError,0);
  577. If (Index<0) or (INdex>=Fcount) then
  578. Error (SListIndexError,Index);
  579. Changing;
  580. Flist^[Index].FString:=S;
  581. Changed;
  582. end;
  583. Procedure TStringList.PutObject(Index: Integer; AObject: TObject);
  584. begin
  585. If (Index<0) or (INdex>=Fcount) then
  586. Error (SListIndexError,Index);
  587. Changing;
  588. Flist^[Index].FObject:=AObject;
  589. Changed;
  590. end;
  591. Procedure TStringList.SetCapacity(NewCapacity: Integer);
  592. Var NewList : Pointer;
  593. MSize : Longint;
  594. begin
  595. If (NewCapacity<0) then
  596. Error (SListCapacityError,NewCapacity);
  597. If NewCapacity>FCapacity then
  598. begin
  599. GetMem (NewList,NewCapacity*SizeOf(TStringItem));
  600. If NewList=Nil then
  601. Error (SListCapacityError,NewCapacity);
  602. If Assigned(FList) then
  603. begin
  604. MSize:=FCapacity*Sizeof(TStringItem);
  605. System.Move (FList^,NewList^,MSize);
  606. FillWord (Pchar(NewList)[MSize],(NewCapacity-FCapacity)*WordRatio, 0);
  607. FreeMem (Flist,MSize);
  608. end;
  609. Flist:=NewList;
  610. FCapacity:=NewCapacity;
  611. end
  612. else if NewCapacity<FCapacity then
  613. begin
  614. if NewCapacity = 0 then
  615. begin
  616. FreeMem(FList);
  617. FList := nil;
  618. end else
  619. begin
  620. GetMem(NewList, NewCapacity * SizeOf(TStringItem));
  621. System.Move(FList^, NewList^, NewCapacity * SizeOf(TStringItem));
  622. FreeMem(FList);
  623. FList := NewList;
  624. end;
  625. FCapacity:=NewCapacity;
  626. end;
  627. end;
  628. Procedure TStringList.SetUpdateState(Updating: Boolean);
  629. begin
  630. If Updating then
  631. Changing
  632. else
  633. Changed
  634. end;
  635. destructor TStringList.Destroy;
  636. Var I : Longint;
  637. begin
  638. FOnChange:=Nil;
  639. FOnChanging:=Nil;
  640. // This will force a dereference. Can be done better...
  641. For I:=0 to FCount-1 do
  642. FList^[I].FString:='';
  643. FCount:=0;
  644. SetCapacity(0);
  645. Inherited destroy;
  646. end;
  647. Function TStringList.Add(const S: string): Integer;
  648. begin
  649. If Not Sorted then
  650. Result:=FCount
  651. else
  652. If Find (S,Result) then
  653. Case DUplicates of
  654. DupIgnore : Exit;
  655. DupError : Error(SDuplicateString,0)
  656. end;
  657. InsertItem (Result,S);
  658. end;
  659. Procedure TStringList.Clear;
  660. Var I : longint;
  661. begin
  662. For I:=0 to FCount-1 do
  663. Flist^[I].FString:='';
  664. FCount:=0;
  665. SetCapacity(0);
  666. end;
  667. Procedure TStringList.Delete(Index: Integer);
  668. begin
  669. If (Index<0) or (Index>=FCount) then
  670. Error(SlistINdexError,Index);
  671. Flist^[Index].FString:='';
  672. Dec(FCount);
  673. If Index<FCount then
  674. System.Move(Flist^[Index+1],
  675. Flist^[Index],
  676. (Fcount-Index)*SizeOf(TStringItem));
  677. end;
  678. Procedure TStringList.Exchange(Index1, Index2: Integer);
  679. begin
  680. If (Index1<0) or (Index1>=FCount) then
  681. Error(SListIndexError,Index1);
  682. If (Index2<0) or (Index2>=FCount) then
  683. Error(SListIndexError,Index2);
  684. Changing;
  685. ExchangeItems(Index1,Index2);
  686. changed;
  687. end;
  688. Function TStringList.Find(const S: string; var Index: Integer): Boolean;
  689. { Searches for the first string <= S, returns True if exact match,
  690. sets index to the index f the found string. }
  691. Var I,L,R,Temp : Longint;
  692. begin
  693. Result:=False;
  694. // Use binary search.
  695. L:=0;
  696. R:=FCount-1;
  697. While L<=R do
  698. begin
  699. I:=(L+R) div 2;
  700. Temp:=AnsiCompareText(FList^ [I].FString,S);
  701. If Temp<0 then
  702. L:=I+1
  703. else
  704. begin
  705. R:=I-1;
  706. If Temp=0 then
  707. begin
  708. Result:=True;
  709. If Duplicates<>DupAccept then L:=I;
  710. end;
  711. end;
  712. end;
  713. Index:=L;
  714. end;
  715. Function TStringList.IndexOf(const S: string): Integer;
  716. begin
  717. If Not Sorted then
  718. Result:=Inherited indexOf(S)
  719. else
  720. // faster using binary search...
  721. If Not Find (S,Result) then
  722. Result:=-1;
  723. end;
  724. Procedure TStringList.Insert(Index: Integer; const S: string);
  725. begin
  726. If Sorted then
  727. Error (SSortedListError,0)
  728. else
  729. If (Index<0) or (Index>FCount) then
  730. Error (SListIndexError,Index)
  731. else
  732. InsertItem (Index,S);
  733. end;
  734. Procedure TStringList.CustomSort(CompareFn: TStringListSortCompare);
  735. begin
  736. If Not Sorted and (FCount>1) then
  737. begin
  738. Changing;
  739. QuickSort(0,FCount-1, CompareFn);
  740. Changed;
  741. end;
  742. end;
  743. function StringListAnsiCompare(List: TStringList; Index1, Index: Integer): Integer;
  744. begin
  745. Result := AnsiCompareText(List.FList^[Index1].FString,
  746. List.FList^[Index].FString);
  747. end;
  748. Procedure TStringList.Sort;
  749. begin
  750. CustomSort(@StringListAnsiCompare);
  751. end;
  752. {
  753. $Log$
  754. Revision 1.12 2002-09-07 15:15:25 peter
  755. * old logs removed and tabs fixed
  756. Revision 1.11 2002/07/17 11:52:01 florian
  757. * at and frame addresses in raise statements changed to pointer; fixed
  758. }