Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

StrPut / StrGet


  • Please log in to reply
10 replies to this topic
Lexikos
  • Administrators
  • 9844 posts
  • AutoHotkey Foundation
  • Last active:
  • Joined: 17 Oct 2006
StrPut / StrGet

Copies a string to or from a memory address, optionally converting it between code pages.
StrPut(String [color=darkgray][[/color], Encoding [color=darkgray]= None ][/color] )
StrPut(String, Address [color=darkgray][[/color], Length[color=darkgray]] [[/color], Encoding [color=darkgray]= None ][/color] )
StrGet(Address [color=darkgray][[/color], Length[color=darkgray]] [[/color], Encoding [color=darkgray]= None ][/color] )
Behaviour should be identical to their built-in counterparts in AutoHotkey_L.

Recommended usage: Copy StrPut.ahk and StrGet.ahk into a function library folder. Do not #include. This way, if your script is run on AutoHotkey_L, it will use the built-in functions rather than these script functions.

Download: See attachments below.

Documentation

BoBo³
  • Guests
  • Last active:
  • Joined: --
Thx for sharing :D

fincs
  • Moderators
  • 1662 posts
  • Last active:
  • Joined: 05 May 2007
For those still using vanilla :)

Lexikos
  • Administrators
  • 9844 posts
  • AutoHotkey Foundation
  • Last active:
  • Joined: 17 Oct 2006
I've fixed some errors in StrPut which had limited its functionality to measuring/encoding UTF-16 strings and copying ANSI strings.

Lexikos
  • Administrators
  • 9844 posts
  • AutoHotkey Foundation
  • Last active:
  • Joined: 17 Oct 2006
Now I've fixed a similar error in StrGet. :oops:

jballi
  • Members
  • 1029 posts
  • Last active:
  • Joined: 01 Oct 2005
I just discovered these functions. Yes, I know that I'm very late to the party. They will be very helpful as I slowly but surely (don't call me Shirley!) transition to AHK_L. Thanks. :)

Mag748
  • Members
  • 10 posts
  • Last active: Jun 07 2013 10:35 PM
  • Joined: 30 May 2013


Download: See attachments below.

 

I have looked all over and can't for the life of me find a download link for the StrPut AHK Basic script. Can anyone point me in the correct direction?

 

I must be missing something, and I appologize for the inconvenience.

 

.

 

Sincerely,

Marcus



Rseding91
  • Members
  • 703 posts
  • Last active: Apr 02 2016 05:05 AM
  • Joined: 07 Jun 2010

I have the StrGet() function - does anyone have the StrPut() function?

 

 

 

EDIT: I found the StrPut() function although I'm not sure if it's the latest one or not - see the next post.

StrGet(Address, Length=-1, Encoding=0)
{
 ; Flexible parameter handling:
 if Length is not integer
 Encoding := Length,  Length := -1
 ; Check for obvious errors.
 if (Address+0 < 1024)
  return
 ; Ensure 'Encoding' contains a numeric identifier.
 if Encoding = UTF-16
  Encoding = 1200
 else if Encoding = UTF-8
  Encoding = 65001
 else if SubStr(Encoding,1,2)="CP"
  Encoding := SubStr(Encoding,3)
 if !Encoding ; "" or 0
 {
  ; No conversion necessary, but we might not want the whole string.
  if (Length == -1)
   Length := DllCall("lstrlen", "uint", Address)
  VarSetCapacity(String, Length)
  DllCall("lstrcpyn", "str", String, "uint", Address, "int", Length + 1)
 }
 else if Encoding = 1200 ; UTF-16
 {
  char_count := DllCall("WideCharToMultiByte", "uint", 0, "uint", 0x400, "uint", Address, "int", Length, "uint", 0, "uint", 0, "uint", 0, "uint", 0)
  VarSetCapacity(String, char_count)
  DllCall("WideCharToMultiByte", "uint", 0, "uint", 0x400, "uint", Address, "int", Length, "str", String, "int", char_count, "uint", 0, "uint", 0)
 }
 else if Encoding is integer
 {
  ; Convert from target encoding to UTF-16 then to the active code page.
  char_count := DllCall("MultiByteToWideChar", "uint", Encoding, "uint", 0, "uint", Address, "int", Length, "uint", 0, "int", 0)
  VarSetCapacity(String, char_count * 2)
  char_count := DllCall("MultiByteToWideChar", "uint", Encoding, "uint", 0, "uint", Address, "int", Length, "uint", &String, "int", char_count * 2)
  String := StrGet(&String, char_count, 1200)
 }
 
 return String
}


Rseding91
  • Members
  • 703 posts
  • Last active: Apr 02 2016 05:05 AM
  • Joined: 07 Jun 2010

StrPut():

 

StrPut(String, Address="", Length=-1, Encoding=0)
{
    if A_IsUnicode
    {
        MsgBox %A_ThisFunc% does not support Unicode. Use the AutoHotkey_L (revision 46+) built-in version instead. The script will now exit.
        ExitApp
    }

; Flexible parameter handling:
    if Address is not integer ; StrPut(String [, Encoding])
        Encoding := Address, Length := 0, Address := 1024
    else if Length is not integer ; StrPut(String, Address, Encoding)
        Encoding := Length, Length := -1

; Check for obvious errors.
    if (Address+0 < 1024)
        return

; Ensure 'Encoding' contains a numeric identifier.
    if Encoding = UTF-16
        Encoding = 1200
    else if Encoding = UTF-8
        Encoding = 65001
    else if SubStr(Encoding,1,2)="CP"
        Encoding := SubStr(Encoding,3)
   
    if !Encoding ; "" or 0
    {
; No conversion required.
        char_count := StrLen(String) + 1 ; + 1 because generally a null-terminator is wanted.
        if (Length)
        {
; Check for sufficient buffer space.
            if (StrLen(String) <= Length || Length == -1)
            {
                if (StrLen(String) == Length)
; Exceptional case: caller doesn't want a null-terminator.
                    char_count--
; Copy the string, including null-terminator if requested.
                DllCall("RtlMoveMemory", "uint", Address, "uint", &String, "uint", char_count)
            }
            else
; For consistency with the sections below, don't truncate the string.
                char_count = 0
        }
;else: Caller just wants the the required buffer size (char_count), which will be returned below.
    }
    else if Encoding = 1200 ; UTF-16
    {
; See the 'else' to this 'if' below for comments.
        if (Length <= 0)
        {
            char_count := DllCall("MultiByteToWideChar", "uint", 0, "uint", 0, "uint", &String, "int", StrLen(String), "uint", 0, "int", 0) + 1
            if (Length == 0)
                return char_count
            Length := char_count
        }
        char_count := DllCall("MultiByteToWideChar", "uint", 0, "uint", 0, "uint", &String, "int", StrLen(String), "uint", Address, "int", Length)
        if (char_count && char_count < Length)
            NumPut(0, Address+0, char_count++*2, "UShort")
    }
    else if Encoding is integer
    {
; Convert native ANSI string to UTF-16 first. NOTE - wbuf_len includes the null-terminator.
        VarSetCapacity(wbuf, 2 * wbuf_len := StrPut(String, "UTF-16")), StrPut(String, &wbuf, "UTF-16")

; UTF-8 and some other encodings do not support this flag. Avoid it for UTF-8
; (which is probably common) and rely on the fallback behaviour for other encodings.
        flags := Encoding=65001 ? 0 : 0x400 ; WC_NO_BEST_FIT_CHARS
        if (Length <= 0) ; -1 or 0
        {
; Determine required buffer size.
            loop 2 {
                char_count := DllCall("WideCharToMultiByte", "uint", Encoding, "uint", flags, "uint", &wbuf, "int", wbuf_len, "uint", 0, "int", 0, "uint", 0, "uint", 0)
                if (char_count || A_LastError != 1004) ; ERROR_INVALID_FLAGS
                    break
                flags := 0 ; Try again without WC_NO_BEST_FIT_CHARS.
            }
            if (!char_count)
                return ; FAIL
            if (Length == 0) ; Caller just wants the required buffer size.
                return char_count
; Assume there is sufficient buffer space and hope for the best:
            Length := char_count
        }
; Convert to target encoding.
        char_count := DllCall("WideCharToMultiByte", "uint", Encoding, "uint", flags, "uint", &wbuf, "int", wbuf_len, "uint", Address, "int", Length, "uint", 0, "uint", 0)
; Since above did not null-terminate, check for buffer space and null-terminate if there's room.
; It is tempting to always null-terminate (potentially replacing the last byte of data),
; but that would exclude this function as a means to copy a string into a fixed-length array.
        if (char_count && char_count < Length)
            NumPut(0, Address+0, char_count++, "Char")
; else no space to null-terminate; or conversion failed.
    }
; Return the number of characters copied.
    return char_count
}


Mag748
  • Members
  • 10 posts
  • Last active: Jun 07 2013 10:35 PM
  • Joined: 30 May 2013
Dear Rseding91,

Thank you very much for the response. I have just tried using the StrGet() function you listed, and I get an error on line 36 that there is a call to nonexistent function StrGetB.

Maybe there is another function that this one requires?

Thanks,
Marcus

Rseding91
  • Members
  • 703 posts
  • Last active: Apr 02 2016 05:05 AM
  • Joined: 07 Jun 2010

Dear Rseding91,

Thank you very much for the response. I have just tried using the StrGet() function you listed, and I get an error on line 36 that there is a call to nonexistent function StrGetB.

Maybe there is another function that this one requires?

Thanks,
Marcus

 

Sorry about that, just change it to "strget" and it will work. I had it renamed in the script where I used it.