private synchronized void determineLines(){
  if (m_lineMap != null)   return;
  int count=lineCountFor(m_text) + 1;
  m_lineMap=new int[(2 * count) + 1];
  int i=0;
  int lineNum=0;
  int startAt=0;
  int endAt=0;
  int length=m_text.length();
  char c='\0';
  while (i < length) {
    c=m_text.charAt(i++);
    if (c == '\n' || c == '\r') {
      m_lineMap[2 * lineNum]=startAt;
      m_lineMap[(2 * lineNum) + 1]=endAt;
      lineNum++;
      if (c == '\r' && i < length && m_text.charAt(i) == '\n')       i++;
      startAt=i;
      endAt=i;
    }
 else     endAt++;
  }
  if (startAt != endAt) {
    m_lineMap[2 * lineNum]=startAt;
    m_lineMap[(2 * lineNum) + 1]=endAt;
  }
}

private synchronized void determineLines ( ) { if ( m_lineMap != null ) return ; int count = lineCountFor ( m_text ) + 1 ; m_lineMap = new int [ ( 2 * count ) + 1 ] ; int i = 0 ; int lineNum = 0 ; int startAt = 0 ; int endAt = 0 ; int length = m_text . length ( ) ; char c = '\0' ; while ( i < length ) { c = m_text . charAt ( i ++ ) ; if ( c == '\n' || c == '\r' ) { m_lineMap [ 2 * lineNum ] = startAt ; m_lineMap [ ( 2 * lineNum ) + 1 ] = endAt ; lineNum ++ ; if ( c == '\r' && i < length && m_text . charAt ( i ) == '\n' ) i ++ ; startAt = i ; endAt = i ; } else endAt ++ ; } if ( startAt != endAt ) { m_lineMap [ 2 * lineNum ] = startAt ; m_lineMap [ ( 2 * lineNum ) + 1 ] = endAt ; } }
build mapping tables based on the line count of the given source string . these tables allow us to compute starting and ending locations of each line of the source file . the assumption using this technique is that most lines of the source files will never be accessed thus we only incur the overhead of 8 bytes ( start & end ) per line , plus the actual string contents each line a line is requested . thus we need 8 * num_files * num_lines_per_file bytes for all these maps . for example , say each file is 1000 lines and we have 400 source files ; we would consume 3 . 2mb . with each request we would allocate an additional 20 + bytes for the string ( assuming a 20b avg line length ) . allocating each line individually we would consume 1000 * 400 * 20 = 8mb . it is debatable whether this scheme is more efficient than actually builing an array of strings to contain the lines , but gut feel says it is ; )
