blob: 4491db6127dfcb1adc3fff5a38ee3b58db22b6a1 [file] [log] [blame]
/*
* Copyright 2000-2010 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.openapi.editor.impl.softwrap.mapping;
import com.intellij.openapi.editor.Document;
import java.util.Collections;
import java.util.List;
/**
* Holds utility methods for document dimensions mapping.
*
* @author Denis Zhdanov
* @since Sep 9, 2010 9:38:42 AM
*/
public class MappingUtil {
private MappingUtil() {
}
/**
* Tries to map given offset to the index of target {@link CacheEntry} that holds information about visual line with that offset.
*
* @param offset target offset
* @param document document which dimensions are being mapped
* @param cache parsed cache entries list that hold information about given document positions and are sorted by visual lines
* in ascending order
* @return non-negative index of target {@link CacheEntry} that holds information about visual line with given offset
* if possible; negative value that indicates insertion point of cache entry for the given offset is to be located.
* That value follows {@link Collections#binarySearch(List, Object)} contract, i.e. real index is calculated
* by <code>'-returned_index - 1'</code>
*/
public static int getCacheEntryIndexForOffset(int offset, Document document, List<CacheEntry> cache) {
if (offset >= document.getTextLength() && (cache.isEmpty() || cache.get(cache.size() - 1).endOffset < offset)) {
return -(cache.size() + 1);
}
int start = 0;
int end = cache.size() - 1;
// We inline binary search here because profiling indicates that it becomes bottleneck to use Collections.binarySearch().
while (start <= end) {
int i = (end + start) >>> 1;
CacheEntry cacheEntry = cache.get(i);
if (cacheEntry.endOffset < offset) {
start = i + 1;
continue;
}
if (cacheEntry.startOffset > offset) {
end = i - 1;
continue;
}
// There is a possible case that currently found cache entry corresponds to soft-wrapped line and soft wrap occurred
// at target offset. We need to return cache entry for the next visual line then (because document offset shared with
// soft wrap offset is assumed to point to 'after soft wrap' position).
if (offset == cacheEntry.endOffset && i < cache.size() - 1) {
CacheEntry nextLineCacheEntry = cache.get(i + 1);
if (nextLineCacheEntry.startOffset == offset) {
return i + 1;
}
}
return i;
}
return -(start + 1);
}
}