I hope the comments on every part are enough for a start.
I'm working on the joining part right now.
The procedures should be cross platform, although I can only test it under Windows,
and they are for ASCII and unicode compilation.
You always have to include the first part, because it defines macros and constants:
Code: Select all
CompilerSelect SizeOf(Character)
CompilerCase 1
CompilerCase 2
CompilerCase 4
CompilerDefault: CompilerError "SizeOf(Character) is not 1, 2 or 4"
CompilerEndSelect
Macro UBound(x):(PeekL((@x) - 8) - 1):EndMacro
CompilerIf #PB_Compiler_Unicode
Macro SplitJoinStringType:p-unicode:EndMacro
CompilerElse
Macro SplitJoinStringType:p-ascii:EndMacro
CompilerEndIf
#SplitString_NoEmptyParts = 1 << 16
#SplitString_MultiSingleCharacter = 1 << 17
#SplitString_NoReDim = 1 << 18
#JoinString_NoEmptyParts = 1 << 16
#JoinString_ForceEndSeparator = 1 << 17
#JoinString_KeepOldString = 1 << 18
Code: Select all
; Splitting a string into parts
;
; strIn = String to split for SplitStringToArray()
; Pointer to memory to split for SplitMemoryToArray()
; The memory-block must have a terminating 0 character!
;
; strOut() = String-array which will contain the parts,
; will be automaticly redimed to fit all parts.
;
; separator = Single- or multi-character string by which the string will be splitted
;
; splitFlags= #SplitString_NoEmptyParts : Will omit empty parts of strIn
; #SplitString_MultiSingleCharacter : If separator-string is more than one character,
; every single character counts as separator.
; If not set, the whole separator-string counts
; as one separator.
; #SplitString_NoReDim : strOut() will not be redimed to minimum size
; at end of procedure.
; You can use several flags by oring them together with '|'.
; A value between 1 - 31 can be add to the flags,
; this will set the minimum step for expanding strOut() in 1024's steps.
; The standard step is 256, which will be enough for any normal text-string,
; but if strIn contains many parts, or you split large memory-blocks,
; it might give a speedup if you set a higher step value.
;
;
; splitTo = Optional parameter. Will set the start index for strOut()
; the parts will be splitted to, so you can split
; several strings into one array
;
; *ubValue = Optional pointer to long, will be set to maximum index of strOut() on return
;
; Returns the number of parts for actual splitting
;
; If the separator is 0, or the strIn contains no separators,
; strOut() will containe the whole string and 1 is returned
;
; If strIn is empty or a 0 pointer, strOut() will not be changed, and 0 is returned
Procedure.l _SplitToArray(*strIn.Character, strOut.s(1), *separator.Character, splitFlags.l = 0, splitTo.l = 0, *ubValue.Long = 0)
Protected strOutUBound.l, uBoundStep.l, splitToIdx.l
Protected firstSeparatorCh.l, SecondSeparatorCh.l
Protected separatorCh.l, strInCh.l
Protected *pStrIn.Character, *thirdSeparatorCh.Character
Protected *splitStart.Character, *splitEnd.Character
strOutUBound = UBound(strOut()) ; Get size of array
splitToIdx = splitTo
If splitFlags & 31
uBoundStep = 1024 * (splitFlags & 31)
Else
uBoundStep = 256
EndIf
If *strIn
Repeat
strInCh = *strIn\c
If *separator
firstSeparatorCh = *separator\c
*separator + SizeOf(Character)
EndIf
If Not firstSeparatorCh
If strInCh
If strOutUBound < splitToIdx
strOutUBound = splitToIdx
ReDim strOut.s(strOutUBound)
EndIf
strOut(splitToIdx) = PeekS(*strIn)
splitToIdx + 1
Break
EndIf
Break
EndIf
*pStrIn = *strIn
*splitStart = *strIn
secondSeparatorCh = *separator\c
If secondSeparatorCh ; *** Split by multicharacter-separator ***
If splitFlags & #SplitString_MultiSingleCharacter ; *** Split by mutlicharacter-separator single characters ***
*separator + SizeOf(Character)
*thirdSeparatorCh = *separator
If splitFlags & #SplitString_NoEmptyParts
While strInCh
Repeat
Repeat
If strInCh = firstSeparatorCh Or strInCh = SecondSeparatorCh
Continue ; *** Match ***
EndIf
*separator = *thirdSeparatorCh
While *separator\c
If strInCh = *separator\c
Break 2 ; *** Match ***
EndIf
*separator + SizeOf(Character)
Wend
Break 2
Until 1
If *pStrIn <> *splitStart
If splitToIdx > strOutUBound
strOutUBound + uBoundStep
uBoundStep << 1
ReDim strOut.s(strOutUBound)
EndIf
CompilerSelect SizeOf(Character)
CompilerCase 1 : strOut(splitToIdx) = PeekS(*splitStart, *pStrIn - *splitStart)
CompilerCase 2 : strOut(splitToIdx) = PeekS(*splitStart, (*pStrIn - *splitStart) >> 1)
CompilerCase 4 : strOut(splitToIdx) = PeekS(*splitStart, (*pStrIn - *splitStart) >> 2)
CompilerEndSelect
splitToIdx + 1
EndIf
*splitStart = *pStrIn + SizeOf(Character)
Until 1
*pStrIn + SizeOf(Character)
strInCh = *pStrIn\c
Wend
If *pStrIn <> *splitStart
If splitToIdx > strOutUBound
strOutUBound + uBoundStep
uBoundStep << 1
ReDim strOut.s(strOutUBound)
EndIf
CompilerSelect SizeOf(Character)
CompilerCase 1 : strOut(splitToIdx) = PeekS(*splitStart, *pStrIn - *splitStart)
CompilerCase 2 : strOut(splitToIdx) = PeekS(*splitStart, (*pStrIn - *splitStart) >> 1)
CompilerCase 4 : strOut(splitToIdx) = PeekS(*splitStart, (*pStrIn - *splitStart) >> 2)
CompilerEndSelect
splitToIdx + 1
EndIf
Else ; *** Keep empty parts ***
While strInCh
Repeat
Repeat
If strInCh = firstSeparatorCh Or strInCh = SecondSeparatorCh
Continue ; *** Match ***
EndIf
*separator = *thirdSeparatorCh
While *separator\c
If strInCh = *separator\c
Break 2 ; *** Match ***
EndIf
*separator + SizeOf(Character)
Wend
Break 2
Until 1
If splitToIdx > strOutUBound
strOutUBound + uBoundStep
uBoundStep << 1
ReDim strOut.s(strOutUBound)
EndIf
CompilerSelect SizeOf(Character)
CompilerCase 1 : strOut(splitToIdx) = PeekS(*splitStart, *pStrIn - *splitStart)
CompilerCase 2 : strOut(splitToIdx) = PeekS(*splitStart, (*pStrIn - *splitStart) >> 1)
CompilerCase 4 : strOut(splitToIdx) = PeekS(*splitStart, (*pStrIn - *splitStart) >> 2)
CompilerEndSelect
splitToIdx + 1
*splitStart = *pStrIn + SizeOf(Character)
Until 1
*pStrIn + SizeOf(Character)
strInCh = *pStrIn\c
Wend
If splitToIdx > strOutUBound
strOutUBound + uBoundStep
uBoundStep << 1
ReDim strOut.s(strOutUBound)
EndIf
CompilerSelect SizeOf(Character)
CompilerCase 1 : strOut(splitToIdx) = PeekS(*splitStart, *pStrIn - *splitStart)
CompilerCase 2 : strOut(splitToIdx) = PeekS(*splitStart, (*pStrIn - *splitStart) >> 1)
CompilerCase 4 : strOut(splitToIdx) = PeekS(*splitStart, (*pStrIn - *splitStart) >> 2)
CompilerEndSelect
splitToIdx + 1
EndIf
Else ; *** Split by multicharacter-separator full string ***
*separator + SizeOf(Character)
*thirdSeparatorCh = *separator
If splitFlags & #SplitString_NoEmptyParts
While strInCh
Repeat
If strInCh = firstSeparatorCh
*splitEnd = *pStrIn
*pStrIn + SizeOf(Character)
If *pStrIn\c <> secondSeparatorCh
strInCh = *pStrIn\c
Continue
EndIf
*pStrIn + SizeOf(Character)
*separator = *thirdSeparatorCh
separatorCh = *separator\c
strInCh = *pStrIn\c
Repeat
While separatorCh
If strInCh <> separatorCh
*pStrIn = *splitEnd
Break 2
EndIf
*pStrIn + SizeOf(Character)
strInCh = *pStrIn\c
*separator + SizeOf(Character)
separatorCh = *separator\c
Wend
If *splitStart <> *splitEnd
If splitToIdx > strOutUBound
strOutUBound + uBoundStep
uBoundStep << 1
ReDim strOut.s(strOutUBound)
EndIf
CompilerSelect SizeOf(Character)
CompilerCase 1 : strOut(splitToIdx) = PeekS(*splitStart, *splitEnd - *splitStart)
CompilerCase 2 : strOut(splitToIdx) = PeekS(*splitStart, (*splitEnd - *splitStart) >> 1)
CompilerCase 4 : strOut(splitToIdx) = PeekS(*splitStart, (*splitEnd - *splitStart) >> 2)
CompilerEndSelect
splitToIdx + 1
EndIf
*splitStart = *pStrIn
Break 2
Until 1
EndIf
*pStrIn + SizeOf(Character)
strInCh = *pStrIn\c
Until 1
Wend
If *splitStart <> *pStrIn
If splitToIdx > strOutUBound
strOutUBound + uBoundStep
uBoundStep << 1
ReDim strOut.s(strOutUBound)
EndIf
CompilerSelect SizeOf(Character)
CompilerCase 1 : strOut(splitToIdx) = PeekS(*splitStart, *pStrIn - *splitStart)
CompilerCase 2 : strOut(splitToIdx) = PeekS(*splitStart, (*pStrIn - *splitStart) >> 1)
CompilerCase 4 : strOut(splitToIdx) = PeekS(*splitStart, (*pStrIn - *splitStart) >> 2)
CompilerEndSelect
splitToIdx + 1
EndIf
Else ; *** Keep empty parts ***
While strInCh
Repeat
If strInCh = firstSeparatorCh
*splitEnd = *pStrIn
*pStrIn + SizeOf(Character)
If *pStrIn\c <> secondSeparatorCh
strInCh = *pStrIn\c
Continue
EndIf
*pStrIn + SizeOf(Character)
*separator = *thirdSeparatorCh
separatorCh = *separator\c
strInCh = *pStrIn\c
Repeat
While separatorCh
If strInCh <> separatorCh
*pStrIn = *splitEnd
Break 2
EndIf
*pStrIn + SizeOf(Character)
strInCh = *pStrIn\c
*separator + SizeOf(Character)
separatorCh = *separator\c
Wend
If splitToIdx > strOutUBound
strOutUBound + uBoundStep
uBoundStep << 1
ReDim strOut.s(strOutUBound)
EndIf
CompilerSelect SizeOf(Character)
CompilerCase 1 : strOut(splitToIdx) = PeekS(*splitStart, *splitEnd - *splitStart)
CompilerCase 2 : strOut(splitToIdx) = PeekS(*splitStart, (*splitEnd - *splitStart) >> 1)
CompilerCase 4 : strOut(splitToIdx) = PeekS(*splitStart, (*splitEnd - *splitStart) >> 2)
CompilerEndSelect
splitToIdx + 1
*splitStart = *pStrIn
Break 2
Until 1
EndIf
*pStrIn + SizeOf(Character)
strInCh = *pStrIn\c
Until 1
Wend
If splitToIdx > strOutUBound
strOutUBound + uBoundStep
uBoundStep << 1
ReDim strOut.s(strOutUBound)
EndIf
CompilerSelect SizeOf(Character)
CompilerCase 1 : strOut(splitToIdx) = PeekS(*splitStart, *pStrIn - *splitStart)
CompilerCase 2 : strOut(splitToIdx) = PeekS(*splitStart, (*pStrIn - *splitStart) >> 1)
CompilerCase 4 : strOut(splitToIdx) = PeekS(*splitStart, (*pStrIn - *splitStart) >> 2)
CompilerEndSelect
splitToIdx + 1
EndIf
EndIf
Else ; *** Split by singlecharacter-separator ***
If splitFlags & #SplitString_NoEmptyParts
While strInCh
If strInCh = firstSeparatorCh
If *pStrIn <> *splitStart
If splitToIdx > strOutUBound
strOutUBound + uBoundStep
uBoundStep << 1
ReDim strOut.s(strOutUBound)
EndIf
CompilerSelect SizeOf(Character)
CompilerCase 1 : strOut(splitToIdx) = PeekS(*splitStart, *pStrIn - *splitStart)
CompilerCase 2 : strOut(splitToIdx) = PeekS(*splitStart, (*pStrIn - *splitStart) >> 1)
CompilerCase 4 : strOut(splitToIdx) = PeekS(*splitStart, (*pStrIn - *splitStart) >> 2)
CompilerEndSelect
splitToIdx + 1
EndIf
*splitStart = *pStrIn + SizeOf(Character)
EndIf
*pStrIn + SizeOf(Character)
strInCh = *pStrIn\c
Wend
If *pStrIn <> *splitStart
If splitToIdx > strOutUBound
strOutUBound + uBoundStep
uBoundStep << 1
ReDim strOut.s(strOutUBound)
EndIf
CompilerSelect SizeOf(Character)
CompilerCase 1 : strOut(splitToIdx) = PeekS(*splitStart, *pStrIn - *splitStart)
CompilerCase 2 : strOut(splitToIdx) = PeekS(*splitStart, (*pStrIn - *splitStart) >> 1)
CompilerCase 4 : strOut(splitToIdx) = PeekS(*splitStart, (*pStrIn - *splitStart) >> 2)
CompilerEndSelect
splitToIdx + 1
EndIf
Else ; *** Keep empty parts ***
While strInCh
If strInCh = firstSeparatorCh
If splitToIdx > strOutUBound
strOutUBound + uBoundStep
uBoundStep << 1
ReDim strOut.s(strOutUBound)
EndIf
CompilerSelect SizeOf(Character)
CompilerCase 1 : strOut(splitToIdx) = PeekS(*splitStart, *pStrIn - *splitStart)
CompilerCase 2 : strOut(splitToIdx) = PeekS(*splitStart, (*pStrIn - *splitStart) >> 1)
CompilerCase 4 : strOut(splitToIdx) = PeekS(*splitStart, (*pStrIn - *splitStart) >> 2)
CompilerEndSelect
splitToIdx + 1
*splitStart = *pStrIn + SizeOf(Character)
EndIf
*pStrIn + SizeOf(Character)
strInCh = *pStrIn\c
Wend
If splitToIdx > strOutUBound
strOutUBound + uBoundStep
uBoundStep << 1
ReDim strOut.s(strOutUBound)
EndIf
CompilerSelect SizeOf(Character)
CompilerCase 1 : strOut(splitToIdx) = PeekS(*splitStart, *pStrIn - *splitStart)
CompilerCase 2 : strOut(splitToIdx) = PeekS(*splitStart, (*pStrIn - *splitStart) >> 1)
CompilerCase 4 : strOut(splitToIdx) = PeekS(*splitStart, (*pStrIn - *splitStart) >> 2)
CompilerEndSelect
splitToIdx + 1
EndIf
EndIf
If Not (splitFlags & #SplitString_NoReDim)
ReDim strOut.s(splitToIdx - 1)
EndIf
Until 1
EndIf
If *ubValue: *ubValue\l = strOutUBound: EndIf
ProcedureReturn splitToIdx - splitTo
EndProcedure
Prototype.l pt_SplitStringToArray(strIn.SplitJoinStringType, strOut.s(1), separator.SplitJoinStringType, splitFlags.l = 0, splitTo.l = 0, *ubValue.Long = 0)
Prototype.l pt_SplitMemoryToArray(*strIn.Character, strOut.s(1), separator.SplitJoinStringType, splitFlags.l = 0, splitTo.l = 0, *ubValue.Long = 0)
Global SplitStringToArray.pt_SplitStringToArray = @_SplitToArray()
Global SplitMemoryToArray.pt_SplitMemoryToArray = @_SplitToArray()
Code: Select all
; Splitting a string into parts
; Splitting a string into parts
;
; strIn = String to split for SplitStringToArray()
; Pointer to memory to split for SplitMemoryToArray()
; The memory-block must have a terminating 0 character!
;
; strOut() = String-list which will contain the parts.
; You have to set the list position before calling this procedure,
; or you can use ClearList() if you only want the parts from actual splitting
; Either way, all new parts will be add after the actual list position.
;
; separator = Single- or multi-character string by which the string will be splitted
;
; splitFlags= #SplitString_NoEmptyParts : Will omit empty parts of strIn
; #SplitString_MultiSingleCharacter : If separator-string is more than one character,
; every single character counts as separator.
; If not set, the whole separator-string counts
; as one separator.
; #SplitString_NoReDim : Does nothing for lists, also the expand step
; value will be ignored.
;
; You can use several flags by oring them together with '|'.
;
; Returns the number of parts for actual splitting
;
; If the separator is 0, or the strIn contains no separators,
; strOut() will containe the whole string and 1 is returned
;
; If strIn is empty or a 0 pointer, strOut() will not be changed, and 0 is returned
Procedure.l _SplitToList(*strIn.Character, strOut.s(), *separator.Character, splitFlags.l = 0)
Protected splitCnt.l
Protected firstSeparatorCh.l, SecondSeparatorCh.l
Protected separatorCh.l, strInCh.l
Protected *pStrIn.Character, *thirdSeparatorCh.Character
Protected *splitStart.Character, *splitEnd.Character
If *strIn
Repeat
strInCh = *strIn\c
If *separator
firstSeparatorCh = *separator\c
*separator + SizeOf(Character)
EndIf
If Not firstSeparatorCh
If strInCh
AddElement(strOut())
strOut() = PeekS(*strIn)
splitCnt + 1
Break
EndIf
Break
EndIf
*pStrIn = *strIn
*splitStart = *strIn
secondSeparatorCh = *separator\c
If secondSeparatorCh ; *** Split by multicharacter-separator ***
If splitFlags & #SplitString_MultiSingleCharacter ; *** Split by mutlicharacter-separator single characters ***
*separator + SizeOf(Character)
*thirdSeparatorCh = *separator
If splitFlags & #SplitString_NoEmptyParts
While strInCh
Repeat
Repeat
If strInCh = firstSeparatorCh Or strInCh = SecondSeparatorCh
Continue ; *** Match ***
EndIf
*separator = *thirdSeparatorCh
While *separator\c
If strInCh = *separator\c
Break 2 ; *** Match ***
EndIf
*separator + SizeOf(Character)
Wend
Break 2
Until 1
If *pStrIn <> *splitStart
AddElement(strOut())
CompilerSelect SizeOf(Character)
CompilerCase 1 : strOut() = PeekS(*splitStart, *pStrIn - *splitStart)
CompilerCase 2 : strOut() = PeekS(*splitStart, (*pStrIn - *splitStart) >> 1)
CompilerCase 4 : strOut() = PeekS(*splitStart, (*pStrIn - *splitStart) >> 2)
CompilerEndSelect
splitCnt + 1
EndIf
*splitStart = *pStrIn + SizeOf(Character)
Until 1
*pStrIn + SizeOf(Character)
strInCh = *pStrIn\c
Wend
If *pStrIn <> *splitStart
AddElement(strOut())
CompilerSelect SizeOf(Character)
CompilerCase 1 : strOut() = PeekS(*splitStart, *pStrIn - *splitStart)
CompilerCase 2 : strOut() = PeekS(*splitStart, (*pStrIn - *splitStart) >> 1)
CompilerCase 4 : strOut() = PeekS(*splitStart, (*pStrIn - *splitStart) >> 2)
CompilerEndSelect
splitCnt + 1
EndIf
Else ; *** Keep empty parts ***
While strInCh
Repeat
Repeat
If strInCh = firstSeparatorCh Or strInCh = SecondSeparatorCh
Continue ; *** Match ***
EndIf
*separator = *thirdSeparatorCh
While *separator\c
If strInCh = *separator\c
Break 2 ; *** Match ***
EndIf
*separator + SizeOf(Character)
Wend
Break 2
Until 1
AddElement(strOut())
CompilerSelect SizeOf(Character)
CompilerCase 1 : strOut() = PeekS(*splitStart, *pStrIn - *splitStart)
CompilerCase 2 : strOut() = PeekS(*splitStart, (*pStrIn - *splitStart) >> 1)
CompilerCase 4 : strOut() = PeekS(*splitStart, (*pStrIn - *splitStart) >> 2)
CompilerEndSelect
splitCnt + 1
*splitStart = *pStrIn + SizeOf(Character)
Until 1
*pStrIn + SizeOf(Character)
strInCh = *pStrIn\c
Wend
AddElement(strOut())
CompilerSelect SizeOf(Character)
CompilerCase 1 : strOut() = PeekS(*splitStart, *pStrIn - *splitStart)
CompilerCase 2 : strOut() = PeekS(*splitStart, (*pStrIn - *splitStart) >> 1)
CompilerCase 4 : strOut() = PeekS(*splitStart, (*pStrIn - *splitStart) >> 2)
CompilerEndSelect
splitCnt + 1
EndIf
Else ; *** Split by multicharacter-separator full string ***
*separator + SizeOf(Character)
*thirdSeparatorCh = *separator
If splitFlags & #SplitString_NoEmptyParts
While strInCh
Repeat
If strInCh = firstSeparatorCh
*splitEnd = *pStrIn
*pStrIn + SizeOf(Character)
If *pStrIn\c <> secondSeparatorCh
strInCh = *pStrIn\c
Continue
EndIf
*pStrIn + SizeOf(Character)
*separator = *thirdSeparatorCh
separatorCh = *separator\c
strInCh = *pStrIn\c
Repeat
While separatorCh
If strInCh <> separatorCh
*pStrIn = *splitEnd
Break 2
EndIf
*pStrIn + SizeOf(Character)
strInCh = *pStrIn\c
*separator + SizeOf(Character)
separatorCh = *separator\c
Wend
If *splitStart <> *splitEnd
AddElement(strOut())
CompilerSelect SizeOf(Character)
CompilerCase 1 : strOut() = PeekS(*splitStart, *splitEnd - *splitStart)
CompilerCase 2 : strOut() = PeekS(*splitStart, (*splitEnd - *splitStart) >> 1)
CompilerCase 4 : strOut() = PeekS(*splitStart, (*splitEnd - *splitStart) >> 2)
CompilerEndSelect
splitCnt + 1
EndIf
*splitStart = *pStrIn
Break 2
Until 1
EndIf
*pStrIn + SizeOf(Character)
strInCh = *pStrIn\c
Until 1
Wend
If *splitStart <> *pStrIn
AddElement(strOut())
CompilerSelect SizeOf(Character)
CompilerCase 1 : strOut() = PeekS(*splitStart, *pStrIn - *splitStart)
CompilerCase 2 : strOut() = PeekS(*splitStart, (*pStrIn - *splitStart) >> 1)
CompilerCase 4 : strOut() = PeekS(*splitStart, (*pStrIn - *splitStart) >> 2)
CompilerEndSelect
splitCnt + 1
EndIf
Else ; *** Keep empty parts ***
While strInCh
Repeat
If strInCh = firstSeparatorCh
*splitEnd = *pStrIn
*pStrIn + SizeOf(Character)
If *pStrIn\c <> secondSeparatorCh
strInCh = *pStrIn\c
Continue
EndIf
*pStrIn + SizeOf(Character)
*separator = *thirdSeparatorCh
separatorCh = *separator\c
strInCh = *pStrIn\c
Repeat
While separatorCh
If strInCh <> separatorCh
*pStrIn = *splitEnd
Break 2
EndIf
*pStrIn + SizeOf(Character)
strInCh = *pStrIn\c
*separator + SizeOf(Character)
separatorCh = *separator\c
Wend
AddElement(strOut())
CompilerSelect SizeOf(Character)
CompilerCase 1 : strOut() = PeekS(*splitStart, *splitEnd - *splitStart)
CompilerCase 2 : strOut() = PeekS(*splitStart, (*splitEnd - *splitStart) >> 1)
CompilerCase 4 : strOut() = PeekS(*splitStart, (*splitEnd - *splitStart) >> 2)
CompilerEndSelect
splitCnt + 1
*splitStart = *pStrIn
Break 2
Until 1
EndIf
*pStrIn + SizeOf(Character)
strInCh = *pStrIn\c
Until 1
Wend
AddElement(strOut())
CompilerSelect SizeOf(Character)
CompilerCase 1 : strOut() = PeekS(*splitStart, *pStrIn - *splitStart)
CompilerCase 2 : strOut() = PeekS(*splitStart, (*pStrIn - *splitStart) >> 1)
CompilerCase 4 : strOut() = PeekS(*splitStart, (*pStrIn - *splitStart) >> 2)
CompilerEndSelect
splitCnt + 1
EndIf
EndIf
Else ; *** Split by singlecharacter-separator ***
If splitFlags & #SplitString_NoEmptyParts
While strInCh
If strInCh = firstSeparatorCh
If *pStrIn <> *splitStart
AddElement(strOut())
CompilerSelect SizeOf(Character)
CompilerCase 1 : strOut() = PeekS(*splitStart, *pStrIn - *splitStart)
CompilerCase 2 : strOut() = PeekS(*splitStart, (*pStrIn - *splitStart) >> 1)
CompilerCase 4 : strOut() = PeekS(*splitStart, (*pStrIn - *splitStart) >> 2)
CompilerEndSelect
splitCnt + 1
EndIf
*splitStart = *pStrIn + SizeOf(Character)
EndIf
*pStrIn + SizeOf(Character)
strInCh = *pStrIn\c
Wend
If *pStrIn <> *splitStart
AddElement(strOut())
CompilerSelect SizeOf(Character)
CompilerCase 1 : strOut() = PeekS(*splitStart, *pStrIn - *splitStart)
CompilerCase 2 : strOut() = PeekS(*splitStart, (*pStrIn - *splitStart) >> 1)
CompilerCase 4 : strOut() = PeekS(*splitStart, (*pStrIn - *splitStart) >> 2)
CompilerEndSelect
splitCnt + 1
EndIf
Else ; *** Keep empty parts ***
While strInCh
If strInCh = firstSeparatorCh
AddElement(strOut())
CompilerSelect SizeOf(Character)
CompilerCase 1 : strOut() = PeekS(*splitStart, *pStrIn - *splitStart)
CompilerCase 2 : strOut() = PeekS(*splitStart, (*pStrIn - *splitStart) >> 1)
CompilerCase 4 : strOut() = PeekS(*splitStart, (*pStrIn - *splitStart) >> 2)
CompilerEndSelect
splitCnt + 1
*splitStart = *pStrIn + SizeOf(Character)
EndIf
*pStrIn + SizeOf(Character)
strInCh = *pStrIn\c
Wend
AddElement(strOut())
CompilerSelect SizeOf(Character)
CompilerCase 1 : strOut() = PeekS(*splitStart, *pStrIn - *splitStart)
CompilerCase 2 : strOut() = PeekS(*splitStart, (*pStrIn - *splitStart) >> 1)
CompilerCase 4 : strOut() = PeekS(*splitStart, (*pStrIn - *splitStart) >> 2)
CompilerEndSelect
splitCnt + 1
EndIf
EndIf
Until 1
EndIf
ProcedureReturn splitCnt
EndProcedure
Prototype.l pt_SplitStringToList(strIn.SplitJoinStringType, strOut.s(), separator.SplitJoinStringType, splitFlags.l = 0)
Prototype.l pt_SplitMemoryToList(*strIn.Character, strOut.s(), separator.SplitJoinStringType, splitFlags.l = 0)
Global SplitStringToList.pt_SplitStringToList = @_SplitToList()
Global SplitMemoryToList.pt_SplitMemoryToList = @_SplitToList()