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