Bug? Matcher.Find is reset once first examined.

RandomCoder

Well-Known Member
Licensed User
Longtime User
Whilst trying to debug some code that uses RegEx, I've found that once you have examined if a match was found, it reset the state. In the example below a match is always found with the values I send and the log displays "A" but never displays "B, C or D" and so with the last statement I always return an empty string. This is the case in Debug mode AND in release mode.
I only found it by chance because I was adding additional log statements in to record what each group had found and I ended up breaking my code. With a little fault finding I worked out that the m.find state is everting to false after the first call.
B4X:
Public Sub Extract( strPattern As String, strText As String, blnCaseSensitive As Boolean, intExtractGroup As Int) As String
    Dim m As Matcher
    If blnCaseSensitive Then
        m = Regex.Matcher(strPattern, strText)       
    Else
        m = Regex.Matcher2(strPattern, Regex.CASE_INSENSITIVE, strText)
    End If
    Log(m.GroupCount)
    If m.Find = True Then Log("A")
    If m.Find = True Then Log("B")
    If m.Find = True Then Log("C")
    If m.Find = True Then Log("D")
    If m.Find = True Then Return m.Group(intExtractGroup)
    ' Return an empty string if pattern not found
    Return ""
End Sub
 

RandomCoder

Well-Known Member
Licensed User
Longtime User
Attached a simple example (taken from a code sample here on the forum)...
B4X:
#Region  Service Attributes
    #StartAtBoot: False
    #ExcludeFromLibrary: True
#End Region

Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.

End Sub

Sub Service_Create
    'This is the program entry point.
    'This is a good place to load resources that are not specific to a single activity.

End Sub

Sub Service_Start (StartingIntent As Intent)
    Log("Valid email format = " & Validate_Email("Hewlett-Packard@HPforyou.hp.com"))
End Sub

'Return true to allow the OS default exceptions handler to handle the uncaught exception.
Sub Application_Error (Error As Exception, StackTrace As String) As Boolean
    Return True
End Sub

Sub Service_Destroy

End Sub

Sub Validate_Email(EmailAddress As String) As Boolean
    Dim MatchEmail As Matcher = Regex.Matcher("^(?i)[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])$", EmailAddress)

    Log("Status=" & MatchEmail.Find)
    If MatchEmail.Find = True Then
        Log(MatchEmail.Match)
        Return True
    Else
        Log("Oops, please double check your email address...")
        Return False
    End If
End Sub
I suppose normally you would only check the find property once and so this could have easily gone unnoticed...
"LogCat connected to: 07795cb8
--------- beginning of crash
--------- beginning of system
--------- beginning of main
** Service (starter) Create **
** Service (starter) Start **
Status=true
Oops, please double check your email address...
Valid email format = false
** Activity (main) Create, isFirst = true **
** Activity (main) Resume **
** Activity (main) Pause, UserClosed = false **"
 

Attachments

  • MatcherTest.zip
    6.8 KB · Views: 211

RandomCoder

Well-Known Member
Licensed User
Longtime User
I should have realised that it would be my mistake, I hadn't realised that calling matcher.find triggered a search for another match and returned true or false again depending on if one was found. I was going through some old code and mistakenly thought that the Regex.Matcher instruction was what did the search, now I see that it only sets the pattern and matcher.find executes the search.
Sorry to have wasted your time and I thank you for putting me back on the right path.

Kind regards,
RandomCoder.
 
Top