stringl.inc 18 KB

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