How to trim a text line?
;==========================================================================================================================================
; How to trim a text line?
;
; How to remove space characters at one side of a string?
;
; Comparison of methods for trimming single lines and trimming multiple lines.
;
; Detlev Dalitz.20020130.20040404.20100208.
;==========================================================================================================================================


;---;
; 1 ;
;---+--------------------------------------------------------------------------------------------------------------------------------------
;
; WinBatch provides the function StrTrim().
;
; strTrimmed = strTrim ("   1 2 3 test   ") ; Will give the result "1 2 3 test".
;
; The WinBatch function strTrim () removes spaces and tab characters from the beginning and end of a text string.
;
;------------------------------------------------------------------------------------------------------------------------------------------


;---;
; 2 ;
;---+--------------------------------------------------------------------------------------------------------------------------------------
;
; What can we do in such cases when trimming is needed only at one side of the string?
;
;------------------------------------------------------------------------------------------------------------------------------------------
;
; Once we have found out a method to prevent the input string of trimming at one edge (saving the other edge),
; we are able to use the WinBatch native function StrTrim ().
;
; We can hinder StrTrim () to trim both sides of a string, if we enclose the input string with a character,
; which StrTrim () cannot detect as trimmable.
; To prevent the right edge from trimming we can add a blocker character at the right edge.
; To prevent the left edge from trimming we can add a blocker character at the left edge.
;
; Example for left trimming:
; strString = "   1 2 3 test   "                ; This is the original string of 16 character size.
; strString = strString : @LF                   ; Just of oddity we add the ASCII 10 LineFeed character.
; strString = strTrim (strString)               ; This will give the result "1 2 3 test   @LF", this is left trimmed.
; strString = ItemRemove (-1, strString, @LF)   ; To get the final result we have to cut away the trailing
;                                               ; trim preventing character, which will give the result "1 2 3 test   ".
;
; Example for right trimming:
; strString = "   1 2 3 test   "                ; This is the original string of 16 character size.
; strString = @LF : strString                   ; Just of oddity we add the ASCII 10 LineFeed character.
; strString = strTrim (strString)               ; This Will give the result "@LF   1 2 3 test", this is right trimmed.
; strString = ItemRemove (1, strString, @LF)    ; To get the final result we have to cut away the leading
;                                               ; trim preventing character, which will give the result "   1 2 3 test".
;------------------------------------------------------------------------------------------------------------------------------------------


;---;
; 3 ;
;---+--------------------------------------------------------------------------------------------------------------------------------------
; User defined functions for trimming a single line.
;------------------------------------------------------------------------------------------------------------------------------------------

;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfStrTrimLeftV1 (strString)
Return ItemRemove (-1, StrTrim (strString : @LF), @LF)
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------

;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfStrTrimRightV1 (strString)
Return ItemRemove (1, StrTrim (@LF : strString), @LF)
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------


;---;
; 4 ;
;---+--------------------------------------------------------------------------------------------------------------------------------------
; User defined functions for trimming multiple lines with EOL sequence @CRLF (Note: must be @CRLF).
;------------------------------------------------------------------------------------------------------------------------------------------

;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfStrTrimLeftV2 (strString)
If strString == "" Then Return strString
intBBSize = 1 + StrLen (strString)
hdlBB = BinaryAlloc (intBBSize)
BinaryEodSet (hdlBB, intBBSize)
BinaryPokeStr (hdlBB, 0, @LF)
BinaryPokeStr (hdlBB, 1, strString)
strSrch = @LF : " "
While !!BinaryReplace (hdlBB, strSrch, @LF, @TRUE)
EndWhile
strString = BinaryPeekStr (hdlBB, 1, BinaryEodGet (hdlBB) - 1)
hdlBB = BinaryFree (hdlBB)
Return strString
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------


;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfStrTrimRightV2 (strString)
If strString == "" Then Return strString
intBBSize = 1 + StrLen (strString)
hdlBB = BinaryAlloc (intBBSize)
BinaryEodSet (hdlBB, intBBSize)
BinaryPokeStr (hdlBB, intBBSize - 1, @CR)
BinaryPokeStr (hdlBB, 0, strString)
strSrch = " " : @CR
While !!BinaryReplace (hdlBB, strSrch, @CR, @TRUE)
EndWhile
strString = BinaryPeekStr (hdlBB, 0, BinaryEodGet (hdlBB) - 1)
hdlBB = BinaryFree (hdlBB)
Return strString
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------


;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfStrTrimLeftV3 (strString)
If strString == "" Then Return strString
strString = @LF : strString
strSrch = @LF : " "
While !!StrIndex (strString, strSrch, 0, @FWDSCAN)
   strString = StrReplace (strString, strSrch, @LF)
EndWhile
Return StrSub (strString, 2, -1)
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------


;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfStrTrimRightV3 (strString)
If strString == "" Then Return strString
strString = strString : @CR
strSrch = " " : @CR
While !!StrIndex (strString, strSrch, 0, @FWDSCAN)
   strString = StrReplace (strString, strSrch, @CR)
EndWhile
Return StrSub (strString, 1, StrLen (strString) - 1)
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------



;------------------------------------------------------------------------------------------------------------------------------------------
; Functional Test.

strIn = "   1 2 3 test   "

strOut = udfStrTrimLeftV1 (strIn)
strMsgTitle = "Demo udfStrTrimLeftV1 (strString)"
strMsgText = 'strIn' : @TAB : '= "' : strIn : '"' : @CRLF : 'strOut' : @TAB : '= "' : strOut : '"'
Pause (strMsgTitle, strMsgText)


strOut = udfStrTrimRightV1 (strIn)
strMsgTitle = "Demo udfStrTrimRightV1 (strString)"
strMsgText = 'strIn' : @TAB : '= "' : strIn : '"' : @CRLF : 'strOut' : @TAB : '= "' : strOut : '"'
Pause (strMsgTitle, strMsgText)


strOut = udfStrTrimLeftV2 (strIn)
strMsgTitle = "Demo udfStrTrimLeftV2 (strString)"
strMsgText = 'strIn' : @TAB : '= "' : strIn : '"' : @CRLF : 'strOut' : @TAB : '= "' : strOut : '"'
Pause (strMsgTitle, strMsgText)


strOut = udfStrTrimRightV2 (strIn)
strMsgTitle = "Demo udfStrTrimRightV2 (strString)"
strMsgText = 'strIn' : @TAB : '= "' : strIn : '"' : @CRLF : 'strOut' : @TAB : '= "' : strOut : '"'
Pause (strMsgTitle, strMsgText)


strOut = udfStrTrimLeftV3 (strIn)
strMsgTitle = "Demo udfStrTrimLeftV3 (strString)"
strMsgText = 'strIn' : @TAB : '= "' : strIn : '"' : @CRLF : 'strOut' : @TAB : '= "' : strOut : '"'
Pause (strMsgTitle, strMsgText)


strOut = udfStrTrimRightV3 (strIn)
strMsgTitle = "Demo udfStrTrimRightV3 (strString)"
strMsgText = 'strIn' : @TAB : '= "' : strIn : '"' : @CRLF : 'strOut' : @TAB : '= "' : strOut : '"'
Pause (strMsgTitle, strMsgText)



;------------------------------------------------------------------------------------------------------------------------------------------
; Performance Test.

strIn = StrFill (" ", 20) : "Performance Test" : StrFill (" ", 20)
intLen = StrLen (strIn) + StrLen (@CRLF)
strIn2 = StrFill (strIn : @CRLF, 100 * intLen)
strIn3 = strIn2

intTestLoop = 100
intTestMin = 2
intTestMax = 3

ClipPut ("")

:StrTrimLeft
ClipAppend (@CRLF : "udfStrTrimLeft" : @CRLF)
strMsgTitle = "Demo  udfStrTrimLeft (strString)   Performance Test"
For intT = intTestMin To intTestMax
   Display (1, strMsgTitle, "Running Test StrTrimLeft %intT%, please wait ...")
   Exclusive (@ON)
   intTicksStart = GetTickCount ()
   For intL = 1 To intTestLoop
      strOut%intT% = udfStrTrimLeftV%intT% (strIn%intT%)
   Next
   intTicks%intT% = GetTickCount () - intTicksStart
   Exclusive (@OFF)
   Display (2, strMsgTitle, "StrLen (strIn) = " : StrLen (strIn%intT%) : @LF : "StrLen (strOut) = " : StrLen (strOut%intT%))
Next

intTicksMax = 0
For intT = intTestMin To intTestMax
   intTicksMax = Max (1, intTicksMax, intTicks%intT%)
Next
For intT = intTestMin To intTestMax
   intPct%intT% = 100 * intTicks%intT% / intTicksMax
Next
strMsgText = ""
For intT = intTestMin To intTestMax
   strMsgText = strMsgText : "Test " : intT : @TAB : "Ticks = " : @TAB : intTicks%intT% : @TAB : "Pct = " : @TAB : intPct%intT% : " %%" : @CRLF
Next
Pause (strMsgTitle, strMsgText)
ClipAppend (strMsgText)


:StrTrimRight
ClipAppend (@CRLF : "udfStrTrimRight" : @CRLF)
strMsgTitle = "Demo  udfStrTrimRight (strString)   Performance Test"
For intT = intTestMin To intTestMax
   Display (1, strMsgTitle, "Running Test StrTrimRight %intT%, please wait ...")
   Exclusive (@ON)
   intTicksStart = GetTickCount ()
   For intL = 1 To intTestLoop
      strOut%intT% = udfStrTrimRightV%intT% (strIn%intT%)
   Next
   intTicks%intT% = GetTickCount () - intTicksStart
   Exclusive (@OFF)
   Display (2, strMsgTitle, "StrLen (strIn) = " : StrLen (strIn%intT%) : @LF : "StrLen (strOut) = " : StrLen (strOut%intT%))
Next

intTicksMax = 0
For intT = intTestMin To intTestMax
   intTicksMax = Max (1, intTicksMax, intTicks%intT%)
Next
For intT = intTestMin To intTestMax
   intPct%intT% = 100 * intTicks%intT% / intTicksMax
Next
strMsgText = ""
For intT = intTestMin To intTestMax
   strMsgText = strMsgText : "Test " : intT : @TAB : "Ticks = " : @TAB : intTicks%intT% : @TAB : "Pct = " : @TAB : intPct%intT% : " %%" : @CRLF
Next
Pause (strMsgTitle, strMsgText)
ClipAppend (strMsgText)

:CANCEL
Exit

;   udfStrTrimLeft
;   Test 2   Ticks =     703   Pct =   48 %   Binary Replace.
;   Test 3   Ticks =    1453   Pct =  100 %   String Replace.
;
;   udfStrTrimRight
;   Test 2   Ticks =     719   Pct =   47 %   Binary Replace.
;   Test 3   Ticks =    1515   Pct =  100 %   String Replace.