public void InstantiateSimple() { string pattern = "11 22 33 ?? 55"; var target = new SimplePatternScanData(pattern); Assert.Equal(new byte[] { 0x01, 0x01, 0x01, 0x00, 0x01 }, target.Mask); Assert.Equal(new byte[] { 0x11, 0x22, 0x33, 0x55 }, target.Bytes); }
/// <summary> /// Attempts to find a given pattern inside the memory region this class was created with. /// This method uses the simple search, which simply iterates over all bytes, reading max 1 byte at once. /// This method generally works better when the expected offset is smaller than 4096. /// </summary> /// <param name="pattern"> /// The pattern to look for inside the given region. /// Example: "11 22 33 ?? 55". /// Key: ?? represents a byte that should be ignored, anything else if a hex byte. i.e. 11 represents 0x11, 1F represents 0x1F /// </param> /// <param name="startingIndex">The index to start searching at.</param> /// <returns>A result indicating an offset (if found) of the pattern.</returns> public PatternScanResult SimpleFindPattern(string pattern, int startingIndex = 0) { var target = new SimplePatternScanData(pattern); var patternData = target.Bytes; var patternMask = target.Mask; int lastIndex = (_data.Span.Length - patternMask.Length) + 1; fixed(byte *patternDataPtr = patternData) { for (int x = startingIndex; x < lastIndex; x++) { int patternDataOffset = 0; int currentIndex = x; int y = 0; do { // Some performance is saved by making the mask a non-string, since a string comparison is a bit more involved with e.g. null checks. if (patternMask[y] == 0x0) { currentIndex += 1; y++; continue; } // Performance: No need to check if Mask is `x`. The only supported wildcard is '?'. if (_dataPtr[currentIndex] != patternDataPtr[patternDataOffset]) { goto loopexit; } currentIndex += 1; patternDataOffset += 1; y++; }while (y < patternMask.Length); return(new PatternScanResult(x)); loopexit :; } return(new PatternScanResult(-1)); } }