Warcraft 3 documentation

vJASS & Zinc Documentation
For the latest documentation about how it works vJASS and Zinc language layers for Warcraft III, please follow these links:
Jasshelper documentation - Zinc documentation - WC3 Optimizer documentation

[Snippet] New Table

moyack · 984

0 Members and 1 Guest are viewing this topic.

[Snippet] New Table
on: March 21, 2012, 03:44:14 AM
Category: Execution, Variables
Language: vJASS

Table is based on the philosophy that you can use one hashtable for your whole map. What it does is divide one hashtable into many different components, and each system in the map can have its own share of the hashtable. Taking advantage of parent keys and child keys to their fullest extent, the ability to have 1 hashtable for the whole map can now be realized.

I came up with the idea for this project after using Vexorian's Table and hitting the limits a number of times. All of those limitations have been fulfilled by this project:

You have access to all the hashtable API, so you can now save handles, booleans, reals, strings and integers, instead of just integers.
You can have up to 2 ^ 31 - 1 Table instances. Previously, you could have 400,000 if you set the constant appropriately, but that generates hundreds of lines of code. This means you don't ever have to worry about creating too many Tables, because you can never really have too many.
2-D array syntax is perfected and allows you to create things called TableArrays. The old method used the volatile StringHash, which easily bypasses the integer limit and starts saving into unpredictable places. This is dangerous when using a shared hashtable because you could overwrite someone else's data without even knowing it.
Table instances can save/load data from within module initializers. This didn't work before because the hashtable was initialized from a struct instead of from the globals block.

You can only have 256 hashtables at a time, so with 2 ^ 31 - 1 Table instances at your disposal and (that's right, I said "and", not "or") roughly 2 ^ 18 TableArray instances with array size 8192 (JASS max array size), you will find yourself with more storage options than you know what to do with.

If you take advantage of this system to its fullest, you will never need to call InitHashtable() again.

How it works
The basis of how it works is this: you often run into situations where you have no use for two keys (only a single key). Usually you just waste a key as 0 and run everything else through child-keys. This system (as well as Vexorian's Table) simply gives you a parent-key to use in a globally-shared hashtable. Just initialize an Table instance via Table.create().

But sometimes you need more than that, and both keys actually mean something to you. Usually the parent-key would be "this" from a struct and the child-keys are various other bits. A TableArray - an array of Tables - is a great way to achieve this. Instanciate a TableArray via TableArray[16] for an array of Tables sized 16, or TableArray[0x2000] for an array of Tables with the same size as a normal JASS array. The size can be very large if you want, but to be practical keep it smaller than a few million, because the total accumulated size of all your TableArrays must remain under 2 ** 31 - 1 (a little more than 2 billion) because that's the limit of how high integers can go.

If you're dealing with more randomly-accessed numbers or consistently very large indices in the parent-key field and couldn't previously accomplish it with a pre-sized TableArray, I have (on July 21, 2015) updated this to NewTable 4.0 where you can instantiate HashTables to do just that!

I now imagine this a completed project, so please let me know if there's more you'd like to see in the future and I'll take it into consideration.

Code: jass
  1. library Table /* made by Bribe, special thanks to Vexorian & Nestharus, version 4.1.0.1.
  2.    
  3.     One map, one hashtable. Welcome to NewTable 4.1.0.1
  4.    
  5.     This newest iteration of Table introduces the new HashTable struct.
  6.     You can now instantiate HashTables which enables the use of large
  7.     parent and large child keys, just like a standard hashtable. Previously,
  8.     the user would have to instantiate a Table to do this on their own which -
  9.     while doable - is something the user should not have to do if I can add it
  10.     to this resource myself (especially if they are inexperienced).
  11.    
  12.     This library was originally called NewTable so it didn't conflict with
  13.     the API of Table by Vexorian. However, the damage is done and it's too
  14.     late to change the library name now. To help with damage control, I
  15.     have provided an extension library called TableBC, which bridges all
  16.     the functionality of Vexorian's Table except for 2-D string arrays &
  17.     the ".flush(integer)" method. I use ".flush()" to flush a child hash-
  18.     table, because I wanted the API in NewTable to reflect the API of real
  19.     hashtables (I thought this would be more intuitive).
  20.    
  21.     API
  22.    
  23.     ------------
  24.     struct Table
  25.     | static method create takes nothing returns Table
  26.     |     create a new Table
  27.     |  
  28.     | method destroy takes nothing returns nothing
  29.     |     destroy it
  30.     |  
  31.     | method flush takes nothing returns nothing
  32.     |     flush all stored values inside of it
  33.     |  
  34.     | method remove takes integer key returns nothing
  35.     |     remove the value at index "key"
  36.     |  
  37.     | method operator []= takes integer key, $TYPE$ value returns nothing
  38.     |     assign "value" to index "key"
  39.     |  
  40.     | method operator [] takes integer key returns $TYPE$
  41.     |     load the value at index "key"
  42.     |  
  43.     | method has takes integer key returns boolean
  44.     |     whether or not the key was assigned
  45.     |
  46.     ----------------
  47.     struct TableArray
  48.     | static method operator [] takes integer array_size returns TableArray
  49.     |     create a new array of Tables of size "array_size"
  50.     |
  51.     | method destroy takes nothing returns nothing
  52.     |     destroy it
  53.     |
  54.     | method flush takes nothing returns nothing
  55.     |     flush and destroy it
  56.     |
  57.     | method operator size takes nothing returns integer
  58.     |     returns the size of the TableArray
  59.     |
  60.     | method operator [] takes integer key returns Table
  61.     |     returns a Table accessible exclusively to index "key"
  62. */
  63.    
  64. globals
  65.     private integer less = 0    //Index generation for TableArrays (below 0).
  66.     private integer more = 8190 //Index generation for Tables.
  67.     //Configure it if you use more than 8190 "key" variables in your map (this will never happen though).
  68.    
  69.     private hashtable ht = InitHashtable()
  70.     private key sizeK
  71.     private key listK
  72. endglobals
  73.    
  74. private struct dex extends array
  75.     static method operator size takes nothing returns Table
  76.         return sizeK
  77.     endmethod
  78.     static method operator list takes nothing returns Table
  79.         return listK
  80.     endmethod
  81. endstruct
  82.    
  83. private struct handles extends array
  84.     method has takes integer key returns boolean
  85.         return HaveSavedHandle(ht, this, key)
  86.     endmethod
  87.     method remove takes integer key returns nothing
  88.         call RemoveSavedHandle(ht, this, key)
  89.     endmethod
  90. endstruct
  91.    
  92. private struct agents extends array
  93.     method operator []= takes integer key, agent value returns nothing
  94.         call SaveAgentHandle(ht, this, key, value)
  95.     endmethod
  96. endstruct
  97.    
  98. //! textmacro NEW_ARRAY_BASIC takes SUPER, FUNC, TYPE
  99. private struct $TYPE$s extends array
  100.     method operator [] takes integer key returns $TYPE$
  101.         return Load$FUNC$(ht, this, key)
  102.     endmethod
  103.     method operator []= takes integer key, $TYPE$ value returns nothing
  104.         call Save$FUNC$(ht, this, key, value)
  105.     endmethod
  106.     method has takes integer key returns boolean
  107.         return HaveSaved$SUPER$(ht, this, key)
  108.     endmethod
  109.     method remove takes integer key returns nothing
  110.         call RemoveSaved$SUPER$(ht, this, key)
  111.     endmethod
  112. endstruct
  113. private module $TYPE$m
  114.     method operator $TYPE$ takes nothing returns $TYPE$s
  115.         return this
  116.     endmethod
  117. endmodule
  118. //! endtextmacro
  119.    
  120. //! textmacro NEW_ARRAY takes FUNC, TYPE
  121. private struct $TYPE$s extends array
  122.     method operator [] takes integer key returns $TYPE$
  123.         return Load$FUNC$Handle(ht, this, key)
  124.     endmethod
  125.     method operator []= takes integer key, $TYPE$ value returns nothing
  126.         call Save$FUNC$Handle(ht, this, key, value)
  127.     endmethod
  128.     method has takes integer key returns boolean
  129.         return HaveSavedHandle(ht, this, key)
  130.     endmethod
  131.     method remove takes integer key returns nothing
  132.         call RemoveSavedHandle(ht, this, key)
  133.     endmethod
  134. endstruct
  135. private module $TYPE$m
  136.     method operator $TYPE$ takes nothing returns $TYPE$s
  137.         return this
  138.     endmethod
  139. endmodule
  140. //! endtextmacro
  141.    
  142. //Run these textmacros to include the entire hashtable API as wrappers.
  143. //Don't be intimidated by the number of macros - Vexorian's map optimizer is
  144. //supposed to kill functions which inline (all of these functions inline).
  145. //! runtextmacro NEW_ARRAY_BASIC("Real", "Real", "real")
  146. //! runtextmacro NEW_ARRAY_BASIC("Boolean", "Boolean", "boolean")
  147. //! runtextmacro NEW_ARRAY_BASIC("String", "Str", "string")
  148. //New textmacro to allow table.integer[] syntax for compatibility with textmacros that might desire it.
  149. //! runtextmacro NEW_ARRAY_BASIC("Integer", "Integer", "integer")
  150.    
  151. //! runtextmacro NEW_ARRAY("Player", "player")
  152. //! runtextmacro NEW_ARRAY("Widget", "widget")
  153. //! runtextmacro NEW_ARRAY("Destructable", "destructable")
  154. //! runtextmacro NEW_ARRAY("Item", "item")
  155. //! runtextmacro NEW_ARRAY("Unit", "unit")
  156. //! runtextmacro NEW_ARRAY("Ability", "ability")
  157. //! runtextmacro NEW_ARRAY("Timer", "timer")
  158. //! runtextmacro NEW_ARRAY("Trigger", "trigger")
  159. //! runtextmacro NEW_ARRAY("TriggerCondition", "triggercondition")
  160. //! runtextmacro NEW_ARRAY("TriggerAction", "triggeraction")
  161. //! runtextmacro NEW_ARRAY("TriggerEvent", "event")
  162. //! runtextmacro NEW_ARRAY("Force", "force")
  163. //! runtextmacro NEW_ARRAY("Group", "group")
  164. //! runtextmacro NEW_ARRAY("Location", "location")
  165. //! runtextmacro NEW_ARRAY("Rect", "rect")
  166. //! runtextmacro NEW_ARRAY("BooleanExpr", "boolexpr")
  167. //! runtextmacro NEW_ARRAY("Sound", "sound")
  168. //! runtextmacro NEW_ARRAY("Effect", "effect")
  169. //! runtextmacro NEW_ARRAY("UnitPool", "unitpool")
  170. //! runtextmacro NEW_ARRAY("ItemPool", "itempool")
  171. //! runtextmacro NEW_ARRAY("Quest", "quest")
  172. //! runtextmacro NEW_ARRAY("QuestItem", "questitem")
  173. //! runtextmacro NEW_ARRAY("DefeatCondition", "defeatcondition")
  174. //! runtextmacro NEW_ARRAY("TimerDialog", "timerdialog")
  175. //! runtextmacro NEW_ARRAY("Leaderboard", "leaderboard")
  176. //! runtextmacro NEW_ARRAY("Multiboard", "multiboard")
  177. //! runtextmacro NEW_ARRAY("MultiboardItem", "multiboarditem")
  178. //! runtextmacro NEW_ARRAY("Trackable", "trackable")
  179. //! runtextmacro NEW_ARRAY("Dialog", "dialog")
  180. //! runtextmacro NEW_ARRAY("Button", "button")
  181. //! runtextmacro NEW_ARRAY("TextTag", "texttag")
  182. //! runtextmacro NEW_ARRAY("Lightning", "lightning")
  183. //! runtextmacro NEW_ARRAY("Image", "image")
  184. //! runtextmacro NEW_ARRAY("Ubersplat", "ubersplat")
  185. //! runtextmacro NEW_ARRAY("Region", "region")
  186. //! runtextmacro NEW_ARRAY("FogState", "fogstate")
  187. //! runtextmacro NEW_ARRAY("FogModifier", "fogmodifier")
  188. //! runtextmacro NEW_ARRAY("Hashtable", "hashtable")
  189.    
  190. struct Table extends array
  191.    
  192.     // Implement modules for intuitive syntax (tb.handle; tb.unit; etc.)
  193.     implement realm
  194.     implement integerm
  195.     implement booleanm
  196.     implement stringm
  197.     implement playerm
  198.     implement widgetm
  199.     implement destructablem
  200.     implement itemm
  201.     implement unitm
  202.     implement abilitym
  203.     implement timerm
  204.     implement triggerm
  205.     implement triggerconditionm
  206.     implement triggeractionm
  207.     implement eventm
  208.     implement forcem
  209.     implement groupm
  210.     implement locationm
  211.     implement rectm
  212.     implement boolexprm
  213.     implement soundm
  214.     implement effectm
  215.     implement unitpoolm
  216.     implement itempoolm
  217.     implement questm
  218.     implement questitemm
  219.     implement defeatconditionm
  220.     implement timerdialogm
  221.     implement leaderboardm
  222.     implement multiboardm
  223.     implement multiboarditemm
  224.     implement trackablem
  225.     implement dialogm
  226.     implement buttonm
  227.     implement texttagm
  228.     implement lightningm
  229.     implement imagem
  230.     implement ubersplatm
  231.     implement regionm
  232.     implement fogstatem
  233.     implement fogmodifierm
  234.     implement hashtablem
  235.    
  236.     method operator handle takes nothing returns handles
  237.         return this
  238.     endmethod
  239.    
  240.     method operator agent takes nothing returns agents
  241.         return this
  242.     endmethod
  243.    
  244.     //set this = tb[GetSpellAbilityId()]
  245.     method operator [] takes integer key returns Table
  246.         return LoadInteger(ht, this, key) //return this.integer[key]
  247.     endmethod
  248.    
  249.     //set tb[389034] = 8192
  250.     method operator []= takes integer key, Table tb returns nothing
  251.         call SaveInteger(ht, this, key, tb) //set this.integer[key] = tb
  252.     endmethod
  253.    
  254.     //set b = tb.has(2493223)
  255.     method has takes integer key returns boolean
  256.         return HaveSavedInteger(ht, this, key) //return this.integer.has(key)
  257.     endmethod
  258.    
  259.     //call tb.remove(294080)
  260.     method remove takes integer key returns nothing
  261.         call RemoveSavedInteger(ht, this, key) //call this.integer.remove(key)
  262.     endmethod
  263.    
  264.     //Remove all data from a Table instance
  265.     method flush takes nothing returns nothing
  266.         call FlushChildHashtable(ht, this)
  267.     endmethod
  268.    
  269.     //local Table tb = Table.create()
  270.     static method create takes nothing returns Table
  271.         local Table this = dex.list[0]
  272.        
  273.         if this == 0 then
  274.             set this = more + 1
  275.             set more = this
  276.         else
  277.             set dex.list[0] = dex.list[this]
  278.             call dex.list.remove(this) //Clear hashed memory
  279.         endif
  280.        
  281.         debug set dex.list[this] = -1
  282.         return this
  283.     endmethod
  284.    
  285.     // Removes all data from a Table instance and recycles its index.
  286.     //
  287.     //     call tb.destroy()
  288.     //
  289.     method destroy takes nothing returns nothing
  290.         debug if dex.list[this] != -1 then
  291.             debug call BJDebugMsg("Table Error: Tried to double-free instance: " + I2S(this))
  292.             debug return
  293.         debug endif
  294.        
  295.         call this.flush()
  296.        
  297.         set dex.list[this] = dex.list[0]
  298.         set dex.list[0] = this
  299.     endmethod
  300.    
  301.     //! runtextmacro optional TABLE_BC_METHODS()
  302. endstruct
  303.    
  304. //! runtextmacro optional TABLE_BC_STRUCTS()
  305.    
  306. struct TableArray extends array
  307.    
  308.     //Returns a new TableArray to do your bidding. Simply use:
  309.     //
  310.     //    local TableArray ta = TableArray[array_size]
  311.     //
  312.     static method operator [] takes integer array_size returns TableArray
  313.         local Table tb = dex.size[array_size] //Get the unique recycle list for this array size
  314.         local TableArray this = tb[0]         //The last-destroyed TableArray that had this array size
  315.        
  316.         debug if array_size <= 0 then
  317.             debug call BJDebugMsg("TypeError: Invalid specified TableArray size: " + I2S(array_size))
  318.             debug return 0
  319.         debug endif
  320.        
  321.         if this == 0 then
  322.             set this = less - array_size
  323.             set less = this
  324.         else
  325.             set tb[0] = tb[this]  //Set the last destroyed to the last-last destroyed
  326.             call tb.remove(this)  //Clear hashed memory
  327.         endif
  328.        
  329.         set dex.size[this] = array_size //This remembers the array size
  330.         return this
  331.     endmethod
  332.    
  333.     //Returns the size of the TableArray
  334.     method operator size takes nothing returns integer
  335.         return dex.size[this]
  336.     endmethod
  337.    
  338.     //This magic method enables two-dimensional[array][syntax] for Tables,
  339.     //similar to the two-dimensional utility provided by hashtables them-
  340.     //selves.
  341.     //
  342.     //ta[integer a].unit[integer b] = unit u
  343.     //ta[integer a][integer c] = integer d
  344.     //
  345.     //Inline-friendly when not running in debug mode
  346.     //
  347.     method operator [] takes integer key returns Table
  348.         static if DEBUG_MODE then
  349.             local integer i = this.size
  350.             if i == 0 then
  351.                 call BJDebugMsg("IndexError: Tried to get key from invalid TableArray instance: " + I2S(this))
  352.                 return 0
  353.             elseif key < 0 or key >= i then
  354.                 call BJDebugMsg("IndexError: Tried to get key [" + I2S(key) + "] from outside TableArray bounds: " + I2S(i))
  355.                 return 0
  356.             endif
  357.         endif
  358.         return this + key
  359.     endmethod
  360.    
  361.     //Destroys a TableArray without flushing it; I assume you call .flush()
  362.     //if you want it flushed too. This is a public method so that you don't
  363.     //have to loop through all TableArray indices to flush them if you don't
  364.     //need to (ie. if you were flushing all child-keys as you used them).
  365.     //
  366.     method destroy takes nothing returns nothing
  367.         local Table tb = dex.size[this.size]
  368.        
  369.         debug if this.size == 0 then
  370.             debug call BJDebugMsg("TypeError: Tried to destroy an invalid TableArray: " + I2S(this))
  371.             debug return
  372.         debug endif
  373.        
  374.         if tb == 0 then
  375.             //Create a Table to index recycled instances with their array size
  376.             set tb = Table.create()
  377.             set dex.size[this.size] = tb
  378.         endif
  379.        
  380.         call dex.size.remove(this) //Clear the array size from hash memory
  381.        
  382.         set tb[this] = tb[0]
  383.         set tb[0] = this
  384.     endmethod
  385.    
  386.     private static Table tempTable
  387.     private static integer tempEnd
  388.    
  389.     //Avoids hitting the op limit
  390.     private static method clean takes nothing returns nothing
  391.         local Table tb = .tempTable
  392.         local integer end = tb + 0x1000
  393.         if end < .tempEnd then
  394.             set .tempTable = end
  395.             call ForForce(bj_FORCE_PLAYER[0], function thistype.clean)
  396.         else
  397.             set end = .tempEnd
  398.         endif
  399.         loop
  400.             call tb.flush()
  401.             set tb = tb + 1
  402.             exitwhen tb == end
  403.         endloop
  404.     endmethod
  405.    
  406.     //Flushes the TableArray and also destroys it. Doesn't get any more
  407.     //similar to the FlushParentHashtable native than this.
  408.     //
  409.     method flush takes nothing returns nothing
  410.         debug if this.size == 0 then
  411.             debug call BJDebugMsg("TypeError: Tried to flush an invalid TableArray instance: " + I2S(this))
  412.             debug return
  413.         debug endif
  414.         set .tempTable = this
  415.         set .tempEnd = this + this.size
  416.         call ForForce(bj_FORCE_PLAYER[0], function thistype.clean)
  417.         call this.destroy()
  418.     endmethod
  419.    
  420. endstruct
  421.    
  422. //NEW: Added in Table 4.0. A fairly simple struct but allows you to do more
  423. //than that which was previously possible.
  424. struct HashTable extends array
  425.  
  426.     //Enables myHash[parentKey][childKey] syntax.
  427.     //Basically, it creates a Table in the place of the parent key if
  428.     //it didn't already get created earlier.
  429.     method operator [] takes integer index returns Table
  430.         local Table t = Table(this)[index]
  431.         if t == 0 then
  432.             set t = Table.create()
  433.             set Table(this)[index] = t //whoops! Forgot that line. I'm out of practice!
  434.         endif
  435.         return t
  436.     endmethod
  437.  
  438.     //You need to call this on each parent key that you used if you
  439.     //intend to destroy the HashTable or simply no longer need that key.
  440.     method remove takes integer index returns nothing
  441.         local Table t = Table(this)[index]
  442.         if t != 0 then
  443.             call t.destroy()
  444.             call Table(this).remove(index)
  445.         endif
  446.     endmethod
  447.    
  448.     //Added in version 4.1
  449.     method has takes integer index returns boolean
  450.         return Table(this).has(index)
  451.     endmethod
  452.    
  453.     //HashTables are just fancy Table indices.
  454.     method destroy takes nothing returns nothing
  455.         call Table(this).destroy()
  456.     endmethod
  457.    
  458.     //Like I said above...
  459.     static method create takes nothing returns thistype
  460.         return Table.create()
  461.     endmethod
  462.  
  463. endstruct
  464.  
  465. endlibrary
  466.  

Example usage of HashTable
Code: jass
  1. local HashTable hash = HashTable.create() //create it
  2. set hash['hfoo'][StringHash("poop")] = 66 //access large parent and child keys as needed
  3. set hash['hfoo'].unit[99999] = GetTriggerUnit() //still works with multiple-type syntax so you still have the full hashtable API.
  4. call hash.remove('hfoo') //This literally is calling FlushChildHashtable, and should be used when the parentkey and/or HashTable are to be retired
  5. call hash.destroy() //DOES NOT FLUSH THE HASHTABLE. You must manually remove each parent key, first, otherwise you'll have a lot of leaked Tables.
  6.  

Backwards Compatibility with Vexorian's Table
Code: jass
  1. library TableBC requires Table
  2. /*
  3.     Backwards-compatibility add-on for scripts employing Vexorian's Table.
  4.  
  5.     Added 31 July 2015: introduced static method operator [] and
  6.     static method flush2D for Table, HandleTable and StringTable. Now,
  7.     almost all of the Vexorian API has been replicated (minus the .flush paradox).
  8.  
  9.     The Table library itself was unchanged to implement these
  10.     enhancements, so you need only update this library to experience the
  11.     improved syntax compatibility.
  12.    
  13.     Disclaimer:
  14.    
  15.     The following error does not occur with HandleTables & StringTables, only
  16.     with the standard, integer-based Table, so you do not need to make any
  17.     changes to StringTable/HandleTable-employing scripts.
  18.    
  19.     The this.flush(key) method from the original Table cannot be parsed with
  20.     the new Table. For the scripts that use this method, they need to be up-
  21.     dated to use the more fitting this.remove(key) method.
  22.    
  23.     Please don't try using StringTables/HandleTables with features exclusive
  24.     to the new Table as they will cause syntax errors. I do not have any plan
  25.     to endorse these types of Tables because delegation in JassHelper is not
  26.     advanced enough for three types of Tables without copying every single
  27.     method over again (as you can see this already generates plenty of code).
  28.     StringTable & HandleTable are wrappers for StringHash & GetHandleId, so
  29.     just type them out.
  30. */
  31.  
  32. //! textmacro TABLE_BC_METHODS
  33.     method reset takes nothing returns nothing
  34.         call this.flush()
  35.     endmethod
  36.     method exists takes integer key returns boolean
  37.         return this.has(key)
  38.     endmethod
  39.     static method operator [] takes string id returns Table
  40.         local integer index = StringHash(id)
  41.         local Table t = Table(thistype.typeid)[index]
  42.         if t == 0 then
  43.             set t = Table.create()
  44.             set Table(thistype.typeid)[index] = t
  45.         endif
  46.         return t
  47.     endmethod
  48.     static method flush2D takes string id returns nothing
  49.         local integer index = StringHash(id)
  50.         local Table t = Table(thistype.typeid)[index]
  51.         if t != 0 then
  52.             call t.destroy()
  53.             call Table(thistype.typeid).remove(index)
  54.         endif
  55.     endmethod
  56. //! endtextmacro
  57.  
  58. //! textmacro TABLE_BC_STRUCTS
  59. struct HandleTable extends array
  60.     static method operator [] takes string index returns thistype
  61.         return Table[index]
  62.     endmethod
  63.     static method flush2D takes string index returns nothing
  64.         call Table.flush2D(index)
  65.     endmethod
  66.     method operator [] takes handle key returns integer
  67.         return Table(this)[GetHandleId(key)]
  68.     endmethod
  69.     method operator []= takes handle key, integer value returns nothing
  70.         set Table(this)[GetHandleId(key)] = value
  71.     endmethod
  72.     method flush takes handle key returns nothing
  73.         call Table(this).remove(GetHandleId(key))
  74.     endmethod
  75.     method exists takes handle key returns boolean
  76.         return Table(this).has(GetHandleId(key))
  77.     endmethod
  78.     method reset takes nothing returns nothing
  79.         call Table(this).flush()
  80.     endmethod
  81.     method destroy takes nothing returns nothing
  82.         call Table(this).destroy()
  83.     endmethod
  84.     static method create takes nothing returns thistype
  85.         return Table.create()
  86.     endmethod
  87. endstruct
  88.  
  89. struct StringTable extends array
  90.     static method operator [] takes string index returns thistype
  91.         return Table[index]
  92.     endmethod
  93.     static method flush2D takes string index returns nothing
  94.         call Table.flush2D(index)
  95.     endmethod
  96.     method operator [] takes string key returns integer
  97.         return Table(this)[StringHash(key)]
  98.     endmethod
  99.     method operator []= takes string key, integer value returns nothing
  100.         set Table(this)[StringHash(key)] = value
  101.     endmethod
  102.     method flush takes string key returns nothing
  103.         call Table(this).remove(StringHash(key))
  104.     endmethod
  105.     method exists takes string key returns boolean
  106.         return Table(this).has(StringHash(key))
  107.     endmethod
  108.     method reset takes nothing returns nothing
  109.         call Table(this).flush()
  110.     endmethod
  111.     method destroy takes nothing returns nothing
  112.         call Table(this).destroy()
  113.     endmethod
  114.     static method create takes nothing returns thistype
  115.         return Table.create()
  116.     endmethod
  117. endstruct
  118. //! endtextmacro
  119.  
  120. endlibrary
  121.  

"Example Usage of Table:"
Code: jass
  1. struct table_demo extends array
  2.     private static method demo takes nothing returns nothing
  3.         //Create it:
  4.         local Table a = Table.create()
  5.        
  6.         //Use it:
  7.         local boolean b = a.has(69)
  8.         set a[654321] = 'A'
  9.         set a[54321] = 'B'
  10.         set a.unit[12345] = GetTriggerUnit()
  11.         set a.unit[GetHandleId(a.unit[12345])] = GetSpellTargetUnit()
  12.         set a.real['ABCD'] = 3.14159
  13.         set a.integer[133] = 21
  14.  
  15.         //remove entries
  16.         call a.handle.remove('ABCD')
  17.         call a.remove(54321)
  18.  
  19.         //Flush/destroy it:
  20.         call a.destroy()
  21.  
  22.         //Or, only flush it:
  23.         call a.flush()
  24.     endmethod
  25. endstruct
  26.  

"Example Usage of TableArray:"
Code: jass
  1. //Create it:
  2. local TableArray da = TableArray[0x2000]
  3.  
  4. //Use it:
  5. local thistype this = 0
  6. loop
  7.     set this = this.next
  8.     exitwhen this == 0
  9.     set this.save = this.save + 1
  10.     set da[this].real[this.save * 3] = GetUnitX(this.unit)
  11.     set da[this].real[this.save * 3 + 1] = GetUnitY(this.unit)
  12.     set da[this].real[this.save * 3 + 2] = GetUnitFlyHeight(this.unit)
  13. endloop
  14.  
  15. //Flush/destroy it:
  16. call da.flush()
  17.  
  18. //Or, only destroy it (more efficient if you manage memory yourself)
  19. call da.destroy()
  20.  
Note the power of TableArray, how it splices the one hashtable into a many-dimensional array. This means you can have a multi-dimensional array (and more) per system.
« Last Edit: December 18, 2017, 02:37:43 PM by moyack »



 

Vivir aprendiendo.co - A place for learning stuff, in Spanish   Chaos Realm - The world of Game modders and wc3 addicts   Diplo, a gaming community   Power of Corruption, an altered melee featuring Naga and Demon. Play it now!!!   WC3JASS.com - The JASS Vault + vJASS and Zinc   Jetcraft - A Starcraft II mod   WormTastic Clan (wTc)