You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sis.apache.org by de...@apache.org on 2022/07/08 13:07:46 UTC
[sis] 01/02: Switch the position of offset and length in `entriesForCodes` bit patterns. It makes easier the use of compressed offset in next commit.
This is an automated email from the ASF dual-hosted git repository.
desruisseaux pushed a commit to branch geoapi-4.0
in repository https://gitbox.apache.org/repos/asf/sis.git
commit 69f581c4ae2cd225207d9a575e2f0b0facd9b552
Author: Martin Desruisseaux <ma...@geomatys.com>
AuthorDate: Fri Jul 8 00:06:40 2022 +0200
Switch the position of offset and length in `entriesForCodes` bit patterns.
It makes easier the use of compressed offset in next commit.
---
.../apache/sis/internal/storage/inflater/LZW.java | 40 ++++++++++++----------
1 file changed, 22 insertions(+), 18 deletions(-)
diff --git a/storage/sis-geotiff/src/main/java/org/apache/sis/internal/storage/inflater/LZW.java b/storage/sis-geotiff/src/main/java/org/apache/sis/internal/storage/inflater/LZW.java
index bdff8a2024..a1b37f7e01 100644
--- a/storage/sis-geotiff/src/main/java/org/apache/sis/internal/storage/inflater/LZW.java
+++ b/storage/sis-geotiff/src/main/java/org/apache/sis/internal/storage/inflater/LZW.java
@@ -80,16 +80,21 @@ final class LZW extends CompressionChannel {
private int codeSize;
/**
- * Position of the lowest bit in an {@link #entriesForCodes} element where the length is stored.
- * The length is extracted from an element by {@code element >>> LOWEST_LENGTH_BIT}.
- * The offset is chosen for allowing {@value #MAX_CODE_SIZE} bits for storing the length.
+ * Position of the lowest bit in an {@link #entriesForCodes} element where the offset is stored.
+ * The position is chosen for leaving {@value #MAX_CODE_SIZE} bits for storing the length before
+ * the offset value.
*
* <div class="note"><b>Rational:</b>
* even in the worst case scenario where the same byte is always appended to the sequence,
* the maximal length can not exceeded the dictionary size because a {@link #CLEAR_CODE}
* will be emitted when the dictionary is full.</div>
*/
- private static final int LOWEST_LENGTH_BIT = Integer.SIZE - MAX_CODE_SIZE;
+ private static final int LOWEST_OFFSET_BIT = MAX_CODE_SIZE;
+
+ /**
+ * The mask to apply on an {@link #entriesForCodes} element for getting the length.
+ */
+ private static final int LENGTH_MASK = (1 << LOWEST_OFFSET_BIT) - 1;
/**
* Extracts the number of bytes of an entry stored in the {@link #stringsFromCode} array.
@@ -98,15 +103,9 @@ final class LZW extends CompressionChannel {
* @return number of consecutive bytes to read in {@link #stringsFromCode} array.
*/
private static int length(final int element) {
- return element >>> LOWEST_LENGTH_BIT;
+ return element & LENGTH_MASK;
}
- /**
- * The mask to apply on an {@link #entriesForCodes} element for getting the offset.
- * The actual offset is {@code (element & OFFSET_MASK)}.
- */
- private static final int OFFSET_MASK = (1 << LOWEST_LENGTH_BIT) - 1;
-
/**
* Extracts the index of the first byte of an entry stored in the {@link #stringsFromCode} array.
*
@@ -114,19 +113,24 @@ final class LZW extends CompressionChannel {
* @return index of the first byte to read in {@link #stringsFromCode} array.
*/
private static int offset(final int element) {
- return element & OFFSET_MASK;
+ return element >>> LOWEST_OFFSET_BIT;
}
/**
* Encodes an offset together with its length.
*/
private static int offsetAndLength(final int offset, final int length) {
- final int element = offset | (length << LOWEST_LENGTH_BIT);
+ final int element = (offset << LOWEST_OFFSET_BIT) | length;
assert offset(element) == offset : offset;
assert length(element) == length : length;
return element;
}
+ /**
+ * Maximal value + 1 that the offset can take. The offset takes all the bits after the length.
+ */
+ private static final int OFFSET_LIMIT = 1 << (Integer.SIZE - LOWEST_OFFSET_BIT);
+
/**
* Pointers to byte sequences for a code in the {@link #entriesForCodes} array.
* Each element is a value encoded by {@link #offsetAndLength(int, int)} method.
@@ -181,9 +185,9 @@ final class LZW extends CompressionChannel {
super(input);
indexOfFreeEntry = FIRST_ADAPTATIVE_CODE;
entriesForCodes = new int [(1 << MAX_CODE_SIZE) - OFFSET_TO_MAXIMUM];
- stringsFromCode = new byte[4 << MAX_CODE_SIZE]; // Dynamically expanded if needed.
+ stringsFromCode = new byte[32 * 1024]; // Dynamically expanded if needed.
for (int i=0; i < (1 << Byte.SIZE); i++) {
- entriesForCodes[i] = i | (1 << LOWEST_LENGTH_BIT);
+ entriesForCodes[i] = (i << LOWEST_OFFSET_BIT) | 1;
stringsFromCode[i] = (byte) i;
}
}
@@ -230,8 +234,8 @@ final class LZW extends CompressionChannel {
*/
if (pendingEntry != 0) {
final int remaining = target.remaining();
- final int stringOffset = pendingEntry & OFFSET_MASK;
- final int stringLength = pendingEntry >>> LOWEST_LENGTH_BIT;
+ final int stringOffset = offset(pendingEntry);
+ final int stringLength = length(pendingEntry);
target.put(stringsFromCode, stringOffset, Math.min(stringLength, remaining));
if (stringLength <= remaining) {
pendingEntry = 0;
@@ -301,7 +305,7 @@ final class LZW extends CompressionChannel {
final int newLength = stringLength + 1;
final int lastNewByte = newOffset + stringLength;
if (lastNewByte >= stringsFromCode.length) {
- final int capacity = Math.min(indexOfFreeString * 2, OFFSET_MASK + 1);
+ final int capacity = Math.min(indexOfFreeString * 2, OFFSET_LIMIT);
if (lastNewByte >= capacity) {
throw new IOException("Dictionary overflow");
}