;; 
;;=====================================================================================----- 
;; 
;;LIBRARY        Hash() 
;; 
;;ACTION         Creates and maintains a set of associative arrays 
;; 
;;AUTHOR         Howard A. Bullock 
;; 
;;VERSION        1.2  - 2013/11/29 
;; 
;;HISTORY        1.0  - 2002/09/30 
;;               1.2  - 2013/11/29 - Enhancments by Christophe Melin 
;;               1.3  - 2020/08/09 - ITCG Code Standards, add support for Arrays in data 
;; 
;;SYNTAX         Hash(HashName, Key, Value) 
;;               HashKeys(HashName) 
;;               DelHashKey(HashName, Key) 
;; 
;;REMARKS        A library of related functions that implement associative arrays, 
;;               Similar to those found in PERL. 
;; 
;; 
;;====================================================================== 
;; 
;;FUNCTION       Hash() 
;; 
;;AUTHOR         Howard A. Bullock 
;; 
;;ACTION         Creates and maintains a set of associative arrays 
;; 
;;SYNTAX         Hash(HashName, Key, Value) 
;; 
;;PARAMETERS     HashName (Required) -  String value 
;;               Key (Required) -  String value 
;;               Value (Required)  
;; 
;;REMARKS        This function creates and maintains a pair of arrays and manipulates 
;;               in a such that the function yields multiple hashses. 
;;               Given the hash name, the function either sets a key and value pair or 
;;               returns the value of the specified hash and key. 
;; 
;;RETURNS        Value if no value is input 
;; 
;;DEPENDENCIES 
;; 
;;EXAMPLES       Hash("Colors","Green","Favorite Color")    ; Sets a hash value 
;;               "Green Color= " + Hash("Colors","Green") ? ; return a hash value 
; 
Function Hash($_HashName, $_Key, Optional $_Value)
 
  Dim $_HashKey, $_HashValue
  Dim $_Found, $_Y, $_Rc
 
  If VarType($_Value) >= 8192
    $_Value = Join($_Value, Chr(30))
  EndIf
 
  $_HashKey   = __CreateHashTableVarName($_HashName, 'Key')
  $_HashValue = __CreateHashTableVarName($_HashName, 'Value')
  $Hash       = Chr(0)
 
  $_Y =
  '
    If VarType(%%_Value) = 0
      If Not IsDeclared(%%_' + $_HashKey + ')
        Exit 1
      EndIf

      ;-- Read a value --
      %%_Found = Ascan(%%_' + $_HashKey + ', "' + $_Key + '")
      If %%_Found = -1
        %%Hash = "Key (' + $_Key + ') Not Defined"
        Exit 2
      EndIf

      %%Hash = %%_' + $_HashValue + '[%%_found]
    Else
      If Not IsDeclared(%%_' + $_HashKey + ')
        ;-- create the hashname --
        %%_Found = 0
        Global %%_' + $_HashKey + '[%%_found]
        Global %%_' + $_HashValue + '[%%_found]
      Else
        ;-- Set a value --
        %%_Found = AScan(%%_' + $_HashKey + ', "' + $_Key + '")
        If %%_Found = -1
          ;-- create a new key for the hashname --
          %%_Found = Ubound(%%_' + $_HashKey + ')+1
          Redim Preserve %%_' + $_HashKey + '[%%_found]
          Redim Preserve %%_' + $_HashValue + '[%%_found]
        EndIf
      EndIf

      %%_' + $_HashKey + '[%%_found] = "' + $_Key + '"
      %%_' + $_HashValue + '[%%_found] = "' + $_Value + '"
    EndIf
  '
  $_Y = Replace($_Y, "%%", chr(36))
 
  $_Rc = Execute($_Y)
 
  If InStr($Hash, Chr(30))
    $Hash = Split($Hash, Chr(30))
  EndIf
 
  Exit $_Rc
        
EndFunction
 
 
;;FUNCTION       HashKeys() 
;; 
;;AUTHOR         Howard A. Bullock 
;; 
;;ACTION         Creates and maintains a set of associative arrays 
;; 
;;SYNTAX         HashKeys(HashName) 
;; 
;;PARAMETERS     HashName (Required) -  String value 
;; 
;;REMARKS        This function returns an array of values that represent keys of 
;;               the HASH named $_HashName. 
;; 
;;RETURNS        Array 
;; 
;;DEPENDENCIES 
;; 
;;EXAMPLES       $_Array = HashKeys("Colors") 
;; 
; 
Function HashKeys($_HashName)
 
  Dim $_HashKey, $_Y, $_Rc
 
  $_HashKey = __CreateHashTableVarName($_HashName, 'Key')
 
  $_Y =
  '
    If IsDeclared(%%_' + $_HashKey + ')
      If UBound(%%_' + $_HashKey + ') >= -1
        %%HashKeys = %%_' + $_HashKey + '
        Exit 0
      EndIf
    EndIf
    Exit 1
  '
  $_Y = Replace($_Y, "%%", chr(36))
 
  $_Rc = Execute($_Y)
 
  Exit $_Rc
  
EndFunction
 
 
;;FUNCTION         DelHashKey() 
;; 
;;AUTHOR           Howard A. Bullock 
;; 
;;ACTION           Creates and maintains a set of associative arrays 
;; 
;;SYNTAX           DelHashKey(HashName, Key) 
;; 
;;PARAMETERS       HashName (Required) -  String value 
;;                 Key (Required) -  String value 
;; 
;;REMARKS          This function deletes the key/value pair from the hash named $_HashName. 
;; 
;;RETURNS          Nothing 
;; 
;;DEPENDENCIES 
;; 
;;EXAMPLES         DelHashKey("Colors", "Green") 
; 
Function DelHashKey($_HashName, $_Key)
 
  Dim $_HashKey, $_HashValue
  Dim $_KeyLimit
  Dim $_Found, $_X, $_Y, $_Rc
 
  $_HashKey  = __CreateHashTableVarName( $_HashName, 'Key')
  $_HashValue  = __CreateHashTableVarName( $_HashName, 'Value')
  
  $_Y =
  '
    If IsDeclared(%%_' + $_HashKey + ')
      ; Delete a value
      %%_KeyLimit = Ubound($_' + $_HashKey + ')

      If %%_KeyLimit = -1 Exit 1 EndIf

      %%_Found = Ascan(%%_' + $_HashKey + ', "' + $_Key + '")
      If %%_Found = -1 Exit 2 EndIf

      If %%_KeyLimit = 0
        Redim %%_' + $_HashKey + '
        Redim %%_' + $_HashValue + '
      Else
        For %%_X = %%_Found to %%_KeyLimit
          If  (%%_X < %%_KeyLimit)
            %%_' + $_HashKey + '[%%_X] = %%_' + $_HashKey + '[%%_X + 1]
            %%_' + $_HashValue + '[%%_X] = %%_' + $_HashValue + '[%%_X + 1]
          EndIf
        Next

        Redim Preserve %%_' + $_HashKey + '[%%_KeyLimit - 1]
        Redim Preserve %%_' + $_HashValue + '[%%_KeyLimit - 1]
      EndIf
    EndIf
  '
 
  $_Y = Replace($_Y, "%%", chr(36))
 
  $_Rc = Execute($_Y)
 
  Exit $_Rc
  
EndFunction
 
 
;;FUNCTION         EmptyHash() 
;; 
;;AUTHOR           Christophe Melin 
;; 
;;ACTION           remove all keys from a set of associatice arrays 
;; 
;;SYNTAX           EmptyHashKey(HashName) 
;; 
;;PARAMETERS       HashName - Required -  String value 
;; 
;;REMARKS          This function remove all key/value pair from the hash named $_HashName. 
;; 
;;RETURNS          Nothing 
;; 
;;DEPENDENCIES 
;; 
;;EXAMPLES         EmptyHash("Colors") 
; 
Function EmptyHash($_HashName)
 
  Dim $_HashKey, $_HashValue, $_KeyLimit
  Dim $_Y, $_Rc
 
  $_HashKey   = __CreateHashTableVarName($_HashName, 'Key')
  $_HashValue = __CreateHashTableVarName($_HashName, 'Value')
 
  $_Y =
  '
    If IsDeclared(%%_' + $_HashKey + ')
      Redim %%_' + $_HashKey + '
      Redim %%_' + $_HashValue + '
    EndIf
  '
  $_Y = Replace($_Y, "%%", chr(36))
 
  $_Rc = Execute($_Y)
 
  Exit $_Rc
  
EndFunction
 
 
;;FUNCTION         __CreateHashTableVarName() 
;; 
;;AUTHOR           Christophe Melin 
;; 
;;ACTION           Creates var name for internal use of other hash functions 
;; 
;;RETURNS          Value if no value is input 
;; 
;;DEPENDENCIES 
; 
Function __CreateHashTableVarName($_Hash, $_Type)
 
  If Not IsDeclared($__InternalHashIllegalCharacters)
    Global $__InternalHashIllegalCharacters
    $__InternalHashIllegalCharacters = ' ', ',', ';', '.', '-', '$_', '+', '(', ')', '*', '/', '&', '<', '>', '=', '%'
  EndIf
 
  Dim $_Prefix, $_I, $_Ch
 
  $_Prefix = '_InternalHashVarName'
  
  For $_I = 0 To UBound($__InternalHashIllegalCharacters)
    $_Ch = $__InternalHashIllegalCharacters[$_I]
    $_Hash = Replace($_Hash, $_Ch, $_I )
  Next
 
  $__CreateHashTableVarName = $_Prefix + '_' + $_Hash + '_' + $_Type
  
EndFunction