@@ -85,7 +85,7 @@ public int read() throws IOException {
85
85
}
86
86
final int result ;
87
87
if (this .eof ) {
88
- result = - 1 ;
88
+ result = ChunkedInputStream . EMPTY_VALUE ;
89
89
} else {
90
90
++this .pos ;
91
91
result = this .origin .read ();
@@ -101,7 +101,7 @@ public int read(final byte[] buf, final int off, final int len)
101
101
}
102
102
final int result ;
103
103
if (this .eof ) {
104
- result = - 1 ;
104
+ result = ChunkedInputStream . EMPTY_VALUE ;
105
105
} else {
106
106
final int shift = Math .min (len , this .size - this .pos );
107
107
final int count = this .origin .read (buf , off , shift );
@@ -137,7 +137,7 @@ private void readCrlf() throws IOException {
137
137
throw new IOException (
138
138
String .format (
139
139
"%s %d%s%d" ,
140
- "CRLF expected at end of chunk: " ,
140
+ ChunkedInputStream . CRLF_EXPECTED ,
141
141
crsymbol ,
142
142
"/" ,
143
143
lfsymbol
@@ -154,6 +154,14 @@ private void nextChunk() throws IOException {
154
154
if (!this .bof ) {
155
155
this .readCrlf ();
156
156
}
157
+ this .clearChunkState ();
158
+ }
159
+
160
+ /**
161
+ * Clears chunk state.
162
+ * @throws IOException If an IO error occurs.
163
+ */
164
+ private void clearChunkState () throws IOException {
157
165
this .size = ChunkedInputStream .chunkSize (this .origin );
158
166
this .bof = false ;
159
167
this .pos = 0 ;
@@ -174,7 +182,7 @@ private static int chunkSize(final InputStream stream)
174
182
throws IOException {
175
183
final ByteArrayOutputStream baos = ChunkedInputStream .sizeLine (stream );
176
184
final String data = baos .toString (Charset .defaultCharset ().name ());
177
- final int separator = data .indexOf (';' );
185
+ final int separator = data .indexOf (ChunkedInputStream . SEMICOLON );
178
186
final Text number = new Trimmed (
179
187
new Unchecked <>(
180
188
new Ternary <>(
@@ -189,41 +197,19 @@ private static int chunkSize(final InputStream stream)
189
197
new UncheckedText (
190
198
number
191
199
).asString (),
192
- 16
200
+ ChunkedInputStream . DEFAULT_RADIX
193
201
);
194
202
} catch (final NumberFormatException ex ) {
195
203
throw new IOException (
196
204
String .format (
197
- "Bad chunk size: %s" ,
205
+ ChunkedInputStream . BAD_CHUNK_SIZE ,
198
206
baos .toString (Charset .defaultCharset ().name ())
199
207
),
200
208
ex
201
209
);
202
210
}
203
211
}
204
212
205
- /**
206
- * Possible states of FSM that used to find chunk size.
207
- */
208
- private enum State {
209
- /**
210
- * Normal.
211
- */
212
- NORMAL ,
213
- /**
214
- * If \r was scanned.
215
- */
216
- R ,
217
- /**
218
- * Inside quoted string.
219
- */
220
- QUOTED_STRING ,
221
- /**
222
- * End.
223
- */
224
- END ;
225
- }
226
-
227
213
/**
228
214
* Extract line with chunk size from stream.
229
215
* @param stream Input stream.
@@ -251,32 +237,26 @@ private static ByteArrayOutputStream sizeLine(final InputStream stream)
251
237
private static State next (final InputStream stream , final State state ,
252
238
final ByteArrayOutputStream line ) throws IOException {
253
239
final int next = stream .read ();
254
- if (next == - 1 ) {
255
- throw new IOException ("chunked stream ended unexpectedly" );
240
+ if (next == ChunkedInputStream . EMPTY_VALUE ) {
241
+ throw new IOException (ChunkedInputStream . END_OF_STREAM );
256
242
}
257
243
final State result ;
258
244
switch (state ) {
259
245
case NORMAL :
260
246
result = nextNormal (state , line , next );
261
247
break ;
262
248
case R :
263
- if (next == '\n' ) {
249
+ if (next == ChunkedInputStream . NEXT_LINE ) {
264
250
result = State .END ;
265
251
} else {
266
- throw new IOException (
267
- String .format (
268
- "%s%s" ,
269
- "Protocol violation: Unexpected" ,
270
- " single newline character in chunk size"
271
- )
272
- );
252
+ throw new IOException (ChunkedInputStream .PROTOCOL_VIOLATION );
273
253
}
274
254
break ;
275
255
case QUOTED_STRING :
276
256
result = nextQuoted (stream , state , line , next );
277
257
break ;
278
258
default :
279
- throw new IllegalStateException ("Bad state" );
259
+ throw new IllegalStateException (ChunkedInputStream . BAD_STATE );
280
260
}
281
261
return result ;
282
262
}
@@ -292,10 +272,10 @@ private static State nextNormal(final State state,
292
272
final ByteArrayOutputStream line , final int next ) {
293
273
final State result ;
294
274
switch (next ) {
295
- case '\r' :
275
+ case ChunkedInputStream . R_VALUE :
296
276
result = State .R ;
297
277
break ;
298
- case '\"' :
278
+ case ChunkedInputStream . QUOTED_STRING :
299
279
result = State .QUOTED_STRING ;
300
280
break ;
301
281
default :
@@ -321,11 +301,11 @@ private static State nextQuoted(final InputStream stream, final State state,
321
301
throws IOException {
322
302
final State result ;
323
303
switch (next ) {
324
- case '\\' :
304
+ case ChunkedInputStream . DOUBLE_SLASH :
325
305
result = state ;
326
306
line .write (stream .read ());
327
307
break ;
328
- case '\"' :
308
+ case ChunkedInputStream . QUOTED_STRING :
329
309
result = State .NORMAL ;
330
310
break ;
331
311
default :
@@ -335,4 +315,78 @@ private static State nextQuoted(final InputStream stream, final State state,
335
315
}
336
316
return result ;
337
317
}
318
+ /**
319
+ * Possible states of FSM that used to find chunk size.
320
+ */
321
+ private enum State {
322
+ /**
323
+ * Normal.
324
+ */
325
+ NORMAL ,
326
+ /**
327
+ * If \r was scanned.
328
+ */
329
+ R ,
330
+ /**
331
+ * Inside quoted string.
332
+ */
333
+ QUOTED_STRING ,
334
+ /**
335
+ * End.
336
+ */
337
+ END ;
338
+ }
339
+
340
+ /**
341
+ * Empty value for checking the result.
342
+ */
343
+ private static final int EMPTY_VALUE = -1 ;
344
+ /**
345
+ * Default radix value.
346
+ */
347
+ private static final int DEFAULT_RADIX = 16 ;
348
+ /**
349
+ * Double slash value.
350
+ */
351
+ private static final int DOUBLE_SLASH = '\\' ;
352
+ /**
353
+ * Quoted string value.
354
+ */
355
+ private static final int QUOTED_STRING = '\"' ;
356
+ /**
357
+ * Next line value.
358
+ */
359
+ private static final int NEXT_LINE = '\n' ;
360
+ /**
361
+ * R value.
362
+ */
363
+ private static final int R_VALUE = '\r' ;
364
+ /**
365
+ * Semicolon value.
366
+ */
367
+ private static final int SEMICOLON = ';' ;
368
+ /**
369
+ * Exception for bad state.
370
+ */
371
+ private static final String BAD_STATE = "Bad state" ;
372
+ /**
373
+ * Exception for bad chunk.
374
+ */
375
+ private static final String BAD_CHUNK_SIZE = "Bad chunk size: %s" ;
376
+ /**
377
+ * Exception for chunk stream end.
378
+ */
379
+ private static final String END_OF_STREAM = "chunked stream ended unexpectedly" ;
380
+ /**
381
+ * Exception for crlf expectation state.
382
+ */
383
+ private static final String CRLF_EXPECTED = "CRLF expected at end of chunk: " ;
384
+ /**
385
+ * Exception for protocol violation.
386
+ */
387
+ private static final String PROTOCOL_VIOLATION = String .format (
388
+ "%s%s" ,
389
+ "Protocol violation: Unexpected" ,
390
+ " single newline character in chunk size"
391
+ );
338
392
}
0 commit comments