Ignore:
Timestamp:
Sep 21, 2012, 9:19:58 AM (12 years ago)
Author:
chronos
Message:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • Generics/NativeGenerics/Units/GenericList.pas

    r424 r425  
    1313
    1414  TGAbstractList<TItem> = class
     15  private
     16    FOnUpdate: TNotifyEvent;
     17    FUpdateCount: NativeInt;
    1518  public
    1619  type
    1720    TIndex = NativeInt;
     21    PItem = ^TItem;
    1822    TSortCompare = function(Item1, Item2: TItem): Integer of object;
    1923    TToStringConverter = function(Item: TItem): string;
     
    2933    function Get(Index: TIndex): TItem; virtual; abstract;
    3034    procedure Put(Index: TIndex; const AValue: TItem); virtual; abstract;
     35    function GetInternal(Index: TIndex): TItem; virtual; abstract;
     36    procedure PutInternal(Index: TIndex; const AValue: TItem); virtual; abstract;
    3137    procedure QuickSort(L, R : TIndex; Compare: TSortCompare);
     38    property ItemsInternal[Index: TIndex]: TItem read GetInternal
     39      write PutInternal;
    3240  public
    3341    function Add(const Item: TItem): TIndex; virtual;
     
    3644    procedure AddListPart(List: TGAbstractList<TItem>; ItemIndex, ItemCount: TIndex);
    3745    procedure Assign(Source: TGAbstractList<TItem>); virtual;
     46    procedure BeginUpdate;
     47    procedure EndUpdate;
     48    procedure Update;
    3849    constructor Create; virtual;
    3950    procedure Clear; virtual;
     
    4657    procedure Explode(Text, Separator: string; Converter: TFromStringConverter; SlicesCount: Integer = -1);
    4758    function Extract(Item: TItem): TItem; virtual;
    48     procedure Fill(Start, Count: TIndex; Value: TItem); virtual;
     59    procedure Fill(Start, ACount: TIndex; Value: TItem); virtual;
    4960    function GetArray(Index, ACount: TIndex): TItemArray; virtual;
    5061    procedure GetList(List: TGAbstractList<TItem>; Index, ACount: TIndex); virtual;
     62    procedure GetBuffer(Index: TIndex; var Buffer; ACount: TIndex); virtual;
    5163    function IndexOfList(List: TGAbstractList<TItem>; Start: TIndex = 0): TIndex; virtual;
    5264    procedure Insert(const Index: TIndex; Item: TItem); virtual;
     
    6274    procedure ReplaceListPart(const Index: TIndex; Source: TGAbstractList<TItem>;
    6375      SourceIndex, SourceCount: TIndex); virtual;
     76    procedure ReplaceBuffer(const Index: TIndex; var Buffer; ACount: TIndex);
    6477    function Remove(const Item: TItem): TIndex;
    6578    procedure Reverse;
     
    7083    property First: TItem read GetFirst write SetFirst;
    7184    property Last: TItem read GetLast write SetLast;
     85    property OnUpdate: TNotifyEvent read FOnUpdate write FOnUpdate;
    7286  end;
    7387
     
    8094  protected
    8195    function Get(Index: TIndex): TItem; override;
     96    function GetInternal(Index: TIndex): TItem; override;
    8297    function GetCapacity: TIndex;
    8398    function GetCount: TIndex; override;
     
    86101    procedure SetCount(const AValue: TIndex); override;
    87102    procedure Put(Index: TIndex; const AValue: TItem); override;
     103    procedure PutInternal(Index: TIndex; const AValue: TItem); override;
    88104  public
    89105    procedure Fill(Start, Count: TIndex; Value: TItem); override;
     
    95111  end;
    96112
     113  { TGObjectList }
     114
    97115  TGObjectList<TItem> = class(TGList<TItem>)
    98116  protected
     
    100118  public
    101119    OwnsObjects: Boolean;
     120    procedure SetCount(const AValue: TIndex); override;
     121    function AddNew(NewObject: TItem = nil): TItem;
    102122    procedure Delete(const Index: Integer); override;
    103123    procedure Clear; override;
     
    110130  private
    111131  public
    112     procedure Delete(Index: Integer); override;
     132    procedure Delete(const Index: Integer); override;
    113133    procedure Clear; override;
    114134    procedure Assign(Source: TGAbstractList<TItem>); override;
     
    136156  end;
    137157
     158  { TListByte }
     159
     160  TListByte = class(TGList<Byte>)
     161    procedure WriteToStream(Stream: TStream);
     162    procedure WriteToStreamPart(Stream: TStream; ItemIndex, ItemCount: TIndex);
     163    procedure ReplaceStream(Stream: TStream);
     164    procedure ReplaceStreamPart(Stream: TStream; ItemIndex, ItemCount: TIndex);
     165    procedure AddStream(Stream: TStream);
     166    procedure AddStreamPart(Stream: TStream; ItemCount: TIndex);
     167    procedure WriteBuffer(var Buffer; Count: Integer);
     168    procedure ReadBuffer(var Buffer; Count: Integer);
     169  end;
     170  TListInteger = TGList<Integer>;
     171  TListString = TGStringList<string>;
     172  TListObject = TGObjectList<TObject>;
     173
     174  { TListNotifyEvent }
     175
     176  TListNotifyEvent = class(TGList<TNotifyEvent>)
     177    procedure CallAll(Sender: TObject);
     178  end;
     179  TBaseEvent = procedure of object;
     180
     181  { TListSimpleEvent }
     182
     183  TListSimpleEvent = class(TGList<TBaseEvent>)
     184    procedure CallAll;
     185  end;
     186  TListBoolean = TGList<Boolean>;
     187  TListDouble = TGList<Double>;
     188
     189function StrToStr(Value: string): string;
     190
     191
    138192
    139193resourcestring
     
    145199
    146200{ TGList<TItem> }
     201
     202function TGList<TItem>.Get(Index: TIndex): TItem;
     203begin
     204  if (Index < 0) or (Index >= Count) then
     205    raise EListError.CreateFmt(SListIndexError, [Index]);
     206  Result := ItemsInternal[Index];
     207end;
     208
     209function TGList<TItem>.GetInternal(Index: TIndex): TItem;
     210begin
     211  Result := FItems[Index];
     212end;
    147213
    148214function TGList<TItem>.GetCapacity: TIndex;
     
    182248end;
    183249
    184 function TGList<TItem>.Get(Index: TIndex): TItem;
     250procedure TGList<TItem>.Put(Index: TIndex; const AValue: TItem);
    185251begin
    186252  if (Index < 0) or (Index >= Count) then
    187253    raise EListError.CreateFmt(SListIndexError, [Index]);
    188   Result := FItems[Index];
    189 end;
    190 
    191 procedure TGList<TItem>.Put(Index: TIndex; const AValue: TItem);
    192 begin
    193   if (Index < 0) or (Index >= Count) then
    194     raise EListError.CreateFmt(SListIndexError, [Index]);
     254  ItemsInternal[Index] := AValue;
     255end;
     256
     257procedure TGList<TItem>.PutInternal(Index: TIndex; const AValue: TItem);
     258begin
    195259  FItems[Index] := AValue;
    196260end;
     
    214278  );
    215279begin
    216   if Source is TGList<TItem> then begin
    217     System.Move(TGList<TItem>(Source).FItems[0], FItems[Index], Source.Count * SizeOf(TItem));
     280  if (Source.Count > 0) and (Source is TGList<TItem>) then begin
     281    System.Move(PByte(TGList<TItem>(Source).FItems)^, FItems[Index], Source.Count * SizeOf(TItem));
    218282  end else inherited;
    219283end;
     
    224288    raise EListError.CreateFmt(SListCountError, [AValue]);
    225289  if AValue > Capacity then SetCapacityOptimized(AValue); // Before FCount change
     290
     291  if AValue > FCount then // Clear allocated space
     292    FillChar(FItems[FCount], (AValue - FCount) * SizeOf(TItem), 0);
    226293  FCount := AValue;
    227294  if AValue < Capacity then SetCapacityOptimized(AValue); // After FCount change
     
    230297function TGList<TItem>.CompareItem(const Item1, Item2: TItem): Boolean;
    231298begin
    232   Result := CompareMem(Addr(Item1), Addr(Item2), SizeOf(TItem));
     299  Result := CompareByte(Item1, Item2, SizeOf(TItem)) = 0;
    233300end;
    234301
     
    240307procedure TGList<TItem>.CopyItems(CurIndex, NewIndex, ACount: TIndex);
    241308begin
    242   System.Move(FItems[CurIndex], FItems[NewIndex], ACount * SizeOf(TItem));
     309  if ACount > 0 then
     310    System.Move(FItems[CurIndex], FItems[NewIndex], ACount * SizeOf(TItem));
    243311end;
    244312
     
    254322procedure TGObjectList<TItem>.Put(Index: Integer; const AValue: TItem);
    255323begin
    256   if OwnsObjects then FItems[Index].Free;
     324  if OwnsObjects and Assigned(FItems[Index]) then FItems[Index].Free;
    257325  inherited Put(Index, AValue);
    258326end;
    259327
     328procedure TGObjectList<TItem>.SetCount(const AValue: TIndex);
     329begin
     330  if AValue < FCount then
     331    Fill(AValue, FCount - AValue, nil);
     332  inherited SetCount(AValue);
     333end;
     334
     335function TGObjectList<TItem>.AddNew(NewObject: TItem): TItem;
     336begin
     337  if Assigned(NewObject) then Result := NewObject
     338    else Result := TItem.Create;
     339  Add(Result);
     340end;
     341
    260342procedure TGObjectList<TItem>.Delete(const Index: Integer);
    261343begin
    262   if OwnsObjects then FItems[Index].Free;
     344  (*if OwnsObjects then begin
     345    FItems[Index].Free;
     346    FItems[Index] := nil;
     347  end;*)
    263348  inherited Delete(Index);
    264349end;
    265350
    266351procedure TGObjectList<TItem>.Clear;
    267 var
    268   I: Integer;
    269 begin
    270   if OwnsObjects then begin
    271     I := 0;
    272     while I < Count do begin
    273       FItems[I].Free;
    274       I := I + 1;
    275     end;
    276   end;
     352begin
     353  Fill(0, Count, nil);
    277354  inherited Clear;
    278355end;
     
    287364begin
    288365  Clear;
    289   inherited Destroy;
     366  inherited;
    290367end;
    291368
     
    298375end;
    299376
    300 procedure TGStringList<TItem>.Delete(Index: Integer);
     377procedure TGStringList<TItem>.Delete(const Index: Integer);
    301378begin
    302379  FItems[Index] := '';
     
    366443  P, Q: TItem;
    367444begin
    368  repeat
    369    I := L;
    370    J := R;
    371    P := Items[(L + R) div 2];
    372    repeat
    373      while Compare(P, Items[I]) > 0 do
    374        I := I + 1;
    375      while Compare(P, Items[J]) < 0 do
    376        J := J - 1;
    377      if I <= J then
    378      begin
    379        Q := Items[I];
    380        Items[I] := Items[J];
    381        Items[J] := Q;
    382        I := I + 1;
    383        J := J - 1;
    384      end;
    385    until I > J;
    386    if L < J then
    387      QuickSort(L, J, Compare);
    388    L := I;
     445  repeat
     446    I := L;
     447    J := R;
     448    P := ItemsInternal[(L + R) div 2];
     449    repeat
     450      while Compare(P, ItemsInternal[I]) > 0 do
     451        I := I + 1;
     452      while Compare(P, ItemsInternal[J]) < 0 do
     453        J := J - 1;
     454      if I <= J then
     455      begin
     456        Q := ItemsInternal[I];
     457        ItemsInternal[I] := ItemsInternal[J];
     458        ItemsInternal[J] := Q;
     459        I := I + 1;
     460        J := J - 1;
     461      end;
     462    until I > J;
     463    if L < J then
     464      QuickSort(L, J, Compare);
     465    L := I;
    389466  until I >= R;
    390467end;
     
    406483procedure TGAbstractList<TItem>.DeleteItems(const Index, ACount: TIndex);
    407484begin
    408   if (Index < 0) or (Index >= (Count - ACount)) then
     485  if (Index < 0) or (Index >= Count) then
    409486    raise EListError.CreateFmt(SListIndexError, [Index]);
    410   CopyItems(Index + ACount, Index, Count - Index - ACount);
     487  MoveItems(Index + ACount, Index, Count - Index - ACount);
    411488  //SetCapacityOptimized(Capacity - ACount);
     489
    412490  Count := Count - ACount;
    413491end;
     
    438516  if ((Index2 >= Count) or (Index2 < 0)) then
    439517    raise EListError.CreateFmt(SListIndexError, [Index2]);
    440   Temp := Items[Index1];
    441   Items[Index1] := Items[Index2];
    442   Items[Index2] := Temp;
     518  Temp := ItemsInternal[Index1];
     519  ItemsInternal[Index1] := ItemsInternal[Index2];
     520  ItemsInternal[Index2] := Temp;
    443521end;
    444522
     
    467545end;
    468546
    469 procedure TGAbstractList<TItem>.Fill(Start, Count: TIndex; Value: TItem);
     547procedure TGAbstractList<TItem>.Fill(Start, ACount: TIndex; Value: TItem);
    470548var
    471549  I: TIndex;
    472550begin
    473551  I := Start;
    474   while I < Count do begin
     552  while I < (Start + ACount) do begin
    475553    Items[I] := Value;
    476554    I := I + 1;
     
    494572  List.Clear;
    495573  List.AddListPart(Self, Index, ACount);
     574end;
     575
     576procedure TGAbstractList<TItem>.GetBuffer(Index: TIndex; var Buffer;
     577  ACount: TIndex);
     578var
     579  P: PItem;
     580  I: TIndex;
     581begin
     582  if (Index + ACount) > Count then
     583    raise EListError.CreateFmt(SListIndexError, [Index + ACount]);
     584  P := PItem(@Buffer);
     585  I := 0;
     586  while I < ACount do begin
     587    P^ := Items[Index + I];
     588    Inc(P, 1);
     589    I := I + 1;
     590  end;
    496591end;
    497592
     
    529624    raise EListError.CreateFmt(SListIndexError, [Index]);
    530625  InsertCount(Index, 1);
    531   Items[Index] := Item;
     626  ItemsInternal[Index] := Item;
    532627end;
    533628
     
    579674    I := 0;
    580675    while I < ACount do begin
    581       Items[NewIndex] := Items[CurIndex];
     676      ItemsInternal[NewIndex] := ItemsInternal[CurIndex];
    582677      CurIndex := CurIndex + 1;
    583678      NewIndex := NewIndex + 1;
     
    589684    CurIndex := CurIndex + ACount - 1;
    590685    while I >= 0 do begin
    591       Items[NewIndex] := Items[CurIndex];
     686      ItemsInternal[NewIndex] := ItemsInternal[CurIndex];
    592687      NewIndex := NewIndex - 1;
    593688      CurIndex := CurIndex - 1;
     
    605700  ACount: TIndex);
    606701var
    607   I: Integer;
     702//  I: Integer;
    608703  Temp: TGList<TItem>;
    609704begin
     705  if (ACount > 0) and (NewIndex <> CurIndex) then
    610706  try
    611707    Temp := TGList<TItem>.Create;
    612     Temp.AddListPart(Self, NewIndex, ACount);
    613     CopyItems(CurIndex, NewIndex, ACount);
    614     ReplaceList(CurIndex, Temp);
     708    if NewIndex > CurIndex then begin
     709      Temp.AddListPart(Self, CurIndex, ACount);
     710      CopyItems(CurIndex + ACount, CurIndex, NewIndex - CurIndex);
     711      ReplaceList(NewIndex, Temp);
     712    end else
     713    if NewIndex < CurIndex then begin
     714      Temp.AddListPart(Self, CurIndex, ACount);
     715      CopyItems(NewIndex, NewIndex + ACount, CurIndex - NewIndex);
     716      ReplaceList(NewIndex, Temp);
     717    end;
    615718  finally
    616719    Temp.Free;
     
    650753  while I < SourceCount do begin
    651754    Items[Index + I] := Source[SourceIndex + I];
     755    I := I + 1;
     756  end;
     757end;
     758
     759procedure TGAbstractList<TItem>.ReplaceBuffer(const Index: TIndex; var Buffer;
     760  ACount: TIndex);
     761var
     762  P: PItem;
     763  I: TIndex;
     764begin
     765  if (Index + ACount) > Count then
     766    raise EListError.CreateFmt(SListIndexError, [Index + ACount]);
     767  P := PItem(@Buffer);
     768  I := 0;
     769  while I < ACount do begin
     770    Items[Index + I] := P^;
     771    Inc(P, 1);
    652772    I := I + 1;
    653773  end;
     
    694814  Count := Count + 1;
    695815  Result := Count - 1;
    696   Items[Result] := Item;
     816  ItemsInternal[Result] := Item;
    697817end;
    698818
     
    724844begin
    725845  Count := Source.Count;
    726   ReplaceList(0, Source);
     846  if Count > 0 then ReplaceList(0, Source);
     847end;
     848
     849procedure TGAbstractList<TItem>.BeginUpdate;
     850begin
     851  Inc(FUpdateCount);
     852end;
     853
     854procedure TGAbstractList<TItem>.EndUpdate;
     855begin
     856  Dec(FUpdateCount);
     857  Update;
     858end;
     859
     860procedure TGAbstractList<TItem>.Update;
     861begin
     862  if Assigned(FOnUpdate) and (FUpdateCount = 0) then FOnUpdate(Self);
    727863end;
    728864
     
    788924end;
    789925
     926function StrToStr(Value: string): string;
     927begin
     928  Result := Value;
     929end;
     930
     931{ TListSimpleEvent }
     932
     933procedure TListSimpleEvent.CallAll;
     934var
     935  I: TIndex;
     936begin
     937  I := 0;
     938  while (I < Count) do begin
     939    Items[I]();
     940    I := I + 1;
     941  end;
     942end;
     943
     944{ TListNotifyEvent }
     945
     946procedure TListNotifyEvent.CallAll(Sender: TObject);
     947var
     948  I: TIndex;
     949begin
     950  I := 0;
     951  while (I < Count) do begin
     952    Items[I](Sender);
     953    I := I + 1;
     954  end;
     955end;
     956
     957{ TListByte }
     958
     959procedure TListByte.WriteToStream(Stream: TStream);
     960var
     961  I: Integer;
     962begin
     963  Stream.Position := 0;
     964  I := 0;
     965  while I < Count do begin
     966    Stream.WriteByte(Items[I]);
     967    I := I + 1;
     968  end;
     969end;
     970
     971procedure TListByte.WriteToStreamPart(Stream: TStream; ItemIndex, ItemCount: TIndex);
     972var
     973  I: Integer;
     974begin
     975  I := ItemIndex;
     976  while I < ItemCount do begin
     977    Stream.WriteByte(Items[I]);
     978    I := I + 1;
     979  end;
     980end;
     981
     982procedure TListByte.ReplaceStream(Stream: TStream);
     983var
     984  I: Integer;
     985begin
     986  Stream.Position := 0;
     987  I := 0;
     988  while I < Count do begin
     989    Items[I] := Stream.ReadByte;
     990    I := I + 1;
     991  end;
     992end;
     993
     994procedure TListByte.ReplaceStreamPart(Stream: TStream; ItemIndex,
     995  ItemCount: TIndex);
     996var
     997  I: Integer;
     998begin
     999  I := ItemIndex;
     1000  while I < ItemCount do begin
     1001    Items[I] := Stream.ReadByte;
     1002    I := I + 1;
     1003  end;
     1004end;
     1005
     1006procedure TListByte.AddStream(Stream: TStream);
     1007var
     1008  I: Integer;
     1009begin
     1010  Stream.Position := 0;
     1011  I := Count;
     1012  Count := Count + Stream.Size;
     1013  while I < Count do begin
     1014    Items[I] := Stream.ReadByte;
     1015    I := I + 1;
     1016  end;
     1017end;
     1018
     1019procedure TListByte.AddStreamPart(Stream: TStream; ItemCount: TIndex);
     1020var
     1021  I: Integer;
     1022begin
     1023  I := Count;
     1024  Count := Count + ItemCount;
     1025  while I < Count do begin
     1026    Items[I] := Stream.ReadByte;
     1027    I := I + 1;
     1028  end;
     1029end;
     1030
     1031procedure TListByte.WriteBuffer(var Buffer; Count: Integer);
     1032begin
     1033
     1034end;
     1035
     1036procedure TListByte.ReadBuffer(var Buffer; Count: Integer);
     1037begin
     1038
     1039end;
     1040
    7901041end.
Note: See TracChangeset for help on using the changeset viewer.