9
9
* %%
10
10
* Redistribution and use in source and binary forms, with or without
11
11
* modification, are permitted provided that the following conditions are met:
12
- *
12
+ *
13
13
* 1. Redistributions of source code must retain the above copyright notice,
14
14
* this list of conditions and the following disclaimer.
15
15
* 2. Redistributions in binary form must reproduce the above copyright notice,
16
16
* this list of conditions and the following disclaimer in the documentation
17
17
* and/or other materials provided with the distribution.
18
- *
18
+ *
19
19
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
20
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
21
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
48
48
/**
49
49
* A <em>data handle</em> is a plugin which provides both streaming and random
50
50
* access to bytes at a {@link Location} (e.g., files or arrays).
51
- *
51
+ *
52
52
* @author Curtis Rueden
53
53
* @see DataHandleInputStream
54
54
* @see DataHandleOutputStream
@@ -58,7 +58,7 @@ public interface DataHandle<L extends Location> extends WrapperPlugin<L>,
58
58
{
59
59
60
60
public enum ByteOrder {
61
- LITTLE_ENDIAN , BIG_ENDIAN
61
+ LITTLE_ENDIAN , BIG_ENDIAN
62
62
}
63
63
64
64
/** Default block size to use when searching through the stream. */
@@ -75,15 +75,15 @@ public enum ByteOrder {
75
75
76
76
/**
77
77
* Tests whether this handle's location actually exists at the source.
78
- *
78
+ *
79
79
* @return True if the location exists; false if not.
80
80
* @throws IOException If something goes wrong with the existence check.
81
81
*/
82
82
boolean exists () throws IOException ;
83
83
84
84
/**
85
85
* Gets the last modified timestamp of the location.
86
- *
86
+ *
87
87
* @return The last modified timestamp, or null if the handle does not support
88
88
* this feature or if the location does not exist.
89
89
* @throws IOException If something goes wrong with the last modified check.
@@ -107,7 +107,7 @@ default Date lastModified() throws IOException {
107
107
* the checksum is still the same, the contents are highly likely to be
108
108
* unchanged.
109
109
* </p>
110
- *
110
+ *
111
111
* @return The checksum, or null if the handle does not support this feature.
112
112
* @throws IOException If something goes wrong when accessing the checksum.
113
113
*/
@@ -126,22 +126,22 @@ default String checksum() throws IOException {
126
126
127
127
/**
128
128
* Returns the length of the data in bytes.
129
- *
129
+ *
130
130
* @return The length, or -1 if the length is unknown.
131
131
*/
132
132
long length () throws IOException ;
133
133
134
134
/**
135
135
* Sets the new length of the handle.
136
- *
136
+ *
137
137
* @param length New length.
138
138
* @throws IOException If there is an error changing the handle's length.
139
139
*/
140
140
void setLength (long length ) throws IOException ;
141
141
142
142
/**
143
- * Gets the number of bytes which can be read from, or written to, the
144
- * data handle, bounded by the specified number of bytes.
143
+ * Gets the number of bytes which can be read from, or written to, the data
144
+ * handle, bounded by the specified number of bytes.
145
145
* <p>
146
146
* In the case of reading, attempting to read the returned number of bytes is
147
147
* guaranteed not to throw {@link EOFException}. However, be aware that the
@@ -161,8 +161,8 @@ default String checksum() throws IOException {
161
161
* </p>
162
162
*
163
163
* @param count Desired number of bytes to read/write.
164
- * @return The actual number of bytes which could be read/written,
165
- * which might be less than the requested value.
164
+ * @return The actual number of bytes which could be read/written, which might
165
+ * be less than the requested value.
166
166
* @throws IOException If something goes wrong with the check.
167
167
*/
168
168
default long available (final long count ) throws IOException {
@@ -172,7 +172,7 @@ default long available(final long count) throws IOException {
172
172
173
173
/**
174
174
* Ensures that the handle has sufficient bytes available to read.
175
- *
175
+ *
176
176
* @param count Number of bytes to read.
177
177
* @see #available(long)
178
178
* @throws EOFException If there are insufficient bytes available.
@@ -187,7 +187,7 @@ default void ensureReadable(final long count) throws IOException {
187
187
/**
188
188
* Ensures that the handle has the correct length to be written to, and
189
189
* extends it as required.
190
- *
190
+ *
191
191
* @param count Number of bytes to write.
192
192
* @return {@code true} if the handle's length was sufficient, or
193
193
* {@code false} if the handle's length required an extension.
@@ -271,7 +271,7 @@ default String readString(final int n) throws IOException {
271
271
272
272
/**
273
273
* Reads a string ending with one of the characters in the given string.
274
- *
274
+ *
275
275
* @see #findString(String...)
276
276
*/
277
277
default String readString (final String lastChars ) throws IOException {
@@ -285,7 +285,7 @@ default String readString(final String lastChars) throws IOException {
285
285
286
286
/**
287
287
* Reads a string ending with one of the given terminating substrings.
288
- *
288
+ *
289
289
* @param terminators The strings for which to search.
290
290
* @return The string from the initial position through the end of the
291
291
* terminating sequence, or through the end of the stream if no
@@ -350,10 +350,7 @@ default String findString(final boolean saveString, final int blockSize,
350
350
final StringBuilder out = new StringBuilder ();
351
351
final long startPos = offset ();
352
352
long bytesDropped = 0 ;
353
- final long inputLen = length ();
354
- long maxLen = inputLen - startPos ;
355
- final boolean tooLong = saveString && maxLen > MAX_SEARCH_SIZE ;
356
- if (tooLong ) maxLen = MAX_SEARCH_SIZE ;
353
+ final long maxLen = saveString ? MAX_SEARCH_SIZE : Long .MAX_VALUE ;
357
354
boolean match = false ;
358
355
int maxTermLen = 0 ;
359
356
for (final String term : terminators ) {
@@ -366,7 +363,10 @@ default String findString(final boolean saveString, final int blockSize,
366
363
new DataHandleInputStream <>(this ), getEncoding ());
367
364
final char [] buf = new char [blockSize ];
368
365
long loc = 0 ;
369
- while (loc < maxLen && offset () < length () - 1 ) {
366
+ int r = 0 ;
367
+
368
+ // NB: we need at least 2 bytes to read a char
369
+ while (loc < maxLen && ((r = in .read (buf , 0 , blockSize )) > 1 )) {
370
370
// if we're not saving the string, drop any old, unnecessary output
371
371
if (!saveString ) {
372
372
final int outLen = out .length ();
@@ -378,16 +378,12 @@ default String findString(final boolean saveString, final int blockSize,
378
378
bytesDropped += dropIndex ;
379
379
}
380
380
}
381
-
382
- // read block from stream
383
- final int r = in .read (buf , 0 , blockSize );
384
- if (r <= 0 ) throw new IOException ("Cannot read from stream: " + r );
385
-
386
381
// append block to output
387
382
out .append (buf , 0 , r );
388
383
389
384
// check output, returning smallest possible string
390
- int min = Integer .MAX_VALUE , tagLen = 0 ;
385
+ int min = Integer .MAX_VALUE ;
386
+ int tagLen = 0 ;
391
387
for (final String t : terminators ) {
392
388
final int len = t .length ();
393
389
final int start = (int ) (loc - bytesDropped - len );
@@ -415,7 +411,9 @@ default String findString(final boolean saveString, final int blockSize,
415
411
}
416
412
417
413
// no match
418
- if (tooLong ) throw new IOException ("Maximum search length reached." );
414
+ if (loc > MAX_SEARCH_SIZE ) {
415
+ throw new IOException ("Maximum search length reached." );
416
+ }
419
417
return saveString ? out .toString () : null ;
420
418
}
421
419
0 commit comments