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

[Lua][vJass] New Table

BBQ

BBQ

Level 4
Joined
Jun 7, 2011
Messages
97
They are non-debug on wc3c.net, which confuses me, it's as if he tested it on this one and didn't test it on that one.

Alright, that makes sense. I may have actually had the version from here, but altered the names myself.

I knew there were such checks (and I actually thought they were non-debug, which they are in the Wc3C version) and that I was exceeding the limit, but for some reason I disregarded them and thought they weren't even working. Silly me.

And that's what you get for having to fulfill each site's "requirements" and post different versions of your libraries ...
 
Last edited:

BBQ

BBQ

Level 4
Joined
Jun 7, 2011
Messages
97
It doesn't make sense that you changed the names :p
Why not? Array and DualArray are more appealing to me (although they may not be technically correct). I find myself changing the names of resources quite often, especially method names.

I had also removed all of the implicit struct to integer and integer to struct typecasting. It may sound silly, but I tend to do such stuff (well, I also do some "bigger" modifications if I consider them essential).

I guess you thought they worked the exact same way or something?
No, I knew that some checks were made debug-only in this version, I just thought that the size limit would be enforced outside of debug mode as well (but for some reason couldn't be arsed to read the code and see that it's not).

I am also inclined towards leaving most of the checks as debug-only (which is why I had taken the version from here in the first place), but I do make the more crucial ones work outside of debug mode as well ...

It was just a misunderstanding, I guess. Again, sorry about it.
 
Level 10
Joined
May 27, 2009
Messages
494
Level 10
Joined
May 27, 2009
Messages
494
well i like anitarf's recipe sys api more xD
well just using your streak system so i use the this table but the recipe library requires teh HandleTable D: but i'm going nuts checking on a way to use this Table's function instead of HandleTable (even though i can just use vex' handletable)
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,464
Looking over Artificial's system it won't work because it uses the .flush()
method from a normal Table which will throw syntax errors with the one
I wrote.

Change Artificial's library to use .remove() instead of .flush() from the
ING_TABLE and RES_TABLE. You can keep it with the COMBINE_TABLE
because that one already supports the .flush() method of Vexorian's
HandleTable.
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,464
I got a new idea: a configurable constant for the user to set the first index of dynamically-generated Tables. I think I would just start it at 8191 by default.

That way, you could just declare Table instances from a globals block, and use the "key" type to generate your index:

JASS:
globals
    private constant key MyTableKey
    private Table MyTable = MyTableKey //Boom, your Table is now declared in the globals block, instead of requiring an initializer to do this.
endglobals

TableArrays could not be done like this, but the Tables themselves will work just fine this way. There shouldn't be more than a few hundred keys max, so the default 8191 index is a very safe number which won't conflict in any reasonable scenario.

If you are using structs, you can take advantage of that otherwise-useless struct integer, instead of declaring the "key" (because keys and struct integers share the same index space):

JASS:
struct MyStruct extends array
    static Table table = MyStruct.typeid
endstruct

I am gonna try something crazy, but I don't know if it will work.

Ideally, this would let you create a Table instance from its declaration in the globals block.

From: http://www.wc3c.net/vexorian/jasshelpermanual.html#slk

I would have to look into it further. Tonight.

Edit: Looking into it further, this won't work. Plus, the SLK's are published after library and struct init, and the user has to specify an exact key to use for each index. So this kinda sux.

It would mostly be used for something like a BonusMod system.
 
That could cause a lot of conflicts :eek:

JASS:
globals
    private Table tb
    private constant key keyTable1
    private constant key keyTable2
    private Table tb2 = keyTable1
    private Table tb3 = keyTable2
endglobals

private module Inits
    private static method onInit takes nothing returns nothing
        set tb = Table.create()
    endmethod
endmodule

One of the tables created using the key is going to point to tb :/
 
My bad, I didn't know you were going to change Table so that it starts allocating at 8191 (I just noticed you said that above, and I have no idea why I didn't acknowledge it >.<)

Could you add backwards compatibility with Vexorian's Table in the form of an optional textmacro? (Sort of like before)

There are a couple of users complaining about the Table I'm using in the StreakSystem thread :/
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,464
Well TableBC does work if the the .flush method is used in the older scripts.

The TableBC library:
JASS:
library TableBC requires Table
/*
    Backwards-compatibility add-on for scripts employing Vexorian's Table.
    
    Disclaimer:
    
    The following error does not occur with HandleTables & StringTables, only
    with the standard, integer-based Table, so you do not need to make any 
    changes to StringTable/HandleTable-employing scripts.
    
    The this.flush(key) method from the original Table cannot be parsed with
    the new Table. For the scripts that use this method, they need to be up-
    dated to use the more fitting this.remove(key) method.
    
    Please don't try using StringTables/HandleTables with features exclusive
    to the new Table as they will cause syntax errors. I do not have any plan
    to endorse these types of Tables because delegation in JassHelper is not 
    advanced enough for three types of Tables without copying every single
    method over again (as you can see this already generates plenty of code).
    StringTable & HandleTable are wrappers for StringHash & GetHandleId, so
    just type them out.
*/

//! textmacro TABLE_BC_METHODS
    method reset takes nothing returns nothing
        call this.flush()
    endmethod
    method exists takes integer key returns boolean
        return this.has(key)
    endmethod
//! endtextmacro

//! textmacro TABLE_BC_STRUCTS
struct HandleTable extends array
    method operator [] takes handle key returns integer
        return Table(this)[GetHandleId(key)]
    endmethod
    method operator []= takes handle key, integer value returns nothing
        set Table(this)[GetHandleId(key)] = value
    endmethod
    method flush takes handle key returns nothing
        call Table(this).remove(GetHandleId(key))
    endmethod
    method exists takes handle key returns boolean
        return Table(this).has(GetHandleId(key))
    endmethod
    method reset takes nothing returns nothing
        call Table(this).flush()
    endmethod
    method destroy takes nothing returns nothing
        call Table(this).destroy()
    endmethod
    static method create takes nothing returns thistype
        return Table.create()
    endmethod
endstruct

struct StringTable extends array
    method operator [] takes string key returns integer
        return Table(this)[StringHash(key)]
    endmethod
    method operator []= takes string key, integer value returns nothing
        set Table(this)[StringHash(key)] = value
    endmethod
    method flush takes string key returns nothing
        call Table(this).remove(StringHash(key))
    endmethod
    method exists takes string key returns boolean
        return Table(this).has(StringHash(key))
    endmethod
    method reset takes nothing returns nothing
        call Table(this).flush()
    endmethod
    method destroy takes nothing returns nothing
        call Table(this).destroy()
    endmethod
    static method create takes nothing returns thistype
        return Table.create()
    endmethod
endstruct
//! endtextmacro

endlibrary
 

BBQ

BBQ

Level 4
Joined
Jun 7, 2011
Messages
97
Edit: This would need to use keys, because keys and structs do not share the same integer generator.
Using a struct's typeid as another struct's index is ridiculously stupid anyway. Also, the typeid is nowhere near useless; but you may think it is as you're one of the people who never take advantage of the pseudo-inheritance JassHelper offers.
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,464
I have taken advantage of psuedo-inheritance before, back in the days when I thought everything in vJass was good programming practice, but I have never needed the ".getType()" feature nor the .typeid constant even then.

It is 100% useless to generate it for a struct which extends array, but JassHelper does it anyway.

And I agree that it is bad practice to use .typeid for such a purpose, but I was thinking of saving variable space (not that it matters though, since the optimizer is supposed to kill those constants)

Edit: I am gonna compile this first, but this is what I plan to update from the current version of Table:

JASS:
library Table /* made by Bribe, special thanks to Vexorian & Nestharus, version 3.1.0.0
    
    One map, one hashtable. Welcome to NewTable 3.1
    
    This library was originally called NewTable so it didn't conflict with
    the API of Table by Vexorian. However, the damage is done and it's too
    late to change the library name now. To help with damage control, I
    have provided an extension library called TableBC, which bridges all
    the functionality of Vexorian's Table except for 2-D string arrays &
    the ".flush(integer)" method. I use ".flush()" to flush a child hash-
    table, because I wanted the API in NewTable to reflect the API of real
    hashtables (I thought this would be more intuitive).
    
    API
    
    ------------
    struct Table
    | static method create takes nothing returns Table
    |     create a new Table
    |    
    | method destroy takes nothing returns nothing
    |     destroy it
    |    
    | method flush takes nothing returns nothing
    |     flush all stored values inside of it
    |    
    | method remove takes integer key returns nothing
    |     remove the value at index "key"
    |    
    | method operator []= takes integer key, $TYPE$ value returns nothing
    |     assign "value" to index "key"
    |    
    | method operator [] takes integer key returns $TYPE$
    |     load the value at index "key"
    |    
    | method has takes integer key returns boolean
    |     whether or not the key was assigned
    |
    ----------------
    struct TableArray
    | static method operator [] takes integer array_size returns TableArray
    |     create a new array of Tables of size "array_size"
    |
    | method destroy takes nothing returns nothing
    |     destroy it
    |
    | method flush takes nothing returns nothing
    |     flush and destroy it
    |
    | method operator size takes nothing returns integer
    |     returns the size of the TableArray
    |
    | method operator [] takes integer key returns Table
    |     returns a Table accessible exclusively to index "key"
*/
    
globals
    private integer less = 0    //Index generation for TableArrays (below 0).
    private integer more = 8190 //Index generation for Tables.
    //Configure it if you use more than 8190 "key" variables in your map (this will never happen though).
    
    private hashtable ht = InitHashtable()
    private key sizeK
    private key listK
endglobals
    
private struct dex extends array
    static method operator size takes nothing returns Table
        return sizeK
    endmethod
    static method operator list takes nothing returns Table
        return listK
    endmethod
endstruct
    
private struct handles extends array
    method has takes integer key returns boolean
        return HaveSavedHandle(ht, this, key)
    endmethod
    method remove takes integer key returns nothing
        call RemoveSavedHandle(ht, this, key)
    endmethod
endstruct
    
private struct agents extends array
    method operator []= takes integer key, agent value returns nothing
        call SaveAgentHandle(ht, this, key, value)
    endmethod
endstruct
    
//! textmacro NEW_ARRAY_BASIC takes SUPER, FUNC, TYPE
private struct $TYPE$s extends array
    method operator [] takes integer key returns $TYPE$
        return Load$FUNC$(ht, this, key)
    endmethod
    method operator []= takes integer key, $TYPE$ value returns nothing
        call Save$FUNC$(ht, this, key, value)
    endmethod
    method has takes integer key returns boolean
        return HaveSaved$SUPER$(ht, this, key)
    endmethod
    method remove takes integer key returns nothing
        call RemoveSaved$SUPER$(ht, this, key)
    endmethod
endstruct
private module $TYPE$m
    method operator $TYPE$ takes nothing returns $TYPE$s
        return this
    endmethod
endmodule
//! endtextmacro
    
//! textmacro NEW_ARRAY takes FUNC, TYPE
private struct $TYPE$s extends array
    method operator [] takes integer key returns $TYPE$
        return Load$FUNC$Handle(ht, this, key)
    endmethod
    method operator []= takes integer key, $TYPE$ value returns nothing
        call Save$FUNC$Handle(ht, this, key, value)
    endmethod
endstruct
private module $TYPE$m
    method operator $TYPE$ takes nothing returns $TYPE$s
        return this
    endmethod
endmodule
//! endtextmacro
    
//Run these textmacros to include the entire hashtable API as wrappers.
//Don't be intimidated by the number of macros - Vexorian's map optimizer is
//supposed to kill functions which inline (all of these functions inline).
//! runtextmacro NEW_ARRAY_BASIC("Real", "Real", "real")
//! runtextmacro NEW_ARRAY_BASIC("Boolean", "Boolean", "boolean")
//! runtextmacro NEW_ARRAY_BASIC("String", "Str", "string")
    
//! runtextmacro NEW_ARRAY("Player", "player")
//! runtextmacro NEW_ARRAY("Widget", "widget")
//! runtextmacro NEW_ARRAY("Destructable", "destructable")
//! runtextmacro NEW_ARRAY("Item", "item")
//! runtextmacro NEW_ARRAY("Unit", "unit")
//! runtextmacro NEW_ARRAY("Ability", "ability")
//! runtextmacro NEW_ARRAY("Timer", "timer")
//! runtextmacro NEW_ARRAY("Trigger", "trigger")
//! runtextmacro NEW_ARRAY("TriggerCondition", "triggercondition")
//! runtextmacro NEW_ARRAY("TriggerAction", "triggeraction")
//! runtextmacro NEW_ARRAY("TriggerEvent", "event")
//! runtextmacro NEW_ARRAY("Force", "force")
//! runtextmacro NEW_ARRAY("Group", "group")
//! runtextmacro NEW_ARRAY("Location", "location")
//! runtextmacro NEW_ARRAY("Rect", "rect")
//! runtextmacro NEW_ARRAY("BooleanExpr", "boolexpr")
//! runtextmacro NEW_ARRAY("Sound", "sound")
//! runtextmacro NEW_ARRAY("Effect", "effect")
//! runtextmacro NEW_ARRAY("UnitPool", "unitpool")
//! runtextmacro NEW_ARRAY("ItemPool", "itempool")
//! runtextmacro NEW_ARRAY("Quest", "quest")
//! runtextmacro NEW_ARRAY("QuestItem", "questitem")
//! runtextmacro NEW_ARRAY("DefeatCondition", "defeatcondition")
//! runtextmacro NEW_ARRAY("TimerDialog", "timerdialog")
//! runtextmacro NEW_ARRAY("Leaderboard", "leaderboard")
//! runtextmacro NEW_ARRAY("Multiboard", "multiboard")
//! runtextmacro NEW_ARRAY("MultiboardItem", "multiboarditem")
//! runtextmacro NEW_ARRAY("Trackable", "trackable")
//! runtextmacro NEW_ARRAY("Dialog", "dialog")
//! runtextmacro NEW_ARRAY("Button", "button")
//! runtextmacro NEW_ARRAY("TextTag", "texttag")
//! runtextmacro NEW_ARRAY("Lightning", "lightning")
//! runtextmacro NEW_ARRAY("Image", "image")
//! runtextmacro NEW_ARRAY("Ubersplat", "ubersplat")
//! runtextmacro NEW_ARRAY("Region", "region")
//! runtextmacro NEW_ARRAY("FogState", "fogstate")
//! runtextmacro NEW_ARRAY("FogModifier", "fogmodifier")
//! runtextmacro NEW_ARRAY("Hashtable", "hashtable")
    
struct Table extends array
    
    // Implement modules for intuitive syntax (tb.handle; tb.unit; etc.)
    implement realm
    implement booleanm
    implement stringm
    implement playerm
    implement widgetm
    implement destructablem
    implement itemm
    implement unitm
    implement abilitym
    implement timerm
    implement triggerm
    implement triggerconditionm
    implement triggeractionm
    implement eventm
    implement forcem
    implement groupm
    implement locationm
    implement rectm
    implement boolexprm
    implement soundm
    implement effectm
    implement unitpoolm
    implement itempoolm
    implement questm
    implement questitemm
    implement defeatconditionm
    implement timerdialogm
    implement leaderboardm
    implement multiboardm
    implement multiboarditemm
    implement trackablem
    implement dialogm
    implement buttonm
    implement texttagm
    implement lightningm
    implement imagem
    implement ubersplatm
    implement regionm
    implement fogstatem
    implement fogmodifierm
    implement hashtablem
    
    method operator handle takes nothing returns handles
        return this
    endmethod
    
    method operator agent takes nothing returns agents
        return this
    endmethod
    
    //set this = tb[GetSpellAbilityId()]
    method operator [] takes integer key returns Table
        return LoadInteger(ht, this, key)
    endmethod
    
    //set tb[389034] = 8192
    method operator []= takes integer key, Table tb returns nothing
        call SaveInteger(ht, this, key, tb)
    endmethod
    
    //set b = tb.has(2493223)
    method has takes integer key returns boolean
        return HaveSavedInteger(ht, this, key)
    endmethod
    
    //call tb.remove(294080)
    method remove takes integer key returns nothing
        call RemoveSavedInteger(ht, this, key)
    endmethod
    
    //Remove all data from a Table instance
    method flush takes nothing returns nothing
        call FlushChildHashtable(ht, this)
    endmethod
    
    //local Table tb = Table.create()
    static method create takes nothing returns Table
        local Table this = dex.list[0]
        
        if this == 0 then
            set this = more + 1
            set more = this
        else
            set dex.list[0] = dex.list[this]
            call dex.list.remove(this) //Clear hashed memory
        endif
        
        debug set dex.list[this] = -1
        return this
    endmethod
    
    // Removes all data from a Table instance and recycles its index.
    //
    //     call tb.destroy()
    //
    method destroy takes nothing returns nothing
        debug if dex.list[this] != -1 then
            debug call BJDebugMsg("Table Error: Tried to double-free instance: " + I2S(this))
            debug return
        debug endif
        
        call this.flush()
        
        set dex.list[this] = dex.list[0]
        set dex.list[0] = this
    endmethod
    
    //! runtextmacro optional TABLE_BC_METHODS()
endstruct
    
//! runtextmacro optional TABLE_BC_STRUCTS()
    
struct TableArray extends array
    
    //Returns a new TableArray to do your bidding. Simply use:
    //
    //    local TableArray ta = TableArray[array_size]
    //
    static method operator [] takes integer array_size returns TableArray
        local Table tb = dex.size[array_size] //Get the unique recycle list for this array size
        local TableArray this = tb[0]         //The last-destroyed TableArray that had this array size
        
        debug if array_size <= 0 then
            debug call BJDebugMsg("TypeError: Invalid specified TableArray size: " + I2S(array_size))
            debug return 0
        debug endif
        
        if this == 0 then
            set this = less - array_size
            set less = this
        else
            set tb[0] = tb[this]  //Set the last destroyed to the last-last destroyed
            call tb.remove(this)  //Clear hashed memory
        endif
        
        set dex.size[this] = array_size //This remembers the array size
        return this
    endmethod
    
    //Returns the size of the TableArray
    method operator size takes nothing returns integer
        return dex.size[this]
    endmethod
    
    //This magic method enables two-dimensional[array][syntax] for Tables,
    //similar to the two-dimensional utility provided by hashtables them-
    //selves.
    //
    //ta[integer a].unit[integer b] = unit u
    //ta[integer a][integer c] = integer d
    //
    //Inline-friendly when not running in debug mode
    //
    method operator [] takes integer key returns Table
        static if DEBUG_MODE then
            local integer i = this.size
            if i == 0 then
                call BJDebugMsg("IndexError: Tried to get key from invalid TableArray instance: " + I2S(this))
                return 0
            elseif key < 0 or key >= i then
                call BJDebugMsg("IndexError: Tried to get key [" + I2S(key) + "] from outside TableArray bounds: " + I2S(i))
                return 0
            endif
        endif
        return this + key
    endmethod
    
    //Destroys a TableArray without flushing it; I assume you call .flush()
    //if you want it flushed too. This is a public method so that you don't
    //have to loop through all TableArray indices to flush them if you don't
    //need to (ie. if you were flushing all child-keys as you used them).
    //
    method destroy takes nothing returns nothing
        local Table tb = dex.size[this.size]
        
        debug if this.size == 0 then
            debug call BJDebugMsg("TypeError: Tried to destroy an invalid TableArray: " + I2S(this))
            debug return
        debug endif
        
        if tb == 0 then
            //Create a Table to index recycled instances with their array size
            set tb = Table.create()
            set dex.size[this.size] = tb
        endif
        
        call dex.size.remove(this) //Clear the array size from hash memory
        
        set tb[this] = tb[0]
        set tb[0] = this
    endmethod
    
    //All you need to know about this one is that it won't hit the op limit.
    private static method clean takes Table tb, integer end returns nothing
        local integer i = tb + 0x1000
        if i < end then
            call clean.evaluate(i, end)
            set end = i
        endif
        loop
            call tb.flush()
            set tb = tb + 1
            exitwhen tb == end
        endloop
    endmethod
    
    //Flushes the TableArray and also destroys it. Doesn't get any more
    //similar to the FlushParentHashtable native than this.
    //
    method flush takes nothing returns nothing
        local integer end = this.size + this
        debug if this == end then
            debug call BJDebugMsg("TypeError: Tried to flush an invalid TableArray instance: " + I2S(this))
            debug return
        debug endif
        call clean.evaluate(this, end)
        call this.destroy()
    endmethod
    
endstruct
    
endlibrary

JASS:
library TableBC requires Table
/*
    Backwards-compatibility add-on for scripts employing Vexorian's Table.
    
    Disclaimer:
    
    The following error does not occur with HandleTables & StringTables, only
    with the standard, integer-based Table, so you do not need to make any 
    changes to StringTable/HandleTable-employing scripts.
    
    The this.flush(key) method from the original Table cannot be parsed with
    the new Table. For the scripts that use this method, they need to be up-
    dated to use the more fitting this.remove(key) method.
    
    Please don't try using StringTables/HandleTables with features exclusive
    to the new Table as they will cause syntax errors. I do not have any plan
    to endorse these types of Tables because delegation in JassHelper is not 
    advanced enough for three types of Tables without copying every single
    method over again (as you can see this already generates plenty of code).
    StringTable & HandleTable are wrappers for StringHash & GetHandleId, so
    just type them out.
*/

//! textmacro TABLE_BC_METHODS
    method reset takes nothing returns nothing
        call this.flush()
    endmethod
    method exists takes integer key returns boolean
        return this.has(key)
    endmethod
//! endtextmacro

//! textmacro TABLE_BC_STRUCTS
struct HandleTable extends array
    method operator [] takes handle key returns integer
        return Table(this)[GetHandleId(key)]
    endmethod
    method operator []= takes handle key, integer value returns nothing
        set Table(this)[GetHandleId(key)] = value
    endmethod
    method flush takes handle key returns nothing
        call Table(this).remove(GetHandleId(key))
    endmethod
    method exists takes handle key returns boolean
        return Table(this).has(GetHandleId(key))
    endmethod
    method reset takes nothing returns nothing
        call Table(this).flush()
    endmethod
    method destroy takes nothing returns nothing
        call Table(this).destroy()
    endmethod
    static method create takes nothing returns thistype
        return Table.create()
    endmethod
endstruct

struct StringTable extends array
    method operator [] takes string key returns integer
        return Table(this)[StringHash(key)]
    endmethod
    method operator []= takes string key, integer value returns nothing
        set Table(this)[StringHash(key)] = value
    endmethod
    method flush takes string key returns nothing
        call Table(this).remove(StringHash(key))
    endmethod
    method exists takes string key returns boolean
        return Table(this).has(StringHash(key))
    endmethod
    method reset takes nothing returns nothing
        call Table(this).flush()
    endmethod
    method destroy takes nothing returns nothing
        call Table(this).destroy()
    endmethod
    static method create takes nothing returns thistype
        return Table.create()
    endmethod
endstruct
//! endtextmacro

endlibrary
 
Last edited:

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,464
I have thoroughly tested it and there were no errors. Go me. So Table is now updated to version 3.1.

New features:

- Brought back the TableBC library
- You can now use the "key" type to generate Table instances, eliminating the need for initializers to create them.
- Added a configurable value where you can choose the index where Tables get generated from, in case you need more than 8190 keys for example (when will this ever happen though).

Edit to 3.1.0.1 -

Removed an .evaluate call from the TableArray struct. Table is now even lighter to implement than before.
 
Last edited:
Level 29
Joined
Mar 10, 2009
Messages
5,016
I have a question and it really bothers me...
I didnt see that this system works like the normal hash coz saved ID's will overwrite the first one, see script...
JASS:
scope CTest initializer init

globals
    Table ai
endglobals

private function init takes nothing returns nothing
    local timer t
    local integer i = 4
    local integer id
    set ai = Table.create()
    loop
        set t = CreateTimer()
        set id = GetHandleId(t)
        set ai[id] = 1
        set ai[id] = 2 //this overwrites first ai[id]
        call BJDebugMsg(I2S(ai[id])) //displays 2   
        set i = i-1
        exitwhen i==0
    endloop   
endfunction

endscope

in view of this do I really need to create Table for each?, like...
JASS:
set ai = Table.create()
set ai2 = Table.create()

in normal hash, we know its done like this, as long as you have the correct childID, then no problem...
JASS:
call SaveInteger(HASH, Parent, 1, 5)
call SaveInteger(HASH, Parent, 2, 7)
call SaveInteger(HASH, Parent, 3, 9)

can it not be like set ai[id+1] = 2, set ai[id+2] = 2, etc...
 
Level 6
Joined
Jun 20, 2011
Messages
249
Yes you've mistaken the use of Table.
local Table tb = Table.create()
works the same as
local integer array tb
Notice that this one is an array and the Table above isn't. But both work as an monodimentional array.
local Table array tb
Now that's a bidimentional array...

And who would use a local table anyways?
Table exists for 2 purposes:
1.- Arrays for struct instances: sometimes you need to store a bunch of data into a struct instance (this) and the only way to do it is using a Table
JASS:
static method create takes nothing returns thistype
    local thistype this = allocate()
    set this.tb = Table.create()
    set this.tb[1] = 3
    set this.tb[2] = 29
    //etc...
endmethod
2..- Using handles or rawcodes as array indexes
tb['hfoo'] = 3

If used properly you would never need another hashtable, ever.

Now a question to you:
How does...
JASS:
        set ai[id] = 1
        set ai[id] = 2 //this overwrites first ai[id]
... makes sense anyways? how would you differ which instance holds 1 and which holds 2? Remember that coding's dogma is based in pure logic, if something makes sense is codeable.
Notice that in your hashtable API example you're doing this:
JASS:
call SaveInteger(HASH, Parent, 1, 5)
call SaveInteger(HASH, Parent, 2, 7)
call SaveInteger(HASH, Parent, 3, 9)
You assing a child index to each var (1,2 and 3) to store the different values (5,7 and 9) while in your example above you aren't.
Dig more into Table's array struct functionallity and you'll discover wonders
 
Level 29
Joined
Mar 10, 2009
Messages
5,016
Pls take note that Im NOT making local Tables in the script I posted...I am
fully aware that locals can change its value within the function...

makes sense anyways? how would you differ which instance holds 1 and which holds 2?

that's precisely my point, 'childID's', why can't it be indexed like the normal hash?...
that'w why in my last statement I wrote like this...
can it not be like set ai[id+1] = 2 , set ai[id+2] = 2 , etc...

and there's nothing wrong in using global Table coz it really worked in
my map and no need for extra hashtables...
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,464
I think what you want is the TableArray, which is also built-in to the system:

JASS:
call SaveInteger(HASH, Parent, 1, 5)
call SaveInteger(HASH, Parent, 2, 7)
call SaveInteger(HASH, Parent, 3, 9)
->
set TA[Parent][1] = 5
set TA[Parent][2] = 7
set TA[Parent][3] = 9

TableArrays are awesome. You can even create them and destroy them and have pretty much unlimited instances of them.

JASS:
set ht = InitHashtable()
->
set ta = TableArray[8192]
...
call FlushParentHashtable(ht)
->
call ta.destroy() or ta.flush()

You can only have 2^8 hashtables, but you can have almost 2^18 TableArrays with size 8192... by the time you get that kind of number and fill it up with stuff your RAM has probably maxed out anyway ;)
 
Last edited:
TableArray has a limit size of ... nothing ;D

edit
Ok, technically speaking, it's 2147483647
But I wouldn't do that if I were you :p
That would consume the entire space.
All TableArrays share the same index space and it has to be lower than 2147483647
Usually, 8192 is a decent indexing space for Tables.
If you have one index that's going to be low and another that's going to be high, you should declare the TableArray with a low size (for the low indices) and use the second parameter ([]) for the high values.

Having high values on both ends wont be a problem either.
Just declare a TableArray with 10000000 instances ;D
(For handle ids, declare it with 1200000)

edit
Or better yet, declare it with 50000 instances and just subtract 0x100000 from the Handle Ids :D
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,464
I generally recommend you keep it less than a few million or billion, each TableArray. You can have about 2,000 TableArrays sized 1 billion each.

But the thing is the highest I've seen people go with TableArrays is 8192, and you can have 2^18 of those which is way crazy numbers (the same size as a JASS array). It acts as an array of Tables, with the advantage of not needing to technically be a "JASS array".
 
Level 29
Joined
Mar 10, 2009
Messages
5,016
if that's the case then awesome, Im asking coz handle Id's are huge numbers and the
sample is only 8190, so I need to extend it to millions...
But it can be reduced using RawCodeIndexer, hoping that it will not bug
in the long term, coz Ima be dissapointed Mags :p...
JASS:
local timer t
    local integer i = 6
    local integer id
    set ai = TableArray[200]
    loop
        set t = CreateTimer()
        set id = RawCode2Id(GetHandleId(t))
        //without RawCode2Id, it will display error since
        //tablearray limit is 200, and id starts at 1049555
        set ai[GetRawCodeId(id)][1] = 1
        set ai[GetRawCodeId(id)][2] = 2
        call BJDebugMsg(I2S(ai[GetRawCodeId(id)][1]))
        call BJDebugMsg(I2S(ai[GetRawCodeId(id)][2]))
        set t = null
        exitwhen i==0
    endloop
 
Top