Index: lucene/core/src/test/org/apache/lucene/util/packed/TestPackedInts.java
===================================================================
--- lucene/core/src/test/org/apache/lucene/util/packed/TestPackedInts.java	(révision 1424827)
+++ lucene/core/src/test/org/apache/lucene/util/packed/TestPackedInts.java	(copie de travail)
@@ -830,4 +830,57 @@
     dir.close();
   }
 
+  public void testPackedBlockReaderWriter() throws IOException {
+    final int blockSize = 1 << _TestUtil.nextInt(random(), 6, 18);
+    final int valueCount = random().nextInt(1 << 20);
+    final long[] values = new long[valueCount];
+    long minValue = 0;
+    int bpv = 0;
+    for (int i = 0; i < valueCount; ++i) {
+      if (i % blockSize == 0) {
+        minValue = rarely() ? random().nextInt(128) : _TestUtil.nextLong(random(), 0, Long.MAX_VALUE - 1);
+        bpv = random().nextInt(PackedInts.bitsRequired(Long.MAX_VALUE - minValue));
+      }
+      if (bpv == 0) {
+        values[i] = minValue;
+      } else {
+        values[i] = minValue + _TestUtil.nextLong(random(), 0, (1L << bpv) - 1);
+      }
+    }
+
+    final Directory dir = newDirectory();
+    final IndexOutput out = dir.createOutput("out.bin", IOContext.DEFAULT);
+    final BlockPackedWriter writer = new BlockPackedWriter(out, blockSize);
+    for (long value : values) {
+      writer.add(value);
+    }
+    writer.finish();
+    final long fp = out.getFilePointer();
+    out.close();
+
+    final IndexInput in = dir.openInput("out.bin", IOContext.DEFAULT);
+    final BlockPackedReader reader = new BlockPackedReader(in, PackedInts.VERSION_CURRENT, blockSize, valueCount);
+    for (int i = 0; i < valueCount; ) {
+      if (random().nextBoolean()) {
+        assertEquals("" + i, values[i], reader.next());
+        ++i;
+      } else {
+        final LongsRef nextValues = reader.next(_TestUtil.nextInt(random(), 1, 1024));
+        for (int j = 0; j < nextValues.length; ++j) {
+          assertEquals("" + (i + j), values[i + j], nextValues.longs[nextValues.offset + j]);
+        }
+        i += nextValues.length;
+      }
+    }
+    assertEquals(fp, in.getFilePointer());
+    try {
+      reader.next();
+      assertTrue(false);
+    } catch (IOException e) {
+      // OK
+    }
+    in.close();
+    dir.close();
+  }
+
 }
Index: lucene/core/src/java/org/apache/lucene/util/packed/BlockPackedReader.java
===================================================================
--- lucene/core/src/java/org/apache/lucene/util/packed/BlockPackedReader.java	(révision 0)
+++ lucene/core/src/java/org/apache/lucene/util/packed/BlockPackedReader.java	(copie de travail)
@@ -0,0 +1,124 @@
+package org.apache.lucene.util.packed;
+
+/*
+ * 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 static org.apache.lucene.util.packed.BlockPackedWriter.BPV_SHIFT;
+import static org.apache.lucene.util.packed.BlockPackedWriter.MIN_VALUE_EQUALS_0;
+import static org.apache.lucene.util.packed.BlockPackedWriter.checkBlockSize;
+
+import java.io.EOFException;
+import java.io.IOException;
+import java.util.Arrays;
+
+import org.apache.lucene.store.DataInput;
+import org.apache.lucene.util.LongsRef;
+
+/**
+ * Reader for sequences of positive longs written with {@link BlockPackedWriter}.
+ * @see BlockPackedWriter
+ * @lucene.internal
+ */
+public final class BlockPackedReader {
+
+  final DataInput in;
+  final int packedIntsVersion;
+  final long valueCount;
+  final LongsRef values;
+  byte[] blocks;
+  int off;
+  long ord;
+
+  /** Sole constructor.
+   * @param blockSize the number of values of a block, must be equal to the
+   *                  block size of the {@link BlockPackedWriter} which has
+   *                  been used to write the stream
+   */
+  public BlockPackedReader(DataInput in, int packedIntsVersion, int blockSize, long valueCount) {
+    checkBlockSize(blockSize);
+    this.in = in;
+    this.packedIntsVersion = packedIntsVersion;
+    this.values = new LongsRef(blockSize);
+    assert valueCount >= 0;
+    this.valueCount = valueCount;
+    off = values.longs.length;
+    ord = 0;
+  }
+
+  /** Read the next value. */
+  public long next() throws IOException {
+    next(1);
+    assert values.length == 1;
+    return values.longs[values.offset];
+  }
+
+  /** Read between <tt>1</tt> and <code>count</code> values. */
+  public LongsRef next(int count) throws IOException {
+    assert count > 0;
+    if (ord == valueCount) {
+      throw new EOFException();
+    }
+    if (off == values.longs.length) {
+      refill();
+    }
+
+    count = Math.min(count, values.longs.length - off);
+    count = (int) Math.min(count, valueCount - ord);
+
+    values.offset = off;
+    values.length = count;
+    off += count;
+    ord += count;
+    return values;
+  }
+
+  private void refill() throws IOException {
+    final int token = in.readByte() & 0xFF;
+    final boolean minEquals0 = (token & MIN_VALUE_EQUALS_0) != 0;
+    final int bitsPerValue = token >>> BPV_SHIFT;
+    if (bitsPerValue >= 64) {
+      throw new IOException("Corrupted");
+    }
+    final long minValue = minEquals0 ? 0L : 1L + in.readVLong();
+    assert minEquals0 || minValue != 0;
+
+    if (bitsPerValue == 0) {
+      Arrays.fill(values.longs, minValue);
+    } else {
+      final PackedInts.Decoder decoder = PackedInts.getDecoder(PackedInts.Format.PACKED, packedIntsVersion, bitsPerValue);
+      final int iterations = values.longs.length / decoder.valueCount();
+      final int blocksSize = iterations * 8 * decoder.blockCount();
+      if (blocks == null || blocks.length < blocksSize) {
+        blocks = new byte[blocksSize];
+      }
+
+      final int valueCount = (int) Math.min(this.valueCount - ord, values.longs.length);
+      final int blocksCount = (int) PackedInts.Format.PACKED.byteCount(packedIntsVersion, valueCount, bitsPerValue);
+      in.readBytes(blocks, 0, blocksCount);
+
+      decoder.decode(blocks, 0, values.longs, 0, iterations);
+
+      if (minValue != 0) {
+        for (int i = 0; i < valueCount; ++i) {
+          values.longs[i] += minValue;
+        }
+      }
+    }
+    off = 0;
+  }
+
+}

Modification de propriétés sur lucene/core/src/java/org/apache/lucene/util/packed/BlockPackedReader.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: lucene/core/src/java/org/apache/lucene/util/packed/BlockPackedWriter.java
===================================================================
--- lucene/core/src/java/org/apache/lucene/util/packed/BlockPackedWriter.java	(révision 0)
+++ lucene/core/src/java/org/apache/lucene/util/packed/BlockPackedWriter.java	(copie de travail)
@@ -0,0 +1,140 @@
+package org.apache.lucene.util.packed;
+
+/*
+ * 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 java.util.Arrays;
+
+import org.apache.lucene.store.DataOutput;
+
+/**
+ * A writer for large sequences of positive longs.
+ * <p>
+ * The sequence is divided into fixed-size blocks and for each block, the
+ * difference between each value and the minimum value of the block is encoded
+ * using as few bits as possible. Memory usage of this class is proportional to
+ * the block size. Each block has an overhead between 1 and 10 bytes to store
+ * the minimum value and the number of bits per value of the block.
+ * @see BlockPackedReader
+ * @lucene.internal
+ */
+public final class BlockPackedWriter {
+
+  static final int MAX_BLOCK_SIZE = 1 << (30 - 3);
+  static final int MIN_VALUE_EQUALS_0 = 1 << 0;
+  static final int BPV_SHIFT = 1;
+
+  static void checkBlockSize(int blockSize) {
+    if (blockSize <= 0 || blockSize > MAX_BLOCK_SIZE) {
+      throw new IllegalArgumentException("blockSize must be > 0 and < " + MAX_BLOCK_SIZE + ", got " + blockSize);
+    }
+    if (blockSize % 64 != 0) {
+      throw new IllegalArgumentException("blockSize must be a multiple of 64, got " + blockSize);
+    }
+  }
+
+  final DataOutput out;
+  final long[] values;
+  byte[] blocks;
+  int off;
+  boolean finished;
+
+  /**
+   * Sole constructor.
+   * @param blockSize the number of values of a single block, must be a multiple of <tt>64</tt>
+   */
+  public BlockPackedWriter(DataOutput out, int blockSize) {
+    checkBlockSize(blockSize);
+    this.out = out;
+    values = new long[blockSize];
+    off = 0;
+    finished = false;
+  }
+
+  private void checkNotFinished() {
+    if (finished) {
+      throw new IllegalStateException("Already finished");
+    }
+  }
+
+  /** Append a new long. */
+  public void add(long l) throws IOException {
+    assert l >= 0;
+    checkNotFinished();
+    if (off == values.length) {
+      flush();
+    }
+    values[off++] = l;
+  }
+
+  /** This method will flush all buffered data to disk. This instance is not
+   *  usable anymore after this method has been called. */
+  public void finish() throws IOException {
+    checkNotFinished();
+    if (off > 0) {
+      flush();
+    }
+    finished = true;
+  }
+
+  private void flush() throws IOException {
+    assert off > 0;
+    long min = Long.MAX_VALUE, max = 0;
+    for (int i = 0; i < off; ++i) {
+      min = Math.min(values[i], min);
+      max = Math.max(values[i], max);
+    }
+
+    final long delta = max - min;
+    assert delta >= 0;
+    final int bitsRequired = delta == 0L ? 0 : PackedInts.bitsRequired(delta);
+    if (min > 0 && bitsRequired == PackedInts.bitsRequired(max)) {
+      min = 0;
+    }
+
+    final int token = (bitsRequired << BPV_SHIFT) | (min == 0 ? MIN_VALUE_EQUALS_0 : 0);
+    out.writeByte((byte) token);
+
+    if (min != 0) {
+      out.writeVLong(min - 1);
+    }
+
+    if (bitsRequired > 0) {
+      if (min != 0) {
+        for (int i = 0; i < off; ++i) {
+          values[i] -= min;
+        }
+      }
+      final PackedInts.Encoder encoder = PackedInts.getEncoder(PackedInts.Format.PACKED, PackedInts.VERSION_CURRENT, bitsRequired);
+      final int iterations = values.length / encoder.valueCount();
+      final int blockSize = encoder.blockCount() * 8 * 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);
+    }
+
+    off = 0;
+  }
+
+}

Modification de propriétés sur lucene/core/src/java/org/apache/lucene/util/packed/BlockPackedWriter.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
