Hi, everybody.
I read what
Jassing wrote above and decided to try and make it as fast as possible.
Well...
The following listing is based on
Wilbert's code. I know it could have been made simpler, but again, I wanted to make it as fast as possible. The essence of the cycle / iteration of a substring by bytes (strings from 30 to 36) is somewhat similar to the native function
CountString(), only it is intended for a memory area. Maybe
Fred will add this in the next version ?
The main reason for this memory routine is to avoid the concatenation process. Do everything in memory, and then only once read the entire resulting piece of memory as a whole and assign it to a string variable. This complex question has been discussed many times on this forum and I looked at a lot of code before writing this. Working with memory only in the name of achieving the best code speed.
Okay...
At first glance the code works. But I have doubts that everything is done correctly. Especially regarding null characters in strings.
ShowMemoryViewer() always displays the contents of memory in a stable manner. But the debugger window sometimes randomly stays blank. Why ? I made a mistake somewhere, but I can't find it on my own. Perhaps I miscalculated the number of bytes for the string.
I would like to ask more experienced members of our forum to look at the final code if you have time. And... point me to the error. Or I'd love to hear your point of view. Can this be further simplified ? I am using PB version without C-backend support. Also, I don't want to add assembler inserts to the code. Use only native functions.
Thank you in advance.
Code: Select all
Macro pIncrement
*pointer + ByteLength
*p + ByteLength
EndMacro
Procedure.s SplitDquotesString(String.s, Separator.s = " ", replace.s = "") ; replace.s = only one char !
Protected S.String, *S.Integer = @S
Protected.i p, slen, counter, rByte
Protected.i ByteLength, memsize
Protected.i *mem, *pointer, *p, *pEnd
Protected.b Byte
Protected result$
slen = Len(Separator)
rByte = Asc(replace) ; byte to replace
ByteLength = SizeOf(Character)
memsize = StringByteLength(String)
*mem = AllocateMemory(memsize, #PB_Memory_NoClear)
*pointer = *mem
*p = *mem
*pEnd = *mem + memsize
*S\i = @String
Repeat
p = FindString(S\s, Separator)
CopyMemoryString(PeekS(*S\i, p - 1), @*pointer)
While *p < *pointer
Byte = PeekB(*p)
If Byte = 34 ; 34 = #DQUOTE$
counter = counter + 1
EndIf
*p + ByteLength
Wend
If 1 &~ counter
If rByte
If (*pEnd - *pointer) > 0
PokeB(*pointer, rByte)
pIncrement
EndIf
EndIf
Else
PokeS(*pointer, Separator, -1, #PB_String_NoZero)
pIncrement
EndIf
*S\i + (p + slen - 1) << #PB_Compiler_Unicode
Until p = 0
*S\i = 0
ShowMemoryViewer(*mem, memsize)
result$ = PeekS(*mem, memsize)
FreeMemory(*mem)
*mem = 0
ProcedureReturn result$
EndProcedure
S.s = "this," + #DQUOTE$ + "this" + #DQUOTE$ + "," + #DQUOTE$ + "should, be" + #DQUOTE$ + ", " + #DQUOTE$ + "three fields" + #DQUOTE$ ; + "," + #DQUOTE$ + "XZZ ZXZ, CCZ" + #DQUOTE$
Debug S
Debug "---------------------------------------"
Debug ""
Debug SplitDquotesString(S, ",", Chr(10))
;Debug ""
;Debug SplitDquotesString(S, ",")