Objstr.pas
上传用户:hylc_2004
上传日期:2014-01-23
资源大小:46800k
文件大小:10k
- {*******************************************************}
- { }
- { Delphi VCL Extensions (RX) }
- { }
- { Copyright (c) 1995, 1996 AO ROSNO }
- { Copyright (c) 1997, 1998 Master-Bank }
- { }
- {*******************************************************}
- unit ObjStr;
- interface
- {$I RX.INC}
- uses SysUtils, Classes, RTLConsts;
- type
- { TObjectStrings }
- TDestroyEvent = procedure(Sender, AObject: TObject) of object;
- TObjectSortCompare = function (const S1, S2: string;
- Item1, Item2: TObject): Integer of object;
- TObjectStrings = class(TStringList)
- private
- FOnDestroyObject: TDestroyEvent;
- protected
- procedure DestroyObject(AObject: TObject); virtual;
- procedure PutObject(Index: Integer; AObject: TObject); override;
- public
- procedure Clear; override;
- procedure Delete(Index: Integer); override;
- procedure Move(CurIndex, NewIndex: Integer); override;
- procedure Remove(Index: Integer);
- procedure ParseStrings(const Values: string);
- procedure SortList(Compare: TObjectSortCompare);
- property OnDestroyObject: TDestroyEvent read FOnDestroyObject
- write FOnDestroyObject;
- end;
- { THugeList class }
- const
- {$IFDEF WIN32}
- MaxHugeListSize = MaxListSize;
- {$ELSE}
- MaxHugeListSize = (MaxLongint div SizeOf(Pointer)) - 4;
- {$ENDIF}
- type
- {$IFDEF WIN32}
- THugeList = class(TList);
- {$ELSE}
- THugeList = class(TObject)
- private
- FList: TMemoryStream;
- FCount: Longint;
- FCapacity: Longint;
- protected
- function Get(Index: Longint): Pointer;
- procedure Grow; virtual;
- procedure Put(Index: Longint; Item: Pointer);
- procedure SetCapacity(NewCapacity: Longint);
- procedure SetCount(NewCount: Longint);
- public
- destructor Destroy; override;
- function Add(Item: Pointer): Longint;
- procedure Clear;
- procedure Delete(Index: Longint);
- procedure Exchange(Index1, Index2: Longint);
- function Expand: THugeList;
- function First: Pointer;
- function IndexOf(Item: Pointer): Longint;
- procedure Insert(Index: Longint; Item: Pointer);
- function Last: Pointer;
- procedure Move(CurIndex, NewIndex: Longint);
- function Remove(Item: Pointer): Longint;
- procedure Pack;
- property Capacity: Longint read FCapacity write SetCapacity;
- property Count: Longint read FCount write SetCount;
- property Items[Index: Longint]: Pointer read Get write Put; default;
- end;
- {$ENDIF WIN32}
- {$IFDEF WIN32}
- { TSortCollection }
- type
- TItemSortCompare = function (Item1, Item2: TCollectionItem): Integer of object;
- TSortCollection = class(TCollection)
- protected
- procedure QuickSort(L, R: Integer; Compare: TItemSortCompare); virtual;
- public
- procedure Sort(Compare: TItemSortCompare);
- end;
- {$ENDIF WIN32}
- implementation
- uses {$IFNDEF WIN32} VCLUtils, {$ENDIF} Consts, rxStrUtils;
- { TObjectStrings }
- procedure QuickSort(SortList: TStrings; L, R: Integer;
- SCompare: TObjectSortCompare);
- var
- I, J: Integer;
- P: TObject;
- S: string;
- begin
- repeat
- I := L;
- J := R;
- P := SortList.Objects[(L + R) shr 1];
- S := SortList[(L + R) shr 1];
- repeat
- while SCompare(SortList[I], S, SortList.Objects[I], P) < 0 do Inc(I);
- while SCompare(SortList[J], S, SortList.Objects[J], P) > 0 do Dec(J);
- if I <= J then begin
- SortList.Exchange(I, J);
- Inc(I);
- Dec(J);
- end;
- until I > J;
- if L < J then QuickSort(SortList, L, J, SCompare);
- L := I;
- until I >= R;
- end;
- procedure TObjectStrings.DestroyObject(AObject: TObject);
- begin
- if Assigned(FOnDestroyObject) then FOnDestroyObject(Self, AObject)
- else if AObject <> nil then AObject.Free;
- end;
- procedure TObjectStrings.Clear;
- var
- I: Integer;
- begin
- if Count > 0 then begin
- Changing;
- for I := 0 to Count - 1 do Objects[I] := nil;
- BeginUpdate;
- try
- inherited Clear;
- finally
- EndUpdate;
- end;
- Changed;
- end;
- end;
- procedure TObjectStrings.Delete(Index: Integer);
- begin
- Objects[Index] := nil;
- inherited Delete(Index);
- end;
- procedure TObjectStrings.Remove(Index: Integer);
- begin
- inherited Delete(Index);
- end;
- procedure TObjectStrings.Move(CurIndex, NewIndex: Integer);
- var
- TempObject: TObject;
- TempString: string;
- begin
- if CurIndex <> NewIndex then
- begin
- TempString := Get(CurIndex);
- TempObject := GetObject(CurIndex);
- inherited Delete(CurIndex);
- try
- InsertObject(NewIndex, TempString, TempObject);
- except
- DestroyObject(TempObject);
- raise;
- end;
- end;
- end;
- procedure TObjectStrings.PutObject(Index: Integer; AObject: TObject);
- begin
- Changing;
- BeginUpdate;
- try
- if (Index < Self.Count) and (Index >= 0) then
- DestroyObject(Objects[Index]);
- inherited PutObject(Index, AObject);
- finally
- EndUpdate;
- end;
- Changed;
- end;
- procedure TObjectStrings.ParseStrings(const Values: string);
- var
- Pos: Integer;
- begin
- Pos := 1;
- BeginUpdate;
- try
- while Pos <= Length(Values) do Add(ExtractSubstr(Values, Pos, [';']));
- finally
- EndUpdate;
- end;
- end;
- procedure TObjectStrings.SortList(Compare: TObjectSortCompare);
- begin
- if Sorted then
- {$IFDEF RX_D3}
- Error(SSortedListError, 0);
- {$ELSE}
- raise EListError.Create(LoadStr(SSortedListError));
- {$ENDIF}
- if Count > 0 then begin
- BeginUpdate;
- try
- QuickSort(Self, 0, Count - 1, Compare);
- finally
- EndUpdate;
- end;
- end;
- end;
- {$IFNDEF WIN32}
- { THugeList }
- function ReturnAddr: Pointer; assembler;
- asm
- MOV AX,[BP].Word[2]
- MOV DX,[BP].Word[4]
- end;
- procedure ListError(Index: Longint);
- begin
- raise EListError.Create(LoadStr(SListIndexError) +
- Format(' (%d)', [Index])) at ReturnAddr;
- end;
- destructor THugeList.Destroy;
- begin
- Clear;
- end;
- function THugeList.Add(Item: Pointer): Longint;
- begin
- Result := FCount;
- if Result = FCapacity then Grow;
- FList.Position := Result * SizeOf(Pointer);
- FList.WriteBuffer(Item, SizeOf(Pointer));
- Inc(FCount);
- end;
- procedure THugeList.Clear;
- begin
- SetCount(0);
- SetCapacity(0);
- end;
- procedure THugeList.Delete(Index: Longint);
- begin
- if (Index < 0) or (Index >= FCount) then ListError(Index);
- Dec(FCount);
- if Index < FCount then
- HugeMove(FList.Memory, Index, Index + 1, FCount - Index);
- end;
- function THugeList.Get(Index: Longint): Pointer;
- begin
- if (Index < 0) or (Index >= FCount) then ListError(Index);
- FList.Position := Index * SizeOf(Pointer);
- FList.ReadBuffer(Result, SizeOf(Pointer));
- end;
- procedure THugeList.Put(Index: Longint; Item: Pointer);
- begin
- if (Index < 0) or (Index >= FCount) then ListError(Index);
- FList.Position := Index * SizeOf(Pointer);
- FList.WriteBuffer(Item, SizeOf(Pointer));
- end;
- procedure THugeList.Exchange(Index1, Index2: Longint);
- var
- Item: Pointer;
- begin
- Item := Get(Index1);
- Put(Index1, Get(Index2));
- Put(Index2, Item);
- end;
- function THugeList.Expand: THugeList;
- begin
- if FCount = FCapacity then Grow;
- Result := Self;
- end;
- function THugeList.First: Pointer;
- begin
- Result := Get(0);
- end;
- procedure THugeList.Grow;
- var
- Delta: Longint;
- begin
- if FCapacity > 8 then Delta := 16
- else if FCapacity > 4 then Delta := 8
- else Delta := 4;
- SetCapacity(FCapacity + Delta);
- end;
- function THugeList.IndexOf(Item: Pointer): Longint;
- begin
- Result := 0;
- while (Result < FCount) and (Get(Result) <> Item) do
- Inc(Result);
- if Result = FCount then Result := -1;
- end;
- procedure THugeList.Insert(Index: Longint; Item: Pointer);
- begin
- if (Index < 0) or (Index > FCount) then ListError(Index);
- if FCount = FCapacity then Grow;
- if Index < FCount then
- HugeMove(FList.Memory, Index + 1, Index, FCount - Index);
- FList.Position := Index * SizeOf(Pointer);
- FList.WriteBuffer(Item, SizeOf(Pointer));
- Inc(FCount);
- end;
- function THugeList.Last: Pointer;
- begin
- Result := Get(FCount - 1);
- end;
- procedure THugeList.Move(CurIndex, NewIndex: Longint);
- var
- Item: Pointer;
- begin
- if CurIndex <> NewIndex then begin
- if (NewIndex < 0) or (NewIndex >= FCount) then ListError(NewIndex);
- Item := Get(CurIndex);
- Delete(CurIndex);
- Insert(NewIndex, Item);
- end;
- end;
- function THugeList.Remove(Item: Pointer): Longint;
- begin
- Result := IndexOf(Item);
- if Result <> -1 then Delete(Result);
- end;
- procedure THugeList.Pack;
- var
- I: Longint;
- begin
- for I := FCount - 1 downto 0 do
- if Items[I] = nil then Delete(I);
- end;
- procedure THugeList.SetCapacity(NewCapacity: Longint);
- var
- NewList: TMemoryStream;
- begin
- if (NewCapacity < FCount) or (NewCapacity > MaxHugeListSize) then
- ListError(NewCapacity);
- if NewCapacity <> FCapacity then begin
- if NewCapacity = 0 then NewList := nil
- else begin
- NewList := TMemoryStream.Create;
- NewList.SetSize(NewCapacity * SizeOf(Pointer));
- if FCount <> 0 then begin
- FList.Position := 0;
- FList.ReadBuffer(NewList.Memory^, FCount * SizeOf(Pointer));
- end;
- end;
- if FCapacity <> 0 then FList.Free;
- FList := NewList;
- FCapacity := NewCapacity;
- end;
- end;
- procedure THugeList.SetCount(NewCount: Longint);
- begin
- if (NewCount < 0) or (NewCount > MaxHugeListSize) then
- ListError(NewCount);
- if NewCount > FCapacity then SetCapacity(NewCount);
- FCount := NewCount;
- end;
- {$ENDIF}
- {$IFDEF WIN32}
- { TSortCollection }
- procedure TSortCollection.QuickSort(L, R: Integer; Compare: TItemSortCompare);
- var
- I, J: Integer;
- P, P1, P2: TCollectionItem;
- begin
- repeat
- I := L;
- J := R;
- P := Items[(L + R) shr 1];
- repeat
- while Compare(Items[I], P) < 0 do Inc(I);
- while Compare(Items[J], P) > 0 do Dec(J);
- if I <= J then begin
- P1 := Items[I];
- P2 := Items[J];
- P1.Index := J;
- P2.Index := I;
- Inc(I);
- Dec(J);
- end;
- until I > J;
- if L < J then QuickSort(L, J, Compare);
- L := I;
- until I >= R;
- end;
- procedure TSortCollection.Sort(Compare: TItemSortCompare);
- begin
- if Count > 0 then begin
- BeginUpdate;
- try
- QuickSort(0, Count - 1, Compare);
- finally
- EndUpdate;
- end;
- end;
- end;
- {$ENDIF WIN32}
- end.