I was looking at whether I could get a dynamic string into a type that I could use PB's routines against. Here's the result.
Essentially you declare a dword somewhere (such as in a type).
You do nothing, it's initially an empty string.
If you want to assign it a value you use the result of AllocateString( "my value" )
When you no longer want the string you call FreeString
If you want to use PB's string routines you call AquireString. When you're done using the routines you call ReleaseString.
You can get the length of the string calling StringLen without acquiring the string.
Could have some bugs in it, but the trivial example seemed to work...
ManualStrings.bas
Edit: Note, these strings should only be used as rval, never as lvals. what that means is you can use them, but you can't ask PB to alter them. You can assign to a pb string, alter the pb string, and then assign back. Some examples of where not to use acquired strings are:
aquiredString += value ' BAD
Replace "x" with "y" In aquiredString ' BAD
The basic rules are:
Any AquiredString must call ReleaseString when you are done with the string variable.
Any AssignString, AllocateString, CopyString must call FreeString when the string value is no longer needed.
I added SafeString which returns a native PB string and can be used in any context. It does not need to be released or freed. It's simpler to use at the cost of a string assignment (i.e. copy).
Essentially you declare a dword somewhere (such as in a type).
You do nothing, it's initially an empty string.
If you want to assign it a value you use the result of AllocateString( "my value" )
When you no longer want the string you call FreeString
If you want to use PB's string routines you call AquireString. When you're done using the routines you call ReleaseString.
You can get the length of the string calling StringLen without acquiring the string.
Could have some bugs in it, but the trivial example seemed to work...
ManualStrings.bas
Code:
#Compile Exe #Dim All #Include "windows.inc" ' Makes value be the string pointed to by p. These can only be used as RVAL's. 'Sub AquireString( ByVal p As Dword, value As String ) ' Releases a string that was aquired 'Sub ReleaseString( value As String ) ' Returns the length of a string without aquiring it 'Function StringLen( ByVal p As Dword Ptr ) As Long 'Assigns a value to a string 'Sub AssignString( p As Dword, value As String ) 'Returns a pointer to a newly allocated string 'Function AllocateString( value As String ) As Dword 'Releases the memory for an Assigned or Allocated string 'Sub FreeString( p As Dword ) 'Copies a string 'Sub CopyString( src As Dword, dst As Dword ) 'Returns a safe PB string, can be safely used as an lval, does not need to be released 'Function SafeString( src As Dword ) As String Type StringExample name As Dword other As Dword End Type Function PBMain () As Long Local v As StringExample v.name = AllocateString( "This is a test" ) Local b, a As String AquireString v.name, a b = a + " for sure" ReleaseString a AssignString v.name, b ? a ' s/b empty AquireString v.name, a ? a ' s/b "This is a test for sure" ReleaseString a ? Str$( StringLen( v.name ) ) CopyString v.name, v.other AquireString v.other, a ? a ReleaseString a FreeString( v.name ) FreeString( v.other ) End Function Sub AquireString( ByVal p As Dword, value As String ) value = "" ' Release whatever the string was pointing to Poke Dword, VarPtr( value ), p End Sub Sub ReleaseString( value As String ) Poke Dword, VarPtr( value ), 0 End Sub Function StringLen( ByVal p As Dword Ptr ) As Long p-=4 Function = @p End Function Sub AssignString( p As Dword, value As String ) If p Then FreeString p p = AllocateString( value ) End Sub Function AllocateString( value As String ) As Dword Local p As Dword Ptr If Len(value)=0 Then Function = 0 Exit Function End If p = GlobalAlloc( %GMEM_FIXED, Len(value)+5 ) Memory Copy StrPtr(value), p+4, Len(value)+1 @p = Len(value) Function = p+4 End Function Sub FreeString( p As Dword ) If p=0 Then Exit Sub p -= 4 GlobalFree( p ) p = 0 End Sub Sub CopyString( src As Dword, dst As Dword ) Local a As String If src=dst Then Exit Sub ' Self copies are really quick! If dst<>0 Then FreeString dst AquireString src, a dst = AllocateString( a ) ReleaseString a End Sub Function SafeString( src As Dword ) As String Local a, b As String AquireString src, a b = a ReleaseString a Function = b End Function
aquiredString += value ' BAD
Replace "x" with "y" In aquiredString ' BAD
The basic rules are:
Any AquiredString must call ReleaseString when you are done with the string variable.
Any AssignString, AllocateString, CopyString must call FreeString when the string value is no longer needed.
I added SafeString which returns a native PB string and can be used in any context. It does not need to be released or freed. It's simpler to use at the cost of a string assignment (i.e. copy).
Comment