• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

Loop table

Status
Not open for further replies.
Level 13
Joined
Nov 7, 2014
Messages
571
Loop table

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.
 
Status
Not open for further replies.
Top