• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

Value Manager

Level 7
Joined
Apr 27, 2011
Messages
272
This simple snippet will allow you to easily make save, load, and erase functions for any value types (except codes). And you can manage the vaue you saved with integers.

Requires: a knowledge about TextMacros

here's the snippet:
JASS:
library ValueManager
//===========================================================================
// Value Manager version 0.0.0 by Alain.Mark
//
// (Note: BE SURE YOU THAT KNOW WHAT TEXTMACROS ARE BEFORE YOU USE THIS)
//
// -About-
//  This snippet is actually a template for making simple save, load, and erase
//  functions for values of any type (excluding codes).(more explanations below)
//
// -How to Use-
//  //! runtextmacro CREATE("<KEYWORD>","<TYPE>")
//  -This textmacro will create the save, load, and erase function that you are going
//   going to use.
//
//  "KEYWORD" - is any combination of unique alphanumeric chars. This will replace the
//              $KEYWORD$ tokens inside the CREATE textmacro and instanceate it for use.
//
//  "TYPE"    - this is the type of argument/value that will be taken by Save_$KEYWORD$
//              and returned by Load_$KEYWORD$.
//   
//  Save_$KEYWORD$($TYPE$ value)  
//  -This will save the "value" in an array variable and return a unique
//   integer that you can use if you want to load "value" back.
//
//  Load_$KEYWORD$(integer acces_id)
//  -This will load and return the value pointed by the "acces_id".
//   (another direct alternative for Load_$KEYWORD$ is accesing the variable itself)
// 
//  Queue_$KEYWORD$(integer acces_id)
//  -This will not actually clear the value pointed by the "acces_id" but
//   prepares its slot to be overwritten instead. You should do this once in a
//   while to save some space.
//
//===========================================================================  
//! textmacro CREATE takes KEYWORD, TYPE 
 globals
    integer       $KEYWORD$_Stocks     =-1
    integer       $KEYWORD$_Stockpiled =-1
    integer array $KEYWORD$_Stock_No
    $TYPE$  array Stored_$KEYWORD$[8190]
 endglobals

//===========================================================================
// This function returns an integer so you can track the value stored in
// the array
 function Save_$KEYWORD$ takes $TYPE$ value returns integer
    local integer acces_id
    if($KEYWORD$_Stockpiled>=0)then
        set acces_id=$KEYWORD$_Stock_No[$KEYWORD$_Stockpiled]
        set $KEYWORD$_Stock_No[$KEYWORD$_Stockpiled]=0
        set $KEYWORD$_Stockpiled=$KEYWORD$_Stockpiled-1
    else
        set $KEYWORD$_Stocks=$KEYWORD$_Stocks+1
        if($KEYWORD$_Stocks>=8190)then
            debug call BJDebugMsg("|cffff0000WARNING|r: You are saving too many values, try erasing some!!!")
            return 0
        endif
        set acces_id=$KEYWORD$_Stocks
    endif
    set Stored_$KEYWORD$[acces_id]=value
    return acces_id
 endfunction

//===========================================================================
// You can directly get the value itself by accessing the variable, I
// just made this function as an interface for it 
 function Load_$KEYWORD$ takes integer acces_id returns $TYPE$
    return Stored_$KEYWORD$[acces_id]
 endfunction

//===========================================================================
 function Queue_$KEYWORD$ takes integer acces_id returns integer
    set $KEYWORD$_Stockpiled=$KEYWORD$_Stockpiled+1
    set $KEYWORD$_Stock_No[$KEYWORD$_Stockpiled]=acces_id
    return acces_id
 endfunction
//! endtextmacro

//===========================================================================
endlibrary

here's a simple test for it
JASS:
library Test initializer Example
// Let's test it on strings

//! runtextmacro CREATE("Str","string")
// I decided to use "Str" as my KEYWORD hence it will replace $KEYWORD$ tokens the resulting function names I will be
//  using are Save_Str, Load_Str, and Erase_Str

 private function Example takes nothing returns nothing
    local integer a=Save_Str("Hello World")
    call BJDebugMsg(Load_Str(a))
 endfunction
 
endlibrary

JASS:
-Changelog-
// Erase_ was replaced by Queue_ because it might cause some confusion
I will be glad to show some extra usage examples requested.

Thanks to: D4RK G4ND4LF and Nestharus for informing me about speed comparison. :)
 
Last edited by a moderator:
Level 7
Joined
Apr 27, 2011
Messages
272
Can I ask where would this be useful? ^_^

to me it looks similar to global variables...

Well its not different from using globals (arrays to be exact) but there are some advantages:

*You can get a unique integer that you can use to recover the value you stored, then that integer will be useful if you want to attach it to a handle (a timer for example).

*It supports multi-instanceability instead of abusing a single global.

*You can recycle array slots.

*You can save time when making scopes or systems that uses array variables (since you will not make an array recycle function anymore)

Here's an example:
JASS:
//! runtextmacro CREATE("Unit","unit")

 function U2I takes unit u returns integer
    return Save_Unit(u)
 endfunction
 
 function I2U takes integer i returns unit
    set i=Queue_Unit(i)
    return Load_Unit(i)
 endfunction

Its not really that but it reminds me of something ^^ an oh try it it actually works.
 
Last edited:
Level 7
Joined
Apr 27, 2011
Messages
272
@Nestharus, I agree w/ you ( I never noticed that ^^) but it can be useful in some ways, like if your planning quickly to legalize some old JASS enhanced spell (that still uses typecasting) to the latest patch.

@Adiktuz, it can be a replacement for hashtables, if you want a quicker way to save values. Like here for instance:
JASS:
call SaveUnitHandle(Hashtable,0,GetHandleId(H),Some_Unit)
// or you can just do this instead
call Save_Unit(Some_Unit)

and for your other question, you only need to run a different instance for each type (w/ a different KEYWORD ofc) and you can enjoy its functionalities but be sure to erase some data once in a while.
 
Last edited:
Level 7
Joined
Apr 27, 2011
Messages
272
For the API, i have no better way of explaining it since the replacement tokens $KEYWORD$ and $TYPE$ are not constant and their names depends on the user's preference. You only need to run the "CREATE" textmacro once per different value types (but it depends if you want more for the same value type anyway).
 
JASS:
struct AccessId extends array
    private integer s
    private static integer array ir
    private static integer ic = 0
    public static method store takes integer v returns thistype
        local thistype this
        if (ir[0] == 0) then
            set this = ic + 1
            set ic = this
        else
            set this = ir[0]
            set ir[0] = ir[this]
        endif
        set this.s = v
        return this
    endmethod
    method load takes nothing returns integer
        return s
    endmethod
    method erase takes nothing returns nothing
        set ir[this] = ir[0]
        set ir[0] = this
    endmethod
endstruct

Do you see my point... that's a struct with a really stupid functionality.

Another way to code it
JASS:
struct AccessId
    public integer data
endstruct
 
Level 7
Joined
Apr 27, 2011
Messages
272
Srsly guys have you tried testing it first? and Nestharus i do not get your example because its really different from what this snippet does...

Example result if we use: //! runtextmacro CREATE("String","string")
JASS:
 function Save_String takes string value returns integer
    local integer acces_id
    if ( String_Stockpiled >= 0 ) then
       //knowing that String_Stockpiled is GREATER THAN or EQUAL to 0
       // acces_id will be equal to the last pending queued index
        set acces_id = String_Stock_No[String_Stockpiled]
        set String_Stock_No[String_Stockpiled]=0
      //then we will decrement String_Stockpiled by one so the next "acces_id"
      // stored in the "String_Stock_No" will be reused
        set String_Stockpiled = String_Stockpiled - 1
    else
        set String_Stocks = String_Stocks + 1
        if ( String_Stocks >= 8190 ) then
             call BJDebugMsg("|cffff0000WARNING|r: You are saving too many values, try queuing some!!!")
            return 0
        endif
        set acces_id = String_Stocks
    endif
    set s__Stored_String[acces_id]= value
    return acces_id
 endfunction

//===========================================================================
 function Load_String takes integer acces_id returns string
    return s__Stored_String[acces_id]
 endfunction

//===========================================================================
 function Queue_String takes integer acces_id returns integer
 //This will store free array slot indexes in an integer array.
    set String_Stockpiled = String_Stockpiled + 1
    set String_Stock_No[String_Stockpiled]=acces_id
    return acces_id
 endfunction

Its actually a modified stack method... if you observe it carefully
 
Top