stringl.inc 18 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067
  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 longint(get_caller_addr(get_frame));
  203. {$else VER1_0}
  204. Raise EStringListError.CreateFmt(Msg,[Data]) at 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 (CompareText(Strings[Result],S)<>0) do Result:=Result+1;
  361. if Result=Count then Result:=-1;
  362. end;
  363. Function TStrings.IndexOfName(const Name: string): Integer;
  364. Var
  365. len : longint;
  366. S : String;
  367. begin
  368. Result:=0;
  369. while (Result<Count) do
  370. begin
  371. S:=Strings[Result];
  372. len:=pos('=',S)-1;
  373. if (len>0) and (CompareText(Name,Copy(S,1,Len))=0) then
  374. exit;
  375. inc(result);
  376. end;
  377. result:=-1;
  378. end;
  379. Function TStrings.IndexOfObject(AObject: TObject): Integer;
  380. begin
  381. Result:=0;
  382. While (Result<count) and (Objects[Result]<>AObject) do Result:=Result+1;
  383. If Result=Count then Result:=-1;
  384. end;
  385. Procedure TStrings.InsertObject(Index: Integer; const S: string;
  386. AObject: TObject);
  387. begin
  388. Insert (Index,S);
  389. Objects[Index]:=AObject;
  390. end;
  391. Procedure TStrings.LoadFromFile(const FileName: string);
  392. Var TheStream : TFileStream;
  393. begin
  394. TheStream:=TFileStream.Create(FileName,fmOpenRead);
  395. LoadFromStream(TheStream);
  396. TheStream.Free;
  397. end;
  398. Procedure TStrings.LoadFromStream(Stream: TStream);
  399. {
  400. Borlands method is no goed, since a pipe for
  401. Instance doesn't have a size.
  402. So we must do it the hard way.
  403. }
  404. Const
  405. BufSize = 1024;
  406. Var
  407. Buffer : Pointer;
  408. BytesRead,
  409. BufLen : Longint;
  410. begin
  411. // reread into a buffer
  412. try
  413. beginupdate;
  414. Buffer:=Nil;
  415. BufLen:=0;
  416. Repeat
  417. ReAllocMem(Buffer,BufLen+BufSize);
  418. BytesRead:=Stream.Read((Buffer+BufLen)^,BufSize);
  419. inc(BufLen,BufSize);
  420. Until BytesRead<>BufSize;
  421. // Null-terminate !!
  422. Pchar(Buffer)[BufLen-BufSize+BytesRead]:=#0;
  423. Text:=PChar(Buffer);
  424. FreeMem(Buffer);
  425. finally
  426. EndUpdate;
  427. end;
  428. end;
  429. Procedure TStrings.Move(CurIndex, NewIndex: Integer);
  430. Var
  431. Obj : TObject;
  432. Str : String;
  433. begin
  434. Obj:=Objects[CurIndex];
  435. Str:=Strings[CurIndex];
  436. Delete(Curindex);
  437. InsertObject(NewIndex,Str,Obj);
  438. end;
  439. Procedure TStrings.SaveToFile(const FileName: string);
  440. Var TheStream : TFileStream;
  441. begin
  442. TheStream:=TFileStream.Create(FileName,fmCreate);
  443. SaveToStream(TheStream);
  444. TheStream.Free;
  445. end;
  446. Procedure TStrings.SaveToStream(Stream: TStream);
  447. Var
  448. S : String;
  449. begin
  450. S:=Text;
  451. Stream.Write(Pointer(S)^,Length(S));
  452. end;
  453. Function GetNextLine (Var P : Pchar; Var S : String) : Boolean;
  454. Var PS : PChar;
  455. begin
  456. S:='';
  457. Result:=False;
  458. If P^=#0 then exit;
  459. PS:=P;
  460. While not (P^ in [#0,#10,#13]) do P:=P+1;
  461. SetLength (S,P-PS);
  462. System.Move (PS^,Pointer(S)^,P-PS);
  463. If P^=#13 then P:=P+1;
  464. If P^=#10 then
  465. P:=P+1; // Point to character after #10(#13)
  466. Result:=True;
  467. end;
  468. Procedure TStrings.SetText(TheText: PChar);
  469. Var S : String;
  470. begin
  471. Try
  472. beginUpdate;
  473. Clear;
  474. While GetNextLine (TheText,S) do
  475. Add(S);
  476. finally
  477. EndUpdate;
  478. end;
  479. end;
  480. {****************************************************************************}
  481. {* TStringList *}
  482. {****************************************************************************}
  483. Procedure TStringList.ExchangeItems(Index1, Index2: Integer);
  484. Var P1,P2 : Pointer;
  485. begin
  486. P1:=Pointer(Flist^[Index1].FString);
  487. P2:=Pointer(Flist^[Index1].FObject);
  488. Pointer(Flist^[Index1].Fstring):=Pointer(Flist^[Index2].Fstring);
  489. Pointer(Flist^[Index1].FObject):=Pointer(Flist^[Index2].FObject);
  490. Pointer(Flist^[Index2].Fstring):=P1;
  491. Pointer(Flist^[Index2].FObject):=P2;
  492. end;
  493. Procedure TStringList.Grow;
  494. Var Extra : Longint;
  495. begin
  496. If FCapacity>64 then
  497. Extra:=FCapacity Div 4
  498. Else If FCapacity>8 Then
  499. Extra:=16
  500. Else
  501. Extra:=4;
  502. SetCapacity(FCapacity+Extra);
  503. end;
  504. Procedure TStringList.QuickSort(L, R: Integer; CompareFn: TStringListSortCompare);
  505. Var I,J, Pivot : Longint;
  506. begin
  507. Repeat
  508. I:=L;
  509. J:=R;
  510. Pivot:=(L+R) div 2;
  511. Repeat
  512. While CompareFn(Self, I, Pivot)<0 do Inc(I);
  513. While CompareFn(Self, J, Pivot)>0 do Dec(J);
  514. If I<=J then
  515. begin
  516. ExchangeItems(I,J); // No check, indices are correct.
  517. if Pivot=I then
  518. Pivot:=J
  519. else if Pivot=J then
  520. Pivot := I;
  521. Inc(I);
  522. Dec(j);
  523. end;
  524. until I>J;
  525. If L<J then QuickSort(L,J, CompareFn);
  526. L:=I;
  527. Until I>=R;
  528. end;
  529. Procedure TStringList.InsertItem(Index: Integer; const S: string);
  530. begin
  531. Changing;
  532. If FCount=Fcapacity then Grow;
  533. If Index<FCount then
  534. System.Move (FList^[Index],FList^[Index+1],
  535. (FCount-Index)*SizeOf(TStringItem));
  536. Pointer(Flist^[Index].Fstring):=Nil; // Needed to initialize...
  537. Flist^[Index].FString:=S;
  538. Flist^[Index].Fobject:=Nil;
  539. Inc(FCount);
  540. Changed;
  541. end;
  542. Procedure TStringList.SetSorted(Value: Boolean);
  543. begin
  544. If FSorted<>Value then
  545. begin
  546. If Value then sort;
  547. FSorted:=VAlue
  548. end;
  549. end;
  550. Procedure TStringList.Changed;
  551. begin
  552. If (FUpdateCount=0) Then
  553. If Assigned(FOnChange) then
  554. FOnchange(Self);
  555. end;
  556. Procedure TStringList.Changing;
  557. begin
  558. If FUpdateCount=0 then
  559. if Assigned(FOnChanging) then
  560. FOnchanging(Self);
  561. end;
  562. Function TStringList.Get(Index: Integer): string;
  563. begin
  564. If (Index<0) or (INdex>=Fcount) then
  565. Error (SListIndexError,Index);
  566. Result:=Flist^[Index].FString;
  567. end;
  568. Function TStringList.GetCapacity: Integer;
  569. begin
  570. Result:=FCapacity;
  571. end;
  572. Function TStringList.GetCount: Integer;
  573. begin
  574. Result:=FCount;
  575. end;
  576. Function TStringList.GetObject(Index: Integer): TObject;
  577. begin
  578. If (Index<0) or (INdex>=Fcount) then
  579. Error (SListIndexError,Index);
  580. Result:=Flist^[Index].FObject;
  581. end;
  582. Procedure TStringList.Put(Index: Integer; const S: string);
  583. begin
  584. If Sorted then
  585. Error(SSortedListError,0);
  586. If (Index<0) or (INdex>=Fcount) then
  587. Error (SListIndexError,Index);
  588. Changing;
  589. Flist^[Index].FString:=S;
  590. Changed;
  591. end;
  592. Procedure TStringList.PutObject(Index: Integer; AObject: TObject);
  593. begin
  594. If (Index<0) or (INdex>=Fcount) then
  595. Error (SListIndexError,Index);
  596. Changing;
  597. Flist^[Index].FObject:=AObject;
  598. Changed;
  599. end;
  600. Procedure TStringList.SetCapacity(NewCapacity: Integer);
  601. Var NewList : Pointer;
  602. MSize : Longint;
  603. begin
  604. If (NewCapacity<0) then
  605. Error (SListCapacityError,NewCapacity);
  606. If NewCapacity>FCapacity then
  607. begin
  608. GetMem (NewList,NewCapacity*SizeOf(TStringItem));
  609. If NewList=Nil then
  610. Error (SListCapacityError,NewCapacity);
  611. If Assigned(FList) then
  612. begin
  613. MSize:=FCapacity*Sizeof(TStringItem);
  614. System.Move (FList^,NewList^,MSize);
  615. FillWord (Pchar(NewList)[MSize],(NewCapacity-FCapacity)*WordRatio, 0);
  616. FreeMem (Flist,MSize);
  617. end;
  618. Flist:=NewList;
  619. FCapacity:=NewCapacity;
  620. end
  621. else if NewCapacity<FCapacity then
  622. begin
  623. if NewCapacity = 0 then
  624. begin
  625. FreeMem(FList);
  626. FList := nil;
  627. end else
  628. begin
  629. GetMem(NewList, NewCapacity * SizeOf(TStringItem));
  630. System.Move(FList^, NewList^, NewCapacity * SizeOf(TStringItem));
  631. FreeMem(FList);
  632. FList := NewList;
  633. end;
  634. FCapacity:=NewCapacity;
  635. end;
  636. end;
  637. Procedure TStringList.SetUpdateState(Updating: Boolean);
  638. begin
  639. If Updating then
  640. Changing
  641. else
  642. Changed
  643. end;
  644. destructor TStringList.Destroy;
  645. Var I : Longint;
  646. begin
  647. FOnChange:=Nil;
  648. FOnChanging:=Nil;
  649. // This will force a dereference. Can be done better...
  650. For I:=0 to FCount-1 do
  651. FList^[I].FString:='';
  652. FCount:=0;
  653. SetCapacity(0);
  654. Inherited destroy;
  655. end;
  656. Function TStringList.Add(const S: string): Integer;
  657. begin
  658. If Not Sorted then
  659. Result:=FCount
  660. else
  661. If Find (S,Result) then
  662. Case DUplicates of
  663. DupIgnore : Exit;
  664. DupError : Error(SDuplicateString,0)
  665. end;
  666. InsertItem (Result,S);
  667. end;
  668. Procedure TStringList.Clear;
  669. Var I : longint;
  670. begin
  671. For I:=0 to FCount-1 do
  672. Flist^[I].FString:='';
  673. FCount:=0;
  674. SetCapacity(0);
  675. end;
  676. Procedure TStringList.Delete(Index: Integer);
  677. begin
  678. If (Index<0) or (Index>=FCount) then
  679. Error(SlistINdexError,Index);
  680. Flist^[Index].FString:='';
  681. Dec(FCount);
  682. If Index<FCount then
  683. System.Move(Flist^[Index+1],
  684. Flist^[Index],
  685. (Fcount-Index)*SizeOf(TStringItem));
  686. end;
  687. Procedure TStringList.Exchange(Index1, Index2: Integer);
  688. begin
  689. If (Index1<0) or (Index1>=FCount) then
  690. Error(SListIndexError,Index1);
  691. If (Index2<0) or (Index2>=FCount) then
  692. Error(SListIndexError,Index2);
  693. Changing;
  694. ExchangeItems(Index1,Index2);
  695. changed;
  696. end;
  697. Function TStringList.Find(const S: string; var Index: Integer): Boolean;
  698. { Searches for the first string <= S, returns True if exact match,
  699. sets index to the index f the found string. }
  700. Var I,L,R,Temp : Longint;
  701. begin
  702. Result:=False;
  703. // Use binary search.
  704. L:=0;
  705. R:=FCount-1;
  706. While L<=R do
  707. begin
  708. I:=(L+R) div 2;
  709. Temp:=AnsiCompareText(FList^ [I].FString,S);
  710. If Temp<0 then
  711. L:=I+1
  712. else
  713. begin
  714. R:=I-1;
  715. If Temp=0 then
  716. begin
  717. Result:=True;
  718. If Duplicates<>DupAccept then L:=I;
  719. end;
  720. end;
  721. end;
  722. Index:=L;
  723. end;
  724. Function TStringList.IndexOf(const S: string): Integer;
  725. begin
  726. If Not Sorted then
  727. Result:=Inherited indexOf(S)
  728. else
  729. // faster using binary search...
  730. If Not Find (S,Result) then
  731. Result:=-1;
  732. end;
  733. Procedure TStringList.Insert(Index: Integer; const S: string);
  734. begin
  735. If Sorted then
  736. Error (SSortedListError,0)
  737. else
  738. If (Index<0) or (Index>FCount) then
  739. Error (SListIndexError,Index)
  740. else
  741. InsertItem (Index,S);
  742. end;
  743. Procedure TStringList.CustomSort(CompareFn: TStringListSortCompare);
  744. begin
  745. If Not Sorted and (FCount>1) then
  746. begin
  747. Changing;
  748. QuickSort(0,FCount-1, CompareFn);
  749. Changed;
  750. end;
  751. end;
  752. function StringListAnsiCompare(List: TStringList; Index1, Index: Integer): Integer;
  753. begin
  754. Result := AnsiCompareText(List.FList^[Index1].FString,
  755. List.FList^[Index].FString);
  756. end;
  757. Procedure TStringList.Sort;
  758. begin
  759. CustomSort(@StringListAnsiCompare);
  760. end;
  761. {
  762. $Log$
  763. Revision 1.1 2003-10-06 20:33:58 peter
  764. * classes moved to rtl for 1.1
  765. * classes .inc and classes.pp files moved to fcl/classes for
  766. backwards 1.0.x compatiblity to have it in the fcl
  767. Revision 1.15 2003/05/29 23:13:57 michael
  768. fixed case insensitivity of TStrings.IndexOf
  769. Revision 1.14 2002/12/10 21:05:44 michael
  770. + IndexOfName is case insensitive
  771. Revision 1.13 2002/10/10 12:50:40 michael
  772. + Fix for handling of double quotes in getquotedstring from Luk Vandelaer ([email protected])
  773. Revision 1.12 2002/09/07 15:15:25 peter
  774. * old logs removed and tabs fixed
  775. Revision 1.11 2002/07/17 11:52:01 florian
  776. * at and frame addresses in raise statements changed to pointer; fixed
  777. }