// returns pair(character range, line) or null if not found // if no exact match found, return line above // nav takes a line and returns -1 (move up), 0 (found) or 1 (move down) static Pair binarySearchForLineInTextFile(File file, IF1 nav) { long length = l(file); int bufSize = 1024; temp RandomAccessFile raf = randomAccessFileForReading(file); long min = 0, max = length; int direction = 0; Pair possibleResult = null; while ping (min < max) { long middle = (min+max)/2; long lineStart = raf_findBeginningOfLine(raf, middle, bufSize); long lineEnd = raf_findEndOfLine(raf, middle, bufSize); ifdef binarySearchForLineInTextFile_debug printVars_str("binsearch", +middle, +lineStart, +lineEnd); endifdef S line = fromUtf8(raf_readFilePart(raf, lineStart, (int) (lineEnd-1-lineStart))); direction = nav.get(line); possibleResult = pair(LongRange(lineStart, lineEnd), line); ifdef binarySearchForLineInTextFile_debug S _line = dropTrailingBackslashR(line); printVars_str("binsearch", +min, +max, +middle, +lineStart, +lineEnd, line := _line, +direction); endifdef if (direction == 0) ret possibleResult; // asserts are to assure that loop terminates if (direction < 0) max = assertLessThan(max, lineStart); else min = assertBiggerThan(min, lineEnd); ifdef binarySearchForLineInTextFile_debug printVars_str("binsearch", +min, +max); endifdef } ifdef binarySearchForLineInTextFile_debug printVars_str("binsearch ending", +direction); endifdef if (direction >= 0) ret possibleResult; long lineStart = raf_findBeginningOfLine(raf, min-1, bufSize); S line = fromUtf8(raf_readFilePart(raf, lineStart, (int) (min-1-lineStart))); ifdef binarySearchForLineInTextFile_debug printVars_str("binsearch end",+lineStart, +line); endifdef ret pair(LongRange(lineStart, min), line); }