content: 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;
  import org.apache.lucene.store.RAMDirectory;
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  
  import com.esotericsoftware.minlog.Log;
  
  final class SegmentTermEnum extends TermEnum implements Cloneable {
  	  public static Logger LOG = LoggerFactory.getLogger(SegmentTermEnum.class);
  
    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;
    public int DEFAULT_OLD_SKIP_INTERVAL=Integer.MAX_VALUE-99999;
    private int formatM1SkipInterval;
    
  
    SegmentTermEnum(IndexInput i, FieldInfos fis, boolean isi,long outsize)
            throws CorruptIndexException, IOException {
      input = i;
      fieldInfos = fis;
      isIndex = isi;
      maxSkipLevels = 1; // use single-level skip lists for formats > -3 
      int formattp=0;
  
      int firstInt = input.readInt();
      if (firstInt >= 0) {
      	formattp=1;
        // original-format file, without explicit format version number
        format = 0;
        size = firstInt;
        if(outsize>=0)
        {
      	  size=outsize; 
        }
  
        // back-compatible settings
        indexInterval = 128;
        skipInterval = DEFAULT_OLD_SKIP_INTERVAL; // switch off skipTo optimization
      } else {
      	formattp=2;
        // 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(outsize>=0)
        {
      	  size=outsize; 
        }
        
        if(format == -1){
          if (!isIndex) {
            indexInterval = input.readInt();
            formatM1SkipInterval = input.readInt();
          }
          formattp=3;
          // switch off skipTo optimization for file format prior to 1.4rc2 in order to avoid a bug in 
          // skipTo implementation of these versions
          skipInterval = DEFAULT_OLD_SKIP_INTERVAL;
        } else {
      	  formattp=4;
          indexInterval = input.readInt();
          skipInterval = input.readInt();
          if (format <= TermInfosWriter.FORMAT) {
            // this new format introduces multi-level skipping
            maxSkipLevels = input.readInt();
          }
        }
  //      Log.info("indexInterval:"+indexInterval+",skipInterval:"+skipInterval+",formattp:"+formattp);
        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();
    }
  }
  