// returns a prefiltered list of elements; you still need to do a
// full-text search on those.
// If it returns null, you have to search all elements
static Cl deepDoubleWordIndex_lookupString(DoubleWordIndex> index, S query, O... _) {
optPar bool debug;
L ranges = index.wordRanges(query);
if (empty(ranges)) null;
int nRanges = l(ranges);
new Map> theMap; // for every snippet, a map of string position to word index
// special case, just a single word in query
if (l(ranges) == 1 && first(ranges).start == 0 && first(ranges).end == l(query)) {
new L out;
for (S fullWord : containingIC(index.index1.words(), query))
for (WithIntArray entry : index.index1.get(fullWord))
out.add(entry!);
ret out;
}
for iWord over ranges: { // go through words in query
IntRange r = ranges.get(iWord);
S word = substring(query, r);
Cl l; // all matching words in index
if (r.start == 0) { // look for ending of word - use reverse index
l = prefixSubSet(index.index2.words(), reversed(word));
if (empty(l)) ret emptyList();
// special loop that accounts for length of actual word
new MultiSetMap positions;
for (S fullWord : l)
for (WithIntArray entry : index.index1.index.get(fullWord))
positions.putAll(entry!, map(i -> i+l(fullWord)-l(word), toList(entry.array)));
for (WithIntArray entry : index.index1.index.get(fullWord)) {
MultiSetMap msm = theMap.get(entry!);
if (msm == null) theMap.put(entry!, msm = new MultiSetMap);
int ofs = l(fullWord)-l(word)-r.start;
for (int i : entry.array)
if (i+ofs >= 0)
msm.put(i+ofs, iWord);
}
continue;
} else if (r.end == l(query)) { // look for start of word
l = lmap reversed(prefixSubSet(index.index1.words(), word));
} else // look for complete word
l = ll(word);
if (empty(l)) ret emptyList();
// merge all positions
new MultiSetMap positions;
for (S fullWord : l)
for (WithIntArray entry : index.index1.index.get(fullWord)) {
MultiSetMap msm = theMap.get(entry!);
if (msm == null) theMap.put(entry!, msm = new MultiSetMap);
for (int i : entry.array)
if (i-r.start >= 0)
msm.put(i-r.start, iWord);
}
}
for i over ranges: {
IntRange range = ranges.get(i);
MultiSetMap positions = multiSetMaps.get(i);
}
new L out;
theLoop: for (A snippet, MultiSetMap msm : theMap) {
for (int position, L wordIndices : msm.data)
if (l(wordIndices) == nRanges) {
out.add(snippet);
continue theLoop;
}
}
ret out;
}