Author: desruisseaux
Date: Fri Mar 18 16:08:11 2016
New Revision: 1735631
URL: http://svn.apache.org/viewvc?rev=1735631&view=rev
Log:
Allows HyperRectangleReader to use an existing array of primitive type, not
necessarily data provided by a ReadableByteChannel.
Added:
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/DataTransfer.java
(with props)
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/MemoryDataTransfer.java
(with props)
Modified:
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/ChannelData.java
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/ChannelDataInput.java
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/HyperRectangleReader.java
sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/HyperRectangleReaderTest.java
Modified:
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/ChannelData.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/ChannelData.java?rev=1735631&r1=1735630&r2=1735631&view=diff
==============================================================================
---
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/ChannelData.java
[UTF-8] (original)
+++
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/ChannelData.java
[UTF-8] Fri Mar 18 16:08:11 2016
@@ -222,7 +222,7 @@ public abstract class ChannelData {
final int n = (int) (position - bufferOffset);
final int p = buffer.position() - n;
final int r = buffer.limit() - n;
- flushAndSetPosition(n); // Number of bytes to forget.
+ flushAndSetPosition(n); // Number of bytes
to forget.
buffer.compact().position(p).limit(r);
/*
* Discard trailing obsolete marks. Note that obsolete marks between
valid marks
@@ -242,7 +242,7 @@ public abstract class ChannelData {
}
/**
- * Writes (if applicable) the buffer content up to the given position,
then set the buffer position
+ * Writes (if applicable) the buffer content up to the given position,
then sets the buffer position
* to the given value. The {@linkplain ByteBuffer#limit() buffer limit} is
unchanged, and the buffer
* offset is incremented by the given value.
*/
@@ -327,6 +327,9 @@ public abstract class ChannelData {
@Debug
@Override
public String toString() {
- return getClass().getSimpleName() + "[“" + filename + "” at " +
getStreamPosition() + ']';
+ final StringBuilder b = new
StringBuilder().append(getClass().getSimpleName()).append("[“").append(filename).append('”');
+ // Even if the buffer should not be null, it is useful to keep the
toString() method robust.
+ if (buffer != null) b.append(" at ").append(getStreamPosition());
+ return b.append(']').toString();
}
}
Modified:
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/ChannelDataInput.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/ChannelDataInput.java?rev=1735631&r1=1735630&r2=1735631&view=diff
==============================================================================
---
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/ChannelDataInput.java
[UTF-8] (original)
+++
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/ChannelDataInput.java
[UTF-8] Fri Mar 18 16:08:11 2016
@@ -190,7 +190,7 @@ public class ChannelDataInput extends Ch
/**
* Returns the "end of file" error message, for {@link EOFException}
creations.
*/
- private String eof() {
+ final String eof() {
return Errors.format(Errors.Keys.UnexpectedEndOfFile_1, filename);
}
@@ -519,41 +519,20 @@ public class ChannelDataInput extends Ch
* Helper class for the {@code readFully(…)} methods,
* in order to avoid duplicating almost identical code many times.
*/
- abstract class ArrayReader {
+ abstract class ArrayReader implements DataTransfer {
/**
- * Returns the size of the Java primitive type which is the element of
the array.
- * The size is expressed as the number of bits to shift.
- */
- abstract int dataSizeShift();
-
- /**
- * Returns the data as a {@code char[]}, {@code short[]}, {@code
int[]}, {@code long[]},
- * {@code float[]} or {@code double[]} array. This is either the array
given in argument
- * to the subclass constructor, or the array created by {@link
#createArray(int)}.
- */
- abstract Object dataArray();
-
- /**
- * Creates a destination array of the given length.
- */
- abstract void createDataArray(int length);
-
- /**
- * Sets the destination to the given data array, which may be {@code
null}.
- */
- abstract void setDest(Object array) throws ClassCastException;
-
- /**
- * Returns the view created by the last call to {@link #createView()},
or {@code null} if none.
+ * For subclass constructors only.
*/
- abstract Buffer view();
+ ArrayReader() {
+ }
/**
- * Creates a new buffer of the type required by the array to fill.
- * This method is guaranteed to be invoked exactly once, after the
- * {@link ChannelDataInput#buffer} contains enough data.
+ * Returns the enclosing data input.
*/
- abstract Buffer createView();
+ @Override
+ public final ChannelDataInput input() {
+ return ChannelDataInput.this;
+ }
/**
* Transfers the data from the buffer created by {@link #createView()}
to array
@@ -563,19 +542,6 @@ public class ChannelDataInput extends Ch
abstract void transfer(int offset, int n);
/**
- * For subclass constructors only.
- */
- ArrayReader() {
- }
-
- /**
- * Returns the enclosing data input.
- */
- final ChannelDataInput input() {
- return ChannelDataInput.this;
- }
-
- /**
* Skips the given amount of bytes in the buffer. It is caller
responsibility to ensure
* that there is enough bytes remaining in the buffer.
*/
@@ -584,8 +550,16 @@ public class ChannelDataInput extends Ch
}
/**
- * Reads {@code length} characters from the stream, and stores them
into the array
- * known to subclass, starting at index {@code offset}.
+ * Moves to the given position in the stream.
+ */
+ @Override
+ public final void seek(long n) throws IOException {
+ ChannelDataInput.this.seek(n);
+ }
+
+ /**
+ * Reads {@code length} values from the stream, and stores them into
the array known to subclass,
+ * starting at index {@code offset}.
*
* <p>If a non-null {@code Buffer} is given in argument to this
method, then it must be a view over
* the full content of {@link ChannelDataInput#buffer} (i.e. the view
element at index 0 shall be
@@ -593,10 +567,11 @@ public class ChannelDataInput extends Ch
*
* @param view Existing buffer to use as a view over {@link
ChannelDataInput#buffer}, or {@code null}.
* @param offset The starting position within {@code dest} to write.
- * @param length The number of characters to read.
+ * @param length The number of values to read.
* @throws IOException if an error (including EOF) occurred while
reading the stream.
*/
- void readFully(Buffer view, int offset, int length) throws IOException
{
+ @Override
+ public void readFully(Buffer view, int offset, int length) throws
IOException {
final int dataSizeShift = dataSizeShift();
ensureBufferContains(Math.min(length << dataSizeShift,
buffer.capacity()));
if (view == null) {
@@ -632,17 +607,16 @@ public class ChannelDataInput extends Ch
*/
@SuppressWarnings("ReturnOfCollectionOrArrayField")
final class BytesReader extends ArrayReader {
- /** The array where to store the values. */ private byte[] dest;
- BytesReader(final byte[] dest) {this.dest = dest;}
-
- @Override int dataSizeShift() {return 0;}
- @Override Object dataArray() {return dest;}
- @Override Buffer view() {return buffer;}
- @Override Buffer createView() {return buffer;}
- @Override void createDataArray(int n) {dest = new byte[n];}
- @Override void transfer(int p, int n) {buffer.get(dest, p, n);}
- @Override void setDest(Object array) {dest = (byte[]) array;};
- @Override void readFully(Buffer view, int offset, int length) throws
IOException {
+ /** The array where to store the values. */ private byte[] dest;
+ BytesReader(final byte[] dest) {this.dest = dest;}
+ @Override public int dataSizeShift() {return 0;}
+ @Override public Object dataArray() {return dest;}
+ @Override public Buffer view() {return buffer;}
+ @Override public Buffer createView() {return buffer;}
+ @Override public void createDataArray(int n) {dest = new byte[n];}
+ @Override void transfer(int p, int n) {buffer.get(dest, p,
n);}
+ @Override public void setDest(Object array) {dest = (byte[])
array;};
+ @Override public void readFully(Buffer view, int offset, int length)
throws IOException {
ChannelDataInput.this.readFully(dest, offset, length);
}
};
@@ -652,17 +626,17 @@ public class ChannelDataInput extends Ch
*/
@SuppressWarnings("ReturnOfCollectionOrArrayField")
final class CharsReader extends ArrayReader {
- /** A view over the enclosing byte buffer. */ private CharBuffer view;
- /** The array where to store the values. */ private char[] dest;
- CharsReader(final char[] dest) {this.dest = dest;}
-
- @Override int dataSizeShift() {return 1;}
- @Override Object dataArray() {return dest;}
- @Override Buffer view() {return view;}
- @Override Buffer createView() {return view =
buffer.asCharBuffer();}
- @Override void createDataArray(int n) {dest = new char[n];}
- @Override void transfer(int p, int n) {view.get(dest, p, n);}
- @Override void setDest(Object array) {dest = (char[]) array;};
+ /** A view over the enclosing byte buffer. */ private CharBuffer
view;
+ /** The array where to store the values. */ private char[] dest;
+ CharsReader(final CharBuffer source) {this.view = source;}
+ CharsReader(final char[] dest) {this.dest = dest;}
+ @Override public int dataSizeShift() {return 1;}
+ @Override public Object dataArray() {return dest;}
+ @Override public Buffer view() {return view;}
+ @Override public Buffer createView() {return view =
buffer.asCharBuffer();}
+ @Override public void createDataArray(int n) {dest = new char[n];}
+ @Override void transfer(int p, int n) {view.get(dest, p, n);}
+ @Override public void setDest(Object array) {dest = (char[])
array;};
};
/**
@@ -670,17 +644,17 @@ public class ChannelDataInput extends Ch
*/
@SuppressWarnings("ReturnOfCollectionOrArrayField")
final class ShortsReader extends ArrayReader {
- /** A view over the enclosing byte buffer. */ private ShortBuffer view;
- /** The array where to store the values. */ private short[] dest;
- ShortsReader(final short[] dest) {this.dest = dest;}
-
- @Override int dataSizeShift() {return 1;}
- @Override Object dataArray() {return dest;}
- @Override Buffer view() {return view;}
- @Override Buffer createView() {return view =
buffer.asShortBuffer();}
- @Override void createDataArray(int n) {dest = new short[n];}
- @Override void transfer(int p, int n) {view.get(dest, p, n);}
- @Override void setDest(Object array) {dest = (short[]) array;};
+ /** A view over the enclosing byte buffer. */ private ShortBuffer
view;
+ /** The array where to store the values. */ private short[] dest;
+ ShortsReader(final ShortBuffer source) {this.view = source;}
+ ShortsReader(final short[] dest) {this.dest = dest;}
+ @Override public int dataSizeShift() {return 1;}
+ @Override public Object dataArray() {return dest;}
+ @Override public Buffer view() {return view;}
+ @Override public Buffer createView() {return view =
buffer.asShortBuffer();}
+ @Override public void createDataArray(int n) {dest = new short[n];}
+ @Override void transfer(int p, int n) {view.get(dest, p, n);}
+ @Override public void setDest(Object array) {dest = (short[])
array;};
};
/**
@@ -688,17 +662,17 @@ public class ChannelDataInput extends Ch
*/
@SuppressWarnings("ReturnOfCollectionOrArrayField")
final class IntsReader extends ArrayReader {
- /** A view over the enclosing byte buffer. */ private IntBuffer view;
- /** The array where to store the values. */ private int[] dest;
- IntsReader(final int[] dest) {this.dest = dest;}
-
- @Override int dataSizeShift() {return 2;}
- @Override Object dataArray() {return dest;}
- @Override Buffer view() {return view;}
- @Override Buffer createView() {return view =
buffer.asIntBuffer();}
- @Override void createDataArray(int n) {dest = new int[n];}
- @Override void transfer(int p, int n) {view.get(dest, p, n);}
- @Override void setDest(Object array) {dest = (int[]) array;};
+ /** A view over the enclosing byte buffer. */ private IntBuffer
view;
+ /** The array where to store the values. */ private int[] dest;
+ IntsReader(final IntBuffer source) {this.view = source;}
+ IntsReader(final int[] dest) {this.dest = dest;}
+ @Override public int dataSizeShift() {return 2;}
+ @Override public Object dataArray() {return dest;}
+ @Override public Buffer view() {return view;}
+ @Override public Buffer createView() {return view =
buffer.asIntBuffer();}
+ @Override public void createDataArray(int n) {dest = new int[n];}
+ @Override void transfer(int p, int n) {view.get(dest, p, n);}
+ @Override public void setDest(Object array) {dest = (int[])
array;};
};
/**
@@ -706,17 +680,17 @@ public class ChannelDataInput extends Ch
*/
@SuppressWarnings("ReturnOfCollectionOrArrayField")
final class LongsReader extends ArrayReader {
- /** A view over the enclosing byte buffer. */ private LongBuffer view;
- /** The array where to store the values. */ private long[] dest;
- LongsReader(final long[] dest) {this.dest = dest;}
-
- @Override int dataSizeShift() {return 3;}
- @Override Object dataArray() {return dest;}
- @Override Buffer view() {return view;}
- @Override Buffer createView() {return view =
buffer.asLongBuffer();}
- @Override void createDataArray(int n) {dest = new long[n];}
- @Override void transfer(int p, int n) {view.get(dest, p, n);}
- @Override void setDest(Object array) {dest = (long[]) array;};
+ /** A view over the enclosing byte buffer. */ private LongBuffer
view;
+ /** The array where to store the values. */ private long[] dest;
+ LongsReader(final LongBuffer source) {this.view = source;}
+ LongsReader(final long[] dest) {this.dest = dest;}
+ @Override public int dataSizeShift() {return 3;}
+ @Override public Object dataArray() {return dest;}
+ @Override public Buffer view() {return view;}
+ @Override public Buffer createView() {return view =
buffer.asLongBuffer();}
+ @Override public void createDataArray(int n) {dest = new long[n];}
+ @Override void transfer(int p, int n) {view.get(dest, p, n);}
+ @Override public void setDest(Object array) {dest = (long[])
array;};
};
/**
@@ -724,17 +698,17 @@ public class ChannelDataInput extends Ch
*/
@SuppressWarnings("ReturnOfCollectionOrArrayField")
final class FloatsReader extends ArrayReader {
- /** A view over the enclosing byte buffer. */ private FloatBuffer view;
- /** The array where to store the values. */ private float[] dest;
- FloatsReader(final float[] dest) {this.dest = dest;}
-
- @Override int dataSizeShift() {return 2;}
- @Override Object dataArray() {return dest;}
- @Override Buffer view() {return view;}
- @Override Buffer createView() {return view =
buffer.asFloatBuffer();}
- @Override void createDataArray(int n) {dest = new float[n];}
- @Override void transfer(int p, int n) {view.get(dest, p, n);}
- @Override void setDest(Object array) {dest = (float[]) array;};
+ /** A view over the enclosing byte buffer. */ private FloatBuffer
view;
+ /** The array where to store the values. */ private float[] dest;
+ FloatsReader(final FloatBuffer source) {this.view = source;}
+ FloatsReader(final float[] dest) {this.dest = dest;}
+ @Override public int dataSizeShift() {return 2;}
+ @Override public Object dataArray() {return dest;}
+ @Override public Buffer view() {return view;}
+ @Override public Buffer createView() {return view =
buffer.asFloatBuffer();}
+ @Override public void createDataArray(int n) {dest = new float[n];}
+ @Override void transfer(int p, int n) {view.get(dest, p, n);}
+ @Override public void setDest(Object array) {dest = (float[])
array;};
};
/**
@@ -742,17 +716,17 @@ public class ChannelDataInput extends Ch
*/
@SuppressWarnings("ReturnOfCollectionOrArrayField")
final class DoublesReader extends ArrayReader {
- /** A view over the enclosing byte buffer. */ private DoubleBuffer
view;
- /** The array where to store the values. */ private double[] dest;
- DoublesReader(final double[] dest) {this.dest = dest;}
-
- @Override int dataSizeShift() {return 3;}
- @Override Object dataArray() {return dest;}
- @Override Buffer view() {return view;}
- @Override Buffer createView() {return view =
buffer.asDoubleBuffer();}
- @Override void createDataArray(int n) {dest = new double[n];}
- @Override void transfer(int p, int n) {view.get(dest, p, n);}
- @Override void setDest(Object array) {dest = (double[]) array;};
+ /** A view over the enclosing byte buffer. */ private DoubleBuffer
view;
+ /** The array where to store the values. */ private double[] dest;
+ DoublesReader(final DoubleBuffer source) {this.view = source;}
+ DoublesReader(final double[] dest) {this.dest = dest;}
+ @Override public int dataSizeShift() {return 3;}
+ @Override public Object dataArray() {return dest;}
+ @Override public Buffer view() {return view;}
+ @Override public Buffer createView() {return view =
buffer.asDoubleBuffer();}
+ @Override public void createDataArray(int n) {dest = new double[n];}
+ @Override void transfer(int p, int n) {view.get(dest, p, n);}
+ @Override public void setDest(Object array) {dest = (double[])
array;};
};
/**
Added:
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/DataTransfer.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/DataTransfer.java?rev=1735631&view=auto
==============================================================================
---
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/DataTransfer.java
(added)
+++
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/DataTransfer.java
[UTF-8] Fri Mar 18 16:08:11 2016
@@ -0,0 +1,95 @@
+/*
+ * 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.sis.internal.storage;
+
+import java.io.IOException;
+import java.nio.Buffer;
+
+
+/**
+ * Transfers data from a buffer to an array specified at construction time.
+ * The kind of buffer and the primitive type in the array depend on the
implementation.
+ *
+ * @author Martin Desruisseaux (Geomatys)
+ * @since 0.7
+ * @version 0.7
+ * @module
+ */
+interface DataTransfer {
+ /**
+ * Returns the enclosing data input.
+ */
+ ChannelDataInput input();
+
+ /**
+ * Returns the size of the Java primitive type which is the element of the
array.
+ * The size is expressed as the number of bits to shift.
+ */
+ int dataSizeShift();
+
+ /**
+ * Returns the data as a {@code char[]}, {@code short[]}, {@code int[]},
{@code long[]},
+ * {@code float[]} or {@code double[]} array. This is either the array
given in argument
+ * to the subclass constructor, or the array created by {@link
#createArray(int)}.
+ */
+ Object dataArray();
+
+ /**
+ * Creates a destination array of the given length.
+ */
+ void createDataArray(int length);
+
+ /**
+ * Sets the destination to the given data array, which may be {@code null}.
+ */
+ void setDest(Object array) throws ClassCastException;
+
+ /**
+ * Returns the view created by the last call to {@link #createView()}, or
{@code null} if none.
+ */
+ Buffer view();
+
+ /**
+ * Creates a new buffer of the type required by the array to fill.
+ * This method is guaranteed to be invoked exactly once, after the
+ * {@link ChannelDataInput#buffer} contains enough data.
+ */
+ Buffer createView();
+
+ /**
+ * Moves to the given position in the stream.
+ *
+ * @param position The position where to move.
+ * @throws IOException if the stream can not be moved to the given
position.
+ */
+ void seek(long position) throws IOException;
+
+ /**
+ * Reads {@code length} values from the stream and stores them into the
array known to subclass,
+ * starting at index {@code offset}.
+ *
+ * <p>If a non-null {@code Buffer} is given in argument to this method,
then it must be a view over
+ * the full content of {@link ChannelDataInput#buffer} (i.e. the view
element at index 0 shall be
+ * defined by the buffer elements starting at index 0).</p>
+ *
+ * @param view Existing buffer to use as a view over {@link
ChannelDataInput#buffer}, or {@code null}.
+ * @param offset The starting position within {@code dest} to write.
+ * @param length The number of values to read.
+ * @throws IOException if an error (including EOF) occurred while reading
the stream.
+ */
+ void readFully(Buffer view, int offset, int length) throws IOException;
+}
Propchange:
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/DataTransfer.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/DataTransfer.java
------------------------------------------------------------------------------
svn:mime-type = text/plain;charset=UTF-8
Modified:
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/HyperRectangleReader.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/HyperRectangleReader.java?rev=1735631&r1=1735630&r2=1735631&view=diff
==============================================================================
---
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/HyperRectangleReader.java
[UTF-8] (original)
+++
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/HyperRectangleReader.java
[UTF-8] Fri Mar 18 16:08:11 2016
@@ -39,7 +39,7 @@ public final class HyperRectangleReader
/**
* The channel from which to read the values, together with a buffer for
transferring data.
*/
- private final ChannelDataInput.ArrayReader reader;
+ private final DataTransfer reader;
/**
* The {@link #input} position of the first sample (ignoring sub-area and
sub-sampling).
@@ -58,13 +58,13 @@ public final class HyperRectangleReader
throws DataStoreException
{
switch (dataType) {
- case Numbers.BYTE: reader = input.new BytesReader (null);
break;
- case Numbers.CHARACTER: reader = input.new CharsReader (null);
break;
- case Numbers.SHORT: reader = input.new ShortsReader (null);
break;
- case Numbers.INTEGER: reader = input.new IntsReader (null);
break;
- case Numbers.LONG: reader = input.new LongsReader (null);
break;
- case Numbers.FLOAT: reader = input.new FloatsReader (null);
break;
- case Numbers.DOUBLE: reader = input.new DoublesReader(null);
break;
+ case Numbers.BYTE: reader = input.new BytesReader (
null); break;
+ case Numbers.CHARACTER: reader = input.new CharsReader ((char[])
null); break;
+ case Numbers.SHORT: reader = input.new ShortsReader ((short[])
null); break;
+ case Numbers.INTEGER: reader = input.new IntsReader ((int[])
null); break;
+ case Numbers.LONG: reader = input.new LongsReader ((long[])
null); break;
+ case Numbers.FLOAT: reader = input.new FloatsReader ((float[])
null); break;
+ case Numbers.DOUBLE: reader = input.new
DoublesReader((double[]) null); break;
default: throw new
DataStoreException(Errors.format(Errors.Keys.UnknownType_1, dataType));
}
this.origin = origin;
@@ -80,6 +80,19 @@ public final class HyperRectangleReader
}
/**
+ * Creates a new reader for the data in an existing buffer.
+ * The data will be read from the current buffer position to the buffer
limit.
+ *
+ * @param name The data source name, for information purpose only.
+ * @param data A buffer containing the data to read.
+ * @throws IOException should never happen.
+ */
+ public HyperRectangleReader(final String name, final Buffer data) throws
IOException {
+ reader = new MemoryDataTransfer(name, data).reader();
+ origin = 0;
+ }
+
+ /**
* Returns the data input specified at construction time.
*
* @return The input channel together with the buffer.
@@ -109,10 +122,9 @@ public final class HyperRectangleReader
}
try {
reader.createDataArray(region.targetLength(region.getDimension()));
- final ChannelDataInput input = reader.input();
final Buffer view = reader.view();
loop: do {
- input.seek(streamPosition);
+ reader.seek(streamPosition);
assert reader.view() == view;
reader.readFully(view, arrayPosition, contiguousDataLength);
for (int i=0; i<cursor.length; i++) {
Added:
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/MemoryDataTransfer.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/MemoryDataTransfer.java?rev=1735631&view=auto
==============================================================================
---
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/MemoryDataTransfer.java
(added)
+++
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/MemoryDataTransfer.java
[UTF-8] Fri Mar 18 16:08:11 2016
@@ -0,0 +1,144 @@
+/*
+ * 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.sis.internal.storage;
+
+import java.io.EOFException;
+import java.io.IOException;
+import java.nio.Buffer;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.DoubleBuffer;
+import java.nio.FloatBuffer;
+import java.nio.IntBuffer;
+import java.nio.LongBuffer;
+import java.nio.ShortBuffer;
+import java.nio.channels.ReadableByteChannel;
+import org.apache.sis.util.resources.Errors;
+import org.apache.sis.util.Classes;
+
+
+/**
+ * A {@code DataTransfer} with all data in the given buffer, without channel.
+ *
+ * <div class="note"><b>Implementation note:</b>
+ * This class implements also an empty {@link ReadableByteChannel} as safety.
When using {@link ChannelDataInput}
+ * without channel, only an existing {@code Buffer} pre-filled with the data
should be used. If we have a bug in
+ * our reading process, the empty channel will cause an {@link
java.io.EOFException} to be thrown instead of a
+ * {@link NullPointerException}.</div>
+ *
+ * @author Martin Desruisseaux (Geomatys)
+ * @since 0.7
+ * @version 0.7
+ * @module
+ */
+final class MemoryDataTransfer implements DataTransfer, ReadableByteChannel {
+ /**
+ * The actual {@code DataTransfer} implementation.
+ */
+ private final ChannelDataInput.ArrayReader reader;
+
+ /**
+ * Creates a in-memory data input for the given buffer.
+ */
+ MemoryDataTransfer(final String filename, final Buffer data) throws
IOException {
+ final ChannelDataInput input = new ChannelDataInput(filename, this,
+ (data instanceof ByteBuffer) ? (ByteBuffer) data : null,
true);
+ if (data instanceof ByteBuffer) reader = input.new BytesReader
( null);
+ else if (data instanceof ShortBuffer) reader = input.new ShortsReader
( (ShortBuffer) data);
+ else if (data instanceof IntBuffer) reader = input.new IntsReader
( (IntBuffer) data);
+ else if (data instanceof LongBuffer) reader = input.new LongsReader
( (LongBuffer) data);
+ else if (data instanceof FloatBuffer) reader = input.new FloatsReader
( (FloatBuffer) data);
+ else if (data instanceof DoubleBuffer) reader = input.new
DoublesReader((DoubleBuffer) data);
+ else if (data instanceof CharBuffer) reader = input.new CharsReader
( (CharBuffer) data);
+ else throw new
IllegalArgumentException(Errors.format(Errors.Keys.UnknownType_1,
Classes.getClass(data)));
+ }
+
+ /**
+ * Returns the most efficient {@code DataTransfer} instance to use.
+ */
+ DataTransfer reader() {
+ return (view() instanceof ByteBuffer) ? reader : this;
+ }
+
+ /**
+ * Moves to the given byte position in the buffer.
+ */
+ @Override
+ public void seek(long position) throws IOException {
+ assert input().bufferOffset == 0;
+ if (position < 0) {
+ throw new
IOException(Errors.format(Errors.Keys.NegativeArgument_2, "position",
position));
+ }
+ final int dataSizeShift = dataSizeShift();
+ if ((position & ((1 << dataSizeShift) - 1)) != 0) {
+ throw new
IOException(Errors.format(Errors.Keys.IllegalArgumentValue_2, "position",
position));
+ }
+ position >>>= dataSizeShift;
+ final Buffer data = view();
+ if (position > data.limit()) {
+ throw new EOFException(input().eof());
+ }
+ data.position((int) position);
+ }
+
+ /**
+ * Delegates to the actual implementation.
+ */
+ @Override public ChannelDataInput input() {return
reader.input();}
+ @Override public int dataSizeShift() {return
reader.dataSizeShift();}
+ @Override public Object dataArray() {return
reader.dataArray();}
+ @Override public Buffer view() {return
reader.view();}
+ @Override public Buffer createView() {return
reader.createView();}
+ @Override public void createDataArray(int length)
{reader.createDataArray(length);}
+ @Override public void setDest(Object array)
{reader.setDest(array);}
+
+ /**
+ * Reads {@code length} values from the buffer and stores them into the
array known to subclass,
+ * starting at index {@code offset}.
+ *
+ * @param view Ignored.
+ * @param offset The starting position within {@code dest} to write.
+ * @param length The number of values to read.
+ */
+ @Override
+ public void readFully(final Buffer view, final int offset, final int
length) {
+ reader.transfer(offset, length);
+ }
+
+ /**
+ * Returns -1 since an empty channel has reached the end-of-stream.
+ */
+ @Override
+ public int read(final ByteBuffer dst) {
+ return -1;
+ }
+
+ /**
+ * The channel is always open.
+ */
+ @Override
+ public boolean isOpen() {
+ return true;
+ }
+
+ /**
+ * Does nothing - keep the channel open.
+ */
+ @Override
+ public void close() throws IOException {
+ }
+}
Propchange:
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/MemoryDataTransfer.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/MemoryDataTransfer.java
------------------------------------------------------------------------------
svn:mime-type = text/plain;charset=UTF-8
Modified:
sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/HyperRectangleReaderTest.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/HyperRectangleReaderTest.java?rev=1735631&r1=1735630&r2=1735631&view=diff
==============================================================================
---
sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/HyperRectangleReaderTest.java
[UTF-8] (original)
+++
sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/HyperRectangleReaderTest.java
[UTF-8] Fri Mar 18 16:08:11 2016
@@ -22,6 +22,8 @@ import java.nio.ByteOrder;
import java.nio.ByteBuffer;
import java.nio.ShortBuffer;
import java.io.IOException;
+import java.nio.channels.ReadableByteChannel;
+import java.nio.channels.SeekableByteChannel;
import org.apache.sis.util.Numbers;
import org.apache.sis.storage.DataStoreException;
import org.apache.sis.test.DependsOnMethod;
@@ -83,8 +85,10 @@ public final strictfp class HyperRectang
* Sample values are index values encoded in base 10. For example the
value at index (4,1,2,3) will be 4123.
*
* @param random The random number generator to use for initializing the
test.
+ * @param useChannel {@code true} for fetching the data from channel to a
small buffer,
+ * or {@code false} if the data are expected to be fully contained
in the buffer.
*/
- private void initialize(final Random random) throws IOException,
DataStoreException {
+ private void initialize(final Random random, final boolean useChannel)
throws IOException, DataStoreException {
/*
* Compute a random hyper-rectangle size, sub-region and sub-sampling.
Each dimension will have a
* size between 1 to 10, so we will be able to use decimal digits from
0 to 9 in the sample values.
@@ -118,7 +122,7 @@ public final strictfp class HyperRectang
* Fill the array with short values using the encoding describes in
javadoc.
* Then wrap the array in a pseudo-channel so we can create the reader
to test.
*/
- ShortBuffer view = ByteBuffer.wrap(array, origin,
length*Short.BYTES).order(ByteOrder.nativeOrder()).asShortBuffer();
+ final ShortBuffer view = ByteBuffer.wrap(array, origin,
length*Short.BYTES).order(ByteOrder.nativeOrder()).asShortBuffer();
for (int i3=0; i3<size[3]; i3++) {
for (int i2=0; i2<size[2]; i2++) {
for (int i1=0; i1<size[1]; i1++) {
@@ -129,10 +133,15 @@ public final strictfp class HyperRectang
}
}
assertEquals(length, view.position());
- final ByteArrayChannel channel = new ByteArrayChannel(array, true);
- final ByteBuffer buffer =
ByteBuffer.allocate(random.nextInt(20) + 20).order(ByteOrder.nativeOrder());
- final ChannelDataInput input = new
ChannelDataInput("HyperRectangle", channel, buffer, false);
- reader = new HyperRectangleReader(Numbers.SHORT, input, origin);
+ if (useChannel) {
+ final ByteArrayChannel channel = new ByteArrayChannel(array, true);
+ final ByteBuffer buffer =
ByteBuffer.allocate(random.nextInt(20) + 20).order(ByteOrder.nativeOrder());
+ final ChannelDataInput input = new
ChannelDataInput("HyperRectangle in channel", channel, buffer, false);
+ reader = new HyperRectangleReader(Numbers.SHORT, input, origin);
+ } else {
+ view.clear();
+ reader = new HyperRectangleReader("HyperRectangle in buffer",
view);
+ }
}
/**
@@ -159,6 +168,21 @@ public final strictfp class HyperRectang
}
/**
+ * Asserts that the reader used a channel and has read at least some bytes.
+ *
+ * @param expected {@code true} if the reader should have used a channel,
+ * or {@code false} if it should have used in-memory data instead.
+ */
+ private void assertUsedChannel(final boolean expected) throws IOException {
+ final ChannelDataInput input = reader.input();
+ final ReadableByteChannel channel = input.channel;
+ assertEquals("(channel instanceof InMemoryInput)", !expected, channel
instanceof MemoryDataTransfer);
+ if (expected) {
+ assertTrue(((SeekableByteChannel) channel).position() >
input.channelOffset);
+ }
+ }
+
+ /**
* Tests reading a random part of the hyper-cube without sub-sampling.
*
* @throws IOException should never happen.
@@ -166,9 +190,10 @@ public final strictfp class HyperRectang
*/
@Test
public void testSubRegion() throws IOException, DataStoreException {
- initialize(TestUtilities.createRandomNumberGenerator());
+ initialize(TestUtilities.createRandomNumberGenerator(), true);
Arrays.fill(subsampling, 0, subsampling.length, 1);
verifyRegionRead();
+ assertUsedChannel(true);
}
/**
@@ -179,10 +204,11 @@ public final strictfp class HyperRectang
*/
@Test
public void testSubSampling() throws IOException, DataStoreException {
- initialize(TestUtilities.createRandomNumberGenerator());
+ initialize(TestUtilities.createRandomNumberGenerator(), true);
System.arraycopy(size, 0, upper, 0, size.length);
Arrays.fill(lower, 0, lower.length, 0);
verifyRegionRead();
+ assertUsedChannel(true);
}
/**
@@ -194,7 +220,22 @@ public final strictfp class HyperRectang
@Test
@DependsOnMethod({"testSubRegion", "testSubSampling"})
public void testRandom() throws IOException, DataStoreException {
- initialize(TestUtilities.createRandomNumberGenerator());
+ initialize(TestUtilities.createRandomNumberGenerator(), true);
+ verifyRegionRead();
+ assertUsedChannel(true);
+ }
+
+ /**
+ * Tests reading data in an existing buffer, without channel.
+ *
+ * @throws IOException should never happen.
+ * @throws DataStoreException should never happen.
+ */
+ @Test
+ @DependsOnMethod("testRandom")
+ public void testReadFromBuffer() throws IOException, DataStoreException {
+ initialize(TestUtilities.createRandomNumberGenerator(4), false);
verifyRegionRead();
+ assertUsedChannel(false);
}
}