Deleted member 219079
D
Deleted member 219079
Last updated: 6.1.2015
Table
v1.0.4
v1.0.4
Quick functionality:
local Table t = Table.create()
<- Assign a newly allocated instance of Table for local variable tt[10]=15
<- Bind integer 15 to index 10local integer i = t[10]
<- Make i hold the value returned from index 10 of tt.flush()
<- Clear all data bound to tt.has(10)
<- Returns whether index 10 has saved integert.destroy()
<- Clears and deallocates the instance of Table assigned to tScript:
JASS:
library Table // Date: 5.1.2015 , Updated: 6.1.2015
// -------------------------
// Table v1.0.4
// Globals
// -------------------------
globals
private constant boolean SLOW_ALLOC = true
/* SLOW_ALLOC = true:
+Allows you to use more than 8190 instances, with hashtable
-Some say hashtable read is 6x slower than array read
SLOW_ALLOC = false
+Allocation is as fast as it can get
-Max 8190 instances (overflow only checked for in debug mode) */
private constant boolean IGNORE_OVERFLOWN = true
/* Note: Only used when SLOW_ALLOC = false
IGNORE_OVERFLOWN = true:
+Allocation doesn't break when deallocation does
-Causes dead instances when there's more than 8191 recycled instances
IGNORE_OVERFLOWN = false:
+Faster deallocation than (true)
-Allows only 8190 instances */
private constant boolean CHECK_DOUBLE_FREE = false
/* CHECK_DOUBLE_FREE = true:
+Checks whether recycler already has deallocated instance
-Costs an instance, and hashtable read+write per destroy
CHECK_DOUBLE_FREE = false:
+Faster and recommended
-Doesn't check for double free (maybe dangerous) */
endglobals
// -------------------------
// Table v1.0.4
// Table
// -------------------------
// Table.create() - gives you new instance of Table
// [n] - gives you value bound to n
// [n]=m - binds value m to n
// .flush() - clears data bound to instance
// .has(n) - returns whether index n is used
// .destroy() - flushes and destroys the instance
globals
private constant hashtable T = InitHashtable()
endglobals
struct Table extends array
static if CHECK_DOUBLE_FREE then
private static thistype dfC // doublefreeChecker
endif
method operator [] takes integer i returns integer
return LoadInteger(T,this,i)
endmethod
method operator []= takes integer i, integer val returns nothing
call SaveInteger(T,this,i,val)
endmethod
method has takes integer i returns boolean
return HaveSavedInteger(T,this,i)
endmethod
method flush takes nothing returns nothing
call FlushChildHashtable(T,this)
endmethod
// allocation:
private static integer C=0 // instance count
private static integer ttArrM=-1 // 0-based array
static if SLOW_ALLOC then
static method create takes nothing returns thistype
if ttArrM>-1 then
static if CHECK_DOUBLE_FREE then
set dfC [LoadInteger(T,0,ttArrM)]=0
endif
set ttArrM=ttArrM-1
return LoadInteger(T,0,ttArrM+1)
endif
set C=C+1
return C
endmethod
else
private static thistype array ttArr
static method create takes nothing returns thistype
if ttArrM>-1 then
static if CHECK_DOUBLE_FREE then
set dfC [ttArr[ttArrM]]=0
endif
set ttArrM=ttArrM-1
return ttArr[ttArrM+1]
endif
set C=C+1
return C
endmethod
endif
method destroy takes nothing returns nothing
static if CHECK_DOUBLE_FREE then
if dfC [this]==1 then
debug call BJDebugMsg("|c00ff0000Error: Table_instance"+I2S(this)+": is destroyed twice.")
return
endif
set dfC[this]=1
endif
call FlushChildHashtable(T,this)
static if SLOW_ALLOC then
set ttArrM=ttArrM+1
call SaveInteger(T,0,ttArrM,this)
else
static if IGNORE_OVERFLOWN then
if ttArrM!=8190 then
set ttArrM=ttArrM+1
set ttArr[ttArrM]=this
endif
else
call FlushChildHashtable(T,this)
debug if ttArrM==8190 then
debug call BJDebugMsg("|c00ffff00Warning: Due to overflow, Table_instance"+I2S(this)+" is inusable.")
debug else
set ttArrM=ttArrM+1
set ttArr[ttArrM]=this
debug endif
endif
endif
endmethod
static if CHECK_DOUBLE_FREE then
private static method onInit takes nothing returns nothing
set dfC = thistype.create()
endmethod
endif
endstruct
// -------------------------
// Table v1.0.4
// TableArr
// -------------------------
// TableArr.create(n) - gives you new instance of TableArr, with n as max index
// [n] - returns instance of Table bound to index n
// .destroy() - flushes and destroys the instance
// .flush() - flushes Tables bound to the instance
globals
private constant boolean TABLEARR_SAFE = true
endglobals
struct TableArr extends array
method operator [] takes integer i returns Table
static if TABLEARR_SAFE then
local Table t = LoadInteger(T,this,i)
if t==0 then
debug call BJDebugMsg("|c00ff0000Error: Tried to access unused index @TableArr_instance"+I2S(this))
endif
return t
endif
return LoadInteger(T,this,i)
endmethod
method flush takes nothing returns nothing
local integer i=0
local Table t
loop
set t = LoadInteger(T,this,i)
exitwhen t==0
call FlushChildHashtable(T,t)
set i=i+1
endloop
endmethod
method destroy takes nothing returns nothing
local integer i=0
local Table t
loop
set t = LoadInteger(T,this,i)
exitwhen t==0
call t.destroy()
set i=i+1
endloop
call Table(this).destroy()
endmethod
static method create takes integer max returns thistype
local thistype this = Table.create()
local integer i = 0
loop
call SaveInteger(T,this,i,Table.create())
exitwhen i==max
set i=i+1
endloop
return this
endmethod
endstruct
// -------------------------
// Table v1.0.4
// Textmacros
// -------------------------
//! textmacro TABLE_EXTEND takes PRIVACY, ALIAS, TYPE, TABLEALIAS
/* E.g. if you want to use Table for widgets:
//! runtextmacro TABLE_EXTENDS("","Table_Widget","widget","WidgetHandle")
*/
$PRIVACY$ struct $ALIAS$ extends array
implement Table_ExtendMod
method operator [] takes integer i returns $TYPE$
return Load$TABLEALIAS$(eT,this,i)
endmethod
method operator []= takes integer i, $TYPE$ val returns nothing
call Save$TABLEALIAS$(eT,this,i,val)
endmethod
endstruct
//! endtextmacro
public module ExtendMod
static hashtable eT // extended table
static method create takes nothing returns thistype
return Table.create()
endmethod
method destroy takes nothing returns nothing
call Table(this).destroy()
endmethod
private static method onInit takes nothing returns nothing
set eT=T
endmethod
endmodule
endlibrary
Internally added functionality:
TableArr:
TableList:
(Temporarily removed)
TableArr:
local TableArr ta = TableArr.create(3)
<- Assign a newly allocated instance of TableArr for local variable ta, with max index of 3ta[0][10]=15
<- Bind integer 15 to index 10 of the Table at index 0local integer i = ta[0][10]
<- Make i hold the value returned from index 10 of Table at index 0ta.flush()
<- Clear all data bound to children of tata.destroy()
<- Clears and destroys children of ta, also destroys taTableList:
(Temporarily removed)
Added functionality via plugins:
TableLibrary:
TableInterface:
See demo below for use guide.
TableLibrary:
JASS:
library TableLibrary requires Table
// -------------------------
// Table v1.0.4
// Extend - library
// -------------------------
/*
Textmacro:
//! textmacro TABLE_EXTEND takes PRIVACY, ALIAS, TYPE, TABLEALIAS
What are these?
Makes so that you can extend the variable type variety of Table.
How to use?
Use the textmacro like used below.
How to use with TableArr?
Let's say tArr is our variable, assigned to an allocated instance
of TableArr with max index of 2, and we wish to store unit to index
1 of tArr and index 3 of the Table. We'll use it like this:
Table_Unit(tArr[1]) [3] = CreateUnit(Player(0),'hfoo',0,0,270)
Now, to read it, we'll use:
Table_Unit(tArr[1]) [3]
*/
//! runtextmacro TABLE_EXTEND ("","Table_Unit","unit","UnitHandle")
//! runtextmacro TABLE_EXTEND ("","Table_Real","real","Real")
//! runtextmacro TABLE_EXTEND ("","Table_Player","player","PlayerHandle")
endlibrary
Table_Unit t = Table_Unit.create()
<- Assign a newly allocated instance of Table_Unit to local variable tt[4]=CreateUnit(Player(0),'hfoo',0,0,270)
<- Saves unit to index 4 of tlocal unit u = t[4]
<- Make u hold the value bound to index 4 of tTableInterface:
JASS:
library TI /* =TableInterface */ requires Table
// -------------------------
// Table v1.0.4
// Interface
// -------------------------
/* Table interface vs normal struct?
+Supports ~2 000 000 instances + 4 000 structs vs 8 190 instances and 1 struct
+TI_Struct.fire(n) will trigger the "fire" method on n's creator struct
-Some say hashtable read is 6x slower than array read
-Costs TriggerEvaluate() and function call
Set-up guide:
1. Sort your methods in such order: ( im.=implement )
im. TI_Top
...
void destroy()
.deallocate()
...
static thistype create(<stuff>)
local thistype this=thistype.allocate()
...
im. TI_Bot
2. Have non-static method called "fire" in any place of "..."
3. Your struct now uses interface! */
globals // limit config:
private constant integer MAX_STRUCTS = 4000 // how many structs can use the interface
/* Note: Please don't set MAX_STRUCTS higher than 8190/2 */
private constant integer MAX_INSTANCES = 100000 // how many instances can be allocated at once
private constant boolean SLOW_ALLOC = true
/* Note: You'll manually set SLOW_ALLOC to match MAX_INSTANCES > 8190, because jasshelper's gay
SLOW_ALLOC = true:
+Supports over 8190 structs
-Costs Table calls
SLOW_ALLOC = false:
+Faster
-Supports up to 8190 structs */
endglobals
// ---------------
//! runtextmacro TI_NEW ("MAX_STRUCTS","MAX_INSTANCES","SLOW_ALLOC")
//! textmacro TI_NEW takes MAX_STRUCTS, MAX_INSTANCES, SLOW_ALLOC
globals
private Table tiT=0 // TI_Table
private integer ttArrM=-1
private integer C=0
private integer idM=-1
private trigger array tArr [$MAX_STRUCTS$] [2]
private constant integer INDEX_DESTR = 0
private constant integer INDEX_FIRE = 1
endglobals
static if not $SLOW_ALLOC$ then
globals
private integer array ttArr
endglobals
endif
public struct Struct extends array
readonly static thistype s // struct
static if DEBUG_MODE then
method fire takes nothing returns boolean
else
method fire takes nothing returns nothing
endif
static if $SLOW_ALLOC$ then
local integer id = tiT[this*2]
else
local integer id = tiT[this]
endif
if id!=-1 then
set s=this
call TriggerEvaluate(tArr[id][INDEX_FIRE])
debug return true
endif
debug return false
endmethod
static if DEBUG_MODE then
method pop takes nothing returns boolean
else
method pop takes nothing returns nothing
endif
static if $SLOW_ALLOC$ then
local integer id = tiT[this*2]
else
local integer id = tiT[this]
endif
if id!=-1 then
set s=this
call TriggerEvaluate(tArr[id][INDEX_FIRE])
call TriggerEvaluate(tArr[id][INDEX_DESTR])
debug return true
endif
debug return false
endmethod
method destroy takes nothing returns nothing
static if $SLOW_ALLOC$ then
local integer id = tiT[this*2]
else
local integer id = tiT[this]
endif
if id==-1 then
set ttArrM=ttArrM+1
static if $SLOW_ALLOC$ then
set tiT[ttArrM*2+1]=this
else
set ttArr[ttArrM]=this
endif
else
set s=this
call TriggerEvaluate(tArr[id][INDEX_DESTR])
endif
endmethod
endstruct
// ---------------
public module Top
static integer ID=-1
static method allocate takes nothing returns thistype
local thistype this
if ttArrM>-1 then
set ttArrM=ttArrM-1
static if $SLOW_ALLOC$ then
set this = tiT[(ttArrM+1)*2+1]
set tiT [this*2] = ID
else
set this = ttArr[ttArrM+1]
set tiT [this] = ID
endif
return this
elseif C<$MAX_INSTANCES$ then
set C=C+1
static if $SLOW_ALLOC$ then
set tiT [C*2] = ID
else
set tiT [C] = ID
endif
return C
debug else
debug call BJDebugMsg("|c00ff0000TableInterface ERROR: Exceeding $MAX_INSTANCES$|r")
endif
return 0
endmethod
method deallocate takes nothing returns nothing
set ttArrM=ttArrM+1
static if $SLOW_ALLOC$ then
set tiT [this*2] = -1
set tiT [ttArrM*2+1] = this
else
set tiT [this] = -1
set ttArr[ttArrM] = this
endif
endmethod
endmodule
// ---------------
public module Bot
static if thistype.fire.exists and thistype.destroy.exists then
private static method onDestr takes nothing returns boolean
call thistype(Struct.s).destroy()
return false
endmethod
private static method onFire takes nothing returns boolean
call thistype(Struct.s).fire()
return false
endmethod
private static method onInit takes nothing returns nothing
if idM<$MAX_STRUCTS$ then
set idM=idM+1
set ID=idM
if tiT == 0 then
set tiT=Table.create()
endif
set tArr[ID][INDEX_DESTR]=CreateTrigger()
call TriggerAddCondition(tArr[ID][INDEX_DESTR],Condition(function thistype.onDestr))
set tArr[ID][INDEX_FIRE]=CreateTrigger()
call TriggerAddCondition(tArr[ID][INDEX_FIRE],Condition(function thistype.onFire))
debug else
debug call BJDebugMsg("|c00ff0000TableInterface ERROR: Exceeding $MAX_STRUCTS$|r")
endif
endmethod
endif
endmodule
// ---------------
//! endtextmacro
endlibrary
Demo:
Uses Table and TableInterface. Also shows how to use TableLibrary's Tables with "sTable".
JASS:
scope TestInferface initializer init
//! runtextmacro TABLE_EXTEND ("","sTable","string","Str")
//! textmacro TI_TEST_CHILD takes ABC
private struct Child$ABC$ extends array
implement TI_Top
private static sTable sT
method destroy takes nothing returns nothing
call BJDebugMsg("Destroying Child$ABC$_instance"+I2S(this))
call deallocate()
endmethod
static method create takes string s returns thistype
local thistype this = thistype.allocate()
set sT[this]=s
return this
endmethod
method fire takes nothing returns nothing
call BJDebugMsg("Child$ABC$ says: "+sT[this])
endmethod
private static method onInit takes nothing returns nothing
set sT=Table.create()
endmethod
implement TI_Bot
endstruct
//! endtextmacro
//! runtextmacro TI_TEST_CHILD("A")
//! runtextmacro TI_TEST_CHILD("B")
//! runtextmacro TI_TEST_CHILD("C")
private function OnEsc takes nothing returns boolean
local TI_Struct a = ChildA.create("Boo!")
local TI_Struct b = ChildB.create("Boo!")
local TI_Struct c = ChildC.create("Boo!")
// test recycler
call BJDebugMsg("a: "+I2S(a)+" ; b: "+I2S(b)+" ; c: "+I2S(c))
call a.destroy()
call b.destroy()
call c.destroy()
set a = ChildA.create("Boo!")
set b = ChildB.create("Boo!")
set c = ChildC.create("Boo!")
call BJDebugMsg("a: "+I2S(a)+" ; b: "+I2S(b)+" ; c: "+I2S(c))
call a.pop()
call b.pop()
call c.pop()
return false
endfunction
private function init takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerAddCondition(t,Condition(function OnEsc))
call TriggerRegisterPlayerEvent(t,Player(0),EVENT_PLAYER_END_CINEMATIC)
set t = null
call BJDebugMsg("Hit ESC to test Table Interfaces")
endfunction
endscope
I'd prefer constructive criticism, "why do you do it like this? ..." -> "you do it like this: ... But I think it's better to do it like this: ..." ; "why do you think this is better than nnn?" -> "I don't think this is better compared to nnn, because nnn ..." ; "your algorithm is bad." -> "your algorithm works like ... , but I think it's better to make like ...". It's stupid to remind people to be constructive, but I often see people say "needs fix", forgetting about "change to ...". If you see a thing that needs fix, say how you'd fix it.