/*
 * 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.
 */
package org.apache.lucene.util.packed;


import static org.apache.lucene.util.packed.PackedInts.checkBlockSize;

import java.io.IOException;
import java.util.Arrays;

import org.apache.lucene.store.DataOutput;

abstract class AbstractBlockPackedWriter {

  static final int MIN_BLOCK_SIZE = 64;
  static final int MAX_BLOCK_SIZE = 1 << (30 - 3);
  static final int MIN_VALUE_EQUALS_0 = 1 << 0;
  static final int BPV_SHIFT = 1;

  // same as DataOutput.writeVLong but accepts negative values
  static void writeVLong(DataOutput out, long i) throws IOException {
    int k = 0;
    while ((i & ~0x7FL) != 0L && k++ < 8) {
      out.writeByte((byte)((i & 0x7FL) | 0x80L));
      i >>>= 7;
    }
    out.writeByte((byte) i);
  }

  protected DataOutput out;
  protected final long[] values;
  protected byte[] blocks;
  protected int off;
  protected long ord;
  protected boolean finished;

  
Sole constructor.
Params:
  • blockSize – the number of values of a single block, must be a multiple of 64
/** * Sole constructor. * @param blockSize the number of values of a single block, must be a multiple of <tt>64</tt> */
public AbstractBlockPackedWriter(DataOutput out, int blockSize) { checkBlockSize(blockSize, MIN_BLOCK_SIZE, MAX_BLOCK_SIZE); reset(out); values = new long[blockSize]; }
Reset this writer to wrap out. The block size remains unchanged.
/** Reset this writer to wrap <code>out</code>. The block size remains unchanged. */
public void reset(DataOutput out) { assert out != null; this.out = out; off = 0; ord = 0L; finished = false; } private void checkNotFinished() { if (finished) { throw new IllegalStateException("Already finished"); } }
Append a new long.
/** Append a new long. */
public void add(long l) throws IOException { checkNotFinished(); if (off == values.length) { flush(); } values[off++] = l; ++ord; } // For testing only void addBlockOfZeros() throws IOException { checkNotFinished(); if (off != 0 && off != values.length) { throw new IllegalStateException("" + off); } if (off == values.length) { flush(); } Arrays.fill(values, 0); off = values.length; ord += values.length; }
Flush all buffered data to disk. This instance is not usable anymore after this method has been called until reset(DataOutput) has been called.
/** Flush all buffered data to disk. This instance is not usable anymore * after this method has been called until {@link #reset(DataOutput)} has * been called. */
public void finish() throws IOException { checkNotFinished(); if (off > 0) { flush(); } finished = true; }
Return the number of values which have been added.
/** Return the number of values which have been added. */
public long ord() { return ord; } protected abstract void flush() throws IOException; protected final void writeValues(int bitsRequired) throws IOException { final PackedInts.Encoder encoder = PackedInts.getEncoder(PackedInts.Format.PACKED, PackedInts.VERSION_CURRENT, bitsRequired); final int iterations = values.length / encoder.byteValueCount(); final int blockSize = encoder.byteBlockCount() * iterations; if (blocks == null || blocks.length < blockSize) { blocks = new byte[blockSize]; } if (off < values.length) { Arrays.fill(values, off, values.length, 0L); } encoder.encode(values, 0, blocks, 0, iterations); final int blockCount = (int) PackedInts.Format.PACKED.byteCount(PackedInts.VERSION_CURRENT, off, bitsRequired); out.writeBytes(blocks, blockCount); } }