- Joined
- Sep 26, 2009
- Messages
- 9,534
StaticList v3.0.0.0
Combining Jesus4Lyf's linked-list method with Vexorian's struct-index technique brings this convention for use with structs. Implement StaticListStruct at the top of an array struct or StaticListModule at the top of any struct to acquire some very useful methods.
Often struct instances share some common ground, such as a projectile-movement system. That common ground often involves somehow linking all instances together using a Stack. Stacks are useful because they allow you to loop through all struct instances and do something for them. This library is designed to make looping through a Stack as quick and painless as possible, using a linked-list approach.
You can loop through a stack starting at the "head" struct, which is 0, then meandering through all structs until you reach the end (0 again). This is fast because it involves a quick "set this = this.next" instead of incrementing through a single array of structs with an "i" variable and a "thistype" array, and is very intuitive and user-friendly to work with.
So, when starting the loop, you start at the head (0), get its next instance, the instance of its next instance, the instance of its next instance's next instance, and so forth, until you reach 0. So a simple
Instead of using the standard allocate/deallocate hidden methods in a struct, make your struct into an array struct
In case you already have a list of indexes, such as if you are using UnitIndexer or just a regular struct, you can still get the benefits of this system by implementing StaticListModule, which adds/removes to the linked list via this.linkNode() and this.unlinkNode(), respectively.
Combining Jesus4Lyf's linked-list method with Vexorian's struct-index technique brings this convention for use with structs. Implement StaticListStruct at the top of an array struct or StaticListModule at the top of any struct to acquire some very useful methods.
Code:
API in both modules:
thistype.head -> thistype; returns the first node in the list (0)
this.prev -> thistype
this.next -> thistype
API in StaticListStruct only:
thistype.allocate() -> thistype
this.deallocate()
API in StaticListModule only:
this.linkNode()
this.unlinkNode()
Often struct instances share some common ground, such as a projectile-movement system. That common ground often involves somehow linking all instances together using a Stack. Stacks are useful because they allow you to loop through all struct instances and do something for them. This library is designed to make looping through a Stack as quick and painless as possible, using a linked-list approach.
You can loop through a stack starting at the "head" struct, which is 0, then meandering through all structs until you reach the end (0 again). This is fast because it involves a quick "set this = this.next" instead of incrementing through a single array of structs with an "i" variable and a "thistype" array, and is very intuitive and user-friendly to work with.
So, when starting the loop, you start at the head (0), get its next instance, the instance of its next instance, the instance of its next instance's next instance, and so forth, until you reach 0. So a simple
exitwhen this == 0
should be placed at the top of the loop, and the loop actions below that statement, and the set this = this.next
statement should be found in there somewhere.Instead of using the standard allocate/deallocate hidden methods in a struct, make your struct into an array struct
struct Name extends array
and implement StaticListStruct. It imports a new set of allocate/deallocate methods that do everything the old ones do, but automatically adds each instance to the linked-list, making your life much easier.In case you already have a list of indexes, such as if you are using UnitIndexer or just a regular struct, you can still get the benefits of this system by implementing StaticListModule, which adds/removes to the linked list via this.linkNode() and this.unlinkNode(), respectively.
JASS:
library StaticList
// Generates indexes and automatically adds them to the list.
module StaticListStruct
private static integer s_ze = 0
private static integer l_st = 0
private thistype pr_v
private thistype n_xt
static method operator head takes nothing returns thistype
return 0
endmethod
method operator next takes nothing returns thistype
return this.n_xt
endmethod
method operator prev takes nothing returns thistype
return this.pr_v
endmethod
static method allocate takes nothing returns thistype
local thistype this
if (l_st == 0) then
set this = s_ze + 1
debug if (integer(this) > 8190) then
debug call BJDebugMsg("StaticList Error: Cannot allocate past 8190!")
debug return 0
debug endif
set s_ze = this
else
set this = l_st
set l_st = this.pr_v
endif
set head.n_xt.pr_v = this
set this.n_xt = head.n_xt
set head.n_xt = this
set this.pr_v = head
return this
endmethod
method deallocate takes nothing returns nothing
static if (DEBUG_MODE) then
if (integer(this) < 1 or integer(this) > 8190) then
call BJDebugMsg("StaticList Error: Attempt to destroy an invalid instance: " + I2S(this))
return
elseif (this.n_xt == head and head.pr_v != this) then
call BJDebugMsg("StaticList Error: Attempt to destroy an alread-destroyed instance: " + I2S(this))
return
endif
set this.n_xt = 0
endif
set this.pr_v.n_xt = this.n_xt
set this.n_xt.pr_v = this.pr_v
set this.pr_v = l_st
set l_st = this
endmethod
endmodule
// When you already have the indexes (eg. with a Unit Indexer)
module StaticListModule
private thistype pr_v
private thistype n_xt
static method operator head takes nothing returns thistype
return 0
endmethod
method operator next takes nothing returns thistype
return this.n_xt
endmethod
method operator prev takes nothing returns thistype
return this.pr_v
endmethod
method linkNode takes nothing returns nothing
static if (DEBUG_MODE) then
if (integer(this) < 1 or integer(this) > 8190) then
call BJDebugMsg("StaticList Error: Attempt to link an invalid instance: " + I2S(this))
return
elseif (this.n_xt != head or head.pr_v == this) then
call BJDebugMsg("StaticList Error: Attempt to link an already-linked instance: " + I2S(this))
return
endif
endif
set head.n_xt.pr_v = this
set this.n_xt = head.n_xt
set head.n_xt = this
set this.pr_v = head
endmethod
method unlinkNode takes nothing returns nothing
static if (DEBUG_MODE) then
if (integer(this) < 1 or integer(this) > 8190) then
call BJDebugMsg("StaticList Error: Attempt to unlink an invalid instance: " + I2S(this))
return
elseif (this.n_xt == head and head.pr_v != this) then
call BJDebugMsg("StaticList Error: Attempt to unlink an already-unlinked instance: " + I2S(this))
return
endif
set this.n_xt = 0
endif
set this.pr_v.n_xt = this.n_xt
set this.n_xt.pr_v = this.pr_v
endmethod
endmodule
endlibrary
JASS:
struct Example extends array // Uses StaticList
implement StaticListStruct
static method create takes nothing returns thistype
return thistype.allocate()
endmethod
method destroy takes nothing returns nothing
call this.deallocate()
endmethod
static method loopAll takes nothing returns nothing
local thistype this = head.next
loop
exitwhen (this == head)
call BJDebugMsg(I2S(this))
set this = this.next
endloop
endmethod
endstruct
struct OtherExample extends array // Uses UnitIndexer and StaticList
implement StaticListModule
method index takes nothing returns nothing
call this.linkNode()
endmethod
method deindex takes nothing returns nothing
call this.unlinkNode()
endmethod
implement UnitIndexStruct
static method loopAll takes nothing returns nothing
local thistype this = head.next
loop
exitwhen (this == head)
call BJDebugMsg(GetUnitName(this.unit))
set this = this.next
endloop
endmethod
endstruct
Last edited: