AutoHotkey Homepage AutoHotkey Community
Let's help each other out
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Scripting.Dictionary Object as Associative Array
Goto page Previous  1, 2, 3, 4, 5  Next
 
Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions
View previous topic :: View next topic  
Author Message
Laszlo



Joined: 14 Feb 2005
Posts: 4710
Location: Boulder, CO

PostPosted: Mon Jun 04, 2007 9:35 pm    Post subject: Reply with quote

majkinetor wrote:
The usage is not the problem. The problem is sharing.
Then I don't understand the problem: you have to pass the dictionary handle to a function as a parameter or make it global. The same is with the variable containing all of your constants. The later is faster and does not need includes or dll calls.
Back to top
View user's profile Send private message
toralf



Joined: 31 Jan 2005
Posts: 3910
Location: Bremen, Germany

PostPosted: Wed Jun 06, 2007 6:21 am    Post subject: Reply with quote

Is there any limitation on OS? Does it run on all windows versions?
_________________
Ciao
toralf
Back to top
View user's profile Send private message Send e-mail Visit poster's website
hoppfrosch



Joined: 25 Jan 2006
Posts: 190
Location: Froschtümpel

PostPosted: Thu Aug 09, 2007 6:09 am    Post subject: Question: Hash of Hashes? Reply with quote

Hi,

got a question concerning "Hash of Hashes" (considering dictionaries as hashes).

What I try to do is putting dictionary items into a dictionary:
Code:

#include %A_ScriptDir%\Includes\CoHelper.ahk
#Include %A_ScriptDir%\Includes\Dic.ahk

CoInitialize()
pdic := Dictionary()
Add(pdic, "ATT1", "ATT1_1")
Add(pdic, "ATT2", "ATT2_1")
Add(pdic, "ATT3", "ATT3_1")
Add(pdic, "ATT4", "ATT4_1")

pdic2 := Dictionary()
Add(pdic2, "ENTRY1", pDic)

MsgBox, % "ENTRY1: " . "`n" . Enumerate(GetItem(pdic2, "ENTRY1"))

; Changing the contents of pDic
SetItem(pdic, "ATT1", "ATT1_2")
SetItem(pdic, "ATT2", "ATT2_2")
SetItem(pdic, "ATT3", "ATT3_2")
SetItem(pdic, "ATT4", "ATT4_2")

; Is pDic stored byVal or byRef? Unfortunately its stored byRef, so the old contents got lost ....
MsgBox, % "ENTRY1: " . "`n" . Enumerate(GetItem(pdic2, "ENTRY1"))

Release(pdic)
Release(pdic2)

CoUninitialize()


Doing the above - changing contents of pdic after inserting it into pdic2, also changes the inserted item in pdic2.
How can I store the contents of pdic in pdic2, instead of just storing the reference of pdic?

Thanks in advance
Hoppfrosch
Back to top
View user's profile Send private message Visit poster's website
Azerty



Joined: 19 Dec 2006
Posts: 72
Location: France

PostPosted: Thu Aug 09, 2007 12:11 pm    Post subject: Reply with quote

Chris wrote:
Thanks for these great functions. I've linked to this topic from the bottom of the Arrays page. Does anyone know whether Windows 9x/NT supports Scripting.Dictionary?


Hi

AFAIK, Scripting.Dictionary is implemented when WSH5.6 is installed. Since MS has a specific version for W98/NT4, it should be supported as well

Sean : thanks for this great work
Back to top
View user's profile Send private message
fade2gray



Joined: 21 Oct 2006
Posts: 23

PostPosted: Tue Oct 23, 2007 10:41 am    Post subject: Reply with quote

Hi, I arrived here by reading the help file on arrays.

I downloaded the Dictionary and CoHelper scripts, but running the example included in Dictionary.ahk results in:-
Quote:
Error at line63 in #include file "\path to\CoHelper.ahk ".

Line Text: Enumerate(penum, ByRef Result)
Error:Duplicate function definition

The Enumerate() function has been defined in Dictionary.ahk as:-
Code:
Enumerate(pdic)
{
   DllCall(VTable(pdic, 20), "Uint", pdic, "UintP", penm)

   VarSetCapacity(var, 8 * 2, 0)

   Loop, % Count(pdic)
   {
      DllCall(VTable(penm, 3), "Uint", penm, "Uint", 1, "Uint", &var, "Uint", 0)
      pKey := DecodeInteger(&var + 8)
      DllCall(VTable(pdic, 9), "Uint", pdic, "Uint", &var, "Uint", &var)
      pItm := DecodeInteger(&var + 8)

      Unicode2Ansi(pKey, sKey)
      Unicode2Ansi(pItm, sItm)
      SysFreeString(pKey)
      SysFreeString(pItm)
      sKeys .= sKey . " : " . sItm . "`n"
   }

   DllCall(VTable(penm, 2), "Uint", penm)

   Return sKeys
}

and in CoHelper.ahk as:-
Code:
Enumerate(penum, ByRef Result)
{
   VarSetCapacity(varResult,16,0)
   If (0 =   hResult:=DllCall(NumGet(NumGet(1*penum)+12), "Uint", penum, "Uint", 1, "Uint", &varResult, "UintP", 0))
      Result:=(vt:=NumGet(varResult,0,"Ushort"))=8||vt<0x1000&&DllCall("oleaut32\VariantChangeTypeEx","Uint",&varResult,"Uint",&varResult,"Uint",LCID,"Ushort",1,"Ushort",8)=0 ? Ansi4Unicode(bstr:=NumGet(varResult,8)) . SubStr(SysFreeString(bstr),1,0) : NumGet(varResult,8)
   Return   hResult
}

Any comments please?
Back to top
View user's profile Send private message
majkinetor



Joined: 24 May 2006
Posts: 4511
Location: Belgrade

PostPosted: Tue Oct 23, 2007 10:48 am    Post subject: Reply with quote

If i recall correctly COM.ahk replaced CoHelper.ahk.
_________________
Back to top
View user's profile Send private message
Sean



Joined: 12 Feb 2007
Posts: 2462

PostPosted: Tue Oct 23, 2007 11:00 am    Post subject: Reply with quote

fade2gray wrote:
I downloaded the Dictionary and CoHelper scripts, but running the example included in Dictionary.ahk results in:-
Quote:
Error at line63 in #include file "\path to\CoHelper.ahk ".

Ah, recently I added Enumerate() to CoHelper.ahk while adding COM_Enumerate() to COM.ahk, completely forgetting about this Scripting.Dictionary (:yes, it's been deleted already from my HDD, all functions were replaced with Invoke()).
Are you gonna use it? I can safely remove Enumerate() from CoHelper.ahk.
However, I suggest to switch to Invoke()/COM_Invoke().
Back to top
View user's profile Send private message
Sean



Joined: 12 Feb 2007
Posts: 2462

PostPosted: Tue Oct 23, 2007 11:40 am    Post subject: Reply with quote

fade2gray wrote:
Error at line63 in #include file "\path to\CoHelper.ahk ".

I commented out Enumerate() in CoHelper.ahk. So, you may redownload it.
BTW, I recommend using COM.ahk over CoHelper.ahk, and COM_Invoke() function over the script(s) Scripting.Dictionary etc.
Back to top
View user's profile Send private message
fade2gray



Joined: 21 Oct 2006
Posts: 23

PostPosted: Tue Oct 23, 2007 4:54 pm    Post subject: Reply with quote

Thanks for the prompt replies.

I was trying to find a method to return multiple variables from a function (believing an array was the way to go) and have just figured how to use StringSplit.
Back to top
View user's profile Send private message
Phoenix



Joined: 23 Sep 2005
Posts: 55

PostPosted: Sun Feb 24, 2008 12:36 am    Post subject: Reply with quote

How do I loop through the whole dictionary the best way?
Back to top
View user's profile Send private message
Phoenix



Joined: 23 Sep 2005
Posts: 55

PostPosted: Mon Apr 21, 2008 5:36 pm    Post subject: Reply with quote

*bump* I would like to know how to loop through through it Smile
Back to top
View user's profile Send private message
Guest






PostPosted: Mon Apr 21, 2008 10:41 pm    Post subject: Reply with quote

There is a function Enumerate in the script.
Back to top
HotKeyIt



Joined: 18 Jun 2008
Posts: 4647
Location: AHK Forum

PostPosted: Mon Jun 22, 2009 8:05 pm    Post subject: Reply with quote

Many thanks for this great functionality, specially to Sean and Laszlo Very Happy

I've tried to put in some more simplicity and functionality in it Smile

I would love to get some feedback Wink

EDIT:
Added action abbreviation characters: + (Add), - (Delete), = (Set)...

HowTo
Code:
;--------------------------------------------------------------------------------------------
;
;        D D D D    D D D D    D D D D           ;      D I C T I O N A R Y   D A T A B A S E
;        D      D   D      D   D       D         ;     
;        D       D  D       D  D        D        ;   
;        D        D D        D D       D         ;             
;        D        D D        D D D D D           ;      B Y   H O T K E Y I T
;        D        D D        D D       D         ;   
;        D       D  D       D  D        D        ;       
;        D      D   D      D   D       D         ;     
;        D D D D    D D D D    D D D D           ;     http://www.autohotkey.com/forum/viewtopic.php?p=276927#276927
;
;---------------------------------------------------------------------------------------------
;
;       Scripting.Dictionary  -  http://msdn.microsoft.com/en-us/library/x4k5wbx4.aspx
;        - A Dictionary object is the equivalent of a PERL associative array.
;          Items can be any form of data, and are stored in the array.
;          Each item is associated with a unique key.
;          The key is used to retrieve an individual item and is usually an integer or a string but can be anything else.
;          THE ONLY CHARACTERS YOU SHOULD NOT USE ARE CHR(2) + CHR(3) - those are used in sort action
;
;       Syntax
;         DDB([database,action,key/option,itm/option,skip,limit])
;
;
;       DDB()  -  ALL PARAMETERS ARE OPTIONAL  -  DDB() will destroy all databases and UNinitialise COM
;
;
;       DDB uses offers following functions ( - Key is like a Var and Item like Value in AutoHotkey - )
;       
;
;        - Create/N     --->   Initialises COM (if not already done so) and creates a new database.
;          key can be used to set comparison mode: 0=Binary (default); 1=Text (case insensitive); 2=Database
;          - DDB( "MyDB" , "create" , 1 ) ;Create a database named MyDB.
;
;        - Count/C      --->   Count items in Database
;          - ItemsInDatabase := DDB( "MyDB" , "count" ) alternatively
;
;        - Destroy/D    --->   Destroy a database
;          - DDB( "MyDB" , "destroy" )
;
;        - DestroyAll/DA--->   Destroy all databases (COM will be not UNinitialised, use DDB() therfore)
;          - DDB( "MyDB" , "destroyall" )
;
;        - GetCompMode  --->   Find out compare mode of database
;          - DDB( "MyDB" , "getcompmode" )
;
;
;        - Add/+        --->   Adds a key and item pair to a database
;          This is similar to var=value where var is the key and value is the itm.
;          - DDB( "MyDB" , "add" , "Key" , "Item" )
;
;        - Get/<        --->   Retrieves an Item from database using a key
;          - Item := DDB( "MyDB" , "get" , "Key" )
;
;        - Set/=        --->   Overwrites an existing Item to new value using a key
;          - DDB( "MyDB" , "set" , "Key" , "New Value" )
;
;        - Exists/?     --->   Checks if a key exist and returns 1 if a key exists
;          - If DDB( "MyDB" , "exists" , "Key" )
;
;        - Delete/-     --->   Delete a Key and its Item from Database
;          - DDB( "MyDB" , "delete" , "Key" )
;
;        - Rename/~     --->   Rename a key
;          - DDB( "MyDB" , "rename" , "Key" , "NewKey" )
;
;        - DeleteAll/_  --->   Delete all keys from database
;          - DDB( "MyDB" , "deleteall" )
;
;         - Hash         --->   Return hash of key
;          hash:=DDB( "MyDB" , "hash" , "key" )
;
;
;        - FIND / MATCH / REGEX / GETALL
;           - For item you can specify a different separator than default (`n)
;           - Parameter skip can be used to ommit first found items
;           - Parameter limit can be used to limit foundings
;             Example: DDB("MyDB","find","au",".",20,100)
;             = Find max 100 keys starting with "au" in "MyDB", ommit first 20 found and separate output by .
;
;        - GetAll        --->   Receives all keys from database
;          - AllKeys:=DDB( "MyDB" , "getall" , A_Space ) ;So output here will be: Key1 Key2 Key3...
;
;        - Find          --->   Find keys starting with given characters and return Values of found keys
;          Key can be used to
;          - FoundKeys:=DDB( "MyDB" , "find" , "Ke" , A_Tab )
;
;        - Match         --->   Match keys containing given characters anywhere inside the key
;          - FoundKeys:=DDB( "MyDB" , "match" , "ey" , A_Tab )
;
;        - RegEx         --->   Find keys using RegEx function
;          - FoundKeys:=DDB( "MyDB" , "regex" , "i).*y$" , A_Tab )
;
;
;
;        - Sort          --->   Sort Database using delimiter Chr(3) !!! DUE TO THIS OPTION "D" IS NOT AVALIABLE !!!
;          Parameter key can be used for sort options from AutoHotkey Sort command, only those are valid: C, CL, F, N, Pn, R
;          - DDB( "MyDB" , "sort" , "N R" )
;
;        - Copy          --->   Copy a database to new database
;          - DB( "MyDB" , "copy" , "MyDB" , "MyNewDB" )
;
;        - Replace       --->   Replace values from Items
;          DDB( "MyDB" , "replace" , "SearchText" , "ReplaceText" , "A" ) ; A to replace all
;
;        - RegExReplace  --->   Replace values from Item using RegExReplace
;          DDB( "MyDB" , "regexreplace" , "SearchText" , "ReplaceText" , "10" ) ;10->replace first 10 found
;
;
;        - Enum/&        --->   This action is used to loop trough keys in database
;          Loop
;             If (key:=DDB( "MyDB" , "enum" ))
;               MsgBox % "Key: " . key . "`nValue: " . DDB( "MyDB" , "get" , key)
;             else break
;          Alternatively you can catch ErrorLevel to receive the EnumPointer and go "manually" trough the database
;          - DDB( "MyDB" , "enum" ), pEnum:=ErrorLevel...
;          - key := DDB( "MyDB" , "enum" , pEnum )
;          To start manually from beginning (this is when you did not "Loop" trough the whole database)
;          - DDB( "MyDB" , "enum" , 0 ) ;start from beginning and return first key in Database
;--------------------------------------------------------------------------------------------

Example
Code:
#Include %A_ScriptDir%\DDB.ahk
SetBatchLines,-1
OnExit, Exit

DDB("MyDB","create",1) ;Same as DDB("MyDB","n",1)

;create 1000 keys and items
Loop 1000
   DDB("MyDB","add",A_Index,A_Index) ;or DDB("MyDB","+"...

;enum trogh database
Loop % (20) {
      If NextKey:=DDB("MyDB","enum"){ ;or DDB("MyDB","&")
         pEnum:=ErrorLevel
         ToolTip % "Key: " . NextKey . "`nValue: " . DDB("MyDB","get",NextKey) ;same as DDB("MyDB","<",NextKey)
         Sleep, 100
      } else break
}
ToolTip
MsgBox % "Change item 21:`nbefore: " . DDB("MyDB","get",21)
         . "`nafter: " . DDB("MyDB","set",21,"Hello World!")
         . DDB("MyDB","get",21)
MsgBox % "Item 21 recieved using pEnum: " . DDB("MyDB","get",DDB("MyDB","enum",pEnum))

MsgBox % "Find max 10 keys that start with character 2 and return their items separated by Tab`n" DDB("MyDB","find","2",A_Tab,0,10)
MsgBox % "Match 2 inside key, skip first 10 found and return max 20 items`n" DDB("MyDB","match",2,"",10,20)
MsgBox % "RegEx based search (^20.?$)`n" DDB("MyDB","regex","^20.?$","",0,10)
MsgBox % "Sort descending by number`n" . DDB("MyDB","sort","N R") . SubStr(DDB("MyDB","getAll"),1,100) . "`n…"
MsgBox % "Replace any 1 in Value by a`n" DDB("MyDB","replace",1,"a") DDB("MyDB","find","","|")
DDB("MyDB","sort","N")
MsgBox % "Rename Key 2 to AutoHotkey + Delete Key 3`n" DDB("MyDB","rename",2,"AutoHotkey") DDB("MyDB","delete",3) DDB("MyDB","getall","|")
MsgBox % "copy database to new database (remember 1 Item was deleted)`nItems in new Database: " DDB("MyDB","copy","new") DDB("new","count")

Exit:
DDB()
ExitApp

Function
Code:
DDB(pdic="",action="",Key="",Item="",skip=0,limit=4294967295,ByRef data=""){
   static
   local CLSID,IID,pKey,pItm,nLen,nLenItm,bExist,label,penum,result,nCompMode,wStr
   static var1,var2, CLSIDString:="{EE09B103-97E0-11CF-978F-00A02463E06F}", IIDString:="{42C642C1-97E1-11CF-978F-00A02463E06F}"
   If (label:="DDB" . action)
      Goto % label
   DDB<:
   DDBGet:
      Gosub,DDBAllocKey
      DllCall(NumGet(NumGet(pDic%pdic%+0)+48), UInt,pDic%pdic%, UInt,&var1, IntP,bExist)
      If bExist {     ; to avoid creating an unwanted new entry
         DllCall(NumGet(NumGet(pDic%pdic%+0)+36), UInt,pDic%pdic%, UInt,&var1, UInt,&var2)
         pItm := NumGet(&var2+8)
         nLen := DllCall("WideCharToMultiByte", UInt,0, UInt,0, UInt,pItm, Int,-1, UInt,0, Int,0, UInt,0, UInt,0)
         VarSetCapacity(Item, nLen)
         DllCall("WideCharToMultiByte", UInt,0, UInt,0, UInt,pItm, Int,-1, Str,Item, Int,nLen, UInt,0, UInt,0)
         DllCall("oleaut32\SysFreeString", UInt,pItm)
      }
      DllCall("oleaut32\SysFreeString", UInt,pKey)
   Return Item
   DDB+:
   DDBAdd:
      Gosub,DDBAllocItm
      DllCall(NumGet(NumGet(pDic%pdic%+0)+40), UInt,pDic%pdic%, UInt,&var1, UInt,&var2)
      DllCall("oleaut32\SysFreeString", UInt,pItm),DllCall("oleaut32\SysFreeString", UInt,pKey)
   Return
   DDB?:
   DDBExists:
      Gosub,DDBAllocKey
      DllCall(NumGet(NumGet(pDic%pdic%+0)+48), UInt,pDic%pdic%, UInt,&var1, IntP,bExist)
      DllCall("oleaut32\SysFreeString", UInt,pKey)
   Return bExist
   DDBFind:
   DDBMatch:
   DDBRegEx:
   DDBGetAll:
   DDBCopy:
   DDBSort:
   DDBRegexReplace:
   DDBReplace:
      ;label:=A_Thislabel
      DllCall(NumGet(NumGet(pDic%pdic%+0)+80), UInt,pDic%pdic%, UIntP,penum) ; create key-list in penum
      Loop % DDB(pdic,"count") {
         If (InStr("Clear0",pDic%pdic%) || DllCall(NumGet(NumGet(penum+0)+12), UInt,penum, UInt,1, UInt,&var1, UInt,0)) {
            DllCall(NumGet(NumGet(penum+0)+8), UInt,penum)   ; END: destroy key-list
            penum =                                          ; signal end of list
            break                                              ; empty
         }
         pKey := NumGet(&var1 + 8)
         nLen := DllCall("WideCharToMultiByte", UInt,0, UInt,0, UInt,pKey, Int,-1, UInt,0, Int,0, UInt,0, UInt,0)
         VarSetCapacity(wStr, nLen)
         DllCall("WideCharToMultiByte", UInt,0, UInt,0, UInt,pKey, Int,-1, Str,wStr, Int,nLen, UInt,0, UInt,0)
         If (InStr("DDBFindDDBMatchDDBRegex",label) and (Key="" or (label="DDBFind"
            ? (InStr(wStr,Key)=1) : (label="DDBMatch" ? (InStr(wStr,Key)) : (RegExMatch(wStr,Key)))))){
            bExist++
            If (bExist>skip){
               result.= DDB(pdic,"get",wStr) . (Item!="" ? Item : "`n")
               nLenItm++
               If (limit<=nLenItm){
                  DllCall("oleaut32\SysFreeString", UInt,pKey)
                  Break
               }
            }
         } else if (label="DDBReplace"){
            result:=DDB(pdic,"get",wStr)
            StringReplace,result,result,%Key%,%Item%,% (Item ? Item : "")
            DDB(pdic,"set",wStr,result)
         } else if (label="DDBRegexReplace"){
            result:=DDB(pdic,"get",wStr)
            result:=RegExReplace(result,Key,Item,"",Item ? Item : -1)
            DDB(pdic,"set",wStr,result)
         } else if !InStr("DDBFindDDBMatchDDBRegex",label){
            result.= wStr . (label="DDBGetAll" ? (Key!="" ? Key : "`n") : (Chr(2) . DDB(pdic,"get",wStr) . Chr(3)))
         }
         DllCall("oleaut32\SysFreeString", UInt,pKey)
      }
      If InStr("DDBGetAllDDBFindDDBMatchDDBRegEx",label)
         Return result
      else if (label="DDBReplace"){
         Return
      } else if (label="DDBCopy"){
         Gosub, DDBGetCompMode
         pdic:=Key
      } else Sort,result,% "D" . Chr(3) . (Key ? Key : "")
         Gosub, DDBDeleteAll
      If (label="DDBCopy"){
         Key:= nCompMode ? nCompMode : (Item ? Item : 1)
         Gosub, DDBCreate
      }
      Loop,Parse,result,% Chr(3)
         If (A_LoopField!="")
            DDB(pdic,"add",SubStr(A_LoopField,1,InStr(A_LoopField,Chr(2))-1),SubStr(A_LoopField,InStr(A_LoopField,Chr(2))+1))
   Return
   DDB&:
   DDBEnum:
      If Key>0
         penum%pdic%:=Key
      else If (!penum%pdic% or Key="0")
         DllCall(NumGet(NumGet(pDic%pdic%+0)+80), UInt,pDic%pdic%, UIntP,penum%pdic%) ; create key-list in penum
      If (InStr("Clear0",pDic%pdic%) || DllCall(NumGet(NumGet(penum%pdic%+0)+12), UInt,penum%pdic%, UInt,1, UInt,&var1, UInt,0)) {
            DllCall(NumGet(NumGet(penum%pdic%+0)+8), UInt,penum%pdic%)   ; END: destroy key-list
            penum%dic%=                                                  ; signal end of list
            ErrorLevel=                                                  ; empty
            Return                                                       
      }
      pKey := NumGet(&var1 + 8)
      nLen := DllCall("WideCharToMultiByte", UInt,0, UInt,0, UInt,pKey, Int,-1, UInt,0, Int,0, UInt,0, UInt,0)
      VarSetCapacity(wStr, nLen)
      DllCall("WideCharToMultiByte", UInt,0, UInt,0, UInt,pKey, Int,-1, Str,wStr, Int,nLen, UInt,0, UInt,0)
      DllCall("oleaut32\SysFreeString", UInt,pKey)
      ErrorLevel:=penum%pdic%
   Return wStr
   DDB=:
   DDBSet:
      Gosub,DDBAllocItm
      DllCall(NumGet(NumGet(pDic%pdic%+0)+32), UInt,pDic%pdic%, UInt,&var1, UInt,&var2)  ; 8 (Set0 -> 7)
      DllCall("oleaut32\SysFreeString", UInt,pKey)
      DllCall("oleaut32\SysFreeString", UInt,pItm)
   Return
   DDBHash:
      Gosub, DDBAllocKey
      DllCall(NumGet(NumGet(pDic%pdic%+0)+48), UInt,pDic%pdic%, UInt,&var1, IntP,bExist)
      DllCall(NumGet(NumGet(pDic%pdic%+0)+84), UInt,pDic%pdic%, UInt,&var1, UInt,&var2)
      result := NumGet(&var2+8)
      DllCall("oleaut32\SysFreeString", UInt,pKey)
      Return result
   Return
   DDB~:
   DDBRename:
      Gosub,DDBAllocItm
      DllCall(NumGet(NumGet(pDic%pdic%+0)+56), UInt,pDic%pdic%, UInt,&var1, UInt,&var2)
      DllCall("oleaut32\SysFreeString", UInt,pKey)
      DllCall("oleaut32\SysFreeString", UInt,pItm)
   Return
   DDB-:
   DDBDelete:
   Gosub,DDBAllocKey
   DllCall(NumGet(NumGet(pDic%pdic%+0)+64), UInt,pDic%pdic%, UInt,&var1)
   DllCall("oleaut32\SysFreeString", UInt,pKey)
   Return
   DDB_:
   DDBDeleteAll:
   Return DllCall(NumGet(NumGet(pDic%pdic%+0)+68), UInt,pDic%pdic%)
   DDBC:
   DDBCount:
      DllCall(NumGet(NumGet(pDic%pdic%+0)+44), UInt,pDic%pdic%, IntP,result)
   Return result
   DDBD:
   DDBDestroy:
      DllCall(NumGet(NumGet(pDic%pdic%+0)+8), UInt,pDic%pdic%)
      StringReplace,DDBAll,DDBAll,|pDic%pdic%|
   Return
   DDBN:
   DDBCreate:
      If !Init
         DllCall("ole32\CoInitialize", UInt,0),Init:=1
         ,VarSetCapacity(var1, 16, 0),VarSetCapacity(var2, 16, 0),NumPut(8, var1),NumPut(8, var2)
      DDBAll.="|" . pdic . "|"
      VarSetCapacity(CLSID, 16)
      VarSetCapacity(wStr, 79)
      DllCall("MultiByteToWideChar", UInt,0, UInt,0, UInt,&CLSIDString, Int,-1, UInt,&wStr, Int,79)
      DllCall("ole32\CLSIDFromString", Str,wStr, Str,CLSID)
      VarSetCapacity(IID, 16)
      DllCall("MultiByteToWideChar", UInt,0, UInt,0, UInt,&IIDString, Int,-1, UInt,&wStr, Int,79)
      DllCall("ole32\CLSIDFromString", Str,wStr, Str,IID)
      DllCall("ole32\CoCreateInstance", Str,CLSID, UInt,0, UInt,5, Str,IID, UIntP,pDic%pdic%) ; CLSCTX=5
      DllCall(NumGet(NumGet(pDic%pdic%+0)+72), UInt,pDic%pdic%, Int,Key) ; Set compare mode
   Return
   DDBGetCompMode:
      DllCall(NumGet(NumGet(pDic%pdic%+0)+76), UInt,pDic%pdic%, IntP,nCompMode)
   return nCompMode
   DDBDA:
   DDBDestroyAll:
      Loop,Parse,DDBAll,|
         If (A_LoopField!="")
            DllCall(NumGet(NumGet(A_LoopField+0)+8), UInt,A_LoopField)
      DDBAll=
   Return
   DDB:
      If DDBDestroyAll
         Gosub, DDBDestroyAll
      DllCall("ole32\CoUnInitialize")
   Return
   DDBAllocItm: ;Internal
      VarSetCapacity(wStr, (StrLen(Item))*2 + 1)
      DllCall("MultiByteToWideChar", UInt,0, UInt,0, UInt,&Item, Int,-1, UInt,&wStr, Int,StrLen(Item)+1)
      pItm := DllCall("oleaut32\SysAllocString", Str,wStr)
      NumPut(pItm,&var2+8)
   DDBAllocKey: ;Internal
      VarSetCapacity(wStr, (StrLen(Key))*2 + 1)
      DllCall("MultiByteToWideChar", UInt,0, UInt,0, UInt,&Key, Int,-1, UInt,&wStr, Int,StrLen(Key)+1)
      pKey := DllCall("oleaut32\SysAllocString", Str,wStr)
      NumPut(pKey,&var1+8)
   Return
}

_________________
AHK_H (2alpha) AHF TT _Struct WatchDir Yaml _Input ObjTree RapidHotkey DynaRun Wink


Last edited by HotKeyIt on Sun Jun 28, 2009 5:33 pm; edited 2 times in total
Back to top
View user's profile Send private message
HotKeyIt



Joined: 18 Jun 2008
Posts: 4647
Location: AHK Forum

PostPosted: Wed Jun 24, 2009 2:19 pm    Post subject: Reply with quote

Below you will find a test using DDB vs. COM vs. Laszlo vers. and vs. toralf version.

Edit:
Add and get are faster than com now Very Happy
But DDB consumes still more memory, please help Sad
Code:

#Include %A_ScriptDir%\Com.ahk
#Include %A_ScriptDir%\DDB.ahk
SetBatchLines,-1
;DDB create
DDB("DB","n",0)
;COM_Init() ; Initialized COM in DDB already
d := COM_CreateObject("Scripting.Dictionary") ; Create dictionary.

;Dic create by Toralf
Dic()

;Create Dictionary by Laszlo
dic:=CreateDictionary()

;how ofter to loop
LoopTimes:=10000


SplashTextOn,300,20,Creating %looptimes% items using DDB function
;Create 10000 Items
Start:=A_TickCount
Loop % LoopTimes
   DDB("DB","+",A_Index,A_Index)
CreateDDB:=A_TickCount-Start

SplashTextOn,300,20,Creating %looptimes% items using COM function
Start:=A_TickCount
Loop % LoopTimes
   COM_Invoke(d,"Item",A_Index,A_Index)
CreateCOM:=A_TickCount-Start

SplashTextOn,300,20,Creating %looptimes% items using Dic function
Start:=A_TickCount
Loop % LoopTimes
   Dic_Add(A_Index,A_Index)
CreateDic:=A_TickCount-Start

SplashTextOn,300,20,Creating %looptimes% items using Add function
Start:=A_TickCount
Loop % LoopTimes
   Add(dic,A_Index,A_Index)
CreateDict:=A_TickCount-Start

SplashTextOff
MsgBox % "Create " LoopTimes " items`nDDB: " CreateDDB "`nCOM: " CreateCOM "`nDic: " CreateDic "`nAdd: " CreateDict


SplashTextOn,300,20,Get %looptimes% items using DDB function
Start:=A_TickCount
Loop % LoopTimes
   DDB("DB","<",A_Index,A_Index)
CreateDDB:=A_TickCount-Start

SplashTextOn,300,20,Get %looptimes% items using COM function
Start:=A_TickCount
Loop % LoopTimes
   COM_Invoke(d,"Item",A_Index)
CreateCOM:=A_TickCount-Start

SplashTextOn,300,20,Get %looptimes% items using Dic function
Start:=A_TickCount
Loop % LoopTimes
   Dic_Get(A_Index)
CreateDic:=A_TickCount-Start

SplashTextOn,300,20,Get %looptimes% items using Get function
Start:=A_TickCount
Loop % LoopTimes
   Get(dic, A_Index)
CreateDict:=A_TickCount-Start
SplashTextOff
MsgBox % "Get " LoopTimes " items`nDDB: " CreateDDB "`nCOM: " CreateCOM "`nDic: " CreateDic "`nGet: " CreateDict




COM_Release(d) ; Done using dictionary d.
;COM_Term() ; Done using COM is done in DDB()
Dic(1)
Destroydictionary(dic)
DDB()




;###############################################################################
;###  Scripting.Dictionary COM object Modul                                  ###
;###############################################################################
Dic(Action=""){
    static initialized, pdic
    If (Action = "pdic")               ;return pdic
        Return pdic
    Else If Action {                   ;exit - clean up
        Dic_DestroyDictionary(pdic)
        ;DllCall("ole32\CoUninitialize")
    }Else{                             ;create a dictionary
        ;If !initialized {
        ;    initialized := True
        ;    DllCall("ole32\CoInitialize", UInt,0)
        ;  }
        pdic := Dic_CreateDictionary()
      }
    Return 1
  }

Dic_Add(sKey, sItm) {  ; If key exists: no effect (<--> Set)
   pdic := Dic("pdic")
   Dic_AllocBString(pKey, var1, sKey)
   Dic_AllocBString(pItm, var2, sItm)
   DllCall(Dic_VTable(pdic,10), UInt,pdic, UInt,&var1, UInt,&var2)
   DllCall("oleaut32\SysFreeString", UInt,pKey)
   DllCall("oleaut32\SysFreeString", UInt,pItm)
}

Dic_Set(sKey, sItm) {  ; If key exists, update the item, Else create a new entry
   pdic := Dic("pdic")
   Dic_AllocBString(pKey, var1, sKey)
   Dic_AllocBString(pItm, var2, sItm)
   DllCall(Dic_VTable(pdic,8), UInt,pdic, UInt,&var1, UInt,&var2)  ; 8 (Set0 -> 7)
   DllCall("oleaut32\SysFreeString", UInt,pKey)
   DllCall("oleaut32\SysFreeString", UInt,pItm)
}

Dic_Get(sKey) {  ; empty if not exists
   pdic := Dic("pdic")
   Dic_AllocBString(pKey, var1, sKey)
   DllCall(Dic_VTable(pdic,12), UInt,pdic, UInt,&var1, IntP,bExist)
   If bExist {     ; to avoid creating an unwanted new entry
      VarSetCapacity(var2, 16, 0)
      DllCall(Dic_VTable(pdic,9), UInt,pdic, UInt,&var1, UInt,&var2)
      pItm := *(&var2+8) | *(&var2+9) << 8 | *(&var2+10) << 16 | *(&var2+11) << 24
      Dic_Unicode2Ansi(pItm, sItm)
      DllCall("oleaut32\SysFreeString", UInt,pItm)
   }
   DllCall("oleaut32\SysFreeString", UInt,pKey)
   Return sItm
}

Dic_NextKey(ByRef penum) {                         ; penum = "": create new list
   pdic := Dic("pdic")
   If penum =                                          ; not static: allow multiple independent lists
      DllCall(Dic_VTable(pdic,20), UInt,pdic, UIntP,penum) ; create key-list in penum
   VarSetCapacity(var, 16, 0)
   If DllCall(Dic_VTable(penum,3), UInt,penum, UInt,1, UInt,&var, UInt,0) {
      DllCall(Dic_VTable(penum,2), UInt,penum)             ; END: destroy key-list
      penum =                                          ; signal end of list
      Return                                           ; empty
   }
   pKey := Dic_UInt@(&var + 8)
   Dic_Unicode2Ansi(pKey, sKey)
   DllCall("oleaut32\SysFreeString", UInt,pKey)
   Return skey
}

Dic_Count() {      ; #entries
   pdic := Dic("pdic")
   DllCall(Dic_VTable(pdic,11), UInt,pdic, IntP,nCount)
   Return nCount
}

Dic_Exists(sKey) {
   pdic := Dic("pdic")
   Dic_AllocBString(pKey, var, sKey)
   DllCall(Dic_VTable(pdic,12), UInt,pdic, UInt,&var, IntP,bExist)
   DllCall("oleaut32\SysFreeString", UInt,pKey)
   Return bExist
}

Dic_Rename(sKeyFr, sKeyTo) {
   pdic := Dic("pdic")
   Dic_AllocBString(pKeyFr, var1, sKeyFr)
   Dic_AllocBString(pKeyTo, var2, sKeyTo)
   DllCall(Dic_VTable(pdic,14), UInt,pdic, UInt,&var1, UInt,&var2)
   DllCall("oleaut32\SysFreeString", UInt,pKeyFr)
   DllCall("oleaut32\SysFreeString", UInt,pKeyTo)
}

Dic_Remove(sKey) {
   pdic := Dic("pdic")
   Dic_AllocBString(pKey, var, sKey)
   DllCall(Dic_VTable(pdic,16), UInt,pdic, UInt,&var)
   DllCall("oleaut32\SysFreeString", UInt,pKey)
}

Dic_RemoveAll() {
   pdic := Dic("pdic")
   Return DllCall(Dic_VTable(pdic,17), UInt,pdic)
}

Dic_SetCompareMode(nCompMode = 1) { ; 0: Binary, 1: Text, 2: Database, n: LCID
   pdic := Dic("pdic")
   Modes = btd
   Loop, Parse, Modes
      If RegExMatch(nCompMode, "i)^" A_LoopField)
         nCompMode := A_Index - 1
   DllCall(Dic_VTable(pdic,18), UInt,pdic, Int,nCompMode)
}

Dic_GetCompareMode() {
   pdic := Dic("pdic")
   DllCall(Dic_VTable(pdic,19), UInt,pdic, IntP,nCompMode)
   Return nCompMode
}

Dic_HashVal(sKey) {
   pdic := Dic("pdic")
   Dic_AllocBString(pKey, var1, sKey)
   DllCall(Dic_VTable(pdic,12), UInt,pdic, UInt,&var1, IntP,bExist)
   VarSetCapacity(var2, 16, 0)
   DllCall(Dic_VTable(pdic,21), UInt,pdic, UInt,&var1, UInt,&var2)
   nHashVal := *(&var2+8) | *(&var2+9) << 8 | *(&var2+10) << 16 | *(&var2+11) << 24
   DllCall("oleaut32\SysFreeString", UInt,pKey)
   Return nHashVal
}

;#########  PRIVATE FUNCTIONS   ################################################

Dic_CreateDictionary() {
    CLSID_Dictionary := "{EE09B103-97E0-11CF-978F-00A02463E06F}"
    IID_IDictionary  := "{42C642C1-97E1-11CF-978F-00A02463E06F}"
    Return Dic_CreateObject(CLSID_Dictionary, IID_IDictionary)
  }

Dic_DestroyDictionary(pdic) {
    DllCall(Dic_UInt@(Dic_UInt@(pdic)+8), UInt,pdic)
  }

Dic_AllocBString(ByRef Key, ByRef Var, sString) {
   Dic_Ansi2Unicode(sString, wString)
   Key := DllCall("oleaut32\SysAllocString", Str,wString)
   VarSetCapacity(Var, 16, 0)
   DllCall("ntdll\RtlFillMemoryUlong", UInt,&Var,  UInt,4, UInt,8)
   DllCall("ntdll\RtlFillMemoryUlong", UInt,&Var+8,UInt,4, UInt,Key)
}

Dic_UInt@(ptr) {
   Return *ptr | *(ptr+1) << 8 | *(ptr+2) << 16 | *(ptr+3) << 24
}

Dic_CreateObject(ByRef CLSID, ByRef IID, CLSCTX = 5) {
   If StrLen(CLSID) = 38
      Dic_GUID4String(CLSID, CLSID)
   If StrLen(IID) = 38
      Dic_GUID4String(IID, IID)
   DllCall("ole32\CoCreateInstance", Str,CLSID, UInt,0, UInt,CLSCTX, Str,IID, UIntP,ppv)
   Return ppv
}
Dic_GUID4String(Byref CLSID, sString) {
   VarSetCapacity(CLSID, 16)
   Dic_Ansi2Unicode(sString, wString, 38)
   DllCall("ole32\CLSIDFromString", Str,wString, Str,CLSID)
}
Dic_Ansi2Unicode(ByRef sString, ByRef wString, nLen = 0) {
   If !nLen
      nLen := DllCall("MultiByteToWideChar", UInt,0, UInt,0, UInt,&sString, Int,-1, UInt,0, Int,0)
   VarSetCapacity(wString, nLen*2 + 1)
   DllCall("MultiByteToWideChar", UInt,0, UInt,0, UInt,&sString, Int,-1, UInt,&wString, Int,nLen)
}
Dic_VTable(ppv, idx) {
   Return Dic_UInt@(Dic_UInt@(ppv) + idx*4)
}
Dic_Unicode2Ansi(ByRef wString, ByRef sString, nLen = 0) {
   pString := wString + 0 > 65535 ? wString : &wString
   If !nLen
      nLen := DllCall("WideCharToMultiByte", UInt,0, UInt,0, UInt,pString, Int,-1, UInt,0, Int,0, UInt,0, UInt,0)
   VarSetCapacity(sString, nLen)
   DllCall("WideCharToMultiByte", UInt,0, UInt,0, UInt,pString, Int,-1, Str,sString, Int,nLen, UInt,0, UInt,0)
}


;By Laszlo

CreateDictionary(nCompMode = 0) { ; Compare mode = 0: Binary, 1: Text, 2: Database, n: LCID
   CLSID_Dictionary := "{EE09B103-97E0-11CF-978F-00A02463E06F}"
   IID_IDictionary  := "{42C642C1-97E1-11CF-978F-00A02463E06F}"
   pdic := CreateObject(CLSID_Dictionary, IID_IDictionary)
   DllCall(VTable(pdic,18), UInt,pdic, Int,nCompMode) ; Set compare mode
   Return pdic
}

DestroyDictionary(pdic) {
   DllCall(UInt@(UInt@(pdic)+8), UInt,pdic)
}

Add(pdic, sKey, sItm) {  ; If key exists: no effect (<--> Set)
   AllocBString(pKey, var1, sKey)
   AllocBString(pItm, var2, sItm)
   DllCall(VTable(pdic,10), UInt,pdic, UInt,&var1, UInt,&var2)
   DllCall("oleaut32\SysFreeString", UInt,pKey)
   DllCall("oleaut32\SysFreeString", UInt,pItm)
}

Set(pdic, sKey, sItm) {  ; If key exists, update the item, Else create a new entry
   AllocBString(pKey, var1, sKey)
   AllocBString(pItm, var2, sItm)
   DllCall(VTable(pdic,8), UInt,pdic, UInt,&var1, UInt,&var2)  ; 8 (Set0 -> 7)
   DllCall("oleaut32\SysFreeString", UInt,pKey)
   DllCall("oleaut32\SysFreeString", UInt,pItm)
}

Get(pdic, sKey) {  ; empty if not exists
   AllocBString(pKey, var1, sKey)
   DllCall(VTable(pdic,12), UInt,pdic, UInt,&var1, IntP,bExist)
   If bExist {     ; to avoid creating an unwanted new entry
      VarSetCapacity(var2, 16, 0)
      DllCall(VTable(pdic,9), UInt,pdic, UInt,&var1, UInt,&var2)
      pItm := *(&var2+8) | *(&var2+9) << 8 | *(&var2+10) << 16 | *(&var2+11) << 24
      Unicode2Ansi(pItm, sItm)
      DllCall("oleaut32\SysFreeString", UInt,pItm)
   }
   DllCall("oleaut32\SysFreeString", UInt,pKey)
   Return sItm
}

Count(pdic) {      ; #entries
   DllCall(VTable(pdic,11), UInt,pdic, IntP,nCount)
   Return nCount
}

Exists(pdic, sKey) {
   AllocBString(pKey, var, sKey)
   DllCall(VTable(pdic,12), UInt,pdic, UInt,&var, IntP,bExist)
   DllCall("oleaut32\SysFreeString", UInt,pKey)
   Return bExist
}

Rename(pdic, sKeyFr, sKeyTo) {
   AllocBString(pKeyFr, var1, sKeyFr)
   AllocBString(pKeyTo, var2, sKeyTo)
   DllCall(VTable(pdic,14), UInt,pdic, UInt,&var1, UInt,&var2)
   DllCall("oleaut32\SysFreeString", UInt,pKeyFr)
   DllCall("oleaut32\SysFreeString", UInt,pKeyTo)
}

Remove(pdic, sKey) {
   AllocBString(pKey, var, sKey)
   DllCall(VTable(pdic,16), UInt,pdic, UInt,&var)
   DllCall("oleaut32\SysFreeString", UInt,pKey)
}

RemoveAll(pdic) {
   Return DllCall(VTable(pdic,17), UInt,pdic)
}

GetCompareMode(pdic) {
   DllCall(VTable(pdic,19), UInt,pdic, IntP,nCompMode)
   Return nCompMode
}

HashVal(pdic,sKey) {
   AllocBString(pKey, var1, sKey)
   DllCall(VTable(pdic,12), UInt,pdic, UInt,&var1, IntP,bExist)
   VarSetCapacity(var2, 16, 0)
   DllCall(VTable(pdic,21), UInt,pdic, UInt,&var1, UInt,&var2)
   nHashVal := *(&var2+8) | *(&var2+9) << 8 | *(&var2+10) << 16 | *(&var2+11) << 24
   DllCall("oleaut32\SysFreeString", UInt,pKey)
   Return nHashVal
}

NextKey(ByRef penum, pdic="") {                        ; penum = "": create new list. pdic=0,"Clear": destroy list
   If penum =                                          ; not static: allow multiple independent lists
      DllCall(VTable(pdic,20), UInt,pdic, UIntP,penum) ; create key-list in penum
   VarSetCapacity(var, 16, 0)
   If (InStr("Clear0",pdic) || DllCall(VTable(penum,3), UInt,penum, UInt,1, UInt,&var, UInt,0)) {
      DllCall(VTable(penum,2), UInt,penum)             ; END: destroy key-list
      penum =                                          ; signal end of list
      Return                                           ; empty
   }
   pKey := UInt@(&var + 8)
   Unicode2Ansi(pKey, sKey)
   DllCall("oleaut32\SysFreeString", UInt,pKey)
   Return skey
}

AllocBString(ByRef Key, ByRef Var, sString) {
   Ansi2Unicode(sString, wString)
   Key := DllCall("oleaut32\SysAllocString", Str,wString)
   VarSetCapacity(Var, 16, 0)
   DllCall("ntdll\RtlFillMemoryUlong", UInt,&Var,  UInt,4, UInt,8)
   DllCall("ntdll\RtlFillMemoryUlong", UInt,&Var+8,UInt,4, UInt,Key)
}

UInt@(ptr) {
   Return *ptr | *(ptr+1) << 8 | *(ptr+2) << 16 | *(ptr+3) << 24
}

;;; COM Helper functions

CreateObject(ByRef CLSID, ByRef IID, CLSCTX = 5) {
   If StrLen(CLSID) = 38
      GUID4String(CLSID, CLSID)
   If StrLen(IID) = 38
      GUID4String(IID, IID)
   DllCall("ole32\CoCreateInstance", Str,CLSID, UInt,0, UInt,CLSCTX, Str,IID, UIntP,ppv)
   Return ppv
}
GUID4String(Byref CLSID, sString) {
   VarSetCapacity(CLSID, 16)
   Ansi2Unicode(sString, wString, 38)
   DllCall("ole32\CLSIDFromString", Str,wString, Str,CLSID)
}
Ansi2Unicode(ByRef sString, ByRef wString, nLen = 0) {
   If !nLen
      nLen := DllCall("MultiByteToWideChar", UInt,0, UInt,0, UInt,&sString, Int,-1, UInt,0, Int,0)
   VarSetCapacity(wString, nLen*2 + 1)
   DllCall("MultiByteToWideChar", UInt,0, UInt,0, UInt,&sString, Int,-1, UInt,&wString, Int,nLen)
}
VTable(ppv, idx) {
   Return UInt@(UInt@(ppv) + idx*4)
}
Unicode2Ansi(ByRef wString, ByRef sString, nLen = 0) {
   pString := wString + 0 > 65535 ? wString : &wString
   If !nLen
      nLen := DllCall("WideCharToMultiByte", UInt,0, UInt,0, UInt,pString, Int,-1, UInt,0, Int,0, UInt,0, UInt,0)
   VarSetCapacity(sString, nLen)
   DllCall("WideCharToMultiByte", UInt,0, UInt,0, UInt,pString, Int,-1, Str,sString, Int,nLen, UInt,0, UInt,0)
}

_________________
AHK_H (2alpha) AHF TT _Struct WatchDir Yaml _Input ObjTree RapidHotkey DynaRun Wink
Back to top
View user's profile Send private message
autokeyminer



Joined: 21 May 2010
Posts: 12

PostPosted: Tue Jul 13, 2010 4:04 pm    Post subject: Reply with quote

The two download links at the top seem to be dead. Maybe it is temporary. Will you check them?
_________________
Anyone have any comments?

Cheerio,
Autokeyminer Cool

autokeyminer@ymail.com
Back to top
View user's profile Send private message Send e-mail
Display posts from previous:   
Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions All times are GMT
Goto page Previous  1, 2, 3, 4, 5  Next
Page 4 of 5

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum


Powered by phpBB © 2001, 2005 phpBB Group