2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
20 using IndexInput = Mono.Lucene.Net.Store.IndexInput;
22 namespace Mono.Lucene.Net.Index
25 public sealed class SegmentTermPositions:SegmentTermDocs, TermPositions
27 private IndexInput proxStream;
28 private int proxCount;
31 // the current payload length
32 private int payloadLength;
33 // indicates whether the payload of the currend position has
34 // been read from the proxStream yet
35 private bool needToLoadPayload;
37 // these variables are being used to remember information
39 private long lazySkipPointer = - 1;
40 private int lazySkipProxCount = 0;
42 internal SegmentTermPositions(SegmentReader p):base(p)
44 this.proxStream = null; // the proxStream will be cloned lazily when nextPosition() is called for the first time
47 internal override void Seek(TermInfo ti, Term term)
51 lazySkipPointer = ti.proxPointer;
53 lazySkipProxCount = 0;
56 needToLoadPayload = false;
59 public override void Close()
62 if (proxStream != null)
66 public int NextPosition()
68 if (currentFieldOmitTermFreqAndPositions)
69 // This field does not store term freq, positions, payloads
71 // perform lazy skips if neccessary
74 return position += ReadDeltaPosition();
77 private int ReadDeltaPosition()
79 int delta = proxStream.ReadVInt();
80 if (currentFieldStoresPayloads)
82 // if the current field stores payloads then
83 // the position delta is shifted one bit to the left.
84 // if the LSB is set, then we have to read the current
88 payloadLength = proxStream.ReadVInt();
90 delta = SupportClass.Number.URShift(delta, 1);
91 needToLoadPayload = true;
96 protected internal override void SkippingDoc()
98 // we remember to skip a document lazily
99 lazySkipProxCount += freq;
102 public override bool Next()
104 // we remember to skip the remaining positions of the current
106 lazySkipProxCount += proxCount;
111 proxCount = freq; // note frequency
112 position = 0; // reset position
118 public override int Read(int[] docs, int[] freqs)
120 throw new System.NotSupportedException("TermPositions does not support processing multiple documents in one call. Use TermDocs instead.");
124 /// <summary>Called by super.skipTo(). </summary>
125 protected internal override void SkipProx(long proxPointer, int payloadLength)
127 // we save the pointer, we might have to skip there lazily
128 lazySkipPointer = proxPointer;
129 lazySkipProxCount = 0;
131 this.payloadLength = payloadLength;
132 needToLoadPayload = false;
135 private void SkipPositions(int n)
137 System.Diagnostics.Debug.Assert(!currentFieldOmitTermFreqAndPositions);
138 for (int f = n; f > 0; f--)
140 // skip unread positions
146 private void SkipPayload()
148 if (needToLoadPayload && payloadLength > 0)
150 proxStream.Seek(proxStream.GetFilePointer() + payloadLength);
152 needToLoadPayload = false;
155 // It is not always neccessary to move the prox pointer
156 // to a new document after the freq pointer has been moved.
157 // Consider for example a phrase query with two terms:
158 // the freq pointer for term 1 has to move to document x
159 // to answer the question if the term occurs in that document. But
160 // only if term 2 also matches document x, the positions have to be
161 // read to figure out if term 1 and term 2 appear next
162 // to each other in document x and thus satisfy the query.
163 // So we move the prox pointer lazily to the document
164 // as soon as positions are requested.
165 private void LazySkip()
167 if (proxStream == null)
170 proxStream = (IndexInput) parent.core.proxStream.Clone();
173 // we might have to skip the current payload
174 // if it was not read yet
177 if (lazySkipPointer != - 1)
179 proxStream.Seek(lazySkipPointer);
180 lazySkipPointer = - 1;
183 if (lazySkipProxCount != 0)
185 SkipPositions(lazySkipProxCount);
186 lazySkipProxCount = 0;
190 public int GetPayloadLength()
192 return payloadLength;
195 public byte[] GetPayload(byte[] data, int offset)
197 if (!needToLoadPayload)
199 throw new System.IO.IOException("Either no payload exists at this term position or an attempt was made to load it more than once.");
202 // read payloads lazily
205 if (data == null || data.Length - offset < payloadLength)
207 // the array is too small to store the payload data,
208 // so we allocate a new one
209 retArray = new byte[payloadLength];
217 proxStream.ReadBytes(retArray, retOffset, payloadLength);
218 needToLoadPayload = false;
222 public bool IsPayloadAvailable()
224 return needToLoadPayload && payloadLength > 0;