| #if FEATURE_BREAKITERATOR |
| using Lucene.Net.Diagnostics; |
| using Lucene.Net.Util; |
| using System.Collections.Generic; |
| using System.Diagnostics; |
| |
| namespace Lucene.Net.Search.PostingsHighlight |
| { |
| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You 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. |
| */ |
| |
| /// <summary> |
| /// Represents a passage (typically a sentence of the document). |
| /// <para/> |
| /// A passage contains <see cref="NumMatches"/> highlights from the query, |
| /// and the offsets and query terms that correspond with each match. |
| /// @lucene.experimental |
| /// </summary> |
| public sealed class Passage |
| { |
| internal int startOffset = -1; |
| internal int endOffset = -1; |
| internal float score = 0.0f; |
| |
| internal int[] matchStarts = new int[8]; |
| internal int[] matchEnds = new int[8]; |
| internal BytesRef[] matchTerms = new BytesRef[8]; |
| internal int numMatches = 0; |
| |
| internal void AddMatch(int startOffset, int endOffset, BytesRef term) |
| { |
| if (Debugging.AssertsEnabled) Debugging.Assert(startOffset >= this.startOffset && startOffset <= this.endOffset); |
| if (numMatches == matchStarts.Length) |
| { |
| int newLength = ArrayUtil.Oversize(numMatches + 1, RamUsageEstimator.NUM_BYTES_OBJECT_REF); |
| int[] newMatchStarts = new int[newLength]; |
| int[] newMatchEnds = new int[newLength]; |
| BytesRef[] newMatchTerms = new BytesRef[newLength]; |
| System.Array.Copy(matchStarts, 0, newMatchStarts, 0, numMatches); |
| System.Array.Copy(matchEnds, 0, newMatchEnds, 0, numMatches); |
| System.Array.Copy(matchTerms, 0, newMatchTerms, 0, numMatches); |
| matchStarts = newMatchStarts; |
| matchEnds = newMatchEnds; |
| matchTerms = newMatchTerms; |
| } |
| if (Debugging.AssertsEnabled) Debugging.Assert(matchStarts.Length == matchEnds.Length && matchEnds.Length == matchTerms.Length); |
| matchStarts[numMatches] = startOffset; |
| matchEnds[numMatches] = endOffset; |
| matchTerms[numMatches] = term; |
| numMatches++; |
| } |
| |
| internal class InPlaceMergeSorterAnonymousHelper : InPlaceMergeSorter |
| { |
| private readonly int[] starts; |
| private readonly int[] ends; |
| private readonly BytesRef[] terms; |
| |
| public InPlaceMergeSorterAnonymousHelper(int[] starts, int[] ends, BytesRef[] terms) |
| { |
| this.starts = starts; |
| this.ends = ends; |
| this.terms = terms; |
| } |
| |
| protected override void Swap(int i, int j) |
| { |
| int temp = starts[i]; |
| starts[i] = starts[j]; |
| starts[j] = temp; |
| |
| temp = ends[i]; |
| ends[i] = ends[j]; |
| ends[j] = temp; |
| |
| BytesRef tempTerm = terms[i]; |
| terms[i] = terms[j]; |
| terms[j] = tempTerm; |
| } |
| |
| protected override int Compare(int i, int j) |
| { |
| return starts[i].CompareTo(starts[j]); |
| } |
| } |
| |
| internal void Sort() |
| { |
| int[] starts = matchStarts; |
| int[] ends = matchEnds; |
| BytesRef[] terms = matchTerms; |
| new InPlaceMergeSorterAnonymousHelper(starts, ends, terms) |
| .Sort(0, numMatches); |
| } |
| |
| internal void Reset() |
| { |
| startOffset = endOffset = -1; |
| score = 0.0f; |
| numMatches = 0; |
| } |
| |
| /// <summary> |
| /// Gets the start index (inclusive) of the passage in the |
| /// original content: always >= 0. |
| /// </summary> |
| public int StartOffset => startOffset; |
| |
| /// <summary> |
| /// Gets the end index (exclusive) of the passage in the |
| /// original content: always >= <see cref="StartOffset"/> |
| /// </summary> |
| public int EndOffset => endOffset; |
| |
| /// <summary> |
| /// Passage's score. |
| /// </summary> |
| public float Score => score; |
| |
| /// <summary> |
| /// Number of term matches available in |
| /// <see cref="MatchStarts"/>, <see cref="MatchEnds"/>, |
| /// <see cref="MatchTerms"/> |
| /// </summary> |
| public int NumMatches => numMatches; |
| |
| /// <summary> |
| /// Start offsets of the term matches, in increasing order. |
| /// <para/> |
| /// Only <see cref="NumMatches"/> are valid. Note that these |
| /// offsets are absolute (not relative to <see cref="StartOffset"/>). |
| /// </summary> |
| /// <returns></returns> |
| public IReadOnlyList<int> MatchStarts => matchStarts; |
| |
| /// <summary> |
| /// End offsets of the term matches, corresponding with <see cref="MatchStarts"/>. |
| /// <para/> |
| /// Only <see cref="NumMatches"/> are valid. Note that its possible that an end offset |
| /// could exceed beyond the bounds of the passage <see cref="EndOffset"/>, if the |
| /// <see cref="Analysis.Analyzer"/> produced a term which spans a passage boundary. |
| /// </summary> |
| public IReadOnlyList<int> MatchEnds => matchEnds; |
| |
| /// <summary> |
| /// BytesRef (term text) of the matches, corresponding with <see cref="MatchStarts"/>. |
| /// <para/> |
| /// Only <see cref="NumMatches"/> are valid. |
| /// </summary> |
| public IReadOnlyList<BytesRef> MatchTerms => matchTerms; |
| } |
| } |
| #endif |