AutoHotkey Community

It is currently May 25th, 2012, 2:53 am

All times are UTC [ DST ]




Post new topic Reply to topic  [ 62 posts ]  Go to page Previous  1, 2, 3, 4, 5  Next
Author Message
 Post subject:
PostPosted: April 27th, 2007, 5:06 pm 
Offline

Joined: February 12th, 2007, 7:54 am
Posts: 2462
Chris wrote:
Sean, to the extent you agree with Laszlo's changes, maybe you'd consider applying them to the topmost post.

I was thinking about rewriting the Enumerate() function, so I may incorporate the NextKey() function.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: April 27th, 2007, 5:22 pm 
Offline

Joined: February 12th, 2007, 7:54 am
Posts: 2462
Laszlo wrote:
AllocString() does more than SysAllocString() in CoHelper.ahk (fill memory). The AllocString name was meant to avoid conflicts with the original. It does allocate a string now, so foom might accept this name for a different functionality.

Sorry, I didn't pay a careful attention.
So, you separated the function to create a variant whose element is BString.
Hmm, would you consider again about the name? IMHO, the name better contain the implication that it's owned by the system.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: April 27th, 2007, 7:13 pm 
Offline

Joined: February 14th, 2005, 4:05 pm
Posts: 4710
Location: Boulder, CO
Sean wrote:
the name better contain the implication that it's owned by the system.
How about SysAllocStringB()?


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: April 27th, 2007, 10:58 pm 
Offline

Joined: February 12th, 2007, 7:54 am
Posts: 2462
Laszlo wrote:
How about SysAllocStringB()?

I was thinking about AllocBString, as I'm not aware of the usage of BString outside COM, but I may be wrong. Personally, anything would be fine if it contains either Sys or B.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: April 27th, 2007, 11:29 pm 
Offline

Joined: February 14th, 2005, 4:05 pm
Posts: 4710
Location: Boulder, CO
Changed to AllocBString, for popular demand :)


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: April 28th, 2007, 1:00 am 
Offline

Joined: February 12th, 2007, 7:54 am
Posts: 2462
Laszlo wrote:
Changed to AllocBString, for popular demand :)

:lol:

Thanks for the change.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: May 11th, 2007, 9:47 pm 
Offline

Joined: January 31st, 2005, 9:50 am
Posts: 3910
Location: Bremen, Germany
I managed to go through Laszlos code. That version is much easier to diggest. It doesn't seem to be too complicated. The only thing I do not like is that I have to provide the dictonary handle to each function. Is there a different way to avoid this then making it global?
Of cause this handle helps to create different namespaces, but I could also name the vars as a combination of namespace and varname.

Another thing to use it as a module, would be if there is a simple init function, so that it is easier to start with. And if needed also an exit function.

_________________
Ciao
toralf
Image


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: May 11th, 2007, 9:52 pm 
Offline

Joined: January 31st, 2005, 9:50 am
Posts: 3910
Location: Bremen, Germany
I was surprised to see the add() function of AHK be overloaded, untill I relalized that AHK doesn't have an add() function. It is just used as an example for functions in the manual. :)
But it would have been a cool feature. >)

_________________
Ciao
toralf
Image


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: May 11th, 2007, 10:07 pm 
Offline

Joined: February 14th, 2005, 4:05 pm
Posts: 4710
Location: Boulder, CO
toralf wrote:
I have to provide the dictionary handle to each function. Is there a different way to avoid this then making it global?
Of cause this handle helps to create different namespaces, but I could also name the vars as a combination of namespace and varname.
If you only use one dictionary, you can make its handle global. You can also pre-process your script, to insert the name of the appropriate handle to the dictionary functions, but until AHK will have true block structure, you have to do this manually.
toralf wrote:
a simple init function, so that it is easier to start with. And if needed also an exit function.
In the beginning you only need
Code:
DllCall("ole32\CoInitialize", UInt,0)
and for each dictionary
Code:
pdic := CreateDictionary()
I cannot imagine a simpler initialization. Maybe, the function CreateDictionary could call CoInitialize at the first invocation, so you don't need even that single line. Similarly
Code:
DestroyDictionary(pdic)
DllCall("ole32\CoUninitialize")
are the only things you need at exit.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: May 11th, 2007, 10:14 pm 
Offline

Joined: January 31st, 2005, 9:50 am
Posts: 3910
Location: Bremen, Germany
Will the dictonary destroy itself when the script exists, or is it mandatory to call the two commands?

_________________
Ciao
toralf
Image


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: May 11th, 2007, 10:49 pm 
Offline

Joined: February 14th, 2005, 4:05 pm
Posts: 4710
Location: Boulder, CO
I think it leaks, but try it in a loop, to see if the free memory is reduced


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: May 11th, 2007, 10:59 pm 
Offline

Joined: January 31st, 2005, 9:50 am
Posts: 3910
Location: Bremen, Germany
Maybe like this (as a module):
Code:
Dic()

Dic_Add("Test1", "This is a Test1")
Dic_Add("Test2", "This is a Test2")
Dic_Add("Test1", "This is a Test3")       ; no effect, already exists
Dic_Add("Test3", "This is a Test9")
Dic_Add("Test0", "")

Dic_Set("Result1", "This is a Result1")   ; create and set
Dic_Set("Result2", "This is a Result2")
Dic_Set("Result1", "This is a Result3")   ; overwrite

Dic_Rename("Result1", "Result3")
Dic_Remove("Test3")

MsgBox, % "Hash of 'Test9': " . Dic_HashVal("Test9")
MsgBox, % "Count: " . Dic_Count()

MsgBox % "Test1:"  . Dic_Get("Test1")
MsgBox % "test2:"  . Dic_Get("test2")     ; empty

Loop {
  k := Dic_NextKey(penum)
  IfEqual penum,, Break                    ; k (Itm) can be empty
  MsgBox % "[1/"  . A_Index . "]" . k . ":" . Dic_Get(k)
}
Loop % Dic_Count() {
  k := Dic_NextKey(penum)
  MsgBox % "[2a/" . A_Index . "]" . k . ":" . Dic_Get(k)
  k := Dic_NextKey(penu1)
  MsgBox % "[2b/" . A_Index . "]" . k . ":" . Dic_Get(k)
}

Dic("Exit")
Return


;###############################################################################
;###  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)
}
I hope I didn't screw up the code. I do not know if it is ok that i removed the optional pdic parameter from NextKey() function. What was the purpose to have it optional anyway? Could it be renamed to "Next"? Acctually I do not 100% understand what NextKey does. Could you please explain it?

_________________
Ciao
toralf
Image


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: May 11th, 2007, 11:19 pm 
Offline

Joined: January 31st, 2005, 9:50 am
Posts: 3910
Location: Bremen, Germany
And this would be the very slim version (only 90 lines of code for the module with only Set and Get functionality)
Code:
Dic()

Dic_Set("Result1", "This is a Result1")   ; create and set
Dic_Set("Result2", "This is a Result2")
Dic_Set("Result1", "This is a Result3")   ; overwrite

MsgBox % "Result2:"  . Dic_Get("Result2")
     . "`ntest2:"    . Dic_Get("test2")     ; empty
     . "`nResult1:"  . Dic_Get("Result1")     ; empty

Dic("Exit")
Return


;###############################################################################
;###  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_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
}
;#########  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)
}

_________________
Ciao
toralf
Image


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: May 11th, 2007, 11:36 pm 
Offline

Joined: February 14th, 2005, 4:05 pm
Posts: 4710
Location: Boulder, CO
They should work with a single dictionary, but slower than a global handle. If you use informative dictionary names, the original would be much more flexible. After Global := CreateDictionary(), Module2 := CreateDictionary() you can use Add(Global,"x",1), Add(Global,"y",0), Add(Module2,"x", 2)…


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: May 12th, 2007, 8:50 am 
Offline

Joined: January 31st, 2005, 9:50 am
Posts: 3910
Location: Bremen, Germany
Yes it might be a bit slower. I did it to simplify the other functions. Since I plan only to use one dictionary. I could still mimic your example with Add("Global.x",1), Add("Global.y",0), Add("Module2.x", 2)…

I still do not understand why NextKey() in your code has an optional pdic parameter. What is the purpose you made it optional?

_________________
Ciao
toralf
Image


Report this post
Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 62 posts ]  Go to page Previous  1, 2, 3, 4, 5  Next

All times are UTC [ DST ]


Who is online

Users browsing this forum: Bing [Bot] and 11 guests


You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Powered by phpBB® Forum Software © phpBB Group