public Tag getPreviousTag(final int pos) { // Note that this method never returns tags for which tag.includInSearch() is false, so separate caching of unregistered tags won't work. if (cache.getSourceLength()==0) return null; if (pos<0 || pos>=cache.getSourceLength()) return null; int index=getIndexOfPos(pos); final CacheEntry cacheEntry=array[index]; final Tag tag; if (cacheEntry.pos==pos && cacheEntry.tag!=null && cacheEntry.tag.includeInSearch()) return cacheEntry.tag; tag=getPreviousTag(getPrevious(cacheEntry),pos,cacheEntry); addPreviousTag(pos,tag); return tag; }
public void addTagAt(final int pos, final Tag tag) { final int index=getIndexOfPos(pos); final CacheEntry nextCacheEntry=array[index]; final CacheEntry previousCacheEntry=getPrevious(nextCacheEntry); add(previousCacheEntry,new CacheEntry(index,pos,tag,pos==previousCacheEntry.pos+1,pos==nextCacheEntry.pos-1),nextCacheEntry); }
private int getIndexOfPos(final int pos) { // return the index of the cacheEntry at pos, or the index where it would be inserted if it does not exist. int minIndex=0; int maxIndex=lastIndex(); // using the following complex calculation instead of a binary search is likely to result in less iterations but is slower overall: // int index=(pos*maxIndex)/cache.getSourceLength(); // approximate first guess at index, assuming even distribution of cache entries int index=maxIndex>>1; while (true) { final CacheEntry cacheEntry=array[index]; if (pos>cacheEntry.pos) { final CacheEntry nextCacheEntry=getNext(cacheEntry); if (pos<=nextCacheEntry.pos) return nextCacheEntry.index; minIndex=nextCacheEntry.index; } else if (pos<cacheEntry.pos) { final CacheEntry previousCacheEntry=getPrevious(cacheEntry); if (pos==previousCacheEntry.pos) return previousCacheEntry.index; if (pos>previousCacheEntry.pos) return index; maxIndex=previousCacheEntry.index; } else { return index; } index=(minIndex+maxIndex)>>1; // using the following complex calculation instead of a binary search is likely to result in less iterations but is slower overall: // final int minIndexPos=array[minIndex].pos; // index=((maxIndex-minIndex-1)*(pos-minIndexPos))/(array[maxIndex].pos-minIndexPos)+minIndex+1; // approximate next guess at index, assuming even distribution of cache entries between min and max entries } }
private Tag getPreviousTag(CacheEntry previousCacheEntry, int pos, CacheEntry nextCacheEntry) { // previousCacheEntry.pos < pos <= nextCacheEntry.pos while (true) { if (!nextCacheEntry.previousCached) { final Tag tag=Tag.getPreviousTagUncached(cache.source,pos,tagType,previousCacheEntry.pos); // if useAllTypesCache is true, automatically adds tag to all caches if one is found, and maybe some unregistered tags along the way. if (tag!=null) { if (!cache.source.useAllTypesCache) addTagAt(tag.begin,tag); // have to add tag manually if useAllTypesCache is false return tag; } } if (previousCacheEntry==bof) return null; if (previousCacheEntry.tag!=null && previousCacheEntry.tag.includeInSearch()) return previousCacheEntry.tag; pos=previousCacheEntry.pos-1; previousCacheEntry=getPrevious(nextCacheEntry=previousCacheEntry); } }
} else if (!getPrevious(stepCacheEntry).nextCached) {
public Tag getNextTag(final int pos) { // Note that this method never returns tags for which tag.includInSearch() is false, so separate caching of unregistered tags won't work. if (cache.getSourceLength()==0) return null; if (pos<0 || pos>=cache.getSourceLength()) return null; int index=getIndexOfPos(pos); final CacheEntry cacheEntry=array[index]; final Tag tag; if (cacheEntry.pos==pos) { if (cacheEntry.tag!=null && cacheEntry.tag.includeInSearch()) return cacheEntry.tag; tag=getNextTag(cacheEntry,pos,getNext(cacheEntry)); } else { tag=getNextTag(getPrevious(cacheEntry),pos,cacheEntry); } addNextTag(pos,tag); return tag; }