Page 1 of 1

PointerList (arrays on-the-fly)

Posted: Sun Sep 03, 2006 9:22 pm
by Trond
I made this code to get some of the functionality of Delphi's TList.
TList stores an array of pointers.
You can create, delete and modify PointerLists on-the-fly. This allows for linked lists, arrays or even linked trees or PointerLists of PointerLists.

It is currently not tested much (doesn't mean it doesn't work), but it's too late now, I'll test it tomorrow and also give a better example.

Code: Select all

; WARNINGS:
; Destroying a list of pointers does not free the memory that
; the pointers are pointing to.

#PL_AllocSize = 64 ; Higher number means more speed and more memory

Global Dim PL_Array(0)

Procedure Max(A, B)
  If A > B
    ProcedureReturn A
  EndIf
  ProcedureReturn B
EndProcedure

Structure SPointerList
  ; All values are read-only unless you know what you're doing
  Array.l       ; The actual array
  Allocated.l   ; For internal use only
  StructureUnion
    Used.l      ; For internal use only
    Length.l    ; The highest index currently in use (in the array).
                ; To add an item add it at index Length+1 and Length
                ; will automagically increase by 1. Read-only!
  EndStructureUnion
EndStructure

; Create a new list of pointers.
Procedure PointerList()
  Dim Array(4)
  *List.SPointerList = AllocateMemory(SizeOf(SPointerList))
  *List\Array = @Array()
  *List\Allocated = 4
  *List\Used = 0
  Array() = 0
  ProcedureReturn *List
EndProcedure

; For internal use, or you can use it to destroy an array of
; long values.
Procedure DestroyArrayOfLong(PointerToArray.l)
  If 0
    Dim Array(0)
  EndIf
  Array() = PointerToArray
EndProcedure

; Destroy a list. Destroying a list does not free the memory
; pointed to by the pointers in the list.
Procedure PL_Destroy(*List.SPointerList)
  DestroyArrayOfLong(*List\Array)
  FreeMemory(*List)
EndProcedure

; Pre-size the list before you add a large number
; of items to it to increase speed. This is only
; necessary when you need extra speed.
; You can also use this so shorten a list.
Procedure PL_Size(*List.SPointerList, MaxIndex)
  PL_Array() = *List\Array
  ReDim PL_Array(MaxIndex)
  *List\Allocated = MaxIndex
  If *List\Used > *List\Allocated
    *List\Used = *List\Allocated
  EndIf
EndProcedure

; Set the value of an item in the list. Index is the
; position. You can use any position you want, memory
; for it is automatically allocated. Be careful with
; using large indexes as memory for all the indexes
; below it will also be reserved.
Procedure PL_Set(*List.SPointerList, Index, Value)
  Protected Size
  PL_Array() = *List\Array
  While Index > *List\Allocated
    Size = *List\Allocated + #PL_AllocSize
    ReDim PL_Array(Size)
    *List\Array = PL_Array()
    *List\Allocated = Size
  Wend
  *List\Used = Max(*List\Used, Index+1)
  DisableDebugger
    PL_Array(Index) = Value
  EnableDebugger
EndProcedure

; Get the value of an item in the list. Index is the
; position.
Procedure.l PL_Get(*List.SPointerList, Index)
  PL_Array() = *List\Array
  CompilerIf #PB_Compiler_Debugger
    If Index > *List\Used
      ; Do not remove, catches more errors than PB's built-in
      ; array check.
      Debug "OUT OF BOUNDS:"
      Debug Index
      Debug *List\Used
      CallDebugger ; ARRAY INDEX OUT OF BOUNDS
    EndIf
  CompilerEndIf
  DisableDebugger
  ProcedureReturn PL_Array(Index)
  EnableDebugger
EndProcedure

Example:

Code: Select all

XIncludeFile "pointer_list.pb"

*List.SPointerList = PointerList()

PL_Set(*List, 3, 333)
Debug PL_Get(*List, 3)

PL_Set(*List, 4, 1234)
Debug PL_Get(*List, 3)

PL_Set(*List, 77, 456)
Debug PL_Get(*List, 3)
Debug PL_Get(*List, 77)

Debug *List\Length

Posted: Wed Sep 06, 2006 2:29 pm
by kinglestat
looks nice
but
what exactly does it do ?

excuse my ignorance
cheers

Terence

Posted: Wed Sep 06, 2006 2:45 pm
by Trond
kinglestat wrote:looks nice
but
what exactly does it do ?

excuse my ignorance
cheers

Terence
It is simply a dynamically created and dynamically sized array of longs. Unlike normal arrays you can "juggle them around". Like creating a tree structure of arrays. ( http://en.wikipedia.org/wiki/Image:Bina ... ucture.png )

And let's say you wanted to make an Object Pascal compiler (think of it as PB with classes) then you would have to keep track of the variables, functions and classes. Then you have some problems with normal arrays:
- You don't want a set limit on the number of variables.
- Variables inside a function can have the same name as a global variable
- Variables inside a class (members) can have the same name as a global variable or a variable inside a function inside or outside the class.
- Functions inside a class can have the same name as a function outside the class.
- Variables inside functions inside classes can have the same names as variables inside classes, global variables or variables inside functions inside or outside classes.
In short, there's lot of naming conflicts. These are most naturally resolved by organizing the items in a tree structure. So that each class has its own PointerList of pointers to functions. And each function has its own PointerList of pointers to local variables.

Posted: Sat Sep 09, 2006 11:54 am
by kinglestat
I got it
cheers

I did something far more basic to handle strings stored inside structures....but a far cry from your code

Terence