- Joined
- Jul 10, 2007
- Messages
- 6,306
A tutorial for understanding the QueueQueue
Textmacro Demo
Module Demo
Data
Looped over forwards
Looped over backwards
JASS:
library QueueQueue /* v2.2.6.5
*******************************************************************
*
* To best understand this data structure, think of a list and then
* imagine that every node on that list can have a list inside of it
* and so on. It's also pretty much a tree.
*
*******************************************************************
*
* API
*
*******************************************************************
*
* module QueueQueue
* readonly thistype parent
* readonly boolean pointer
* boolean skips
*
* static method allocate takes nothing returns thistype
* method deallocate takes nothing returns nothing
*
* method add takes nothing returns thistype
* method point takes integer head returns thistype
* method operator next takes nothing returns thistype
* method operator in takes nothing returns thistype
*
* Loop macros
* //! textmacro QUEUE_QUEUE_HEADER takes STRUCT
* //! textmacro QUEUE_QUEUE_START_LOOP takes THIS
* //! textmacro QUEUE_QUEUE_END_LOOP
* //! textmacro QUEUE_QUEUE_HEADER_B takes STRUCT
* //! textmacro QUEUE_QUEUE_START_LOOP_B takes THIS
* //! textmacro QUEUE_QUEUE_END_LOOP_B
*
* module QueueQueueLoop
* readonly thistype get
* readonly thistype skip
* readonly thistype depthPointer
* readonly thistype depthNode
* integer id
* method start takes nothing returns thistype
* method end takes nothing returns nothing
*
*******************************************************************
*
* module QueueQueue
*
*******************************************************************
*
* readonly thistype next
* - Next node
* readonly thistype in
* - Inner node (any given node can have nodes inside of it)
* readonly thistype parent
* - The node that the node is contained inside of.
* readonly boolean pointer
* - This determines whether the node is a pointer or not. Pointers are
* - the first node on the QueueQueue (a special pointer called a head, only
* - generated with allocate) and nodes made through the point method. Pointers
* - are automatically skipped, however their skip option can be set with the
* - skips property.
* boolean skips
* - This determines whether or not to skip a pointer. Pointers that are skipped
* - are not looped over in loops. This is useful for systems that want to read
* - values inside of pointers to see if a pointer's contents should be skipped
* - over or not.
*
* static method allocate takes nothing returns thistype
* - Returns the head for the entire object.
* method deallocate takes nothing returns nothing
* - Destroys the entire structure given the head
*
* method add takes nothing returns thistype
* - Adds a cell to the cell. Cells generated in this fashion
* - are entirely local to the QueueQueue they were added to, meaninng
* - that they can't be pointed to.
* method point takes integer head returns thistype
* - Points a node to a head. Any node allocated with the allocate
* - method is a head. Pointers can't point to anything other than the head.
*
********************************************************************
*
* Loop macros
*
* A loop macro used for looping through a QueueQueue.
*
*******************************************************************
*
* Regular loop (looped in right order)
* //! textmacro QUEUE_QUEUE_HEADER takes STRUCT
* - Place at top of the method/function.
* -
* - STRUCT: Refers to the struct type to loop for.
* //! textmacro QUEUE_QUEUE_START_LOOP takes THIS
* - Place where the loop should start
* -
* - THIS: Refers to where to start the loop from and also
* - used to store current node inside of for reading.
* - THIS must be a variable, and it is not recommended
* - that the this variable be used.
* //! textmacro QUEUE_QUEUE_END_LOOP
* - Place where the loop should end
*
* Deep first postorder loop macros (inner before outer, backwards)
* //! textmacro QUEUE_QUEUE_HEADER_B takes STRUCT
* //! textmacro QUEUE_QUEUE_START_LOOP_B takes THIS
* //! textmacro QUEUE_QUEUE_END_LOOP_B
*
* ---------------------------------------------------------------------
* -
* - Example
* -
* - //both are used the same way
* - function Test takes QueueQueue q returns nothing
* - //header
* - //! runtextmacro QUEUE_QUEUE_HEADER("QueueQueue")
* -
* - local QueueQueue node = q //make a copy
* -
* - //loop
* - //! runtextmacro QUEUE_QUEUE_START_LOOP("node")
* - //code
* - call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, I2S(node))
* - //endloop
* - //! runtextmacro QUEUE_QUEUE_END_LOOP
* - endfunction
* -
* ---------------------------------------------------------------------
*
*********************************************************************
*
* module QueueQueueLoop
*
* A module that provides methods for looping through a
* QueueQueue given an instanced looper.
*
*******************************************************************
*
* readonly thistype get
* - Retrieves the next value in the QueueQueue given a looper.
* readonly thistype skip
* - Skips inner values of the current node and returns next node.
* readonly thistype depthPointer
* - Returns pointer of current depth of loop that stores node. Depth
* - pointers are a stack, so depthPointer.depthPointer would go up one.
* readonly thistype depthNode
* - Returns the node stored within the depth pointer.
* integer id
* - For referencing a depth pointer to something. Depth pointers can be recycled
* - en masse w/o the user's knowledge, meaning that depth pointers should not be used
* - as references for values. It is best to reference the id of a depth pointer.
*
* method start takes nothing returns thistype
* - Creates a new looper for the QueueQueue.
* method end takes nothing returns nothing
* - Destroys a looper for a QueueQueue. Only used when not looping
* - through the entire QueueQueue. The looper is automatically destroyed
* - if the entire QueueQueue is looped through. This could be useful for value
* - searches where looping through the rest of the QueueQueue is pointles.
*
* ---------------------------------------------------------------------
* -
* - Example
* -
* - function Test takes QueueQueue q returns nothing
* - local QueueQueue looper = q.start() //create a new looper
* - local QueueQueue node
* -
* - loop
* - set node = looper.get //get the next node
* - exitwhen node == 0 //exitwhen the node is null
* -
* - //code
* - call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, I2S(node))
* - endloop
* - endfunction
* -
* ---------------------------------------------------------------------
*
*******************************************************************/
module QueueQueue
private static integer array nc //next column
private static integer array nr //next row
private static integer array lr //last row
private static integer ic=0 //column count
private static integer array rc //position recycler
debug private static boolean array a //is node allocated
debug private static integer array rs //references
private static boolean array h
readonly boolean pointer
readonly thistype parent
private boolean z
method operator skips takes nothing returns boolean
return z
endmethod
method operator skips= takes boolean b returns nothing
debug if (pointer) then
set z=b
debug else
debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,"QUEUE QUEUE ERROR: ATTEMPTED TO MANIPULATE SKIP OPTION FOR NON POINTER")
debug endif
endmethod
//can only add rows to current object
static method allocate takes nothing returns thistype
local thistype this
//allocate
if (0==rc[0]) then
set this=ic+1
set ic=this
else
set this=rc[0]
set rc[0]=rc[this]
endif
debug set a[this]=true
set nc[this]=0 //next column is 0
set nr[this]=0 //next row is 0
set pointer=true //is a pointer
set z=true
set parent=0
//is head
debug set h[this]=true
return this
endmethod
method add takes nothing returns thistype
local thistype n
debug if (a[this] and (not pointer or h[this])) then
//allocate
if (0==rc[0]) then
set n=ic+1
set ic=n
else
set n=rc[0]
set rc[0]=rc[n]
endif
debug set a[n]=true
if (0==nc[this]) then
//if nothing to the right, expand
set nc[this]=n
set lr[this]=n
else
//otherwise, add
set nr[lr[this]]=n
set lr[this]=n
endif
set nr[n]=0 //next row is 0
set nc[n]=0 //next column is 0
set n.parent=this
return n
debug else
debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,"QUEUE QUEUE ERROR: ATTEMPTED TO MANIPULATE NULL NODE")
debug endif
debug return 0
endmethod
//special add that adds an existing cell
method point takes integer p returns thistype
local thistype n
//if allocated and not a shadowed pointer (hidden)
debug if (a[this] and (not pointer or h[this]) and h) then
//allocate
if (0==rc[0]) then
set n=ic+1
set ic=n
else
set n=rc[0]
set rc[0]=rc[n]
endif
debug set a[n]=true
//add
if (0==nc[this]) then
//if nothing to the right, expand
set nc[this]=n
set lr[this]=n
else
//otherwise, add
set nr[lr[this]] = n
set lr[this] = n
endif
//expand and point to p
set nc[n]=p
set nr[n]=0
set n.pointer=true
set n.z=true
set n.parent=this
debug if (h) then
debug set rs=rs+1
debug endif
return n
debug else
debug if (not h) then
debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,"QUEUE QUEUE ERROR: ATTEMPTED TO POINT TO NON HEAD")
debug elseif (a[this]) then
debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,"QUEUE QUEUE ERROR: ATTEMPTED TO MANIPULATE NON HEAD POINTER")
debug else
debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,"QUEUE QUEUE ERROR: ATTEMPTED TO MANIPULATE NULL NODE")
debug endif
debug endif
return 0
endmethod
method operator next takes nothing returns thistype
return nr[this]
endmethod
method operator in takes nothing returns thistype
return nc[this]
endmethod
method deallocate takes nothing returns nothing
local thistype array r //first row on column
local thistype c = -1 //column
local thistype n = this //node
local boolean p = false
debug if (h[n] and 0==rs[n]) then
debug set h[n]=false
debug set a[n]=false
set rc[n]=rc[0]
set rc[0]=n
set pointer=false
set z=false
loop
if (p) then
debug if (h[nc[n]]) then
debug set rs[nc[n]]=rs[nc[n]]-1
debug endif
set n.pointer=false
set n.z=false
loop
//go left until can go down or all the way left
exitwhen 0!=nr[n] or 0==c
set c=c-1
set n=r[c]
endloop
set n=nr[n]
set r[c]=n
else
if (0==nc[n]) then
//if there is nothing to the right, then go down
loop
//go left until can go down or all the way left
exitwhen 0!=nr[n] or 0==c
set c=c-1
set n=r[c]
endloop
set n=nr[n]
set r[c]=n
else
//go right
set c=c+1 //go to next column
set n=nc[n]
set r[c]=n //update next column
endif
endif
exitwhen 0==n
set p=n.pointer
debug set a[n]=false
//destroy
set rc[n]=rc[0]
set rc[0]=n
endloop
debug else
debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,"QUEUE QUEUE ERROR: ATTEMPT TO DESTROY NON HEAD "+I2S(n))
debug endif
endmethod
endmodule
//! textmacro QUEUE_QUEUE_HEADER_B takes STRUCT
local boolean array d_1
local $STRUCT$ array r_1
local $STRUCT$ c_1
local $STRUCT$ n_1
//! endtextmacro
//! textmacro QUEUE_QUEUE_START_LOOP_B takes THIS
set n_1=$THIS$
set c_1=0
if (0!=n_1.in) then
loop
//go to lowest position
loop
exitwhen d_1[c_1] or (0==n_1.next and 0==n_1.in)
set d_1[c_1]=true
//first go down, then right
if (0!=n_1.in) then
set c_1=c_1+1
set r_1[c_1]=n_1
if (0!=n_1.next) then
set c_1=c_1+1
set r_1[c_1]=n_1.in
set n_1=n_1.next
else
set n_1=n_1.in
endif
elseif (0!=n_1.next) then
set c_1=c_1+1
set r_1[c_1]=n_1
set n_1=n_1.next
endif
endloop
if (not n_1.skips) then
set $THIS$=n_1
//! endtextmacro
//! textmacro QUEUE_QUEUE_END_LOOP_B
endif
//go up 1
set d_1[c_1]=false
set n_1=r_1[c_1]
set c_1=c_1-1
exitwhen 0==n_1
endloop
endif
//! endtextmacro
//! textmacro QUEUE_QUEUE_HEADER takes STRUCT
local $STRUCT$ array r_1
local $STRUCT$ c_1
local $STRUCT$ n_1
//! endtextmacro
//! textmacro QUEUE_QUEUE_START_LOOP takes THIS
set n_1=$THIS$
set c_1=-1
loop
if (not n_1.skips) then
set $THIS$=n_1
//! endtextmacro
//! textmacro QUEUE_QUEUE_END_LOOP
endif
if (0==n_1.in) then
//if there is nothing to the right, then go down
loop
//go left until can go down or all the way left
exitwhen 0!=n_1.next or 0==c_1
set c_1=c_1-1
set n_1=r_1[c_1]
endloop
set n_1=n_1.next
set r_1[c_1]=n_1
else
//go right
set c_1=c_1+1 //go to next column
set n_1=n_1.in
set r_1[c_1]=n_1 //update next column
endif
exitwhen 0==n_1
endloop
//! endtextmacro
module QueueQueueLoop
private thistype c
private thistype n
private boolean e
private boolean s
integer id
debug private boolean o
private static thistype array rr //recyler
private static thistype rc=0 //instance count
method operator depthNode takes nothing returns thistype
return n
endmethod
method operator depthPointer takes nothing returns thistype
local thistype h=c
loop
exitwhen not h.n.skips
set h=h.c
endloop
if (h==this) then
return 0
endif
return h
endmethod
method operator skip takes nothing returns thistype
local thistype n=c.n
debug if (o) then
//first, skip the node
loop
//go left until can go down or all the way left
exitwhen 0!=n.next or c.e
//destroy
set rr[c]=rr[0]
set rr[0]=c
set c=c.c
set n=c.n
endloop
set n=n.next
set c.n=n
//then find a node that doesn't skip
loop
exitwhen not n.skips
if (0==n.in) then
//if there is nothing to the right, then go down
loop
//go left until can go down or all the way left
exitwhen 0!=n.next or c.e
//destroy
set rr[c]=rr[0]
set rr[0]=c
set c=c.c
set n=c.n
endloop
set n=n.next
set c.n=n
else
//go right
if (0==rr[0]) then
set rc=rc+1
set rc.c=c
set c=rc
else
set rr[0].c=c
set c=rr[0]
set rr[0]=rr[c]
endif
set c.id=0
set n=n.in
set c.n=n
endif
endloop
if (0==n) then
debug set o=false
set s=false
set e=false
set rr[this]=rr[0]
set rr[0]=this
else
set c.id=0
endif
return n
debug else
debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,"QUEUE QUEUE LOOP ERROR: LOOP NOT OPEN")
debug endif
debug return 0
endmethod
method operator get takes nothing returns thistype
local thistype n=c.n
local string es=""
debug if (o) then
if (s) then
set s=false
if (not n.skips) then
return n
endif
endif
loop
if (0==n.in) then
//if there is nothing to the right, then go down
loop
//go left until can go down or all the way left
exitwhen 0!=n.next or c.e
//destroy
set rr[c]=rr[0]
set rr[0]=c
set c=c.c
set n=c.n
endloop
set n=n.next
set c.n=n
else
//go right
if (0==rr[0]) then
set rc=rc+1
set rc.c=c
set c=rc
else
set rr[0].c=c
set c=rr[0]
set rr[0]=rr[c]
endif
set c.id=0
set n=n.in
set c.n=n
endif
exitwhen not n.skips
endloop
if (0==n) then
debug set o=false
set s=false
set e=false
set rr[this]=rr[0]
set rr[0]=this
else
set c.id=0
endif
return n
debug else
debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,"QUEUE QUEUE LOOP ERROR: LOOP NOT OPEN")
debug endif
debug return 0
endmethod
method start takes nothing returns thistype
local thistype t
if (0==rr[0]) then
set rc=rc+1
set t=rc
else
set t=rr[0]
set rr[0]=rr[t]
endif
set t.id=0
set t.s=true
set t.c=t
set t.e=true
set t.n=this
debug set t.o=true
return t
endmethod
method end takes nothing returns nothing
local thistype c=this.c
debug if (o) then
debug set o=false
loop
exitwhen c.e
set rr[c]=rr[0]
set rr[0]=c
set c=c.c
endloop
set s=false
set e=false
set rr[c]=rr[0]
set rr[0]=c
debug else
debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,"QUEUE QUEUE LOOP ERROR: LOOP NOT OPEN")
debug endif
endmethod
endmodule
endlibrary
Textmacro Demo
JASS:
scope ttt
//remove the _B to see loop forward and add the _B to see loop backward
private module HeadLoop
//! runtextmacro QUEUE_QUEUE_HEADER_B("thistype")
endmodule
private module StartLoop
//! runtextmacro QUEUE_QUEUE_START_LOOP_B("node")
endmodule
private module EndLoop
//! runtextmacro QUEUE_QUEUE_END_LOOP_B()
endmodule
private struct ttt extends array
//the first node on the QueueQueue does not actually have to be a head
//as only the entire QueueQueue structure can be destroyed.
//
//keep in mind that only heads can be pointed to*
private static constant boolean SHOW_HEAD = true
implement QueueQueue
string v //represent values in node, shows positioning
integer id //depth for spacing
private method test takes nothing returns nothing
local thistype node = this
local string s = ""
local integer i = 0
//first create the header. The header takes the struct type
implement HeadLoop
//next, start the loop. Pass node in to the loop (this)
//node is overwritten, so don't actually pass in this unless you
//don't need it
implement StartLoop
set s = ""
//mumbo jumbo for spacing
//notice that I am just reading the node variable here as it's automatically set
//by the macro
if (SHOW_HEAD) then
set i = node.id-1
else
set i = node.id-2
endif
loop
exitwhen i == 0
set s = s + " "
set i = i - 1
endloop
set s = s + node.v
call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, s)
//end the loop
implement EndLoop
endmethod
/****************************************
*
* Looping Forwards
*
*****************************************
*
* 1
* 1.1
* 1.2
* 1.2.1
* 1.2.1.1
* 1.2.2
* 1.2.3
* 1.3
* 1.4
* 2
* 2.1
* 2.2
* 2.2.1
* 2.2.1.1
* 2.2.2
* 2.2.3
* 2.3
* 2.4
*
****************************************/
/****************************************
*
* Looping Backwards
*
*****************************************
*
* 2.4
* 2.3
* 2.2.3
* 2.2.2
* 2.2.1.1
* 2.2.1
* 2.2
* 2.1
* 2
* 1.4
* 1.3
* 1.2.3
* 1.2.2
* 1.2.1.1
* 1.2.1
* 1.2
* 1.1
* 1
*
****************************************/
private static method run takes nothing returns nothing
local thistype this = thistype.allocate()
local thistype r1 = add()
local thistype r1_r1 = r1.add()
local thistype r1_r2 = r1.add()
local thistype r1_r2_r1 = r1_r2.add()
local thistype r1_r2_r1_r1 = r1_r2_r1.add()
local thistype r1_r2_r2 = r1_r2.add()
local thistype r1_r2_r3 = r1_r2.add()
local thistype r1_r3 = r1.add()
local thistype r1_r4 = r1.add()
local thistype r2 = add()
local thistype r2_r1 = r2.add()
local thistype r2_r2 = r2.add()
local thistype r2_r2_r1 = r2_r2.add()
local thistype r2_r2_r1_r1 = r2_r2_r1.add()
local thistype r2_r2_r2 = r2_r2.add()
local thistype r2_r2_r3 = r2_r2.add()
local thistype r2_r3 = r2.add()
local thistype r2_r4 = r2.add()
set skips = not SHOW_HEAD
set id = 1
set v = "head"
set r1.id = 2
set r1_r1.id = 3
set r1_r2.id = 3
set r1_r2_r1.id = 4
set r1_r2_r1_r1.id = 5
set r1_r2_r2.id = 4
set r1_r2_r3.id = 4
set r1_r3.id = 3
set r1_r4.id = 3
set r2.id = 2
set r2_r1.id = 3
set r2_r2.id = 3
set r2_r2_r1.id = 4
set r2_r2_r1_r1.id = 5
set r2_r2_r2.id = 4
set r2_r2_r3.id = 4
set r2_r3.id = 3
set r2_r4.id = 3
set r1.v = "1"
set r1_r4.v = "1.4"
set r1_r3.v = "1.3"
set r1_r2.v = "1.2"
set r1_r2_r3.v = "1.2.3"
set r1_r2_r2.v = "1.2.2"
set r1_r2_r1_r1.v = "1.2.1.1"
set r1_r2_r1.v = "1.2.1"
set r1_r1.v = "1.1"
set r2.v = "2"
set r2_r4.v = "2.4"
set r2_r3.v = "2.3"
set r2_r2.v = "2.2"
set r2_r2_r3.v = "2.2.3"
set r2_r2_r2.v = "2.2.2"
set r2_r2_r1_r1.v = "2.2.1.1"
set r2_r2_r1.v = "2.2.1"
set r2_r1.v = "2.1"
call test()
call deallocate()
call DestroyTimer(GetExpiredTimer())
endmethod
private static method onInit takes nothing returns nothing
call TimerStart(CreateTimer(), 0, false, function thistype.run)
endmethod
endstruct
endscope
Module Demo
JASS:
scope ttt
private module HeadLoop
local thistype looper = start()
loop
endmodule
private module StartLoop
set node = looper.get
exitwhen node == 0
endmodule
private module EndLoop
endloop
endmodule
private struct ttt extends array
//the first node on the QueueQueue does not actually have to be a head
//as only the entire QueueQueue structure can be destroyed.
//
//keep in mind that only heads can be pointed to*
private static constant boolean SHOW_HEAD = false
implement QueueQueue
implement QueueQueueLoop
string v //represent values in node, shows positioning
integer id //depth for spacing
private method test takes nothing returns nothing
local thistype node = this
local string s = ""
local integer i = 0
//first create the header. The header takes the struct type
implement HeadLoop
//next, start the loop. Pass node in to the loop (this)
//node is overwritten, so don't actually pass in this unless you
//don't need it
implement StartLoop
set s = ""
//mumbo jumbo for spacing
//notice that I am just reading the node variable here as it's automatically set
//by the macro
if (SHOW_HEAD) then
set i = node.id-1
else
set i = node.id-2
endif
loop
exitwhen i == 0
set s = s + " "
set i = i - 1
endloop
set s = s + node.v
call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, s)
//end the loop
implement EndLoop
endmethod
/****************************************
*
* Looping Forwards
*
*****************************************
*
* 1
* 1.1
* 1.2
* 1.2.1
* 1.2.1.1
* 1.2.2
* 1.2.3
* 1.3
* 1.4
* 2
* 2.1
* 2.2
* 2.2.1
* 2.2.1.1
* 2.2.2
* 2.2.3
* 2.3
* 2.4
*
****************************************/
/****************************************
*
* Looping Backwards
*
*****************************************
*
* 2.4
* 2.3
* 2.2.3
* 2.2.2
* 2.2.1.1
* 2.2.1
* 2.2
* 2.1
* 2
* 1.4
* 1.3
* 1.2.3
* 1.2.2
* 1.2.1.1
* 1.2.1
* 1.2
* 1.1
* 1
*
****************************************/
private static method run takes nothing returns nothing
local thistype this = thistype.allocate()
local thistype r1 = add()
local thistype r1_r1 = r1.add()
local thistype r1_r2 = r1.add()
local thistype r1_r2_r1 = r1_r2.add()
local thistype r1_r2_r1_r1 = r1_r2_r1.add()
local thistype r1_r2_r2 = r1_r2.add()
local thistype r1_r2_r3 = r1_r2.add()
local thistype r1_r3 = r1.add()
local thistype r1_r4 = r1.add()
local thistype r2 = add()
local thistype r2_r1 = r2.add()
local thistype r2_r2 = r2.add()
local thistype r2_r2_r1 = r2_r2.add()
local thistype r2_r2_r1_r1 = r2_r2_r1.add()
local thistype r2_r2_r2 = r2_r2.add()
local thistype r2_r2_r3 = r2_r2.add()
local thistype r2_r3 = r2.add()
local thistype r2_r4 = r2.add()
set skips = not SHOW_HEAD
set id = 1
set v = "head"
set r1.id = 2
set r1_r1.id = 3
set r1_r2.id = 3
set r1_r2_r1.id = 4
set r1_r2_r1_r1.id = 5
set r1_r2_r2.id = 4
set r1_r2_r3.id = 4
set r1_r3.id = 3
set r1_r4.id = 3
set r2.id = 2
set r2_r1.id = 3
set r2_r2.id = 3
set r2_r2_r1.id = 4
set r2_r2_r1_r1.id = 5
set r2_r2_r2.id = 4
set r2_r2_r3.id = 4
set r2_r3.id = 3
set r2_r4.id = 3
set r1.v = "1"
set r1_r4.v = "1.4"
set r1_r3.v = "1.3"
set r1_r2.v = "1.2"
set r1_r2_r3.v = "1.2.3"
set r1_r2_r2.v = "1.2.2"
set r1_r2_r1_r1.v = "1.2.1.1"
set r1_r2_r1.v = "1.2.1"
set r1_r1.v = "1.1"
set r2.v = "2"
set r2_r4.v = "2.4"
set r2_r3.v = "2.3"
set r2_r2.v = "2.2"
set r2_r2_r3.v = "2.2.3"
set r2_r2_r2.v = "2.2.2"
set r2_r2_r1_r1.v = "2.2.1.1"
set r2_r2_r1.v = "2.2.1"
set r2_r1.v = "2.1"
call test()
call deallocate()
call DestroyTimer(GetExpiredTimer())
endmethod
private static method onInit takes nothing returns nothing
call TimerStart(CreateTimer(), 0, false, function thistype.run)
endmethod
endstruct
endscope
Data
Code:
1
1.1
1.2
1.2.1
1.2.1.1
1.2.2
1.2.3
1.3
1.4
2
2.1
2.2
2.2.1
2.2.1.1
2.2.2
2.2.3
2.3
2.4
Looped over forwards
Code:
1
1.1
1.2
1.2.1
1.2.1.1
1.2.2
1.2.3
1.3
1.4
2
2.1
2.2
2.2.1
2.2.1.1
2.2.2
2.2.3
2.3
2.4
Looped over backwards
Code:
2.4
2.3
2.2.3
2.2.2
2.2.1.1
2.2.1
2.2
2.1
2
1.4
1.3 1.2.3
1.2.2
1.2.1.1
1.2.1
1.2
1.1
1
Last edited: