--- /dev/null
+package org.apache.lucene.index;
+
+/**
+ * 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.
+ */
+
+import java.io.IOException;
+import org.apache.lucene.store.IndexInput;
+
+final class SegmentTermEnum extends TermEnum implements Cloneable {
+ private IndexInput input;
+ FieldInfos fieldInfos;
+ long size;
+ long position = -1;
+ private boolean first = true;
+
+ private TermBuffer termBuffer = new TermBuffer();
+ private TermBuffer prevBuffer = new TermBuffer();
+ private TermBuffer scanBuffer = new TermBuffer(); // used for scanning
+
+ private TermInfo termInfo = new TermInfo();
+
+ private int format;
+ private boolean isIndex = false;
+ long indexPointer = 0;
+ int indexInterval;
+ int skipInterval;
+ int maxSkipLevels;
+ private int formatM1SkipInterval;
+
+ SegmentTermEnum(IndexInput i, FieldInfos fis, boolean isi)
+ throws CorruptIndexException, IOException {
+ input = i;
+ fieldInfos = fis;
+ isIndex = isi;
+ maxSkipLevels = 1; // use single-level skip lists for formats > -3
+
+ int firstInt = input.readInt();
+ if (firstInt >= 0) {
+ // original-format file, without explicit format version number
+ format = 0;
+ size = firstInt;
+
+ // back-compatible settings
+ indexInterval = 128;
+ skipInterval = Integer.MAX_VALUE; // switch off skipTo optimization
+ } else {
+ // we have a format version number
+ format = firstInt;
+
+ // check that it is a format we can understand
+ if (format < TermInfosWriter.FORMAT_CURRENT)
+ throw new IndexFormatTooNewException(input, format, -1, TermInfosWriter.FORMAT_CURRENT);
+
+ size = input.readLong(); // read the size
+
+ if(format == -1){
+ if (!isIndex) {
+ indexInterval = input.readInt();
+ formatM1SkipInterval = input.readInt();
+ }
+ // switch off skipTo optimization for file format prior to 1.4rc2 in order to avoid a bug in
+ // skipTo implementation of these versions
+ skipInterval = Integer.MAX_VALUE;
+ } else {
+ indexInterval = input.readInt();
+ skipInterval = input.readInt();
+ if (format <= TermInfosWriter.FORMAT) {
+ // this new format introduces multi-level skipping
+ maxSkipLevels = input.readInt();
+ }
+ }
+ assert indexInterval > 0: "indexInterval=" + indexInterval + " is negative; must be > 0";
+ assert skipInterval > 0: "skipInterval=" + skipInterval + " is negative; must be > 0";
+ }
+ if (format > TermInfosWriter.FORMAT_VERSION_UTF8_LENGTH_IN_BYTES) {
+ termBuffer.setPreUTF8Strings();
+ scanBuffer.setPreUTF8Strings();
+ prevBuffer.setPreUTF8Strings();
+ }
+ }
+
+ @Override
+ protected Object clone() {
+ SegmentTermEnum clone = null;
+ try {
+ clone = (SegmentTermEnum) super.clone();
+ } catch (CloneNotSupportedException e) {}
+
+ clone.input = (IndexInput) input.clone();
+ clone.termInfo = new TermInfo(termInfo);
+
+ clone.termBuffer = (TermBuffer)termBuffer.clone();
+ clone.prevBuffer = (TermBuffer)prevBuffer.clone();
+ clone.scanBuffer = new TermBuffer();
+
+ return clone;
+ }
+
+ final void seek(long pointer, long p, Term t, TermInfo ti)
+ throws IOException {
+ input.seek(pointer);
+ position = p;
+ termBuffer.set(t);
+ prevBuffer.reset();
+ termInfo.set(ti);
+ first = p == -1;
+ }
+
+ /** Increments the enumeration to the next element. True if one exists.*/
+ @Override
+ public final boolean next() throws IOException {
+ if (position++ >= size - 1) {
+ prevBuffer.set(termBuffer);
+ termBuffer.reset();
+ return false;
+ }
+
+ prevBuffer.set(termBuffer);
+ termBuffer.read(input, fieldInfos);
+
+ termInfo.docFreq = input.readVInt(); // read doc freq
+ termInfo.freqPointer += input.readVLong(); // read freq pointer
+ termInfo.proxPointer += input.readVLong(); // read prox pointer
+
+ if(format == -1){
+ // just read skipOffset in order to increment file pointer;
+ // value is never used since skipTo is switched off
+ if (!isIndex) {
+ if (termInfo.docFreq > formatM1SkipInterval) {
+ termInfo.skipOffset = input.readVInt();
+ }
+ }
+ }
+ else{
+ if (termInfo.docFreq >= skipInterval)
+ termInfo.skipOffset = input.readVInt();
+ }
+
+ if (isIndex)
+ indexPointer += input.readVLong(); // read index pointer
+
+ return true;
+ }
+
+ /* Optimized scan, without allocating new terms.
+ * Return number of invocations to next().
+ *
+ * NOTE: LUCENE-3183: if you pass Term("", "") here then this
+ * will incorrectly return before positioning the enum,
+ * and position will be -1; caller must detect this. */
+ final int scanTo(Term term) throws IOException {
+ scanBuffer.set(term);
+ int count = 0;
+ if (first) {
+ // Always force initial next() in case term is Term("", "")
+ next();
+ first = false;
+ count++;
+ }
+ while (scanBuffer.compareTo(termBuffer) > 0 && next()) {
+ count++;
+ }
+ return count;
+ }
+
+ /** Returns the current Term in the enumeration.
+ Initially invalid, valid after next() called for the first time.*/
+ @Override
+ public final Term term() {
+ return termBuffer.toTerm();
+ }
+
+ /** Returns the previous Term enumerated. Initially null.*/
+ final Term prev() {
+ return prevBuffer.toTerm();
+ }
+
+ /** Returns the current TermInfo in the enumeration.
+ Initially invalid, valid after next() called for the first time.*/
+ final TermInfo termInfo() {
+ return new TermInfo(termInfo);
+ }
+
+ /** Sets the argument to the current TermInfo in the enumeration.
+ Initially invalid, valid after next() called for the first time.*/
+ final void termInfo(TermInfo ti) {
+ ti.set(termInfo);
+ }
+
+ /** Returns the docFreq from the current TermInfo in the enumeration.
+ Initially invalid, valid after next() called for the first time.*/
+ @Override
+ public final int docFreq() {
+ return termInfo.docFreq;
+ }
+
+ /* Returns the freqPointer from the current TermInfo in the enumeration.
+ Initially invalid, valid after next() called for the first time.*/
+ final long freqPointer() {
+ return termInfo.freqPointer;
+ }
+
+ /* Returns the proxPointer from the current TermInfo in the enumeration.
+ Initially invalid, valid after next() called for the first time.*/
+ final long proxPointer() {
+ return termInfo.proxPointer;
+ }
+
+ /** Closes the enumeration to further activity, freeing resources. */
+ @Override
+ public final void close() throws IOException {
+ input.close();
+ }
+}