PointerList (arrays on-the-fly)
Posted: Sun Sep 03, 2006 9:22 pm
I made this code to get some of the functionality of Delphi's TList.
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.
Example:
You can create, delete and modify PointerLists on-the-fly. This allows for linked lists, arrays or even linked trees or PointerLists of PointerLists.TList stores an array of pointers.
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