4040 * character encodings which are compatible with the lower 127 ASCII chart (ISO-8859-1, Windows-1252, UTF-8, etc).
4141 * </p>
4242 * <p>
43- * This class is not thread-safe. Each thread should use its own instance .
43+ * This class is thread-safe.
4444 * </p>
4545 *
4646 * @see <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045</a>
@@ -155,12 +155,6 @@ public class Base64 extends BaseNCodec {
155155 */
156156 private final int encodeSize ;
157157
158- /**
159- * Place holder for the bytes we're dealing with for our based logic.
160- * Bitwise operations store and extract the encoding or decoding from this variable.
161- */
162- private int bitWorkArea ;
163-
164158 /**
165159 * Creates a Base64 codec used for decoding (all modes) and encoding in URL-unsafe mode.
166160 * <p>
@@ -321,67 +315,68 @@ public boolean isUrlSafe() {
321315 * Position to start reading data from.
322316 * @param inAvail
323317 * Amount of bytes available from input for encoding.
318+ * @param context the context to be used
324319 */
325320 @ Override
326- void encode (byte [] in , int inPos , int inAvail ) {
327- if (eof ) {
321+ void encode (byte [] in , int inPos , int inAvail , Context context ) {
322+ if (context . eof ) {
328323 return ;
329324 }
330325 // inAvail < 0 is how we're informed of EOF in the underlying data we're
331326 // encoding.
332327 if (inAvail < 0 ) {
333- eof = true ;
334- if (0 == modulus && lineLength == 0 ) {
328+ context . eof = true ;
329+ if (0 == context . modulus && lineLength == 0 ) {
335330 return ; // no leftovers to process and not using chunking
336331 }
337- ensureBufferSize (encodeSize );
338- int savedPos = pos ;
339- switch (modulus ) { // 0-2
332+ ensureBufferSize (encodeSize , context );
333+ int savedPos = context . pos ;
334+ switch (context . modulus ) { // 0-2
340335 case 1 : // 8 bits = 6 + 2
341- buffer [pos ++] = encodeTable [(bitWorkArea >> 2 ) & MASK_6BITS ]; // top 6 bits
342- buffer [pos ++] = encodeTable [(bitWorkArea << 4 ) & MASK_6BITS ]; // remaining 2
336+ context . buffer [context . pos ++] = encodeTable [(context . ibitWorkArea >> 2 ) & MASK_6BITS ]; // top 6 bits
337+ context . buffer [context . pos ++] = encodeTable [(context . ibitWorkArea << 4 ) & MASK_6BITS ]; // remaining 2
343338 // URL-SAFE skips the padding to further reduce size.
344339 if (encodeTable == STANDARD_ENCODE_TABLE ) {
345- buffer [pos ++] = PAD ;
346- buffer [pos ++] = PAD ;
340+ context . buffer [context . pos ++] = PAD ;
341+ context . buffer [context . pos ++] = PAD ;
347342 }
348343 break ;
349344
350345 case 2 : // 16 bits = 6 + 6 + 4
351- buffer [pos ++] = encodeTable [(bitWorkArea >> 10 ) & MASK_6BITS ];
352- buffer [pos ++] = encodeTable [(bitWorkArea >> 4 ) & MASK_6BITS ];
353- buffer [pos ++] = encodeTable [(bitWorkArea << 2 ) & MASK_6BITS ];
346+ context . buffer [context . pos ++] = encodeTable [(context . ibitWorkArea >> 10 ) & MASK_6BITS ];
347+ context . buffer [context . pos ++] = encodeTable [(context . ibitWorkArea >> 4 ) & MASK_6BITS ];
348+ context . buffer [context . pos ++] = encodeTable [(context . ibitWorkArea << 2 ) & MASK_6BITS ];
354349 // URL-SAFE skips the padding to further reduce size.
355350 if (encodeTable == STANDARD_ENCODE_TABLE ) {
356- buffer [pos ++] = PAD ;
351+ context . buffer [context . pos ++] = PAD ;
357352 }
358353 break ;
359354 }
360- currentLinePos += pos - savedPos ; // keep track of current line position
355+ context . currentLinePos += context . pos - savedPos ; // keep track of current line position
361356 // if currentPos == 0 we are at the start of a line, so don't add CRLF
362- if (lineLength > 0 && currentLinePos > 0 ) {
363- System .arraycopy (lineSeparator , 0 , buffer , pos , lineSeparator .length );
364- pos += lineSeparator .length ;
357+ if (lineLength > 0 && context . currentLinePos > 0 ) {
358+ System .arraycopy (lineSeparator , 0 , context . buffer , context . pos , lineSeparator .length );
359+ context . pos += lineSeparator .length ;
365360 }
366361 } else {
367362 for (int i = 0 ; i < inAvail ; i ++) {
368- ensureBufferSize (encodeSize );
369- modulus = (modulus +1 ) % BYTES_PER_UNENCODED_BLOCK ;
363+ ensureBufferSize (encodeSize , context );
364+ context . modulus = (context . modulus +1 ) % BYTES_PER_UNENCODED_BLOCK ;
370365 int b = in [inPos ++];
371366 if (b < 0 ) {
372367 b += 256 ;
373368 }
374- bitWorkArea = (bitWorkArea << 8 ) + b ; // BITS_PER_BYTE
375- if (0 == modulus ) { // 3 bytes = 24 bits = 4 * 6 bits to extract
376- buffer [pos ++] = encodeTable [(bitWorkArea >> 18 ) & MASK_6BITS ];
377- buffer [pos ++] = encodeTable [(bitWorkArea >> 12 ) & MASK_6BITS ];
378- buffer [pos ++] = encodeTable [(bitWorkArea >> 6 ) & MASK_6BITS ];
379- buffer [pos ++] = encodeTable [bitWorkArea & MASK_6BITS ];
380- currentLinePos += BYTES_PER_ENCODED_BLOCK ;
381- if (lineLength > 0 && lineLength <= currentLinePos ) {
382- System .arraycopy (lineSeparator , 0 , buffer , pos , lineSeparator .length );
383- pos += lineSeparator .length ;
384- currentLinePos = 0 ;
369+ context . ibitWorkArea = (context . ibitWorkArea << 8 ) + b ; // BITS_PER_BYTE
370+ if (0 == context . modulus ) { // 3 bytes = 24 bits = 4 * 6 bits to extract
371+ context . buffer [context . pos ++] = encodeTable [(context . ibitWorkArea >> 18 ) & MASK_6BITS ];
372+ context . buffer [context . pos ++] = encodeTable [(context . ibitWorkArea >> 12 ) & MASK_6BITS ];
373+ context . buffer [context . pos ++] = encodeTable [(context . ibitWorkArea >> 6 ) & MASK_6BITS ];
374+ context . buffer [context . pos ++] = encodeTable [context . ibitWorkArea & MASK_6BITS ];
375+ context . currentLinePos += BYTES_PER_ENCODED_BLOCK ;
376+ if (lineLength > 0 && lineLength <= context . currentLinePos ) {
377+ System .arraycopy (lineSeparator , 0 , context . buffer , context . pos , lineSeparator .length );
378+ context . pos += lineSeparator .length ;
379+ context . currentLinePos = 0 ;
385380 }
386381 }
387382 }
@@ -410,32 +405,33 @@ void encode(byte[] in, int inPos, int inAvail) {
410405 * Position to start reading data from.
411406 * @param inAvail
412407 * Amount of bytes available from input for encoding.
408+ * @param context the context to be used
413409 */
414410 @ Override
415- void decode (byte [] in , int inPos , int inAvail ) {
416- if (eof ) {
411+ void decode (byte [] in , int inPos , int inAvail , Context context ) {
412+ if (context . eof ) {
417413 return ;
418414 }
419415 if (inAvail < 0 ) {
420- eof = true ;
416+ context . eof = true ;
421417 }
422418 for (int i = 0 ; i < inAvail ; i ++) {
423- ensureBufferSize (decodeSize );
419+ ensureBufferSize (decodeSize , context );
424420 byte b = in [inPos ++];
425421 if (b == PAD ) {
426422 // We're done.
427- eof = true ;
423+ context . eof = true ;
428424 break ;
429425 } else {
430426 if (b >= 0 && b < DECODE_TABLE .length ) {
431427 int result = DECODE_TABLE [b ];
432428 if (result >= 0 ) {
433- modulus = (modulus +1 ) % BYTES_PER_ENCODED_BLOCK ;
434- bitWorkArea = (bitWorkArea << BITS_PER_ENCODED_BYTE ) + result ;
435- if (modulus == 0 ) {
436- buffer [pos ++] = (byte ) ((bitWorkArea >> 16 ) & MASK_8BITS );
437- buffer [pos ++] = (byte ) ((bitWorkArea >> 8 ) & MASK_8BITS );
438- buffer [pos ++] = (byte ) (bitWorkArea & MASK_8BITS );
429+ context . modulus = (context . modulus +1 ) % BYTES_PER_ENCODED_BLOCK ;
430+ context . ibitWorkArea = (context . ibitWorkArea << BITS_PER_ENCODED_BYTE ) + result ;
431+ if (context . modulus == 0 ) {
432+ context . buffer [context . pos ++] = (byte ) ((context . ibitWorkArea >> 16 ) & MASK_8BITS );
433+ context . buffer [context . pos ++] = (byte ) ((context . ibitWorkArea >> 8 ) & MASK_8BITS );
434+ context . buffer [context . pos ++] = (byte ) (context . ibitWorkArea & MASK_8BITS );
439435 }
440436 }
441437 }
@@ -445,22 +441,22 @@ void decode(byte[] in, int inPos, int inAvail) {
445441 // Two forms of EOF as far as base64 decoder is concerned: actual
446442 // EOF (-1) and first time '=' character is encountered in stream.
447443 // This approach makes the '=' padding characters completely optional.
448- if (eof && modulus != 0 ) {
449- ensureBufferSize (decodeSize );
444+ if (context . eof && context . modulus != 0 ) {
445+ ensureBufferSize (decodeSize , context );
450446
451447 // We have some spare bits remaining
452448 // Output all whole multiples of 8 bits and ignore the rest
453- switch (modulus ) {
449+ switch (context . modulus ) {
454450 // case 1: // 6 bits - ignore entirely
455451 // break;
456452 case 2 : // 12 bits = 8 + 4
457- bitWorkArea = bitWorkArea >> 4 ; // dump the extra 4 bits
458- buffer [pos ++] = (byte ) ((bitWorkArea ) & MASK_8BITS );
453+ context . ibitWorkArea = context . ibitWorkArea >> 4 ; // dump the extra 4 bits
454+ context . buffer [context . pos ++] = (byte ) ((context . ibitWorkArea ) & MASK_8BITS );
459455 break ;
460456 case 3 : // 18 bits = 8 + 8 + 2
461- bitWorkArea = bitWorkArea >> 2 ; // dump 2 bits
462- buffer [pos ++] = (byte ) ((bitWorkArea >> 8 ) & MASK_8BITS );
463- buffer [pos ++] = (byte ) ((bitWorkArea ) & MASK_8BITS );
457+ context . ibitWorkArea = context . ibitWorkArea >> 2 ; // dump 2 bits
458+ context . buffer [context . pos ++] = (byte ) ((context . ibitWorkArea >> 8 ) & MASK_8BITS );
459+ context . buffer [context . pos ++] = (byte ) ((context . ibitWorkArea ) & MASK_8BITS );
464460 break ;
465461 }
466462 }
0 commit comments