(preparedSearch, prepared, allowSpaces=false, allowPartialMatch=false)
| 359 | |
| 360 | |
| 361 | var algorithm = (preparedSearch, prepared, allowSpaces=false, allowPartialMatch=false) => { |
| 362 | if(allowSpaces===false && preparedSearch.containsSpace) return algorithmSpaces(preparedSearch, prepared, allowPartialMatch) |
| 363 | |
| 364 | var searchLower = preparedSearch._lower |
| 365 | var searchLowerCodes = preparedSearch.lowerCodes |
| 366 | var searchLowerCode = searchLowerCodes[0] |
| 367 | var targetLowerCodes = prepared._targetLowerCodes |
| 368 | var searchLen = searchLowerCodes.length |
| 369 | var targetLen = targetLowerCodes.length |
| 370 | var searchI = 0 // where we at |
| 371 | var targetI = 0 // where you at |
| 372 | var matchesSimpleLen = 0 |
| 373 | |
| 374 | // very basic fuzzy match; to remove non-matching targets ASAP! |
| 375 | // walk through target. find sequential matches. |
| 376 | // if all chars aren't found then exit |
| 377 | for(;;) { |
| 378 | var isMatch = searchLowerCode === targetLowerCodes[targetI] |
| 379 | if(isMatch) { |
| 380 | matchesSimple[matchesSimpleLen++] = targetI |
| 381 | ++searchI; if(searchI === searchLen) break |
| 382 | searchLowerCode = searchLowerCodes[searchI] |
| 383 | } |
| 384 | ++targetI; if(targetI >= targetLen) return NULL // Failed to find searchI |
| 385 | } |
| 386 | |
| 387 | var searchI = 0 |
| 388 | var successStrict = false |
| 389 | var matchesStrictLen = 0 |
| 390 | |
| 391 | var nextBeginningIndexes = prepared._nextBeginningIndexes |
| 392 | if(nextBeginningIndexes === NULL) nextBeginningIndexes = prepared._nextBeginningIndexes = prepareNextBeginningIndexes(prepared.target) |
| 393 | targetI = matchesSimple[0]===0 ? 0 : nextBeginningIndexes[matchesSimple[0]-1] |
| 394 | |
| 395 | // Our target string successfully matched all characters in sequence! |
| 396 | // Let's try a more advanced and strict test to improve the score |
| 397 | // only count it as a match if it's consecutive or a beginning character! |
| 398 | var backtrackCount = 0 |
| 399 | if(targetI !== targetLen) for(;;) { |
| 400 | if(targetI >= targetLen) { |
| 401 | // We failed to find a good spot for this search char, go back to the previous search char and force it forward |
| 402 | if(searchI <= 0) break // We failed to push chars forward for a better match |
| 403 | |
| 404 | ++backtrackCount; if(backtrackCount > 200) break // exponential backtracking is taking too long, just give up and return a bad match |
| 405 | |
| 406 | --searchI |
| 407 | var lastMatch = matchesStrict[--matchesStrictLen] |
| 408 | targetI = nextBeginningIndexes[lastMatch] |
| 409 | |
| 410 | } else { |
| 411 | var isMatch = searchLowerCodes[searchI] === targetLowerCodes[targetI] |
| 412 | if(isMatch) { |
| 413 | matchesStrict[matchesStrictLen++] = targetI |
| 414 | ++searchI; if(searchI === searchLen) { successStrict = true; break } |
| 415 | ++targetI |
| 416 | } else { |
| 417 | targetI = nextBeginningIndexes[targetI] |
| 418 | } |
no test coverage detected
searching dependent graphs…