View Javadoc
1   /*
2    * The contents of this file are subject to the terms of the Common Development and
3    * Distribution License (the License). You may not use this file except in compliance with the
4    * License.
5    *
6    * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
7    * specific language governing permission and limitations under the License.
8    *
9    * When distributing Covered Software, include this CDDL Header Notice in each file and include
10   * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
11   * Header, with the fields enclosed by brackets [] replaced by your own identifying
12   * information: "Portions copyright [year] [name of copyright owner]".
13   *
14   * Copyright 2015-2016 ForgeRock AS.
15   */
16  
17  
18  package org.forgerock.util.encode;
19  
20  import java.util.Arrays;
21  
22  /**
23   * A very fast and memory efficient class to encode and decode to and from
24   * BASE64 in full accordance with RFC 2045.<br>
25   * <br>
26   * On Windows XP sp1 with 1.4.2_04 and later ;), this encoder and decoder is
27   * about 10 times faster on small arrays (10 - 1000 bytes) and 2-3 times as fast
28   * on larger arrays (10000 - 1000000 bytes) compared to
29   * <code>sun.misc.Encoder()/Decoder()</code>.<br>
30   * <br>
31   * On byte arrays the encoder is about 20% faster than Jakarta Commons Base64
32   * Codec for encode and about 50% faster for decoding large arrays. This
33   * implementation is about twice as fast on very small arrays (&lt; 30 bytes).
34   * If source/destination is a <code>String</code> this version is about three
35   * times as fast due to the fact that the Commons Codec result has to be recoded
36   * to a <code>String</code> from <code>byte[]</code>, which is very expensive.<br>
37   * <br>
38   * This encode/decode algorithm doesn't create any temporary arrays as many
39   * other codecs do, it only allocates the resulting array. This produces less
40   * garbage and it is possible to handle arrays twice as large as algorithms that
41   * create a temporary array. (E.g. Jakarta Commons Codec). It is unknown whether
42   * Sun's <code>sun.misc.Encoder()/Decoder()</code> produce temporary arrays but
43   * since performance is quite low it probably does.<br>
44   * <br>
45   * The encoder produces the same output as the Sun one except that the Sun's
46   * encoder appends a trailing line separator if the last character isn't a pad.
47   * Unclear why but it only adds to the length and is probably a side effect.
48   * Both are in conformance with RFC 2045 though.<br>
49   * Commons codec seem to always att a trailing line separator.<br>
50   * <br>
51   * <b>Note!</b> The encode/decode method pairs (types) come in three versions
52   * with the <b>exact</b> same algorithm and thus a lot of code redundancy. This
53   * is to not create any temporary arrays for transcoding to/from different
54   * format types. The methods not used can simply be commented out.<br>
55   * <br>
56   * There is also a "fast" version of all decode methods that works the same way
57   * as the normal ones, but har a few demands on the decoded input. Normally
58   * though, these fast verions should be used if the source if the input is known
59   * and it hasn't bee tampered with.<br>
60   * <br>
61   * If you find the code useful or you find a bug, please send me a note at
62   * base64 @ miginfocom . com.
63   *
64   * @version 2.2
65   */
66  public final class Base64 {
67  
68      private static final char[] CA =
69              "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".toCharArray();
70      private static final int[] IA = new int[256];
71  
72      static {
73          Arrays.fill(IA, -1);
74          for (int i = 0, iS = CA.length; i < iS; i++) {
75              IA[CA[i]] = i;
76          }
77          IA['='] = 0;
78      }
79  
80      /**
81       * Decodes a BASE64 encoded byte array. All illegal characters will be
82       * ignored and can handle both arrays with and without line separators.
83       *
84       * @param sArr
85       *            The source array. Length 0 will return an empty array.
86       *            <code>null</code> will throw an exception.
87       * @return The decoded array of bytes. May be of length 0. Will be
88       *         <code>null</code> if the legal characters (including '=') isn't
89       *         divideable by 4. (I.e. definitely corrupted).
90       */
91      public static byte[] decode(final byte[] sArr) {
92          // Check special case
93          final int sLen = sArr.length;
94  
95          /*
96           * Count illegal characters (including '\r', '\n') to know what size the
97           * returned array will be, so we don't have to reallocate & copy it
98           * later.
99           */
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         // Number of separator characters. (Actually illegal characters, but that's a bonus...)
176         int sepCnt = 0;
177         // If input is "pure" (I.e. no line separators or illegal chars) base64 this loop can be commented out.
178         for (int i = 0; i < sLen; i++) {
179             if (IA[sArr[i]] < 0) {
180                 sepCnt++;
181             }
182         }
183 
184         /*
185          * Check so that legal chars (including '=') are evenly divideable by 4
186          * as specified in RFC 2045.
187          */
188         if ((sLen - sepCnt) % 4 != 0) {
189             return null;
190         }
191 
192         int pad = 0;
193         for (int i = sLen; i > 1 && IA[sArr[--i]] <= 0;) {
194             if (sArr[i] == '=') {
195                 pad++;
196             }
197         }
198 
199         final int len = ((sLen - sepCnt) * 6 >> 3) - pad;
200 
201         final byte[] dArr = new byte[len]; // Preallocate byte[] of exact length
202 
203         for (int s = 0, d = 0; d < len;) {
204             // Assemble three bytes into an int from four "valid" characters.
205             int i = 0;
206             for (int j = 0; j < 4; j++) { // j only increased if a valid char was found.
207                 final int c = IA[sArr[s++]];
208                 if (c >= 0) {
209                     i |= c << 18 - j * 6;
210                 } else {
211                     j--;
212                 }
213             }
214             // Add the bytes
215             dArr[d++] = (byte) (i >> 16);
216             if (d < len) {
217                 dArr[d++] = (byte) (i >> 8);
218                 if (d < len) {
219                     dArr[d++] = (byte) i;
220                 }
221             }
222         }
223         return dArr;
224     }
225 
226     /**
227      * Decodes a BASE64 encoded <code>String</code>. All illegal characters will
228      * be ignored and can handle both strings with and without line separators.<br>
229      * <b>Note!</b> It can be up to about 2x the speed to call
230      * <code>decode(str.toCharArray())</code> instead. That will create a
231      * temporary array though. This version will use <code>str.charAt(i)</code>
232      * to iterate the string.
233      *
234      * @param str
235      *            The source string. <code>null</code> or length 0 will return
236      *            an empty array.
237      * @return The decoded array of bytes. May be of length 0. Will be
238      *         <code>null</code> if the legal characters (including '=') isn't
239      *         divideable by 4. (I.e. definitely corrupted).
240      */
241     public static byte[] decode(final String str) {
242         // Check special case
243         final int sLen = str != null ? str.length() : 0;
244         if (sLen == 0) {
245             return new byte[0];
246         }
247 
248         /*
249          * Count illegal characters (including '\r', '\n') to know what size the
250          * returned array will be, so we don't have to reallocate & copy it
251          * later.
252          */
253         // Number of separator characters. (Actually illegal characters, but that's a bonus...)
254         int sepCnt = 0;
255         // If input is "pure" (I.e. no line separators or illegal chars) base64 this loop can be commented out.
256         for (int i = 0; i < sLen; i++) {
257             if (IA[str.charAt(i)] < 0) {
258                 sepCnt++;
259             }
260         }
261 
262         /*
263          * Check so that legal chars (including '=') are evenly divideable by 4
264          * as specified in RFC 2045.
265          */
266         if ((sLen - sepCnt) % 4 != 0) {
267             return null;
268         }
269 
270         // Count '=' at end
271         int pad = 0;
272         for (int i = sLen; i > 1 && IA[str.charAt(--i)] <= 0;) {
273             if (str.charAt(i) == '=') {
274                 pad++;
275             }
276         }
277 
278         final int len = ((sLen - sepCnt) * 6 >> 3) - pad;
279 
280         final byte[] dArr = new byte[len]; // Preallocate byte[] of exact length
281 
282         for (int s = 0, d = 0; d < len;) {
283             // Assemble three bytes into an int from four "valid" characters.
284             int i = 0;
285             for (int j = 0; j < 4; j++) { // j only increased if a valid char was found.
286                 final int c = IA[str.charAt(s++)];
287                 if (c >= 0) {
288                     i |= c << 18 - j * 6;
289                 } else {
290                     j--;
291                 }
292             }
293             // Add the bytes
294             dArr[d++] = (byte) (i >> 16);
295             if (d < len) {
296                 dArr[d++] = (byte) (i >> 8);
297                 if (d < len) {
298                     dArr[d++] = (byte) i;
299                 }
300             }
301         }
302         return dArr;
303     }
304 
305     /**
306      * Decodes a BASE64 encoded byte array that is known to be resonably well
307      * formatted. The method is about twice as fast as {@link #decode(byte[])}.
308      * The preconditions are:<br>
309      * + The array must have a line length of 76 chars OR no line separators at
310      * all (one line).<br>
311      * + Line separator must be "\r\n", as specified in RFC 2045 + The array
312      * must not contain illegal characters within the encoded string<br>
313      * + The array CAN have illegal characters at the beginning and end, those
314      * will be dealt with appropriately.<br>
315      *
316      * @param sArr
317      *            The source array. Length 0 will return an empty array.
318      *            <code>null</code> will throw an exception.
319      * @return The decoded array of bytes. May be of length 0.
320      */
321     public static byte[] decodeFast(final byte[] sArr) {
322         // Check special case
323         final int sLen = sArr.length;
324         if (sLen == 0) {
325             return new byte[0];
326         }
327 
328         int sIx = 0, eIx = sLen - 1; // Start and end index after trimming.
329 
330         // Trim illegal chars from start
331         while (sIx < eIx && IA[sArr[sIx] & 0xff] < 0) {
332             sIx++;
333         }
334 
335         // Trim illegal chars from end
336         while (eIx > 0 && IA[sArr[eIx] & 0xff] < 0) {
337             eIx--;
338         }
339 
340         // get the padding count (=) (0, 1 or 2)
341         final int pad = sArr[eIx] == '=' ? sArr[eIx - 1] == '=' ? 2 : 1 : 0; // Count '=' at end.
342         final int cCnt = eIx - sIx + 1; // Content count including possible separators
343         final int sepCnt = sLen > 76 ? (sArr[76] == '\r' ? cCnt / 78 : 0) << 1 : 0;
344 
345         final int len = ((cCnt - sepCnt) * 6 >> 3) - pad; // The number of decoded bytes
346         final byte[] dArr = new byte[len]; // Preallocate byte[] of exact length
347 
348         // Decode all but the last 0 - 2 bytes.
349         int d = 0;
350         for (int cc = 0, eLen = len / 3 * 3; d < eLen;) {
351             // Assemble three bytes into an int from four "valid" characters.
352             final int i =
353                     IA[sArr[sIx++]] << 18 | IA[sArr[sIx++]] << 12 | IA[sArr[sIx++]] << 6
354                             | IA[sArr[sIx++]];
355 
356             // Add the bytes
357             dArr[d++] = (byte) (i >> 16);
358             dArr[d++] = (byte) (i >> 8);
359             dArr[d++] = (byte) i;
360 
361             // If line separator, jump over it.
362             if (sepCnt > 0 && ++cc == 19) {
363                 sIx += 2;
364                 cc = 0;
365             }
366         }
367 
368         if (d < len) {
369             // Decode last 1-3 bytes (incl '=') into 1-3 bytes
370             int i = 0;
371             for (int j = 0; sIx <= eIx - pad; j++) {
372                 i |= IA[sArr[sIx++]] << 18 - j * 6;
373             }
374 
375             for (int r = 16; d < len; r -= 8) {
376                 dArr[d++] = (byte) (i >> r);
377             }
378         }
379 
380         return dArr;
381     }
382 
383     /**
384      * Decodes a BASE64 encoded char array that is known to be resonably well
385      * formatted. The method is about twice as fast as {@link #decode(char[])}.
386      * The preconditions are:<br>
387      * + The array must have a line length of 76 chars OR no line separators at
388      * all (one line).<br>
389      * + Line separator must be "\r\n", as specified in RFC 2045 + The array
390      * must not contain illegal characters within the encoded string<br>
391      * + The array CAN have illegal characters at the beginning and end, those
392      * will be dealt with appropriately.<br>
393      *
394      * @param sArr
395      *            The source array. Length 0 will return an empty array.
396      *            <code>null</code> will throw an exception.
397      * @return The decoded array of bytes. May be of length 0.
398      */
399     public static byte[] decodeFast(final char[] sArr) {
400         // Check special case
401         final int sLen = sArr.length;
402         if (sLen == 0) {
403             return new byte[0];
404         }
405 
406         int sIx = 0, eIx = sLen - 1; // Start and end index after trimming.
407 
408         // Trim illegal chars from start
409         while (sIx < eIx && IA[sArr[sIx]] < 0) {
410             sIx++;
411         }
412 
413         // Trim illegal chars from end
414         while (eIx > 0 && IA[sArr[eIx]] < 0) {
415             eIx--;
416         }
417 
418         // get the padding count (=) (0, 1 or 2)
419         final int pad = sArr[eIx] == '=' ? sArr[eIx - 1] == '=' ? 2 : 1 : 0; // Count '=' at end.
420         final int cCnt = eIx - sIx + 1; // Content count including possible separators
421         final int sepCnt = sLen > 76 ? (sArr[76] == '\r' ? cCnt / 78 : 0) << 1 : 0;
422 
423         final int len = ((cCnt - sepCnt) * 6 >> 3) - pad; // The number of decoded bytes
424         final byte[] dArr = new byte[len]; // Preallocate byte[] of exact length
425 
426         // Decode all but the last 0 - 2 bytes.
427         int d = 0;
428         for (int cc = 0, eLen = len / 3 * 3; d < eLen;) {
429             // Assemble three bytes into an int from four "valid" characters.
430             final int i =
431                     IA[sArr[sIx++]] << 18 | IA[sArr[sIx++]] << 12 | IA[sArr[sIx++]] << 6
432                             | IA[sArr[sIx++]];
433 
434             // Add the bytes
435             dArr[d++] = (byte) (i >> 16);
436             dArr[d++] = (byte) (i >> 8);
437             dArr[d++] = (byte) i;
438 
439             // If line separator, jump over it.
440             if (sepCnt > 0 && ++cc == 19) {
441                 sIx += 2;
442                 cc = 0;
443             }
444         }
445 
446         if (d < len) {
447             // Decode last 1-3 bytes (incl '=') into 1-3 bytes
448             int i = 0;
449             for (int j = 0; sIx <= eIx - pad; j++) {
450                 i |= IA[sArr[sIx++]] << 18 - j * 6;
451             }
452 
453             for (int r = 16; d < len; r -= 8) {
454                 dArr[d++] = (byte) (i >> r);
455             }
456         }
457 
458         return dArr;
459     }
460 
461     /**
462      * Decodes a BASE64 encoded string that is known to be resonably well
463      * formatted. The method is about twice as fast as {@link #decode(String)}.
464      * The preconditions are:<br>
465      * + The array must have a line length of 76 chars OR no line separators at
466      * all (one line).<br>
467      * + Line separator must be "\r\n", as specified in RFC 2045 + The array
468      * must not contain illegal characters within the encoded string<br>
469      * + The array CAN have illegal characters at the beginning and end, those
470      * will be dealt with appropriately.<br>
471      *
472      * @param s
473      *            The source string. Length 0 will return an empty array.
474      *            <code>null</code> will throw an exception.
475      * @return The decoded array of bytes. May be of length 0.
476      */
477     public static byte[] decodeFast(final String s) {
478         // Check special case
479         final int sLen = s.length();
480         if (sLen == 0) {
481             return new byte[0];
482         }
483 
484         int sIx = 0, eIx = sLen - 1; // Start and end index after trimming.
485 
486         // Trim illegal chars from start
487         while (sIx < eIx && IA[s.charAt(sIx) & 0xff] < 0) {
488             sIx++;
489         }
490 
491         // Trim illegal chars from end
492         while (eIx > 0 && IA[s.charAt(eIx) & 0xff] < 0) {
493             eIx--;
494         }
495 
496         // get the padding count (=) (0, 1 or 2)
497         final int pad = s.charAt(eIx) == '=' ? s.charAt(eIx - 1) == '=' ? 2 : 1 : 0; // Count '=' at end.
498         final int cCnt = eIx - sIx + 1; // Content count including possible separators
499         final int sepCnt = sLen > 76 ? (s.charAt(76) == '\r' ? cCnt / 78 : 0) << 1 : 0;
500 
501         final int len = ((cCnt - sepCnt) * 6 >> 3) - pad; // The number of decoded bytes
502         final byte[] dArr = new byte[len]; // Preallocate byte[] of exact length
503 
504         // Decode all but the last 0 - 2 bytes.
505         int d = 0;
506         for (int cc = 0, eLen = len / 3 * 3; d < eLen;) {
507             // Assemble three bytes into an int from four "valid" characters.
508             final int i =
509                     IA[s.charAt(sIx++)] << 18 | IA[s.charAt(sIx++)] << 12
510                             | IA[s.charAt(sIx++)] << 6 | IA[s.charAt(sIx++)];
511 
512             // Add the bytes
513             dArr[d++] = (byte) (i >> 16);
514             dArr[d++] = (byte) (i >> 8);
515             dArr[d++] = (byte) i;
516 
517             // If line separator, jump over it.
518             if (sepCnt > 0 && ++cc == 19) {
519                 sIx += 2;
520                 cc = 0;
521             }
522         }
523 
524         if (d < len) {
525             // Decode last 1-3 bytes (incl '=') into 1-3 bytes
526             int i = 0;
527             for (int j = 0; sIx <= eIx - pad; j++) {
528                 i |= IA[s.charAt(sIx++)] << 18 - j * 6;
529             }
530 
531             for (int r = 16; d < len; r -= 8) {
532                 dArr[d++] = (byte) (i >> r);
533             }
534         }
535 
536         return dArr;
537     }
538 
539     /**
540      * This method is using {@link #encode(byte[], boolean)}, and it only exists
541      * so we don't break the API.
542      *
543      * @param content
544      *            The bytearray that needs to be Base64 encoded
545      * @return the Base64 encoded
546      */
547     public static String encode(final byte[] content) {
548         return encode(content, false);
549     }
550 
551     /**
552      * Encodes a raw byte array into a BASE64 <code>String</code> representation
553      * i accordance with RFC 2045.
554      *
555      * @param sArr
556      *            The bytes to convert. If <code>null</code> or length 0 an
557      *            empty array will be returned.
558      * @param lineSep
559      *            Optional "\r\n" after 76 characters, unless end of file.<br>
560      *            No line separator will be in breach of RFC 2045 which
561      *            specifies max 76 per line but will be a little faster.
562      * @return A BASE64 encoded array. Never <code>null</code>.
563      */
564     public static String encode(final byte[] sArr, final boolean lineSep) {
565         /*
566          * Reuse char[] since we can't create a String incrementally anyway and
567          * StringBuffer/Builder would be slower.
568          */
569         return new String(encodeToChar(sArr, lineSep));
570     }
571 
572     /**
573      * Encodes a raw byte array into a BASE64 <code>byte[]</code> representation
574      * i accordance with RFC 2045.
575      *
576      * @param sArr
577      *            The bytes to convert. If <code>null</code> or length 0 an
578      *            empty array will be returned.
579      * @param lineSep
580      *            Optional "\r\n" after 76 characters, unless end of file.<br>
581      *            No line separator will be in breach of RFC 2045 which
582      *            specifies max 76 per line but will be a little faster.
583      * @return A BASE64 encoded array. Never <code>null</code>.
584      */
585     public static byte[] encodeToByte(final byte[] sArr, final boolean lineSep) {
586         // Check special case
587         final int sLen = sArr != null ? sArr.length : 0;
588         if (sLen == 0) {
589             return new byte[0];
590         }
591 
592         final int eLen = sLen / 3 * 3; // Length of even 24-bits.
593         final int cCnt = (sLen - 1) / 3 + 1 << 2; // Returned character count
594         final int dLen = cCnt + (lineSep ? (cCnt - 1) / 76 << 1 : 0); // Length of returned array
595         final byte[] dArr = new byte[dLen];
596 
597         // Encode even 24-bits
598         for (int s = 0, d = 0, cc = 0; s < eLen;) {
599             // Copy next three bytes into lower 24 bits of int, paying attension to sign.
600             final int i = (sArr[s++] & 0xff) << 16 | (sArr[s++] & 0xff) << 8 | sArr[s++] & 0xff;
601 
602             // Encode the int into four chars
603             dArr[d++] = (byte) CA[i >>> 18 & 0x3f];
604             dArr[d++] = (byte) CA[i >>> 12 & 0x3f];
605             dArr[d++] = (byte) CA[i >>> 6 & 0x3f];
606             dArr[d++] = (byte) CA[i & 0x3f];
607 
608             // Add optional line separator
609             if (lineSep && ++cc == 19 && d < dLen - 2) {
610                 dArr[d++] = '\r';
611                 dArr[d++] = '\n';
612                 cc = 0;
613             }
614         }
615 
616         // Pad and encode last bits if source isn't an even 24 bits.
617         final int left = sLen - eLen; // 0 - 2.
618         if (left > 0) {
619             // Prepare the int
620             final int i =
621                     (sArr[eLen] & 0xff) << 10 | (left == 2 ? (sArr[sLen - 1] & 0xff) << 2 : 0);
622 
623             // Set last four chars
624             dArr[dLen - 4] = (byte) CA[i >> 12];
625             dArr[dLen - 3] = (byte) CA[i >>> 6 & 0x3f];
626             dArr[dLen - 2] = left == 2 ? (byte) CA[i & 0x3f] : (byte) '=';
627             dArr[dLen - 1] = '=';
628         }
629         return dArr;
630     }
631 
632     /**
633      * Encodes a raw byte array into a BASE64 <code>char[]</code> representation
634      * i accordance with RFC 2045.
635      *
636      * @param sArr
637      *            The bytes to convert. If <code>null</code> or length 0 an
638      *            empty array will be returned.
639      * @param lineSep
640      *            Optional "\r\n" after 76 characters, unless end of file.<br>
641      *            No line separator will be in breach of RFC 2045 which
642      *            specifies max 76 per line but will be a little faster.
643      * @return A BASE64 encoded array. Never <code>null</code>.
644      */
645     public static char[] encodeToChar(final byte[] sArr, final boolean lineSep) {
646         // Check special case
647         final int sLen = sArr != null ? sArr.length : 0;
648         if (sLen == 0) {
649             return new char[0];
650         }
651 
652         final int eLen = sLen / 3 * 3; // Length of even 24-bits.
653         final int cCnt = (sLen - 1) / 3 + 1 << 2; // Returned character count
654         final int dLen = cCnt + (lineSep ? (cCnt - 1) / 76 << 1 : 0); // Length of returned array
655         final char[] dArr = new char[dLen];
656 
657         // Encode even 24-bits
658         for (int s = 0, d = 0, cc = 0; s < eLen;) {
659             // Copy next three bytes into lower 24 bits of int, paying attension to sign.
660             final int i = (sArr[s++] & 0xff) << 16 | (sArr[s++] & 0xff) << 8 | sArr[s++] & 0xff;
661 
662             // Encode the int into four chars
663             dArr[d++] = CA[i >>> 18 & 0x3f];
664             dArr[d++] = CA[i >>> 12 & 0x3f];
665             dArr[d++] = CA[i >>> 6 & 0x3f];
666             dArr[d++] = CA[i & 0x3f];
667 
668             // Add optional line separator
669             if (lineSep && ++cc == 19 && d < dLen - 2) {
670                 dArr[d++] = '\r';
671                 dArr[d++] = '\n';
672                 cc = 0;
673             }
674         }
675 
676         // Pad and encode last bits if source isn't even 24 bits.
677         final int left = sLen - eLen; // 0 - 2.
678         if (left > 0) {
679             // Prepare the int
680             final int i =
681                     (sArr[eLen] & 0xff) << 10 | (left == 2 ? (sArr[sLen - 1] & 0xff) << 2 : 0);
682 
683             // Set last four chars
684             dArr[dLen - 4] = CA[i >> 12];
685             dArr[dLen - 3] = CA[i >>> 6 & 0x3f];
686             dArr[dLen - 2] = left == 2 ? CA[i & 0x3f] : '=';
687             dArr[dLen - 1] = '=';
688         }
689         return dArr;
690     }
691 
692     private Base64() {
693         // No impl.
694     }
695 }