Forum > General

TFPList

(1/2) > >>

Pasqualish:
I am looking at the code defined in ../rtl/objpas/classes/classesh.inc  for an TFPList class, in the situation when FPC_TESTGENERICS is false.  I don't understand how it works as it has a private member - FList: PPointerList - which is a pointer to a static array - array[0..MaxListSize - 1] of Pointer;   However, there is no constructor for this class. I don't see how FList gets a valid value or what it points to would be created.


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---TypePPointerList = ^TPointerList;TPointerList = array[0..MaxListSize - 1] of Pointer; TFPList = class(TObject)  private    FList: PPointerList;    FCount: Integer;    FCapacity: Integer;    procedure CopyMove (aList : TFPList);    procedure MergeMove (aList : TFPList);    procedure DoCopy(ListA, ListB : TFPList);    procedure DoSrcUnique(ListA, ListB : TFPList);    procedure DoAnd(ListA, ListB : TFPList);    procedure DoDestUnique(ListA, ListB : TFPList);    procedure DoOr(ListA, ListB : TFPList);    procedure DoXOr(ListA, ListB : TFPList);  protected    function Get(Index: Integer): Pointer; {$ifdef CLASSESINLINE} inline; {$endif CLASSESINLINE}    procedure Put(Index: Integer; Item: Pointer); {$ifdef CLASSESINLINE} inline; {$endif CLASSESINLINE}    procedure SetCapacity(NewCapacity: Integer);    procedure SetCount(NewCount: Integer);    Procedure RaiseIndexError(Index: Integer);  public    Type      TDirection = (FromBeginning, FromEnd);    destructor Destroy; override;    Procedure AddList(AList : TFPList);    function Add(Item: Pointer): Integer; {$ifdef CLASSESINLINE} inline; {$endif CLASSESINLINE}    procedure Clear;    procedure Delete(Index: Integer); {$ifdef CLASSESINLINE} inline; {$endif CLASSESINLINE}    class procedure Error(const Msg: string; Data: PtrInt);    procedure Exchange(Index1, Index2: Integer);    function Expand: TFPList; {$ifdef CLASSESINLINE} inline; {$endif CLASSESINLINE}    function Extract(Item: Pointer): Pointer;    function First: Pointer;    function GetEnumerator: TFPListEnumerator;    function IndexOf(Item: Pointer): Integer;    function IndexOfItem(Item: Pointer; Direction: TDirection): Integer;    procedure Insert(Index: Integer; Item: Pointer); {$ifdef CLASSESINLINE} inline; {$endif CLASSESINLINE}    function Last: Pointer;    procedure Move(CurIndex, NewIndex: Integer);    procedure Assign (ListA: TFPList; AOperator: TListAssignOp=laCopy; ListB: TFPList=nil);    function Remove(Item: Pointer): Integer;    procedure Pack;    procedure Sort(Compare: TListSortCompare);    procedure ForEachCall(proc2call:TListCallback;arg:pointer);    procedure ForEachCall(proc2call:TListStaticCallback;arg:pointer);    property Capacity: Integer read FCapacity write SetCapacity;    property Count: Integer read FCount write SetCount;    property Items[Index: Integer]: Pointer read Get write Put; default;    property List: PPointerList read FList;  end;

Thaddy:
The constructor is the default constructor for TObject which will initialize the structure.
Ultimately the ppointerlist is expanded on demand through ultimately setcapacity.
The capacity is checked and expanded/initialized when you add an Item to the list.
Hence the code is always valid.

Pasqualish:
Thanks! 

I don't understand why the pointer type is defined to point to a static array as it doesn't appear that there is any limitation with regard to going past a static array bound. Although it does indirectly show what the allocation/re-allocation checks for as far as a size limit before raising an exception, so maybe it is for documentation.


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---{$R+} type   SomeArrayType  = array [0 .. 1000] of Pointer;   PSomeArrayType = ^SomeArrayType;                                 var   myPointer : PSomeArrayType;   i : Cardinal;begin   New(myPointer);   for i := 0 to 2000 do      Inc(myPointer);   WriteLn('program ended normally');end.
outputs:

--- Quote ---program ended normally
--- End quote ---

Thaddy:
There are TWO big limitations: memory and stackspace.
If you would allocate a full array as TArray you either run out of memory or you blow up the stack. That's why they are PArray's or even PPArrays. The full size never gets used because you will probably run out of memory or blow up the stack long before hand. If you look in the implementation in Lists.inc you see what I mean.
This is normal and prudent programming procedure and this is also how it works in e.g. C and C++.
--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---procedure BlowStack;var  Arr:array[0.maxint-1] of pointer;begin  Result :=0;end; type  TMaxArray = array[0..maxint-1] of pointer;  PMaxArray = ^TMaxArray;procedure DontBlowStack;var  arr: PMaxArray;begin  result := 0;end; 

Thaddy:

--- Quote ---it doesn't appear that there is any limitation with regard to going past a static array bound
--- End quote ---
Of course there is: Its called Range checking and Stack checking. What you want can only work if range checks are off and inside a method when stack checking is also off.
But this is an often used programming technique (good or bad!)

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---{$RANGECHECKS OFF} TMyArray = array[0..0] of integer;// works only with range checks off in any meaningful wayPMyArray = ^TMyArray;// Now try any index other than 0 with {$R+} or {$RANGECHECKS ON}http://www.freepascal.org/docs-html/current/prog/progsu65.html#x72-710001.2.65
http://www.freepascal.org/docs-html/current/prog/progsu115.html#x123-1240001.3.32

Navigation

[0] Message Index

[#] Next page

Go to full version