Enumeration ;ReplaceStringAt results
#ReplaceStringAt_OK
#ReplaceStringAt_PositionGreaterThanDestinationLength
#ReplaceStringAt_PositionPlusLengthGreaterThanDestinationLength
#ReplaceStringAt_LengthGreaterThanReplacementLength
EndEnumeration
Procedure ReplaceStringAt(*Pd, *Pr, Position, Length)
;Loop through the string to the requested position, ensuring we don't reach the end
;of the destination string
For i = 1 To Position - 1
If PeekB(*Pd) = 0
ProcedureReturn #ReplaceStringAt_PositionGreaterThanDestinationLength
EndIf
*Pd + 1
Next i
For i = 1 To Length
;as we move through both the source and destination ensure that
;we don't reach the end of either
If PeekB(*Pd) = 0
ProcedureReturn #ReplaceStringAt_PositionPlusLengthGreaterThanDestinationLength
EndIf
If PeekB(*Pr) = 0
ProcedureReturn #ReplaceStringAt_LengthGreaterThanReplacementLength
EndIf
PokeB(*Pd, PeekB(*Pr))
*Pd + 1
*Pr + 1
Next i
EndProcedure
Procedure assert(Test, Description.s)
If Test
Debug Description + ": Pass"
Else
Debug Description + ": Fail"
EndIf
EndProcedure
;Test a good request
t.s = "123456789"
Result = ReplaceStringAt(@t, @"XXX", 4, 3)
assert(Result = #ReplaceStringAt_OK And t = "123XXX789", "OK")
;If the replacement is shorter than length it is ignored
t.s = "123456789"
Result = ReplaceStringAt(@t, @"XXXXX", 4, 3)
assert(Result = #ReplaceStringAt_OK And t = "123XXX789", "OK")
;If the position is off the end of the destination the string
;will remain unchanged.
t = "123456789"
Result = ReplaceStringAt(@t, @"XXX", 11, 3)
assert(Result = #ReplaceStringAt_PositionGreaterThanDestinationLength And t = "123456789", "PositionGreaterThanDestinationLength")
;If the replacment runs off the end of the destinatino we
;change what we can but destination is not extended.
t = "123456789"
Result = ReplaceStringAt(@t, @"XXX", 8, 3)
assert(Result = #ReplaceStringAt_PositionPlusLengthGreaterThanDestinationLength And t = "1234567XX", "PositionPlusLengthGreaterThanDestinationLength")
;If replacement is shorter than the given length we replace what we have
t = "123456789"
Result = ReplaceStringAt(@t, @"XXX", 4, 5)
assert(Result = #ReplaceStringAt_LengthGreaterThanReplacementLength And t = "123XXX789", "LengthGreaterThanReplacementLength")
ukandrewc wrote:Also, I have passed a 400K string to PB from VB, and am able alter and pass it back. Is this not supposed to happen?
When you use a PB function that returns a string, the function stores the result in a buffer and the application retrieves that string from the buffer and assigns it to the variable the result should be assigned to.
The standard buffer size is 64000 bytes. If you manipulate a string yourself, without using this buffer, a 400KB string is no problem at all. If you do want to use such a string with the PB functions, you have to increase the buffer size. For testing purposes I worked with a 4 megabyte string that way without any problems.
There is a thread here somewhere where large strings were discussed. (I can't find the thread now so maybe it was in th bugs area and dopped or maybe I am searching badly - but I remember seeing it)
From recollection (vague) the conclusion was that very large strings give the illusion of being OK, but cause probs down the track. There was also some sort of work-around which was hotly argued.
; free the old string buffer
! pushd [_PB_StringBase]
! pushd 0
! pushd [_PB_MemoryBase]
! call _HeapFree@12
; allocate a new string buffer of 512KB
! pushd 524288
! pushd 8
! pushd [_PB_MemoryBase]
! call _HeapAlloc@12
! mov [_PB_StringBase],eax
; create a 400KB string
myLongString.s = Space(409600)
Debug Len(myLongString)
This works fine for me.
What could cause problems is if there are string functions with a loop inside that is based on a 16 bit counter (for example in asm cx instead of ecx) but I don't know if there are PB functions like that.