< prev index next >
src/java.base/share/classes/java/util/Base64.java
Print this page
@@ -739,13 +739,38 @@
// integer limit. The final value will always be in integer
// limits
return 3 * (int) ((len + 3L) / 4) - paddings;
}
- private int decode0(byte[] src, int sp, int sl, byte[] dst) {
+ // decodeBlock() can be overridden by an arch-specific intrinsic.
+ // decodeBlock is allowed to not decode all the (legal) bytes that
+ // are passed to it. It can choose to decode all, none, or a
+ // variable-sized prefix of the data. This allows the intrinsic to
+ // decode in chunks of the source that of a favorable size for the
+ // specific processor it's running on. For example, some
+ // processors may do better at decoding 256 byte blocks at a time,
+ // and another type may choose 32 bytes at a time, leaving the (sl
+ // % block_size) bytes for decodeBlockSlow to finish up.
+ //
+ // If any illegal base64 bytes are encountered in the src by the
+ // intrinsic, the intrinsic can simply return a data length of zero
+ // or any number of bytes before the place where the illegal
+ // base64 byte was encountered. In this case, decodeBlockSlow will
+ // be called to pinpoint the exact cause of the problem, starting
+ // at the source byte calculated by the returned data length.
+ //
+ // If the intrinsic function does not process all of the bytes,
+ // it should process a multiple of four of the input characters,
+ // making the returned destination length a multiple of three.
+ //
+ @HotSpotIntrinsicCandidate
+ private int decodeBlock(byte[] src, int sp, int sl, byte[] dst, boolean isURL) {
+ return 0;
+ }
+
+ private int decodeBlockSlow(byte[] src, int sp, int sl, byte[] dst, int dp) {
int[] base64 = isURL ? fromBase64URL : fromBase64;
- int dp = 0;
int bits = 0;
int shiftto = 18; // pos of first byte of 4-byte atom
while (sp < sl) {
if (shiftto == 18 && sp + 4 < sl) { // fast path
@@ -818,10 +843,46 @@
throw new IllegalArgumentException(
"Input byte array has incorrect ending byte at " + sp);
}
return dp;
}
+
+ private int decode0(byte[] src, int sp, int sl, byte[] dst) {
+ if (isMIME) {
+ // TODO? Add HotSpot intrinsic candidate for the isMIME == true case
+ return decodeBlockSlow(src, sp, sl, dst, 0);
+ } else {
+ int dl = decodeBlock(src, sp, sl, dst, isURL);
+ // Calculate how many characters were processed by how
+ // many bytes of data were returned.
+ int chars_decoded = ((dl + 2) / 3) * 4;
+ if (sl > chars_decoded) {
+ // Base64 characters always come in groups of four,
+ // producing three bytes of binary data (except for
+ // on the final four-character piece where it can
+ // produce one to three data bytes depending on how
+ // many fill characters there - zero, one, or
+ // two). The only case where there should be a
+ // non-multiple of three returned is if the
+ // intrinsic has processed all of the characters
+ // passed to it. At this point in the logic,
+ // however, we know the instrinsic hasn't processed
+ // all of the chracters.
+ //
+ // Round dl down to the nearest three-byte boundary
+ dl = (dl / 3) * 3;
+
+ // Recalculate chars_decoded based on the rounded dl
+ chars_decoded = (dl / 3) * 4;
+
+ // Finish the process using decodeBlockSlow
+ return decodeBlockSlow(src, sp + chars_decoded, sl, dst, dl);
+ } else {
+ return dl;
+ }
+ }
+ }
}
/*
* An output stream for encoding bytes into the Base64.
*/
< prev index next >