All Downloads are FREE. Search and download functionalities are using the official Maven repository.

sttp.tapir.server.jdkhttp.internal.KMPMatcher.scala Maven / Gradle / Ivy

The newest version!
package sttp.tapir.server.jdkhttp.internal
import scala.collection.mutable

class KMPMatcher(delimiter: Array[Byte]) {
  private val table = KMPMatcher.buildLongestPrefixSuffixTable(delimiter)
  private var matches: Int = 0

  def noMatches = this.matches == 0
  def getMatches: Int = this.matches
  def getDelimiter: Array[Byte] = this.delimiter

  def matchByte(b: Byte): KMPMatcher.MatchResult = {
    val numMatchesBeforeReset = getMatches
    while (getMatches > 0 && b != delimiter(getMatches)) {
      this.matches = this.table(getMatches - 1)
    }

    val matchesBeforeCurrentByte = getMatches

    if (b == delimiter(matches)) {
      matches += 1
      if (this.matches == delimiter.length) {
        this.matches = 0
        KMPMatcher.Match
      } else {
        KMPMatcher.NotMatched(numMatchesBeforeReset - matchesBeforeCurrentByte)
      }
    } else {
      KMPMatcher.NotMatched(numMatchesBeforeReset - matchesBeforeCurrentByte)
    }
  }
}

object KMPMatcher {
  sealed trait MatchResult
  case object Match extends MatchResult
  case class NotMatched(numNoLongerMatchedBytes: Int) extends MatchResult

  private def buildLongestPrefixSuffixTable(s: Array[Byte]): mutable.ArrayBuffer[Int] = {
    val lookupTable = mutable.ArrayBuffer.fill(s.length)(-1)
    lookupTable(0) = 0
    var len = 0
    var i = 1
    while (i < s.length) {
      if (s(i) == s(len)) {
        len += 1
        lookupTable(i) = len
        i += 1
      } else {
        if (len == 0) {
          lookupTable(i) = 0
          i = i + 1
        } else {
          len = lookupTable(len - 1)
        }
      }
    }
    lookupTable
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy