Welcome, Guest
Username: Password: Remember me
This public forum is meant for questions and discussions about Visual FoxPro
  • Page:
  • 1

TOPIC:

VFP *TRIM() functions 20 May 2020 21:20 #14652

  • atlopes
  • atlopes's Avatar
  • Topic Author


  • Posts: 84
  • As an experiment on varying number of parameters in a function declaration, a proposal of the implementation of *Trim() functions:

    • ALLTRIM(Expression [, nFlags] [, cParseChar [, cParseChar2 [, ...]]])
    • LTRIM(Expression [, nFlags] [, cParseChar [, cParseChar2 [, ...]]])
    • RTRIM(cExpression [, nFlags] [, cParseChar [, cParseChar2 [, ...]]])

    TRIM() = RTRIM(), so a header file could be used to add it to the list.

    Testing (but no stress test):
    Procedure Trim_Test ()
        
        ? 'Alltrim(" ") == ""', IIF(Alltrim(" ") == "", "OK", "Fail")
        ? 'Alltrim(e" \n ", 0, " ", CHR(9), CHR(10), CHR(13)) == ""', IIF(Alltrim(e" \n ", 0, " ", CHR(9), CHR(10), CHR(13)) == "", "OK", "Fail")
        ? 'Alltrim("Test ") == "Test"', IIF(Alltrim("Test ") == "Test", "OK", "Fail")
        ? 'Alltrim(e"Test \n ", 0, " ", CHR(9), CHR(10), CHR(13)) == "Test"', IIF(Alltrim(e"Test \n ", 0, " ", CHR(9), CHR(10), CHR(13)) == "Test", "OK", "Fail")
        ? 'Alltrim("TeTeTest", 0, "te") == "TeTeTest"', IIF(Alltrim("TeTeTest", 0, "te") == "TeTeTest", "OK", "Fail")
        ? 'Alltrim("TeTeTest", 1, "te") == "st"', IIF(Alltrim("TeTeTest", 1, "te") == "st", "OK", "Fail")
        ? 'Alltrim("TeTeTest", 0, "t", "e") == "TeTeTes"', IIF(Alltrim("TeTeTest", 0, "t", "e") == "TeTeTes", "OK", "Fail")
        ? 'Alltrim("TeTeTest", 1, "t", "e") == "s"', IIF(Alltrim("TeTeTest", 1, "t", "e") == "s", "OK", "Fail")
        ? 'Alltrim("***abc*", 0, "*") == "abc"', IIF(Alltrim("***abc*", 0, "*") == "abc", "OK", "Fail")
        ? 'Ltrim("***abc*", 0, "*") == "abc*"', IIF(Ltrim("***abc*", 0, "*") == "abc*", "OK", "Fail")
        ? 'Rtrim("***abc*", 0, "*") == "***abc"', IIF(Rtrim("***abc*", 0, "*") == "***abc", "OK", "Fail")
        ? 'Alltrim("abcdefghab", 1, "AB", "B") == "cdefgh"', IIF(Alltrim("abcdefghab", 1, "AB", "B") == "cdefgh", "OK", "Fail")
        ? 'Alltrim("abcdefghab", 1, "B", "AB") == "cdefgha"', IIF(Alltrim("abcdefghab", 1, "B", "AB") == "cdefgha", "OK", "Fail")
    //    ? 'ISNULL(Rtrim(NULL))', IIF(ISNULL(Rtrim(NULL)), "OK", "Fail")
    
    End Proc

    Result:



    The functions set:
    Function Alltrim (Expression AS String) AS String
    
    	Return _trim(.T., .T., Expression, 0, " ")
    
    End Function
    
    Function Alltrim (Expression AS String, Flags AS Int, TrimChars PARAMS String[]) AS String STRICT
    
    	Return _trim(.T., .T., Expression, Flags, TrimChars)
    
    End Function
    
    Function Ltrim (Expression AS String) AS String
    
    	Return _trim(.T., .F., Expression, 0, " ")
    
    End Function
    
    Function Ltrim (Expression AS String, Flags AS Int, TrimChars PARAMS String[]) AS String STRICT
    
    	Return _trim(.T., .F., Expression, Flags, TrimChars)
    
    End Function
    
    Function Rtrim (Expression AS String) AS String
    
    	Return _trim(.F., .T., Expression, 0, " ")
    
    End Function
    
    Function Rtrim (Expression AS String, Flags AS Int, TrimChars PARAMS String[]) AS String STRICT
    
    	Return _trim(.F., .T., Expression, Flags, TrimChars)
    
    End Function
    
    
    STATIC Function _trim (TrimLeft AS Boolean, TrimRight AS Boolean, Expression As String, Flags As Int, TrimChars PARAMS String[]) AS String STRICT
    
        LOCAL parmNdx AS Int
        LOCAL Trimmed = .T. AS Boolean
        LOCAL LRTrimmed AS Int
        LOCAL comparison = StringComparison.Ordinal
        LOCAL compared AS String
    
        IF Expression = NULL
            Return Expression
        END IF
    
        IF Flags = 1
            comparison = StringComparison.OrdinalIgnoreCase
        END IF
    
        DO WHILE Trimmed
    
            Trimmed = .F.
    
            FOR parmNdx = 1 TO TrimChars:Length
                
                IF TrimLeft
                    LRTrimmed = 0
     
                    compared = TrimChars[parmNdx]
                    DO WHILE Expression:StartsWith(compared, comparison)
                        LRTrimmed = compared:Length
                        compared = String.Concat(compared, TrimChars[parmNdx])
                    END DO
                    IF LRTrimmed > 0
                        Expression = Expression:Substring(LRTrimmed)
                        Trimmed = .T.
                    END IF
                END IF
    
                IF TrimRight
                    LRTrimmed = 0
    
                    compared = TrimChars[parmNdx]
                    DO WHILE Expression:EndsWith(compared, comparison)
                        LRTrimmed = compared:Length
                        compared = String.Concat(compared, TrimChars[parmNdx])
                    END DO
                    IF LRTrimmed > 0
                        Expression = Expression:Substring(0, Expression:Length - LRTrimmed)
                        Trimmed = .T.
                    END IF
                END IF
    
            NEXT
     
        END DO
    
        Return Expression
    
    End Function

    Please Log in or Create an account to join the conversation.

    VFP *TRIM() functions 21 May 2020 17:17 #14667

    • Chris
    • Chris's Avatar


  • Posts: 3980
  • Hi Antonio,

    Thanks a lot for your contribution! Will add it to the runtime, will just need to make small adjustments so that it can co-exist with the already existing implementation of AllTrim() etc. Fortunately the versions with no params at all seem to have the same behavior in both FoxPro and VO.

    It should be possible to improve the performance by somehow avoiding creating many new strings while the function runs, but this can be improved later.
    XSharp Development Team
    chris(at)xsharp.eu

    Please Log in or Create an account to join the conversation.

    VFP *TRIM() functions 22 May 2020 12:03 #14675

    • Karl-Heinz
    • Karl-Heinz's Avatar


  • Posts: 774
  • Hi Antonio,

    nice work and interesting to see how many trim options VFP offers !

    About the Trim() function: Simply add it to your existing functions.

    FUNCTION Trim (Expression AS STRING) AS STRING
    RETURN RTrim (Expression )  
    
    FUNCTION Trim (Expression AS STRING, Flags AS INT, TrimChars PARAMS STRING[]) AS STRING STRICT
    RETURN RTrim (Expression , Flags, TrimChars )

    regards
    Karl-Heinz

    Please Log in or Create an account to join the conversation.

    VFP *TRIM() functions 22 May 2020 15:19 #14676

    • atlopes
    • atlopes's Avatar
    • Topic Author


  • Posts: 84
  • Thank you, Chris & Karl-Heinz. Like Matt, Thomas, Kevin, and others that are contributing to the X# VFP runtime, we hope that these steps may add to the potential of X# as a viable or interesting option for the VFP community, humble as they might be.

    Before moving to something else, I reduced a little bit the need for the creation of new strings:
    STATIC Function TrimHelper (TrimLeft AS Boolean, TrimRight AS Boolean, Expression As String, Flags As Int, TrimChars PARAMS String[]) AS String STRICT
    
        LOCAL parmNdx AS Int
        LOCAL Trimmed = .T. AS Boolean
        LOCAL LRTrimmed AS Int
        LOCAL comparison = StringComparison.Ordinal AS System.StringComparison
        LOCAL compared AS String
    
        IF Expression = NULL
            Return Expression
        END IF
    
        IF Flags = 1
             comparison = StringComparison.OrdinalIgnoreCase
        END IF
    
        DO WHILE Trimmed
    
            Trimmed = .F.
    
            FOR parmNdx = 1 TO TrimChars:Length
     
                compared = TrimChars[parmNdx]
    
                IF TrimLeft
                    LRTrimmed = 0
     
                    DO WHILE String.Compare(Expression, LRTrimmed, compared, 0, compared:Length, comparison) = 0
                        LRTrimmed += compared:Length
                    END DO
                    IF LRTrimmed > 0
                        Expression = Expression:Substring(LRTrimmed)
                        Trimmed = .T.
                    END IF
                END IF
    
                IF TrimRight
                    LRTrimmed = Expression:Length - compared:Length
    
                    DO WHILE LRTrimmed >= 0 AND String.Compare(Expression, LRTrimmed, compared, 0, compared:Length, comparison) = 0
                        LRTrimmed -= compared:Length
                    END DO
                    IF LRTrimmed < (Expression:Length - compared:Length)
                        Expression = Expression:Substring(0, LRTrimmed + compared:Length)
                        Trimmed = .T.
                    END IF
                END IF
    
            NEXT
     
        END DO
    
        Return Expression
    
    End Function

    Please Log in or Create an account to join the conversation.

    VFP *TRIM() functions 22 May 2020 17:48 #14684

    • Chris
    • Chris's Avatar


  • Posts: 3980
  • Hi Antonio,

    Thanks, looks perfect to me now!
    I have updated the source in Git.
    XSharp Development Team
    chris(at)xsharp.eu

    Please Log in or Create an account to join the conversation.

    • Page:
    • 1