1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003 |
- ' Copyright (c) 2007-2025 Bruce A Henderson
- ' All rights reserved.
- '
- ' Redistribution and use in source and binary forms, with or without
- ' modification, are permitted provided that the following conditions are met:
- ' * Redistributions of source code must retain the above copyright
- ' notice, this list of conditions and the following disclaimer.
- ' * Redistributions in binary form must reproduce the above copyright
- ' notice, this list of conditions and the following disclaimer in the
- ' documentation and/or other materials provided with the distribution.
- ' * Neither the name of Bruce A Henderson nor the
- ' names of its contributors may be used to endorse or promote products
- ' derived from this software without specific prior written permission.
- '
- ' THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
- ' EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- ' WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- ' DISCLAIMED. IN NO EVENT SHALL Bruce A Henderson BE LIABLE FOR ANY
- ' DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- ' (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- ' LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- ' ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- ' (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- ' SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- '
- SuperStrict
- Rem
- bbdoc: Regular Expressions
- End Rem
- Module Text.RegEx
- ModuleInfo "Version: 1.13"
- ModuleInfo "Author: PCRE - Philip Hazel"
- ModuleInfo "License: BSD"
- ModuleInfo "Copyright: PCRE - 1997-2021 University of Cambridge"
- ModuleInfo "Copyright: Wrapper - 2007-2025 Bruce A Henderson"
- ModuleInfo "History: 1.13"
- ModuleInfo "History: Fixed free of pcre pointer."
- ModuleInfo "History: 1.12"
- ModuleInfo "History: Updated to PCRE 10.43"
- ModuleInfo "History: Options are now configured per search. Default options are used if none provided."
- ModuleInfo "History: Added SetDefaultOptions method."
- ModuleInfo "History: Options can be ignored in preference for pattern provided options."
- ModuleInfo "History: 1.11"
- ModuleInfo "History: Updated to PCRE 10.39"
- ModuleInfo "History: 1.10"
- ModuleInfo "History: Updated to PCRE 10.31"
- ModuleInfo "History: 1.09"
- ModuleInfo "History: Fixed issue using wrong ovector offset."
- ModuleInfo "History: 1.08"
- ModuleInfo "History: Updated to PCRE 10.30"
- ModuleInfo "History: 1.07"
- ModuleInfo "History: Updated for 64-bit."
- ModuleInfo "History: 1.06"
- ModuleInfo "History: Updated to PCRE 10.00"
- ModuleInfo "History: Changed TRegExMatch to get data as required, rather than cache it."
- ModuleInfo "History: Added support for JIT compilation via new options."
- ModuleInfo "History: Added ByName methods for sub expression retrieval."
- ModuleInfo "History: 1.05"
- ModuleInfo "History: Updated to PCRE 8.34"
- ModuleInfo "History: Changed to use pcre16 functions, which is BlitzMax's native character size. (no more utf8 conversions)"
- ModuleInfo "History: Don't include the zero-termination character in sub expressions."
- ModuleInfo "History: 1.04"
- ModuleInfo "History: Updated to PCRE 8.0"
- ModuleInfo "History: Fixed offset problems when working with non-ascii text."
- ModuleInfo "History: Fixed Replace() where loop was overflowing."
- ModuleInfo "History: Added test_08 for utf-8."
- ModuleInfo "History: 1.03"
- ModuleInfo "History: Updated to PCRE 7.4"
- ModuleInfo "History: 1.02"
- ModuleInfo "History: Added grable's subquery/replace tweak."
- ModuleInfo "History: 1.01"
- ModuleInfo "History: Options now global."
- ModuleInfo "History: 1.00"
- ModuleInfo "History: Initial Release. (PCRE 7.0)"
- ModuleInfo "CC_OPTS: -DHAVE_CONFIG_H -DPCRE2_CODE_UNIT_WIDTH=16"
- ?macos
- ModuleInfo "CC_VOPT: osversion|-mmacosx-version-min=11.00"
- ?
- Import "common.bmx"
- Rem
- bbdoc: Performs #Find and #Replace / #ReplaceAll on strings using Perl Compatible Regular Expressions.
- End Rem
- Type TRegEx
- ' Configures the way in which Regular Expressions are handled.
- Global defaultOptions:TRegExOptions
- ' The options to use for this search.
- Field options:TRegExOptions
- ' The pattern to search for.
- Field searchPattern:String
- ' The replacement pattern string.
- 'Field replacePattern:String
-
- Field lastPattern:String
- Field lastTarget:String
-
- ' pointer to the target string (as a WString)
- Field TArg:Byte Ptr
- ' the length of the target string
- Field targLength:Size_T
-
- Field lastEndPos:Size_T
-
- ' pointer to the compiled expression
- Field pcre:Byte Ptr
-
- ' pointer to the offsets vector, owned by pcre2
- Field offsets:Size_T Ptr
- ' number of offsets
- Field sizeOffsets:Int
-
- Field matchPtr:Byte Ptr
-
- Field compiled:Int = False
-
- Method Delete()
-
- If TArg Then
- MemFree(TArg)
- TArg = Null
- End If
-
- If matchPtr Then
- pcre2_match_data_free_16(matchPtr)
- matchPtr = Null
- End If
-
- If pcre
- pcre2_code_free_16(pcre)
- pcre = Null
- EndIf
-
- End Method
- Rem
- bbdoc: Creates a new #TRegEx object.
- about: @searchPattern is the regular expression with which to perform the search.
- End Rem
- Method New(searchPattern:String, options:TRegExOptions = Null)
- Self.searchPattern = searchPattern
- If options Then
- Self.options = options
- Else
- If Not defaultOptions Then
- defaultOptions = New TRegExOptions
- End If
- Self.options = defaultOptions
- End If
- End Method
-
- Rem
- bbdoc: Creates a new #TRegEx object.
- about: @searchPattern is the regular expression with which to perform the search.
- End Rem
- Function Create:TRegEx(searchPattern:String, options:TRegExOptions = Null)
- Return New TRegEx(searchPattern, options)
- End Function
- Rem
- bbdoc: Sets the default options for all new #TRegEx objects.
- about: This is useful if you want to set the options once and use them for all searches.
- End Rem
- Function SetDefaultOptions(options:TRegExOptions)
- defaultOptions = options
- End Function
-
- Rem
- bbdoc: Replaces all occurances of the search Pattern with @replaceWith on @target, from @startPos.
- returns: The newly replaced string.
- about: Doesn't affect the original @target contents.
- End Rem
- Method ReplaceAll:String(target:String, replaceWith:String, startPos:Size_T = 0)
- If Not options Then
- options = New TRegExOptions
- End If
- ' remember the current setting
- Local oldOpt:Int = options.replaceAllMatches
-
- ' enable global replace
- options.replaceAllMatches = True
-
- ' let Replace do all the work
- Local s:String = Replace(target, replaceWith, startPos)
-
- ' put back the "current" setting
- options.replaceAllMatches = oldOpt
-
- Return s
- End Method
-
- Rem
- bbdoc: Replaces the first occurance of the search Pattern with @replaceWith on @target, from @startPos.
- returns: The newly replaced string.
- about: To access a specific subquery during the replace, you can use the \n syntax in @replaceWith, where \0
- refers to the whole match, and \1 refers to the first subquery/group, and so on. <i>(see
- <a href="../tests/test_07.bmx">test_07</a> for an example)</i>.
- <p>Doesn't affect the original @target contents.</p>
- End Rem
- Method Replace:String(target:String, replaceWith:String, startPos:Size_T = 0)
- If Not options Then
- options = New TRegExOptions
- End If
- Local globalReplace:Int = options.replaceAllMatches
- ' the search pattern has changed !
- ' recompile
- ' this only happens very occasionally... (probably ;-)
- 'If lastPattern <> searchPattern Or Not pcre Then
- If Not compiled Then
- init()
- End If
- Local retString:String
-
- ' this is a new target...
- If target <> lastTarget Then
- lastTarget = target
-
- If TArg Then
- MemFree(TArg)
- End If
-
- TArg = target.toWString()
- targLength = target.length
- End If
- ' initial search...
- Local result:Int = pcre2_match_16(pcre, TArg, targLength, startPos, getExecOpt(), matchPtr, Null)
- ' if there wasn't an error... process the match (even for no-match)
- While result >= 0 Or result = PCRE2_ERROR_NOMATCH
- sizeOffsets = pcre2_get_ovector_count_16(matchPtr)
- offsets = pcre2_get_ovector_pointer_16(matchPtr)
- Local replaceStr:String = replaceWith
- Local ofs:Size_T Ptr = offsets
- For Local i:Int = 0 Until result
- Local idx:Int = i * 2
- replaceStr = replaceStr.Replace( "\" + i, lastTarget[ofs[idx]..ofs[idx+1]])
- Next
- If result > 0 Then
- ' add text so far, and the replacement
- retString:+ lastTarget[startPos..offsets[0]] + replaceStr
-
- Else
- ' search finished. Fill to the end
- retString:+ lastTarget[startPos..targLength]
- Exit
- End If
-
- ' set start to the end of the last match position
- startPos = offsets[1]
-
- ' only doing the first replace? Then we can exit now...
- If Not globalReplace Then
-
- ' all done. Fill to the end
- retString:+ lastTarget[startPos..targLength]
- Exit
- End If
-
- ' find the next match
- result = pcre2_match_16(pcre, TArg, targLength, startPos, getExecOpt(), matchPtr, Null)
- Wend
-
- Return retString ' convert back to max string
- End Method
-
- Rem
- bbdoc: Performs a search on the given @target from @startPos, using the search Pattern.
- returns: A #TRegExMatch object or Null if no matches found.
- about: If @target is <b>not</b> set, the search will use the <b>previous</b> @target.
- You will want to set @target the first time this method is called.<br>
- If you call this method with no parameters it will start the search from the end of the last search, effectively
- iterating through the target string.
- End Rem
- Method Find:TRegExMatch(target:String = Null)
- If Not options Then
- options = New TRegExOptions
- End If
- ' the search pattern has changed !
- ' recompile
- ' this only happens very occasionally... (probably ;-)
- 'If lastPattern <> searchPattern Or Not pcre Then
- If Not compiled Then
- init()
- End If
- Local startPos:Size_T
- ' no target specified, we are probably performing another search on the original target
- If Not target Then
-
- ' no lastTarget? Not allowed.
- If Not lastTarget Then
- Return Null
- End If
- startPos = lastEndPos
- Else
- ' this is a new target...
- If target <> lastTarget Then
- lastTarget = target
-
- If TArg Then
- MemFree(TArg)
- End If
-
- TArg = target.toWString()
- targLength = target.length
- End If
- End If
- Return DoFind(startPos)
- End Method
- Method DoFind:TRegExMatch(startPos:Size_T)
- Local result:Int = pcre2_match_16(pcre, TArg, targLength, startPos, getExecOpt(), matchPtr, Null)
-
- If result >= 0 Then
- sizeOffsets = pcre2_get_ovector_count_16(matchPtr)
- offsets = pcre2_get_ovector_pointer_16(matchPtr)
- Local match:TRegExMatch = New TRegExMatch(pcre, matchPtr)
- lastEndPos = offsets[1]
- Return match
- Else
- ' no point raising an exception when nothing found... we can just return a null object
- If result = PCRE2_ERROR_NOMATCH Then
- Return Null
- End If
-
- ' there was an error of some kind... throw it!
- Throw TRegExException.Raise(result)
- End If
- End Method
- Rem
- bbdoc: Performs a search on the given @target from @startPos, using the search Pattern.
- returns: A #TRegExMatch object or Null if no matches found.
- End Rem
- Method Find:TRegExMatch(target:String, startPos:Size_T)
-
- If Not options Then
- options = New TRegExOptions
- End If
- ' the search pattern has changed !
- ' recompile
- ' this only happens very occasionally... (probably ;-)
- 'If lastPattern <> searchPattern Or Not pcre Then
- If Not compiled Then
- init()
- End If
- ' no target specified, we are probably performing another search on the original target
- If Not target Then
-
- ' no lastTarget? Not allowed.
- If Not lastTarget Then
- Return Null
- End If
-
- ' no startPos? then we'll start from the end of the last search point
- If startPos < 0 Then
- startPos = lastEndPos
- End If
- Else
- ' this is a new target...
- If target <> lastTarget Then
- lastTarget = target
-
- If TArg Then
- MemFree(TArg)
- End If
-
- TArg = target.toWString()
- targLength = target.length
- End If
- End If
- ' set the startPos to 0 if not already set
- If startPos < 0 Then
- startPos = 0
- End If
-
- Return DoFind(startPos)
- End Method
-
- ' resets and recompiles the regular expression
- Method init()
- lastPattern = searchPattern
-
- Local pat:Short Ptr = lastPattern.ToWString()
- Local errorcode:Int
- Local erroffset:Size_T
- Local bptr:Byte Ptr = pcre2_compile_16(pat, Size_T(lastPattern.length), getCompileOpt(), Varptr errorcode, ..
- Varptr erroffset, Null)
- MemFree(pat)
-
- If bptr Then
- If pcre
- pcre2_code_free_16(pcre)
- EndIf
-
- pcre = bptr
- Else
- Local buffer:Short[256]
- pcre2_get_error_message_16(errorcode, buffer, 256)
- Throw TRegExException.Raise(-99, String.fromWString(buffer))
- End If
- Local jitOptions:Int = getJITOpt()
- If jitOptions Then
- Local result:Int = pcre2_jit_compile_16(pcre, jitOptions)
- End If
-
- If matchPtr Then
- pcre2_match_data_free_16(matchPtr)
- End If
- matchPtr = pcre2_match_data_create_from_pattern_16(pcre, Null)
-
- compiled = True
- End Method
-
- ' possible options for compiling
- Method getCompileOpt:Int()
- Local opt:Int = PCRE2_UTF
- If options.onlyPatternOptions Then
- Return opt
- End If
-
- If Not options.caseSensitive Then
- opt:| PCRE2_CASELESS
- End If
-
- If options.dotMatchAll Then
- opt:| PCRE2_DOTALL
- End If
-
- If Not options.greedy Then
- opt:| PCRE2_UNGREEDY
- End If
-
- Select options.lineEndType
- Case 1
- opt:| PCRE2_NEWLINE_CR
- Case 2
- opt:| PCRE2_NEWLINE_LF
- Case 3
- opt:| PCRE2_NEWLINE_CRLF
- Default
- opt:| PCRE2_NEWLINE_ANY
- End Select
-
- If Not options.matchEmpty Then
- opt:| PCRE2_NOTEMPTY
- End If
-
- If options.targetIsMultiline Then
- opt:| PCRE2_MULTILINE
- End If
-
- If options.dollarEndOnly Then
- opt:| PCRE2_DOLLAR_ENDONLY
- End If
-
- If options.extended Then
- opt:| PCRE2_EXTENDED
- End If
-
- Return opt
- End Method
-
- ' possible options for execution
- Method getExecOpt:Int()
- Local opt:Int
- If options.onlyPatternOptions Then
- Return opt
- End If
-
- Select options.lineEndType
- Case 1
- opt:| PCRE2_NEWLINE_CR
- Case 2
- opt:| PCRE2_NEWLINE_LF
- Case 3
- opt:| PCRE2_NEWLINE_CRLF
- Default
- opt:| PCRE2_NEWLINE_ANY
- End Select
- If Not options.matchEmpty Then
- opt:| PCRE2_NOTEMPTY
- End If
-
- If Not options.stringIsLineBeginning Then
- opt:| PCRE2_NOTBOL
- End If
-
- If Not options.stringIsLineEnding Then
- opt:| PCRE2_NOTEOL
- End If
-
- Return opt
- End Method
-
- ' possible options for jit
- Method getJITOpt:Int()
- Local opt:Int
- If options.onlyPatternOptions Then
- Return opt
- End If
-
- If options.jitComplete Then
- opt :| PCRE2_JIT_COMPLETE
- End If
- If options.jitPartialSoft Then
- opt :| PCRE2_JIT_PARTIAL_SOFT
- End If
- If options.jitPartialHard Then
- opt :| PCRE2_JIT_PARTIAL_HARD
- End If
-
- End Method
- Rem
- bbdoc: Returns which optional features are available.
- End Rem
- Function Config:Int(what:Int, where_:Int Var)
- If what <> PCRE2_CONFIG_UNICODE_VERSION And what <> PCRE2_CONFIG_VERSION Then
- Return pcre2_config_16(what, Varptr where_)
- End If
- Return PCRE2_ERROR_BADOPTION
- End Function
- End Type
- Rem
- bbdoc: Used to extract the matched string when doing a search with regular expressions.
- End Rem
- Type TRegExMatch
- Private
- Field pcre:Byte Ptr
- Field matchPtr:Byte Ptr
- Field count:UInt
- Method New(pcre:Byte Ptr, matchPtr:Byte Ptr)
- Self.pcre = pcre
- Self.matchPtr = matchPtr
- Self.count = pcre2_get_ovector_count_16(matchPtr)
- End Method
- Public
- Rem
- bbdoc: Returns the number of subexpressions as a result of the search.
- End Rem
- Method SubCount:Int()
- Return count
- End Method
-
- Rem
- bbdoc: Returns the subexpression for @matchNumber.
- returns: The matched string, the subexpression string, or "" if @matchNumber is out of range.
- about: For expressions with no subpattern groups, this method can be used without
- a parameter to return the matched string.
- End Rem
- Method SubExp:String(matchNumber:Int = 0)
- Local _subExpr:String
-
- If matchNumber >= 0 And matchNumber < count Then
- Local sPtr:Short Ptr
- Local sLen:Size_T
- Local result:Int = pcre2_substring_get_bynumber_16(matchPtr, matchNumber, Varptr sPtr, Varptr sLen)
- If Not result Then
- _subExpr = String.FromShorts(sPtr, Int(sLen))
- pcre2_substring_free_16(sPtr)
- End If
- End If
-
-
- Return _subExpr
- End Method
-
- Rem
- bbdoc: Returns the start position for subexpression @matchNumber.
- returns: The start position, or -1 if @matchNumber is out of range.
- about: For expressions with no subpattern groups, this method can be used without a parameter
- to return the start position of the matched string.
- End Rem
- Method SubStart:Int(matchNumber:Int = 0)
- If matchNumber >= 0 And matchNumber < count Then
- Local offsets:Size_T Ptr = pcre2_get_ovector_pointer_16(matchPtr)
- Return offsets[matchNumber]
- End If
- Return -1
- End Method
- Rem
- bbdoc: Returns the end position for subexpression @matchNumber.
- returns: The end position, or -1 if @matchNumber is out of range.
- about: For expressions with no subpattern groups, this method can be used without a parameter
- to return the end position of the matched string.
- End Rem
- Method SubEnd:Int(matchNumber:Int = 0)
- If matchNumber >= 0 And matchNumber < count Then
- Local offsets:Size_T Ptr = pcre2_get_ovector_pointer_16(matchPtr)
- Return offsets[matchNumber + 1] - 1
- End If
- Return -1
- End Method
-
- Rem
- bbdoc: Returns the subexpression for the given @name.
- returns: The matched string, the subexpression string, or "" if @matchNumber is out of range.
- End Rem
- Method SubExp:String(name:String)
- Return SubExpByName(name)
- End Method
- Rem
- bbdoc: Returns the subexpression for the given @name.
- returns: The matched string, the subexpression string, or "" if @matchNumber is out of range.
- End Rem
- Method SubExpByName:String(name:String)
- Local _subExpr:String
- If name Then
- Local sPtr:Short Ptr
- Local sLen:Size_T
- Local n:Short Ptr = name.ToWString()
- Local result:Int = pcre2_substring_get_byname_16(matchPtr, n, Varptr sPtr, Varptr sLen)
- MemFree(n)
- If Not result Then
- _subExpr = String.FromShorts(sPtr, Int(sLen))
-
- pcre2_substring_free_16(sPtr)
- End If
- End If
-
- Return _subExpr
- End Method
- Rem
- bbdoc: Returns the index of the subexpression for the given @name.
- End Rem
- Method SubIndex:Int(name:String)
- Return SubIndexByName(name)
- End Method
- Rem
- bbdoc: Returns the index of the subexpression for the given @name.
- End Rem
- Method SubIndexByName:Int(name:String)
- If name Then
- Local n:Short Ptr = name.ToWString()
- Local index:Int = pcre2_substring_number_from_name_16(pcre, n)
- MemFree(n)
-
- If index >= 0 Then
- Return index
- End If
- End If
- Return -1
- End Method
- Rem
- bbdoc: Returns the start position of the subexpression for the given @name.
- End Rem
- Method SubStart:Int(name:String)
- Return SubStartByName(name)
- End Method
- Rem
- bbdoc: Returns the start position of the subexpression for the given @name.
- End Rem
- Method SubStartByName:Int(name:String)
- If name Then
- Local n:Short Ptr = name.ToWString()
- Local index:Int = pcre2_substring_number_from_name_16(pcre, n)
- MemFree(n)
-
- If index >= 0 Then
- Local offsets:Size_T Ptr = pcre2_get_ovector_pointer_16(matchPtr)
- Return offsets[index]
- End If
- End If
- Return -1
- End Method
- Rem
- bbdoc: Returns the end position of the subexpression for the given @name.
- End Rem
- Method SubEnd:Int(name:String)
- Return SubEndByName(name)
- End Method
- Rem
- bbdoc: Returns the end position of the subexpression for the given @name.
- End Rem
- Method SubEndByName:Int(name:String)
- If name Then
- Local n:Short Ptr = name.ToWString()
- Local index:Int = pcre2_substring_number_from_name_16(pcre, n)
- MemFree(n)
-
- If index >= 0 Then
- Local offsets:Size_T Ptr = pcre2_get_ovector_pointer_16(matchPtr)
- Return offsets[index + 1] - 1
- End If
- End If
- Return -1
- End Method
-
- End Type
- Rem
- bbdoc: Specifies options used when performing searches.
- End Rem
- Type TRegExOptions
- Rem
- bbdoc: Ignore other options and use only the pattern's options, like case sensitivity, etc.
- End Rem
- Field onlyPatternOptions:Int = False
- Rem
- bbdoc: Whether matches are case sensitive.
- End Rem
- Field caseSensitive:Int = False
- Rem
- bbdoc: Allow dot (period) to match new lines as well as everything else.
- about: False indicates dot doesn't match new lines.
- End Rem
- Field dotMatchAll:Int = False
- Rem
- bbdoc: Greedy matches everything from the beginning of the first delimeter to the end of the last delimiter, and everything in between.
- about:
- End Rem
- Field greedy:Int = True
- Rem
- bbdoc: Determines how new lines are interpreted.
- about:
- <ul>
- <li>0 - any line ending</li>
- <li>1 - \r</li>
- <li>2 - \n</li>
- <li>3 - \r\n</li>
- </ul>
- End Rem
- Field lineEndType:Int = 0
- Rem
- bbdoc: Allow patterns to match empty strings.
- End Rem
- Field matchEmpty:Int = True
- 'Rem
- 'bbdoc: Indicates whether all occurances of matches will be replaced.
- 'about: Only applicable during a Replace.
- 'End Rem
- Field replaceAllMatches:Int = False
- Rem
- bbdoc: Count the beginning of a string as the beginning of a line.
- End Rem
- Field stringIsLineBeginning:Int = True
- Rem
- bbdoc: Count the end of a string as the end of a line.
- End Rem
- Field stringIsLineEnding:Int = True
- Rem
- bbdoc: Matches internal new lines against ^ and $.
- about: Set to false to ignore internal new lines.
- End Rem
- Field targetIsMultiline:Int = True
- Rem
- bbdoc: Dollar ($) matches newline at end.
- about: Set to True for dollar to only match the end of the string, otherwise
- matches a newline before the end of the string.
- End Rem
- Field dollarEndOnly:Int = False
- Rem
- bbdoc: Ignore whitespace and # comments.
- about: When set to True, whitespace in the pattern (other than in a character class) and
- characters between a # outside a character class and the next newline are ignored.<br>
- An escaping backslash can be used to include a whitespace or # character as part of the pattern.
- End Rem
- Field extended:Int = False
- Rem
- bbdoc: Compile code for full matching.
- about: When set to True, the JIT compiler is enabled.
- End Rem
- Field jitComplete:Int = False
- Rem
- bbdoc: Compile code For soft partial matching.
- about: When set to True, the JIT compiler is enabled.
- End Rem
- Field jitPartialSoft:Int = False
- Rem
- bbdoc: Compile code for hard partial matching.
- about: When set to True, the JIT compiler is enabled.
- End Rem
- Field jitPartialHard:Int = False
- End Type
- Rem
- bbdoc: A Regular Expression exception.
- about: This can be thrown either during regular expression compilation (-99) or during a search (-1 to -23).
- End Rem
- Type TRegExException
- Rem
- bbdoc: The type of error thrown.
- about: -99 is a regular expression compile error. Read #message for details.<br>
- -1 to -23 is thrown during a search. Read #message for details.
- End Rem
- Field num:Int
- Rem
- bbdoc: The error text.
- End Rem
- Field message:String
-
- Function Raise:TRegExException(num:Int, message:String = Null)
- Local this:TRegExException = New TRegExException
-
- If message Then
- this.message = message
- Else
- this.message = this.getFromNum(num)
- End If
-
- this.num = num
- Return this
- End Function
-
- Rem
- bbdoc: Returns the exception as a String.
- End Rem
- Method toString:String()
- Return "( " + num + " ) " + message
- End Method
-
- Method getFromNum:String(err:Int)
- Select err
- Case -1
- Return "No Match"
- Case -2
- Return "PCRE2_ERROR_PARTIAL"
- Case -3
- Return "PCRE2_ERROR_UTF8_ERR1"
- Case -4
- Return "PCRE2_ERROR_UTF8_ERR2"
- Case -5
- Return "PCRE2_ERROR_UTF8_ERR3"
- Case -6
- Return "PCRE2_ERROR_UTF8_ERR4"
- Case -7
- Return "PCRE2_ERROR_UTF8_ERR5"
- Case -8
- Return "PCRE2_ERROR_UTF8_ERR6"
- Case -9
- Return "PCRE2_ERROR_UTF8_ERR7"
- Case -10
- Return "PCRE2_ERROR_UTF8_ERR8"
- Case -11
- Return "PCRE2_ERROR_UTF8_ERR9"
- Case -12
- Return "PCRE2_ERROR_UTF8_ERR10"
- Case -13
- Return "PCRE2_ERROR_UTF8_ERR11"
- Case -14
- Return "PCRE2_ERROR_UTF8_ERR12"
- Case -15
- Return "PCRE2_ERROR_UTF8_ERR13"
- Case -16
- Return "PCRE2_ERROR_UTF8_ERR14"
- Case -17
- Return "PCRE2_ERROR_UTF8_ERR15"
- Case -18
- Return "PCRE2_ERROR_UTF8_ERR16"
- Case -19
- Return "PCRE2_ERROR_UTF8_ERR17"
- Case -20
- Return "PCRE2_ERROR_UTF8_ERR18"
- Case -21
- Return "PCRE2_ERROR_UTF8_ERR19"
- Case -22
- Return "PCRE2_ERROR_UTF8_ERR20"
- Case -23
- Return "PCRE2_ERROR_UTF8_ERR21"
- Case -24
- Return "PCRE2_ERROR_UTF16_ERR1"
- Case -25
- Return "PCRE2_ERROR_UTF16_ERR2"
- Case -26
- Return "PCRE2_ERROR_UTF16_ERR3"
- Case -27
- Return "PCRE2_ERROR_UTF32_ERR1"
- Case -28
- Return "PCRE2_ERROR_UTF32_ERR2"
- Case -29
- Return "PCRE2_ERROR_BADDATA"
- Case -30
- Return "PCRE2_ERROR_BADLENGTH"
- Case -31
- Return "PCRE2_ERROR_BADMAGIC"
- Case -32
- Return "PCRE2_ERROR_BADMODE"
- Case -33
- Return "PCRE2_ERROR_BADOFFSET"
- Case -34
- Return "PCRE2_ERROR_BADOPTION"
- Case -35
- Return "PCRE2_ERROR_BADREPLACEMENT"
- Case -36
- Return "PCRE2_ERROR_BADUTFOFFSET"
- Case -37
- Return "PCRE2_ERROR_CALLOUT"
- Case -38
- Return "PCRE2_ERROR_DFA_BADRESTART"
- Case -39
- Return "PCRE2_ERROR_DFA_RECURSE"
- Case -40
- Return "PCRE2_ERROR_DFA_UCOND"
- Case -41
- Return "PCRE2_ERROR_DFA_UFUNC"
- Case -42
- Return "PCRE2_ERROR_DFA_UITEM"
- Case -43
- Return "PCRE2_ERROR_DFA_WSSIZE"
- Case -44
- Return "PCRE2_ERROR_INTERNAL"
- Case -45
- Return "PCRE2_ERROR_JIT_BADOPTION"
- Case -46
- Return "PCRE2_ERROR_JIT_STACKLIMIT"
- Case -47
- Return "PCRE2_ERROR_MATCHLIMIT"
- Case -48
- Return "PCRE2_ERROR_NOMEMORY"
- Case -49
- Return "PCRE2_ERROR_NOSUBSTRING"
- Case -50
- Return "PCRE2_ERROR_NOUNIQUESUBSTRING"
- Case -51
- Return "PCRE2_ERROR_NULL"
- Case -52
- Return "PCRE2_ERROR_RECURSELOOP"
- Case -53
- Return "PCRE2_ERROR_RECURSIONLIMIT"
- Case -54
- Return "PCRE2_ERROR_UNAVAILABLE"
- Case -55
- Return "PCRE2_ERROR_UNSET"
- End Select
- End Method
-
- End Type
|