/// <summary> /// Managed wrapper around the raw match API. /// <para>From the RE2 docs for the underlying function: /// Don't ask for more match information than you will use: /// runs much faster with nsubmatch == 1 than nsubmatch > 1, and /// runs even faster if nsubmatch == 0. /// Doesn't make sense to use nsubmatch > 1 + NumberOfCapturingGroups(), /// but will be handled correctly. /// </para> /// </summary> /// <param name="hayBytes">The string to match the pattern against</param> /// <param name="startByteIndex">The byte offset to start at</param> /// <param name="numCaptures">The number of match groups to return</param> /// <returns>An array of byte ranges for the captures</returns> private unsafe ByteRange[] RawMatch( ReadOnlySpan <byte> hayBytes, int startByteIndex, int numCaptures) { var captures = new Re2Ffi.cre2_string_t[numCaptures]; fixed(byte *pinnedHayBytes = hayBytes) { // TODO: Support anchor as a parameter var matchResult = Re2Ffi.cre2_match( RawHandle, pinnedHayBytes, hayBytes.Length, startByteIndex, hayBytes.Length, Re2Ffi.cre2_anchor_t.CRE2_UNANCHORED, captures, captures.Length); if (matchResult != 1) { return(Array.Empty <ByteRange>()); } // Convert the captured strings to array indices while we still // have the haystack pinned. We can't have the haystack move // between the `_match` and the conversion to byte ranges // otherwise the pointer arithmetic we do will be invalidated. return(StringsToRanges(captures, new IntPtr(pinnedHayBytes))); } }
/// <summary> /// Checks if the pattern matches somewhere in the given /// <paramref name="haystack" />. /// </summary> /// <param name="haystack">The text to find the pattern in</param> /// <returns>True if the pattern matches, false otherwise.</returns> public unsafe bool IsMatch(ReadOnlySpan <byte> haystack) { var captures = Array.Empty <Re2Ffi.cre2_string_t>(); fixed(byte *hayBytesPtr = haystack) { // TODO: Support anchor as a parameter var matchResult = Re2Ffi.cre2_match( RawHandle, hayBytesPtr, haystack.Length, 0, haystack.Length, Re2Ffi.cre2_anchor_t.CRE2_UNANCHORED, captures, 0); return(matchResult == 1); } }