- I had in mind, for the Encoding parameter: 'hex' for lower-case hex, 'Hex' (or any other case other than 'hex') for upper-case hex, and 'Base64' (any case).
- I've tried to implement all of the more fiddly ideas in my wish list request myself, as custom functions, to explore their feasibility, and, to explain clearly my intentions, being some reasons. AFAIK this, my extended Sort function, and my slightly-improved dialogs are the last examples.
Sort function + extra features - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=6&t=50431
slightly-improved dialogs - AutoHotkey Community
https://autohotkey.com/boards/viewtopic ... 37&t=45220
- WARNING: If something like this was in theory to be implemented as built-in functionality, into AHK, the design could be subtly or significantly different. However, I did try to create functions that matched the nature of StrPut/StrGet. Also, errors relating to writing to specific memory addresses and allocating memory can lead to script crashes. Also, these functions have not been extensively tested.
Code: Select all
;functions:
;JEE_HexGet(vAddr, oParams*) ;vAddr, vSize, vCase:="U"
;JEE_HexPut(ByRef vHex, oParams*)
;JEE_Base64Get(vAddr, oParams*) ;vAddr, vSize
;JEE_Base64Put(ByRef vBase64, oParams*)
;JEE_StrGet(vAddr, oParams*)
;JEE_StrPut(vText, oParams*)
;JEE_StrIsType(vText, vType)
;notes (base64):
;Base64 - Wikipedia
;https://en.wikipedia.org/wiki/Base64
;Specifically, given an input of n bytes, the output will be [4*Ceil(n/3)] bytes long, including padding characters.
;notes (StrPut/StrGet):
;StrPut / StrGet
;https://autohotkey.com/docs/commands/StrPutGet.htm
;[the default encoding is *CP0* (ANSI) and not CP0/UTF-16 depending on A_IsUnicode]
;Specify an empty string or "CP0" to use the system default ANSI code page.
;[StrPut with UTF-16 returns a char count, not a byte count]
;StrPut returns char count, but VarSetCapacity needs bytes.
q:: ;add hex/base64 support to StrPut/StrGet
;we need a rare string as an example:
;for use with CP0/UTF-8/UTF-16 it can be any string
;it must be a valid hex string (0-9A-F, multiple of 2 bytes)
;it must be a valid base64 string (A-Za-z0-9+/, multiple of 4 bytes, padded with =)
;so this requires: (0-9A-F, multiple of 4 bytes)
vText := "aabbccddeeff"
;vText := "aabbccddeeffaabbccddeeff"
vList := ",CP0,UTF-8,UTF-16,Hex,hex,Base64"
vOutput := ""
Loop, Parse, vList, % ","
{
vEnc := A_LoopField
vMult := (vEnc = "UTF-16"||vEnc = "CP1200") ? 2 : 1
vSize := JEE_StrPut(vText, A_LoopField)
vSize2 := vSize
VarSetCapacity(vData, vMult*vSize, 0)
if (vEnc = "Hex")
vSize2 *= 4
else if (vEnc = "Base64")
vSize2 := 4*Ceil(vSize/3)
JEE_StrPut(vText, &vData, vSize2, vEnc)
vRet := JEE_StrGet(&vData, vSize, vEnc)
vOutput .= (vMult*vSize) "`t" A_LoopField "`t" vRet "`r`n"
}
MsgBox, % vOutput
return
;==================================================
; q:: ;hex get/put example (data)
; vHex := "AABBCCDD"
; VarSetCapacity(vData, StrLen(vHex)/2, 0)
; JEE_HexPut(vHex, &vData)
; vNum := NumGet(&vData, 0, "UInt")
; MsgBox, % Format("0x{:X}", vNum) ;0xDDCCBBAA
; MsgBox, % JEE_HexGet(&vData, 3) ;AABBCC
; MsgBox, % JEE_HexGet(&vData, 3, "L") ;aabbcc
; return
; ;hex get example (file)
; vPath := A_AhkPath
; if !oFile := FileOpen(vPath, "r")
; return
; vSize := oFile.Length
; VarSetCapacity(vData, vSize)
; oFile.RawRead(&vData, oFile.Length)
; oFile.Close()
; Clipboard := JEE_HexGet(&vData, vSize)
; return
;cf. StrGet(Address [, Length] [, Encoding := None])
;case: U/L (upper/lower)
JEE_HexGet(vAddr, oParams*) ;vAddr, vSize, vCase:="U"
{
static vIsVistaPlus := (DllCall("kernel32\GetVersion", UInt) & 0xFF) >= 6
vCase := "U"
if (oParams.Length() = 2) ;Address, Length, Case
vSize := oParams.1, vCase := oParams.2
else if !JEE_StrIsType(oParams.1, "number") ;Address, Case
vCase := oParams.1, vSize := 0
else if (oParams.1 = 0) ;Address, Length
return
else if oParams.HasKey(1) ;Address, Length
vSize := oParams.1
else ;Address
vSize := 0
if vIsVistaPlus
{
;CRYPT_STRING_NOCRLF := 0x40000000
;CRYPT_STRING_HEXRAW := 0xC ;to return raw hex (not supported by Windows XP)
DllCall("crypt32\CryptBinaryToString", Ptr,vAddr, UInt,vSize, UInt,0x4000000C, Ptr,0, UIntP,vChars)
VarSetCapacity(vHex, vChars*2, 0)
DllCall("crypt32\CryptBinaryToString", Ptr,vAddr, UInt,vSize, UInt,0x4000000C, Str,vHex, UIntP,vChars)
}
else
{
;CRYPT_STRING_HEX := 0x4 ;to return space/CRLF-separated text
DllCall("crypt32\CryptBinaryToString", Ptr,vAddr, UInt,vSize, UInt,0x4, Ptr,0, UIntP,vChars)
VarSetCapacity(vHex, vChars*2, 0)
DllCall("crypt32\CryptBinaryToString", Ptr,vAddr, UInt,vSize, UInt,0x4, Str,vHex, UIntP,vChars)
vHex := StrReplace(vHex, "`r`n")
vHex := StrReplace(vHex, " ")
}
return (vCase = "L") ? vHex : Format("{:U}", vHex)
}
;==================================================
;cf. StrPut(String [, Encoding := None])
;cf. StrPut(String, Address [, Length] [, Encoding := None])
JEE_HexPut(ByRef vHex, oParams*)
{
if !oParams.Length()
return Floor(StrLen(vHex)/2)
vAddr := oParams.RemoveAt(1)
if oParams.HasKey(1)
vChars := oParams.1
else
vChars := StrLen(vHex)
;CRYPT_STRING_HEX := 0x4
;CRYPT_STRING_HEXRAW := 0xC ;(not supported by Windows XP)
;DllCall("crypt32\CryptStringToBinary", Ptr,&vHex, UInt,vChars, UInt,0x4, Ptr,0, UIntP,vSize, Ptr,0, Ptr,0)
vSize := Floor(vChars/2)
DllCall("crypt32\CryptStringToBinary", Ptr,&vHex, UInt,vChars, UInt,0x4, Ptr,vAddr, UIntP,vSize, Ptr,0, Ptr,0)
return vSize ;bytes written
}
;==================================================
; q:: ;base64 get/put example
; ;create ANSI string 'abcdefghijklmnopqrstuvwxyz'
; VarSetCapacity(vData, 26, 0)
; Loop, 26
; NumPut(96+A_Index, &vData, A_Index-1, "UChar")
; vSize := 26
; vBase64 := JEE_Base64Get(&vData, vSize)
; MsgBox, % vBase64 ;YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXo=
; vBase64 := "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXo="
; vSize := JEE_Base64Put(vBase64)
; VarSetCapacity(vAnsi, vSize+1, 0)
; JEE_Base64Put(vBase64, &vAnsi)
; MsgBox, % StrGet(&vAnsi, "CP0")
; return
;cf. StrGet(Address [, Length] [, Encoding := None])
JEE_Base64Get(vAddr, oParams*) ;vAddr, vSize
{
if (oParams.Length() = 2)
vSize := oParams.1
if !JEE_StrIsType(oParams.1, "number")
vSize := 0
else if (oParams.1 = 0)
return
else if oParams.HasKey(1)
vSize := oParams.1
else
vSize := 0
if !JEE_StrIsType(vSize, "number")
vSize := 0
;CRYPT_STRING_BASE64 := 0x1
DllCall("crypt32\CryptBinaryToString", Ptr,vAddr, UInt,vSize, UInt,0x1, Ptr,0, UIntP,vChars)
VarSetCapacity(vBase64, vChars*2, 0)
DllCall("crypt32\CryptBinaryToString", Ptr,vAddr, UInt,vSize, UInt,0x1, Str,vBase64, UIntP,vChars)
return StrReplace(vBase64, "`r`n")
}
;==================================================
;cf. StrPut(String [, Encoding := None])
;cf. StrPut(String, Address [, Length] [, Encoding := None])
JEE_Base64Put(ByRef vBase64, oParams*)
{
if !oParams.Length()
{
DllCall("crypt32\CryptStringToBinary", Ptr,&vBase64, UInt,vChars, UInt,0x1, Ptr,0, UIntP,vSize, Ptr,0, Ptr,0)
return vSize
}
vAddr := oParams.RemoveAt(1)
if oParams.HasKey(1)
vChars := oParams.1
else
vChars := StrLen(vBase64)
;CRYPT_STRING_BASE64 := 0x1
DllCall("crypt32\CryptStringToBinary", Ptr,&vBase64, UInt,vChars, UInt,0x1, Ptr,0, UIntP,vSize, Ptr,0, Ptr,0)
DllCall("crypt32\CryptStringToBinary", Ptr,&vBase64, UInt,vChars, UInt,0x1, Ptr,vAddr, UIntP,vSize, Ptr,0, Ptr,0)
return vSize ;bytes written
}
;==================================================
;StrPut(String [, Encoding := None])
;StrPut(String, Address [, Length] [, Encoding := None])
;StrGet(Address [, Length] [, Encoding := None])
;StrPut(vText [, vEnc:=""])
;StrPut(vText, vAddr [, vLen] [, vEnc:=""])
;StrGet(vAddr [, vLen] [, vEnc:=""])
;JEE_HexPut(vText)
;JEE_HexPut(vText, vAddr [, vLen])
;JEE_HexGet(vAddr, vSize, vCase:="U")
;JEE_Base64Put(vText)
;JEE_Base64Put(vText, vAddr [, vLen])
;JEE_Base64Get(vAddr, vSize)
;cf. StrGet(Address [, Length] [, Encoding := None])
JEE_StrGet(vAddr, oParams*)
{
if !oParams.Length()
return StrGet(vAddr) ;Address
else if (oParams.Length() > 2)
return
else if (oParams.Length() = 1) ;Address, Length
&& JEE_StrIsType(oParams.1, "number")
return StrGet(vAddr, oParams.1)
vEnc := oParams.Pop()
if (vEnc == "hex")
vFunc := "JEE_HexGet", vEnc := "L"
else if (vEnc = "Hex")
vFunc := "JEE_HexGet", vEnc := "U"
else if (vEnc = "Base64")
vFunc := "JEE_Base64Get", vEnc := ""
else
vFunc := "StrGet"
if oParams.Length() ;Address, Length, Encoding
return %vFunc%(vAddr, oParams.1, vEnc)
else ;Address, Encoding
return %vFunc%(vAddr, vEnc)
}
;==================================================
;cf. StrPut(String [, Encoding := None])
;cf. StrPut(String, Address [, Length] [, Encoding := None])
JEE_StrPut(vText, oParams*)
{
if !oParams.Length() ;String
return StrPut(vText)
else if (oParams.Length() > 3)
return
if !JEE_StrIsType(oParams.1, "number") ;String, Encoding
if (oParams.1 = "Hex")
return JEE_HexPut(vText)
else if (oParams.1 = "Base64")
return JEE_Base64Put(vText)
else
return StrPut(vText, oParams.1)
if (oParams.Length() = 2)
&& JEE_StrIsType(oParams.2, "number") ;String, Address, Length
return StrPut(vText, oParams.1, oParams.2)
vEnc := oParams.Pop()
if (vEnc = "Hex")
vFunc := "JEE_HexPut"
else if (vEnc = "Base64")
vFunc := "JEE_Base64Put"
else
vFunc := "StrPut"
if (oParams.Length() = 2)
return %vFunc%(vText, oParams.1, oParams.2, vEnc) ;String, Address, Length, Encoding
else
return %vFunc%(vText, oParams.1) ;String, Address, Encoding
}
;==================================================
;If Var is [not] integer|float|number|digit|xdigit|alpha|upper|lower|alnum|space|time
;e.g. if JEE_StrIsType(vText, "digit")
JEE_StrIsType(vText, vType)
{
%vType% := vType ;for AHK v2
;if JEE_StrIsType(vText, vType) ;[appearance of line below if converted, warning: this would cause an infinite loop]
if vText is %vType% ;[DO NOT CONVERT]
return 1
else
return 0
}
;==================================================