- Joined
- Nov 7, 2014
- Messages
- 571
Loop table
Lt (loop/lookup table) tries to implement a struct that acts as a
Other
Lt (loop/lookup table) tries to implement a struct that acts as a
string => integer
map that also allows iteration over its keys.
JASS:
library Ltdemo initializer init
private function demo takes nothing returns nothing
local Lt_string_integer t = Lt_string_integer.create()
local Kv_string_integer kv
set t["a"] = 1
set t["b"] = 2
set t["c"] = 3
call t.begin_loop()
loop
set kv = t.next()
exitwhen kv.no_next
call BJDebugMsg("t[\"" + kv.k + "\"]: " + I2S(kv.v))
endloop
call BJDebugMsg("removing key \"b\"")
if t.has("b") then
call t.remove("b")
endif
call t.begin_loop()
loop
set kv = t.next()
exitwhen kv.no_next
call BJDebugMsg("t[\"" + kv.k + "\"]: " + I2S(kv.v))
endloop
call BJDebugMsg("removing all keys")
call t.clear()
if not t.has("a") then
call BJDebugMsg("t[\"a\"]: " + I2S(t["a"]))
endif
call t.destroy()
endfunction
private function lazy_init takes nothing returns nothing
call demo()
endfunction
private function init takes nothing returns nothing
call TimerStart(CreateTimer(), 0.0, false, function lazy_init)
endfunction
endlibrary
JASS:
library Lt
globals
private hashtable ht = InitHashtable()
endglobals
struct Kv_string_integer extends array
/*readonly*/ string k
/*readonly*/ integer v
/*readonly*/ boolean no_next // exitwhen kv.no_next
endstruct
struct Lt_string_integer
private Kv_string_integer kv
private integer ki
// we implicitly store the keys in `ht`
// private string array ks
static method create takes nothing returns thistype
local thistype this = allocate()
set this.kv = Kv_string_integer(this)
return this
endmethod
method operator[]= takes string k, integer v returns nothing
local integer p = thistype.typeid * 8191 + this
local integer h = StringHash(k)
local integer i
if not HaveSavedInteger(ht, p, h) then
set i = LoadInteger(ht, -p, 0) + 1
call SaveInteger(ht, -p, 0, i)
call SaveStr(ht, -p, i, k)
endif
call SaveInteger(ht, p, h, v)
endmethod
method operator [] takes string k returns integer
return LoadInteger(ht, thistype.typeid * 8191 + this, StringHash(k))
endmethod
method begin_loop takes nothing returns nothing
set this.ki = 1
endmethod
method next takes nothing returns Kv_string_integer
local integer p = thistype.typeid * 8191 + this
local integer i = LoadInteger(ht, -p, 0)
if this.ki > i then
set this.kv.no_next = true
set this.kv.k = ""
set this.kv.v = 0
else
set this.kv.no_next = false
set this.kv.k = LoadStr(ht, -p, this.ki)
set this.kv.v = LoadInteger(ht, p, StringHash(this.kv.k))
set this.ki = this.ki + 1
endif
return this.kv
endmethod
method has takes string k returns boolean
return HaveSavedInteger(ht, thistype.typeid * 8191 + this, StringHash(k))
endmethod
method remove takes string k returns nothing
local integer p = thistype.typeid * 8191 + this
local integer h = StringHash(k)
local integer len = LoadInteger(ht, -p, 0)
local integer i
if HaveSavedInteger(ht, p, h) then
call RemoveSavedInteger(ht, p, h)
set i = 1
loop
exitwhen i > len
if LoadStr(ht, -p, i) == k then
loop
call SaveStr(ht, -p, i, LoadStr(ht, -p, i + 1))
set i = i + 1
exitwhen i == len
endloop
exitwhen true
endif
set i = i + 1
endloop
call SaveInteger(ht, -p, 0, len - 1)
endif
endmethod
method clear takes nothing returns nothing
local integer p = thistype.typeid * 8191 + this
call FlushChildHashtable(ht, p)
call FlushChildHashtable(ht, -p)
endmethod
method destroy takes nothing returns nothing
local integer p = thistype.typeid * 8191 + this
call FlushChildHashtable(ht, p)
call FlushChildHashtable(ht, -p)
call this.deallocate()
endmethod
endstruct
// other Lt_<key-type>_<value-type> structs could go here I guess
endlibrary
Other
Lt_<key-type>_<value-type>
maps could be useful as well, I guess.