It's a pretty useless system, actually just a waste of performance. Allows you to make
I do accept constructive criticism as long as they are not like "Delete this nao" or "GTFO with this crap bro"( I know this will probably end up in the Graveyard ), but ideas how to make this even more faster( right now its 4 times slower than ForGroup ). I also appreciate bugs reported if there any.
ForGroup, ForForce
like iterations. I couldn't think out a demonstration code, so I gladly accept any ideas.
JASS:
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// //
// Iterator v1.0 by Geries - Pretty shortened edition. //
// //
// Iterator does no really special stuff, it's just some eye-candy stuff with some loss of performance. It //
// allows to have calls like ForGroup or ForForce, etc.. Also it is vulnerable to DestroyTrigger( ) stuffs... //
// //
// Using optional modules: //
// - Table by Bribe: Saves one hashtable for you. //
// //
// API: //
// //
// Creates an iterator instance and sets up the code to be executed. //
// static method create takes code toRun returns Iterator //
// //
// Destroys an iterator instance. //
// method destroy takes nothing returns nothing //
// //
// Starts iterating for a given amount of loops. OP limit safe. You can also set it self-destructing when //
// finished. //
// method iterate takes integer count , boolean doDestroy returns nothing //
// //
// Gets the current iterator instance. //
// static method getIterator takes nothing returns Iterator //
// //
// Gets the iterator position. //
// method tellp takes nothing returns integer //
// //
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// //
// CONFIG //
// //
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
globals
// Allow Iterator to use the Table if it is available
constant boolean ITERATOR_USES_TABLE = true
endglobals
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// //
// SCRIPTS //
// //
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
library Iterator requires optional Table
struct Iterator extends array
static if ITERATOR_USES_TABLE and LIBRARY_Table then // Checks if Table available for the system
// One for iterator IDs
private static Table TData // ID to Trigger
// An other one for holding data for Iterators
private static Table DataA // Current Loop
private static Table DataB // End of loop
else
// Or only one hashtable and more performance
private static constant hashtable HT = InitHashtable( )
endif
private static integer Cu
static method create takes code toRun returns thistype
local trigger T = CreateTrigger( )
local integer id = GetHandleId( T )
static if ITERATOR_USES_TABLE and LIBRARY_Table then
set thistype.TData.trigger[id] = T
else
call SaveTriggerHandle( thistype.HT , 0 , id , T )
endif
call TriggerAddCondition( T , Condition( toRun ) )
set T = null
return id
endmethod
method destroy takes nothing returns nothing
static if ITERATOR_USES_TABLE and LIBRARY_Table then
call DestroyTrigger( TData.trigger[this] )
call thistype.TData.handle.remove( this )
call thistype.DataA.remove( this )
call thistype.DataB.remove( this )
else
call DestroyTrigger( LoadTriggerHandle( thistype.HT , 0 , this ) )
call RemoveSavedHandle( thistype.HT , 0 , this )
call RemoveSavedInteger( thistype.HT , this , 0 )
call RemoveSavedInteger( thistype.HT , this , 1 )
endif
endmethod
method iterate takes integer count , boolean doDestroy returns nothing
static if ITERATOR_USES_TABLE and LIBRARY_Table then
debug if thistype.TData.handle.has( this ) then
if not thistype.DataB.has( this ) then
if count > 0 then
set thistype.DataB[this] = count
set thistype.Cu = this
call ExecuteFunc( thistype.iterateLoop.name )
if doDestroy then
call this.destroy( )
endif
debug else
debug call BJDebugMsg( "|cffff0000[Iterator] - You shall give a number bigger than zero!|r" )
endif
debug else
debug call BJDebugMsg( "|cffff0000[Iterator] - You can't start an iteration before it didn't finish!|r" )
endif
debug else
debug call BJDebugMsg( "|cffff0000[Iterator] - Not existing iterator ID, no iteration." )
debug endif
else
debug if HaveSavedHandle( thistype.HT , 0 , this ) then
if not HaveSavedInteger( thistype.HT , this , 1 ) then
if count > 0 then
call SaveInteger( thistype.HT , this , 1 , count )
set thistype.Cu = this
call ExecuteFunc( thistype.iterateLoop.name )
if doDestroy then
call this.destroy( )
endif
debug else
debug call BJDebugMsg( "|cffff0000[Iterator] - You shall give a number greater than zero!|r" )
endif
debug else
debug call BJDebugMsg( "|cffff0000[Iterator] - You can't start an iteration on the same iterator instance before it would finish previous iterations!|r" )
endif
debug else
debug call BJDebugMsg( "|cffff0000[Iterator] - Not existing iterator ID, no iteration." )
debug endif
endif
endmethod
static method getIterator takes nothing returns Iterator
static if ITERATOR_USES_TABLE and LIBRARY_Table then
if thistype.TData.handle.has( GetHandleId( GetTriggeringTrigger( ) ) ) then
return GetHandleId( GetTriggeringTrigger( ) )
endif
else
if HaveSavedHandle( thistype.HT , 0 , GetHandleId( GetTriggeringTrigger( ) ) ) then
return GetHandleId( GetTriggeringTrigger( ) )
endif
endif
debug call BJDebugMsg( "|cffff0000[Iterator] - Your script is not running under iterator, no return." )
return 0
endmethod
method tellp takes nothing returns integer
static if ITERATOR_USES_TABLE and LIBRARY_Table then
debug if thistype.TData.handle.has( this ) then
return thistype.DataA[this]
debug endif
else
debug if HaveSavedHandle( thistype.HT , 0 , this ) then
return LoadInteger( thistype.HT , GetHandleId( GetTriggeringTrigger( ) ) , 0 )
debug endif
endif
debug call BJDebugMsg( "|cffff0000[Iterator] - Not existing iterator ID, no return." )
debug return 0
endmethod
private static method iterateLoop takes nothing returns nothing
local integer this = thistype.Cu
static if ITERATOR_USES_TABLE and LIBRARY_Table then
local integer max = thistype.DataB[this]
local integer Curr = thistype.DataA[this]
else
local integer max = LoadInteger( thistype.HT , thistype.Cu , 1 )
local integer Curr = LoadInteger( thistype.HT , thistype.Cu , 0 )
endif
local integer i = 0
loop
exitwhen i == 2000 or max <= Curr
set i = i + 1
set Curr = Curr + 1
static if ITERATOR_USES_TABLE and LIBRARY_Table then
set thistype.DataA[this] = Curr
call TriggerEvaluate( thistype.TData.trigger[this] )
else
call SaveInteger( thistype.HT , this , 0 , Curr )
call TriggerEvaluate( LoadTriggerHandle( thistype.HT , 0 , this ) )
endif
endloop
if max > Curr then
set thistype.Cu = this
call ExecuteFunc( thistype.iterateLoop.name )
else
static if ITERATOR_USES_TABLE and LIBRARY_Table then
call thistype.DataA.remove( this )
call thistype.DataB.remove( this )
else
call RemoveSavedInteger( thistype.HT , this , 0 )
call RemoveSavedInteger( thistype.HT , this , 1 )
endif
endif
endmethod
static if ITERATOR_USES_TABLE and LIBRARY_Table then
private static method onInit takes nothing returns nothing
set thistype.TData = Table.create( )
set thistype.DataA = Table.create( )
set thistype.DataB = Table.create( )
endmethod
endif
endstruct
endlibrary