Jump to content


Photo

[Func] VarInit(). Load a byte sequence into a variable.


  • Please log in to reply
3 replies to this topic

#1 VxE

VxE
  • Fellows
  • 3508 posts

Posted 14 March 2012 - 01:28 AM

This is my solution to a wish. In that thread, the OP wished to change VarSetCapacity() to return the variable's address instead of the available capacity.

The consensus in that thread was that VarSetCapacity() is just fine the way it is, but that someone might find it convenient to have variable initialization and getting the variable's address all in one function.

So, I came up with this. At it's simplest level, this function is the same as Laszlo's mighty MCode() function. Here's a summary of the bells and whistles I added:[*:21fktfo6] Returns the address of 'var'
[*:21fktfo6] The hex string may (or may not) start with "0x" and may be an odd number of characters long (an implicit '0' is appended to odd-length strings)
[*:21fktfo6] The byte sequence represented by the hex string may be replicated any number of times.
[*:21fktfo6] Compatible with AHK-L and AHK-Basic
VarInit( BYREF var, hex_string, multiplier = 1 ) { ; > http://www.autohotkey.com/forum/viewtopic.php?t=83760
; Function by [VxE]. Allocates space for a variable, insert data from a hex string (optionally replicating the
; byte sequence multiple times) and return the variable's address. 
	oel := ErrorLevel, Ptr := !A_PtrSize ? "UInt" : "Ptr", multiplier := 1 < multiplier ? 0 | multiplier : 1
	StringTrimLeft hex_string, hex_string, 1 = InStr( hex_string, "0x" ) ? 2 : 0
	If ( 1 < byte_count := 1 + StrLen( hex_string ) >> 1 )
	{
		VarSetCapacity( var, byte_count * multiplier + 2 ), hex_string .= "0"

		Loop % byte_count
			NumPut( "0x" SubStr( hex_string, 2 * A_Index - 1, 2 ), var, A_Index - 1, "Char" )

		Loop % Ceil( Ln( multiplier ) / Ln( 2 ) )
			DllCall( "RtlMoveMemory", Ptr, &var + ( byte_count << A_Index - 1 ), Ptr, &var, "UInt", multiplier >> A_Index ? byte_count << A_Index - 1 : byte_count * ( multiplier - ( 1 << A_Index - 1 ) ) )
	}
	Else VarSetCapacity( var, byte_count * multiplier + 2, hex_string = "" ? 0 : "0x" string )

	Return &var, NumPut( 0, var, byte_count * multiplier, "Short" ), ErrorLevel := oel
}

Example:
; Create a string of "123" repeated 1000 times
VarInit( string, A_IsUnicode ? "310032003300" : "313233", 1000 )
VarSetCapacity( string, -1 )
MsgBox %string%


#2 Guests

  • Guests

Posted 14 March 2012 - 04:18 AM

This is my solution to a wish. In that thread, the OP wished to change VarSetCapacity() to return the variable's address instead of the available capacity.

The consensus in that thread was that VarSetCapacity() is just fine the way it is, but that someone might find it convenient to have variable initialization and getting the variable's address all in one function.

It seems you have misunderstood the wish. The idea is to add an option to the function to return the address, meaning the function would not change the behavior without the option.

Otherwise, good effort.

#3 sinkfaze

sinkfaze
  • Moderators
  • 6089 posts

Posted 14 March 2012 - 05:11 AM

Guest,

I ask that you direct any wish discussion back to the original wish thread, where [VxE] was nice enough to post a comment referencing this thread in the event that the discussion should continue. Let us leave this thread for people to comment on the value of the function.

#4 VxE

VxE
  • Fellows
  • 3508 posts

Posted 15 March 2012 - 02:13 AM

Thanks for the backup, sinkfaze. I honestly don't expect much discussion (unless there are bugs *knocks wood*) since VarInit offers nothing that hasn't already been demonstrated.

My primary reason for posting it here is to (eventually) build a collection of practical examples, tentatively including SendMessage where the address of a struct is passed in the lparam, structs/arrays to receive data (e.g: GetDeviceGammaRamp), and one or two listview messages.