Objstr.pas
上传用户:hylc_2004
上传日期:2014-01-23
资源大小:46800k
文件大小:10k
源码类别:

Delphi控件源码

开发平台:

Delphi

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