< prev index next >
src/java.base/share/classes/java/util/Base64.java
Print this page
@@ -739,13 +739,48 @@
// 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) {
+ /**
+ * Decodes base64 characters, and returns the number of data bytes
+ * produced by the base64 decode intrinsic.
+ *
+ * decodeBlock() can be overridden by an arch-specific intrinsic.
+ * decodeBlock can choose to decode all, none, or a variable-sized
+ * prefix of the source bytes. This allows the intrinsic to decode
+ * in chunks of the source that are of a favorable size for the
+ * specific processor it's running on.
+ *
+ * If the intrinsic function does not process all of the source
+ * bytes, it should process a multiple of four of them, making the
+ * returned destination length a multiple of three.
+ *
+ * If any illegal base64 bytes are encountered in the source by the
+ * intrinsic, the intrinsic can return a data length of zero or any
+ * number of bytes before the place where the illegal base64 byte
+ * was encountered.
+ *
+ * @param src
+ * the source byte array of Base64 encoded bytes
+ * @param sp
+ * the offset into src array to begin processing
+ * @param sl
+ * the total length of source array
+ * @param dst
+ * the destination byte array of decoded data bytes
+ * @param isURL
+ * boolean, when true decode RFC4648 URL-safe base64 characters
+ * @return the number of destination data bytes produced
+ */
+ @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 +853,49 @@
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 >