home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 September / Chip_2001-09_cd1.bin / zkuste / delphi / kolekce / d6 / RX275D6.ZIP / Units / OBJSTR.PAS < prev    next >
Pascal/Delphi Source File  |  2001-06-24  |  11KB  |  447 lines

  1. {*******************************************************}
  2. {                                                       }
  3. {         Delphi VCL Extensions (RX)                    }
  4. {                                                       }
  5. {         Copyright (c) 1995, 1996 AO ROSNO             }
  6. {         Copyright (c) 1997, 1998 Master-Bank          }
  7. {                                                       }
  8. {*******************************************************}
  9.  
  10. unit ObjStr;
  11.  
  12. interface
  13.  
  14. {$I RX.INC}
  15.  
  16. uses SysUtils, Classes, RTLConsts;
  17.  
  18. type
  19.  
  20. { TObjectStrings }
  21.  
  22.   TDestroyEvent = procedure(Sender, AObject: TObject) of object;
  23.   TObjectSortCompare = function (const S1, S2: string;
  24.     Item1, Item2: TObject): Integer of object;
  25.  
  26.   TObjectStrings = class(TStringList)
  27.   private
  28.     FOnDestroyObject: TDestroyEvent;
  29.   protected
  30.     procedure DestroyObject(AObject: TObject); virtual;
  31.     procedure PutObject(Index: Integer; AObject: TObject); override;
  32.   public
  33.     procedure Clear; override;
  34.     procedure Delete(Index: Integer); override;
  35.     procedure Move(CurIndex, NewIndex: Integer); override;
  36.     procedure Remove(Index: Integer);
  37.     procedure ParseStrings(const Values: string);
  38.     procedure SortList(Compare: TObjectSortCompare);
  39.     property OnDestroyObject: TDestroyEvent read FOnDestroyObject
  40.       write FOnDestroyObject;
  41.   end;
  42.  
  43. { THugeList class }
  44.  
  45. const
  46. {$IFDEF WIN32}
  47.   MaxHugeListSize = MaxListSize;
  48. {$ELSE}
  49.   MaxHugeListSize = (MaxLongint div SizeOf(Pointer)) - 4;
  50. {$ENDIF}
  51.  
  52. type
  53. {$IFDEF WIN32}
  54.   THugeList = class(TList);
  55. {$ELSE}
  56.   THugeList = class(TObject)
  57.   private
  58.     FList: TMemoryStream;
  59.     FCount: Longint;
  60.     FCapacity: Longint;
  61.   protected
  62.     function Get(Index: Longint): Pointer;
  63.     procedure Grow; virtual;
  64.     procedure Put(Index: Longint; Item: Pointer);
  65.     procedure SetCapacity(NewCapacity: Longint);
  66.     procedure SetCount(NewCount: Longint);
  67.   public
  68.     destructor Destroy; override;
  69.     function Add(Item: Pointer): Longint;
  70.     procedure Clear;
  71.     procedure Delete(Index: Longint);
  72.     procedure Exchange(Index1, Index2: Longint);
  73.     function Expand: THugeList;
  74.     function First: Pointer;
  75.     function IndexOf(Item: Pointer): Longint;
  76.     procedure Insert(Index: Longint; Item: Pointer);
  77.     function Last: Pointer;
  78.     procedure Move(CurIndex, NewIndex: Longint);
  79.     function Remove(Item: Pointer): Longint;
  80.     procedure Pack;
  81.     property Capacity: Longint read FCapacity write SetCapacity;
  82.     property Count: Longint read FCount write SetCount;
  83.     property Items[Index: Longint]: Pointer read Get write Put; default;
  84.   end;
  85. {$ENDIF WIN32}
  86.  
  87. {$IFDEF WIN32}
  88.  
  89. { TSortCollection }
  90.  
  91. type
  92.   TItemSortCompare = function (Item1, Item2: TCollectionItem): Integer of object;
  93.  
  94.   TSortCollection = class(TCollection)
  95.   protected
  96.     procedure QuickSort(L, R: Integer; Compare: TItemSortCompare); virtual;
  97.   public
  98.     procedure Sort(Compare: TItemSortCompare);
  99.   end;
  100.  
  101. {$ENDIF WIN32}
  102.  
  103. implementation
  104.  
  105. uses {$IFNDEF WIN32} VCLUtils, {$ENDIF} Consts, rxStrUtils;
  106.  
  107. { TObjectStrings }
  108.  
  109. procedure QuickSort(SortList: TStrings; L, R: Integer;
  110.   SCompare: TObjectSortCompare);
  111. var
  112.   I, J: Integer;
  113.   P: TObject;
  114.   S: string;
  115. begin
  116.   repeat
  117.     I := L;
  118.     J := R;
  119.     P := SortList.Objects[(L + R) shr 1];
  120.     S := SortList[(L + R) shr 1];
  121.     repeat
  122.       while SCompare(SortList[I], S, SortList.Objects[I], P) < 0 do Inc(I);
  123.       while SCompare(SortList[J], S, SortList.Objects[J], P) > 0 do Dec(J);
  124.       if I <= J then begin
  125.         SortList.Exchange(I, J);
  126.         Inc(I);
  127.         Dec(J);
  128.       end;
  129.     until I > J;
  130.     if L < J then QuickSort(SortList, L, J, SCompare);
  131.     L := I;
  132.   until I >= R;
  133. end;
  134.  
  135. procedure TObjectStrings.DestroyObject(AObject: TObject);
  136. begin
  137.   if Assigned(FOnDestroyObject) then FOnDestroyObject(Self, AObject)
  138.   else if AObject <> nil then AObject.Free;
  139. end;
  140.  
  141. procedure TObjectStrings.Clear;
  142. var
  143.   I: Integer;
  144. begin
  145.   if Count > 0 then begin
  146.     Changing;
  147.     for I := 0 to Count - 1 do Objects[I] := nil;
  148.     BeginUpdate;
  149.     try
  150.       inherited Clear;
  151.     finally
  152.       EndUpdate;
  153.     end;
  154.     Changed;
  155.   end;
  156. end;
  157.  
  158. procedure TObjectStrings.Delete(Index: Integer);
  159. begin
  160.   Objects[Index] := nil;
  161.   inherited Delete(Index);
  162. end;
  163.  
  164. procedure TObjectStrings.Remove(Index: Integer);
  165. begin
  166.   inherited Delete(Index);
  167. end;
  168.  
  169. procedure TObjectStrings.Move(CurIndex, NewIndex: Integer);
  170. var
  171.   TempObject: TObject;
  172.   TempString: string;
  173. begin
  174.   if CurIndex <> NewIndex then
  175.   begin
  176.     TempString := Get(CurIndex);
  177.     TempObject := GetObject(CurIndex);
  178.     inherited Delete(CurIndex);
  179.     try
  180.       InsertObject(NewIndex, TempString, TempObject);
  181.     except
  182.       DestroyObject(TempObject);
  183.       raise;
  184.     end;
  185.   end;
  186. end;
  187.  
  188. procedure TObjectStrings.PutObject(Index: Integer; AObject: TObject);
  189. begin
  190.   Changing;
  191.   BeginUpdate;
  192.   try
  193.     if (Index < Self.Count) and (Index >= 0) then
  194.       DestroyObject(Objects[Index]);
  195.     inherited PutObject(Index, AObject);
  196.   finally
  197.     EndUpdate;
  198.   end;
  199.   Changed;
  200. end;
  201.  
  202. procedure TObjectStrings.ParseStrings(const Values: string);
  203. var
  204.   Pos: Integer;
  205. begin
  206.   Pos := 1;
  207.   BeginUpdate;
  208.   try
  209.     while Pos <= Length(Values) do Add(ExtractSubstr(Values, Pos, [';']));
  210.   finally
  211.     EndUpdate;
  212.   end;
  213. end;
  214.  
  215. procedure TObjectStrings.SortList(Compare: TObjectSortCompare);
  216. begin
  217.   if Sorted then
  218. {$IFDEF RX_D3}
  219.     Error(SSortedListError, 0);
  220. {$ELSE}
  221.     raise EListError.Create(LoadStr(SSortedListError));
  222. {$ENDIF}
  223.   if Count > 0 then begin
  224.     BeginUpdate;
  225.     try
  226.       QuickSort(Self, 0, Count - 1, Compare);
  227.     finally
  228.       EndUpdate;
  229.     end;
  230.   end;
  231. end;
  232.  
  233. {$IFNDEF WIN32}
  234.  
  235. { THugeList }
  236.  
  237. function ReturnAddr: Pointer; assembler;
  238. asm
  239.         MOV     AX,[BP].Word[2]
  240.         MOV     DX,[BP].Word[4]
  241. end;
  242.  
  243. procedure ListError(Index: Longint);
  244. begin
  245.   raise EListError.Create(LoadStr(SListIndexError) +
  246.     Format(' (%d)', [Index])) at ReturnAddr;
  247. end;
  248.  
  249. destructor THugeList.Destroy;
  250. begin
  251.   Clear;
  252. end;
  253.  
  254. function THugeList.Add(Item: Pointer): Longint;
  255. begin
  256.   Result := FCount;
  257.   if Result = FCapacity then Grow;
  258.   FList.Position := Result * SizeOf(Pointer);
  259.   FList.WriteBuffer(Item, SizeOf(Pointer));
  260.   Inc(FCount);
  261. end;
  262.  
  263. procedure THugeList.Clear;
  264. begin
  265.   SetCount(0);
  266.   SetCapacity(0);
  267. end;
  268.  
  269. procedure THugeList.Delete(Index: Longint);
  270. begin
  271.   if (Index < 0) or (Index >= FCount) then ListError(Index);
  272.   Dec(FCount);
  273.   if Index < FCount then
  274.     HugeMove(FList.Memory, Index, Index + 1, FCount - Index);
  275. end;
  276.  
  277. function THugeList.Get(Index: Longint): Pointer;
  278. begin
  279.   if (Index < 0) or (Index >= FCount) then ListError(Index);
  280.   FList.Position := Index * SizeOf(Pointer);
  281.   FList.ReadBuffer(Result, SizeOf(Pointer));
  282. end;
  283.  
  284. procedure THugeList.Put(Index: Longint; Item: Pointer);
  285. begin
  286.   if (Index < 0) or (Index >= FCount) then ListError(Index);
  287.   FList.Position := Index * SizeOf(Pointer);
  288.   FList.WriteBuffer(Item, SizeOf(Pointer));
  289. end;
  290.  
  291. procedure THugeList.Exchange(Index1, Index2: Longint);
  292. var
  293.   Item: Pointer;
  294. begin
  295.   Item := Get(Index1);
  296.   Put(Index1, Get(Index2));
  297.   Put(Index2, Item);
  298. end;
  299.  
  300. function THugeList.Expand: THugeList;
  301. begin
  302.   if FCount = FCapacity then Grow;
  303.   Result := Self;
  304. end;
  305.  
  306. function THugeList.First: Pointer;
  307. begin
  308.   Result := Get(0);
  309. end;
  310.  
  311. procedure THugeList.Grow;
  312. var
  313.   Delta: Longint;
  314. begin
  315.   if FCapacity > 8 then Delta := 16
  316.   else if FCapacity > 4 then Delta := 8
  317.   else Delta := 4;
  318.   SetCapacity(FCapacity + Delta);
  319. end;
  320.  
  321. function THugeList.IndexOf(Item: Pointer): Longint;
  322. begin
  323.   Result := 0;
  324.   while (Result < FCount) and (Get(Result) <> Item) do
  325.     Inc(Result);
  326.   if Result = FCount then Result := -1;
  327. end;
  328.  
  329. procedure THugeList.Insert(Index: Longint; Item: Pointer);
  330. begin
  331.   if (Index < 0) or (Index > FCount) then ListError(Index);
  332.   if FCount = FCapacity then Grow;
  333.   if Index < FCount then
  334.     HugeMove(FList.Memory, Index + 1, Index, FCount - Index);
  335.   FList.Position := Index * SizeOf(Pointer);
  336.   FList.WriteBuffer(Item, SizeOf(Pointer));
  337.   Inc(FCount);
  338. end;
  339.  
  340. function THugeList.Last: Pointer;
  341. begin
  342.   Result := Get(FCount - 1);
  343. end;
  344.  
  345. procedure THugeList.Move(CurIndex, NewIndex: Longint);
  346. var
  347.   Item: Pointer;
  348. begin
  349.   if CurIndex <> NewIndex then begin
  350.     if (NewIndex < 0) or (NewIndex >= FCount) then ListError(NewIndex);
  351.     Item := Get(CurIndex);
  352.     Delete(CurIndex);
  353.     Insert(NewIndex, Item);
  354.   end;
  355. end;
  356.  
  357. function THugeList.Remove(Item: Pointer): Longint;
  358. begin
  359.   Result := IndexOf(Item);
  360.   if Result <> -1 then Delete(Result);
  361. end;
  362.  
  363. procedure THugeList.Pack;
  364. var
  365.   I: Longint;
  366. begin
  367.   for I := FCount - 1 downto 0 do
  368.     if Items[I] = nil then Delete(I);
  369. end;
  370.  
  371. procedure THugeList.SetCapacity(NewCapacity: Longint);
  372. var
  373.   NewList: TMemoryStream;
  374. begin
  375.   if (NewCapacity < FCount) or (NewCapacity > MaxHugeListSize) then
  376.     ListError(NewCapacity);
  377.   if NewCapacity <> FCapacity then begin
  378.     if NewCapacity = 0 then NewList := nil
  379.     else begin
  380.       NewList := TMemoryStream.Create;
  381.       NewList.SetSize(NewCapacity * SizeOf(Pointer));
  382.       if FCount <> 0 then begin
  383.         FList.Position := 0;
  384.         FList.ReadBuffer(NewList.Memory^, FCount * SizeOf(Pointer));
  385.       end;
  386.     end;
  387.     if FCapacity <> 0 then FList.Free;
  388.     FList := NewList;
  389.     FCapacity := NewCapacity;
  390.   end;
  391. end;
  392.  
  393. procedure THugeList.SetCount(NewCount: Longint);
  394. begin
  395.   if (NewCount < 0) or (NewCount > MaxHugeListSize) then
  396.     ListError(NewCount);
  397.   if NewCount > FCapacity then SetCapacity(NewCount);
  398.   FCount := NewCount;
  399. end;
  400.  
  401. {$ENDIF}
  402.  
  403. {$IFDEF WIN32}
  404.  
  405. { TSortCollection }
  406.  
  407. procedure TSortCollection.QuickSort(L, R: Integer; Compare: TItemSortCompare);
  408. var
  409.   I, J: Integer;
  410.   P, P1, P2: TCollectionItem;
  411. begin
  412.   repeat
  413.     I := L;
  414.     J := R;
  415.     P := Items[(L + R) shr 1];
  416.     repeat
  417.       while Compare(Items[I], P) < 0 do Inc(I);
  418.       while Compare(Items[J], P) > 0 do Dec(J);
  419.       if I <= J then begin
  420.         P1 := Items[I];
  421.         P2 := Items[J];
  422.         P1.Index := J;
  423.         P2.Index := I;
  424.         Inc(I);
  425.         Dec(J);
  426.       end;
  427.     until I > J;
  428.     if L < J then QuickSort(L, J, Compare);
  429.     L := I;
  430.   until I >= R;
  431. end;
  432.  
  433. procedure TSortCollection.Sort(Compare: TItemSortCompare);
  434. begin
  435.   if Count > 0 then begin
  436.     BeginUpdate;
  437.     try
  438.       QuickSort(0, Count - 1, Compare);
  439.     finally
  440.       EndUpdate;
  441.     end;
  442.   end;
  443. end;
  444.  
  445. {$ENDIF WIN32}
  446.  
  447. end.