001/*
002 * The contents of this file are subject to the terms of the Common Development and
003 * Distribution License (the License). You may not use this file except in compliance with the License.
004 *
005 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
006 * specific language governing permission and limitations under the License.
007 *
008 * When distributing Covered Software, include this CDDL Header Notice in each file and include
009 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
010 * Header, with the fields enclosed by brackets [] replaced by your own identifying
011 * information: "Portions copyright [year] [name of copyright owner]".
012 *
013 * Copyright 2015 ForgeRock AS.
014 */
015
016
017package org.forgerock.util.encode;
018
019import java.util.Arrays;
020
021/**
022 * A very fast and memory efficient class to encode and decode to and from
023 * BASE64 in full accordance with RFC 2045.<br>
024 * <br>
025 * On Windows XP sp1 with 1.4.2_04 and later ;), this encoder and decoder is
026 * about 10 times faster on small arrays (10 - 1000 bytes) and 2-3 times as fast
027 * on larger arrays (10000 - 1000000 bytes) compared to
028 * <code>sun.misc.Encoder()/Decoder()</code>.<br>
029 * <br>
030 * On byte arrays the encoder is about 20% faster than Jakarta Commons Base64
031 * Codec for encode and about 50% faster for decoding large arrays. This
032 * implementation is about twice as fast on very small arrays (&lt; 30 bytes).
033 * If source/destination is a <code>String</code> this version is about three
034 * times as fast due to the fact that the Commons Codec result has to be recoded
035 * to a <code>String</code> from <code>byte[]</code>, which is very expensive.<br>
036 * <br>
037 * This encode/decode algorithm doesn't create any temporary arrays as many
038 * other codecs do, it only allocates the resulting array. This produces less
039 * garbage and it is possible to handle arrays twice as large as algorithms that
040 * create a temporary array. (E.g. Jakarta Commons Codec). It is unknown whether
041 * Sun's <code>sun.misc.Encoder()/Decoder()</code> produce temporary arrays but
042 * since performance is quite low it probably does.<br>
043 * <br>
044 * The encoder produces the same output as the Sun one except that the Sun's
045 * encoder appends a trailing line separator if the last character isn't a pad.
046 * Unclear why but it only adds to the length and is probably a side effect.
047 * Both are in conformance with RFC 2045 though.<br>
048 * Commons codec seem to always att a trailing line separator.<br>
049 * <br>
050 * <b>Note!</b> The encode/decode method pairs (types) come in three versions
051 * with the <b>exact</b> same algorithm and thus a lot of code redundancy. This
052 * is to not create any temporary arrays for transcoding to/from different
053 * format types. The methods not used can simply be commented out.<br>
054 * <br>
055 * There is also a "fast" version of all decode methods that works the same way
056 * as the normal ones, but har a few demands on the decoded input. Normally
057 * though, these fast verions should be used if the source if the input is known
058 * and it hasn't bee tampered with.<br>
059 * <br>
060 * If you find the code useful or you find a bug, please send me a note at
061 * base64 @ miginfocom . com.
062 *
063 * @version 2.2
064 * @author Mikael Grev Date: 2004-aug-02 Time: 11:31:11
065 */
066public class Base64 {
067
068    private static final char[] CA =
069            "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".toCharArray();
070    private static final int[] IA = new int[256];
071
072    static {
073        Arrays.fill(IA, -1);
074        for (int i = 0, iS = CA.length; i < iS; i++) {
075            IA[CA[i]] = i;
076        }
077        IA['='] = 0;
078    }
079
080    /**
081     * Decodes a BASE64 encoded byte array. All illegal characters will be
082     * ignored and can handle both arrays with and without line separators.
083     *
084     * @param sArr
085     *            The source array. Length 0 will return an empty array.
086     *            <code>null</code> will throw an exception.
087     * @return The decoded array of bytes. May be of length 0. Will be
088     *         <code>null</code> if the legal characters (including '=') isn't
089     *         divideable by 4. (I.e. definitely corrupted).
090     */
091    public static byte[] decode(final byte[] sArr) {
092        // Check special case
093        final int sLen = sArr.length;
094
095        /*
096         * Count illegal characters (including '\r', '\n') to know what size the
097         * returned array will be, so we don't have to reallocate & copy it
098         * later.
099         */
100        int sepCnt = 0; // Number of separator characters. (Actually illegal characters, but that's a bonus...)
101        // If input is "pure" (I.e. no line separators or illegal chars) base64 this loop can be removed.
102        for (byte aSArr : sArr) {
103            if (IA[aSArr & 0xff] < 0) {
104                sepCnt++;
105            }
106        }
107
108        /*
109         * Check so that legal chars (including '=') are evenly divideable by 4
110         * as specified in RFC 2045.
111         */
112        if ((sLen - sepCnt) % 4 != 0) {
113            return null;
114        }
115
116        int pad = 0;
117        for (int i = sLen; i > 1 && IA[sArr[--i] & 0xff] <= 0;) {
118            if (sArr[i] == '=') {
119                pad++;
120            }
121        }
122
123        final int len = ((sLen - sepCnt) * 6 >> 3) - pad;
124
125        final byte[] dArr = new byte[len]; // Preallocate byte[] of exact length
126
127        for (int s = 0, d = 0; d < len;) {
128            // Assemble three bytes into an int from four "valid" characters.
129            int i = 0;
130            for (int j = 0; j < 4; j++) { // j only increased if a valid char was found.
131                final int c = IA[sArr[s++] & 0xff];
132                if (c >= 0) {
133                    i |= c << 18 - j * 6;
134                } else {
135                    j--;
136                }
137            }
138
139            // Add the bytes
140            dArr[d++] = (byte) (i >> 16);
141            if (d < len) {
142                dArr[d++] = (byte) (i >> 8);
143                if (d < len) {
144                    dArr[d++] = (byte) i;
145                }
146            }
147        }
148
149        return dArr;
150    }
151
152    /**
153     * Decodes a BASE64 encoded char array. All illegal characters will be
154     * ignored and can handle both arrays with and without line separators.
155     *
156     * @param sArr
157     *            The source array. <code>null</code> or length 0 will return an
158     *            empty array.
159     * @return The decoded array of bytes. May be of length 0. Will be
160     *         <code>null</code> if the legal characters (including '=') isn't
161     *         divideable by 4. (I.e. definitely corrupted).
162     */
163    public static byte[] decode(final char[] sArr) {
164        // Check special case
165        final int sLen = sArr != null ? sArr.length : 0;
166        if (sLen == 0) {
167            return new byte[0];
168        }
169
170        /*
171         * Count illegal characters (including '\r', '\n') to know what size the
172         * returned array will be, so we don't have to reallocate & copy it
173         * later.
174         */
175        int sepCnt = 0; // Number of separator characters. (Actually illegal characters, but that's a bonus...)
176        for (int i = 0; i < sLen; i++) // If input is "pure" (I.e. no line separators or illegal chars) base64 this loop can be commented out.
177        {
178            if (IA[sArr[i]] < 0) {
179                sepCnt++;
180            }
181        }
182
183        /*
184         * Check so that legal chars (including '=') are evenly divideable by 4
185         * as specified in RFC 2045.
186         */
187        if ((sLen - sepCnt) % 4 != 0) {
188            return null;
189        }
190
191        int pad = 0;
192        for (int i = sLen; i > 1 && IA[sArr[--i]] <= 0;) {
193            if (sArr[i] == '=') {
194                pad++;
195            }
196        }
197
198        final int len = ((sLen - sepCnt) * 6 >> 3) - pad;
199
200        final byte[] dArr = new byte[len]; // Preallocate byte[] of exact length
201
202        for (int s = 0, d = 0; d < len;) {
203            // Assemble three bytes into an int from four "valid" characters.
204            int i = 0;
205            for (int j = 0; j < 4; j++) { // j only increased if a valid char was found.
206                final int c = IA[sArr[s++]];
207                if (c >= 0) {
208                    i |= c << 18 - j * 6;
209                } else {
210                    j--;
211                }
212            }
213            // Add the bytes
214            dArr[d++] = (byte) (i >> 16);
215            if (d < len) {
216                dArr[d++] = (byte) (i >> 8);
217                if (d < len) {
218                    dArr[d++] = (byte) i;
219                }
220            }
221        }
222        return dArr;
223    }
224
225    /**
226     * Decodes a BASE64 encoded <code>String</code>. All illegal characters will
227     * be ignored and can handle both strings with and without line separators.<br>
228     * <b>Note!</b> It can be up to about 2x the speed to call
229     * <code>decode(str.toCharArray())</code> instead. That will create a
230     * temporary array though. This version will use <code>str.charAt(i)</code>
231     * to iterate the string.
232     *
233     * @param str
234     *            The source string. <code>null</code> or length 0 will return
235     *            an empty array.
236     * @return The decoded array of bytes. May be of length 0. Will be
237     *         <code>null</code> if the legal characters (including '=') isn't
238     *         divideable by 4. (I.e. definitely corrupted).
239     */
240    public static byte[] decode(final String str) {
241        // Check special case
242        final int sLen = str != null ? str.length() : 0;
243        if (sLen == 0) {
244            return new byte[0];
245        }
246
247        /*
248         * Count illegal characters (including '\r', '\n') to know what size the
249         * returned array will be, so we don't have to reallocate & copy it
250         * later.
251         */
252        int sepCnt = 0; // Number of separator characters. (Actually illegal characters, but that's a bonus...)
253        for (int i = 0; i < sLen; i++) // If input is "pure" (I.e. no line separators or illegal chars) base64 this loop can be commented out.
254        {
255            if (IA[str.charAt(i)] < 0) {
256                sepCnt++;
257            }
258        }
259
260        /*
261         * Check so that legal chars (including '=') are evenly divideable by 4
262         * as specified in RFC 2045.
263         */
264        if ((sLen - sepCnt) % 4 != 0) {
265            return null;
266        }
267
268        // Count '=' at end
269        int pad = 0;
270        for (int i = sLen; i > 1 && IA[str.charAt(--i)] <= 0;) {
271            if (str.charAt(i) == '=') {
272                pad++;
273            }
274        }
275
276        final int len = ((sLen - sepCnt) * 6 >> 3) - pad;
277
278        final byte[] dArr = new byte[len]; // Preallocate byte[] of exact length
279
280        for (int s = 0, d = 0; d < len;) {
281            // Assemble three bytes into an int from four "valid" characters.
282            int i = 0;
283            for (int j = 0; j < 4; j++) { // j only increased if a valid char was found.
284                final int c = IA[str.charAt(s++)];
285                if (c >= 0) {
286                    i |= c << 18 - j * 6;
287                } else {
288                    j--;
289                }
290            }
291            // Add the bytes
292            dArr[d++] = (byte) (i >> 16);
293            if (d < len) {
294                dArr[d++] = (byte) (i >> 8);
295                if (d < len) {
296                    dArr[d++] = (byte) i;
297                }
298            }
299        }
300        return dArr;
301    }
302
303    /**
304     * Decodes a BASE64 encoded byte array that is known to be resonably well
305     * formatted. The method is about twice as fast as {@link #decode(byte[])}.
306     * The preconditions are:<br>
307     * + The array must have a line length of 76 chars OR no line separators at
308     * all (one line).<br>
309     * + Line separator must be "\r\n", as specified in RFC 2045 + The array
310     * must not contain illegal characters within the encoded string<br>
311     * + The array CAN have illegal characters at the beginning and end, those
312     * will be dealt with appropriately.<br>
313     *
314     * @param sArr
315     *            The source array. Length 0 will return an empty array.
316     *            <code>null</code> will throw an exception.
317     * @return The decoded array of bytes. May be of length 0.
318     */
319    public static byte[] decodeFast(final byte[] sArr) {
320        // Check special case
321        final int sLen = sArr.length;
322        if (sLen == 0) {
323            return new byte[0];
324        }
325
326        int sIx = 0, eIx = sLen - 1; // Start and end index after trimming.
327
328        // Trim illegal chars from start
329        while (sIx < eIx && IA[sArr[sIx] & 0xff] < 0) {
330            sIx++;
331        }
332
333        // Trim illegal chars from end
334        while (eIx > 0 && IA[sArr[eIx] & 0xff] < 0) {
335            eIx--;
336        }
337
338        // get the padding count (=) (0, 1 or 2)
339        final int pad = sArr[eIx] == '=' ? sArr[eIx - 1] == '=' ? 2 : 1 : 0; // Count '=' at end.
340        final int cCnt = eIx - sIx + 1; // Content count including possible separators
341        final int sepCnt = sLen > 76 ? (sArr[76] == '\r' ? cCnt / 78 : 0) << 1 : 0;
342
343        final int len = ((cCnt - sepCnt) * 6 >> 3) - pad; // The number of decoded bytes
344        final byte[] dArr = new byte[len]; // Preallocate byte[] of exact length
345
346        // Decode all but the last 0 - 2 bytes.
347        int d = 0;
348        for (int cc = 0, eLen = len / 3 * 3; d < eLen;) {
349            // Assemble three bytes into an int from four "valid" characters.
350            final int i =
351                    IA[sArr[sIx++]] << 18 | IA[sArr[sIx++]] << 12 | IA[sArr[sIx++]] << 6
352                            | IA[sArr[sIx++]];
353
354            // Add the bytes
355            dArr[d++] = (byte) (i >> 16);
356            dArr[d++] = (byte) (i >> 8);
357            dArr[d++] = (byte) i;
358
359            // If line separator, jump over it.
360            if (sepCnt > 0 && ++cc == 19) {
361                sIx += 2;
362                cc = 0;
363            }
364        }
365
366        if (d < len) {
367            // Decode last 1-3 bytes (incl '=') into 1-3 bytes
368            int i = 0;
369            for (int j = 0; sIx <= eIx - pad; j++) {
370                i |= IA[sArr[sIx++]] << 18 - j * 6;
371            }
372
373            for (int r = 16; d < len; r -= 8) {
374                dArr[d++] = (byte) (i >> r);
375            }
376        }
377
378        return dArr;
379    }
380
381    /**
382     * Decodes a BASE64 encoded char array that is known to be resonably well
383     * formatted. The method is about twice as fast as {@link #decode(char[])}.
384     * The preconditions are:<br>
385     * + The array must have a line length of 76 chars OR no line separators at
386     * all (one line).<br>
387     * + Line separator must be "\r\n", as specified in RFC 2045 + The array
388     * must not contain illegal characters within the encoded string<br>
389     * + The array CAN have illegal characters at the beginning and end, those
390     * will be dealt with appropriately.<br>
391     *
392     * @param sArr
393     *            The source array. Length 0 will return an empty array.
394     *            <code>null</code> will throw an exception.
395     * @return The decoded array of bytes. May be of length 0.
396     */
397    public static byte[] decodeFast(final char[] sArr) {
398        // Check special case
399        final int sLen = sArr.length;
400        if (sLen == 0) {
401            return new byte[0];
402        }
403
404        int sIx = 0, eIx = sLen - 1; // Start and end index after trimming.
405
406        // Trim illegal chars from start
407        while (sIx < eIx && IA[sArr[sIx]] < 0) {
408            sIx++;
409        }
410
411        // Trim illegal chars from end
412        while (eIx > 0 && IA[sArr[eIx]] < 0) {
413            eIx--;
414        }
415
416        // get the padding count (=) (0, 1 or 2)
417        final int pad = sArr[eIx] == '=' ? sArr[eIx - 1] == '=' ? 2 : 1 : 0; // Count '=' at end.
418        final int cCnt = eIx - sIx + 1; // Content count including possible separators
419        final int sepCnt = sLen > 76 ? (sArr[76] == '\r' ? cCnt / 78 : 0) << 1 : 0;
420
421        final int len = ((cCnt - sepCnt) * 6 >> 3) - pad; // The number of decoded bytes
422        final byte[] dArr = new byte[len]; // Preallocate byte[] of exact length
423
424        // Decode all but the last 0 - 2 bytes.
425        int d = 0;
426        for (int cc = 0, eLen = len / 3 * 3; d < eLen;) {
427            // Assemble three bytes into an int from four "valid" characters.
428            final int i =
429                    IA[sArr[sIx++]] << 18 | IA[sArr[sIx++]] << 12 | IA[sArr[sIx++]] << 6
430                            | IA[sArr[sIx++]];
431
432            // Add the bytes
433            dArr[d++] = (byte) (i >> 16);
434            dArr[d++] = (byte) (i >> 8);
435            dArr[d++] = (byte) i;
436
437            // If line separator, jump over it.
438            if (sepCnt > 0 && ++cc == 19) {
439                sIx += 2;
440                cc = 0;
441            }
442        }
443
444        if (d < len) {
445            // Decode last 1-3 bytes (incl '=') into 1-3 bytes
446            int i = 0;
447            for (int j = 0; sIx <= eIx - pad; j++) {
448                i |= IA[sArr[sIx++]] << 18 - j * 6;
449            }
450
451            for (int r = 16; d < len; r -= 8) {
452                dArr[d++] = (byte) (i >> r);
453            }
454        }
455
456        return dArr;
457    }
458
459    /**
460     * Decodes a BASE64 encoded string that is known to be resonably well
461     * formatted. The method is about twice as fast as {@link #decode(String)}.
462     * The preconditions are:<br>
463     * + The array must have a line length of 76 chars OR no line separators at
464     * all (one line).<br>
465     * + Line separator must be "\r\n", as specified in RFC 2045 + The array
466     * must not contain illegal characters within the encoded string<br>
467     * + The array CAN have illegal characters at the beginning and end, those
468     * will be dealt with appropriately.<br>
469     *
470     * @param s
471     *            The source string. Length 0 will return an empty array.
472     *            <code>null</code> will throw an exception.
473     * @return The decoded array of bytes. May be of length 0.
474     */
475    public static byte[] decodeFast(final String s) {
476        // Check special case
477        final int sLen = s.length();
478        if (sLen == 0) {
479            return new byte[0];
480        }
481
482        int sIx = 0, eIx = sLen - 1; // Start and end index after trimming.
483
484        // Trim illegal chars from start
485        while (sIx < eIx && IA[s.charAt(sIx) & 0xff] < 0) {
486            sIx++;
487        }
488
489        // Trim illegal chars from end
490        while (eIx > 0 && IA[s.charAt(eIx) & 0xff] < 0) {
491            eIx--;
492        }
493
494        // get the padding count (=) (0, 1 or 2)
495        final int pad = s.charAt(eIx) == '=' ? s.charAt(eIx - 1) == '=' ? 2 : 1 : 0; // Count '=' at end.
496        final int cCnt = eIx - sIx + 1; // Content count including possible separators
497        final int sepCnt = sLen > 76 ? (s.charAt(76) == '\r' ? cCnt / 78 : 0) << 1 : 0;
498
499        final int len = ((cCnt - sepCnt) * 6 >> 3) - pad; // The number of decoded bytes
500        final byte[] dArr = new byte[len]; // Preallocate byte[] of exact length
501
502        // Decode all but the last 0 - 2 bytes.
503        int d = 0;
504        for (int cc = 0, eLen = len / 3 * 3; d < eLen;) {
505            // Assemble three bytes into an int from four "valid" characters.
506            final int i =
507                    IA[s.charAt(sIx++)] << 18 | IA[s.charAt(sIx++)] << 12
508                            | IA[s.charAt(sIx++)] << 6 | IA[s.charAt(sIx++)];
509
510            // Add the bytes
511            dArr[d++] = (byte) (i >> 16);
512            dArr[d++] = (byte) (i >> 8);
513            dArr[d++] = (byte) i;
514
515            // If line separator, jump over it.
516            if (sepCnt > 0 && ++cc == 19) {
517                sIx += 2;
518                cc = 0;
519            }
520        }
521
522        if (d < len) {
523            // Decode last 1-3 bytes (incl '=') into 1-3 bytes
524            int i = 0;
525            for (int j = 0; sIx <= eIx - pad; j++) {
526                i |= IA[s.charAt(sIx++)] << 18 - j * 6;
527            }
528
529            for (int r = 16; d < len; r -= 8) {
530                dArr[d++] = (byte) (i >> r);
531            }
532        }
533
534        return dArr;
535    }
536
537    /**
538     * This method is using {@link #encode(byte[], boolean)}, and it only exists
539     * so we don't break the API.
540     *
541     * @param content
542     *            The bytearray that needs to be Base64 encoded
543     * @return the Base64 encoded
544     */
545    public static String encode(final byte[] content) {
546        return encode(content, false);
547    }
548
549    /**
550     * Encodes a raw byte array into a BASE64 <code>String</code> representation
551     * i accordance with RFC 2045.
552     *
553     * @param sArr
554     *            The bytes to convert. If <code>null</code> or length 0 an
555     *            empty array will be returned.
556     * @param lineSep
557     *            Optional "\r\n" after 76 characters, unless end of file.<br>
558     *            No line separator will be in breach of RFC 2045 which
559     *            specifies max 76 per line but will be a little faster.
560     * @return A BASE64 encoded array. Never <code>null</code>.
561     */
562    public static String encode(final byte[] sArr, final boolean lineSep) {
563        /*
564         * Reuse char[] since we can't create a String incrementally anyway and
565         * StringBuffer/Builder would be slower.
566         */
567        return new String(encodeToChar(sArr, lineSep));
568    }
569
570    /**
571     * Encodes a raw byte array into a BASE64 <code>byte[]</code> representation
572     * i accordance with RFC 2045.
573     *
574     * @param sArr
575     *            The bytes to convert. If <code>null</code> or length 0 an
576     *            empty array will be returned.
577     * @param lineSep
578     *            Optional "\r\n" after 76 characters, unless end of file.<br>
579     *            No line separator will be in breach of RFC 2045 which
580     *            specifies max 76 per line but will be a little faster.
581     * @return A BASE64 encoded array. Never <code>null</code>.
582     */
583    public static byte[] encodeToByte(final byte[] sArr, final boolean lineSep) {
584        // Check special case
585        final int sLen = sArr != null ? sArr.length : 0;
586        if (sLen == 0) {
587            return new byte[0];
588        }
589
590        final int eLen = sLen / 3 * 3; // Length of even 24-bits.
591        final int cCnt = (sLen - 1) / 3 + 1 << 2; // Returned character count
592        final int dLen = cCnt + (lineSep ? (cCnt - 1) / 76 << 1 : 0); // Length of returned array
593        final byte[] dArr = new byte[dLen];
594
595        // Encode even 24-bits
596        for (int s = 0, d = 0, cc = 0; s < eLen;) {
597            // Copy next three bytes into lower 24 bits of int, paying attension to sign.
598            final int i = (sArr[s++] & 0xff) << 16 | (sArr[s++] & 0xff) << 8 | sArr[s++] & 0xff;
599
600            // Encode the int into four chars
601            dArr[d++] = (byte) CA[i >>> 18 & 0x3f];
602            dArr[d++] = (byte) CA[i >>> 12 & 0x3f];
603            dArr[d++] = (byte) CA[i >>> 6 & 0x3f];
604            dArr[d++] = (byte) CA[i & 0x3f];
605
606            // Add optional line separator
607            if (lineSep && ++cc == 19 && d < dLen - 2) {
608                dArr[d++] = '\r';
609                dArr[d++] = '\n';
610                cc = 0;
611            }
612        }
613
614        // Pad and encode last bits if source isn't an even 24 bits.
615        final int left = sLen - eLen; // 0 - 2.
616        if (left > 0) {
617            // Prepare the int
618            final int i =
619                    (sArr[eLen] & 0xff) << 10 | (left == 2 ? (sArr[sLen - 1] & 0xff) << 2 : 0);
620
621            // Set last four chars
622            dArr[dLen - 4] = (byte) CA[i >> 12];
623            dArr[dLen - 3] = (byte) CA[i >>> 6 & 0x3f];
624            dArr[dLen - 2] = left == 2 ? (byte) CA[i & 0x3f] : (byte) '=';
625            dArr[dLen - 1] = '=';
626        }
627        return dArr;
628    }
629
630    /**
631     * Encodes a raw byte array into a BASE64 <code>char[]</code> representation
632     * i accordance with RFC 2045.
633     *
634     * @param sArr
635     *            The bytes to convert. If <code>null</code> or length 0 an
636     *            empty array will be returned.
637     * @param lineSep
638     *            Optional "\r\n" after 76 characters, unless end of file.<br>
639     *            No line separator will be in breach of RFC 2045 which
640     *            specifies max 76 per line but will be a little faster.
641     * @return A BASE64 encoded array. Never <code>null</code>.
642     */
643    public static char[] encodeToChar(final byte[] sArr, final boolean lineSep) {
644        // Check special case
645        final int sLen = sArr != null ? sArr.length : 0;
646        if (sLen == 0) {
647            return new char[0];
648        }
649
650        final int eLen = sLen / 3 * 3; // Length of even 24-bits.
651        final int cCnt = (sLen - 1) / 3 + 1 << 2; // Returned character count
652        final int dLen = cCnt + (lineSep ? (cCnt - 1) / 76 << 1 : 0); // Length of returned array
653        final char[] dArr = new char[dLen];
654
655        // Encode even 24-bits
656        for (int s = 0, d = 0, cc = 0; s < eLen;) {
657            // Copy next three bytes into lower 24 bits of int, paying attension to sign.
658            final int i = (sArr[s++] & 0xff) << 16 | (sArr[s++] & 0xff) << 8 | sArr[s++] & 0xff;
659
660            // Encode the int into four chars
661            dArr[d++] = CA[i >>> 18 & 0x3f];
662            dArr[d++] = CA[i >>> 12 & 0x3f];
663            dArr[d++] = CA[i >>> 6 & 0x3f];
664            dArr[d++] = CA[i & 0x3f];
665
666            // Add optional line separator
667            if (lineSep && ++cc == 19 && d < dLen - 2) {
668                dArr[d++] = '\r';
669                dArr[d++] = '\n';
670                cc = 0;
671            }
672        }
673
674        // Pad and encode last bits if source isn't even 24 bits.
675        final int left = sLen - eLen; // 0 - 2.
676        if (left > 0) {
677            // Prepare the int
678            final int i =
679                    (sArr[eLen] & 0xff) << 10 | (left == 2 ? (sArr[sLen - 1] & 0xff) << 2 : 0);
680
681            // Set last four chars
682            dArr[dLen - 4] = CA[i >> 12];
683            dArr[dLen - 3] = CA[i >>> 6 & 0x3f];
684            dArr[dLen - 2] = left == 2 ? CA[i & 0x3f] : '=';
685            dArr[dLen - 1] = '=';
686        }
687        return dArr;
688    }
689
690    private Base64() {
691        // No impl.
692    }
693}