< 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 >