• 🏆 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!

Simple Table<T>

Status
Not open for further replies.
** APPROPRIATELY RENAMED Array<T>

Disclaimer: If you're looking for the full featured, fully developed version, please use Vector<T> Developed by Bannar in conjunction with Bribe's table.

Edit: This code snippet now contains code for a Map<T, T> (currently only supports value type to value type)

This is a very simple implementation with a small amount of code. Why did I do this?

  1. Deepen my own understanding of the single hash-table philosophy
  2. Create a simple library that's easy to read and understand
  3. Allow others who are learning to study the concept themselves a bit, in a more simplified fashion.
So if you want to build your own customized table, this resource would be an IDEAL starting point for you. This is a very simplistic approach to the one hashtable philosophy.

This is also for anyone just wanting a simple all-in-one solution to this problem with not dependencies on other libraries.

onto the code:



JASS:
//not much to see here, just a function I'm using to dealloc triggers
library TriggerUtil

    public function cleanTrigger takes trigger t returns nothing
        call TriggerClearActions(t)
        call TriggerClearActions(t)
        call DestroyTrigger(t)
    endfunction
 
endlibrary



JASS:
    /*
    This is for use with types integer, real, and string
 
    DO NOT ATTEMPT TO USE THIS WITH trigger or other handle types
 
 
    */
 
    //! textmacro mapValueType takes ACCSESSOR, KEY_TYPE_LOWER, KEY_TYPE_UPPER, HASH_FUNC, VALUE_TYPE_UPPER, VALUE_TYPE_LOWER
    public struct $KEY_TYPE_UPPER$To$VALUE_TYPE_UPPER$Map
        private integer tableInd
        private integer values
 
        public static method create takes nothing returns thistype
            local thistype new = .allocate()
            set new.tableInd = allocTable()
            set new.values = 0
        
            if new.tableInd == -1 then
                call BJDebugMsg("Warning... inner hashtable allocation failed! Report this issue to the map maker. No table struct allocated...")
            
                call new.destroy()
            
                return -1
            endif
        
            return new
        endmethod
    
        public method operator[] takes $KEY_TYPE_LOWER$ key returns $VALUE_TYPE_LOWER$
            local integer ind = $HASH_FUNC$(key)
    
            if (not(this.hasValueAt(ind))) then
                call BJDebugMsg("Map error: No value at element " + I2S(ind) + " when trying to access element, report this bug to the map maker!")
            endif
    
            return Load$ACCSESSOR$(hashtables, this.tableInd, ind)
        endmethod
    
        //DO NOT use this method for expanding the table, use push instead!
        public method operator[]= takes $KEY_TYPE_LOWER$ key, $VALUE_TYPE_LOWER$ value returns nothing
            local integer ind = $HASH_FUNC$(key)
    
            if (not(this.hasValueAt(ind))) then
                call BJDebugMsg("Map error: No value at element " + I2S(ind) + " when trying to mutate element, report this bug to the map maker!")
                return
            endif
    
            call Save$ACCSESSOR$(hashtables, this.tableInd, ind, value)
        endmethod
    
        public method push takes $KEY_TYPE_LOWER$ key, $VALUE_TYPE_LOWER$ value returns nothing
            local integer ind = $HASH_FUNC$(key)
    
            call Save$ACCSESSOR$(hashtables, this.tableInd, ind, value)
        
            set this.values = this.values + 1
        endmethod
    
        public method pop takes $KEY_TYPE_LOWER$ key returns nothing
            local integer ind = $HASH_FUNC$(key)
        
            if (not(this.hasValueAt(ind))) then
                call BJDebugMsg("Map error: No value at element " + I2S(ind) + " when trying to pop element, report this bug to the map maker!")
                return
            endif
        
            set this.values = this.values - 1
        
            call RemoveSaved$VALUE_TYPE_UPPER$(hashtables, this.tableInd, ind)
        endmethod
    
        public method size takes nothing returns integer
            return this.values
        endmethod
    
        public method hashtableIndex takes nothing returns integer
            return this.tableInd
        endmethod
    
        private method hasValueAt takes integer ind returns boolean
            return HaveSaved$VALUE_TYPE_UPPER$(hashtables, this.tableInd, ind)
        endmethod
    
        public method hasValueAtKey takes $KEY_TYPE_LOWER$ key returns boolean
            local integer ind = $HASH_FUNC$(key)
            return this.hasValueAt(ind)
        endmethod
    
        public method flush takes nothing returns nothing
            call FlushChildHashtable(hashtables, this.tableInd)
            set this.values = 0
        endmethod
    
        public method onDestroy takes nothing returns nothing
            if deallocTable(this.tableInd) == -1 then
                call BJDebugMsg("Hashtable deallocation failed! Report this issue to the map maker.")
            endif
        
            call this.flush()
        endmethod
    endstruct
    //! endtextmacro



JASS:
    /*
    This is for use with types integer, real, and string
 
    DO NOT ATTEMPT TO USE THIS WITH trigger or other handle types
 
 
    */
 
    //! textmacro arrayValueType takes ACCSESSOR, TYPE_UPPER, TYPE_LOWER
    public struct $TYPE_UPPER$Array
        private integer tableInd
        private integer values

        public static method create takes nothing returns thistype
            local thistype new = .allocate()
            set new.tableInd = allocTable()
            set new.values = 0
       
            if new.tableInd == -1 then
                call BJDebugMsg("Warning... inner hashtable allocation failed! Report this issue to the map maker. No table struct allocated...")
           
                call new.destroy()
           
                return -1
            endif
       
            return new
        endmethod
   
        public method operator[] takes integer ind returns $TYPE_LOWER$
            if (not(this.hasValueAt(ind))) then
                call BJDebugMsg("Array error: No value at element " + I2S(ind) + " when trying to access element, report this bug to the map maker!")
            endif
   
            return Load$ACCSESSOR$(hashtables, this.tableInd, ind)
        endmethod
   
        //DO NOT use this method for expanding the table, use push instead!
        public method operator[]= takes integer ind, $TYPE_LOWER$ value returns nothing
            if (not(this.hasValueAt(ind))) then
                call BJDebugMsg("Array error: No value at element " + I2S(ind) + " when trying to mutate element, report this bug to the map maker!")
                return
            endif
   
            call Save$ACCSESSOR$(hashtables, this.tableInd, ind, value)
        endmethod
   
        public method push takes $TYPE_LOWER$ value returns nothing
            call Save$ACCSESSOR$(hashtables, this.tableInd, this.values, value)
       
            set this.values = this.values + 1
        endmethod
   
        public method pop takes nothing returns nothing
            if this.values == 0 then
                call BJDebugMsg("Array error: table is EMPTY, report this bug to the map maker!")
                return
            endif
   
            call RemoveSaved$TYPE_UPPER$(hashtables, this.tableInd, this.values - 1)
       
            set this.values = this.values - 1
        endmethod
   
        public method top takes nothing returns $TYPE_LOWER$
            if this.values == 0 then
                call BJDebugMsg("Array error: table is EMPTY, report this bug to the map maker!")
            endif
       
            return Load$ACCSESSOR$(hashtables, this.tableInd, this.values -1)
        endmethod
   
        public method bottom takes nothing returns $TYPE_LOWER$
            if this.values == 0 then
                call BJDebugMsg("Array error: table is EMPTY, report this bug to the map maker!")
            endif
       
            return Load$ACCSESSOR$(hashtables, this.tableInd, 0)
        endmethod
   
        public method size takes nothing returns integer
            return this.values
        endmethod
   
        public method hashtableIndex takes nothing returns integer
            return this.tableInd
        endmethod
   
        public method hasValueAt takes integer ind returns boolean
            return HaveSaved$TYPE_UPPER$(hashtables, this.tableInd, ind)
        endmethod
   
        public method flush takes nothing returns nothing
            call FlushChildHashtable(hashtables, this.tableInd)
            set this.values = 0
        endmethod
   
        public method onDestroy takes nothing returns nothing
            if deallocTable(this.tableInd) == -1 then
                call BJDebugMsg("Hashtable deallocation failed! Report this issue to the map maker.")
            endif
       
            call this.flush()
        endmethod
    endstruct
    //! endtextmacro



JASS:
       /*
    This is for use with handle types like trigger
 
    Memory, by default, is NOT managed by the table.
    However, if you set wantDestroy to true,
    the table will deallocate the underlying objects.
 
    You can also use destroyTop which is a destructive version of pop
    */
 
   //! textmacro arrayHandleType takes TYPE_UPPER, TYPE_LOWER, DEALLOC_FUNC
    public struct $TYPE_UPPER$Array
        private integer tableInd
        private integer values
        private boolean wantDestroy

        public static method create takes nothing returns thistype
            local thistype new = .allocate()
            set new.tableInd = allocTable()
            set new.values = 0
            set new.wantDestroy = false
       
            if new.tableInd == -1 then
                call BJDebugMsg("Warning... inner hashtable allocation failed! Report this issue to the map maker. No table struct allocated...")
           
                call new.destroy()
           
                return -1
            endif
       
            return new
        endmethod
   
        public method operator[] takes integer ind returns $TYPE_LOWER$
            if (not(this.hasValueAt(ind))) then
                call BJDebugMsg("Array error: No value at element " + I2S(ind) + " when trying to access element, report this bug to the map maker!")
                return null
            endif
   
            return Load$TYPE_UPPER$Handle(hashtables, this.tableInd, ind)
        endmethod
   
        //DO NOT use this method for expanding the table, use push instead!
        public method operator[]= takes integer ind, $TYPE_LOWER$ value returns nothing
            if (not(this.hasValueAt(ind))) then
                call BJDebugMsg("Array error: No value at element " + I2S(ind) + " when trying to mutate element, report this bug to the map maker!")
                return
            endif
   
            call Save$TYPE_UPPER$Handle(hashtables, this.tableInd, ind, value)
        endmethod
   
        public method push takes $TYPE_LOWER$ value returns nothing
            call Save$TYPE_UPPER$Handle(hashtables, this.tableInd, this.values, value)
       
            set this.values = this.values + 1
        endmethod
   
        //this method won't call the deallocation method for the underlying object
        public method pop takes nothing returns nothing
            if this.values == 0 then
                call BJDebugMsg("Array error: table is EMPTY, report this bug to the map maker!")
                return
            endif
   
            call RemoveSavedHandle(hashtables, this.tableInd, this.values - 1)
       
            set this.values = this.values - 1
        endmethod
   
        //like pop, but destructive to the underlying object
        public method destroyTop takes nothing returns nothing
            local $TYPE_LOWER$ toDestroy
       
            if this.values == 0 then
                call BJDebugMsg("Array error: table is EMPTY, report this bug to the map maker!")
                return
            endif
       
            set toDestroy = Load$TYPE_UPPER$Handle(hashtables, this.tableInd, this.values - 1)
       
            call RemoveSavedHandle(hashtables, this.tableInd, this.values - 1)
       
            call $DEALLOC_FUNC$(toDestroy)
       
            set toDestroy = null
       
            set this.values = this.values - 1
        endmethod
   
        /*
            Destroys the element at ind and replaces it with with.
            Removes the memory for the underlying object
            Must be an object at element ind!
        */
        public method replace takes integer ind, $TYPE_LOWER$ with returns nothing
            local $TYPE_LOWER$ toDestroy
   
            if (not(this.hasValueAt(ind))) then
                call BJDebugMsg("Array error: No value at element " + I2S(ind) + " when trying to mutate element, report this bug to the map maker!")
                return
            endif
   
            set toDestroy = Load$TYPE_UPPER$Handle(hashtables, this.tableInd, ind)
            call Save$TYPE_UPPER$Handle(hashtables, this.tableInd, ind, with)
       
            call $DEALLOC_FUNC$(toDestroy)
            set toDestroy = null
        endmethod
   
        public method top takes nothing returns $TYPE_LOWER$
            if this.values == 0 then
                call BJDebugMsg("Array error: table is EMPTY, report this bug to the map maker!")
                return null
            endif
       
            return Load$TYPE_UPPER$Handle(hashtables, this.tableInd, this.values -1)
        endmethod
   
        public method bottom takes nothing returns $TYPE_LOWER$
            if this.values == 0 then
                call BJDebugMsg("Array error: table is EMPTY, report this bug to the map maker!")
                return null
            endif
       
            return Load$TYPE_UPPER$Handle(hashtables, this.tableInd, 0)
        endmethod
   
        public method size takes nothing returns integer
            return this.values
        endmethod
   
        public method hashtableIndex takes nothing returns integer
            return this.tableInd
        endmethod
   
        public method hasValueAt takes integer ind returns boolean
            return HaveSavedHandle(hashtables, this.tableInd, ind)
        endmethod
   
        //this method will not deallocate the underlying objects
        public method flush takes nothing returns nothing
            call FlushChildHashtable(hashtables, this.tableInd)
            set this.values = 0
        endmethod
   
        //identitcal to flush, but also destroys the underlying objects
        public method cleansAll takes nothing returns nothing
            loop
                exitwhen this.values == 0
                call this.destroyTop()
            endloop
       
            call this.flush()
        endmethod
   
        //flags wantDestroy to the desired value
        //if wantDestroy is flagged, cleansAll() is called upon destruction rather than flush()
        public method setWantDestroy takes boolean to returns nothing
            set this.wantDestroy = to
        endmethod
   
        public method isWantDestroy takes  nothing returns boolean
            return this.wantDestroy
        endmethod
   
        public method onDestroy takes nothing returns nothing
            if deallocTable(this.tableInd) == -1 then
                call BJDebugMsg("Hashtable deallocation failed! Report this issue to the map maker.")
            endif
       
            if (this.wantDestroy) then
                call this.cleansAll()
            else
                call this.flush()
            endif
        endmethod
    endstruct
    //! endtextmacro



JASS:
    /*
        This is for use with struct types
        Not to be used with any other variable types, must be a struct
    */
 
    //! textmacro arrayStructType takes TYPE
    public struct $TYPE$Array
        private integer tableInd
        private integer values
        private boolean wantDestroy

        public static method create takes nothing returns thistype
            local thistype new = .allocate()
            set new.tableInd = allocTable()
            set new.values = 0
            set new.wantDestroy = false
       
            if new.tableInd == -1 then
                call BJDebugMsg("Warning... inner hashtable allocation failed! Report this issue to the map maker. No table struct allocated...")
           
                call new.destroy()
           
                return -1
            endif
       
            return new
        endmethod
   
        public method operator[] takes integer ind returns $TYPE$
            if (not(this.hasValueAt(ind))) then
                call BJDebugMsg("Array error: No value at element " + I2S(ind) + " when trying to access element, report this bug to the map maker!")
                return null
            endif
   
            return LoadInteger(hashtables, this.tableInd, ind)
        endmethod
   
        //DO NOT use this method for expanding the table, use push instead!
        public method operator[]= takes integer ind, $TYPE$ value returns nothing
            if (not(this.hasValueAt(ind))) then
                call BJDebugMsg("Array error: No value at element " + I2S(ind) + " when trying to mutate element, report this bug to the map maker!")
                return
            endif
   
            call SaveInteger(hashtables, this.tableInd, ind, value)
        endmethod
   
        public method push takes $TYPE$ value returns nothing
            call SaveInteger(hashtables, this.tableInd, this.values, value)
       
            set this.values = this.values + 1
        endmethod
   
        //this method won't call the deallocation method for the underlying object
        public method pop takes nothing returns nothing
            if this.values == 0 then
                call BJDebugMsg("Array error: table is EMPTY, report this bug to the map maker!")
                return
            endif
   
            call RemoveSavedInteger(hashtables, this.tableInd, this.values - 1)
       
            set this.values = this.values - 1
        endmethod
   
        //like pop, but destructive to the underlying object
        public method destroyTop takes nothing returns nothing
            local $TYPE$ toDestroy
       
            if this.values == 0 then
                call BJDebugMsg("Array error: table is EMPTY, report this bug to the map maker!")
                return
            endif
       
            set toDestroy = LoadInteger(hashtables, this.tableInd, this.values - 1)
       
            call RemoveSavedInteger(hashtables, this.tableInd, this.values - 1)
       
            call toDestroy.destroy()
       
            set this.values = this.values - 1
        endmethod
   
        /*
            Destroys the element at ind and replaces it with with.
            Removes the memory for the underlying object
            Must be an object at element ind!
        */
        public method replace takes integer ind, $TYPE$ with returns nothing
            local $TYPE$ toDestroy
   
            if (not(this.hasValueAt(ind))) then
                call BJDebugMsg("Array error: No value at element " + I2S(ind) + " when trying to mutate element, report this bug to the map maker!")
                return
            endif
   
            set toDestroy = LoadInteger(hashtables, this.tableInd, ind)
            call SaveInteger(hashtables, this.tableInd, ind, with)
       
            call toDestroy.destroy()
        endmethod
   
        public method top takes nothing returns $TYPE$
            if this.values == 0 then
                call BJDebugMsg("Array error: table is EMPTY, report this bug to the map maker!")
                return -1
            endif
       
            return LoadInteger(hashtables, this.tableInd, this.values -1)
        endmethod
   
        public method bottom takes nothing returns $TYPE$
            if this.values == 0 then
                call BJDebugMsg("Array error: table is EMPTY, report this bug to the map maker!")
                return -1
            endif
       
            return LoadInteger(hashtables, this.tableInd, 0)
        endmethod
   
        public method size takes nothing returns integer
            return this.values
        endmethod
   
        public method hashtableIndex takes nothing returns integer
            return this.tableInd
        endmethod
   
        public method hasValueAt takes integer ind returns boolean
            return HaveSavedInteger(hashtables, this.tableInd, ind)
        endmethod
   
        //this method will not deallocate the underlying objects
        public method flush takes nothing returns nothing
            call FlushChildHashtable(hashtables, this.tableInd)
            set this.values = 0
        endmethod
   
        //identitcal to flush, but also destroys the underlying objects
        public method cleansAll takes nothing returns nothing
            loop
                exitwhen this.values == 0
                call this.destroyTop()
            endloop
       
            call this.flush()
        endmethod
   
        //flags wantDestroy to the desired value
        //if wantDestroy is flagged, cleansAll() is called upon destruction rather than flush()
        public method setWantDestroy takes boolean to returns nothing
            set this.wantDestroy = to
        endmethod
   
        public method isWantDestroy takes  nothing returns boolean
            return this.wantDestroy
        endmethod
   
        public method onDestroy takes nothing returns nothing
            if deallocTable(this.tableInd) == -1 then
                call BJDebugMsg("Hashtable deallocation failed! Report this issue to the map maker.")
            endif
       
            if (this.wantDestroy) then
                call this.cleansAll()
            else
                call this.flush()
            endif
        endmethod
    endstruct
    //! endtextmacro



JASS:
library containers initializer init requires TriggerUtil
    globals
        private constant integer MAX_TABLES = 1500
        private integer array freeIndices
        private integer tos = 0
        public hashtable hashtables = InitHashtable()
    endglobals
 
    private function init takes nothing returns nothing
        local integer i = 0
   
        loop
            set freeIndices[i] = i
       
            set i = i + 1
            exitwhen i == MAX_TABLES
        endloop
    endfunction
 
    public function allocTable takes nothing returns integer
        local integer index = freeIndices[tos]
   
        if tos == MAX_TABLES then
            set tos = tos - 1
            call BJDebugMsg("Max hashtables reached. Allocation failed.")
            return -1
        endif
   
        set tos = tos + 1
   
        return index
    endfunction
 
    public function deallocTable takes integer ind returns integer
        if tos == 0 then
            call BJDebugMsg("Deallocation failed. There are no tables to deallocate!")
            return -1
        endif
   
        set tos = tos - 1
        set freeIndices[tos] = ind
   
        return 0
    endfunction
 
    //! runtextmacro mapValueType("Str", "string", "String", "StringHash", "String", "string")

    //! runtextmacro arrayValueType("Boolean", "Boolean", "boolean")
    //! runtextmacro arrayValueType("Integer", "Integer", "integer")
    //! runtextmacro arrayValueType("Real", "Real", "real")
    //! runtextmacro arrayValueType("Str", "String", "string")

    //! runtextmacro arrayHandleType("Ability", "ability", "TriggerUtil_dummy")
    //! runtextmacro arrayHandleType("Button", "button", "TriggerUtil_dummy")
    //! runtextmacro arrayHandleType("DefeatCondition", "defeatcondition", "DestroyDefeatCondition")
    //! runtextmacro arrayHandleType("Destructable", "destructable", "RemoveDestructable")
    //! runtextmacro arrayHandleType("Dialog", "dialog", "DialogDestroy")
    //! runtextmacro arrayHandleType("Effect", "effect", "DestroyEffect")
    //! runtextmacro arrayHandleType("FogModifier", "fogmodifier", "DestroyFogModifier")
    //! runtextmacro arrayHandleType("FogState", "fogstate", "TriggerUtil_dummy")
    //! runtextmacro arrayHandleType("Force", "force", "DestroyForce")
    //! runtextmacro arrayHandleType("Group", "group", "DestroyGroup")
    //! runtextmacro arrayHandleType("Hashtable", "hashtable", "FlushParentHashtable")
    //! runtextmacro arrayHandleType("Image", "image", "DestroyImage")
    //! runtextmacro arrayHandleType("Item", "item", "RemoveItem")
    //! runtextmacro arrayHandleType("ItemPool", "itempool", "DestroyItemPool")
    //! runtextmacro arrayHandleType("Leaderboard", "leaderboard", "DestroyLeaderboard")
    //! runtextmacro arrayHandleType("Lightning", "lightning", "DestroyLightning")
    //! runtextmacro arrayHandleType("Location", "location", "RemoveLocation")
    //! runtextmacro arrayHandleType("Multiboard", "multiboard", "DestroyMultiboard")
    //! runtextmacro arrayHandleType("MultiboardItem", "multiboarditem", "MultiboardReleaseItem")
    //! runtextmacro arrayHandleType("Player", "player", "TriggerUtil_dummy")
    //! runtextmacro arrayHandleType("Quest", "quest", "DestroyQuest")
    //! runtextmacro arrayHandleType("QuestItem", "questitem", "TriggerUtil_dummy")
    //! runtextmacro arrayHandleType("Rect", "rect", "RemoveRect")
    //! runtextmacro arrayHandleType("Sound", "sound", "TriggerUtil_dummy")
    //! runtextmacro arrayHandleType("TextTag", "texttag", "DestroyTextTag")
    //! runtextmacro arrayHandleType("TimerDialog", "timerdialog", "DestroyTimerDialog")
    //! runtextmacro arrayHandleType("Timer", "timer", "DestroyTimer")
    //! runtextmacro arrayHandleType("Trackable", "trackable", "TriggerUtil_dummy")
    //! runtextmacro arrayHandleType("TriggerAction", "triggeraction", "TriggerUtil_dummy")
    //! runtextmacro arrayHandleType("TriggerCondition", "triggercondition", "TriggerUtil_dummy")
    //! runtextmacro arrayHandleType("TriggerEvent", "event", "TriggerUtil_dummy")
    //! runtextmacro arrayHandleType("Trigger", "trigger", "DestroyTrigger")
    //! runtextmacro arrayHandleType("Ubersplat", "ubersplat", "DestroyUbersplat")
    //! runtextmacro arrayHandleType("Unit", "unit", "RemoveUnit")
    //! runtextmacro arrayHandleType("UnitPool", "unitpool", "DestroyUnitPool")
    //! runtextmacro arrayHandleType("Widget", "widget", "TriggerUtil_dummy")
endlibrary





JASS:
function myCallback takes nothing returns nothing
    call DisplayTextToPlayer(Player(0), 0, 0, "Hello from a trigger")
 
endfunction

function Trig_Untitled_Trigger_001_Actions takes nothing returns nothing
    local integer i = 0
    local tables_TriggerTable myTable = tables_TriggerTable.create()
    local tables_TriggerTableTable inner = tables_TriggerTableTable.create()
    local trigger t = CreateTrigger()
 
    call inner.push(myTable)
 
    call myTable.push(t)
 
    call TriggerAddAction(t, function myCallback)
 
    call TriggerExecute(inner.top()[0])
 
    if (inner.top().hasValueAt(0)) then
        call DisplayTextToPlayer(Player(0), 0, 0, "Has a value")
    else
        call DisplayTextToPlayer(Player(0), 0, 0, "Doesn't have a value")
    endif
 
    if (inner.top().hasValueAt(1)) then
        call DisplayTextToPlayer(Player(0), 0, 0, "Has a value")
    else
        call DisplayTextToPlayer(Player(0), 0, 0, "Doesn't have a value")
    endif
 
    call myTable.setWantDestroy(true)
 
    call inner.setWantDestroy(true)
 
    call inner.destroy()
 
    set t = null
endfunction

//===========================================================================
function InitTrig_Untitled_Trigger_001 takes nothing returns nothing
    set gg_trg_Untitled_Trigger_001 = CreateTrigger(  )
    call TriggerRegisterTimerEventSingle( gg_trg_Untitled_Trigger_001, 0.00 )
    call TriggerAddAction( gg_trg_Untitled_Trigger_001, function Trig_Untitled_Trigger_001_Actions )
endfunction



JASS:
function Trig_Untitled_Trigger_001_Actions takes nothing returns nothing
    local containers_StringToStringMap people = containers_StringToStringMap.create()
 
    call people.push("Patrick Leonard", "Kinda nerdy guy with a lot of unexpected twists hidden just under the surface. Likes C#.")
    call people.push("Destiny Showman", "Patrick's Girlfriend, a very sweet, loving, caring girl. Not the brightest one in the bunch though (don't tell her I said that I love her very much). HOWEVER, she has excellent memory and is very insightful.")
 
    call DisplayTextToPlayer(Player(0), 0, 0, people["Patrick Leonard"])
    call DisplayTextToPlayer(Player(0), 0, 0, people["Destiny Showman"])
    call DisplayTextToPlayer(Player(0), 0, 0, people["ME DOZ NOT EXIST"])
endfunction

//===========================================================================
function InitTrig_Untitled_Trigger_001 takes nothing returns nothing
    set gg_trg_Untitled_Trigger_001 = CreateTrigger(  )
    call TriggerRegisterTimerEventSingle( gg_trg_Untitled_Trigger_001, 0.01 )
    call TriggerAddAction( gg_trg_Untitled_Trigger_001, function Trig_Untitled_Trigger_001_Actions )
endfunction
 
Last edited:
Level 13
Joined
Nov 7, 2014
Messages
571
So if you want to build your own customized table, this resource would be an IDEAL starting point for you. This is a very simplistic approach to the one hashtable philosophy.
I am pretty sure [hash]tables are about mapping big integers (StringHash, GetHandleId) to struct instances (integers), primitive types and all the other types hashtables can save.
And the "one hashtable philosophy" comes from the fact that usually one of the two keys of the hashtable is unused, e.g mapping hex digits to integers:
JASS:
...
call SaveInteger(ht, /*unused*/0, StringHash("A"), 10)
call SaveInteger(ht, /*unused*/0, StringHash("B"), 11)
...
set hex_ord = LoadInteger(ht, /*unused*/0, StringHash(hex_digit))

Your tables seem to be more like arrays:
JASS:
public method operator[] takes integer ind returns $TYPE_LOWER$
    if (not(this.hasValueAt(ind))) then
        call BJDebugMsg("Table error: No value at element " + I2S(ind) + " when trying to access element, report this bug to the map maker!")
    endif

    return Load$ACCSESSOR$(hashtables, this.tableInd, ind)
endmethod

//DO NOT use this method for expanding the table, use push instead!
public method operator[]= takes integer ind, $TYPE_LOWER$ value returns nothing
    if (not(this.hasValueAt(ind))) then
        call BJDebugMsg("Table error: No value at element " + I2S(ind) + " when trying to mutate element, report this bug to the map maker!")
        return
    endif

    call Save$ACCSESSOR$(hashtables, this.tableInd, ind, value)
endmethod

I.e you explicitly forbid inserting/modifing values at "random" indicies unless they are less then the size of the array which grows with the push method:
JASS:
public method push takes $TYPE_LOWER$ value returns nothing
    call Save$ACCSESSOR$(hashtables, this.tableInd, this.values, value)

    set this.values = this.values + 1
endmethod

Create a simple library that's easy to read and understand
Can confirm.

The chained destruction (array of array of trigger, from the demo) is also kind of interesting, I suppose.
 
I am pretty sure [hash]tables are about mapping big integers (StringHash, GetHandleId) to struct instances (integers), primitive types and all the other types hashtables can save.
And the "one hashtable philosophy" comes from the fact that usually one of the two keys of the hashtable is unused, e.g mapping hex digits to integers:
JASS:
...
call SaveInteger(ht, /*unused*/0, StringHash("A"), 10)
call SaveInteger(ht, /*unused*/0, StringHash("B"), 11)
...
set hex_ord = LoadInteger(ht, /*unused*/0, StringHash(hex_digit))

Your tables seem to be more like arrays:
JASS:
public method operator[] takes integer ind returns $TYPE_LOWER$
    if (not(this.hasValueAt(ind))) then
        call BJDebugMsg("Table error: No value at element " + I2S(ind) + " when trying to access element, report this bug to the map maker!")
    endif

    return Load$ACCSESSOR$(hashtables, this.tableInd, ind)
endmethod

//DO NOT use this method for expanding the table, use push instead!
public method operator[]= takes integer ind, $TYPE_LOWER$ value returns nothing
    if (not(this.hasValueAt(ind))) then
        call BJDebugMsg("Table error: No value at element " + I2S(ind) + " when trying to mutate element, report this bug to the map maker!")
        return
    endif

    call Save$ACCSESSOR$(hashtables, this.tableInd, ind, value)
endmethod

I.e you explicitly forbid inserting/modifing values at "random" indicies unless they are less then the size of the array which grows with the push method:
JASS:
public method push takes $TYPE_LOWER$ value returns nothing
    call Save$ACCSESSOR$(hashtables, this.tableInd, this.values, value)

    set this.values = this.values + 1
endmethod


Can confirm.

The chained destruction (array of array of trigger, from the demo) is also kind of interesting, I suppose.

Should I call this Array<T>? Would that be a better name?

Also, there's another reason to do it this way. It grants mobility by it being a class rather than an array which you can't pass around so easilly
 
Last edited:
You should name it whatever makes sense to you. Its your call.

PS: an attempt of mine of an easy table (shameless plug)

I'm considering now that I've done all this work, making a simple hashtable struct to go along with this.

Gonna call it map

Probably also gonna make one that works with any two handle types.

Edit: Make that I'll make three, one that maps value types to value, value to handle, handle to handle, handle to value, struct to value, etc

Edit2: actually, I might pay for some overhead, but might it be wiser at this point to just switch to the philosophy where all native types are encapsulated by object? So I can just code the datastructures once and they take type "object"? Or will this ultimately be too much overhead...... hmmmm

Edit3: I see the problem with the idea now.... You can't have an interface method without a return type can you? You could get away doing it with handle types, but I'm certain the native types you're screwed. Kinda breaks the idea in its entirety....

Edit4: Though, that doesn't really stop me from making the Object Struct for just handles. Maybe I can work with that. It would reduce SOME work...

Edit5: Okay nevermind. Really this would be entirely pointless to essentially recreate Java here XD
 
Last edited:
Status
Not open for further replies.
Top