- A Tiny 2L Function to maintain a single dimension UINT array
FA(E=0,V="",S="") { ; www.autohotkey.com/forum/viewtopic.php?p=242750#242750
Static C,P
Return ((E+0)>=0&&V="")?(NumGet(P+0,E*4)):(E&&(V+0)>=0)?(NumPut(V,P+0,E*4)-4):(S="+"&&V
>0)?((O:=NumPut((V:=NumGet(E*4+P)+V),E*4+P))-O+V):(S="-"&&V>0)?((O:=NumPut((V:=NumGet(E*4
+P)-V),E*4+P))-O+V):(E>0&&V="Init")?(VarSetCapacity(C,(E+1)*4,0)+(P:=NumPut(E,C)-4)-P):(E
="Rel"&&P)?((P:=0)+VarSetCapacity(C,0)+1):(E="Ptr"&&P) ? P : ""
}
; [color=red]The above ternary version was derived from following code[/color]
/*
[color=darkblue]FA( E=0,V="",S="" ) {
Static C,P
If ((E+0)>=0&&V="") ; NumGet
Return (NumGet(P+0,E*4))
If (E&&(V+0)>=0) ; NumPut
Return (NumPut(V,P+0,E*4)-4)
If (S="+"&&V>0) ; NumAdd
Return ((O:=NumPut((V:=NumGet(E*4+P)+V),E*4+P))-O+V)
If (S="-"&&V>0) ; NumSub
Return ((O:=NumPut((V:=NumGet(E*4+P)-V),E*4+P))-O+V)
If (E>0&&V="Init") ; Init Var
Return,(VarSetCapacity(C,(E+1)*4,0)+(P:=NumPut(E,C)-4)-P)
If (E="Rel"&&P) ; Release Var
Return ((P:=0)+VarSetCapacity(C,0)+1)
If (E="Ptr"&&P) ; Obtain Pointer
Return P
} [/color]
*/
The primary objective of this function is to provide a mechanism to share Integers between functions, thereby avoiding a clutter of Global variables.
In short, FA() is a function that acts as an single dimension array
The parameters are cumbersome to document, and so, I provide here example calls, instead.
Basic:
FA(10,"Init") ; Initialise capacity for 10 UINT elements
; Returns the Static Variable's size
FA(6,25000) ; Put 25000 in element 6
; Returns the pointer to the UINT
FA(4,0) ; Nullify element 4
; same as above
FA(7) ; Return the value stored in element 7
Extended:
Support for counters.
FA(6,1230,"+") ; Increment the value stored in element 6 by 1230
; Returns the new value
FA(6,1230,"-") ; Decrement the value stored in element 6 by 1230
; Returns the new value
For any further manipulation, the pointer to the array can be retrieved..
FA("Ptr")
..and to release/reset the array
FA("Rel")
My Requirement:
With forth-coming release: 1.0.48, using ProcAddress directly in DllCall() would increase the performance significantly. I needed a mechanism to initialise the and share the ProcAddresses between many functions of the same wrapper - without creating global variables, and hence I wrote FA()
The following is a dumb, but working example of my intended use.
MsgBox, % FormatBytes( GetFileSize( A_AhkPath ) )
MsgBox, % FormatBytes( GetFileSize( A_ScriptFullPath ) )
GetFileSize( File ) { ; 4GB Limit
Static Init,FOpen,FSeek,FClose
If !Init
Init:=InitAPI(), FOpen:=FA(1),FSeek:=FA(3),FClose:=FA(4)
If ( H := DllCall(FOpen,Str,File,Int,0x0) ) < 1
Return H
FilePointer := DllCall(FSeek,Int,H,Int,0,Int,2), DllCall(FClose,UInt,H)
Return FilePointer
}
FormatBytes( Bytes ) {
Static FormatBytes
If !FormatBytes
FormatBytes:=FA(11), VarSetCapacity(Formatted,16)
DllCall(FormatBytes, Int64,Bytes, Str,Formatted, UInt,16 )
Return Formatted
}
InitAPI() {
Static Funx
IfNotEqual,Funx,,Return,Funx
FA( 20, "Init" ) ; Initialise 20 UINT elements
Kernel32 := DllCall( "GetModuleHandle", Str,"Kernel32.dll" )
FA( 1, DllCall( "GetProcAddress", UInt,Kernel32, Str,"_lopen" ) )
FA( 2, DllCall( "GetProcAddress", UInt,Kernel32, Str,"_lread" ) )
FA( 3, DllCall( "GetProcAddress", UInt,Kernel32, Str,"_llseek" ) )
FA( 4, DllCall( "GetProcAddress", UInt,Kernel32, Str,"_lclose" ) )
FA( 5, DllCall( "GetProcAddress", UInt,Kernel32, Str,"_lcreat" ) )
FA( 6, DllCall( "GetProcAddress", UInt,Kernel32, Str,"_lwrite" ) )
FA( 7, DllCall( "GetProcAddress", UInt,Kernel32, Str,"RtlMoveMemory" ) )
ShlwAPI := DllCall( "LoadLibrary", Str,"Shlwapi.dll" )
FA( 11, DllCall( "GetProcAddress", UInt,ShlwAPI, Str,"StrFormatByteSize64A" ) )
; unused elements are for future use
Return (Funx:=1)
}
FA(E=0,V="",S="") { ; www.autohotkey.com/forum/viewtopic.php?p=242750#242750
Static C,P
Return ((E+0)>=0&&V="")?(NumGet(P+0,E*4)):(E&&(V+0)>=0)?(NumPut(V,P+0,E*4)-4):(S="+"&&V
>0)?((O:=NumPut((V:=NumGet(E*4+P)+V),E*4+P))-O+V):(S="-"&&V>0)?((O:=NumPut((V:=NumGet(E*4
+P)-V),E*4+P))-O+V):(E>0&&V="Init")?(VarSetCapacity(C,(E+1)*4,0)+(P:=NumPut(E,C)-4)-P):(E
="Rel"&&P)?((P:=0)+VarSetCapacity(C,0)+1):(E="Ptr"&&P) ? P : ""
}